Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
Refine logic
Browse files Browse the repository at this point in the history
  • Loading branch information
zmiao committed Apr 29, 2020
1 parent 00cf68c commit 06aad3d
Showing 1 changed file with 39 additions and 32 deletions.
71 changes: 39 additions & 32 deletions src/mbgl/style/expression/distance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ double segmentToSegmentDistance(const mapbox::geometry::point<double>& p1,
pointToLineDistance(p2, mapbox::geometry::line_string<double>{q1, q2}, ruler));
auto dist2 = std::min(pointToLineDistance(q1, mapbox::geometry::line_string<double>{p1, p2}, ruler),
pointToLineDistance(q2, mapbox::geometry::line_string<double>{p1, p2}, ruler));
auto dist = std::min(dist1, dist2);
return dist;
return std::min(dist1, dist2);
}

double lineToLineDistance(const mapbox::geometry::line_string<double>& line1,
Expand Down Expand Up @@ -182,7 +181,7 @@ double pointsToPointsDistance(const mapbox::geometry::multi_point<double>& point
double pointToPolygonDistance(const mapbox::geometry::point<double>& point,
const mapbox::geometry::polygon<double>& polygon,
mapbox::cheap_ruler::CheapRuler& ruler) {
if (pointWithinPolygon(point, polygon, true)) return 0.0;
if (pointWithinPolygon(point, polygon, true /*trueOnBoundary*/)) return 0.0;
double dist = InfiniteDistance;
for (const auto& ring : polygon) {
const auto nearestPoint = std::get<0>(ruler.pointOnLine(ring, point));
Expand All @@ -202,7 +201,7 @@ double lineToPolygonDistance(const mapbox::geometry::line_string<double>& line,
return InvalidDistance;
}
for (std::size_t i = range.first; i <= range.second; ++i) {
if (pointWithinPolygon(line[i], polygon, true)) return 0.0;
if (pointWithinPolygon(line[i], polygon, true /*trueOnBoundary*/)) return 0.0;
}

double dist = InfiniteDistance;
Expand Down Expand Up @@ -234,15 +233,16 @@ double polygonToPolygonDistance(const mapbox::geometry::polygon<double>& polygon
const mapbox::geometry::polygon<double>& poly2) {
for (const auto& ring : poly1) {
for (std::size_t i = 0; i <= ring.size() - 2; ++i) {
if (pointWithinPolygon(ring[i], poly2, true)) return true;
if (pointWithinPolygon(ring[i], poly2, true /*trueOnBoundary*/)) return true;
}
}
return false;
};
if (boxWithinBox(bbox1, bbox2)) {
if (polygonIntersect(polygon1, polygon2)) return 0.0;
} else if (polygonIntersect(polygon2, polygon1))
} else if (polygonIntersect(polygon2, polygon1)) {
return 0.0;
}

double dist = InfiniteDistance;
for (const auto& ring1 : polygon1) {
Expand Down Expand Up @@ -278,14 +278,15 @@ double lineToPolygonDistance(const mapbox::geometry::line_string<double>& line,
mapbox::cheap_ruler::CheapRuler& ruler,
double currentMiniDist = InfiniteDistance) {
auto miniDist = std::min(ruler.distance(line[0], polygon[0][0]), currentMiniDist);
if (miniDist == 0.0) return miniDist;
DistQueue distQueue;
distQueue.push(std::forward_as_tuple(0, IndexRange(0, line.size() - 1), IndexRange(0, 0)));

const auto polyBBox = getBBox(polygon);
while (!distQueue.empty()) {
auto distPair = distQueue.top();
distQueue.pop();
if (std::get<0>(distPair) > miniDist) continue;
if (std::get<0>(distPair) >= miniDist) continue;
auto& range = std::get<1>(distPair);

// In case the set size are relatively small, we could use brute-force directly
Expand All @@ -300,9 +301,9 @@ double lineToPolygonDistance(const mapbox::geometry::line_string<double>& line,
[&distQueue, &miniDist, &ruler, &line, &polyBBox](mbgl::optional<IndexRange>& rangeA) {
if (!rangeA) return;
auto tempDist = bboxToBBoxDistance(getBBox(line, *rangeA), polyBBox, ruler);
// Insert new pair to the queue if the bbox distance is less or equal to miniDist,
// Insert new pair to the queue if the bbox distance is less than miniDist,
// The pair with biggest distance will be at the top
if (tempDist <= miniDist)
if (tempDist < miniDist)
distQueue.push(std::make_tuple(tempDist, std::move(*rangeA), IndexRange(0, 0)));
};
updateQueue(newRangesA.first);
Expand All @@ -317,14 +318,15 @@ double pointsToPolygonDistance(const mapbox::geometry::multi_point<double>& poin
mapbox::cheap_ruler::CheapRuler& ruler,
double currentMiniDist = InfiniteDistance) {
auto miniDist = std::min(ruler.distance(points[0], polygon[0][0]), currentMiniDist);
if (miniDist == 0.0) return miniDist;
DistQueue distQueue;
distQueue.push(std::forward_as_tuple(0, IndexRange(0, points.size() - 1), IndexRange(0, 0)));

const auto polyBBox = getBBox(polygon);
while (!distQueue.empty()) {
auto distPair = distQueue.top();
distQueue.pop();
if (std::get<0>(distPair) > miniDist) continue;
if (std::get<0>(distPair) >= miniDist) continue;
auto& range = std::get<1>(distPair);

// In case the set size are relatively small, we could use brute-force directly
Expand All @@ -340,9 +342,9 @@ double pointsToPolygonDistance(const mapbox::geometry::multi_point<double>& poin
[&distQueue, &miniDist, &ruler, &points, &polyBBox](mbgl::optional<IndexRange>& rangeA) {
if (!rangeA) return;
auto tempDist = bboxToBBoxDistance(getBBox(points, *rangeA), polyBBox, ruler);
// Insert new pair to the queue if the bbox distance is less or equal to miniDist,
// Insert new pair to the queue if the bbox distance is less than miniDist,
// The pair with biggest distance will be at the top
if (tempDist <= miniDist)
if (tempDist < miniDist)
distQueue.push(std::make_tuple(tempDist, std::move(*rangeA), IndexRange(0, 0)));
};
updateQueue(newRangesA.first);
Expand All @@ -357,13 +359,14 @@ double lineToLineDistance(const mapbox::geometry::line_string<double>& line1,
mapbox::cheap_ruler::CheapRuler& ruler,
double currentMiniDist = InfiniteDistance) {
auto miniDist = std::min(ruler.distance(line1[0], line2[0]), currentMiniDist);
if (miniDist == 0.0) return miniDist;
DistQueue distQueue;
distQueue.push(std::forward_as_tuple(0, IndexRange(0, line1.size() - 1), IndexRange(0, line2.size() - 1)));

while (!distQueue.empty()) {
auto distPair = distQueue.top();
distQueue.pop();
if (std::get<0>(distPair) > miniDist) continue;
if (std::get<0>(distPair) >= miniDist) continue;
auto& rangeA = std::get<1>(distPair);
auto& rangeB = std::get<2>(distPair);

Expand All @@ -380,9 +383,9 @@ double lineToLineDistance(const mapbox::geometry::line_string<double>& line1,
mbgl::optional<IndexRange>& range1, mbgl::optional<IndexRange>& range2) {
if (!range1 || !range2) return;
auto tempDist = bboxToBBoxDistance(getBBox(line1, *range1), getBBox(line2, *range2), ruler);
// Insert new pair to the queue if the bbox distance is less or equal to miniDist,
// Insert new pair to the queue if the bbox distance is less than miniDist,
// The pair with biggest distance will be at the top
if (tempDist <= miniDist)
if (tempDist < miniDist)
distQueue.push(std::make_tuple(tempDist, std::move(*range1), std::move(*range2)));
};
updateQueue(newRangesA.first, newRangesB.first);
Expand All @@ -398,13 +401,14 @@ double pointsToPointsDistance(const mapbox::geometry::multi_point<double>& point
const mapbox::geometry::multi_point<double>& pointSet2,
mapbox::cheap_ruler::CheapRuler& ruler) {
auto miniDist = ruler.distance(pointSet1[0], pointSet2[0]);
if (miniDist == 0.0) return miniDist;
DistQueue distQueue;
distQueue.push(std::forward_as_tuple(0, IndexRange(0, pointSet1.size() - 1), IndexRange(0, pointSet2.size() - 1)));

while (!distQueue.empty()) {
auto distPair = distQueue.top();
distQueue.pop();
if (std::get<0>(distPair) > miniDist) {
if (std::get<0>(distPair) >= miniDist) {
continue;
}
auto& rangeA = std::get<1>(distPair);
Expand All @@ -423,9 +427,9 @@ double pointsToPointsDistance(const mapbox::geometry::multi_point<double>& point
mbgl::optional<IndexRange>& range1, mbgl::optional<IndexRange>& range2) {
if (!range1 || !range2) return;
auto tempDist = bboxToBBoxDistance(getBBox(pointSet1, *range1), getBBox(pointSet2, *range2), ruler);
// Insert new pair to the queue if the bbox distance is less or equal to miniDist,
// Insert new pair to the queue if the bbox distance is less than miniDist,
// The pair with biggest distance will be at the top
if (tempDist <= miniDist)
if (tempDist < miniDist)
distQueue.push(std::make_tuple(tempDist, std::move(*range1), std::move(*range2)));
};
updateQueue(newRangesA.first, newRangesB.first);
Expand All @@ -441,13 +445,14 @@ double pointsToLineDistance(const mapbox::geometry::multi_point<double>& points,
const mapbox::geometry::line_string<double>& line,
mapbox::cheap_ruler::CheapRuler& ruler) {
auto miniDist = ruler.distance(points[0], line[0]);
if (miniDist == 0.0) return miniDist;
DistQueue distQueue;
distQueue.push(std::forward_as_tuple(0, IndexRange(0, points.size() - 1), IndexRange(0, line.size() - 1)));

while (!distQueue.empty()) {
auto distPair = distQueue.top();
distQueue.pop();
if (std::get<0>(distPair) > miniDist) continue;
if (std::get<0>(distPair) >= miniDist) continue;
auto& rangeA = std::get<1>(distPair);
auto& rangeB = std::get<2>(distPair);

Expand All @@ -472,9 +477,9 @@ double pointsToLineDistance(const mapbox::geometry::multi_point<double>& points,
mbgl::optional<IndexRange>& range1, mbgl::optional<IndexRange>& range2) {
if (!range1 || !range2) return;
auto tempDist = bboxToBBoxDistance(getBBox(points, *range1), getBBox(line, *range2), ruler);
// Insert new pair to the queue if the bbox distance is less or equal to miniDist,
// Insert new pair to the queue if the bbox distance is less than miniDist,
// The pair with biggest distance will be at the top
if (tempDist <= miniDist)
if (tempDist < miniDist)
distQueue.push(std::make_tuple(tempDist, std::move(*range1), std::move(*range2)));
};
updateQueue(newRangesA.first, newRangesB.first);
Expand All @@ -492,7 +497,7 @@ double pointsToLinesDistance(const mapbox::geometry::multi_point<double>& points
double dist = InfiniteDistance;
for (const auto& line : lines) {
dist = std::min(dist, pointsToLineDistance(points, line, ruler));
if (dist == 0.0) return 0.0;
if (dist == 0.0) return dist;
}
return dist;
}
Expand All @@ -503,7 +508,7 @@ double lineToLinesDistance(const mapbox::geometry::line_string<double>& line,
double dist = InfiniteDistance;
for (const auto& l : lines) {
dist = std::min(dist, lineToLineDistance(line, l, ruler, dist));
if (dist == 0.0) return 0.0;
if (dist == 0.0) return dist;
}
return dist;
}
Expand Down Expand Up @@ -533,7 +538,7 @@ double pointsToGeometryDistance(const mapbox::geometry::multi_point<double>& poi
auto tempDist = pointsToPolygonDistance(points, polygon, ruler, dist);
if (std::isnan(tempDist)) return tempDist;
dist = std::min(dist, tempDist);
if (dist == 0.0 || std::isnan(dist)) return dist;
if (dist == 0.0) return dist;
}
return dist;
},
Expand Down Expand Up @@ -565,7 +570,7 @@ double lineToGeometryDistance(const mapbox::geometry::line_string<double>& line,
auto tempDist = lineToPolygonDistance(line, polygon, ruler, dist);
if (std::isnan(tempDist)) return tempDist;
dist = std::min(dist, tempDist);
if (dist == 0.0 || std::isnan(dist)) return dist;
if (dist == 0.0) return dist;
}
return dist;
},
Expand All @@ -590,8 +595,9 @@ double polygonToGeometryDistance(const mapbox::geometry::polygon<double>& polygo
double dist = InfiniteDistance;
for (const auto& line : lines) {
auto tempDist = lineToPolygonDistance(line, polygon, ruler);
if (std::isnan(tempDist)) return tempDist;
dist = std::min(dist, tempDist);
if (dist == 0.0 || std::isnan(dist)) return dist;
if (dist == 0.0) return dist;
}
return dist;
},
Expand All @@ -602,8 +608,9 @@ double polygonToGeometryDistance(const mapbox::geometry::polygon<double>& polygo
double dist = InfiniteDistance;
for (const auto& polygon1 : polygons) {
auto tempDist = polygonToPolygonDistance(polygon, polygon1, ruler, dist);
if (std::isnan(tempDist)) return tempDist;
dist = std::min(dist, tempDist);
if (dist == 0.0 || std::isnan(dist)) return dist;
if (dist == 0.0) return dist;
}
return dist;
},
Expand All @@ -630,7 +637,7 @@ double calculateDistance(const GeometryTileFeature& feature,
auto tempDist = lineToGeometryDistance(line, geoSet);
if (std::isnan(tempDist)) return tempDist;
dist = std::min(dist, tempDist);
if (dist == 0.0 || std::isnan(dist)) return dist;
if (dist == 0.0) return dist;
}
return dist;
},
Expand All @@ -643,7 +650,7 @@ double calculateDistance(const GeometryTileFeature& feature,
auto tempDist = polygonToGeometryDistance(polygon, geoSet);
if (std::isnan(tempDist)) return tempDist;
dist = std::min(dist, tempDist);
if (dist == 0.0 || std::isnan(dist)) return dist;
if (dist == 0.0) return dist;
}
return dist;
},
Expand Down Expand Up @@ -677,7 +684,7 @@ optional<GeoJSON> parseValue(const style::conversion::Convertible& value, style:

optional<Feature::geometry_type> getGeometry(const Feature& feature, mbgl::style::expression::ParsingContext& ctx) {
const auto type = apply_visitor(ToFeatureType(), feature.geometry);
if (type != FeatureType::Unknown) {
if (type == FeatureType::Point || type == FeatureType::LineString || type == FeatureType::Polygon) {
return feature.geometry;
}
ctx.error(
Expand All @@ -701,7 +708,7 @@ EvaluationResult Distance::evaluate(const EvaluationContext& params) const {
return EvaluationError{"distance expression requirs valid feature and canonical information."};
}
auto geometryType = params.feature->getType();
if (geometryType != FeatureType::Unknown) {
if (geometryType == FeatureType::Point || geometryType == FeatureType::LineString || geometryType == FeatureType::Polygon) {
auto distance = calculateDistance(*params.feature, *params.canonical, geometries);
if (!std::isnan(distance)) {
assert(distance >= 0.0);
Expand Down Expand Up @@ -739,7 +746,7 @@ ParseResult Distance::parse(const Convertible& value, ParsingContext& ctx) {
return ParseResult();
},
[&ctx](const auto&) {
ctx.error("'distance' expression requires valid geojson that contains LineString/Point geometries.");
ctx.error("'distance' expression requires valid geojson that contains Point/LineString/Polygon geometries.");
return ParseResult();
});

Expand Down

0 comments on commit 06aad3d

Please sign in to comment.