diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-06-26 18:49:06 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-06-29 10:54:17 -0700 |
commit | 42c06e70392941a9c07b842f019c4b060f716ff7 (patch) | |
tree | 18dfc09adcabc7239a738a416d7bac98b0ef50f9 | |
parent | f675d233142bbbfbe77c0145128c3eedfb18e824 (diff) | |
download | qtlocation-mapboxgl-42c06e70392941a9c07b842f019c4b060f716ff7.tar.gz |
Use array of structs rather than parallel arrays for annotations
-rw-r--r-- | include/mbgl/annotation/point_annotation.hpp | 22 | ||||
-rw-r--r-- | include/mbgl/annotation/shape_annotation.hpp | 24 | ||||
-rw-r--r-- | include/mbgl/map/map.hpp | 19 | ||||
-rw-r--r-- | platform/default/glfw_view.cpp | 18 | ||||
-rw-r--r-- | platform/ios/MGLMapView.mm | 27 | ||||
-rw-r--r-- | src/mbgl/map/annotation.cpp | 186 | ||||
-rw-r--r-- | src/mbgl/map/annotation.hpp | 30 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 24 |
8 files changed, 179 insertions, 171 deletions
diff --git a/include/mbgl/annotation/point_annotation.hpp b/include/mbgl/annotation/point_annotation.hpp new file mode 100644 index 0000000000..17b6fe5369 --- /dev/null +++ b/include/mbgl/annotation/point_annotation.hpp @@ -0,0 +1,22 @@ +#ifndef MBGL_ANNOTATION_POINT_ANNOTATION +#define MBGL_ANNOTATION_POINT_ANNOTATION + +#include <mbgl/util/geo.hpp> + +#include <string> + +namespace mbgl { + +class PointAnnotation { +public: + inline PointAnnotation(const LatLng& position_, const std::string& icon_ = "") + : position(position_), icon(icon_) { + } + + const LatLng position; + const std::string icon; +}; + +} + +#endif diff --git a/include/mbgl/annotation/shape_annotation.hpp b/include/mbgl/annotation/shape_annotation.hpp new file mode 100644 index 0000000000..a35b867266 --- /dev/null +++ b/include/mbgl/annotation/shape_annotation.hpp @@ -0,0 +1,24 @@ +#ifndef MBGL_ANNOTATION_SHAPE_ANNOTATION +#define MBGL_ANNOTATION_SHAPE_ANNOTATION + +#include <mbgl/util/geo.hpp> +#include <mbgl/map/map.hpp> +#include <mbgl/style/style_properties.hpp> + +#include <string> + +namespace mbgl { + +class ShapeAnnotation { +public: + inline ShapeAnnotation(const AnnotationSegments& segments_, const StyleProperties& styleProperties_) + : segments(segments_), styleProperties(styleProperties_) { + } + + const AnnotationSegments segments; + const StyleProperties styleProperties; +}; + +} + +#endif diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 6fd5e96063..59f23fe2b2 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -4,7 +4,6 @@ #include <mbgl/util/chrono.hpp> #include <mbgl/map/update.hpp> #include <mbgl/map/mode.hpp> -#include <mbgl/style/style_properties.hpp> #include <mbgl/util/geo.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/vec.hpp> @@ -14,7 +13,6 @@ #include <functional> #include <vector> #include <memory> -#include <unordered_map> namespace mbgl { @@ -24,6 +22,8 @@ class MapData; class MapContext; class StillImage; class Transform; +class PointAnnotation; +class ShapeAnnotation; namespace util { template <class T> class Thread; @@ -129,15 +129,16 @@ public: // Annotations void setDefaultPointAnnotationSymbol(const std::string&); double getTopOffsetPixelsForAnnotationSymbol(const std::string&); - uint32_t addPointAnnotation(const LatLng&, const std::string& symbol); - AnnotationIDs addPointAnnotations(const AnnotationSegment&, - const std::vector<std::string>& symbols); - uint32_t addShapeAnnotation(const AnnotationSegments&, - const StyleProperties&); - AnnotationIDs addShapeAnnotations(const std::vector<AnnotationSegments>&, - const std::vector<StyleProperties>&); + + uint32_t addPointAnnotation(const PointAnnotation&); + AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&); + + uint32_t addShapeAnnotation(const ShapeAnnotation&); + AnnotationIDs addShapeAnnotations(const std::vector<ShapeAnnotation>&); + void removeAnnotation(uint32_t); void removeAnnotations(const AnnotationIDs&); + AnnotationIDs getAnnotationsInBounds(const LatLngBounds&, const AnnotationType& = AnnotationType::Any); LatLngBounds getBoundsForAnnotations(const AnnotationIDs&); diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp index 756b842695..fe37b398d2 100644 --- a/platform/default/glfw_view.cpp +++ b/platform/default/glfw_view.cpp @@ -1,3 +1,5 @@ +#include <mbgl/annotation/point_annotation.hpp> +#include <mbgl/annotation/shape_annotation.hpp> #include <mbgl/platform/default/glfw_view.hpp> #include <mbgl/platform/gl.hpp> #include <mbgl/platform/log.hpp> @@ -149,21 +151,18 @@ mbgl::LatLng GLFWView::makeRandomPoint() const { void GLFWView::addRandomPointAnnotations(int count) { - std::vector<mbgl::LatLng> points; - std::vector<std::string> markers; + std::vector<mbgl::PointAnnotation> points; for (int i = 0; i < count; i++) { - points.push_back(makeRandomPoint()); - markers.push_back("default_marker"); + points.emplace_back(makeRandomPoint(), "default_marker"); } - auto newIDs = map->addPointAnnotations(points, markers); + auto newIDs = map->addPointAnnotations(points); annotationIDs.insert(annotationIDs.end(), newIDs.begin(), newIDs.end()); } void GLFWView::addRandomShapeAnnotations(int count) { - std::vector<mbgl::AnnotationSegments> shapes; - std::vector<mbgl::StyleProperties> shapesProperties; + std::vector<mbgl::ShapeAnnotation> shapes; mbgl::FillProperties fillProperties; fillProperties.opacity = .1; @@ -180,11 +179,10 @@ void GLFWView::addRandomShapeAnnotations(int count) { mbgl::AnnotationSegments segments; segments.push_back(triangle); - shapes.push_back(segments); - shapesProperties.push_back(properties); + shapes.emplace_back(segments, properties); } - auto newIDs = map->addShapeAnnotations(shapes, shapesProperties); + auto newIDs = map->addShapeAnnotations(shapes); annotationIDs.insert(annotationIDs.end(), newIDs.begin(), newIDs.end()); } diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 07822dd03e..5395964314 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -8,6 +8,8 @@ #import <OpenGLES/EAGL.h> #include <mbgl/mbgl.hpp> +#include <mbgl/annotation/point_annotation.hpp> +#include <mbgl/annotation/shape_annotation.hpp> #include <mbgl/platform/platform.hpp> #include <mbgl/platform/darwin/reachability.h> #include <mbgl/storage/default_file_source.hpp> @@ -1780,11 +1782,8 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) { if ( ! annotations) return; - std::vector<mbgl::LatLng> points; - std::vector<std::string> symbols; - - std::vector<mbgl::AnnotationSegments> shapes; - std::vector<mbgl::StyleProperties> shapesProperties; + std::vector<mbgl::PointAnnotation> points; + std::vector<mbgl::ShapeAnnotation> shapes; BOOL delegateImplementsSymbolLookup = [self.delegate respondsToSelector:@selector(mapView:symbolNameForAnnotation:)]; BOOL delegateImplementsAlphaForShape = [self.delegate respondsToSelector:@selector(mapView:alphaForShapeAnnotation:)]; @@ -1851,29 +1850,25 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) userInfo:nil] raise]; } - shapesProperties.push_back(shapeProperties); - NSUInteger count = [(MGLMultiPoint *)annotation pointCount]; CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D *)malloc(count * sizeof(CLLocationCoordinate2D)); [(MGLMultiPoint *)annotation getCoordinates:coordinates range:NSMakeRange(0, count)]; - mbgl::AnnotationSegment shape; - shape.reserve(count); + mbgl::AnnotationSegment segment; + segment.reserve(count); for (NSUInteger i = 0; i < count; i++) { - shape.push_back(mbgl::LatLng(coordinates[i].latitude, coordinates[i].longitude)); + segment.push_back(mbgl::LatLng(coordinates[i].latitude, coordinates[i].longitude)); } free(coordinates); - shapes.push_back({{ shape }}); + shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties); } else { - points.push_back(MGLLatLngFromLocationCoordinate2D(annotation.coordinate)); - NSString *symbolName = nil; if (delegateImplementsSymbolLookup) @@ -1881,13 +1876,13 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) symbolName = [self.delegate mapView:self symbolNameForAnnotation:annotation]; } - symbols.push_back((symbolName ? [symbolName UTF8String] : "")); + points.emplace_back(MGLLatLngFromLocationCoordinate2D(annotation.coordinate), symbolName ? [symbolName UTF8String] : ""); } } if (points.size()) { - std::vector<uint32_t> pointAnnotationIDs = _mbglMap->addPointAnnotations(points, symbols); + std::vector<uint32_t> pointAnnotationIDs = _mbglMap->addPointAnnotations(points); for (size_t i = 0; i < pointAnnotationIDs.size(); ++i) { @@ -1898,7 +1893,7 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) if (shapes.size()) { - std::vector<uint32_t> shapeAnnotationIDs = _mbglMap->addShapeAnnotations(shapes, shapesProperties); + std::vector<uint32_t> shapeAnnotationIDs = _mbglMap->addShapeAnnotations(shapes); for (size_t i = 0; i < shapeAnnotationIDs.size(); ++i) { diff --git a/src/mbgl/map/annotation.cpp b/src/mbgl/map/annotation.cpp index 68491bb985..5b857e9b59 100644 --- a/src/mbgl/map/annotation.cpp +++ b/src/mbgl/map/annotation.cpp @@ -1,5 +1,6 @@ #include <mbgl/map/annotation.hpp> -#include <mbgl/map/map.hpp> +#include <mbgl/annotation/point_annotation.hpp> +#include <mbgl/annotation/shape_annotation.hpp> #include <mbgl/map/tile_id.hpp> #include <mbgl/map/live_tile.hpp> #include <mbgl/util/constants.hpp> @@ -77,94 +78,6 @@ vec2<double> AnnotationManager::projectPoint(const LatLng& point) { return { x, y }; } -std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> -AnnotationManager::addAnnotations(const AnnotationType type, - const std::vector<AnnotationSegments>& segments, - const std::vector<StyleProperties>& styleProperties, - const AnnotationsProperties& annotationsProperties, - const uint8_t maxZoom) { - std::lock_guard<std::mutex> lock(mtx); - - assert(type != AnnotationType::Any); - - // We pre-generate tiles to contain each annotation up to the map's max zoom. - // We do this for fast rendering without projection conversions on the fly, as well as - // to simplify bounding box queries of annotations later. Tiles get invalidated when - // annotations are added or removed in order to refresh the map render without - // touching the base map underneath. - - AnnotationIDs annotationIDs; - annotationIDs.reserve((type == AnnotationType::Shape ? - segments.size() : // shapes - segments[0][0].size())); // points - - std::unordered_set<TileID, TileID::Hash> affectedTiles; - - for (size_t s = 0; s < segments.size(); ++s) { - - if (type == AnnotationType::Point) { - - for (size_t l = 0; l < segments[s].size(); ++l) { - - for (size_t p = 0; p < segments[s][l].size(); ++p) { - - auto& point = segments[s][l][p]; - - // projection conversion into unit space - const auto pp = projectPoint(point); - - const uint32_t pointAnnotationID = nextID(); - - // at render time we style the point according to its {sprite} field - std::unordered_map<std::string, std::string> pointFeatureProperties; - const std::string& symbol = annotationsProperties.at("symbols")[p]; - if (symbol.length()) { - pointFeatureProperties.emplace("sprite", symbol); - } else { - pointFeatureProperties.emplace("sprite", defaultPointAnnotationSymbol); - } - - // add individual point tile feature - auto featureAffectedTiles = addTileFeature( - pointAnnotationID, - AnnotationSegments({{ point }}), - std::vector<std::vector<vec2<double>>>({{ pp }}), - AnnotationType::Point, - {{ }}, - pointFeatureProperties, - maxZoom - ); - - std::copy(featureAffectedTiles.begin(), featureAffectedTiles.end(), std::inserter(affectedTiles, affectedTiles.begin())); - - annotationIDs.push_back(pointAnnotationID); - } - } - } else { - - const uint32_t shapeAnnotationID = nextID(); - - // current shape tiles are on-the-fly, so we don't get any "affected tiles" - // and just expire all annotation tiles for shape adds - - addTileFeature( - shapeAnnotationID, - segments[s], - {{ }}, - AnnotationType::Shape, - styleProperties[s], - {{ }}, - maxZoom - ); - - annotationIDs.push_back(shapeAnnotationID); - } - } - - // Tile:IDs that need refreshed and the annotation identifiers held onto by the client. - return std::make_pair(affectedTiles, annotationIDs); -} - std::unordered_set<TileID, TileID::Hash> AnnotationManager::addTileFeature(const uint32_t annotationID, const AnnotationSegments& segments, @@ -346,26 +259,91 @@ AnnotationManager::addTileFeature(const uint32_t annotationID, } std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> -AnnotationManager::addPointAnnotations(const AnnotationSegment& points, - const AnnotationsProperties& annotationsProperties, +AnnotationManager::addPointAnnotations(const std::vector<PointAnnotation>& points, const uint8_t maxZoom) { - return addAnnotations(AnnotationType::Point, - {{ points }}, - {{ }}, - annotationsProperties, - maxZoom); + std::lock_guard<std::mutex> lock(mtx); + + // We pre-generate tiles to contain each annotation up to the map's max zoom. + // We do this for fast rendering without projection conversions on the fly, as well as + // to simplify bounding box queries of annotations later. Tiles get invalidated when + // annotations are added or removed in order to refresh the map render without + // touching the base map underneath. + + AnnotationIDs annotationIDs; + annotationIDs.reserve(points.size()); + + std::unordered_set<TileID, TileID::Hash> affectedTiles; + + for (const PointAnnotation& point : points) { + // projection conversion into unit space + const auto pp = projectPoint(point.position); + const uint32_t pointAnnotationID = nextID(); + + // at render time we style the point according to its {sprite} field + std::unordered_map<std::string, std::string> pointFeatureProperties; + if (point.icon.length()) { + pointFeatureProperties.emplace("sprite", point.icon); + } else { + pointFeatureProperties.emplace("sprite", defaultPointAnnotationSymbol); + } + + // add individual point tile feature + auto featureAffectedTiles = addTileFeature( + pointAnnotationID, + AnnotationSegments({{ point.position }}), + std::vector<std::vector<vec2<double>>>({{ pp }}), + AnnotationType::Point, + {{ }}, + pointFeatureProperties, + maxZoom + ); + + std::copy(featureAffectedTiles.begin(), featureAffectedTiles.end(), std::inserter(affectedTiles, affectedTiles.begin())); + + annotationIDs.push_back(pointAnnotationID); + } + + // Tile:IDs that need refreshed and the annotation identifiers held onto by the client. + return std::make_pair(affectedTiles, annotationIDs); } std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> -AnnotationManager::addShapeAnnotations(const std::vector<AnnotationSegments>& shapes, - const std::vector<StyleProperties>& styleProperties, - const AnnotationsProperties& annotationsProperties, +AnnotationManager::addShapeAnnotations(const std::vector<ShapeAnnotation>& shapes, const uint8_t maxZoom) { - return addAnnotations(AnnotationType::Shape, - shapes, - styleProperties, - annotationsProperties, - maxZoom); + std::lock_guard<std::mutex> lock(mtx); + + // We pre-generate tiles to contain each annotation up to the map's max zoom. + // We do this for fast rendering without projection conversions on the fly, as well as + // to simplify bounding box queries of annotations later. Tiles get invalidated when + // annotations are added or removed in order to refresh the map render without + // touching the base map underneath. + + AnnotationIDs annotationIDs; + annotationIDs.reserve(shapes.size()); + + std::unordered_set<TileID, TileID::Hash> affectedTiles; + + for (const ShapeAnnotation& shape : shapes) { + const uint32_t shapeAnnotationID = nextID(); + + // current shape tiles are on-the-fly, so we don't get any "affected tiles" + // and just expire all annotation tiles for shape adds + + addTileFeature( + shapeAnnotationID, + shape.segments, + {{ }}, + AnnotationType::Shape, + shape.styleProperties, + {{ }}, + maxZoom + ); + + annotationIDs.push_back(shapeAnnotationID); + } + + // Tile:IDs that need refreshed and the annotation identifiers held onto by the client. + return std::make_pair(affectedTiles, annotationIDs); } std::unordered_set<TileID, TileID::Hash> AnnotationManager::removeAnnotations(const AnnotationIDs& ids, diff --git a/src/mbgl/map/annotation.hpp b/src/mbgl/map/annotation.hpp index 4296fea520..e75c57f1f0 100644 --- a/src/mbgl/map/annotation.hpp +++ b/src/mbgl/map/annotation.hpp @@ -21,12 +21,11 @@ namespace mbgl { class Annotation; -class Map; +class PointAnnotation; +class ShapeAnnotation; class LiveTile; class LiveTileFeature; -using AnnotationsProperties = std::unordered_map<std::string, std::vector<std::string>>; - using GeoJSONVT = mapbox::util::geojsonvt::GeoJSONVT; class Annotation : private util::noncopyable { @@ -57,18 +56,19 @@ public: std::unordered_set<TileID, TileID::Hash> resetStaleTiles(); void setDefaultPointAnnotationSymbol(const std::string& symbol); - std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> addPointAnnotations( - const AnnotationSegment&, - const AnnotationsProperties&, - const uint8_t maxZoom); - std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> addShapeAnnotations( - const std::vector<AnnotationSegments>&, - const std::vector<StyleProperties>&, - const AnnotationsProperties&, - const uint8_t maxZoom); + + std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> + addPointAnnotations(const std::vector<PointAnnotation>&, + const uint8_t maxZoom); + + std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> + addShapeAnnotations(const std::vector<ShapeAnnotation>&, + const uint8_t maxZoom); + std::unordered_set<TileID, TileID::Hash> removeAnnotations(const AnnotationIDs&, const uint8_t maxZoom); AnnotationIDs getOrderedShapeAnnotations() const { return orderedShapeAnnotations; } const StyleProperties getAnnotationStyleProperties(uint32_t) const; + AnnotationIDs getAnnotationsInBounds(const LatLngBounds&, const uint8_t maxZoom, const AnnotationType& = AnnotationType::Any) const; LatLngBounds getBoundsForAnnotations(const AnnotationIDs&) const; @@ -80,12 +80,6 @@ public: private: inline uint32_t nextID(); static vec2<double> projectPoint(const LatLng& point); - std::pair<std::unordered_set<TileID, TileID::Hash>, AnnotationIDs> addAnnotations( - const AnnotationType, - const std::vector<AnnotationSegments>&, - const std::vector<StyleProperties>&, - const AnnotationsProperties&, - const uint8_t maxZoom); std::unordered_set<TileID, TileID::Hash> addTileFeature( const uint32_t annotationID, const AnnotationSegments&, diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 940ab82379..2097747bc5 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -4,12 +4,12 @@ #include <mbgl/map/transform.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/map/map_data.hpp> +#include <mbgl/annotation/point_annotation.hpp> +#include <mbgl/annotation/shape_annotation.hpp> #include <mbgl/util/projection.hpp> #include <mbgl/util/thread.hpp> -#include <unordered_map> - namespace mbgl { Map::Map(View& view, FileSource& fileSource, MapMode mode) @@ -292,26 +292,22 @@ double Map::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) { return context->invokeSync<double>(&MapContext::getTopOffsetPixelsForAnnotationSymbol, symbol); } -uint32_t Map::addPointAnnotation(const LatLng& point, const std::string& symbol) { - return addPointAnnotations({ point }, { symbol }).front(); +uint32_t Map::addPointAnnotation(const PointAnnotation& annotation) { + return addPointAnnotations({ annotation }).front(); } -AnnotationIDs Map::addPointAnnotations(const AnnotationSegment& points, - const std::vector<std::string>& symbols) { - AnnotationsProperties properties = { { "symbols", symbols } }; - auto result = data->annotationManager.addPointAnnotations(points, properties, getMaxZoom()); +AnnotationIDs Map::addPointAnnotations(const std::vector<PointAnnotation>& annotations) { + auto result = data->annotationManager.addPointAnnotations(annotations, getMaxZoom()); context->invoke(&MapContext::updateAnnotationTiles, result.first); return result.second; } -uint32_t Map::addShapeAnnotation(const AnnotationSegments& shape, - const StyleProperties& styleProperties) { - return addShapeAnnotations({ shape }, { styleProperties }).front(); +uint32_t Map::addShapeAnnotation(const ShapeAnnotation& annotation) { + return addShapeAnnotations({ annotation }).front(); } -AnnotationIDs Map::addShapeAnnotations(const std::vector<AnnotationSegments>& shapes, - const std::vector<StyleProperties>& styleProperties) { - auto result = data->annotationManager.addShapeAnnotations(shapes, styleProperties, {{}}, getMaxZoom()); +AnnotationIDs Map::addShapeAnnotations(const std::vector<ShapeAnnotation>& annotations) { + auto result = data->annotationManager.addShapeAnnotations(annotations, getMaxZoom()); context->invoke(&MapContext::updateAnnotationTiles, result.first); return result.second; } |