[core] Include geometry in queryRenderedFeatures results

This commit is contained in:
John Firebaugh
2016-05-17 13:21:19 -07:00
parent 1b1df9e354
commit 5864c8fc4c
8 changed files with 102 additions and 15 deletions

View File

@@ -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"

View File

@@ -53,7 +53,6 @@ module.exports = function (style, options, callback) {
function prepareFeatures(r) {
delete r.layer;
r.geometry = null;
return r;
}
};

View File

@@ -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));
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -206,6 +206,7 @@ void VectorTileData::queryRenderedFeatures(
std::pow(2, transformState.getZoom() - id.overscaledZ),
layerIDs,
*geometryTile,
id.canonical,
style);
}

View File

@@ -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);