Files
MapLibreParticleLab/src/mbgl/annotation/shape_annotation_impl.cpp
Vladimir Agafonkin b44331245a [core] update geojson-vt options
- fix the code to use the same simplification tolerance
- remove outdated indexMaxZoom/Points values and rely on default
- bump buffer 2x to fix bleeding linecaps on thick lines
2015-12-10 12:59:49 -08:00

163 lines
5.7 KiB
C++

#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>
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.join = JoinType::Round;
const LineAnnotationProperties& properties = shape.properties.get<LineAnnotationProperties>();
layer->paint.opacity = properties.opacity;
layer->paint.width = properties.width;
layer->paint.color = 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.opacity = properties.opacity;
layer->paint.color = properties.color;
layer->paint.outlineColor = 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);
}
}
void ShapeAnnotationImpl::updateTile(const TileID& tileID, AnnotationTile& tile) {
static const double baseTolerance = 10;
static const uint16_t extent = 4096;
if (!shapeTiler) {
const uint64_t maxAmountOfTiles = 1 << maxZoom;
const double tolerance = baseTolerance / (maxAmountOfTiles * extent);
geojsonvt::ProjectedRings rings;
std::vector<geojsonvt::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(geojsonvt::LonLat(shape.segments[0][i].longitude, constraintedLatitude));
}
if (type == geojsonvt::ProjectedFeatureType::Polygon &&
(points.front().lon != points.back().lon || points.front().lat != points.back().lat)) {
points.push_back(geojsonvt::LonLat(points.front().lon, points.front().lat));
}
auto ring = geojsonvt::Convert::projectRing(points, tolerance);
rings.push_back(ring);
std::vector<geojsonvt::ProjectedFeature> features;
features.push_back(geojsonvt::Convert::create(geojsonvt::Tags(), type, rings));
mapbox::geojsonvt::Options options;
options.maxZoom = maxZoom;
options.buffer = 128u;
options.tolerance = baseTolerance;
shapeTiler = std::make_unique<mapbox::geojsonvt::GeoJSONVT>(features, options);
}
const auto& shapeTile = shapeTiler->getTile(tileID.z, tileID.x, tileID.y);
if (!shapeTile)
return;
AnnotationTileLayer& layer = *tile.layers.emplace(layerID,
std::make_unique<AnnotationTileLayer>()).first->second;
for (auto& shapeFeature : shapeTile.features) {
FeatureType featureType = FeatureType::Unknown;
if (shapeFeature.type == geojsonvt::TileFeatureType::LineString) {
featureType = FeatureType::LineString;
} else if (shapeFeature.type == geojsonvt::TileFeatureType::Polygon) {
featureType = FeatureType::Polygon;
}
assert(featureType != FeatureType::Unknown);
GeometryCollection renderGeometry;
for (auto& shapeRing : shapeFeature.tileGeometry.get<geojsonvt::TileRings>()) {
std::vector<Coordinate> renderLine;
for (auto& shapePoint : shapeRing) {
renderLine.emplace_back(shapePoint.x, shapePoint.y);
}
renderGeometry.push_back(renderLine);
}
layer.features.emplace_back(
std::make_shared<AnnotationTileFeature>(featureType, renderGeometry));
}
}
LatLngBounds ShapeAnnotationImpl::bounds() const {
LatLngBounds result;
for (const auto& segment : shape.segments) {
for (const auto& point : segment) {
result.extend(point);
}
}
return result;
}
} // namespace mbgl