[all] Rationalize annotation API

This commit is contained in:
John Firebaugh
2016-05-31 17:34:11 -07:00
parent cfd6757ecc
commit 0fba70d5a8
32 changed files with 461 additions and 545 deletions

View File

@@ -1,11 +1,52 @@
#pragma once
#include <mbgl/style/types.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/variant.hpp>
#include <cstdint>
#include <vector>
#include <string>
namespace mbgl {
using AnnotationID = uint32_t;
using AnnotationIDs = std::vector<AnnotationID>;
class SymbolAnnotation {
public:
Geometry<double> geometry;
std::string icon;
};
class LineAnnotation {
public:
Geometry<double> geometry;
float opacity = 1;
float width = 1;
Color color = {{ 0, 0, 0, 1 }};
};
class FillAnnotation {
public:
Geometry<double> geometry;
float opacity = 1;
Color color = {{ 0, 0, 0, 1 }};
Color outlineColor = {{ 0, 0, 0, -1 }};
};
// An annotation whose type and properties are sourced from a style layer.
class StyleSourcedAnnotation {
public:
Geometry<double> geometry;
std::string layerID;
};
using Annotation = variant<
SymbolAnnotation,
LineAnnotation,
FillAnnotation,
StyleSourcedAnnotation>;
} // namespace mbgl

View File

@@ -1,18 +0,0 @@
#pragma once
#include <mbgl/util/geo.hpp>
#include <string>
namespace mbgl {
class PointAnnotation {
public:
PointAnnotation(const LatLng& position_, const std::string& icon_ = "")
: position(position_.wrapped()), icon(icon_) {}
const LatLng position;
const std::string icon;
};
} // namespace mbgl

View File

@@ -1,37 +0,0 @@
#pragma once
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/variant.hpp>
namespace mbgl {
struct FillAnnotationProperties {
float opacity = 1;
Color color = {{ 0, 0, 0, 1 }};
Color outlineColor = {{ 0, 0, 0, -1 }};
};
struct LineAnnotationProperties {
float opacity = 1;
float width = 1;
Color color = {{ 0, 0, 0, 1 }};
};
class ShapeAnnotation {
public:
using Properties = variant<
FillAnnotationProperties, // creates a fill annotation
LineAnnotationProperties, // creates a line annotation
std::string>; // creates an annotation whose type and properties are sourced from a style layer
ShapeAnnotation(const Geometry<double>& geometry_, const Properties& properties_)
: geometry(geometry_), properties(properties_) {}
const Geometry<double> geometry;
const Properties properties;
};
} // namespace mbgl

View File

@@ -23,8 +23,6 @@ namespace mbgl {
class FileSource;
class View;
class SpriteImage;
class PointAnnotation;
class ShapeAnnotation;
struct CameraOptions;
struct AnimationOptions;
@@ -142,16 +140,9 @@ public:
void removeAnnotationIcon(const std::string&);
double getTopOffsetPixelsForAnnotationIcon(const std::string&);
AnnotationID addPointAnnotation(const PointAnnotation&);
AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&);
AnnotationID addShapeAnnotation(const ShapeAnnotation&);
AnnotationIDs addShapeAnnotations(const std::vector<ShapeAnnotation>&);
void updatePointAnnotation(AnnotationID, const PointAnnotation&);
AnnotationID addAnnotation(const Annotation&);
void updateAnnotation(AnnotationID, const Annotation&);
void removeAnnotation(AnnotationID);
void removeAnnotations(const AnnotationIDs&);
AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&);

View File

@@ -44,7 +44,6 @@ public:
void report(float duration);
private:
mbgl::LatLng makeRandomLatLng() const;
mbgl::Point<double> makeRandomPoint() const;
static std::shared_ptr<const mbgl::SpriteImage>
makeSpriteImage(int width, int height, float pixelRatio);

View File

@@ -13,8 +13,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/platform/event.hpp>
#include <mbgl/platform/log.hpp>
@@ -681,8 +680,10 @@ void nativeUpdateMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
jdouble latitude = jni::GetField<jdouble>(*env, position, *latLngLatitudeId);
jdouble longitude = jni::GetField<jdouble>(*env, position, *latLngLongitudeId);
// Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
nativeMapView->getMap().updatePointAnnotation(markerId, mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), iconId));
nativeMapView->getMap().updateAnnotation(markerId, mbgl::SymbolAnnotation {
mbgl::Point<double>(longitude, latitude),
iconId
});
}
jni::jarray<jlong>* nativeAddMarkers(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
@@ -693,30 +694,30 @@ jni::jarray<jlong>* nativeAddMarkers(JNIEnv *env, jni::jobject* obj, jlong nativ
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
std::vector<mbgl::PointAnnotation> markers;
markers.reserve(len);
std::vector<mbgl::AnnotationID> ids;
ids.reserve(len);
for (std::size_t i = 0; i < len; i++) {
jni::jobject* marker = jni::GetObjectArrayElement(*env, *jarray, i);
jni::jobject* position = jni::GetField<jni::jobject*>(*env, marker, *markerPositionId);
jni::jobject* icon = jni::GetField<jni::jobject*>(*env, marker, *markerIconId);
jni::DeleteLocalRef(*env, marker);
jni::jstring* jid = reinterpret_cast<jni::jstring*>(jni::GetField<jni::jobject*>(*env, icon, *iconIdId));
jni::DeleteLocalRef(*env, icon);
std::string id = std_string_from_jstring(env, jid);
jni::DeleteLocalRef(*env, jid);
jdouble latitude = jni::GetField<jdouble>(*env, position, *latLngLatitudeId);
jdouble longitude = jni::GetField<jdouble>(*env, position, *latLngLongitudeId);
jni::DeleteLocalRef(*env, position);
markers.emplace_back(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), id));
ids.push_back(nativeMapView->getMap().addAnnotation(mbgl::SymbolAnnotation {
mbgl::Point<double>(longitude, latitude),
std_string_from_jstring(env, jid)
}));
jni::DeleteLocalRef(*env, position);
jni::DeleteLocalRef(*env, jid);
jni::DeleteLocalRef(*env, icon);
jni::DeleteLocalRef(*env, marker);
}
std::vector<uint32_t> pointAnnotationIDs = nativeMapView->getMap().addPointAnnotations(markers);
return std_vector_uint_to_jobject(env, pointAnnotationIDs);
return std_vector_uint_to_jobject(env, ids);
}
static mbgl::Color toColor(jint color) {
@@ -762,24 +763,23 @@ jni::jarray<jlong>* nativeAddPolylines(JNIEnv *env, jni::jobject* obj, jlong nat
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
std::vector<mbgl::ShapeAnnotation> shapes;
shapes.reserve(len);
std::vector<mbgl::AnnotationID> ids;
ids.reserve(len);
for (std::size_t i = 0; i < len; i++) {
jni::jobject* polyline = jni::GetObjectArrayElement(*env, *jarray, i);
mbgl::LineAnnotationProperties lineProperties;
lineProperties.opacity = jni::GetField<jfloat>(*env, polyline, *polylineAlphaId);
lineProperties.color = toColor(jni::GetField<jint>(*env, polyline, *polylineColorId));
lineProperties.width = jni::GetField<jfloat>(*env, polyline, *polylineWidthId);
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
shapes.emplace_back(toGeometry<mbgl::LineString<double>>(env, points), lineProperties);
mbgl::LineAnnotation annotation { toGeometry<mbgl::LineString<double>>(env, points) };
annotation.opacity = jni::GetField<jfloat>(*env, polyline, *polylineAlphaId);
annotation.color = toColor(jni::GetField<jint>(*env, polyline, *polylineColorId));
annotation.width = jni::GetField<jfloat>(*env, polyline, *polylineWidthId);
ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
jni::DeleteLocalRef(*env, polyline);
}
return std_vector_uint_to_jobject(env, nativeMapView->getMap().addShapeAnnotations(shapes));
return std_vector_uint_to_jobject(env, ids);
}
jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
@@ -790,24 +790,23 @@ jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nati
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
std::vector<mbgl::ShapeAnnotation> shapes;
shapes.reserve(len);
std::vector<mbgl::AnnotationID> ids;
ids.reserve(len);
for (std::size_t i = 0; i < len; i++) {
jni::jobject* polygon = jni::GetObjectArrayElement(*env, *jarray, i);
mbgl::FillAnnotationProperties fillProperties;
fillProperties.opacity = jni::GetField<jfloat>(*env, polygon, *polygonAlphaId);
fillProperties.outlineColor = toColor(jni::GetField<jint>(*env, polygon, *polygonStrokeColorId));
fillProperties.color = toColor(jni::GetField<jint>(*env, polygon, *polygonFillColorId));
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
shapes.emplace_back(mbgl::Polygon<double> { toGeometry<mbgl::LinearRing<double>>(env, points) }, fillProperties);
mbgl::FillAnnotation annotation { mbgl::Polygon<double> { toGeometry<mbgl::LinearRing<double>>(env, points) } };
annotation.opacity = jni::GetField<jfloat>(*env, polygon, *polygonAlphaId);
annotation.outlineColor = toColor(jni::GetField<jint>(*env, polygon, *polygonStrokeColorId));
annotation.color = toColor(jni::GetField<jint>(*env, polygon, *polygonFillColorId));
ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
jni::DeleteLocalRef(*env, polygon);
}
return std_vector_uint_to_jobject(env, nativeMapView->getMap().addShapeAnnotations(shapes));
return std_vector_uint_to_jobject(env, ids);
}
void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jlong>* jarray) {
@@ -817,20 +816,14 @@ void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
std::vector<uint32_t> ids;
ids.reserve(len);
auto elements = jni::GetArrayElements(*env, *jarray);
jlong* jids = std::get<0>(elements).get();
for (std::size_t i = 0; i < len; i++) {
if(jids[i] == -1L)
continue;
ids.push_back(static_cast<uint32_t>(jids[i]));
nativeMapView->getMap().removeAnnotation(jids[i]);
}
nativeMapView->getMap().removeAnnotations(ids);
}
jni::jarray<jlong>* nativeGetAnnotationsInBounds(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* latLngBounds_) {

View File

@@ -6,6 +6,7 @@
#endif
#import <mbgl/util/geo.hpp>
#import <mbgl/util/geometry.hpp>
/// Returns the smallest rectangle that contains both the given rectangle and
/// the given point.
@@ -15,6 +16,10 @@ NS_INLINE mbgl::LatLng MGLLatLngFromLocationCoordinate2D(CLLocationCoordinate2D
return mbgl::LatLng(coordinate.latitude, coordinate.longitude);
}
NS_INLINE mbgl::Point<double> MGLPointFromLocationCoordinate2D(CLLocationCoordinate2D coordinate) {
return mbgl::Point<double>(coordinate.longitude, coordinate.latitude);
}
NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) {
return CLLocationCoordinate2DMake(latLng.latitude, latLng.longitude);
}

