summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzmiao <miao.zhao@mapbox.com>2020-03-20 19:55:55 +0200
committerzmiao <miao.zhao@mapbox.com>2020-03-26 14:13:59 +0200
commit848f48ac274afc52614d22b940d6ad31717e027a (patch)
tree9a0c3ab0b514fed07e7c326d55e2c1ad095dde47
parent9009089a933013df93a35c095021a0c102f8788b (diff)
downloadqtlocation-mapboxgl-848f48ac274afc52614d22b940d6ad31717e027a.tar.gz
[core] Fix within meridian issue
-rw-r--r--src/mbgl/style/expression/within.cpp39
-rw-r--r--src/mbgl/util/geometry_within.cpp6
2 files changed, 38 insertions, 7 deletions
diff --git a/src/mbgl/style/expression/within.cpp b/src/mbgl/style/expression/within.cpp
index be6db20c35..271bf8f175 100644
--- a/src/mbgl/style/expression/within.cpp
+++ b/src/mbgl/style/expression/within.cpp
@@ -67,24 +67,41 @@ MultiPolygon<int64_t> getTilePolygons(const Feature::geometry_type& polygonGeoSe
[](const auto&) { return MultiPolygon<int64_t>(); });
}
+void updatePoint(Point<int64_t>& p, WithinBBox& bbox, const WithinBBox& polyBBox, const int64_t worldSize) {
+ if (p.x <= polyBBox[0] || p.x >= polyBBox[2]) {
+ int64_t shift = 0;
+ shift = (p.x - polyBBox[0] > worldSize / 2) ? -worldSize : (polyBBox[0] - p.x > worldSize / 2) ? worldSize : 0;
+ if (shift == 0) {
+ shift =
+ (p.x - polyBBox[2] > worldSize / 2) ? -worldSize : (polyBBox[2] - p.x > worldSize / 2) ? worldSize : 0;
+ }
+ p.x += shift;
+ }
+ updateBBox(bbox, p);
+}
+
MultiPoint<int64_t> getTilePoints(const GeometryCoordinates& points,
const mbgl::CanonicalTileID& canonical,
- WithinBBox& bbox) {
+ WithinBBox& bbox,
+ const WithinBBox& polyBBox) {
const int64_t xShift = util::EXTENT * canonical.x;
const int64_t yShift = util::EXTENT * canonical.y;
+ const auto worldSize = util::EXTENT * std::pow(2, canonical.z);
MultiPoint<int64_t> results;
results.reserve(points.size());
for (const auto& p : points) {
- const auto point = Point<int64_t>(p.x + xShift, p.y + yShift);
- updateBBox(bbox, point);
+ auto point = Point<int64_t>(p.x + xShift, p.y + yShift);
+ updatePoint(point, bbox, polyBBox, worldSize);
results.push_back(point);
}
+
return results;
}
MultiLineString<int64_t> getTileLines(const GeometryCollection& lines,
const mbgl::CanonicalTileID& canonical,
- WithinBBox& bbox) {
+ WithinBBox& bbox,
+ const WithinBBox& polyBBox) {
const int64_t xShift = util::EXTENT * canonical.x;
const int64_t yShift = util::EXTENT * canonical.y;
MultiLineString<int64_t> results;
@@ -99,6 +116,16 @@ MultiLineString<int64_t> getTileLines(const GeometryCollection& lines,
}
results.push_back(std::move(lineString));
}
+
+ const auto worldSize = util::EXTENT * std::pow(2, canonical.z);
+ if (bbox[2] - bbox[0] <= worldSize / 2) {
+ bbox = DefaultBBox;
+ for (auto& line : results) {
+ for (auto& p : line) {
+ updatePoint(p, bbox, polyBBox, worldSize);
+ }
+ }
+ }
return results;
}
@@ -113,7 +140,7 @@ bool featureWithinPolygons(const GeometryTileFeature& feature,
case FeatureType::Point: {
assert(!geometries.empty());
WithinBBox pointBBox = DefaultBBox;
- MultiPoint<int64_t> points = getTilePoints(geometries.at(0), canonical, pointBBox);
+ MultiPoint<int64_t> points = getTilePoints(geometries.at(0), canonical, pointBBox, polyBBox);
if (!boxWithinBox(pointBBox, polyBBox)) return false;
return std::all_of(
@@ -121,7 +148,7 @@ bool featureWithinPolygons(const GeometryTileFeature& feature,
}
case FeatureType::LineString: {
WithinBBox lineBBox = DefaultBBox;
- MultiLineString<int64_t> multiLineString = getTileLines(geometries, canonical, lineBBox);
+ MultiLineString<int64_t> multiLineString = getTileLines(geometries, canonical, lineBBox, polyBBox);
if (!boxWithinBox(lineBBox, polyBBox)) return false;
return std::all_of(multiLineString.begin(), multiLineString.end(), [&polygons](const auto& line) {
diff --git a/src/mbgl/util/geometry_within.cpp b/src/mbgl/util/geometry_within.cpp
index 28a53c8ebc..89e3d84fc6 100644
--- a/src/mbgl/util/geometry_within.cpp
+++ b/src/mbgl/util/geometry_within.cpp
@@ -47,7 +47,11 @@ bool lineIntersectLine(const Point<int64_t>& a,
y2 = p2.y - q1.y;
x3 = q2.x - q1.x;
y3 = q2.y - q1.y;
- if ((x1 * y3 - x3 * y1) * (x2 * y3 - x3 * y2) < 0) return true;
+ auto ret1 = (x1 * y3 - x3 * y1);
+ auto ret2 = (x2 * y3 - x3 * y2);
+ if ((ret1 > 0 && ret2 < 0) || (ret1 < 0 && ret2 > 0)) {
+ return true;
+ }
return false;
};