[core] Include geometry in queryRenderedFeatures results
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"aws-sdk": "^2.3.5",
|
||||
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#4749c0f1ced2ef2d2cda9a90190fbad89449e813",
|
||||
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#b3441d9a285ffbe9b876677acb13d7df07e5b975",
|
||||
"node-gyp": "^3.3.1",
|
||||
"request": "^2.72.0",
|
||||
"tape": "^4.5.1"
|
||||
|
||||
@@ -53,7 +53,6 @@ module.exports = function (style, options, callback) {
|
||||
|
||||
function prepareFeatures(r) {
|
||||
delete r.layer;
|
||||
r.geometry = null;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,6 +57,7 @@ void FeatureIndex::query(
|
||||
const double scale,
|
||||
const optional<std::vector<std::string>>& filterLayerIDs,
|
||||
const GeometryTile& geometryTile,
|
||||
const CanonicalTileID& tileID,
|
||||
const Style& style) const {
|
||||
|
||||
mapbox::geometry::box<int16_t> 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<IndexedSubfeature> 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<std::vector<std::string>>& 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<SymbolLayer>() &&
|
||||
!styleLayer->queryIntersectsGeometry(queryGeometry, geometryTileFeature->getGeometries(), bearing, pixelsToTileUnits))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!styleLayer->is<SymbolLayer>()) {
|
||||
auto geometries = geometryTileFeature->getGeometries();
|
||||
if (!styleLayer->queryIntersectsGeometry(queryGeometry, geometries, bearing, pixelsToTileUnits)) continue;
|
||||
}
|
||||
|
||||
Feature feature { mapbox::geometry::point<double>() };
|
||||
feature.properties = geometryTileFeature->getProperties();
|
||||
feature.id = geometryTileFeature->getID();
|
||||
|
||||
result[layerID].push_back(std::move(feature));
|
||||
result[layerID].push_back(convertFeature(*geometryTileFeature, tileID));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<std::vector<std::string>>& layerIDs,
|
||||
const GeometryTile&,
|
||||
const CanonicalTileID&,
|
||||
const Style&) const;
|
||||
|
||||
static optional<GeometryCollection> translateQueryGeometry(
|
||||
@@ -58,6 +60,7 @@ private:
|
||||
const GeometryCollection& queryGeometry,
|
||||
const optional<std::vector<std::string>>& filterLayerIDs,
|
||||
const GeometryTile&,
|
||||
const CanonicalTileID&,
|
||||
const Style&,
|
||||
const float bearing,
|
||||
const float pixelsToTileUnits) const;
|
||||
|
||||
@@ -51,4 +51,85 @@ std::vector<GeometryCollection> 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<int16_t>& p) {
|
||||
double y2 = 180 - (p.y + y0) * 360 / size;
|
||||
return Point<double>(
|
||||
(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<double>(NAN, NAN);
|
||||
}
|
||||
|
||||
case FeatureType::Point: {
|
||||
MultiPoint<double> 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<double> multiLineString;
|
||||
for (const auto& g : geometries) {
|
||||
LineString<double> 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<double> multiPolygon;
|
||||
for (const auto& pg : classifyRings(geometries)) {
|
||||
Polygon<double> polygon;
|
||||
for (const auto& r : pg) {
|
||||
LinearRing<double> 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<double>();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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<GeometryCollection> classifyRings(const GeometryCollection&);
|
||||
|
||||
// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature)
|
||||
Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -206,6 +206,7 @@ void VectorTileData::queryRenderedFeatures(
|
||||
std::pow(2, transformState.getZoom() - id.overscaledZ),
|
||||
layerIDs,
|
||||
*geometryTile,
|
||||
id.canonical,
|
||||
style);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ using MultiLineString = mapbox::geometry::multi_line_string<T>;
|
||||
template <class T>
|
||||
using MultiPolygon = mapbox::geometry::multi_polygon<T>;
|
||||
|
||||
template <class T>
|
||||
using LinearRing = mapbox::geometry::linear_ring<T>;
|
||||
|
||||
template <class S, class T>
|
||||
Point<S> convertPoint(const Point<T>& p) {
|
||||
return Point<S>(p.x, p.y);
|
||||
|
||||
Reference in New Issue
Block a user