View File

@@ -3,7 +3,7 @@
#import "MGLGeometry.h"
#import "MGLTypes.h"
#import <mbgl/annotation/shape_annotation.hpp>
#import <mbgl/annotation/annotation.hpp>
#import <vector>
#import <CoreGraphics/CoreGraphics.h>
@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds;
/** Constructs a shape annotation object, asking the delegate for style values. */
- (mbgl::ShapeAnnotation)shapeAnnotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate;
- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate;
@end

View File

@@ -36,19 +36,19 @@
return result;
}
- (mbgl::ShapeAnnotation)shapeAnnotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
mbgl::FillAnnotationProperties fillProperties;
fillProperties.opacity = [delegate alphaForShapeAnnotation:self];
fillProperties.outlineColor = [delegate strokeColorForShapeAnnotation:self];
fillProperties.color = [delegate fillColorForPolygonAnnotation:self];
- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
mbgl::Polygon<double> geometry;
geometry.push_back(self.ring);
for (MGLPolygon *polygon in self.interiorPolygons) {
geometry.push_back(polygon.ring);
}
return mbgl::ShapeAnnotation(geometry, fillProperties);
mbgl::FillAnnotation annotation { geometry };
annotation.opacity = [delegate alphaForShapeAnnotation:self];
annotation.outlineColor = [delegate strokeColorForShapeAnnotation:self];
annotation.color = [delegate fillColorForPolygonAnnotation:self];
return annotation;
}
@end

View File

@@ -13,12 +13,7 @@
return [[self alloc] initWithCoordinates:coords count:count];
}
- (mbgl::ShapeAnnotation)shapeAnnotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
mbgl::LineAnnotationProperties lineProperties;
lineProperties.opacity = [delegate alphaForShapeAnnotation:self];
lineProperties.color = [delegate strokeColorForShapeAnnotation:self];
lineProperties.width = [delegate lineWidthForPolylineAnnotation:self];
- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
NSUInteger count = self.pointCount;
CLLocationCoordinate2D *coordinates = self.coordinates;
@@ -28,7 +23,12 @@
geometry.push_back(mbgl::Point<double>(coordinates[i].longitude, coordinates[i].latitude));
}
return mbgl::ShapeAnnotation(geometry, lineProperties);
mbgl::LineAnnotation annotation { geometry };
annotation.opacity = [delegate alphaForShapeAnnotation:self];
annotation.color = [delegate strokeColorForShapeAnnotation:self];
annotation.width = [delegate lineWidthForPolylineAnnotation:self];
return annotation;
}
@end

View File

