From 351f421080572849b175326ccbee13a77a39bae6 Mon Sep 17 00:00:00 2001 From: zmiao Date: Tue, 18 Feb 2020 14:11:50 +0200 Subject: [core] Update unti tests. Remove unnecessary debugging code --- src/mbgl/style/expression/within.cpp | 166 +++++++++++++++-------------------- src/mbgl/util/geometry_within.cpp | 98 +++++++-------------- src/mbgl/util/geometry_within.hpp | 10 +-- 3 files changed, 104 insertions(+), 170 deletions(-) (limited to 'src') diff --git a/src/mbgl/style/expression/within.cpp b/src/mbgl/style/expression/within.cpp index c5582b4168..0447dfe228 100644 --- a/src/mbgl/style/expression/within.cpp +++ b/src/mbgl/style/expression/within.cpp @@ -5,9 +5,9 @@ #include #include +#include #include #include -#include #include #include @@ -38,100 +38,64 @@ public: bool pointsWithinPolygons(const mbgl::GeometryTileFeature& feature, const mbgl::CanonicalTileID& canonical, - const mbgl::GeoJSON& geoJson) { - return geoJson.match( - [&feature, &canonical](const mapbox::geometry::geometry& geometrySet) -> bool { - mbgl::Feature f(geometrySet); - PolygonFeature polyFeature(f, CanonicalTileID(0, 0, 0)); - auto refinedGeoSet = convertGeometry(polyFeature, CanonicalTileID(0, 0, 0)); - return refinedGeoSet.match( - [&feature, &canonical](const mapbox::geometry::multi_polygon& polygons) -> bool { - return convertGeometry(feature, canonical) - .match( - [&polygons](const mapbox::geometry::point& point) -> bool { - return pointWithinPolygons(point, polygons); - }, - [&polygons](const mapbox::geometry::multi_point& points) -> bool { - return std::all_of(points.begin(), points.end(), [&polygons](const auto& p) { - return pointWithinPolygons(p, polygons); - }); - }, - [](const auto&) -> bool {return false;}); - }, - [&feature, &canonical](const mapbox::geometry::polygon& polygon) -> bool { - return convertGeometry(feature, canonical) - .match( - [&polygon](const mapbox::geometry::point& point) -> bool { - return pointWithinPolygon(point, polygon); - }, - [&polygon](const mapbox::geometry::multi_point& points) -> bool { - return std::all_of(points.begin(), points.end(), [&polygon](const auto& p) { - return pointWithinPolygon(p, polygon); - }); - }, - [](const auto&) -> bool { return false; }); - }, - [](const auto&) -> bool { return false; }); + const Feature::geometry_type& polygonGeoSet) { + return polygonGeoSet.match( + [&feature, &canonical](const mapbox::geometry::multi_polygon& polygons) -> bool { + return convertGeometry(feature, canonical) + .match( + [&polygons](const mapbox::geometry::point& point) -> bool { + return pointWithinPolygons(point, polygons); + }, + [&polygons](const mapbox::geometry::multi_point& points) -> bool { + return std::all_of(points.begin(), points.end(), [&polygons](const auto& p) { + return pointWithinPolygons(p, polygons); + }); + }, + [](const auto&) -> bool { return false; }); + }, + [&feature, &canonical](const mapbox::geometry::polygon& polygon) -> bool { + return convertGeometry(feature, canonical) + .match( + [&polygon](const mapbox::geometry::point& point) -> bool { + return pointWithinPolygon(point, polygon); + }, + [&polygon](const mapbox::geometry::multi_point& points) -> bool { + return std::all_of(points.begin(), points.end(), [&polygon](const auto& p) { + return pointWithinPolygon(p, polygon); + }); + }, + [](const auto&) -> bool { return false; }); }, [](const auto&) -> bool { return false; }); } - - bool linesWithinPolygons(const mbgl::GeometryTileFeature& feature, const mbgl::CanonicalTileID& canonical, - const mbgl::GeoJSON& geoJson) { - mbgl::Log::Debug(mbgl::Event::General, "------------------------Canonical ID is-------------------------------"); - mbgl::Log::Debug( - mbgl::Event::General, "----- '%d' / '%d' / '%d'-------------", canonical.z, canonical.x, canonical.y); - - return geoJson.match( - [&feature, &canonical](const mapbox::geometry::geometry& geometrySet) -> bool { - mbgl::Feature f(geometrySet); - PolygonFeature polyFeature(f, CanonicalTileID(0, 0, 0)); - auto refinedGeoSet = convertGeometry(polyFeature, CanonicalTileID(0, 0, 0)); - return refinedGeoSet.match( - [&feature, &canonical](const MultiPolygon& polygons) -> bool { - return convertGeometry(feature, canonical) - .match( - [&polygons](const LineString& line) -> bool { - printLine(line); - return lineStringWithinPolygons(line, polygons); - }, - [&polygons](const MultiLineString& lines) -> bool { - return std::all_of(lines.begin(), lines.end(), [&polygons](const auto& line) { - printLine(line); - return lineStringWithinPolygons(line, polygons); - }); - }, - [](const auto&) -> bool { - return false; - }); - }, - [&feature, &canonical](const Polygon& polygon) -> bool { - return convertGeometry(feature, canonical) - .match( - [&polygon](const LineString& line) -> bool { - printLine(line); - return lineStringWithinPolygon(line, polygon); - }, - [&polygon](const MultiLineString& lines) -> bool { - return std::all_of(lines.begin(), lines.end(), [&polygon](const auto& line) { - printLine(line); - return lineStringWithinPolygon(line, polygon); - }); - }, - [](const auto&) -> bool { - return false; - }); - }, - [](const auto&) -> bool { - return false; - }); + const Feature::geometry_type& polygonGeoSet) { + return polygonGeoSet.match( + [&feature, &canonical](const MultiPolygon& polygons) -> bool { + return convertGeometry(feature, canonical) + .match([&polygons]( + const LineString& line) -> bool { return lineStringWithinPolygons(line, polygons); }, + [&polygons](const MultiLineString& lines) -> bool { + return std::all_of(lines.begin(), lines.end(), [&polygons](const auto& line) { + return lineStringWithinPolygons(line, polygons); + }); + }, + [](const auto&) -> bool { return false; }); + }, + [&feature, &canonical](const Polygon& polygon) -> bool { + return convertGeometry(feature, canonical) + .match([&polygon]( + const LineString& line) -> bool { return lineStringWithinPolygon(line, polygon); }, + [&polygon](const MultiLineString& lines) -> bool { + return std::all_of(lines.begin(), lines.end(), [&polygon](const auto& line) { + return lineStringWithinPolygon(line, polygon); + }); + }, + [](const auto&) -> bool { return false; }); }, - [](const auto&) -> bool { - return false; - }); + [](const auto&) -> bool { return false; }); } mbgl::optional parseValue(const mbgl::style::conversion::Convertible& value_, @@ -150,7 +114,7 @@ mbgl::optional parseValue(const mbgl::style::conversion::Converti } } } - ctx.error("'Within' expression requires valid geojson source that contains polygon geometry type."); + ctx.error("'within' expression requires valid geojson source that contains polygon geometry type."); return nullopt; } @@ -159,7 +123,8 @@ mbgl::optional parseValue(const mbgl::style::conversion::Converti namespace style { namespace expression { -Within::Within(GeoJSON geojson) : Expression(Kind::Within, type::Boolean), geoJSONSource(std::move(geojson)) {} +Within::Within(GeoJSON geojson, Feature::geometry_type geometries_) + : Expression(Kind::Within, type::Boolean), geoJSONSource(std::move(geojson)), geometries(std::move(geometries_)) {} Within::~Within() = default; @@ -172,11 +137,12 @@ EvaluationResult Within::evaluate(const EvaluationContext& params) const { auto geometryType = params.feature->getType(); // Currently only support Point/Points in Polygon/Polygons if (geometryType == FeatureType::Point) { - return pointsWithinPolygons(*params.feature, *params.canonical, geoJSONSource); + return pointsWithinPolygons(*params.feature, *params.canonical, geometries); } else if (geometryType == FeatureType::LineString) { - return linesWithinPolygons(*params.feature, *params.canonical, geoJSONSource); + return linesWithinPolygons(*params.feature, *params.canonical, geometries); } - mbgl::Log::Warning(mbgl::Event::General, "within expression currently only support 'Point' geometry type"); + mbgl::Log::Warning(mbgl::Event::General, + "within expression currently only support Point/LineString geometry type."); return false; } @@ -194,8 +160,20 @@ ParseResult Within::parse(const Convertible& value, ParsingContext& ctx) { if (!parsedValue) { return ParseResult(); } - return ParseResult(std::make_unique(*parsedValue)); + + return parsedValue->match( + [&parsedValue](const mapbox::geometry::geometry& geometrySet) { + mbgl::Feature f(geometrySet); + PolygonFeature polyFeature(f, CanonicalTileID(0, 0, 0)); + auto refinedGeoSet = convertGeometry(polyFeature, CanonicalTileID(0, 0, 0)); + return ParseResult(std::make_unique(*parsedValue, refinedGeoSet)); + }, + [&ctx](const auto&) { + ctx.error("'within' expression requires geojson source that contains valid geometry data."); + return ParseResult(); + }); } + ctx.error("'within' expression needs to be an array with exactly one argument."); return ParseResult(); } diff --git a/src/mbgl/util/geometry_within.cpp b/src/mbgl/util/geometry_within.cpp index 0d60a5622b..bb62047077 100644 --- a/src/mbgl/util/geometry_within.cpp +++ b/src/mbgl/util/geometry_within.cpp @@ -8,51 +8,41 @@ bool rayIntersect(const Point& p, const Point& p1, const Point p.y) != (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x); } -// a, b are end point for line segment1, c and d are end points for line segment2 -bool lineIntersectLine(const Point& a, - const Point& b, - const Point& c, - const Point& d) { - const auto perp = [](const Point& v1, const Point& v2) { - return (v1.x * v2.y - v1.y * v2.x); - }; - - // check if p1 and p2 are in different sides of line segment q1->q2 - const auto twoSided = [](const Point& p1, - const Point& p2, - const Point& q1, - const Point& q2) { - double x1, y1, x2, y2, x3, y3; - - // q1->p1 (x1, y1), q1->p2 (x2, y2), q1->q2 (x3, y3) - x1 = p1.x - q1.x; - y1 = p1.y - q1.y; - x2 = p2.x - q1.x; - 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; - return false; - }; +// a, b are end points for line segment1, c and d are end points for line segment2 +bool lineIntersectLine(const Point& a, const Point& b, const Point& c, const Point& d) { + const auto perp = [](const Point& v1, const Point& v2) { return (v1.x * v2.y - v1.y * v2.x); }; + // check if two segments are parallel or not + // precondition is end point a, b is inside polygon, if line a->b is + // parallel to polygon edge c->d, then a->b won't intersect with c->d auto vectorP = Point(b.x - a.x, b.y - a.y); auto vectorQ = Point(d.x - c.x, d.y - c.y); - - // check if two segments are parallel or not - // precondition is end point a, b is inside polygon, if they line a->b is - // parallel to edge c->d, then a->b won't intersect with c->d if (perp(vectorQ, vectorP) == 0) return false; - // check if there are intersecting with each other - // a and b lie in separate side of segment c->d - // c and d lie in separate side of segment a->b + // check if p1 and p2 are in different sides of line segment q1->q2 + const auto twoSided = + [](const Point& p1, const Point& p2, const Point& q1, const Point& q2) { + double x1, y1, x2, y2, x3, y3; + + // q1->p1 (x1, y1), q1->p2 (x2, y2), q1->q2 (x3, y3) + x1 = p1.x - q1.x; + y1 = p1.y - q1.y; + x2 = p2.x - q1.x; + 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; + return false; + }; + + // If lines are intersecting with each other, the relative location should be: + // a and b lie in different sides of segment c->d + // c and d lie in different sides of segment a->b if (twoSided(a, b, c, d) && twoSided(c, d, a, b)) return true; return false; } -bool lineIntersectPolygon(const Point& p1, - const Point& p2, - const Polygon& polygon) { +bool lineIntersectPolygon(const Point& p1, const Point& p2, const Polygon& polygon) { for (auto ring : polygon) { auto length = ring.size(); // loop through every edge of the ring @@ -64,26 +54,7 @@ bool lineIntersectPolygon(const Point& p1, } return false; } -} - -void printPolygon(const Polygon& polygon) { - mbgl::Log::Debug(mbgl::Event::General, "-------Print Polygon------"); - for (auto ring : polygon) { - auto length = ring.size(); - mbgl::Log::Debug(mbgl::Event::General, "-------Print New ring with size: %d ------", length); - // loop through every edge of the ring - for (std::size_t i = 0; i < length - 1; ++i) { - mbgl::Log::Debug(mbgl::Event::General, "point [%.15f, %.15f],", ring[i].x, ring[i].y); - } - } -} - -void printLine(const LineString& lineString) { - mbgl::Log::Debug(mbgl::Event::General, "-------Print LineString------"); - for (std::size_t i = 0; i < lineString.size(); ++i) { - mbgl::Log::Debug(mbgl::Event::General, "point [%.15f, %.15f],", lineString[i].x, lineString[i].y); - } -} +} // namespace // ray casting algorithm for detecting if point is in polygon bool pointWithinPolygon(const Point& point, const Polygon& polygon) { @@ -107,14 +78,11 @@ bool pointWithinPolygons(const Point& point, const MultiPolygon& return false; } - -bool lineStringWithinPolygon(const LineString& line, - const Polygon& polygon) { +bool lineStringWithinPolygon(const LineString& line, const Polygon& polygon) { const auto length = line.size(); - // First, check if endpoints of line are all inside polygon + // First, check if geometry points of line segments are all inside polygon for (std::size_t i = 0; i < length; ++i) { if (!pointWithinPolygon(line[i], polygon)) { - mbgl::Log::Debug(mbgl::Event::General, "point %.15f, %.15f is not inside polygon", line[i].x, line[i].y); return false; } } @@ -122,12 +90,6 @@ bool lineStringWithinPolygon(const LineString& line, // Second, check if there is line segment intersecting polygon edge for (std::size_t i = 0; i < length - 1; ++i) { if (lineIntersectPolygon(line[i], line[i + 1], polygon)) { - mbgl::Log::Debug(mbgl::Event::General, - "---------line [%.15f, %.15f] to [%.15f, %.15f] is not inside polygon", - line[i].x, - line[i].y, - line[i + 1].x, - line[i + 1].y); return false; } } @@ -140,4 +102,4 @@ bool lineStringWithinPolygons(const LineString& line, const MultiPolygon } return false; } -} +} // namespace mbgl diff --git a/src/mbgl/util/geometry_within.hpp b/src/mbgl/util/geometry_within.hpp index fe9312cd4a..86658ecc83 100644 --- a/src/mbgl/util/geometry_within.hpp +++ b/src/mbgl/util/geometry_within.hpp @@ -3,17 +3,11 @@ namespace mbgl { -void printPolygon(const Polygon& polygon); - -void printLine(const LineString& lineString); - -// ray casting algorithm for detecting if point is in polygon bool pointWithinPolygon(const Point& point, const Polygon& polygon); bool pointWithinPolygons(const Point& point, const MultiPolygon& polygons); -bool lineStringWithinPolygon(const LineString& lineString, - const Polygon& polygon); +bool lineStringWithinPolygon(const LineString& lineString, const Polygon& polygon); bool lineStringWithinPolygons(const LineString& line, const MultiPolygon& polygons); -} +} // namespace mbgl -- cgit v1.2.1