Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion platform/node/test/suite_implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ module.exports = function (style, options, callback) {

function prepareFeatures(r) {
delete r.layer;
r.geometry = null;
return r;
}
};
21 changes: 8 additions & 13 deletions src/mbgl/geometry/feature_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -73,15 +74,15 @@ 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
assert(collisionTile);
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);
}
}

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

Expand Down
3 changes: 3 additions & 0 deletions src/mbgl/geometry/feature_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace mbgl {
class Style;
class CollisionTile;
enum class TranslateAnchorType : bool;
class CanonicalTileID;

class IndexedSubfeature {
public:
Expand All @@ -38,6 +39,7 @@ class FeatureIndex {
const double scale,
const optional<std::vector<std::string>>& layerIDs,
const GeometryTile&,
const CanonicalTileID&,
const Style&) const;

static optional<GeometryCollection> translateQueryGeometry(
Expand All @@ -58,6 +60,7 @@ class FeatureIndex {
const GeometryCollection& queryGeometry,
const optional<std::vector<std::string>>& filterLayerIDs,
const GeometryTile&,
const CanonicalTileID&,
const Style&,
const float bearing,
const float pixelsToTileUnits) const;
Expand Down
135 changes: 135 additions & 0 deletions src/mbgl/tile/geometry_tile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile_id.hpp>

namespace mbgl {

static double signedArea(const GeometryCoordinates& ring) {
double sum = 0;

for (std::size_t i = 0, len = ring.size(), j = len - 1; i < len; j = i++) {
const GeometryCoordinate& p1 = ring[i];
const GeometryCoordinate& p2 = ring[j];
sum += (p2.x - p1.x) * (p1.y + p2.y);
}

return sum;
}

std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
std::vector<GeometryCollection> polygons;

std::size_t len = rings.size();

if (len <= 1) {
polygons.push_back(rings);
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;

if (ccw == 0)
ccw = (area < 0 ? -1 : 1);

if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) {
polygons.push_back(polygon);
polygon.clear();
}

polygon.push_back(rings[i]);
}

if (!polygon.empty())
polygons.push_back(polygon);

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
8 changes: 8 additions & 0 deletions src/mbgl/tile/geometry_tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -87,6 +89,12 @@ class GeometryTileMonitor : private util::noncopyable {
virtual std::unique_ptr<AsyncRequest> monitorTile(const Callback&) = 0;
};

// 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
1 change: 1 addition & 0 deletions src/mbgl/tile/vector_tile_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ void VectorTileData::queryRenderedFeatures(
std::pow(2, transformState.getZoom() - id.overscaledZ),
layerIDs,
*geometryTile,
id.canonical,
style);
}

Expand Down
3 changes: 3 additions & 0 deletions src/mbgl/util/geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down