@@ -1,6 +1,5 @@
#include <mbgl/platform/default/glfw_view.hpp>
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/style/property_transition.hpp>
#include <mbgl/gl/gl.hpp>
@@ -208,14 +207,10 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action,
}
}
mbgl::LatLng GLFWView::makeRandomLatLng() const {
mbgl::Point<double> GLFWView::makeRandomPoint() const {
const double x = width * double(std::rand()) / RAND_MAX;
const double y = height * double(std::rand()) / RAND_MAX;
return map->latLngForPixel({ x, y });
}
mbgl::Point<double> GLFWView::makeRandomPoint() const {
mbgl::LatLng latLng = makeRandomLatLng();
mbgl::LatLng latLng = map->latLngForPixel({ x, y });
return { latLng.longitude, latLng.latitude };
}
@@ -259,53 +254,34 @@ void GLFWView::nextOrientation() {
}
void GLFWView::addRandomCustomPointAnnotations(int count) {
std::vector<mbgl::PointAnnotation> points;
for (int i = 0; i < count; i++) {
static int spriteID = 1;
const auto name = std::string{ "marker-" } + mbgl::util::toString(spriteID++);
map->addAnnotationIcon(name, makeSpriteImage(22, 22, 1));
spriteIDs.push_back(name);
points.emplace_back(makeRandomLatLng(), name);
annotationIDs.push_back(map->addAnnotation(mbgl::SymbolAnnotation { makeRandomPoint(), name }));
}
auto newIDs = map->addPointAnnotations(points);
annotationIDs.insert(annotationIDs.end(), newIDs.begin(), newIDs.end());
}
void GLFWView::addRandomPointAnnotations(int count) {
std::vector<mbgl::PointAnnotation> points;
for (int i = 0; i < count; i++) {
points.emplace_back(makeRandomLatLng(), "default_marker");
annotationIDs.push_back(map->addAnnotation(mbgl::SymbolAnnotation { makeRandomPoint(), "default_marker" }));
}
auto newIDs = map->addPointAnnotations(points);
annotationIDs.insert(annotationIDs.end(), newIDs.begin(), newIDs.end());
}
void GLFWView::addRandomShapeAnnotations(int count) {
std::vector<mbgl::ShapeAnnotation> shapes;
mbgl::FillAnnotationProperties properties;
properties.opacity = .1;
for (int i = 0; i < count; i++) {
mbgl::Polygon<double> triangle;
triangle.push_back({ makeRandomPoint(), makeRandomPoint(), makeRandomPoint() });
shapes.emplace_back(triangle, properties);
annotationIDs.push_back(map->addAnnotation(mbgl::FillAnnotation { triangle, .1 }));
}
auto newIDs = map->addShapeAnnotations(shapes);
annotationIDs.insert(annotationIDs.end(), newIDs.begin(), newIDs.end());
}
void GLFWView::clearAnnotations() {
if (annotationIDs.empty()) {
return;
for (const auto& id : annotationIDs) {
map->removeAnnotation(id);
}
map->removeAnnotations(annotationIDs);
annotationIDs.clear();
}

View File

@@ -7,8 +7,7 @@
#import <OpenGLES/EAGL.h>
#include <mbgl/mbgl.hpp>
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/mode.hpp>
@@ -1776,9 +1775,9 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
// but safely updated.
if (annotation == [self annotationWithTag:annotationTag])
{
const mbgl::LatLng latLng = MGLLatLngFromLocationCoordinate2D(annotation.coordinate);
const mbgl::Point<double> point = MGLPointFromLocationCoordinate2D(annotation.coordinate);
MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
_mbglMap->updatePointAnnotation(annotationTag, { latLng, annotationImage.styleIconIdentifier.UTF8String ?: "" });
_mbglMap->updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, annotationImage.styleIconIdentifier.UTF8String ?: "" });
if (annotationTag == _selectedAnnotationTag)
{
[self deselectAnnotation:annotation animated:YES];
@@ -2796,11 +2795,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
if ( ! annotations) return;
[self willChangeValueForKey:@"annotations"];
NSMutableArray *userPoints = [NSMutableArray array];
std::vector<mbgl::PointAnnotation> points;
NSMutableArray *userShapes = [NSMutableArray array];
std::vector<mbgl::ShapeAnnotation> shapes;
NSMutableDictionary *annotationImagesForAnnotation = [NSMutableDictionary dictionary];
NSMutableDictionary *annotationViewsForAnnotation = [NSMutableDictionary dictionary];
@@ -2820,8 +2814,11 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
if (!multiPoint.pointCount) {
continue;
}
shapes.emplace_back([multiPoint shapeAnnotationObjectWithDelegate:self]);
[userShapes addObject:annotation];
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation([multiPoint annotationObjectWithDelegate:self]);
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
}
else if ([annotation isKindOfClass:[MGLMultiPolyline class]]
|| [annotation isKindOfClass:[MGLMultiPolygon class]]
@@ -2877,22 +2874,11 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
annotationImagesForAnnotation[annotationValue] = annotationImage;
}
[userPoints addObject:annotation];
points.emplace_back(MGLLatLngFromLocationCoordinate2D(annotation.coordinate), symbolName.UTF8String ?: "");
}
}
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation(mbgl::SymbolAnnotation {
MGLPointFromLocationCoordinate2D(annotation.coordinate),
symbolName.UTF8String ?: ""
});
if (points.size())
{
// refactor this to build contexts above and just associate with tags here
std::vector<MGLAnnotationTag> annotationTags = _mbglMap->addPointAnnotations(points);
for (size_t i = 0; i < annotationTags.size(); ++i)
{
id<MGLAnnotation> annotation = userPoints[i];
NSValue *annotationValue = [NSValue valueWithNonretainedObject:annotation];
MGLAnnotationContext context;
context.annotation = annotation;
MGLAnnotationImage *annotationImage = annotationImagesForAnnotation[annotationValue];
@@ -2900,13 +2886,11 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
if (annotationImage) {
context.imageReuseIdentifier = annotationImage.reuseIdentifier;
}
MGLAnnotationView *annotationView = annotationViewsForAnnotation[annotationValue];
if (annotationView) {
context.annotationView = annotationView;
context.viewReuseIdentifier = annotationView.reuseIdentifier;
}
MGLAnnotationTag annotationTag = annotationTags[i];
_annotationContextsByAnnotationTag[annotationTag] = context;
if ([annotation isKindOfClass:[NSObject class]]) {
NSAssert(![annotation isKindOfClass:[MGLMultiPoint class]], @"Point annotation should not be MGLMultiPoint.");
@@ -2915,21 +2899,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
}
}
if (shapes.size())
{
std::vector<MGLAnnotationTag> annotationTags = _mbglMap->addShapeAnnotations(shapes);
for (size_t i = 0; i < annotationTags.size(); ++i)
{
MGLAnnotationTag annotationTag = annotationTags[i];
id <MGLAnnotation> annotation = userShapes[i];
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
}
}
[self updateAnnotationContainerViewWithAnnotationViews:newAnnotationViews];
[self didChangeValueForKey:@"annotations"];
@@ -3072,8 +3041,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
if ( ! annotations) return;
std::vector<MGLAnnotationTag> annotationTagsToRemove;
annotationTagsToRemove.reserve(annotations.count);
[self willChangeValueForKey:@"annotations"];
for (id <MGLAnnotation> annotation in annotations)
{
@@ -3088,8 +3056,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
MGLAnnotationView *annotationView = annotationContext.annotationView;
[annotationView removeFromSuperview];
annotationTagsToRemove.push_back(annotationTag);
if (annotationTag == _selectedAnnotationTag)
{
@@ -3102,15 +3068,12 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinate" context:(void *)(NSUInteger)annotationTag];
}
_mbglMap->removeAnnotation(annotationTag);
}
if ( ! annotationTagsToRemove.empty())
{
[self willChangeValueForKey:@"annotations"];
_mbglMap->removeAnnotations(annotationTagsToRemove);
[self didChangeValueForKey:@"annotations"];
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
[self didChangeValueForKey:@"annotations"];
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
- (void)addOverlay:(id <MGLOverlay>)overlay
@@ -3675,8 +3638,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
if ([pair.second.imageReuseIdentifier isEqualToString:reuseIdentifier])
{
const mbgl::LatLng latLng = MGLLatLngFromLocationCoordinate2D(pair.second.annotation.coordinate);
_mbglMap->updatePointAnnotation(pair.first, { latLng, iconIdentifier.UTF8String ?: "" });
const mbgl::Point<double> point = MGLPointFromLocationCoordinate2D(pair.second.annotation.coordinate);
_mbglMap->updateAnnotation(pair.first, mbgl::SymbolAnnotation { point, iconIdentifier.UTF8String ?: "" });
}
}
}

View File

