diff --git a/src/mbgl/map/annotation.cpp b/src/mbgl/map/annotation.cpp index 874459797..9cfb857bc 100644 --- a/src/mbgl/map/annotation.cpp +++ b/src/mbgl/map/annotation.cpp @@ -89,166 +89,118 @@ AnnotationManager::addTileFeature(const uint32_t annotationID, assert(type != AnnotationType::Any); // track the annotation global ID and its original geometry - auto anno_it = annotations.emplace(annotationID, - std::make_unique(type, segments, styleProperties)); - - std::unordered_set affectedTiles; + annotations.emplace(annotationID, std::make_unique(type, segments, styleProperties)); if (type == AnnotationType::Shape) { - - orderedShapeAnnotations.push_back(annotationID); - - using namespace mapbox::util::geojsonvt; - - const uint32_t z2 = 1 << maxZoom; - const double baseTolerance = 3; - const uint16_t extent = 4096; - - const double tolerance = baseTolerance / (z2 * extent); - - ProjectedGeometryContainer rings; - - std::vector points; - - for (size_t i = 0; i < segments[0].size(); ++i) { // first segment for now (no holes) - const double constraintedLatitude = ::fmin(::fmax(segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); - points.push_back(LonLat(segments[0][i].longitude, constraintedLatitude)); - } - - ProjectedFeatureType featureType; - - if (styleProperties.is()) { - featureType = ProjectedFeatureType::Polygon; - - if (points.front().lon != points.back().lon || points.front().lat != points.back().lat) { - points.push_back(LonLat(points.front().lon, points.front().lat)); - } - } else { - featureType = ProjectedFeatureType::LineString; - } - - ProjectedGeometryContainer ring = Convert::project(points, tolerance); - - rings.members.push_back(ring); - - std::vector features; - - features.push_back(Convert::create(Tags(), featureType, rings)); - - shapeTilers.emplace(annotationID, std::make_unique(features, maxZoom, 4, 100, 10)); - + return addShapeFeature(annotationID, segments, styleProperties, maxZoom); } else { + return addPointFeature(annotationID, projectedFeature, featureProperties, maxZoom); + } +} - // side length of map at max zoom - uint32_t z2 = 1 << maxZoom; +std::unordered_set +AnnotationManager::addShapeFeature(const uint32_t annotationID, + const AnnotationSegments& segments, + const StyleProperties& styleProperties, + const uint8_t maxZoom) { + // Currently unused. + std::unordered_set affectedTiles; - const uint16_t extent = 4096; + orderedShapeAnnotations.push_back(annotationID); - uint32_t x = 0; - uint32_t y = 0; + using namespace mapbox::util::geojsonvt; - for (int8_t z = maxZoom; z >= 0; z--) { + const uint32_t z2 = 1 << maxZoom; + const double baseTolerance = 3; + const uint16_t extent = 4096; - std::unordered_map featureTiles; + const double tolerance = baseTolerance / (z2 * extent); - if (type == AnnotationType::Point) { - auto& pp = projectedFeature[0][0]; + ProjectedGeometryContainer rings; - x = pp.x * z2; - y = pp.y * z2; + std::vector points; - const Coordinate coordinate(extent * (pp.x * z2 - x), extent * (pp.y * z2 - y)); + for (size_t i = 0; i < segments[0].size(); ++i) { // first segment for now (no holes) + const double constraintedLatitude = ::fmin(::fmax(segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); + points.push_back(LonLat(segments[0][i].longitude, constraintedLatitude)); + } - GeometryCollection geometries = {{ {{ coordinate }} }}; + ProjectedFeatureType featureType; - featureTiles.emplace(TileID(z, x, y, z), geometries); - } else { - for (size_t l = 0; l < projectedFeature.size(); ++l) { - for (size_t p = 0; p < projectedFeature[l].size(); ++p) { - - auto& pp = projectedFeature[l][p]; - - x = pp.x * z2; - y = pp.y * z2; - - const Coordinate coordinate(extent * (pp.x * z2 - x), extent * (pp.y * z2 - y)); - - auto tile_it = featureTiles.find(TileID(z, x, y, z)); - - if (tile_it != featureTiles.end()) { - GeometryCollection& geometries = featureTiles.find(TileID(z, x, y, z))->second; - if (!geometries.empty()) { - geometries.back().push_back(coordinate); - } else { - geometries.push_back({{ coordinate }}); - } - } else { - GeometryCollection geometries = {{ {{ coordinate }} }}; - featureTiles.emplace(TileID(z, x, y, z), geometries); - } - } - } - } - - for (auto& featureTile : featureTiles) { - // determine feature type - FeatureType featureType; - if (type == AnnotationType::Point) { - featureType = FeatureType::Point; - } else if (styleProperties.is()) { - featureType = FeatureType::LineString; - } else if (styleProperties.is()) { - featureType = FeatureType::Polygon; - } else { - throw std::runtime_error("Invalid feature type"); - } - - // create tile feature - auto feature = std::make_shared( - featureType, - featureTile.second, - featureProperties - ); - - // check for tile & create if necessary - auto tile_pos = tiles.emplace(featureTile.first, - std::make_pair(std::unordered_set({ annotationID }), - std::make_unique())); - - // check for annotation layer & create if necessary - util::ptr layer; - std::string layerID = ""; - if (type == AnnotationType::Point) { - layerID = PointLayerID; - } else { - layerID = ShapeLayerID + "." + util::toString(annotationID); - } - if (tile_pos.second || tile_pos.first->second.second->getMutableLayer(layerID) == nullptr) { - layer = std::make_shared(); - tile_pos.first->second.second->addLayer(layerID, layer); - } else { - layer = tile_pos.first->second.second->getMutableLayer(layerID); - - // associate annotation with tile - tile_pos.first->second.first.insert(annotationID); - } - - // add feature to layer - layer->addFeature(feature); - - // Record annotation association with tile and tile feature. This is used to determine stale tiles, - // as well as to remove the feature from the tile upon annotation deletion. - anno_it.first->second->tilePointFeatures.emplace(featureTile.first, std::weak_ptr(feature)); - - // track affected tile - affectedTiles.insert(featureTile.first); - } - - // get ready for the next-lower zoom number - z2 /= 2; - x /= 2; - y /= 2; + if (styleProperties.is()) { + featureType = ProjectedFeatureType::Polygon; + + if (points.front().lon != points.back().lon || points.front().lat != points.back().lat) { + points.push_back(LonLat(points.front().lon, points.front().lat)); } + } else { + featureType = ProjectedFeatureType::LineString; + } + + ProjectedGeometryContainer ring = Convert::project(points, tolerance); + rings.members.push_back(ring); + + std::vector features; + features.push_back(Convert::create(Tags(), featureType, rings)); + + shapeTilers.emplace(annotationID, std::make_unique(features, maxZoom, 4, 100, 10)); + + return affectedTiles; +} + +std::unordered_set +AnnotationManager::addPointFeature(const uint32_t annotationID, + const std::vector>>& projectedFeature, + const std::unordered_map& featureProperties, + const uint8_t maxZoom) { + std::unordered_set affectedTiles; + + auto anno_it = annotations.find(annotationID); + assert(anno_it != annotations.end()); + + const uint16_t extent = 4096; + auto& pp = projectedFeature[0][0]; + + for (int8_t z = maxZoom; z >= 0; z--) { + uint32_t z2 = 1 << z; + uint32_t x = pp.x * z2; + uint32_t y = pp.y * z2; + + const Coordinate coordinate(extent * (pp.x * z2 - x), extent * (pp.y * z2 - y)); + + GeometryCollection geometries = {{ {{ coordinate }} }}; + TileID featureTileID = TileID(z, x, y, z); + + auto feature = std::make_shared(FeatureType::Point, geometries, featureProperties); + + // check for tile & create if necessary + auto tile_pos = tiles.emplace(featureTileID, + std::make_pair(std::unordered_set({ annotationID }), + std::make_unique())); + + // check for annotation layer & create if necessary + util::ptr layer; + std::string layerID = PointLayerID; + + if (tile_pos.second || tile_pos.first->second.second->getMutableLayer(layerID) == nullptr) { + layer = std::make_shared(); + tile_pos.first->second.second->addLayer(layerID, layer); + } else { + layer = tile_pos.first->second.second->getMutableLayer(layerID); + + // associate annotation with tile + tile_pos.first->second.first.insert(annotationID); + } + + // add feature to layer + layer->addFeature(feature); + + // Record annotation association with tile and tile feature. This is used to determine stale tiles, + // as well as to remove the feature from the tile upon annotation deletion. + anno_it->second->tilePointFeatures.emplace(featureTileID, std::weak_ptr(feature)); + + // track affected tile + affectedTiles.insert(featureTileID); } return affectedTiles; diff --git a/src/mbgl/map/annotation.hpp b/src/mbgl/map/annotation.hpp index 5adec162f..7691e4508 100644 --- a/src/mbgl/map/annotation.hpp +++ b/src/mbgl/map/annotation.hpp @@ -80,14 +80,27 @@ public: private: inline uint32_t nextID(); static vec2 projectPoint(const LatLng& point); - std::unordered_set addTileFeature( - const uint32_t annotationID, - const AnnotationSegments&, - const std::vector>>& projectedFeature, - const AnnotationType&, - const StyleProperties&, - const std::unordered_map& featureProperties, - const uint8_t maxZoom); + + std::unordered_set + addTileFeature(const uint32_t annotationID, + const AnnotationSegments&, + const std::vector>>& projectedFeature, + const AnnotationType&, + const StyleProperties&, + const std::unordered_map& featureProperties, + const uint8_t maxZoom); + + std::unordered_set + addShapeFeature(const uint32_t annotationID, + const AnnotationSegments& segments, + const StyleProperties& styleProperties, + const uint8_t maxZoom); + + std::unordered_set + addPointFeature(const uint32_t annotationID, + const std::vector>>& projectedFeature, + const std::unordered_map& featureProperties, + const uint8_t maxZoom); private: std::string defaultPointAnnotationSymbol;