diff options
Diffstat (limited to 'src')
26 files changed, 184 insertions, 169 deletions
diff --git a/src/csscolorparser/csscolorparser.cpp b/src/csscolorparser/csscolorparser.cpp index 106dae6cef..0de921b265 100644 --- a/src/csscolorparser/csscolorparser.cpp +++ b/src/csscolorparser/csscolorparser.cpp @@ -176,7 +176,7 @@ std::vector<std::string> split(const std::string& s, char delim) { return elems; } -optional<Color> parse(const std::string& css_str) { +mbgl::optional<Color> parse(const std::string& css_str) { std::string str = css_str; // Remove all whitespace, not compliant, but should just be more accepting. diff --git a/src/csscolorparser/csscolorparser.hpp b/src/csscolorparser/csscolorparser.hpp index b6bc5570f9..88b916620e 100644 --- a/src/csscolorparser/csscolorparser.hpp +++ b/src/csscolorparser/csscolorparser.hpp @@ -25,15 +25,13 @@ #ifndef CSS_COLOR_PARSER_CPP #define CSS_COLOR_PARSER_CPP +#include <mbgl/util/optional.hpp> + #include <string> #include <cmath> -#include <optional.hpp> namespace CSSColorParser { -template <class T> -using optional = std::experimental::optional<T>; - struct Color { inline Color() { } @@ -52,7 +50,7 @@ inline bool operator!=(const Color& lhs, const Color& rhs) { return !(lhs == rhs); } -optional<Color> parse(const std::string& css_str); +mbgl::optional<Color> parse(const std::string& css_str); } // namespace CSSColorParser diff --git a/src/mbgl/annotation/annotation_tile.cpp b/src/mbgl/annotation/annotation_tile.cpp index 6c3c9eb617..a410adc95e 100644 --- a/src/mbgl/annotation/annotation_tile.cpp +++ b/src/mbgl/annotation/annotation_tile.cpp @@ -58,7 +58,7 @@ FeatureIdentifier AnnotationTileFeature::getID() const { return data->id; } -GeometryCollection AnnotationTileFeature::getGeometries() const { +const GeometryCollection& AnnotationTileFeature::getGeometries() const { return data->geometries; } diff --git a/src/mbgl/annotation/annotation_tile.hpp b/src/mbgl/annotation/annotation_tile.hpp index 1e23fdf98a..741b598a8c 100644 --- a/src/mbgl/annotation/annotation_tile.hpp +++ b/src/mbgl/annotation/annotation_tile.hpp @@ -28,7 +28,7 @@ public: FeatureType getType() const override; optional<Value> getValue(const std::string&) const override; FeatureIdentifier getID() const override; - GeometryCollection getGeometries() const override; + const GeometryCollection& getGeometries() const override; private: std::shared_ptr<const AnnotationTileFeatureData> data; diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 3675e8bc6e..b76e02be3f 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -159,7 +159,7 @@ void FeatureIndex::addFeature( continue; } - result[layerID].push_back(convertFeature(*geometryTileFeature, tileID)); + result[layerID].emplace_back(convertFeature(*geometryTileFeature, tileID)); } } diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp index f41f842294..59fe67586b 100644 --- a/src/mbgl/gfx/vertex_vector.hpp +++ b/src/mbgl/gfx/vertex_vector.hpp @@ -11,11 +11,13 @@ template <class V> class VertexVector { public: using Vertex = V; + template<typename Arg> + void emplace_back(Arg&& vertex) { + v.emplace_back(std::forward<Arg>(vertex)); + } - template <class... Args> - void emplace_back(Args&&... args) { - static_assert(sizeof...(args) == 1, "wrong buffer element count"); - util::ignore({ (v.emplace_back(std::forward<Args>(args)), 0)... }); + void extend(std::size_t n, const Vertex& val) { + v.resize(v.size() + n, val); } std::size_t elements() const { diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index 95f8b181fc..858d515347 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -106,7 +106,7 @@ public: const auto i = patternFeature.i; std::unique_ptr<GeometryTileFeature> feature = std::move(patternFeature.feature); const PatternLayerMap& patterns = patternFeature.patterns; - GeometryCollection geometries = feature->getGeometries(); + const GeometryCollection& geometries = feature->getGeometries(); bucket->addFeature(*feature, geometries, patternPositions, patterns); featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID); diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp index 72f613d4b6..ed9c0783d0 100644 --- a/src/mbgl/layout/symbol_feature.hpp +++ b/src/mbgl/layout/symbol_feature.hpp @@ -13,14 +13,14 @@ class SymbolFeature : public GeometryTileFeature { public: SymbolFeature(std::unique_ptr<GeometryTileFeature> feature_) : feature(std::move(feature_)), - geometry(feature->getGeometries()) // we need a mutable copy of the geometry for mergeLines() + geometry(feature->getGeometries().clone()) // we need a mutable copy of the geometry for mergeLines() {} FeatureType getType() const override { return feature->getType(); } optional<Value> getValue(const std::string& key) const override { return feature->getValue(key); }; - std::unordered_map<std::string,Value> getProperties() const override { return feature->getProperties(); }; + const PropertyMap& getProperties() const override { return feature->getProperties(); }; FeatureIdentifier getID() const override { return feature->getID(); }; - GeometryCollection getGeometries() const override { return geometry; }; + const GeometryCollection& getGeometries() const override { return geometry; }; friend bool operator < (const SymbolFeature& lhs, const SymbolFeature& rhs) { return lhs.sortKey < rhs.sortKey; diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index cf59319307..4f1620364f 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -167,7 +167,7 @@ bool RenderCircleLayer::queryIntersectsFeature( projectQueryGeometry(translatedQueryGeometry, posMatrix, transformState.getSize()); auto transformedSize = alignWithMap ? size * pixelsToTileUnits : size; - auto geometry = feature.getGeometries(); + const auto& geometry = feature.getGeometries(); for (auto& ring : geometry) { for (auto& point : ring) { const GeometryCoordinate& transformedPoint = alignWithMap ? point : projectPoint(point, posMatrix, transformState.getSize()); diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 5c56826bd7..fcd52b21df 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -214,16 +214,22 @@ void RenderLineLayer::render(PaintParameters& parameters) { } } -optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const double offset) { - if (offset == 0) return {}; +namespace { + +GeometryCollection offsetLine(const GeometryCollection& rings, double offset) { + assert(offset != 0.0f); + assert(!rings.empty()); GeometryCollection newRings; - Point<double> zero(0, 0); + newRings.reserve(rings.size()); + + const Point<double> zero(0, 0); for (const auto& ring : rings) { newRings.emplace_back(); auto& newRing = newRings.back(); + newRing.reserve(ring.size()); - for (auto i = ring.begin(); i != ring.end(); i++) { + for (auto i = ring.begin(); i != ring.end(); ++i) { auto& p = *i; Point<double> aToB = i == ring.begin() ? @@ -237,13 +243,15 @@ optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const d const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y; extrude *= (1.0 / cosHalfAngle); - newRing.push_back(convertPoint<int16_t>(extrude * offset) + p); + newRing.emplace_back(convertPoint<int16_t>(extrude * offset) + p); } } return newRings; } +} // namespace + bool RenderLineLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, @@ -263,16 +271,21 @@ bool RenderLineLayer::queryIntersectsFeature( // Evaluate function auto offset = evaluated.get<style::LineOffset>() .evaluate(feature, zoom, style::LineOffset::defaultValue()) * pixelsToTileUnits; + // Test intersection + const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits; // Apply offset to geometry - auto offsetGeometry = offsetLine(feature.getGeometries(), offset); + if (offset != 0.0f && !feature.getGeometries().empty()) { + return util::polygonIntersectsBufferedMultiLine( + translatedQueryGeometry.value_or(queryGeometry), + offsetLine(feature.getGeometries(), offset), + halfWidth); + } - // Test intersection - const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits; return util::polygonIntersectsBufferedMultiLine( - translatedQueryGeometry.value_or(queryGeometry), - offsetGeometry.value_or(feature.getGeometries()), - halfWidth); + translatedQueryGeometry.value_or(queryGeometry), + feature.getGeometries(), + halfWidth); } void RenderLineLayer::updateColorRamp() { diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index ecaee2985c..82d135b9ef 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -77,12 +77,14 @@ static std::array<float, 3> spinWeights(float spin) { void RenderRasterLayer::prepare(const LayerPrepareParameters& params) { renderTiles = params.source->getRenderTiles(); imageData = params.source->getImageRenderData(); - assert(renderTiles || imageData); + // It is possible image data is not available until the source loads it. + assert(renderTiles || imageData || !params.source->isEnabled()); } void RenderRasterLayer::render(PaintParameters& parameters) { - if (parameters.pass != RenderPass::Translucent) + if (parameters.pass != RenderPass::Translucent || (!renderTiles && !imageData)) { return; + } const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated; RasterProgram::Binders paintAttributeData{ evaluated, 0 }; diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index f15dc7e6f4..c1ca1fd017 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -47,6 +47,7 @@ bool RenderLayer::supportsZoom(float zoom) const { void RenderLayer::prepare(const LayerPrepareParameters& params) { assert(params.source); + assert(params.source->isEnabled()); renderTiles = params.source->getRenderTiles(); addRenderPassesFromTiles(); } diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 4ce36434d2..5b6b27c185 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -274,9 +274,6 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar // Reserve size for filteredLayersForSource if there are sources. if (!sourceImpls->empty()) { filteredLayersForSource.reserve(layerImpls->size()); - if (filteredLayersForSource.capacity() > layerImpls->size()) { - filteredLayersForSource.shrink_to_fit(); - } } // Update all sources and initialize renderItems. @@ -487,7 +484,12 @@ void RenderOrchestrator::queryRenderedSymbols(std::unordered_map<std::string, st std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options, const std::unordered_map<std::string, const RenderLayer*>& layers) const { std::unordered_set<std::string> sourceIDs; + std::unordered_map<std::string, const RenderLayer*> filteredLayers; for (const auto& pair : layers) { + if (!pair.second->needsRendering() || !pair.second->supportsZoom(zoomHistory.lastZoom)) { + continue; + } + filteredLayers.emplace(pair); sourceIDs.emplace(pair.second->baseImpl->source); } @@ -497,12 +499,12 @@ std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(const ScreenLineS std::unordered_map<std::string, std::vector<Feature>> resultsByLayer; for (const auto& sourceID : sourceIDs) { if (RenderSource* renderSource = getRenderSource(sourceID)) { - auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); + auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, filteredLayers, options, projMatrix); std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } } - queryRenderedSymbols(resultsByLayer, geometry, layers, options); + queryRenderedSymbols(resultsByLayer, geometry, filteredLayers, options); std::vector<Feature> result; @@ -511,11 +513,7 @@ std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(const ScreenLineS } // Combine all results based on the style layer renderItems. - for (const auto& pair : layers) { - if (!pair.second->needsRendering() || !pair.second->supportsZoom(zoomHistory.lastZoom)) { - continue; - } - + for (const auto& pair : filteredLayers) { auto it = resultsByLayer.find(pair.second->baseImpl->id); if (it != resultsByLayer.end()) { std::move(it->second.begin(), it->second.end(), std::back_inserter(result)); @@ -560,6 +558,7 @@ FeatureExtensionValue RenderOrchestrator::queryFeatureExtensions(const std::stri } void RenderOrchestrator::reduceMemoryUse() { + filteredLayersForSource.shrink_to_fit(); for (const auto& entry : renderSources) { entry.second->reduceMemoryUse(); } diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index f47198e275..54e0b1eb26 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -293,6 +293,7 @@ std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRendered } LineString<double> queryGeometry; + queryGeometry.reserve(geometry.size()); for (const auto& p : geometry) { queryGeometry.push_back(TileCoordinate::fromScreenCoordinate( diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp index 825307432b..6958b1d625 100644 --- a/src/mbgl/style/expression/compound_expression.cpp +++ b/src/mbgl/style/expression/compound_expression.cpp @@ -435,7 +435,8 @@ const auto& propertiesCompoundExpression() { }; } std::unordered_map<std::string, Value> result; - const PropertyMap properties = params.feature->getProperties(); + const PropertyMap& properties = params.feature->getProperties(); + result.reserve(properties.size()); for (const auto& entry : properties) { result[entry.first] = toExpressionValue(entry.second); } diff --git a/src/mbgl/style/expression/expression.cpp b/src/mbgl/style/expression/expression.cpp index b3641b9448..eedc706633 100644 --- a/src/mbgl/style/expression/expression.cpp +++ b/src/mbgl/style/expression/expression.cpp @@ -15,9 +15,8 @@ public: FeatureType getType() const override { return apply_visitor(ToFeatureType(), feature.geometry); } - PropertyMap getProperties() const override { return feature.properties; } + const PropertyMap& getProperties() const override { return feature.properties; } FeatureIdentifier getID() const override { return feature.id; } - GeometryCollection getGeometries() const override { return {}; } optional<mbgl::Value> getValue(const std::string& key) const override { auto it = feature.properties.find(key); if (it != feature.properties.end()) { diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index b7d2189afd..79bb984aa2 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -545,46 +545,38 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState seenCrossTileIDs.insert(symbolInstance.crossTileID); if (symbolInstance.hasText) { - auto opacityVertex = SymbolSDFTextProgram::opacityVertex(opacityState.text.placed, opacityState.text.opacity); + size_t textOpacityVerticesSize = 0u; + const auto& opacityVertex = SymbolSDFTextProgram::opacityVertex(opacityState.text.placed, opacityState.text.opacity); if (symbolInstance.placedRightTextIndex) { - for (size_t i = 0; i < symbolInstance.rightJustifiedGlyphQuadsSize * 4; i++) { - bucket.text.opacityVertices.emplace_back(opacityVertex); - } + textOpacityVerticesSize += symbolInstance.rightJustifiedGlyphQuadsSize * 4; PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedRightTextIndex]; placed.hidden = opacityState.isHidden(); } if (symbolInstance.placedCenterTextIndex && !symbolInstance.singleLine) { - for (size_t i = 0; i < symbolInstance.centerJustifiedGlyphQuadsSize * 4; i++) { - bucket.text.opacityVertices.emplace_back(opacityVertex); - } + textOpacityVerticesSize += symbolInstance.centerJustifiedGlyphQuadsSize * 4; PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedCenterTextIndex]; placed.hidden = opacityState.isHidden(); } if (symbolInstance.placedLeftTextIndex && !symbolInstance.singleLine) { - for (size_t i = 0; i < symbolInstance.leftJustifiedGlyphQuadsSize * 4; i++) { - bucket.text.opacityVertices.emplace_back(opacityVertex); - } + textOpacityVerticesSize += symbolInstance.leftJustifiedGlyphQuadsSize * 4; PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedLeftTextIndex]; placed.hidden = opacityState.isHidden(); } if (symbolInstance.placedVerticalTextIndex) { - for (size_t i = 0; i < symbolInstance.verticalGlyphQuadsSize * 4; i++) { - bucket.text.opacityVertices.emplace_back(opacityVertex); - } + textOpacityVerticesSize += symbolInstance.verticalGlyphQuadsSize * 4; bucket.text.placedSymbols[*symbolInstance.placedVerticalTextIndex].hidden = opacityState.isHidden(); } + bucket.text.opacityVertices.extend(textOpacityVerticesSize, opacityVertex); + auto prevOffset = variableOffsets.find(symbolInstance.crossTileID); if (prevOffset != variableOffsets.end()) { markUsedJustification(bucket, prevOffset->second.anchor, symbolInstance); } } if (symbolInstance.hasIcon) { - auto opacityVertex = SymbolIconProgram::opacityVertex(opacityState.icon.placed, opacityState.icon.opacity); - bucket.icon.opacityVertices.emplace_back(opacityVertex); - bucket.icon.opacityVertices.emplace_back(opacityVertex); - bucket.icon.opacityVertices.emplace_back(opacityVertex); - bucket.icon.opacityVertices.emplace_back(opacityVertex); + const auto& opacityVertex = SymbolIconProgram::opacityVertex(opacityState.icon.placed, opacityState.icon.opacity); + bucket.icon.opacityVertices.extend(4, opacityVertex); if (symbolInstance.placedIconIndex) { bucket.icon.placedSymbols[*symbolInstance.placedIconIndex].hidden = opacityState.isHidden(); } @@ -594,10 +586,8 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState if (feature.alongLine) { return; } - auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false, {}); - for (size_t i = 0; i < feature.boxes.size() * 4; i++) { - bucket.collisionBox->dynamicVertices.emplace_back(dynamicVertex); - } + const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false, {}); + bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex); }; auto updateCollisionTextBox = [this, &bucket, &symbolInstance, &state, variablePlacement, rotateWithMap, pitchWithMap](const auto& feature, const bool placed) { @@ -629,10 +619,8 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState used = false; } } - auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !used, shift); - for (size_t i = 0; i < feature.boxes.size() * 4; i++) { - bucket.collisionBox->dynamicVertices.emplace_back(dynamicVertex); - } + const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !used, shift); + bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex); }; auto updateCollisionCircles = [&](const auto& feature, const bool placed) { @@ -640,11 +628,8 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState return; } for (const CollisionBox& box : feature.boxes) { - auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !box.used, {}); - bucket.collisionCircle->dynamicVertices.emplace_back(dynamicVertex); - bucket.collisionCircle->dynamicVertices.emplace_back(dynamicVertex); - bucket.collisionCircle->dynamicVertices.emplace_back(dynamicVertex); - bucket.collisionCircle->dynamicVertices.emplace_back(dynamicVertex); + const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !box.used, {}); + bucket.collisionCircle->dynamicVertices.extend(4, dynamicVertex); } }; @@ -665,18 +650,29 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState } } +namespace { +optional<size_t> justificationToIndex(style::TextJustifyType justify, const SymbolInstance& symbolInstance) { + switch(justify) { + case style::TextJustifyType::Right: return symbolInstance.placedRightTextIndex; + case style::TextJustifyType::Center: return symbolInstance.placedCenterTextIndex; + case style::TextJustifyType::Left: return symbolInstance.placedLeftTextIndex; + case style::TextJustifyType::Auto: break; + } + assert(false); + return nullopt; +} + +const style::TextJustifyType justifyTypes[] = {style::TextJustifyType::Right, style::TextJustifyType::Center, style::TextJustifyType::Left}; + +} // namespace + void Placement::markUsedJustification(SymbolBucket& bucket, style::TextVariableAnchorType placedAnchor, SymbolInstance& symbolInstance) { - std::map<style::TextJustifyType, optional<size_t>> justificationToIndex { - {style::TextJustifyType::Right, symbolInstance.placedRightTextIndex}, - {style::TextJustifyType::Center, symbolInstance.placedCenterTextIndex}, - {style::TextJustifyType::Left, symbolInstance.placedLeftTextIndex}, - }; - style::TextJustifyType justify = getAnchorJustification(placedAnchor); - assert(justify == style::TextJustifyType::Right || justify == style::TextJustifyType::Center || justify == style::TextJustifyType::Left); - const optional<size_t> autoIndex = justificationToIndex[justify]; - - for (auto& pair : justificationToIndex) { - const optional<size_t> index = pair.second; + style::TextJustifyType anchorJustify = getAnchorJustification(placedAnchor); + assert(anchorJustify != style::TextJustifyType::Auto); + const optional<size_t>& autoIndex = justificationToIndex(anchorJustify, symbolInstance); + + for (auto& justify : justifyTypes) { + const optional<size_t> index = justificationToIndex(justify, symbolInstance); if (index) { assert(bucket.text.placedSymbols.size() > *index); if (autoIndex && *index != *autoIndex) { diff --git a/src/mbgl/tile/geojson_tile_data.hpp b/src/mbgl/tile/geojson_tile_data.hpp index 3605af9690..5559965cd7 100644 --- a/src/mbgl/tile/geojson_tile_data.hpp +++ b/src/mbgl/tile/geojson_tile_data.hpp @@ -17,7 +17,7 @@ public: return apply_visitor(ToFeatureType(), feature.geometry); } - PropertyMap getProperties() const override { + const PropertyMap& getProperties() const override { return feature.properties; } @@ -25,15 +25,17 @@ public: return feature.id; } - GeometryCollection getGeometries() const override { - GeometryCollection geometry = apply_visitor(ToGeometryCollection(), feature.geometry); + const GeometryCollection& getGeometries() const override { + if (!geometry) { + geometry = apply_visitor(ToGeometryCollection(), feature.geometry); - // https://github.com/mapbox/geojson-vt-cpp/issues/44 - if (getType() == FeatureType::Polygon) { - geometry = fixupPolygons(geometry); + // https://github.com/mapbox/geojson-vt-cpp/issues/44 + if (getType() == FeatureType::Polygon) { + geometry = fixupPolygons(*geometry); + } } - return geometry; + return *geometry; } optional<Value> getValue(const std::string& key) const override { @@ -43,6 +45,8 @@ public: } return optional<Value>(); } + + mutable optional<GeometryCollection> geometry; }; class GeoJSONTileLayer : public GeometryTileLayer { diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 7f1bed49f4..a431ae423e 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -360,7 +360,7 @@ void GeometryTile::querySourceFeatures( continue; } - result.push_back(convertFeature(*feature, id.canonical)); + result.emplace_back(convertFeature(*feature, id.canonical)); } } } diff --git a/src/mbgl/tile/geometry_tile_data.cpp b/src/mbgl/tile/geometry_tile_data.cpp index 680f8d1497..5320df6893 100644 --- a/src/mbgl/tile/geometry_tile_data.cpp +++ b/src/mbgl/tile/geometry_tile_data.cpp @@ -57,32 +57,31 @@ std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) { std::size_t len = rings.size(); if (len <= 1) { - polygons.push_back(rings); + polygons.emplace_back(rings.clone()); return polygons; } GeometryCollection polygon; int8_t ccw = 0; - for (std::size_t i = 0; i < len; i++) { - double area = signedArea(rings[i]); - - if (area == 0) - continue; + for (const auto& ring : rings) { + double area = signedArea(ring); + if (area == 0) continue; - if (ccw == 0) + if (ccw == 0) { ccw = (area < 0 ? -1 : 1); + } if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) { - polygons.push_back(polygon); - polygon.clear(); + polygons.emplace_back(std::move(polygon)); } - polygon.push_back(rings[i]); + polygon.emplace_back(ring); } - if (!polygon.empty()) - polygons.push_back(polygon); + if (!polygon.empty()) { + polygons.emplace_back(std::move(polygon)); + } return polygons; } @@ -112,7 +111,7 @@ static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometr ); }; - GeometryCollection geometries = geometryTileFeature.getGeometries(); + const GeometryCollection& geometries = geometryTileFeature.getGeometries(); switch (geometryTileFeature.getType()) { case FeatureType::Unknown: { @@ -180,4 +179,14 @@ Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const Can return feature; } +const PropertyMap& GeometryTileFeature::getProperties() const { + static const PropertyMap dummy; + return dummy; +} + +const GeometryCollection& GeometryTileFeature::getGeometries() const { + static const GeometryCollection dummy; + return dummy; +} + } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp index 6ce67a532e..5d43a68388 100644 --- a/src/mbgl/tile/geometry_tile_data.hpp +++ b/src/mbgl/tile/geometry_tile_data.hpp @@ -35,6 +35,13 @@ public: GeometryCollection(Args&&... args) : std::vector<GeometryCoordinates>(std::forward<Args>(args)...) {} GeometryCollection(std::initializer_list<GeometryCoordinates> args) : std::vector<GeometryCoordinates>(std::move(args)) {} + GeometryCollection(GeometryCollection&&) = default; + GeometryCollection& operator=(GeometryCollection&&) = default; + + GeometryCollection clone() const { return GeometryCollection(*this); } + +private: + GeometryCollection(const GeometryCollection&) = default; }; class GeometryTileFeature { @@ -42,9 +49,9 @@ public: virtual ~GeometryTileFeature() = default; virtual FeatureType getType() const = 0; virtual optional<Value> getValue(const std::string& key) const = 0; - virtual PropertyMap getProperties() const { return PropertyMap(); } + virtual const PropertyMap& getProperties() const; virtual FeatureIdentifier getID() const { return NullValue {}; } - virtual GeometryCollection getGeometries() const = 0; + virtual const GeometryCollection& getGeometries() const; }; class GeometryTileLayer { @@ -90,31 +97,16 @@ struct ToGeometryCollection { return { { geom } }; } GeometryCollection operator()(const mapbox::geometry::multi_point<int16_t>& geom) const { - GeometryCoordinates coordinates; - coordinates.reserve(geom.size()); - for (const auto& point : geom) { - coordinates.emplace_back(point); - } - return { coordinates }; + return { geom }; } GeometryCollection operator()(const mapbox::geometry::line_string<int16_t>& geom) const { - GeometryCoordinates coordinates; - coordinates.reserve(geom.size()); - for (const auto& point : geom) { - coordinates.emplace_back(point); - } - return { coordinates }; + return { geom }; } GeometryCollection operator()(const mapbox::geometry::multi_line_string<int16_t>& geom) const { GeometryCollection collection; collection.reserve(geom.size()); for (const auto& ring : geom) { - GeometryCoordinates coordinates; - coordinates.reserve(ring.size()); - for (const auto& point : ring) { - coordinates.emplace_back(point); - } - collection.push_back(std::move(coordinates)); + collection.emplace_back(ring); } return collection; } @@ -122,25 +114,15 @@ struct ToGeometryCollection { GeometryCollection collection; collection.reserve(geom.size()); for (const auto& ring : geom) { - GeometryCoordinates coordinates; - coordinates.reserve(ring.size()); - for (const auto& point : ring) { - coordinates.emplace_back(point); - } - collection.push_back(std::move(coordinates)); + collection.emplace_back(ring); } return collection; } GeometryCollection operator()(const mapbox::geometry::multi_polygon<int16_t>& geom) const { GeometryCollection collection; - for (auto& polygon : geom) { - for (auto& ring : polygon) { - GeometryCoordinates coordinates; - coordinates.reserve(ring.size()); - for (auto& point : ring) { - coordinates.emplace_back(point); - } - collection.push_back(std::move(coordinates)); + for (const auto& polygon : geom) { + for (const auto& ring : polygon) { + collection.emplace_back(ring); } } return collection; diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index a69825d346..f4d57e5bfc 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -382,7 +382,7 @@ void GeometryTileWorker::parse() { if (!filter(expression::EvaluationContext { static_cast<float>(this->id.overscaledZ), feature.get() })) continue; - GeometryCollection geometries = feature->getGeometries(); + const GeometryCollection& geometries = feature->getGeometries(); bucket->addFeature(*feature, geometries, {}, PatternLayerMap ()); featureIndex->insert(geometries, i, sourceLayerID, leaderImpl.id); } diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp index 2d47515e0f..d53f1deba6 100644 --- a/src/mbgl/tile/vector_tile_data.cpp +++ b/src/mbgl/tile/vector_tile_data.cpp @@ -26,22 +26,26 @@ optional<Value> VectorTileFeature::getValue(const std::string& key) const { return value->is<NullValue>() ? nullopt : std::move(value); } -std::unordered_map<std::string, Value> VectorTileFeature::getProperties() const { - return feature.getProperties(); +const PropertyMap& VectorTileFeature::getProperties() const { + if (!properties) { + properties = feature.getProperties(); + } + return *properties; } FeatureIdentifier VectorTileFeature::getID() const { return feature.getID(); } -GeometryCollection VectorTileFeature::getGeometries() const { - const float scale = float(util::EXTENT) / feature.getExtent(); - auto lines = feature.getGeometries<GeometryCollection>(scale); - if (feature.getVersion() >= 2 || feature.getType() != mapbox::vector_tile::GeomType::POLYGON) { - return lines; - } else { - return fixupPolygons(lines); +const GeometryCollection& VectorTileFeature::getGeometries() const { + if (!lines) { + const float scale = float(util::EXTENT) / feature.getExtent(); + lines = feature.getGeometries<GeometryCollection>(scale); + if (feature.getVersion() < 2 && feature.getType() == mapbox::vector_tile::GeomType::POLYGON) { + lines = fixupPolygons(*lines); + } } + return *lines; } VectorTileLayer::VectorTileLayer(std::shared_ptr<const std::string> data_, diff --git a/src/mbgl/tile/vector_tile_data.hpp b/src/mbgl/tile/vector_tile_data.hpp index 7c95121a37..f5086936f8 100644 --- a/src/mbgl/tile/vector_tile_data.hpp +++ b/src/mbgl/tile/vector_tile_data.hpp @@ -15,12 +15,14 @@ public: FeatureType getType() const override; optional<Value> getValue(const std::string& key) const override; - std::unordered_map<std::string, Value> getProperties() const override; + const PropertyMap& getProperties() const override; FeatureIdentifier getID() const override; - GeometryCollection getGeometries() const override; + const GeometryCollection& getGeometries() const override; private: mapbox::vector_tile::feature feature; + mutable optional<GeometryCollection> lines; + mutable optional<PropertyMap> properties; }; class VectorTileLayer : public GeometryTileLayer { diff --git a/src/mbgl/util/grid_index.cpp b/src/mbgl/util/grid_index.cpp index f6b59b1bac..f33e889ddb 100644 --- a/src/mbgl/util/grid_index.cpp +++ b/src/mbgl/util/grid_index.cpp @@ -9,14 +9,16 @@ namespace mbgl { template <class T> -GridIndex<T>::GridIndex(const float width_, const float height_, const int16_t cellSize_) : +GridIndex<T>::GridIndex(const float width_, const float height_, const uint32_t cellSize_) : width(width_), height(height_), - xCellCount(std::ceil(width_ / cellSize_)), - yCellCount(std::ceil(height_ / cellSize_)), - xScale(xCellCount / width_), - yScale(yCellCount / height_) + xCellCount(std::ceil(width / cellSize_)), + yCellCount(std::ceil(height / cellSize_)), + xScale(xCellCount / width), + yScale(yCellCount / height) { + assert(width > 0.0f); + assert(height > 0.0f); boxCells.resize(xCellCount * yCellCount); circleCells.resize(xCellCount * yCellCount); } @@ -30,7 +32,7 @@ void GridIndex<T>::insert(T&& t, const BBox& bbox) { auto cx2 = convertToXCellCoord(bbox.max.x); auto cy2 = convertToYCellCoord(bbox.max.y); - int16_t x, y, cellIndex; + std::size_t x, y, cellIndex; for (x = cx1; x <= cx2; ++x) { for (y = cy1; y <= cy2; ++y) { cellIndex = xCellCount * y + x; @@ -50,7 +52,7 @@ void GridIndex<T>::insert(T&& t, const BCircle& bcircle) { auto cx2 = convertToXCellCoord(bcircle.center.x + bcircle.radius); auto cy2 = convertToYCellCoord(bcircle.center.y + bcircle.radius); - int16_t x, y, cellIndex; + std::size_t x, y, cellIndex; for (x = cx1; x <= cx2; ++x) { for (y = cy1; y <= cy2; ++y) { cellIndex = xCellCount * y + x; @@ -151,7 +153,7 @@ void GridIndex<T>::query(const BBox& queryBBox, std::function<bool (const T&, co auto cx2 = convertToXCellCoord(queryBBox.max.x); auto cy2 = convertToYCellCoord(queryBBox.max.y); - int16_t x, y, cellIndex; + std::size_t x, y, cellIndex; for (x = cx1; x <= cx2; ++x) { for (y = cy1; y <= cy2; ++y) { cellIndex = xCellCount * y + x; @@ -214,7 +216,7 @@ void GridIndex<T>::query(const BCircle& queryBCircle, std::function<bool (const auto cx2 = convertToXCellCoord(queryBCircle.center.x + queryBCircle.radius); auto cy2 = convertToYCellCoord(queryBCircle.center.y + queryBCircle.radius); - int16_t x, y, cellIndex; + std::size_t x, y, cellIndex; for (x = cx1; x <= cx2; ++x) { for (y = cy1; y <= cy2; ++y) { cellIndex = xCellCount * y + x; @@ -252,12 +254,12 @@ void GridIndex<T>::query(const BCircle& queryBCircle, std::function<bool (const } template <class T> -int16_t GridIndex<T>::convertToXCellCoord(const float x) const { +std::size_t GridIndex<T>::convertToXCellCoord(const float x) const { return util::max(0.0, util::min(xCellCount - 1.0, std::floor(x * xScale))); } template <class T> -int16_t GridIndex<T>::convertToYCellCoord(const float y) const { +std::size_t GridIndex<T>::convertToYCellCoord(const float y) const { return util::max(0.0, util::min(yCellCount - 1.0, std::floor(y * yScale))); } diff --git a/src/mbgl/util/grid_index.hpp b/src/mbgl/util/grid_index.hpp index 4c2d7dccc8..cb38023e59 100644 --- a/src/mbgl/util/grid_index.hpp +++ b/src/mbgl/util/grid_index.hpp @@ -57,7 +57,7 @@ template <class T> class GridIndex { public: - GridIndex(const float width_, const float height_, const int16_t cellSize_); + GridIndex(const float width_, const float height_, const uint32_t cellSize_); using BBox = mapbox::geometry::box<float>; using BCircle = geometry::circle<float>; @@ -81,8 +81,8 @@ private: void query(const BBox&, std::function<bool (const T&, const BBox&)>) const; void query(const BCircle&, std::function<bool (const T&, const BBox&)>) const; - int16_t convertToXCellCoord(const float x) const; - int16_t convertToYCellCoord(const float y) const; + std::size_t convertToXCellCoord(const float x) const; + std::size_t convertToYCellCoord(const float y) const; bool boxesCollide(const BBox&, const BBox&) const; bool circlesCollide(const BCircle&, const BCircle&) const; @@ -91,8 +91,8 @@ private: const float width; const float height; - const int16_t xCellCount; - const int16_t yCellCount; + const std::size_t xCellCount; + const std::size_t yCellCount; const double xScale; const double yScale; |