@@ -18,7 +18,7 @@
#import "MGLMapViewDelegate.h"
#import <mbgl/mbgl.hpp>
#import <mbgl/annotation/point_annotation.hpp>
#import <mbgl/annotation/annotation.hpp>
#import <mbgl/map/camera.hpp>
#import <mbgl/platform/darwin/reachability.h>
#import <mbgl/gl/gl.hpp>
@@ -481,9 +481,9 @@ public:
// match a valid annotation tag, the annotation will be unnecessarily
// but safely updated.
if (annotation == [self annotationWithTag:annotationTag]) {
const mbgl::LatLng latLng = MGLLatLngFromLocationCoordinate2D(annotation.coordinate);
const mbgl::Point<double> point = MGLPointFromLocationCoordinate2D(annotation.coordinate);
MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
_mbglMap->updatePointAnnotation(annotationTag, { latLng, annotationImage.styleIconIdentifier.UTF8String ?: "" });
_mbglMap->updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, annotationImage.styleIconIdentifier.UTF8String ?: "" });
if (annotationTag == _selectedAnnotationTag) {
[self deselectAnnotation:annotation];
}
@@ -1604,12 +1604,6 @@ public:
BOOL delegateHasImagesForAnnotations = [self.delegate respondsToSelector:@selector(mapView:imageForAnnotation:)];
NSMutableArray *userPoints = [NSMutableArray array];
std::vector<mbgl::PointAnnotation> points;
NSMutableArray *userShapes = [NSMutableArray array];
std::vector<mbgl::ShapeAnnotation> shapes;
NSMutableArray *annotationImages = [NSMutableArray arrayWithCapacity:annotations.count];
for (id <MGLAnnotation> annotation in annotations) {
NSAssert([annotation conformsToProtocol:@protocol(MGLAnnotation)], @"Annotation does not conform to MGLAnnotation");
@@ -1619,8 +1613,11 @@ public:
if (!multiPoint.pointCount) {
continue;
}
shapes.emplace_back([multiPoint shapeAnnotationObjectWithDelegate:self]);
[userShapes addObject:annotation];
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation([multiPoint annotationObjectWithDelegate:self]);
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
} else if ([annotation isKindOfClass:[MGLMultiPolyline class]]
|| [annotation isKindOfClass:[MGLMultiPolygon class]]
|| [annotation isKindOfClass:[MGLShapeCollection class]]) {
@@ -1647,28 +1644,12 @@ public:
self.annotationImagesByIdentifier[annotationImage.reuseIdentifier] = annotationImage;
[self installAnnotationImage:annotationImage];
}
[annotationImages addObject:annotationImage];
[userPoints addObject:annotation];
points.emplace_back(MGLLatLngFromLocationCoordinate2D(annotation.coordinate), symbolName.UTF8String ?: "");
// Opt into potentially expensive tooltip tracking areas.
if (annotation.toolTip.length) {
_wantsToolTipRects = YES;
}
}
}
// Add any point annotations to mbgl and our own index.
if (points.size()) {
std::vector<MGLAnnotationTag> annotationTags = _mbglMap->addPointAnnotations(points);
for (size_t i = 0; i < annotationTags.size(); ++i) {
MGLAnnotationTag annotationTag = annotationTags[i];
MGLAnnotationImage *annotationImage = annotationImages[i];
annotationImage.styleIconIdentifier = @(points[i].icon.c_str());
id <MGLAnnotation> annotation = userPoints[i];
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation(mbgl::SymbolAnnotation {
MGLPointFromLocationCoordinate2D(annotation.coordinate),
symbolName.UTF8String ?: ""
});
MGLAnnotationContext context;
context.annotation = annotation;
context.imageReuseIdentifier = annotationImage.reuseIdentifier;
@@ -1678,23 +1659,14 @@ public:
NSAssert(![annotation isKindOfClass:[MGLMultiPoint class]], @"Point annotation should not be MGLMultiPoint.");
[(NSObject *)annotation addObserver:self forKeyPath:@"coordinate" options:0 context:(void *)(NSUInteger)annotationTag];
}
// Opt into potentially expensive tooltip tracking areas.
if (annotation.toolTip.length) {
_wantsToolTipRects = YES;
}
}
}
// Add any shape annotations to mbgl and our own index.
if (shapes.size()) {
std::vector<MGLAnnotationTag> annotationTags = _mbglMap->addShapeAnnotations(shapes);
for (size_t i = 0; i < annotationTags.size(); ++i) {
MGLAnnotationTag annotationTag = annotationTags[i];
id <MGLAnnotation> annotation = userShapes[i];
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
}
}
[self didChangeValueForKey:@"annotations"];
[self updateAnnotationTrackingAreas];
@@ -1765,16 +1737,14 @@ public:
return;
}
std::vector<MGLAnnotationTag> annotationTagsToRemove;
annotationTagsToRemove.reserve(annotations.count);
[self willChangeValueForKey:@"annotations"];
for (id <MGLAnnotation> annotation in annotations) {
NSAssert([annotation conformsToProtocol:@protocol(MGLAnnotation)], @"Annotation does not conform to MGLAnnotation");
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
NSAssert(annotationTag != MGLAnnotationTagNotFound, @"No ID for annotation %@", annotation);
annotationTagsToRemove.push_back(annotationTag);
if (annotationTag == _selectedAnnotationTag) {
[self deselectAnnotation:annotation];
}
@@ -1788,10 +1758,10 @@ public:
![annotation isKindOfClass:[MGLMultiPoint class]]) {
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinate" context:(void *)(NSUInteger)annotationTag];
}
_mbglMap->removeAnnotation(annotationTag);
}
[self willChangeValueForKey:@"annotations"];
_mbglMap->removeAnnotations(annotationTagsToRemove);
[self didChangeValueForKey:@"annotations"];
[self updateAnnotationTrackingAreas];

View File

