#include #include #include #include #include namespace mbgl { const std::string AnnotationManager::SourceID = "com.mapbox.annotations"; const std::string AnnotationManager::PointLayerID = "com.mapbox.annotations.points"; AnnotationManager::AnnotationManager(float pixelRatio) : spriteStore(pixelRatio), spriteAtlas(1024, 1024, pixelRatio, spriteStore) { } AnnotationManager::~AnnotationManager() = default; AnnotationIDs AnnotationManager::addPointAnnotations(const std::vector& points, const uint8_t) { AnnotationIDs annotationIDs; annotationIDs.reserve(points.size()); for (const auto& point : points) { const uint32_t annotationID = nextID++; auto annotation = std::make_shared(annotationID, point); pointTree.insert(annotation); pointAnnotations.emplace(annotationID, annotation); annotationIDs.push_back(annotationID); } return annotationIDs; } AnnotationIDs AnnotationManager::addShapeAnnotations(const std::vector& shapes, const uint8_t maxZoom) { AnnotationIDs annotationIDs; annotationIDs.reserve(shapes.size()); for (const auto& shape : shapes) { const uint32_t annotationID = nextID++; shapeAnnotations.emplace(annotationID, std::make_unique(annotationID, shape, maxZoom)); annotationIDs.push_back(annotationID); } return annotationIDs; } void AnnotationManager::updatePointAnnotation(const AnnotationID& id, const PointAnnotation& point, const uint8_t) { auto foundAnnotation = pointAnnotations.find(id); if (foundAnnotation != pointAnnotations.end()) { auto updatedAnnotation = std::make_shared(id, point); pointTree.remove(foundAnnotation->second); pointTree.insert(updatedAnnotation); foundAnnotation->second = updatedAnnotation; } } void AnnotationManager::removeAnnotations(const AnnotationIDs& ids) { for (const auto& id : ids) { if (pointAnnotations.find(id) != pointAnnotations.end()) { pointTree.remove(pointAnnotations.at(id)); pointAnnotations.erase(id); } else if (shapeAnnotations.find(id) != shapeAnnotations.end()) { obsoleteShapeAnnotationLayers.push_back(shapeAnnotations.at(id)->layerID); shapeAnnotations.erase(id); } } } AnnotationIDs AnnotationManager::getPointAnnotationsInBounds(const LatLngBounds& bounds) const { AnnotationIDs result; pointTree.query(boost::geometry::index::intersects(bounds), boost::make_function_output_iterator([&](const auto& val){ result.push_back(val->id); })); return result; } std::unique_ptr AnnotationManager::getTile(const TileID& tileID) { if (pointAnnotations.empty() && shapeAnnotations.empty()) return nullptr; auto tile = std::make_unique(); AnnotationTileLayer& pointLayer = *tile->layers.emplace( PointLayerID, std::make_unique()).first->second; LatLngBounds tileBounds(tileID); pointTree.query(boost::geometry::index::intersects(tileBounds), boost::make_function_output_iterator([&](const auto& val){ val->updateLayer(tileID, pointLayer); })); for (const auto& shape : shapeAnnotations) { shape.second->updateTile(tileID, *tile); } return tile; } void AnnotationManager::updateStyle(Style& style) { // Create annotation source, point layer, and point bucket if (!style.getSource(SourceID)) { std::unique_ptr source = std::make_unique(SourceType::Annotations, SourceID, "", util::tileSize, std::make_unique(), nullptr); source->enabled = true; style.addSource(std::move(source)); std::unique_ptr layer = std::make_unique(); layer->id = PointLayerID; layer->source = SourceID; layer->sourceLayer = PointLayerID; layer->layout.icon.image = std::string("{sprite}"); layer->layout.icon.allowOverlap = true; layer->spriteAtlas = &spriteAtlas; style.addLayer(std::move(layer)); } for (const auto& shape : shapeAnnotations) { shape.second->updateStyle(style); } for (const auto& layer : obsoleteShapeAnnotationLayers) { if (style.getLayer(layer)) { style.removeLayer(layer); } } obsoleteShapeAnnotationLayers.clear(); for (auto& monitor : monitors) { monitor->update(getTile(monitor->tileID)); } } void AnnotationManager::addTileMonitor(AnnotationTileMonitor& monitor) { monitors.insert(&monitor); monitor.update(getTile(monitor.tileID)); } void AnnotationManager::removeTileMonitor(AnnotationTileMonitor& monitor) { monitors.erase(&monitor); } void AnnotationManager::addIcon(const std::string& name, std::shared_ptr sprite) { spriteStore.setSprite(name, sprite); spriteAtlas.updateDirty(); } void AnnotationManager::removeIcon(const std::string& name) { spriteStore.removeSprite(name); spriteAtlas.updateDirty(); } double AnnotationManager::getTopOffsetPixelsForIcon(const std::string& name) { auto sprite = spriteStore.getSprite(name); return sprite ? -(sprite->image.height / sprite->pixelRatio) / 2 : 0; } } // namespace mbgl