summaryrefslogtreecommitdiff
path: root/test/style/property_expression.test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/style/property_expression.test.cpp')
-rw-r--r--test/style/property_expression.test.cpp370
1 files changed, 369 insertions, 1 deletions
diff --git a/test/style/property_expression.test.cpp b/test/style/property_expression.test.cpp
index 570ba4a6f3..c584d64741 100644
--- a/test/style/property_expression.test.cpp
+++ b/test/style/property_expression.test.cpp
@@ -7,6 +7,9 @@
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/format_section_override.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <mbgl/util/io.hpp>
+
#include <sstream>
using namespace mbgl;
@@ -395,7 +398,7 @@ TEST(PropertyExpression, WithinExpressionAntiMeridian) {
// evaluation test with line geometries
{
- static const std::string polygon1 = R"data(
+ const std::string polygon1 = R"data(
{
"type": "Polygon",
"coordinates": [[[-190, 0], [-178, 0], [-178, 10], [-190, 10], [-190, 0]]]
@@ -461,3 +464,368 @@ TEST(PropertyExpression, WithinExpressionAntiMeridian) {
EXPECT_FALSE(evaluatedResult);
}
}
+
+TEST(PropertyExpression, DistanceExpression) {
+ static const double invalidResult = std::numeric_limits<double>::quiet_NaN();
+ static const CanonicalTileID canonicalTileID(15, 18653, 9484);
+ // Parsing error with invalid geojson source
+ {
+ // geoJSON source must be Point or LineString.
+ const std::string invalidGeoSource = R"({
+ "type": "Polygon",
+ "coordinates": [[[0, 0], [0, 5], [5, 5], [5, 0], [0, 0]]]
+ })";
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << invalidGeoSource << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_FALSE(expression);
+ }
+
+ // Parsing error with invalid unit
+ {
+ const std::string invalidGeoSource = R"({
+ "type": "Point",
+ "coordinates": [0, 0],
+ })";
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << invalidGeoSource << std::string(R"(, "InvalidUnits"])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_FALSE(expression);
+ }
+
+ // Evaluation test with non-supported geometry type
+ {
+ const std::string pointGeoSource = R"({
+ "type": "Point",
+ "coordinates":
+ [
+ 24.938492774963375,
+ 60.16980226227959
+ ]
+ })";
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ Polygon<double> testRing{{{24.937505722045895, 60.16815846879986},
+ {24.940595626831055, 60.16815846879986},
+ {24.940595626831055, 60.169268572114106},
+ {24.937505722045895, 60.169268572114106},
+ {24.937505722045895, 60.16815846879986}}};
+ auto geoPoly = convertGeometry(testRing, canonicalTileID);
+ StubGeometryTileFeature polyFeature(FeatureType::Polygon, geoPoly);
+
+ // return evaluation error
+ auto evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&polyFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_TRUE(std::isnan(evaluatedResult));
+ }
+
+ // Evaluation test with Point to Point distance by using different units
+ {
+ const std::string pointGeoSource = R"({
+ "type": "Point",
+ "coordinates":
+ [
+ 24.938492774963375,
+ 60.16980226227959
+ ]
+ })";
+
+ Point<double> featurePoint{24.931159615516663, 60.16733387258923};
+ auto geoPoint = convertGeometry(featurePoint, canonicalTileID);
+ StubGeometryTileFeature pointFeature(FeatureType::Point, geoPoint);
+
+ std::stringstream ss;
+
+ // Default Unit: Meters
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ auto evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(491.307, evaluatedResult, 0.01);
+
+ // Unit: Meters
+ ss.str(std::string());
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"(, "Meters" ])");
+ expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ propExpr = std::move(expression);
+
+ evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(491.307, evaluatedResult, 0.01);
+
+ // Unit: Kilometers
+ ss.str(std::string());
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"(, "Kilometers" ])");
+ expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ propExpr = std::move(expression);
+
+ evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(0.491307, evaluatedResult, 0.00001);
+
+ // Unit: Miles
+ ss.str(std::string());
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"(, "Miles" ])");
+ expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ propExpr = std::move(expression);
+
+ evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(0.305284, evaluatedResult, 0.00001);
+
+ // Unit: NauticalMiles
+ ss.str(std::string());
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"(, "NauticalMiles" ])");
+ expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ propExpr = std::move(expression);
+
+ evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(0.265284, evaluatedResult, 0.00001);
+
+ // Unit: Yards
+ ss.str(std::string());
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"(, "Yards" ])");
+ expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ propExpr = std::move(expression);
+
+ evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(537.299, evaluatedResult, 0.01);
+
+ // Unit: Feet
+ ss.str(std::string());
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"(, "Feet" ])");
+ expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ propExpr = std::move(expression);
+
+ evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(1611.898, evaluatedResult, 0.01);
+
+ // Unit: Inches
+ ss.str(std::string());
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"(, "Inches" ])");
+ expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ propExpr = std::move(expression);
+
+ evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&pointFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(19342.781, evaluatedResult, 0.01);
+ }
+
+ // Evaluation test with Point to MultiPoint distance
+ {
+ const std::string pointGeoSource = R"({
+ "type": "Point",
+ "coordinates":
+ [
+ 24.938492774963375,
+ 60.16980226227959
+ ]
+ })";
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ MultiPoint<double> featurePoint{{24.931159615516663, 60.16733387258923},
+ {24.936089515686035, 60.169033745694826}};
+ auto geoPoint = convertGeometry(featurePoint, canonicalTileID);
+ StubGeometryTileFeature feature(FeatureType::Point, geoPoint);
+
+ auto evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&feature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(158.541, evaluatedResult, 0.01);
+ }
+
+ // Evaluation test with Point to LineString distance
+ {
+ const std::string pointGeoSource = R"({
+ "type": "Point",
+ "coordinates":
+ [
+ 24.938492774963375,
+ 60.16980226227959
+ ]
+ })";
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ LineString<double> line{{24.93621826171875, 60.17131789507754},
+ {24.941453933715817, 60.170229208170014},
+ {24.941110610961914, 60.16850004304534}};
+ auto geoLine = convertGeometry(line, canonicalTileID);
+ StubGeometryTileFeature lineFeature(FeatureType::LineString, geoLine);
+
+ auto evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&lineFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(107.211, evaluatedResult, 0.01);
+ }
+
+ // Evaluation test with Point to MultiLineString distance
+ {
+ const std::string pointGeoSource = R"({
+ "type": "Point",
+ "coordinates":
+ [
+ 24.938492774963375,
+ 60.16980226227959
+ ]
+ })";
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << pointGeoSource << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ MultiLineString<double> lines{
+ {{24.93621826171875, 60.17131789507754},
+ {24.941453933715817, 60.170229208170014},
+ {24.941110610961914, 60.16850004304534}},
+ {{24.937773942947388, 60.16940199546824}, {24.933900833129883, 60.17007977773949}}};
+ auto geoLine = convertGeometry(lines, canonicalTileID);
+ StubGeometryTileFeature lineFeature(FeatureType::LineString, geoLine);
+
+ auto evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&lineFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(59.845, evaluatedResult, 0.01);
+ }
+
+ const auto getFeature = [](const std::string &name, FeatureType type, const CanonicalTileID &canonical) {
+ const auto geometryInput = mbgl::util::read_file(std::string("test/fixtures/geometry_data/" + name));
+ mapbox::geojson::geojson geojson{mapbox::geojson::parse(geometryInput)};
+ const auto &geometry = geojson.match(
+ [](const mapbox::geometry::geometry<double> &geometrySet) { return mbgl::Feature(geometrySet).geometry; },
+ [](const mapbox::feature::feature<double> &feature) { return mbgl::Feature(feature).geometry; },
+ [](const mapbox::feature::feature_collection<double> &features) {
+ return mbgl::Feature(features.front()).geometry;
+ },
+ [](const auto &) { return mapbox::geometry::empty(); });
+ return StubGeometryTileFeature(type, convertGeometry(geometry, canonical));
+ };
+
+ // Evaluation test with MultiPoint to MultiPoint distance
+ {
+ const auto multiPoints1 = mbgl::util::read_file("test/fixtures/geometry_data/multi_point_1.geojson");
+ const auto multiPointsFeature = getFeature("multi_point_2.geojson", FeatureType::Point, canonicalTileID);
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << multiPoints1 << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ auto evaluatedResult = propExpr.evaluate(
+ EvaluationContext(&multiPointsFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(283.60, evaluatedResult, 0.1);
+ }
+
+ // Evaluation test with MultiPoint to LineString distance
+ {
+ const auto multiPoints1 = mbgl::util::read_file("test/fixtures/geometry_data/multi_point_1.geojson");
+ const auto multiLineFeature = getFeature("line_string_2.geojson", FeatureType::LineString, canonicalTileID);
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << multiPoints1 << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ auto evaluatedResult = propExpr.evaluate(
+ EvaluationContext(&multiLineFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(258.691, evaluatedResult, 0.01);
+
+ // ----------------- switch feature and argument -----------------
+ const auto multiLine2 = mbgl::util::read_file("test/fixtures/geometry_data/line_string_2.geojson");
+ const auto multiPointsFeature = getFeature("multi_point_1.geojson", FeatureType::Point, canonicalTileID);
+ std::stringstream ss1;
+ ss1 << std::string(R"(["distance", )") << multiLine2 << std::string(R"( ])");
+ auto expression1 = createExpression(ss1.str().c_str());
+ ASSERT_TRUE(expression1);
+ PropertyExpression<double> propExpr1(std::move(expression1));
+
+ auto evaluatedResult1 = propExpr1.evaluate(
+ EvaluationContext(&multiPointsFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(258.691, evaluatedResult1, 0.01);
+ }
+
+ // Evaluation test with LineString to LineString distance
+ {
+ const auto lineString1 = mbgl::util::read_file("test/fixtures/geometry_data/line_string_1.geojson");
+ const auto lineFeature = getFeature("line_string_2.geojson", FeatureType::LineString, canonicalTileID);
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << lineString1 << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ auto evaluatedResult =
+ propExpr.evaluate(EvaluationContext(&lineFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(180.408, evaluatedResult, 0.01);
+ }
+
+ // Evaluation test with MultiPoints to MutltiLineString distance
+ {
+ const auto multiPoints = mbgl::util::read_file("test/fixtures/geometry_data/multi_point_2.geojson");
+ const auto multiLineFeature =
+ getFeature("multi_line_string_1.geojson", FeatureType::LineString, canonicalTileID);
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << multiPoints << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ auto evaluatedResult = propExpr.evaluate(
+ EvaluationContext(&multiLineFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(937.632, evaluatedResult, 0.01);
+ }
+
+ // Evaluation test with LineString to MutltiLineString distance
+ {
+ const auto LineString1 = mbgl::util::read_file("test/fixtures/geometry_data/line_string_1.geojson");
+ const auto multiLineFeature =
+ getFeature("multi_line_string_2.geojson", FeatureType::LineString, canonicalTileID);
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << LineString1 << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ auto evaluatedResult = propExpr.evaluate(
+ EvaluationContext(&multiLineFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(17.511, evaluatedResult, 0.01);
+ }
+
+ // Evaluation test with MultiLineString to MutltiLineString distance
+ {
+ const auto multiLineString1 = mbgl::util::read_file("test/fixtures/geometry_data/multi_line_string_1.geojson");
+ const auto multiLineFeature =
+ getFeature("multi_line_string_2.geojson", FeatureType::LineString, canonicalTileID);
+ std::stringstream ss;
+ ss << std::string(R"(["distance", )") << multiLineString1 << std::string(R"( ])");
+ auto expression = createExpression(ss.str().c_str());
+ ASSERT_TRUE(expression);
+ PropertyExpression<double> propExpr(std::move(expression));
+
+ auto evaluatedResult = propExpr.evaluate(
+ EvaluationContext(&multiLineFeature).withCanonicalTileID(&canonicalTileID), invalidResult);
+ EXPECT_NEAR(384.109, evaluatedResult, 0.01);
+ }
+}