@@ -20,11 +20,9 @@ typedef quint32 AnnotationID;
typedef QList<AnnotationID> AnnotationIDs;
typedef QPair<Coordinate, QString> PointAnnotation;
typedef QList<PointAnnotation> PointAnnotations;
// FIXME: We need to add support for custom style properties
typedef QPair<CoordinateSegments, QString> ShapeAnnotation;
typedef QList<ShapeAnnotation> ShapeAnnotations;
enum NetworkMode {
Online, // Default

View File

@@ -165,15 +165,11 @@ public:
QStringList getClasses() const;
QMapbox::AnnotationID addPointAnnotation(const QMapbox::PointAnnotation &);
QMapbox::AnnotationIDs addPointAnnotations(const QMapbox::PointAnnotations &);
QMapbox::AnnotationID addShapeAnnotation(const QMapbox::ShapeAnnotation &);
QMapbox::AnnotationIDs addShapeAnnotations(const QMapbox::ShapeAnnotations &);
void updatePointAnnotation(QMapbox::AnnotationID, const QMapbox::PointAnnotation &);
void removeAnnotation(QMapbox::AnnotationID);
void removeAnnotations(const QMapbox::AnnotationIDs &);
bool isRotating() const;
bool isScaling() const;

View File

@@ -1,7 +1,6 @@
#include "qmapboxgl_p.hpp"
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/map.hpp>
@@ -376,40 +375,23 @@ QStringList QMapboxGL::getClasses() const
return classNames;
}
mbgl::PointAnnotation fromPointAnnotation(const PointAnnotation &pointAnnotation) {
mbgl::Annotation fromPointAnnotation(const PointAnnotation &pointAnnotation) {
const Coordinate &coordinate = pointAnnotation.first;
const QString &icon = pointAnnotation.second;
return { { coordinate.first, coordinate.second }, icon.toStdString() };
return mbgl::SymbolAnnotation { mbgl::Point<double> { coordinate.second, coordinate.first }, icon.toStdString() };
}
AnnotationID QMapboxGL::addPointAnnotation(const PointAnnotation &pointAnnotation)
{
return d_ptr->mapObj->addPointAnnotation(fromPointAnnotation(pointAnnotation));
}
AnnotationIDs QMapboxGL::addPointAnnotations(const PointAnnotations &pointAnnotations)
{
std::vector<mbgl::PointAnnotation> mbglPointAnnotations;
mbglPointAnnotations.reserve(pointAnnotations.size());
for (const PointAnnotation &pointAnnotation : pointAnnotations) {
mbglPointAnnotations.emplace_back(fromPointAnnotation(pointAnnotation));
}
AnnotationIDs ids;
for (const mbgl::AnnotationID &id : d_ptr->mapObj->addPointAnnotations(mbglPointAnnotations)) {
ids << id;
}
return ids;
return d_ptr->mapObj->addAnnotation(fromPointAnnotation(pointAnnotation));
}
void QMapboxGL::updatePointAnnotation(AnnotationID id, const PointAnnotation &pointAnnotation)
{
d_ptr->mapObj->updatePointAnnotation(id, fromPointAnnotation(pointAnnotation));
d_ptr->mapObj->updateAnnotation(id, fromPointAnnotation(pointAnnotation));
}
mbgl::ShapeAnnotation fromQMapboxGLShapeAnnotation(const ShapeAnnotation &shapeAnnotation) {
mbgl::Annotation fromQMapboxGLShapeAnnotation(const ShapeAnnotation &shapeAnnotation) {
const CoordinateSegments &segments = shapeAnnotation.first;
const QString &styleLayer = shapeAnnotation.second;
@@ -427,29 +409,12 @@ mbgl::ShapeAnnotation fromQMapboxGLShapeAnnotation(const ShapeAnnotation &shapeA
polygon.emplace_back(linearRing);
}
return { polygon, styleLayer.toStdString() };
return mbgl::StyleSourcedAnnotation { polygon, styleLayer.toStdString() };
}
AnnotationID QMapboxGL::addShapeAnnotation(const ShapeAnnotation &shapeAnnotation)
{
return d_ptr->mapObj->addShapeAnnotation(fromQMapboxGLShapeAnnotation(shapeAnnotation));
}
AnnotationIDs QMapboxGL::addShapeAnnotations(const ShapeAnnotations &shapeAnnotations)
{
std::vector<mbgl::ShapeAnnotation> mbglShapeAnnotations;
mbglShapeAnnotations.reserve(shapeAnnotations.size());
for (const ShapeAnnotation &shapeAnnotation : shapeAnnotations) {
mbglShapeAnnotations.emplace_back(fromQMapboxGLShapeAnnotation(shapeAnnotation));
}
AnnotationIDs ids;
for (const mbgl::AnnotationID &id : d_ptr->mapObj->addShapeAnnotations(mbglShapeAnnotations)) {
ids << id;
}
return ids;
return d_ptr->mapObj->addAnnotation(fromQMapboxGLShapeAnnotation(shapeAnnotation));
}
void QMapboxGL::removeAnnotation(AnnotationID annotationID)
@@ -457,18 +422,6 @@ void QMapboxGL::removeAnnotation(AnnotationID annotationID)
d_ptr->mapObj->removeAnnotation(annotationID);
}
void QMapboxGL::removeAnnotations(const AnnotationIDs &annotationIDs)
{
std::vector<mbgl::AnnotationID> mbglAnnotationIds;
mbglAnnotationIds.reserve(annotationIDs.size());
for (const AnnotationID annotationID : annotationIDs) {
mbglAnnotationIds.emplace_back(annotationID);
}
d_ptr->mapObj->removeAnnotations(mbglAnnotationIds);
}
bool QMapboxGL::isRotating() const
{
return d_ptr->mapObj->isRotating();

View File

@@ -1,5 +1,9 @@
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/annotation/line_annotation_impl.hpp>
#include <mbgl/annotation/fill_annotation_impl.hpp>
#include <mbgl/annotation/style_sourced_annotation_impl.hpp>
#include <mbgl/source/source.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/layer/symbol_layer.hpp>
@@ -18,63 +22,54 @@ AnnotationManager::AnnotationManager(float pixelRatio)
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;
AnnotationID AnnotationManager::addAnnotation(const Annotation& annotation, const uint8_t maxZoom) {
AnnotationID id = nextID++;
updateAnnotation(id, annotation, maxZoom);
return id;
}
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::updateAnnotation(const AnnotationID& id, const Annotation& annotation, const uint8_t maxZoom) {
removeAnnotation(id);
Annotation::visit(annotation, [&] (const auto& annotation_) {
this->add(id, annotation_, maxZoom);
});
}
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::removeAnnotation(const AnnotationID& id) {
if (symbolAnnotations.find(id) != symbolAnnotations.end()) {
symbolTree.remove(symbolAnnotations.at(id));
symbolAnnotations.erase(id);
} else if (shapeAnnotations.find(id) != shapeAnnotations.end()) {
obsoleteShapeAnnotationLayers.push_back(shapeAnnotations.at(id)->layerID);
shapeAnnotations.erase(id);
}
}
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);
}
}
void AnnotationManager::add(const AnnotationID& id, const SymbolAnnotation& annotation, const uint8_t) {
auto impl = std::make_shared<SymbolAnnotationImpl>(id, annotation);
symbolTree.insert(impl);
symbolAnnotations.emplace(id, impl);
}
void AnnotationManager::add(const AnnotationID& id, const LineAnnotation& annotation, const uint8_t maxZoom) {
shapeAnnotations.emplace(id,
std::make_unique<LineAnnotationImpl>(id, annotation, maxZoom));
}
void AnnotationManager::add(const AnnotationID& id, const FillAnnotation& annotation, const uint8_t maxZoom) {
shapeAnnotations.emplace(id,
std::make_unique<FillAnnotationImpl>(id, annotation, maxZoom));
}
void AnnotationManager::add(const AnnotationID& id, const StyleSourcedAnnotation& annotation, const uint8_t maxZoom) {
shapeAnnotations.emplace(id,
std::make_unique<StyleSourcedAnnotationImpl>(id, annotation, maxZoom));
}
AnnotationIDs AnnotationManager::getPointAnnotationsInBounds(const LatLngBounds& bounds) const {
AnnotationIDs result;
pointTree.query(boost::geometry::index::intersects(bounds),
symbolTree.query(boost::geometry::index::intersects(bounds),
boost::make_function_output_iterator([&](const auto& val){
result.push_back(val->id);
}));
@@ -83,7 +78,7 @@ AnnotationIDs AnnotationManager::getPointAnnotationsInBounds(const LatLngBounds&
}
std::unique_ptr<AnnotationTile> AnnotationManager::getTile(const CanonicalTileID& tileID) {
if (pointAnnotations.empty() && shapeAnnotations.empty())
if (symbolAnnotations.empty() && shapeAnnotations.empty())
return nullptr;
auto tile = std::make_unique<AnnotationTile>();
@@ -94,7 +89,7 @@ std::unique_ptr<AnnotationTile> AnnotationManager::getTile(const CanonicalTileID
LatLngBounds tileBounds(tileID);
pointTree.query(boost::geometry::index::intersects(tileBounds),
symbolTree.query(boost::geometry::index::intersects(tileBounds),
boost::make_function_output_iterator([&](const auto& val){
val->updateLayer(tileID, pointLayer);
}));

View File

@@ -1,8 +1,7 @@
#pragma once
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/annotation/point_annotation_impl.hpp>
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/sprite/sprite_store.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/util/geo.hpp>
@@ -11,13 +10,14 @@
#include <string>
#include <vector>
#include <set>
#include <unordered_map>
namespace mbgl {
class PointAnnotation;
class ShapeAnnotation;
class AnnotationTile;
class AnnotationTileMonitor;
class SymbolAnnotationImpl;
class ShapeAnnotationImpl;
class Style;
class AnnotationManager : private util::noncopyable {
@@ -25,10 +25,9 @@ public:
AnnotationManager(float pixelRatio);
~AnnotationManager();
AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&, const uint8_t maxZoom);
AnnotationIDs addShapeAnnotations(const std::vector<ShapeAnnotation>&, const uint8_t maxZoom);
void updatePointAnnotation(const AnnotationID&, const PointAnnotation&, const uint8_t maxZoom);
void removeAnnotations(const AnnotationIDs&);
AnnotationID addAnnotation(const Annotation&, const uint8_t maxZoom);
void updateAnnotation(const AnnotationID&, const Annotation&, const uint8_t maxZoom);
void removeAnnotation(const AnnotationID&);
AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&) const;
@@ -46,12 +45,22 @@ public:
static const std::string PointLayerID;
private:
void add(const AnnotationID&, const SymbolAnnotation&, const uint8_t);
void add(const AnnotationID&, const LineAnnotation&, const uint8_t);
void add(const AnnotationID&, const FillAnnotation&, const uint8_t);
void add(const AnnotationID&, const StyleSourcedAnnotation&, const uint8_t);
std::unique_ptr<AnnotationTile> getTile(const CanonicalTileID&);
AnnotationID nextID = 0;
PointAnnotationImpl::Tree pointTree;
PointAnnotationImpl::Map pointAnnotations;
ShapeAnnotationImpl::Map shapeAnnotations;
using SymbolAnnotationTree = boost::geometry::index::rtree<std::shared_ptr<const SymbolAnnotationImpl>, boost::geometry::index::rstar<16, 4>>;
using SymbolAnnotationMap = std::unordered_map<AnnotationID, std::shared_ptr<SymbolAnnotationImpl>>;
using ShapeAnnotationMap = std::unordered_map<AnnotationID, std::unique_ptr<ShapeAnnotationImpl>>;
SymbolAnnotationTree symbolTree;
SymbolAnnotationMap symbolAnnotations;
ShapeAnnotationMap shapeAnnotations;
std::vector<std::string> obsoleteShapeAnnotationLayers;
std::set<AnnotationTileMonitor*> monitors;

View File

@@ -0,0 +1,36 @@
#include <mbgl/annotation/fill_annotation_impl.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/layer/fill_layer.hpp>
namespace mbgl {
namespace geojsonvt = mapbox::geojsonvt;
FillAnnotationImpl::FillAnnotationImpl(const AnnotationID id_, const FillAnnotation& annotation_, const uint8_t maxZoom_)
: ShapeAnnotationImpl(id_, maxZoom_),
annotation(annotation_) {
}
void FillAnnotationImpl::updateStyle(Style& style) const {
if (style.getLayer(layerID))
return;
std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>();
layer->paint.fillOpacity = annotation.opacity;
layer->paint.fillColor = annotation.color;
layer->paint.fillOutlineColor = annotation.outlineColor;
layer->id = layerID;
layer->source = AnnotationManager::SourceID;
layer->sourceLayer = layer->id;
style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
}
const Geometry<double>& FillAnnotationImpl::geometry() const {
return annotation.geometry;
}
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#pragma once
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/annotation/annotation.hpp>
namespace mbgl {
class FillAnnotationImpl : public ShapeAnnotationImpl {
public:
FillAnnotationImpl(const AnnotationID, const FillAnnotation&, const uint8_t maxZoom);
void updateStyle(Style&) const final;
const Geometry<double>& geometry() const final;
private:
const FillAnnotation annotation;
};
} // namespace mbgl

View File

@@ -0,0 +1,37 @@
#include <mbgl/annotation/line_annotation_impl.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/layer/line_layer.hpp>
namespace mbgl {
namespace geojsonvt = mapbox::geojsonvt;
LineAnnotationImpl::LineAnnotationImpl(const AnnotationID id_, const LineAnnotation& annotation_, const uint8_t maxZoom_)
: ShapeAnnotationImpl(id_, maxZoom_),
annotation(annotation_) {
}
void LineAnnotationImpl::updateStyle(Style& style) const {
if (style.getLayer(layerID))
return;
std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>();
layer->layout.lineJoin = LineJoinType::Round;
layer->paint.lineOpacity = annotation.opacity;
layer->paint.lineWidth = annotation.width;
layer->paint.lineColor = annotation.color;
layer->id = layerID;
layer->source = AnnotationManager::SourceID;
layer->sourceLayer = layer->id;
style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
}
const Geometry<double>& LineAnnotationImpl::geometry() const {
return annotation.geometry;
}
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#pragma once
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/annotation/annotation.hpp>
namespace mbgl {
class LineAnnotationImpl : public ShapeAnnotationImpl {
public:
LineAnnotationImpl(const AnnotationID, const LineAnnotation&, const uint8_t maxZoom);
void updateStyle(Style&) const final;
const Geometry<double>& geometry() const final;
private:
const LineAnnotation annotation;
};
} // namespace mbgl

View File

@@ -1,83 +1,21 @@
#include <mapbox/geojsonvt/convert.hpp>
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/layer/line_layer.hpp>
#include <mbgl/layer/fill_layer.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/math/wrap.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/constants.hpp>
namespace mbgl {
namespace geojsonvt = mapbox::geojsonvt;
ShapeAnnotationImpl::ShapeAnnotationImpl(const AnnotationID id_,
const ShapeAnnotation& shape_,
const uint8_t maxZoom_)
: id(id_),
layerID("com.mapbox.annotations.shape." + util::toString(id)),
shape(shape_),
maxZoom(maxZoom_) {
}
void ShapeAnnotationImpl::updateStyle(Style& style) {
if (style.getLayer(layerID))
return;
if (shape.properties.is<LineAnnotationProperties>()) {
type = geojsonvt::ProjectedFeatureType::LineString;
std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>();
layer->layout.lineJoin = LineJoinType::Round;
const LineAnnotationProperties& properties = shape.properties.get<LineAnnotationProperties>();
layer->paint.lineOpacity = properties.opacity;
layer->paint.lineWidth = properties.width;
layer->paint.lineColor = properties.color;
layer->id = layerID;
layer->source = AnnotationManager::SourceID;
layer->sourceLayer = layer->id;
style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
} else if (shape.properties.is<FillAnnotationProperties>()) {
type = geojsonvt::ProjectedFeatureType::Polygon;
std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>();
const FillAnnotationProperties& properties = shape.properties.get<FillAnnotationProperties>();
layer->paint.fillOpacity = properties.opacity;
layer->paint.fillColor = properties.color;
layer->paint.fillOutlineColor = properties.outlineColor;
layer->id = layerID;
layer->source = AnnotationManager::SourceID;
layer->sourceLayer = layer->id;
style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
} else {
const StyleLayer* sourceLayer = style.getLayer(shape.properties.get<std::string>());
if (!sourceLayer) return;
std::unique_ptr<StyleLayer> layer = sourceLayer->clone();
type = layer->is<LineLayer>()
? geojsonvt::ProjectedFeatureType::LineString
: geojsonvt::ProjectedFeatureType::Polygon;
layer->id = layerID;
layer->ref = "";
layer->source = AnnotationManager::SourceID;
layer->sourceLayer = layer->id;
layer->visibility = VisibilityType::Visible;
style.addLayer(std::move(layer), sourceLayer->id);
}
ShapeAnnotationImpl::ShapeAnnotationImpl(const AnnotationID id_, const uint8_t maxZoom_)
: id(id_),
maxZoom(maxZoom_),
layerID("com.mapbox.annotations.shape." + util::toString(id)) {
}
struct ToGeoJSONVT {
@@ -166,7 +104,7 @@ void ShapeAnnotationImpl::updateTile(const CanonicalTileID& tileID, AnnotationTi
const double tolerance = baseTolerance / (maxAmountOfTiles * util::EXTENT);
std::vector<geojsonvt::ProjectedFeature> features = {
Geometry<double>::visit(shape.geometry, ToGeoJSONVT(tolerance))
Geometry<double>::visit(geometry(), ToGeoJSONVT(tolerance))
};
mapbox::geojsonvt::Options options;

View File

@@ -3,12 +3,9 @@
#include <mapbox/geojsonvt.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/util/geo.hpp>
#include <memory>
#include <string>
#include <map>
#include <memory>
namespace mbgl {
@@ -18,20 +15,17 @@ class CanonicalTileID;
class ShapeAnnotationImpl {
public:
using Map = std::map<AnnotationID, std::unique_ptr<ShapeAnnotationImpl>>;
ShapeAnnotationImpl(const AnnotationID, const uint8_t maxZoom);
virtual ~ShapeAnnotationImpl() = default;
ShapeAnnotationImpl(const AnnotationID, const ShapeAnnotation&, const uint8_t maxZoom);
virtual void updateStyle(Style&) const = 0;
virtual const Geometry<double>& geometry() const = 0;
void updateStyle(Style&);
void updateTile(const CanonicalTileID&, AnnotationTile&);
const AnnotationID id;
const std::string layerID;
const ShapeAnnotation shape;
private:
const uint8_t maxZoom;
mapbox::geojsonvt::ProjectedFeatureType type;
const std::string layerID;
std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> shapeTiler;
};

View File

@@ -0,0 +1,38 @@
#include <mbgl/annotation/style_sourced_annotation_impl.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
namespace mbgl {
namespace geojsonvt = mapbox::geojsonvt;
StyleSourcedAnnotationImpl::StyleSourcedAnnotationImpl(const AnnotationID id_, const StyleSourcedAnnotation& annotation_, const uint8_t maxZoom_)
: ShapeAnnotationImpl(id_, maxZoom_),
annotation(annotation_) {
}
void StyleSourcedAnnotationImpl::updateStyle(Style& style) const {
if (style.getLayer(layerID))
return;
const StyleLayer* sourceLayer = style.getLayer(annotation.layerID);
if (!sourceLayer)
return;
std::unique_ptr<StyleLayer> layer = sourceLayer->clone();
layer->id = layerID;
layer->ref = "";
layer->source = AnnotationManager::SourceID;
layer->sourceLayer = layer->id;
layer->visibility = VisibilityType::Visible;
style.addLayer(std::move(layer), sourceLayer->id);
}
const Geometry<double>& StyleSourcedAnnotationImpl::geometry() const {
return annotation.geometry;
}
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#pragma once
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/annotation/annotation.hpp>
namespace mbgl {
class StyleSourcedAnnotationImpl : public ShapeAnnotationImpl {
public:
StyleSourcedAnnotationImpl(const AnnotationID, const StyleSourcedAnnotation&, const uint8_t maxZoom);
void updateStyle(Style&) const final;
const Geometry<double>& geometry() const final;
private:
const StyleSourcedAnnotation annotation;
};
} // namespace mbgl

View File

@@ -1,24 +1,29 @@
#include <mbgl/annotation/point_annotation_impl.hpp>
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/math/clamp.hpp>
namespace mbgl {
PointAnnotationImpl::PointAnnotationImpl(const AnnotationID id_, const PointAnnotation& point_)
SymbolAnnotationImpl::SymbolAnnotationImpl(const AnnotationID id_, const SymbolAnnotation& annotation_)
: id(id_),
point(point_) {
annotation(annotation_) {
if (!annotation.geometry.is<Point<double>>()) {
throw std::runtime_error("unsupported symbol annotation geometry type");
}
}
void PointAnnotationImpl::updateLayer(const CanonicalTileID& tileID, AnnotationTileLayer& layer) const {
void SymbolAnnotationImpl::updateLayer(const CanonicalTileID& tileID, AnnotationTileLayer& layer) const {
std::unordered_map<std::string, std::string> featureProperties;
featureProperties.emplace("sprite", point.icon.empty() ? std::string("default_marker") : point.icon);
featureProperties.emplace("sprite", annotation.icon.empty() ? std::string("default_marker") : annotation.icon);
const Point<double>& p = annotation.geometry.get<Point<double>>();
// Clamp to the latitude limits of Web Mercator.
const double constrainedLatitude = util::clamp(point.position.latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
const double constrainedLatitude = util::clamp(p.y, -util::LATITUDE_MAX, util::LATITUDE_MAX);
// Project a coordinate into unit space in a square map.
const double sine = std::sin(constrainedLatitude * util::DEG2RAD);
const double x = point.position.longitude / util::DEGREES_MAX + 0.5;
const double x = p.x / util::DEGREES_MAX + 0.5;
const double y = 0.5 - 0.25 * std::log((1.0 + sine) / (1.0 - sine)) / M_PI;
Point<double> projected(x, y);

View File

@@ -1,7 +1,6 @@
#pragma once
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/util/geo.hpp>
#include <string>
@@ -36,31 +35,29 @@ namespace mbgl {
class AnnotationTileLayer;
class CanonicalTileID;
class PointAnnotationImpl {
class SymbolAnnotationImpl {
public:
using Map = std::map<AnnotationID, std::shared_ptr<PointAnnotationImpl>>;
using Tree = boost::geometry::index::rtree<std::shared_ptr<const PointAnnotationImpl>, boost::geometry::index::rstar<16, 4>>;
PointAnnotationImpl(const AnnotationID, const PointAnnotation&);
SymbolAnnotationImpl(const AnnotationID, const SymbolAnnotation&);
void updateLayer(const CanonicalTileID&, AnnotationTileLayer&) const;
const AnnotationID id;
const PointAnnotation point;
const SymbolAnnotation annotation;
};
} // namespace mbgl
// Tell Boost Geometry how to access a std::shared_ptr<mbgl::PointAnnotation> object.
// Tell Boost Geometry how to access a std::shared_ptr<mbgl::SymbolAnnotation> object.
namespace boost {
namespace geometry {
namespace index {
template <>
struct indexable<std::shared_ptr<const mbgl::PointAnnotationImpl>> {
using result_type = const mbgl::LatLng&;
inline const mbgl::LatLng& operator()(const std::shared_ptr<const mbgl::PointAnnotationImpl>& v) const {
return v->point.position;
struct indexable<std::shared_ptr<const mbgl::SymbolAnnotationImpl>> {
using result_type = mbgl::LatLng;
inline mbgl::LatLng operator()(const std::shared_ptr<const mbgl::SymbolAnnotationImpl>& v) const {
const mbgl::Point<double>& p = v->annotation.geometry.get<mbgl::Point<double>>();
return mbgl::LatLng(p.y, p.x);
}
};

View File

@@ -3,8 +3,6 @@
#include <mbgl/map/view.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_observer.hpp>
@@ -693,37 +691,19 @@ double Map::getTopOffsetPixelsForAnnotationIcon(const std::string& name) {
return impl->annotationManager->getTopOffsetPixelsForIcon(name);
}
AnnotationID Map::addPointAnnotation(const PointAnnotation& annotation) {
return addPointAnnotations({ annotation }).front();
}
AnnotationIDs Map::addPointAnnotations(const std::vector<PointAnnotation>& annotations) {
auto result = impl->annotationManager->addPointAnnotations(annotations, getMaxZoom());
AnnotationID Map::addAnnotation(const Annotation& annotation) {
auto result = impl->annotationManager->addAnnotation(annotation, getMaxZoom());
update(Update::Annotations);
return result;
}
AnnotationID Map::addShapeAnnotation(const ShapeAnnotation& annotation) {
return addShapeAnnotations({ annotation }).front();
}
AnnotationIDs Map::addShapeAnnotations(const std::vector<ShapeAnnotation>& annotations) {
auto result = impl->annotationManager->addShapeAnnotations(annotations, getMaxZoom());
update(Update::Annotations);
return result;
}
void Map::updatePointAnnotation(AnnotationID annotationId, const PointAnnotation& annotation) {
impl->annotationManager->updatePointAnnotation(annotationId, annotation, getMaxZoom());
void Map::updateAnnotation(AnnotationID id, const Annotation& annotation) {
impl->annotationManager->updateAnnotation(id, annotation, getMaxZoom());
update(Update::Annotations);
}
void Map::removeAnnotation(AnnotationID annotation) {
removeAnnotations({ annotation });
}
void Map::removeAnnotations(const AnnotationIDs& annotations) {
impl->annotationManager->removeAnnotations(annotations);
impl->annotationManager->removeAnnotation(annotation);
update(Update::Annotations);
}

View File

@@ -1,8 +1,7 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/platform/default/headless_display.hpp>
@@ -29,7 +28,7 @@ void checkRendering(Map& map, const char * name) {
} // end namespace
TEST(Annotations, PointAnnotation) {
TEST(Annotations, SymbolAnnotation) {
util::RunLoop loop;
auto display = std::make_shared<mbgl::HeadlessDisplay>();
@@ -39,7 +38,7 @@ TEST(Annotations, PointAnnotation) {
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
map.addPointAnnotation(PointAnnotation({ 0, 0 }, "default_marker"));
map.addAnnotation(SymbolAnnotation { Point<double>(0, 0), "default_marker" });
checkRendering(map, "point_annotation");
}
@@ -56,11 +55,11 @@ TEST(Annotations, LineAnnotation) {
LineString<double> line = {{ { 0, 0 }, { 45, 45 } }};
LineAnnotationProperties properties;
properties.color = {{ 255, 0, 0, 1 }};
properties.width = 5;
LineAnnotation annotation { line };
annotation.color = {{ 255, 0, 0, 1 }};
annotation.width = 5;
map.addShapeAnnotation(ShapeAnnotation(line, properties));
map.addAnnotation(annotation);
checkRendering(map, "line_annotation");
}
@@ -77,10 +76,10 @@ TEST(Annotations, FillAnnotation) {
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
FillAnnotationProperties properties;
properties.color = {{ 255, 0, 0, 1 }};
FillAnnotation annotation { polygon };
annotation.color = {{ 255, 0, 0, 1 }};
map.addShapeAnnotation(ShapeAnnotation(polygon, properties));
map.addAnnotation(annotation);
checkRendering(map, "fill_annotation");
}
@@ -97,7 +96,7 @@ TEST(Annotations, StyleSourcedShapeAnnotation) {
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
map.addShapeAnnotation(ShapeAnnotation(polygon, "annotation"));
map.addAnnotation(StyleSourcedAnnotation { polygon, "annotation" });
checkRendering(map, "style_sourced_shape_annotation");
}
@@ -112,11 +111,11 @@ TEST(Annotations, AddMultiple) {
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
map.addPointAnnotation(PointAnnotation({ 0, -10 }, "default_marker"));
map.addAnnotation(SymbolAnnotation { Point<double> { -10, 0 }, "default_marker" });
test::render(map);
map.addPointAnnotation(PointAnnotation({ 0, 10 }, "default_marker"));
map.addAnnotation(SymbolAnnotation { Point<double> { 10, 0 }, "default_marker" });
checkRendering(map, "add_multiple");
}
@@ -135,10 +134,10 @@ TEST(Annotations, NonImmediateAdd) {
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
FillAnnotationProperties properties;
properties.color = {{ 255, 0, 0, 1 }};
FillAnnotation annotation { polygon };
annotation.color = {{ 255, 0, 0, 1 }};
map.addShapeAnnotation(ShapeAnnotation(polygon, properties));
map.addAnnotation(annotation);
checkRendering(map, "non_immediate_add");
}
@@ -153,7 +152,7 @@ TEST(Annotations, UpdateIcon) {
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
map.addAnnotationIcon("flipped_marker", namedMarker("default_marker.png"));
map.addPointAnnotation(PointAnnotation({ 0, 0 }, "flipped_marker"));
map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "flipped_marker" });
test::render(map);
@@ -175,11 +174,11 @@ TEST(Annotations, UpdatePoint) {
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
map.addAnnotationIcon("flipped_marker", namedMarker("flipped_marker.png"));
AnnotationID point = map.addPointAnnotation(PointAnnotation({ 0, 0 }, "default_marker"));
AnnotationID point = map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
test::render(map);
map.updatePointAnnotation(point, PointAnnotation({ 0, -10 }, "flipped_marker"));
map.updateAnnotation(point, SymbolAnnotation { Point<double> { -10, 0 }, "flipped_marker" });
checkRendering(map, "update_point");
}
@@ -194,7 +193,7 @@ TEST(Annotations, RemovePoint) {
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
AnnotationID point = map.addPointAnnotation(PointAnnotation({ 0, 0 }, "default_marker"));
AnnotationID point = map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
test::render(map);
@@ -212,13 +211,13 @@ TEST(Annotations, RemoveShape) {
LineString<double> line = {{ { 0, 0 }, { 45, 45 } }};
LineAnnotationProperties properties;
properties.color = {{ 255, 0, 0, 1 }};
properties.width = 5;
LineAnnotation annotation { line };
annotation.color = {{ 255, 0, 0, 1 }};
annotation.width = 5;
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
AnnotationID shape = map.addShapeAnnotation(ShapeAnnotation(line, properties));
AnnotationID shape = map.addAnnotation(annotation);
test::render(map);
@@ -235,7 +234,7 @@ TEST(Annotations, ImmediateRemoveShape) {
StubFileSource fileSource;
Map map(view, fileSource, MapMode::Still);
map.removeAnnotation(map.addShapeAnnotation(ShapeAnnotation(LineString<double>(), {})));
map.removeAnnotation(map.addAnnotation(LineAnnotation { LineString<double>() }));
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
test::render(map);
@@ -251,7 +250,7 @@ TEST(Annotations, SwitchStyle) {
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
map.addPointAnnotation(PointAnnotation({ 0, 0 }, "default_marker"));
map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
test::render(map);
@@ -270,12 +269,11 @@ TEST(Annotations, QueryRenderedFeatures) {
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
const LatLng latLng(0, 0);
map.addPointAnnotation(PointAnnotation(latLng, "default_marker"));
map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
test::render(map);
auto point = map.pixelForLatLng(latLng);
auto point = map.pixelForLatLng({ 0, 0 });
auto features = map.queryRenderedFeatures(point);
EXPECT_EQ(features.size(), 1);
}

View File

@@ -16,6 +16,8 @@
#include <mbgl/layer/line_layer.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mapbox/geojsonvt.hpp>
using namespace mbgl;
class SourceTest {