From 5864c8fc4cc0e42b2c13f57845492ac20f6980dd Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 17 May 2016 13:21:19 -0700 Subject: [core] Include geometry in queryRenderedFeatures results --- src/mbgl/geometry/feature_index.cpp | 21 ++++------ src/mbgl/geometry/feature_index.hpp | 3 ++ src/mbgl/tile/geometry_tile.cpp | 81 +++++++++++++++++++++++++++++++++++++ src/mbgl/tile/geometry_tile.hpp | 5 +++ src/mbgl/tile/vector_tile_data.cpp | 1 + src/mbgl/util/geometry.hpp | 3 ++ 6 files changed, 101 insertions(+), 13 deletions(-) (limited to 'src/mbgl') diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index fb68b572b1..ab451bcd6a 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -57,6 +57,7 @@ void FeatureIndex::query( const double scale, const optional>& filterLayerIDs, const GeometryTile& geometryTile, + const CanonicalTileID& tileID, const Style& style) const { mapbox::geometry::box box = mapbox::geometry::envelope(queryGeometry); @@ -73,7 +74,7 @@ void FeatureIndex::query( if (indexedFeature.sortIndex == previousSortIndex) continue; previousSortIndex = indexedFeature.sortIndex; - addFeature(result, indexedFeature, queryGeometry, filterLayerIDs, geometryTile, style, bearing, pixelsToTileUnits); + addFeature(result, indexedFeature, queryGeometry, filterLayerIDs, geometryTile, tileID, style, bearing, pixelsToTileUnits); } // query symbol features @@ -81,7 +82,7 @@ void FeatureIndex::query( std::vector symbolFeatures = collisionTile->queryRenderedSymbols(box, scale); std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols); for (const auto& symbolFeature : symbolFeatures) { - addFeature(result, symbolFeature, queryGeometry, filterLayerIDs, geometryTile, style, bearing, pixelsToTileUnits); + addFeature(result, symbolFeature, queryGeometry, filterLayerIDs, geometryTile, tileID, style, bearing, pixelsToTileUnits); } } @@ -91,6 +92,7 @@ void FeatureIndex::addFeature( const GeometryCollection& queryGeometry, const optional>& filterLayerIDs, const GeometryTile& geometryTile, + const CanonicalTileID& tileID, const Style& style, const float bearing, const float pixelsToTileUnits) const { @@ -112,20 +114,13 @@ void FeatureIndex::addFeature( } auto styleLayer = style.getLayer(layerID); - if (!styleLayer) { + if (!styleLayer || + (!styleLayer->is() && + !styleLayer->queryIntersectsGeometry(queryGeometry, geometryTileFeature->getGeometries(), bearing, pixelsToTileUnits))) { continue; } - if (!styleLayer->is()) { - auto geometries = geometryTileFeature->getGeometries(); - if (!styleLayer->queryIntersectsGeometry(queryGeometry, geometries, bearing, pixelsToTileUnits)) continue; - } - - Feature feature { mapbox::geometry::point() }; - feature.properties = geometryTileFeature->getProperties(); - feature.id = geometryTileFeature->getID(); - - result[layerID].push_back(std::move(feature)); + result[layerID].push_back(convertFeature(*geometryTileFeature, tileID)); } } diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index 0cb9a891d7..a0afbb885a 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -14,6 +14,7 @@ namespace mbgl { class Style; class CollisionTile; enum class TranslateAnchorType : bool; +class CanonicalTileID; class IndexedSubfeature { public: @@ -38,6 +39,7 @@ public: const double scale, const optional>& layerIDs, const GeometryTile&, + const CanonicalTileID&, const Style&) const; static optional translateQueryGeometry( @@ -58,6 +60,7 @@ private: const GeometryCollection& queryGeometry, const optional>& filterLayerIDs, const GeometryTile&, + const CanonicalTileID&, const Style&, const float bearing, const float pixelsToTileUnits) const; diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 9f57c7ab6f..2e3d0576db 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -51,4 +51,85 @@ std::vector classifyRings(const GeometryCollection& rings) { return polygons; } +static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) { + const double size = util::EXTENT * std::pow(2, tileID.z); + const double x0 = util::EXTENT * tileID.x; + const double y0 = util::EXTENT * tileID.y; + + auto tileCoordinatesToLatLng = [&] (const Point& p) { + double y2 = 180 - (p.y + y0) * 360 / size; + return Point( + (p.x + x0) * 360 / size - 180, + 360.0 / M_PI * std::atan(std::exp(y2 * M_PI / 180)) - 90.0 + ); + }; + + GeometryCollection geometries = geometryTileFeature.getGeometries(); + + switch (geometryTileFeature.getType()) { + case FeatureType::Unknown: { + assert(false); + return Point(NAN, NAN); + } + + case FeatureType::Point: { + MultiPoint multiPoint; + for (const auto& p : geometries.at(0)) { + multiPoint.push_back(tileCoordinatesToLatLng(p)); + } + if (multiPoint.size() == 1) { + return multiPoint[0]; + } else { + return multiPoint; + } + } + + case FeatureType::LineString: { + MultiLineString multiLineString; + for (const auto& g : geometries) { + LineString lineString; + for (const auto& p : g) { + lineString.push_back(tileCoordinatesToLatLng(p)); + } + multiLineString.push_back(std::move(lineString)); + } + if (multiLineString.size() == 1) { + return multiLineString[0]; + } else { + return multiLineString; + } + } + + case FeatureType::Polygon: { + MultiPolygon multiPolygon; + for (const auto& pg : classifyRings(geometries)) { + Polygon polygon; + for (const auto& r : pg) { + LinearRing linearRing; + for (const auto& p : r) { + linearRing.push_back(tileCoordinatesToLatLng(p)); + } + polygon.push_back(std::move(linearRing)); + } + multiPolygon.push_back(std::move(polygon)); + } + if (multiPolygon.size() == 1) { + return multiPolygon[0]; + } else { + return multiPolygon; + } + } + } + + // Unreachable, but placate GCC. + return Point(); +} + +Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) { + Feature feature { convertGeometry(geometryTileFeature, tileID) }; + feature.properties = geometryTileFeature.getProperties(); + feature.id = geometryTileFeature.getID(); + return feature; +} + } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index edbe91b6c9..d98e1b3b0c 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -25,6 +25,8 @@ enum class FeatureType : uint8_t { Polygon = 3 }; +class CanonicalTileID; + // Normalized vector tile coordinates. // Each geometry coordinate represents a point in a bidimensional space, // varying from -V...0...+V, where V is the maximum extent applicable. @@ -90,6 +92,9 @@ public: // classifies an array of rings into polygons with outer rings and holes std::vector classifyRings(const GeometryCollection&); +// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature) +Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&); + } // namespace mbgl #endif diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp index 457ffd4171..10b5bae182 100644 --- a/src/mbgl/tile/vector_tile_data.cpp +++ b/src/mbgl/tile/vector_tile_data.cpp @@ -206,6 +206,7 @@ void VectorTileData::queryRenderedFeatures( std::pow(2, transformState.getZoom() - id.overscaledZ), layerIDs, *geometryTile, + id.canonical, style); } diff --git a/src/mbgl/util/geometry.hpp b/src/mbgl/util/geometry.hpp index bf44d5ce93..f9b91bcb39 100644 --- a/src/mbgl/util/geometry.hpp +++ b/src/mbgl/util/geometry.hpp @@ -23,6 +23,9 @@ using MultiLineString = mapbox::geometry::multi_line_string; template using MultiPolygon = mapbox::geometry::multi_polygon; +template +using LinearRing = mapbox::geometry::linear_ring; + template Point convertPoint(const Point& p) { return Point(p.x, p.y); -- cgit v1.2.1