Files
MapLibreParticleLab/src/mbgl/annotation/annotation_manager.cpp
2016-02-12 16:47:24 -08:00

168 lines
5.5 KiB
C++

#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/layer/symbol_layer.hpp>
#include <boost/function_output_iterator.hpp>
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<PointAnnotation>& 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<PointAnnotationImpl>(annotationID, point);
pointTree.insert(annotation);
pointAnnotations.emplace(annotationID, annotation);
annotationIDs.push_back(annotationID);
}
return annotationIDs;
}
AnnotationIDs
AnnotationManager::addShapeAnnotations(const std::vector<ShapeAnnotation>& 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<ShapeAnnotationImpl>(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<PointAnnotationImpl>(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<AnnotationTile> AnnotationManager::getTile(const TileID& tileID) {
if (pointAnnotations.empty() && shapeAnnotations.empty())
return nullptr;
auto tile = std::make_unique<AnnotationTile>();
AnnotationTileLayer& pointLayer = *tile->layers.emplace(
PointLayerID,
std::make_unique<AnnotationTileLayer>()).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> source = std::make_unique<Source>(SourceType::Annotations, SourceID, "", util::tileSize, std::make_unique<SourceInfo>(), nullptr);
source->enabled = true;
style.addSource(std::move(source));
std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>();
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<const SpriteImage> 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