summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/annotation/shape_annotation.hpp11
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.cpp139
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.hpp8
-rw-r--r--src/mbgl/style/class_properties.hpp4
-rw-r--r--test/api/annotations.cpp15
-rw-r--r--test/fixtures/api/annotation.json19
6 files changed, 129 insertions, 67 deletions
diff --git a/include/mbgl/annotation/shape_annotation.hpp b/include/mbgl/annotation/shape_annotation.hpp
index 5e6a13149a..90f2a96dd0 100644
--- a/include/mbgl/annotation/shape_annotation.hpp
+++ b/include/mbgl/annotation/shape_annotation.hpp
@@ -15,14 +15,17 @@ using AnnotationSegments = std::vector<AnnotationSegment>;
class ShapeAnnotation {
public:
- using Properties = mapbox::util::variant<FillPaintProperties, LinePaintProperties>;
+ using Properties = mapbox::util::variant<
+ FillPaintProperties, // creates a fill annotation
+ LinePaintProperties, // creates a line annotation
+ std::string>; // creates an annotation whose type and properties are sourced from a style layer
- inline ShapeAnnotation(const AnnotationSegments& segments_, const Properties& styleProperties_)
- : segments(segments_), styleProperties(styleProperties_) {
+ ShapeAnnotation(const AnnotationSegments& segments_, const Properties& properties_)
+ : segments(segments_), properties(properties_) {
}
const AnnotationSegments segments;
- const Properties styleProperties;
+ const Properties properties;
};
}
diff --git a/src/mbgl/annotation/shape_annotation_impl.cpp b/src/mbgl/annotation/shape_annotation_impl.cpp
index 5b3c07fbc9..4ab9958fdf 100644
--- a/src/mbgl/annotation/shape_annotation_impl.cpp
+++ b/src/mbgl/annotation/shape_annotation_impl.cpp
@@ -15,92 +15,115 @@ using namespace mapbox::util::geojsonvt;
ShapeAnnotationImpl::ShapeAnnotationImpl(const AnnotationID id_,
const ShapeAnnotation& shape_,
- const uint8_t maxZoom)
+ const uint8_t maxZoom_)
: id(id_),
layerID("com.mapbox.annotations.shape." + util::toString(id)),
shape(shape_),
- shapeTiler(([&] {
- const double baseTolerance = 3;
- const uint16_t extent = 4096;
- const double tolerance = baseTolerance / ((1 << maxZoom) * extent);
-
- ProjectedGeometryContainer rings;
- std::vector<LonLat> points;
-
- for (size_t i = 0; i < shape.segments[0].size(); ++i) { // first segment for now (no holes)
- const double constraintedLatitude = ::fmin(::fmax(shape.segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX);
- points.push_back(LonLat(shape.segments[0][i].longitude, constraintedLatitude));
- }
-
- ProjectedFeatureType featureType;
-
- if (shape.styleProperties.is<FillPaintProperties>()) {
- featureType = ProjectedFeatureType::Polygon;
-
- if (points.front().lon != points.back().lon || points.front().lat != points.back().lat) {
- points.push_back(LonLat(points.front().lon, points.front().lat));
- }
- } else {
- featureType = ProjectedFeatureType::LineString;
- }
-
- ProjectedGeometryContainer ring = Convert::project(points, tolerance);
- rings.members.push_back(ring);
-
- std::vector<ProjectedFeature> features;
- features.push_back(Convert::create(Tags(), featureType, rings));
- return features;
- })(), maxZoom, 4, 100, 10) {}
+ maxZoom(maxZoom_) {
+}
void ShapeAnnotationImpl::updateStyle(Style& style) {
if (style.getLayer(layerID))
return;
- if (shape.styleProperties.is<LinePaintProperties>()) {
- const LinePaintProperties& properties = shape.styleProperties.get<LinePaintProperties>();
+ std::unique_ptr<StyleLayer> layer;
- std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>();
- layer->id = layerID;
- layer->type = StyleLayerType::Line;
+ if (shape.properties.is<LinePaintProperties>()) {
+ layer = createLineLayer();
+ const LinePaintProperties& properties = shape.properties.get<LinePaintProperties>();
ClassProperties paintProperties;
paintProperties.set(PropertyKey::LineOpacity, ConstantFunction<float>(properties.opacity));
paintProperties.set(PropertyKey::LineWidth, ConstantFunction<float>(properties.width));
paintProperties.set(PropertyKey::LineColor, ConstantFunction<Color>(properties.color));
layer->styles.emplace(ClassID::Default, std::move(paintProperties));
- layer->bucket = std::make_shared<StyleBucket>(layer->type);
- layer->bucket->name = layer->id;
- layer->bucket->source = AnnotationManager::SourceID;
- layer->bucket->source_layer = layer->id;
- layer->bucket->layout.set(PropertyKey::LineJoin, ConstantFunction<JoinType>(JoinType::Round));
-
- style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
-
- } else if (shape.styleProperties.is<FillPaintProperties>()) {
- const FillPaintProperties& properties = shape.styleProperties.get<FillPaintProperties>();
-
- std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>();
- layer->id = layerID;
- layer->type = StyleLayerType::Fill;
+ } else if (shape.properties.is<FillPaintProperties>()) {
+ layer = createFillLayer();
+ const FillPaintProperties& properties = shape.properties.get<FillPaintProperties>();
ClassProperties paintProperties;
paintProperties.set(PropertyKey::FillOpacity, ConstantFunction<float>(properties.opacity));
paintProperties.set(PropertyKey::FillColor, ConstantFunction<Color>(properties.fill_color));
paintProperties.set(PropertyKey::FillOutlineColor, ConstantFunction<Color>(properties.stroke_color));
layer->styles.emplace(ClassID::Default, std::move(paintProperties));
- layer->bucket = std::make_shared<StyleBucket>(layer->type);
- layer->bucket->name = layer->id;
- layer->bucket->source = AnnotationManager::SourceID;
- layer->bucket->source_layer = layer->id;
+ } else {
+ const StyleLayer* sourceLayer = style.getLayer(shape.properties.get<std::string>());
+ if (!sourceLayer) return;
+
+ switch (sourceLayer->type) {
+ case StyleLayerType::Line:
+ layer = createLineLayer();
+ break;
+
+ case StyleLayerType::Fill:
+ layer = createFillLayer();
+ break;
- style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
+ default:
+ return;
+ }
+
+ layer->styles = sourceLayer->styles;
+ layer->bucket->layout = sourceLayer->bucket->layout;
}
+
+ layer->bucket->name = layer->id;
+ layer->bucket->source = AnnotationManager::SourceID;
+ layer->bucket->source_layer = layer->id;
+
+ style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
+}
+
+std::unique_ptr<StyleLayer> ShapeAnnotationImpl::createLineLayer() {
+ type = ProjectedFeatureType::LineString;
+ std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>();
+ layer->id = layerID;
+ layer->type = StyleLayerType::Line;
+ layer->bucket = std::make_shared<StyleBucket>(layer->type);
+ layer->bucket->layout.set(PropertyKey::LineJoin, ConstantFunction<JoinType>(JoinType::Round));
+ return std::move(layer);
+}
+
+std::unique_ptr<StyleLayer> ShapeAnnotationImpl::createFillLayer() {
+ type = ProjectedFeatureType::Polygon;
+ std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>();
+ layer->id = layerID;
+ layer->type = StyleLayerType::Fill;
+ layer->bucket = std::make_shared<StyleBucket>(layer->type);
+ return std::move(layer);
}
void ShapeAnnotationImpl::updateTile(const TileID& tileID, AnnotationTile& tile) {
- const auto& shapeTile = shapeTiler.getTile(tileID.z, tileID.x, tileID.y);
+ if (!shapeTiler) {
+ const double baseTolerance = 3;
+ const uint16_t extent = 4096;
+ const double tolerance = baseTolerance / ((1 << maxZoom) * extent);
+
+ ProjectedGeometryContainer rings;
+ std::vector<LonLat> points;
+
+ for (size_t i = 0; i < shape.segments[0].size(); ++i) { // first segment for now (no holes)
+ const double constraintedLatitude = ::fmin(::fmax(shape.segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX);
+ points.push_back(LonLat(shape.segments[0][i].longitude, constraintedLatitude));
+ }
+
+ if (type == ProjectedFeatureType::Polygon &&
+ (points.front().lon != points.back().lon || points.front().lat != points.back().lat)) {
+ points.push_back(LonLat(points.front().lon, points.front().lat));
+ }
+
+ ProjectedGeometryContainer ring = Convert::project(points, tolerance);
+ rings.members.push_back(ring);
+
+ std::vector<ProjectedFeature> features;
+ features.push_back(Convert::create(Tags(), type, rings));
+
+ shapeTiler = std::make_unique<mapbox::util::geojsonvt::GeoJSONVT>(features, maxZoom, 4, 100, 10);
+ }
+
+ const auto& shapeTile = shapeTiler->getTile(tileID.z, tileID.x, tileID.y);
if (!shapeTile)
return;
diff --git a/src/mbgl/annotation/shape_annotation_impl.hpp b/src/mbgl/annotation/shape_annotation_impl.hpp
index 4cf6c23f61..1b1dacf370 100644
--- a/src/mbgl/annotation/shape_annotation_impl.hpp
+++ b/src/mbgl/annotation/shape_annotation_impl.hpp
@@ -13,6 +13,7 @@
namespace mbgl {
class Style;
+class StyleLayer;
class AnnotationTile;
class ShapeAnnotationImpl {
@@ -30,7 +31,12 @@ public:
const ShapeAnnotation shape;
private:
- mapbox::util::geojsonvt::GeoJSONVT shapeTiler;
+ std::unique_ptr<StyleLayer> createLineLayer();
+ std::unique_ptr<StyleLayer> createFillLayer();
+
+ const uint8_t maxZoom;
+ mapbox::util::geojsonvt::ProjectedFeatureType type;
+ std::unique_ptr<mapbox::util::geojsonvt::GeoJSONVT> shapeTiler;
};
}
diff --git a/src/mbgl/style/class_properties.hpp b/src/mbgl/style/class_properties.hpp
index 888a90c5d7..0f147fdda6 100644
--- a/src/mbgl/style/class_properties.hpp
+++ b/src/mbgl/style/class_properties.hpp
@@ -11,10 +11,6 @@ namespace mbgl {
class ClassProperties {
public:
- inline ClassProperties() {}
- inline ClassProperties(ClassProperties &&properties_)
- : properties(std::move(properties_.properties)) {}
-
inline void set(PropertyKey key, const PropertyValue &value) {
properties.emplace(key, value);
}
diff --git a/test/api/annotations.cpp b/test/api/annotations.cpp
index 415b2ddb69..a9667c4343 100644
--- a/test/api/annotations.cpp
+++ b/test/api/annotations.cpp
@@ -75,6 +75,21 @@ TEST(Annotations, FillAnnotation) {
util::write_file("test/output/fill_annotation.png", renderPNG(map));
}
+TEST(Annotations, StyleSourcedShapeAnnotation) {
+ auto display = std::make_shared<mbgl::HeadlessDisplay>();
+ HeadlessView view(display, 1);
+ DefaultFileSource fileSource(nullptr);
+
+ Map map(view, fileSource, MapMode::Still);
+ map.setStyleJSON(util::read_file("test/fixtures/api/annotation.json"), "");
+
+ AnnotationSegments segments = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
+
+ map.addShapeAnnotation(ShapeAnnotation(segments, "annotation"));
+
+ util::write_file("test/output/style_sourced_shape_annotation.png", renderPNG(map));
+}
+
TEST(Annotations, AddMultiple) {
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
diff --git a/test/fixtures/api/annotation.json b/test/fixtures/api/annotation.json
new file mode 100644
index 0000000000..75fcfca41f
--- /dev/null
+++ b/test/fixtures/api/annotation.json
@@ -0,0 +1,19 @@
+{
+ "version": 8,
+ "sources": {
+ "fake": {
+ "type": "vector",
+ "url": "asset://TEST_DATA/fixtures/tiles/streets.json"
+ }
+ },
+ "layers": [{
+ "id": "annotation",
+ "type": "fill",
+ "source": "fake",
+ "source-layer": "fake",
+ "paint": {
+ "fill-color": "rgba(255,0,0,1)"
+ }
+ }],
+ "sprite": "asset://TEST_DATA/fixtures/resources/sprite"
+}