From 695475e77b2cbab8706d24cbce0c4418bf4bdff5 Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Mon, 10 Aug 2026 16:02:44 +0200 Subject: [PATCH 1/8] working reattaching getWKT for Point --- geo/Geo.cpp | 16 ++++++++++++++++ geo/Geo.h | 7 +++++-- geo/Geo.tpp | 14 ++++++++------ tests/GeoTestCRS.cpp | 16 ++++++++++++++++ 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/geo/Geo.cpp b/geo/Geo.cpp index 1f41593..d047305 100644 --- a/geo/Geo.cpp +++ b/geo/Geo.cpp @@ -127,6 +127,22 @@ util::geo::CRSType util::geo::getCRSType(const char* c, const char** endr) { return UNSUPPORTED; } +// _____________________________________________________________________________ +std::string util::geo::getCrsIri(util::geo::CRSType sourceCRS) { + switch (sourceCRS) + { + case CRS84: + // Not attaching IRI as CRS84 is the default. + return ""; + case WGS84: + return " "; + case WEB_MERCATOR: + return " "; + default: + throw std::runtime_error("Trying to get CRS IRI for unsupported CRS type."); + } +} + // _____________________________________________________________________________ double util::geo::distToSegment(double lax, double lay, double lbx, double lby, double px, double py) { diff --git a/geo/Geo.h b/geo/Geo.h index 518229d..0c53dac 100644 --- a/geo/Geo.h +++ b/geo/Geo.h @@ -298,11 +298,14 @@ RotatedBox shrink(const RotatedBox& b, double d); bool doubleEq(double a, double b); +// This is used by 'getWKT' to attach the CRS IRI for a specified CRS. +std::string getCrsIri(CRSType sourceCRS); + template -std::string getWKT(const Point& p, uint16_t prec); +std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS = CRS84); template -std::string getWKT(const Point& p); +std::string getWKT(const Point& p, CRSType sourceCRS = CRS84); template std::string getWKT(const std::vector>& p, uint16_t prec); diff --git a/geo/Geo.tpp b/geo/Geo.tpp index 529e59c..21c30d6 100644 --- a/geo/Geo.tpp +++ b/geo/Geo.tpp @@ -483,21 +483,23 @@ RotatedBox shrink(const RotatedBox& b, double d) { // _____________________________________________________________________________ template -std::string getWKT(const Point& p, uint16_t prec) { +std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS) { + // Project from internal CRS84 to original 'sourceCRS'. + auto proj = projectToCRS(p, CRS84, sourceCRS); std::string ret; - ret = "POINT("; + ret = getCrsIri(sourceCRS) + "POINT("; ret.reserve(6 + prec + 3 + prec + 3 + 1); - ret.append(formatFloat(p.getX(), prec)); + ret.append(formatFloat(proj.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(p.getY(), prec)); + ret.append(formatFloat(proj.getY(), prec)); ret.push_back(')'); return ret; } // _____________________________________________________________________________ template -std::string getWKT(const Point& p) { - return getWKT(p, 6); +std::string getWKT(const Point& p, CRSType sourceCRS) { + return getWKT(p, 6, sourceCRS); } // _____________________________________________________________________________ diff --git a/tests/GeoTestCRS.cpp b/tests/GeoTestCRS.cpp index c8e8b9c..0c2a3e5 100644 --- a/tests/GeoTestCRS.cpp +++ b/tests/GeoTestCRS.cpp @@ -543,4 +543,20 @@ void GeoTest::testCRS() { "GEOMETRYCOLLECTION(MULTIPOINT(7 47,8 48),MULTIPOLYGON(((7 47,8 47,8 48,7 48,7 47))," "((8 48,9 48,9 49,8 49,8 48))),MULTILINESTRING((7 47,8 47),(8 48,7 48)))"); } + + { + // Test correct reattaching of CRS IRIs. + + auto projCRS84 = util::geo::pointFromWKT( + " POINT(2 3)"); + TEST(getWKT(projCRS84, util::geo::CRSType::CRS84), ==, "POINT(2 3)"); + + auto projWGS84 = util::geo::pointFromWKT( + " POINT(3 2)"); + TEST(getWKT(projWGS84, util::geo::CRSType::WGS84), ==, " POINT(3 2)"); + + auto projWebMerc = util::geo::pointFromWKT( + " POINT(222638.98158654 334111.17140195)"); + TEST(getWKT(projWebMerc, util::geo::CRSType::WEB_MERCATOR), ==, " POINT(222638.98158654 334111.17140195)"); + } } From b75589f9cfe9887b5fde47c03d7095ec39c13fe2 Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Thu, 13 Aug 2026 13:02:18 +0200 Subject: [PATCH 2/8] Adjusted getWKT for all geometries --- geo/Geo.h | 31 ++++++----- geo/Geo.tpp | 125 +++++++++++++++++++++++-------------------- tests/GeoTestCRS.cpp | 120 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 204 insertions(+), 72 deletions(-) diff --git a/geo/Geo.h b/geo/Geo.h index 0c53dac..d1d3f7b 100644 --- a/geo/Geo.h +++ b/geo/Geo.h @@ -301,29 +301,32 @@ bool doubleEq(double a, double b); // This is used by 'getWKT' to attach the CRS IRI for a specified CRS. std::string getCrsIri(CRSType sourceCRS); +// The 'getWKT' functions now attach the original CRS IRI (specified by 'sourceCRS'). +// By default or for 'sourceCRS == CRS84' no IRI will be attached. +// As the collection uses the 'getWKT' function of the subgeometries, the IRIs for these geometries are hidden (via 'hideIri'). template -std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS = CRS84); +std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Point& p, CRSType sourceCRS = CRS84); +std::string getWKT(const Point& p, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& p, uint16_t prec); +std::string getWKT(const std::vector>& p, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& p); +std::string getWKT(const std::vector>& p, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Line& l, uint16_t prec); +std::string getWKT(const Line& l, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Line& l); +std::string getWKT(const Line& l, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls, uint16_t prec); +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls); +std::string getWKT(const std::vector>& ls, CRSType sourceCRS = CRS84, bool hideIri = false); template std::string getWKT(const XSortedPolygon& ls, uint16_t prec); @@ -344,22 +347,22 @@ template std::string getWKT(const Box& l); template -std::string getWKT(const Polygon& p, uint16_t prec); +std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Polygon& p); +std::string getWKT(const Polygon& p, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls, uint16_t prec); +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls); +std::string getWKT(const std::vector>& ls, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Collection& coll, uint16_t prec); +std::string getWKT(const Collection& coll, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Collection& coll); +std::string getWKT(const Collection& coll, CRSType sourceCRS = CRS84, bool hideIri = false); template bool contains(const Point& p, const Box& box); diff --git a/geo/Geo.tpp b/geo/Geo.tpp index 21c30d6..23ccc1e 100644 --- a/geo/Geo.tpp +++ b/geo/Geo.tpp @@ -483,11 +483,11 @@ RotatedBox shrink(const RotatedBox& b, double d) { // _____________________________________________________________________________ template -std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS) { +std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS, bool hideIri) { // Project from internal CRS84 to original 'sourceCRS'. auto proj = projectToCRS(p, CRS84, sourceCRS); std::string ret; - ret = getCrsIri(sourceCRS) + "POINT("; + ret = hideIri ? "POINT(" : getCrsIri(sourceCRS) + "POINT("; ret.reserve(6 + prec + 3 + prec + 3 + 1); ret.append(formatFloat(proj.getX(), prec)); ret.push_back(' '); @@ -498,20 +498,21 @@ std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS) { // _____________________________________________________________________________ template -std::string getWKT(const Point& p, CRSType sourceCRS) { - return getWKT(p, 6, sourceCRS); +std::string getWKT(const Point& p, CRSType sourceCRS, bool hideIri) { + return getWKT(p, 6, sourceCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& p, uint16_t prec) { - std::string ret = "MULTIPOINT("; +std::string getWKT(const std::vector>& p, uint16_t prec, CRSType sourceCRS, bool hideIri) { + std::string ret = hideIri ? "MULTIPOINT(" : getCrsIri(sourceCRS) + "MULTIPOINT("; ret.reserve(10 + 1 + p.size() * (prec + 3) * 2 + 1); for (size_t i = 0; i < p.size(); i++) { if (i) ret.push_back(','); - ret.append(formatFloat(p[i].getX(), prec)); + auto point = projectToCRS(p[i], CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(p[i].getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } ret.push_back(')'); return ret; @@ -519,20 +520,21 @@ std::string getWKT(const std::vector>& p, uint16_t prec) { // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& p) { - return getWKT(p, 6); +std::string getWKT(const std::vector>& p, CRSType sourceCRS, bool hideIri) { + return getWKT(p, 6, sourceCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const Line& l, uint16_t prec) { - std::string ret = "LINESTRING("; +std::string getWKT(const Line& l, uint16_t prec, CRSType sourceCRS, bool hideIri) { + std::string ret = hideIri ? "LINESTRING(" : getCrsIri(sourceCRS) + "LINESTRING("; ret.reserve(10 + 1 + l.size() * (prec + 3) * 2 + 1); for (size_t i = 0; i < l.size(); i++) { if (i) ret.push_back(','); - ret.append(formatFloat(l[i].getX(), prec)); + auto point = projectToCRS(l[i], CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(l[i].getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } ret.push_back(')'); return ret; @@ -540,14 +542,14 @@ std::string getWKT(const Line& l, uint16_t prec) { // _____________________________________________________________________________ template -std::string getWKT(const Line& l) { - return getWKT(l, 6); +std::string getWKT(const Line& l, CRSType sourceCRS, bool hideIri) { + return getWKT(l, 6, sourceCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls, uint16_t prec) { - std::string ret = "MULTILINESTRING("; +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS, bool hideIri) { + std::string ret = hideIri ? "MULTILINESTRING(" : getCrsIri(sourceCRS) + "MULTILINESTRING("; if (ls.size()) ret.reserve(15 + 2 + ls[0].size() * (prec + 3) * 2 + 2); @@ -556,9 +558,10 @@ std::string getWKT(const std::vector>& ls, uint16_t prec) { ret.push_back('('); for (size_t i = 0; i < ls[j].size(); i++) { if (i) ret.push_back(','); - ret.append(formatFloat(ls[j][i].getX(), prec)); + auto point = projectToCRS(ls[j][i], CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(ls[j][i].getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } ret.push_back(')'); } @@ -569,8 +572,8 @@ std::string getWKT(const std::vector>& ls, uint16_t prec) { // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls) { - return getWKT(ls, 6); +std::string getWKT(const std::vector>& ls, CRSType sourceCRS, bool hideIri) { + return getWKT(ls, 6, sourceCRS, hideIri); } // _____________________________________________________________________________ @@ -656,23 +659,25 @@ std::string getWKT(const Box& l) { // _____________________________________________________________________________ template -std::string getWKT(const Polygon& p, uint16_t prec) { +std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS, bool hideIri) { if (p.getOuter().size() == 0) return "POLYGON()"; - std::string ret = "POLYGON(("; + std::string ret = hideIri ? "POLYGON((" : getCrsIri(sourceCRS) + "POLYGON(("; ret.reserve(7 + 2 + p.getOuter().size() * (prec + 3) * 2 + 2); for (size_t i = 0; i < p.getOuter().size(); i++) { if (i > 0) ret.push_back(','); - ret.append(formatFloat(p.getOuter()[i].getX(), prec)); + auto point = projectToCRS(p.getOuter()[i], CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(p.getOuter()[i].getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } if (p.getOuter().front() != p.getOuter().back()) { ret.push_back(','); - ret.append(formatFloat(p.getOuter().front().getX(), prec)); + auto point = projectToCRS(p.getOuter().front(), CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(p.getOuter().front().getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } ret.push_back(')'); @@ -680,16 +685,18 @@ std::string getWKT(const Polygon& p, uint16_t prec) { ret.append(",("); for (size_t i = 0; i < inner.size(); i++) { if (i > 0) ret.push_back(','); - ret.append(formatFloat(inner[i].getX(), prec)); + auto point = projectToCRS(inner[i], CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(inner[i].getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } if (inner.front() != inner.back()) { ret.push_back(','); - ret.append(formatFloat(inner.front().getX(), prec)); + auto point = projectToCRS(inner.front(), CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(inner.front().getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } ret.push_back(')'); } @@ -699,14 +706,14 @@ std::string getWKT(const Polygon& p, uint16_t prec) { // _____________________________________________________________________________ template -std::string getWKT(const Polygon& p) { - return getWKT(p, 6); +std::string getWKT(const Polygon& p, CRSType sourceCRS, bool hideIri) { + return getWKT(p, 6, sourceCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls, uint16_t prec) { - std::string ret = "MULTIPOLYGON("; +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS, bool hideIri) { + std::string ret = hideIri ? "MULTIPOLYGON(" : getCrsIri(sourceCRS) + "MULTIPOLYGON("; if (ls.size()) ret.reserve(12 + 2 + ls[0].getOuter().size() * (prec + 3) * 2 + 2); @@ -716,16 +723,18 @@ std::string getWKT(const std::vector>& ls, uint16_t prec) { ret.push_back('('); for (size_t i = 0; i < ls[j].getOuter().size(); i++) { if (i > 0) ret.push_back(','); - ret.append(formatFloat(ls[j].getOuter()[i].getX(), prec)); + auto point = projectToCRS(ls[j].getOuter()[i], CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(ls[j].getOuter()[i].getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } if (ls[j].getOuter().front() != ls[j].getOuter().back()) { ret.push_back(','); - ret.append(formatFloat(ls[j].getOuter().front().getX(), prec)); + auto point = projectToCRS(ls[j].getOuter().front(), CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(ls[j].getOuter().front().getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } ret.push_back(')'); @@ -734,15 +743,17 @@ std::string getWKT(const std::vector>& ls, uint16_t prec) { ret.push_back('('); for (size_t i = 0; i < inner.size(); i++) { if (i > 0) ret.push_back(','); - ret.append(formatFloat(inner[i].getX(), prec)); + auto point = projectToCRS(inner[i], CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(inner[i].getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } if (inner.front() != inner.back()) { ret.push_back(','); - ret.append(formatFloat(inner.front().getX(), prec)); + auto point = projectToCRS(inner.front(), CRS84, sourceCRS); + ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(inner.front().getY(), prec)); + ret.append(formatFloat(point.getY(), prec)); } ret.push_back(')'); } @@ -755,27 +766,27 @@ std::string getWKT(const std::vector>& ls, uint16_t prec) { // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls) { - return getWKT(ls, 6); +std::string getWKT(const std::vector>& ls, CRSType sourceCRS, bool hideIri) { + return getWKT(ls, 6, sourceCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const Collection& coll, uint16_t prec) { - std::string ret = "GEOMETRYCOLLECTION("; +std::string getWKT(const Collection& coll, uint16_t prec, CRSType sourceCRS, bool hideIri) { + std::string ret = hideIri ? "GEOMETRYCOLLECTION(" : getCrsIri(sourceCRS) + "GEOMETRYCOLLECTION("; std::string delim = ""; for (const auto& g : coll) { ret += delim; delim = ","; - if (g.getType() == 0) ret += util::geo::getWKT(g.getPoint(), prec); - if (g.getType() == 1) ret += util::geo::getWKT(g.getLine(), prec); - if (g.getType() == 2) ret += util::geo::getWKT(g.getPolygon(), prec); - if (g.getType() == 3) ret += util::geo::getWKT(g.getMultiLine(), prec); - if (g.getType() == 4) ret += util::geo::getWKT(g.getMultiPolygon(), prec); - if (g.getType() == 5) ret += util::geo::getWKT(g.getCollection(), prec); - if (g.getType() == 6) ret += util::geo::getWKT(g.getMultiPoint(), prec); + if (g.getType() == 0) ret += util::geo::getWKT(g.getPoint(), prec, sourceCRS, true); + if (g.getType() == 1) ret += util::geo::getWKT(g.getLine(), prec, sourceCRS, true); + if (g.getType() == 2) ret += util::geo::getWKT(g.getPolygon(), prec, sourceCRS, true); + if (g.getType() == 3) ret += util::geo::getWKT(g.getMultiLine(), prec, sourceCRS, true); + if (g.getType() == 4) ret += util::geo::getWKT(g.getMultiPolygon(), prec, sourceCRS, true); + if (g.getType() == 5) ret += util::geo::getWKT(g.getCollection(), prec, sourceCRS, true); + if (g.getType() == 6) ret += util::geo::getWKT(g.getMultiPoint(), prec, sourceCRS, true); } return ret + ")"; @@ -783,8 +794,8 @@ std::string getWKT(const Collection& coll, uint16_t prec) { // _____________________________________________________________________________ template -std::string getWKT(const Collection& coll) { - return getWKT(coll, 6); +std::string getWKT(const Collection& coll, CRSType sourceCRS, bool hideIri) { + return getWKT(coll, 6, sourceCRS, hideIri); } // _____________________________________________________________________________ diff --git a/tests/GeoTestCRS.cpp b/tests/GeoTestCRS.cpp index 0c2a3e5..6b00d7a 100644 --- a/tests/GeoTestCRS.cpp +++ b/tests/GeoTestCRS.cpp @@ -547,6 +547,7 @@ void GeoTest::testCRS() { { // Test correct reattaching of CRS IRIs. + // POINT auto projCRS84 = util::geo::pointFromWKT( " POINT(2 3)"); TEST(getWKT(projCRS84, util::geo::CRSType::CRS84), ==, "POINT(2 3)"); @@ -557,6 +558,123 @@ void GeoTest::testCRS() { auto projWebMerc = util::geo::pointFromWKT( " POINT(222638.98158654 334111.17140195)"); - TEST(getWKT(projWebMerc, util::geo::CRSType::WEB_MERCATOR), ==, " POINT(222638.98158654 334111.17140195)"); + // The point will change a bit due to the reprojecting. + TEST(getWKT(projWebMerc, util::geo::CRSType::WEB_MERCATOR), ==, " POINT(222638.981587 334111.171402)"); + + // MULTIPOINT + auto projCRS84_2 = util::geo::multiPointFromWKT( + " MULTIPOINT((7 47), (8 48))"); + TEST(getWKT(projCRS84_2, util::geo::CRSType::CRS84), ==, "MULTIPOINT(7 47,8 48)"); + + auto projWGS84_2 = util::geo::multiPointFromWKT( + " MULTIPOINT((47 7), (48 8))"); + TEST(getWKT(projWGS84_2, util::geo::CRSType::WGS84), ==, " MULTIPOINT(47 7,48 8)"); + + auto projWebMerc_2 = util::geo::multiPointFromWKT( + " MULTIPOINT((779236.435552915 5942074.072431109)," + " (890555.9263461885 6106854.834885074))"); + TEST(getWKT(projWebMerc_2, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTIPOINT(779236.435553 5942074.072431," + "890555.926346 6106854.834885)"); + + // Line + auto projCRS84_3 = util::geo::lineFromWKT( + " LINESTRING(7 47, 7 48)"); + TEST(getWKT(projCRS84_3, util::geo::CRSType::CRS84), ==, "LINESTRING(7 47,7 48)"); + + auto projWGS84_3 = util::geo::lineFromWKT( + " LINESTRING(47 7, 48 7)"); + TEST(getWKT(projWGS84_3, util::geo::CRSType::WGS84), ==, " LINESTRING(47 7,48 7)"); + + + auto projWebMerc_3 = util::geo::lineFromWKT( + " LINESTRING(779236.435552915 " + "5942074.072431109, 779236.435552915 6106854.834885074)"); + TEST(getWKT(projWebMerc_3, util::geo::CRSType::WEB_MERCATOR), ==, + " LINESTRING(779236.435553 " + "5942074.072431,779236.435553 6106854.834885)"); + + // MULTILINESTRING + auto projCRS8_4 = util::geo::multiLineFromWKT( + " MULTILINESTRING((7 47, 8 47), (8 48, 7 48))"); + TEST(getWKT(projCRS8_4, util::geo::CRSType::CRS84), ==, "MULTILINESTRING((7 47,8 47),(8 48,7 48))"); + + auto projWGS8_4 = util::geo::multiLineFromWKT( + " MULTILINESTRING((47 7, 47 8), (48 8, 48 7))"); + TEST(getWKT(projWGS8_4, util::geo::CRSType::WGS84), ==, " MULTILINESTRING((47 7,47 8),(48 8,48 7))"); + + auto projWebMerc_4 = util::geo::multiLineFromWKT( + " MULTILINESTRING((779236.435552915 5942074.072431109," + " 890555.9263461885 5942074.072431109), (890555.9263461885 6106854.834885074, 779236.435552915 6106854.834885074))"); + TEST(getWKT(projWebMerc_4, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTILINESTRING((779236.435553 5942074.072431," + "890555.926346 5942074.072431),(890555.926346 6106854.834885,779236.435553 6106854.834885))"); + + // POLYGON + auto projCRS84_5 = util::geo::polygonFromWKT( + " POLYGON((7 47, 8 47, 8 48, 7 48, 7 47))"); + TEST(getWKT(projCRS84_5, util::geo::CRSType::CRS84), ==, "POLYGON((7 47,8 47,8 48,7 48,7 47))"); + + auto projWGS84_5 = util::geo::polygonFromWKT( + " POLYGON((47 7, 47 8, 48 8, 48 7, 47 7))"); + TEST(getWKT(projWGS84_5, util::geo::CRSType::WGS84), ==, " POLYGON((47 7,47 8,48 8,48 7,47 7))"); + + auto projWebMerc_5 = util::geo::polygonFromWKT( + " POLYGON((779236.435552915 5942074.072431109," + " 890555.9263461885 5942074.072431109, 890555.9263461885 6106854.834885074, 779236.435552915" + " 6106854.834885074, 779236.435552915 5942074.072431109))"); + TEST(getWKT(projWebMerc_5, util::geo::CRSType::WEB_MERCATOR), ==, + " POLYGON((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553" + " 6106854.834885,779236.435553 5942074.072431))"); + + // MULTIPOLYGON + auto projCRS84_6 = util::geo::multiPolygonFromWKT( + " MULTIPOLYGON(((7 47, 8 47, 8 48, 7 48, 7 47))," + " ((8 48, 9 48, 9 49, 8 49, 8 48)))"); + TEST(getWKT(projCRS84_6, util::geo::CRSType::CRS84), ==, "MULTIPOLYGON(((7 47,8 47,8 48,7 48,7 47)),((8 48,9 48,9 49,8 49,8 48)))"); + + auto projWGS84_6 = util::geo::multiPolygonFromWKT( + " MULTIPOLYGON(((47 7, 47 8, 48 8, 48 7, 47 7))," + " ((48 8, 48 9, 49 9, 49 8, 48 8)))"); + TEST(getWKT(projWGS84_6, util::geo::CRSType::WGS84), ==, + " MULTIPOLYGON(((47 7,47 8,48 8,48 7,47 7))," + "((48 8,48 9,49 9,49 8,48 8)))"); + + auto projWebMerc_6 = util::geo::multiPolygonFromWKT( + " MULTIPOLYGON(((779236.435552915 5942074.072431109," + " 890555.9263461885 5942074.072431109, 890555.9263461885 6106854.834885074, 779236.435552915 6106854.834885074," + " 779236.435552915 5942074.072431109)), ((890555.9263461885 6106854.834885074, 1001875.4171394621 6106854.834885074," + " 1001875.4171394621 6274861.394006576, 890555.9263461885 6274861.394006576, 890555.9263461885 6106854.834885074)))"); + TEST(getWKT(projWebMerc_6, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTIPOLYGON(((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," + "779236.435553 5942074.072431)),((890555.926346 6106854.834885,1001875.417139 6106854.834885," + "1001875.417139 6274861.394007,890555.926346 6274861.394007,890555.926346 6106854.834885)))"); + + // COLLECTION + auto projCRS84_7 = util::geo::collectionFromWKT( + " GEOMETRYCOLLECTION(POINT(7 47)," + " LINESTRING(7 47, 8 48), POLYGON((7 47, 8 47, 8 48, 7 48, 7 47)))"); + TEST(getWKT(projCRS84_7, util::geo::CRSType::CRS84), ==, + "GEOMETRYCOLLECTION(POINT(7 47),LINESTRING(7 47,8 48),POLYGON((7 47,8 47,8 48,7 48,7 47)))"); + + auto projWGS84_7 = util::geo::collectionFromWKT( + " GEOMETRYCOLLECTION(POINT(47 7), " + "LINESTRING(47 7, 48 8), POLYGON((47 7, 47 8, 48 8, 48 7, 47 7)))"); + TEST(getWKT(projWGS84_7, util::geo::CRSType::WGS84), ==, + " GEOMETRYCOLLECTION(POINT(47 7)," + "LINESTRING(47 7,48 8),POLYGON((47 7,47 8,48 8,48 7,47 7)))"); + + auto projWebMerc_7 = util::geo::collectionFromWKT( + " GEOMETRYCOLLECTION(POINT(779236.435552915 5942074.072431109)," + " LINESTRING(779236.435552915 5942074.072431109, 890555.9263461885 6106854.834885074), POLYGON((779236.435552915" + " 5942074.072431109, 890555.9263461885 5942074.072431109, 890555.9263461885 6106854.834885074, 779236.435552915 " + "6106854.834885074, 779236.435552915 5942074.072431109)))"); + TEST(getWKT(projWebMerc_7, util::geo::CRSType::WEB_MERCATOR), ==, + " GEOMETRYCOLLECTION(POINT(779236.435553 5942074.072431)," + "LINESTRING(779236.435553 5942074.072431,890555.926346 6106854.834885),POLYGON((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," + "779236.435553 5942074.072431)))"); } } From 4ca13b3adad9f1596e1f363280e9181a1e383c32 Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Tue, 18 Aug 2026 17:31:36 +0200 Subject: [PATCH 3/8] IRIs as constants --- geo/Geo.cpp | 4 ++-- geo/Geo.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/geo/Geo.cpp b/geo/Geo.cpp index d047305..638c3f0 100644 --- a/geo/Geo.cpp +++ b/geo/Geo.cpp @@ -135,9 +135,9 @@ std::string util::geo::getCrsIri(util::geo::CRSType sourceCRS) { // Not attaching IRI as CRS84 is the default. return ""; case WGS84: - return " "; + return wgs84Iri; case WEB_MERCATOR: - return " "; + return webMercIri; default: throw std::runtime_error("Trying to get CRS IRI for unsupported CRS type."); } diff --git a/geo/Geo.h b/geo/Geo.h index d1d3f7b..6f2dcbf 100644 --- a/geo/Geo.h +++ b/geo/Geo.h @@ -163,6 +163,9 @@ enum CRSType : uint8_t { WEB_MERCATOR = 3, }; +constexpr const char* wgs84Iri = " "; +constexpr const char* webMercIri = " "; + uint8_t boolArrToInt8(const std::array arr); template From fa190012741bc0a5ede918cf1e6508174753b273 Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Wed, 19 Aug 2026 14:29:44 +0200 Subject: [PATCH 4/8] Added currentCRS argument to getWKT; new tests --- geo/Geo.cpp | 4 +- geo/Geo.h | 35 +++---- geo/Geo.tpp | 94 +++++++++---------- tests/GeoTestCRS.cpp | 219 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 265 insertions(+), 87 deletions(-) diff --git a/geo/Geo.cpp b/geo/Geo.cpp index 638c3f0..c3a4028 100644 --- a/geo/Geo.cpp +++ b/geo/Geo.cpp @@ -128,8 +128,8 @@ util::geo::CRSType util::geo::getCRSType(const char* c, const char** endr) { } // _____________________________________________________________________________ -std::string util::geo::getCrsIri(util::geo::CRSType sourceCRS) { - switch (sourceCRS) +std::string util::geo::getCrsIri(util::geo::CRSType targetCRS) { + switch (targetCRS) { case CRS84: // Not attaching IRI as CRS84 is the default. diff --git a/geo/Geo.h b/geo/Geo.h index 6f2dcbf..265c7c9 100644 --- a/geo/Geo.h +++ b/geo/Geo.h @@ -302,34 +302,35 @@ RotatedBox shrink(const RotatedBox& b, double d); bool doubleEq(double a, double b); // This is used by 'getWKT' to attach the CRS IRI for a specified CRS. -std::string getCrsIri(CRSType sourceCRS); +std::string getCrsIri(CRSType targetCRS); -// The 'getWKT' functions now attach the original CRS IRI (specified by 'sourceCRS'). -// By default or for 'sourceCRS == CRS84' no IRI will be attached. +// The 'getWKT' functions now attach a given CRS IRI (specified by 'targetCRS'). +// By default or for 'targetCRS == CRS84' no IRI will be attached. +// The point will also be projected from 'currentCRS' to the 'targetCRS'. // As the collection uses the 'getWKT' function of the subgeometries, the IRIs for these geometries are hidden (via 'hideIri'). template -std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Point& p, uint16_t prec, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Point& p, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Point& p, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& p, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const std::vector>& p, uint16_t prec, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& p, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const std::vector>& p, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Line& l, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Line& l, uint16_t prec, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Line& l, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Line& l, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const std::vector>& ls, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template std::string getWKT(const XSortedPolygon& ls, uint16_t prec); @@ -350,22 +351,22 @@ template std::string getWKT(const Box& l); template -std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Polygon& p, uint16_t prec, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Polygon& p, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Polygon& p, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const std::vector>& ls, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const std::vector>& ls, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Collection& coll, uint16_t prec, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Collection& coll, uint16_t prec, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template -std::string getWKT(const Collection& coll, CRSType sourceCRS = CRS84, bool hideIri = false); +std::string getWKT(const Collection& coll, CRSType currentCRS = CRS84, CRSType targetCRS = CRS84, bool hideIri = false); template bool contains(const Point& p, const Box& box); diff --git a/geo/Geo.tpp b/geo/Geo.tpp index 23ccc1e..39446dc 100644 --- a/geo/Geo.tpp +++ b/geo/Geo.tpp @@ -483,11 +483,11 @@ RotatedBox shrink(const RotatedBox& b, double d) { // _____________________________________________________________________________ template -std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS, bool hideIri) { +std::string getWKT(const Point& p, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { // Project from internal CRS84 to original 'sourceCRS'. - auto proj = projectToCRS(p, CRS84, sourceCRS); + auto proj = projectToCRS(p, currentCRS, targetCRS); std::string ret; - ret = hideIri ? "POINT(" : getCrsIri(sourceCRS) + "POINT("; + ret = hideIri ? "POINT(" : getCrsIri(targetCRS) + "POINT("; ret.reserve(6 + prec + 3 + prec + 3 + 1); ret.append(formatFloat(proj.getX(), prec)); ret.push_back(' '); @@ -498,18 +498,18 @@ std::string getWKT(const Point& p, uint16_t prec, CRSType sourceCRS, bool hid // _____________________________________________________________________________ template -std::string getWKT(const Point& p, CRSType sourceCRS, bool hideIri) { - return getWKT(p, 6, sourceCRS, hideIri); +std::string getWKT(const Point& p, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + return getWKT(p, 6, currentCRS, targetCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& p, uint16_t prec, CRSType sourceCRS, bool hideIri) { - std::string ret = hideIri ? "MULTIPOINT(" : getCrsIri(sourceCRS) + "MULTIPOINT("; +std::string getWKT(const std::vector>& p, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + std::string ret = hideIri ? "MULTIPOINT(" : getCrsIri(targetCRS) + "MULTIPOINT("; ret.reserve(10 + 1 + p.size() * (prec + 3) * 2 + 1); for (size_t i = 0; i < p.size(); i++) { if (i) ret.push_back(','); - auto point = projectToCRS(p[i], CRS84, sourceCRS); + auto point = projectToCRS(p[i], currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -520,18 +520,18 @@ std::string getWKT(const std::vector>& p, uint16_t prec, CRSType source // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& p, CRSType sourceCRS, bool hideIri) { - return getWKT(p, 6, sourceCRS, hideIri); +std::string getWKT(const std::vector>& p, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + return getWKT(p, 6, currentCRS, targetCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const Line& l, uint16_t prec, CRSType sourceCRS, bool hideIri) { - std::string ret = hideIri ? "LINESTRING(" : getCrsIri(sourceCRS) + "LINESTRING("; +std::string getWKT(const Line& l, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + std::string ret = hideIri ? "LINESTRING(" : getCrsIri(targetCRS) + "LINESTRING("; ret.reserve(10 + 1 + l.size() * (prec + 3) * 2 + 1); for (size_t i = 0; i < l.size(); i++) { if (i) ret.push_back(','); - auto point = projectToCRS(l[i], CRS84, sourceCRS); + auto point = projectToCRS(l[i], currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -542,14 +542,14 @@ std::string getWKT(const Line& l, uint16_t prec, CRSType sourceCRS, bool hide // _____________________________________________________________________________ template -std::string getWKT(const Line& l, CRSType sourceCRS, bool hideIri) { - return getWKT(l, 6, sourceCRS, hideIri); +std::string getWKT(const Line& l, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + return getWKT(l, 6, currentCRS, targetCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS, bool hideIri) { - std::string ret = hideIri ? "MULTILINESTRING(" : getCrsIri(sourceCRS) + "MULTILINESTRING("; +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + std::string ret = hideIri ? "MULTILINESTRING(" : getCrsIri(targetCRS) + "MULTILINESTRING("; if (ls.size()) ret.reserve(15 + 2 + ls[0].size() * (prec + 3) * 2 + 2); @@ -558,7 +558,7 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType source ret.push_back('('); for (size_t i = 0; i < ls[j].size(); i++) { if (i) ret.push_back(','); - auto point = projectToCRS(ls[j][i], CRS84, sourceCRS); + auto point = projectToCRS(ls[j][i], currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -572,8 +572,8 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType source // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls, CRSType sourceCRS, bool hideIri) { - return getWKT(ls, 6, sourceCRS, hideIri); +std::string getWKT(const std::vector>& ls, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + return getWKT(ls, 6, currentCRS, targetCRS, hideIri); } // _____________________________________________________________________________ @@ -659,14 +659,14 @@ std::string getWKT(const Box& l) { // _____________________________________________________________________________ template -std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS, bool hideIri) { +std::string getWKT(const Polygon& p, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { if (p.getOuter().size() == 0) return "POLYGON()"; - std::string ret = hideIri ? "POLYGON((" : getCrsIri(sourceCRS) + "POLYGON(("; + std::string ret = hideIri ? "POLYGON((" : getCrsIri(targetCRS) + "POLYGON(("; ret.reserve(7 + 2 + p.getOuter().size() * (prec + 3) * 2 + 2); for (size_t i = 0; i < p.getOuter().size(); i++) { if (i > 0) ret.push_back(','); - auto point = projectToCRS(p.getOuter()[i], CRS84, sourceCRS); + auto point = projectToCRS(p.getOuter()[i], currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -674,7 +674,7 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS, bool h if (p.getOuter().front() != p.getOuter().back()) { ret.push_back(','); - auto point = projectToCRS(p.getOuter().front(), CRS84, sourceCRS); + auto point = projectToCRS(p.getOuter().front(), currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -685,7 +685,7 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS, bool h ret.append(",("); for (size_t i = 0; i < inner.size(); i++) { if (i > 0) ret.push_back(','); - auto point = projectToCRS(inner[i], CRS84, sourceCRS); + auto point = projectToCRS(inner[i], currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -693,7 +693,7 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS, bool h if (inner.front() != inner.back()) { ret.push_back(','); - auto point = projectToCRS(inner.front(), CRS84, sourceCRS); + auto point = projectToCRS(inner.front(), currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -706,14 +706,14 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType sourceCRS, bool h // _____________________________________________________________________________ template -std::string getWKT(const Polygon& p, CRSType sourceCRS, bool hideIri) { - return getWKT(p, 6, sourceCRS, hideIri); +std::string getWKT(const Polygon& p, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + return getWKT(p, 6, currentCRS, targetCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sourceCRS, bool hideIri) { - std::string ret = hideIri ? "MULTIPOLYGON(" : getCrsIri(sourceCRS) + "MULTIPOLYGON("; +std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + std::string ret = hideIri ? "MULTIPOLYGON(" : getCrsIri(targetCRS) + "MULTIPOLYGON("; if (ls.size()) ret.reserve(12 + 2 + ls[0].getOuter().size() * (prec + 3) * 2 + 2); @@ -723,7 +723,7 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sou ret.push_back('('); for (size_t i = 0; i < ls[j].getOuter().size(); i++) { if (i > 0) ret.push_back(','); - auto point = projectToCRS(ls[j].getOuter()[i], CRS84, sourceCRS); + auto point = projectToCRS(ls[j].getOuter()[i], currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -731,7 +731,7 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sou if (ls[j].getOuter().front() != ls[j].getOuter().back()) { ret.push_back(','); - auto point = projectToCRS(ls[j].getOuter().front(), CRS84, sourceCRS); + auto point = projectToCRS(ls[j].getOuter().front(), currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -743,14 +743,14 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sou ret.push_back('('); for (size_t i = 0; i < inner.size(); i++) { if (i > 0) ret.push_back(','); - auto point = projectToCRS(inner[i], CRS84, sourceCRS); + auto point = projectToCRS(inner[i], currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); } if (inner.front() != inner.back()) { ret.push_back(','); - auto point = projectToCRS(inner.front(), CRS84, sourceCRS); + auto point = projectToCRS(inner.front(), currentCRS, targetCRS); ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -766,27 +766,27 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType sou // _____________________________________________________________________________ template -std::string getWKT(const std::vector>& ls, CRSType sourceCRS, bool hideIri) { - return getWKT(ls, 6, sourceCRS, hideIri); +std::string getWKT(const std::vector>& ls, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + return getWKT(ls, 6, currentCRS, targetCRS, hideIri); } // _____________________________________________________________________________ template -std::string getWKT(const Collection& coll, uint16_t prec, CRSType sourceCRS, bool hideIri) { - std::string ret = hideIri ? "GEOMETRYCOLLECTION(" : getCrsIri(sourceCRS) + "GEOMETRYCOLLECTION("; +std::string getWKT(const Collection& coll, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + std::string ret = hideIri ? "GEOMETRYCOLLECTION(" : getCrsIri(targetCRS) + "GEOMETRYCOLLECTION("; std::string delim = ""; for (const auto& g : coll) { ret += delim; delim = ","; - if (g.getType() == 0) ret += util::geo::getWKT(g.getPoint(), prec, sourceCRS, true); - if (g.getType() == 1) ret += util::geo::getWKT(g.getLine(), prec, sourceCRS, true); - if (g.getType() == 2) ret += util::geo::getWKT(g.getPolygon(), prec, sourceCRS, true); - if (g.getType() == 3) ret += util::geo::getWKT(g.getMultiLine(), prec, sourceCRS, true); - if (g.getType() == 4) ret += util::geo::getWKT(g.getMultiPolygon(), prec, sourceCRS, true); - if (g.getType() == 5) ret += util::geo::getWKT(g.getCollection(), prec, sourceCRS, true); - if (g.getType() == 6) ret += util::geo::getWKT(g.getMultiPoint(), prec, sourceCRS, true); + if (g.getType() == 0) ret += util::geo::getWKT(g.getPoint(), prec, currentCRS, targetCRS, true); + if (g.getType() == 1) ret += util::geo::getWKT(g.getLine(), prec, currentCRS, targetCRS, true); + if (g.getType() == 2) ret += util::geo::getWKT(g.getPolygon(), prec, currentCRS, targetCRS, true); + if (g.getType() == 3) ret += util::geo::getWKT(g.getMultiLine(), prec, currentCRS, targetCRS, true); + if (g.getType() == 4) ret += util::geo::getWKT(g.getMultiPolygon(), prec, currentCRS, targetCRS, true); + if (g.getType() == 5) ret += util::geo::getWKT(g.getCollection(), prec, currentCRS, targetCRS, true); + if (g.getType() == 6) ret += util::geo::getWKT(g.getMultiPoint(), prec, currentCRS, targetCRS, true); } return ret + ")"; @@ -794,8 +794,8 @@ std::string getWKT(const Collection& coll, uint16_t prec, CRSType sourceCRS, // _____________________________________________________________________________ template -std::string getWKT(const Collection& coll, CRSType sourceCRS, bool hideIri) { - return getWKT(coll, 6, sourceCRS, hideIri); +std::string getWKT(const Collection& coll, CRSType currentCRS, CRSType targetCRS, bool hideIri) { + return getWKT(coll, 6, currentCRS, targetCRS, hideIri); } // _____________________________________________________________________________ diff --git a/tests/GeoTestCRS.cpp b/tests/GeoTestCRS.cpp index 6b00d7a..8d7d718 100644 --- a/tests/GeoTestCRS.cpp +++ b/tests/GeoTestCRS.cpp @@ -550,80 +550,170 @@ void GeoTest::testCRS() { // POINT auto projCRS84 = util::geo::pointFromWKT( " POINT(2 3)"); - TEST(getWKT(projCRS84, util::geo::CRSType::CRS84), ==, "POINT(2 3)"); + TEST(getWKT(projCRS84, util::geo::CRSType::CRS84, util::geo::CRSType::CRS84), ==, "POINT(2 3)"); auto projWGS84 = util::geo::pointFromWKT( " POINT(3 2)"); - TEST(getWKT(projWGS84, util::geo::CRSType::WGS84), ==, " POINT(3 2)"); + TEST(getWKT(projWGS84, util::geo::CRSType::CRS84, util::geo::CRSType::WGS84), ==, " POINT(3 2)"); auto projWebMerc = util::geo::pointFromWKT( " POINT(222638.98158654 334111.17140195)"); // The point will change a bit due to the reprojecting. - TEST(getWKT(projWebMerc, util::geo::CRSType::WEB_MERCATOR), ==, " POINT(222638.981587 334111.171402)"); + TEST(getWKT(projWebMerc, util::geo::CRSType::CRS84, util::geo::CRSType::WEB_MERCATOR), ==, " POINT(222638.981587 334111.171402)"); + + // POINT (from WGS84) + util::geo::DPoint pWGS84{3, 2}; + TEST(getWKT(pWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "POINT(2 3)"); + TEST(getWKT(pWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, " POINT(3 2)"); + TEST(getWKT(pWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, " POINT(222638.981587 334111.171402)"); + + // POINT (from WebMerc) + util::geo::DPoint pWebMerc{222638.981587, 334111.171402}; + TEST(getWKT(pWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::CRS84), ==, "POINT(2 3)"); + TEST(getWKT(pWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WGS84), ==, " POINT(3 2)"); + TEST(getWKT(pWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WEB_MERCATOR), ==, " POINT(222638.981587 334111.171402)"); // MULTIPOINT auto projCRS84_2 = util::geo::multiPointFromWKT( " MULTIPOINT((7 47), (8 48))"); - TEST(getWKT(projCRS84_2, util::geo::CRSType::CRS84), ==, "MULTIPOINT(7 47,8 48)"); + TEST(getWKT(projCRS84_2, util::geo::CRSType::CRS84, util::geo::CRSType::CRS84), ==, "MULTIPOINT(7 47,8 48)"); auto projWGS84_2 = util::geo::multiPointFromWKT( " MULTIPOINT((47 7), (48 8))"); - TEST(getWKT(projWGS84_2, util::geo::CRSType::WGS84), ==, " MULTIPOINT(47 7,48 8)"); + TEST(getWKT(projWGS84_2, util::geo::CRSType::CRS84, util::geo::CRSType::WGS84), ==, " MULTIPOINT(47 7,48 8)"); auto projWebMerc_2 = util::geo::multiPointFromWKT( " MULTIPOINT((779236.435552915 5942074.072431109)," " (890555.9263461885 6106854.834885074))"); - TEST(getWKT(projWebMerc_2, util::geo::CRSType::WEB_MERCATOR), ==, + TEST(getWKT(projWebMerc_2, util::geo::CRSType::CRS84, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTIPOINT(779236.435553 5942074.072431," + "890555.926346 6106854.834885)"); + + // MULTIPOINT (from WGS84) + util::geo::DMultiPoint mpWGS84{util::geo::DPoint{47, 7}, util::geo::DPoint{48, 8}}; + TEST(getWKT(mpWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "MULTIPOINT(7 47,8 48)"); + TEST(getWKT(mpWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, " MULTIPOINT(47 7,48 8)"); + TEST(getWKT(mpWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTIPOINT(779236.435553 5942074.072431," + "890555.926346 6106854.834885)"); + + // MULTIPOINT (from WebMerc) + util::geo::DMultiPoint mpWebMerc{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DPoint{890555.926346, 6106854.834885}}; + TEST(getWKT(mpWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::CRS84), ==, "MULTIPOINT(7 47,8 48)"); + TEST(getWKT(mpWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WGS84), ==, " MULTIPOINT(47 7,48 8)"); + TEST(getWKT(mpWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WEB_MERCATOR), ==, " MULTIPOINT(779236.435553 5942074.072431," "890555.926346 6106854.834885)"); // Line auto projCRS84_3 = util::geo::lineFromWKT( " LINESTRING(7 47, 7 48)"); - TEST(getWKT(projCRS84_3, util::geo::CRSType::CRS84), ==, "LINESTRING(7 47,7 48)"); + TEST(getWKT(projCRS84_3, util::geo::CRSType::CRS84, util::geo::CRSType::CRS84), ==, "LINESTRING(7 47,7 48)"); auto projWGS84_3 = util::geo::lineFromWKT( " LINESTRING(47 7, 48 7)"); - TEST(getWKT(projWGS84_3, util::geo::CRSType::WGS84), ==, " LINESTRING(47 7,48 7)"); + TEST(getWKT(projWGS84_3, util::geo::CRSType::CRS84, util::geo::CRSType::WGS84), ==, " LINESTRING(47 7,48 7)"); auto projWebMerc_3 = util::geo::lineFromWKT( " LINESTRING(779236.435552915 " "5942074.072431109, 779236.435552915 6106854.834885074)"); - TEST(getWKT(projWebMerc_3, util::geo::CRSType::WEB_MERCATOR), ==, + TEST(getWKT(projWebMerc_3, util::geo::CRSType::CRS84, util::geo::CRSType::WEB_MERCATOR), ==, + " LINESTRING(779236.435553 " + "5942074.072431,779236.435553 6106854.834885)"); + + // LINE (from WGS84) + util::geo::DLine lWGS84{util::geo::DPoint{47, 7}, util::geo::DPoint{48, 7}}; + TEST(getWKT(lWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "LINESTRING(7 47,7 48)"); + TEST(getWKT(lWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, " LINESTRING(47 7,48 7)"); + TEST(getWKT(lWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " LINESTRING(779236.435553 " + "5942074.072431,779236.435553 6106854.834885)"); + + // LINE (from WebMerc) + util::geo::DLine lWebMerc{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DPoint{779236.435553, 6106854.834885}}; + TEST(getWKT(lWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::CRS84), ==, "LINESTRING(7 47,7 48)"); + TEST(getWKT(lWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WGS84), ==, " LINESTRING(47 7,48 7)"); + TEST(getWKT(lWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WEB_MERCATOR), ==, " LINESTRING(779236.435553 " "5942074.072431,779236.435553 6106854.834885)"); // MULTILINESTRING auto projCRS8_4 = util::geo::multiLineFromWKT( " MULTILINESTRING((7 47, 8 47), (8 48, 7 48))"); - TEST(getWKT(projCRS8_4, util::geo::CRSType::CRS84), ==, "MULTILINESTRING((7 47,8 47),(8 48,7 48))"); + TEST(getWKT(projCRS8_4, util::geo::CRSType::CRS84, util::geo::CRSType::CRS84), ==, "MULTILINESTRING((7 47,8 47),(8 48,7 48))"); auto projWGS8_4 = util::geo::multiLineFromWKT( " MULTILINESTRING((47 7, 47 8), (48 8, 48 7))"); - TEST(getWKT(projWGS8_4, util::geo::CRSType::WGS84), ==, " MULTILINESTRING((47 7,47 8),(48 8,48 7))"); + TEST(getWKT(projWGS8_4, util::geo::CRSType::CRS84, util::geo::CRSType::WGS84), ==, " MULTILINESTRING((47 7,47 8),(48 8,48 7))"); auto projWebMerc_4 = util::geo::multiLineFromWKT( " MULTILINESTRING((779236.435552915 5942074.072431109," " 890555.9263461885 5942074.072431109), (890555.9263461885 6106854.834885074, 779236.435552915 6106854.834885074))"); - TEST(getWKT(projWebMerc_4, util::geo::CRSType::WEB_MERCATOR), ==, + TEST(getWKT(projWebMerc_4, util::geo::CRSType::CRS84, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTILINESTRING((779236.435553 5942074.072431," + "890555.926346 5942074.072431),(890555.926346 6106854.834885,779236.435553 6106854.834885))"); + + // MULTILINESTRING (from WGS84) + util::geo::DMultiLine mlWGS84{util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{47, 8}}, + util::geo::DLine{util::geo::DPoint{48, 8}, util::geo::DPoint{48, 7}}}; + TEST(getWKT(mlWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "MULTILINESTRING((7 47,8 47),(8 48,7 48))"); + TEST(getWKT(mlWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, " MULTILINESTRING((47 7,47 8),(48 8,48 7))"); + TEST(getWKT(mlWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTILINESTRING((779236.435553 5942074.072431," + "890555.926346 5942074.072431),(890555.926346 6106854.834885,779236.435553 6106854.834885))"); + + // MULTILINESTRING (from WebMerc) + util::geo::DMultiLine mlWebMerc{util::geo::DLine{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DPoint{890555.926346, 5942074.072431}}, + util::geo::DLine{util::geo::DPoint{890555.926346, 6106854.834885}, util::geo::DPoint{779236.435553, 6106854.834885}}}; + TEST(getWKT(mlWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::CRS84), ==, "MULTILINESTRING((7 47,8 47),(8 48,7 48))"); + TEST(getWKT(mlWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WGS84), ==, " MULTILINESTRING((47 7,47 8),(48 8,48 7))"); + TEST(getWKT(mlWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WEB_MERCATOR), ==, " MULTILINESTRING((779236.435553 5942074.072431," "890555.926346 5942074.072431),(890555.926346 6106854.834885,779236.435553 6106854.834885))"); // POLYGON auto projCRS84_5 = util::geo::polygonFromWKT( " POLYGON((7 47, 8 47, 8 48, 7 48, 7 47))"); - TEST(getWKT(projCRS84_5, util::geo::CRSType::CRS84), ==, "POLYGON((7 47,8 47,8 48,7 48,7 47))"); + TEST(getWKT(projCRS84_5, util::geo::CRSType::CRS84, util::geo::CRSType::CRS84), ==, "POLYGON((7 47,8 47,8 48,7 48,7 47))"); auto projWGS84_5 = util::geo::polygonFromWKT( " POLYGON((47 7, 47 8, 48 8, 48 7, 47 7))"); - TEST(getWKT(projWGS84_5, util::geo::CRSType::WGS84), ==, " POLYGON((47 7,47 8,48 8,48 7,47 7))"); + TEST(getWKT(projWGS84_5, util::geo::CRSType::CRS84, util::geo::CRSType::WGS84), ==, " POLYGON((47 7,47 8,48 8,48 7,47 7))"); auto projWebMerc_5 = util::geo::polygonFromWKT( " POLYGON((779236.435552915 5942074.072431109," " 890555.9263461885 5942074.072431109, 890555.9263461885 6106854.834885074, 779236.435552915" " 6106854.834885074, 779236.435552915 5942074.072431109))"); - TEST(getWKT(projWebMerc_5, util::geo::CRSType::WEB_MERCATOR), ==, + TEST(getWKT(projWebMerc_5, util::geo::CRSType::CRS84, util::geo::CRSType::WEB_MERCATOR), ==, + " POLYGON((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553" + " 6106854.834885,779236.435553 5942074.072431))"); + + // POLYGON (from WGS84) + /* TODO original test not working + util::geo::DPolygon polyWGS84{util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{47, 8}, + util::geo::DPoint{48, 8}, util::geo::DPoint{48, 7}, util::geo::DPoint{47, 7}}}; + TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "POLYGON((7 47,8 47,8 48,7 48,7 47))"); + TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, " POLYGON((47 7,47 8,48 8,48 7,47 7))"); + TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " POLYGON((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553" + " 6106854.834885,779236.435553 5942074.072431))");*/ + util::geo::DPolygon polyWGS84{util::geo::DLine{util::geo::DPoint{48, 7}, util::geo::DPoint{48, 8}, + util::geo::DPoint{47, 8}, util::geo::DPoint{47, 7}, util::geo::DPoint{48, 7}}}; + TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "POLYGON((7 48,8 48,8 47,7 47,7 48))"); + TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, " POLYGON((48 7,48 8,47 8,47 7,48 7))"); + TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " POLYGON((779236.435553 6106854.834885,890555.926346 6106854.834885," + "890555.926346 5942074.072431,779236.435553 5942074.072431,779236.435553 6106854.834885))"); + + // POLYGON (from WebMerc) + util::geo::DPolygon polyWebMerc{util::geo::DLine{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DPoint{890555.926346, 5942074.072431}, + util::geo::DPoint{890555.926346, 6106854.834885}, util::geo::DPoint{779236.435553, 6106854.834885}, util::geo::DPoint{779236.435553, 5942074.072431}}}; + TEST(getWKT(polyWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::CRS84), ==, "POLYGON((7 47,8 47,8 48,7 48,7 47))"); + TEST(getWKT(polyWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WGS84), ==, " POLYGON((47 7,47 8,48 8,48 7,47 7))"); + TEST(getWKT(polyWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WEB_MERCATOR), ==, " POLYGON((779236.435553 5942074.072431," "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553" " 6106854.834885,779236.435553 5942074.072431))"); @@ -632,12 +722,12 @@ void GeoTest::testCRS() { auto projCRS84_6 = util::geo::multiPolygonFromWKT( " MULTIPOLYGON(((7 47, 8 47, 8 48, 7 48, 7 47))," " ((8 48, 9 48, 9 49, 8 49, 8 48)))"); - TEST(getWKT(projCRS84_6, util::geo::CRSType::CRS84), ==, "MULTIPOLYGON(((7 47,8 47,8 48,7 48,7 47)),((8 48,9 48,9 49,8 49,8 48)))"); + TEST(getWKT(projCRS84_6, util::geo::CRSType::CRS84, util::geo::CRSType::CRS84), ==, "MULTIPOLYGON(((7 47,8 47,8 48,7 48,7 47)),((8 48,9 48,9 49,8 49,8 48)))"); auto projWGS84_6 = util::geo::multiPolygonFromWKT( " MULTIPOLYGON(((47 7, 47 8, 48 8, 48 7, 47 7))," " ((48 8, 48 9, 49 9, 49 8, 48 8)))"); - TEST(getWKT(projWGS84_6, util::geo::CRSType::WGS84), ==, + TEST(getWKT(projWGS84_6, util::geo::CRSType::CRS84, util::geo::CRSType::WGS84), ==, " MULTIPOLYGON(((47 7,47 8,48 8,48 7,47 7))," "((48 8,48 9,49 9,49 8,48 8)))"); @@ -646,7 +736,50 @@ void GeoTest::testCRS() { " 890555.9263461885 5942074.072431109, 890555.9263461885 6106854.834885074, 779236.435552915 6106854.834885074," " 779236.435552915 5942074.072431109)), ((890555.9263461885 6106854.834885074, 1001875.4171394621 6106854.834885074," " 1001875.4171394621 6274861.394006576, 890555.9263461885 6274861.394006576, 890555.9263461885 6106854.834885074)))"); - TEST(getWKT(projWebMerc_6, util::geo::CRSType::WEB_MERCATOR), ==, + TEST(getWKT(projWebMerc_6, util::geo::CRSType::CRS84, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTIPOLYGON(((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," + "779236.435553 5942074.072431)),((890555.926346 6106854.834885,1001875.417139 6106854.834885," + "1001875.417139 6274861.394007,890555.926346 6274861.394007,890555.926346 6106854.834885)))"); + + // MULTIPOLYGON (from WGS84) + /* TODO original test fails + util::geo::DMultiPolygon mpolyWGS84{util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{47, 8}, + util::geo::DPoint{48, 8}, util::geo::DPoint{48, 7}, util::geo::DPoint{47, 7}}}, + util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{48, 8}, util::geo::DPoint{48, 9}, + util::geo::DPoint{49, 9}, util::geo::DPoint{49, 8}, util::geo::DPoint{48, 8}}}}; + TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "MULTIPOLYGON(((7 47,8 47,8 48,7 48,7 47)),((8 48,9 48,9 49,8 49,8 48)))"); + TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, + " MULTIPOLYGON(((47 7,47 8,48 8,48 7,47 7))," + "((48 8,48 9,49 9,49 8,48 8)))"); + TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTIPOLYGON(((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," + "779236.435553 5942074.072431)),((890555.926346 6106854.834885,1001875.417139 6106854.834885," + "1001875.417139 6274861.394007,890555.926346 6274861.394007,890555.926346 6106854.834885)))"); + */ + util::geo::DMultiPolygon mpolyWGS84{util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{48, 7}, util::geo::DPoint{48, 8}, + util::geo::DPoint{47, 8}, util::geo::DPoint{47, 7}, util::geo::DPoint{48, 7}}}, + util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{49, 8}, util::geo::DPoint{49, 9}, + util::geo::DPoint{48, 9}, util::geo::DPoint{48, 8}, util::geo::DPoint{49, 8}}}}; + TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "MULTIPOLYGON(((7 48,8 48,8 47,7 47,7 48)),((8 49,9 49,9 48,8 48,8 49)))"); + TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, + " MULTIPOLYGON(((48 7,48 8,47 8,47 7,48 7)),((49 8,49 9,48 9,48 8,49 8)))"); + TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " MULTIPOLYGON(((779236.435553 6106854.834885,890555.926346 6106854.834885,890555.926346 5942074.072431," + "779236.435553 5942074.072431,779236.435553 6106854.834885)),((890555.926346 6274861.394007,1001875.417139 6274861.394007,1001875.417139 6106854.834885," + "890555.926346 6106854.834885,890555.926346 6274861.394007)))"); + + // MULTIPOLYGON (from WebMerc) + util::geo::DMultiPolygon mpolyWebMerc{util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DPoint{890555.926346, 5942074.072431}, + util::geo::DPoint{890555.926346, 6106854.834885}, util::geo::DPoint{779236.435553, 6106854.834885}, util::geo::DPoint{779236.435553, 5942074.072431}}}, + util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{890555.926346, 6106854.834885}, util::geo::DPoint{1001875.417139, 6106854.834885}, + util::geo::DPoint{1001875.417139, 6274861.394007}, util::geo::DPoint{890555.926346, 6274861.394007}, util::geo::DPoint{890555.926346, 6106854.834885}}}}; + TEST(getWKT(mpolyWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::CRS84), ==, "MULTIPOLYGON(((7 47,8 47,8 48,7 48,7 47)),((8 48,9 48,9 49,8 49,8 48)))"); + TEST(getWKT(mpolyWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WGS84), ==, + " MULTIPOLYGON(((47 7,47 8,48 8,48 7,47 7))," + "((48 8,48 9,49 9,49 8,48 8)))"); + TEST(getWKT(mpolyWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WEB_MERCATOR), ==, " MULTIPOLYGON(((779236.435553 5942074.072431," "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," "779236.435553 5942074.072431)),((890555.926346 6106854.834885,1001875.417139 6106854.834885," @@ -656,13 +789,13 @@ void GeoTest::testCRS() { auto projCRS84_7 = util::geo::collectionFromWKT( " GEOMETRYCOLLECTION(POINT(7 47)," " LINESTRING(7 47, 8 48), POLYGON((7 47, 8 47, 8 48, 7 48, 7 47)))"); - TEST(getWKT(projCRS84_7, util::geo::CRSType::CRS84), ==, + TEST(getWKT(projCRS84_7, util::geo::CRSType::CRS84, util::geo::CRSType::CRS84), ==, "GEOMETRYCOLLECTION(POINT(7 47),LINESTRING(7 47,8 48),POLYGON((7 47,8 47,8 48,7 48,7 47)))"); auto projWGS84_7 = util::geo::collectionFromWKT( " GEOMETRYCOLLECTION(POINT(47 7), " "LINESTRING(47 7, 48 8), POLYGON((47 7, 47 8, 48 8, 48 7, 47 7)))"); - TEST(getWKT(projWGS84_7, util::geo::CRSType::WGS84), ==, + TEST(getWKT(projWGS84_7, util::geo::CRSType::CRS84, util::geo::CRSType::WGS84), ==, " GEOMETRYCOLLECTION(POINT(47 7)," "LINESTRING(47 7,48 8),POLYGON((47 7,47 8,48 8,48 7,47 7)))"); @@ -671,7 +804,51 @@ void GeoTest::testCRS() { " LINESTRING(779236.435552915 5942074.072431109, 890555.9263461885 6106854.834885074), POLYGON((779236.435552915" " 5942074.072431109, 890555.9263461885 5942074.072431109, 890555.9263461885 6106854.834885074, 779236.435552915 " "6106854.834885074, 779236.435552915 5942074.072431109)))"); - TEST(getWKT(projWebMerc_7, util::geo::CRSType::WEB_MERCATOR), ==, + TEST(getWKT(projWebMerc_7, util::geo::CRSType::CRS84, util::geo::CRSType::WEB_MERCATOR), ==, + " GEOMETRYCOLLECTION(POINT(779236.435553 5942074.072431)," + "LINESTRING(779236.435553 5942074.072431,890555.926346 6106854.834885),POLYGON((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," + "779236.435553 5942074.072431)))"); + + // COLLECTION (from WGS84) + /* TODO + util::geo::DCollection colWGS84{util::geo::DPoint{47, 7}, util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{48, 8}}, + util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{47, 8}, + util::geo::DPoint{48, 8}, util::geo::DPoint{48, 7}, util::geo::DPoint{47, 7}}}}; + TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, + "GEOMETRYCOLLECTION(POINT(7 47),LINESTRING(7 47,8 48),POLYGON((7 47,8 47,8 48,7 48,7 47)))"); + TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, + " GEOMETRYCOLLECTION(POINT(47 7)," + "LINESTRING(47 7,48 8),POLYGON((47 7,47 8,48 8,48 7,47 7)))"); + TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " GEOMETRYCOLLECTION(POINT(779236.435553 5942074.072431)," + "LINESTRING(779236.435553 5942074.072431,890555.926346 6106854.834885),POLYGON((779236.435553 5942074.072431," + "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," + "779236.435553 5942074.072431)))"); + */ + util::geo::DCollection colWGS84{util::geo::DPoint{47, 7}, util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{48, 8}}, + util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{48, 7}, util::geo::DPoint{48, 8}, + util::geo::DPoint{47, 8}, util::geo::DPoint{47, 7}, util::geo::DPoint{48, 7}}}}; + TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, + "GEOMETRYCOLLECTION(POINT(7 47),LINESTRING(7 47,8 48),POLYGON((7 48,8 48,8 47,7 47,7 48)))"); + TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, + " GEOMETRYCOLLECTION(POINT(47 7)," + "LINESTRING(47 7,48 8),POLYGON((48 7,48 8,47 8,47 7,48 7)))"); + TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, + " GEOMETRYCOLLECTION(POINT(779236.435553 5942074.072431)," + "LINESTRING(779236.435553 5942074.072431,890555.926346 6106854.834885),POLYGON((779236.435553 6106854.834885," + "890555.926346 6106854.834885,890555.926346 5942074.072431,779236.435553 5942074.072431,779236.435553 6106854.834885)))"); + + // COLLECTION (from WebMerc) + util::geo::DCollection colWebMerc{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DLine{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DPoint{890555.926346, 6106854.834885}}, + util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{779236.435553, 5942074.072431}, util::geo::DPoint{890555.926346, 5942074.072431}, + util::geo::DPoint{890555.926346, 6106854.834885}, util::geo::DPoint{779236.435553, 6106854.834885}, util::geo::DPoint{779236.435553, 5942074.072431}}}}; + TEST(getWKT(colWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::CRS84), ==, + "GEOMETRYCOLLECTION(POINT(7 47),LINESTRING(7 47,8 48),POLYGON((7 47,8 47,8 48,7 48,7 47)))"); + TEST(getWKT(colWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WGS84), ==, + " GEOMETRYCOLLECTION(POINT(47 7)," + "LINESTRING(47 7,48 8),POLYGON((47 7,47 8,48 8,48 7,47 7)))"); + TEST(getWKT(colWebMerc, util::geo::CRSType::WEB_MERCATOR, util::geo::CRSType::WEB_MERCATOR), ==, " GEOMETRYCOLLECTION(POINT(779236.435553 5942074.072431)," "LINESTRING(779236.435553 5942074.072431,890555.926346 6106854.834885),POLYGON((779236.435553 5942074.072431," "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," From 9bcef4983d134c867eee705e76f88d0d40af8313 Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Thu, 20 Aug 2026 14:44:53 +0200 Subject: [PATCH 5/8] removed old tests --- tests/GeoTestCRS.cpp | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/tests/GeoTestCRS.cpp b/tests/GeoTestCRS.cpp index 8d7d718..b2f30ad 100644 --- a/tests/GeoTestCRS.cpp +++ b/tests/GeoTestCRS.cpp @@ -691,15 +691,6 @@ void GeoTest::testCRS() { " 6106854.834885,779236.435553 5942074.072431))"); // POLYGON (from WGS84) - /* TODO original test not working - util::geo::DPolygon polyWGS84{util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{47, 8}, - util::geo::DPoint{48, 8}, util::geo::DPoint{48, 7}, util::geo::DPoint{47, 7}}}; - TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "POLYGON((7 47,8 47,8 48,7 48,7 47))"); - TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, " POLYGON((47 7,47 8,48 8,48 7,47 7))"); - TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, - " POLYGON((779236.435553 5942074.072431," - "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553" - " 6106854.834885,779236.435553 5942074.072431))");*/ util::geo::DPolygon polyWGS84{util::geo::DLine{util::geo::DPoint{48, 7}, util::geo::DPoint{48, 8}, util::geo::DPoint{47, 8}, util::geo::DPoint{47, 7}, util::geo::DPoint{48, 7}}}; TEST(getWKT(polyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "POLYGON((7 48,8 48,8 47,7 47,7 48))"); @@ -743,21 +734,6 @@ void GeoTest::testCRS() { "1001875.417139 6274861.394007,890555.926346 6274861.394007,890555.926346 6106854.834885)))"); // MULTIPOLYGON (from WGS84) - /* TODO original test fails - util::geo::DMultiPolygon mpolyWGS84{util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{47, 8}, - util::geo::DPoint{48, 8}, util::geo::DPoint{48, 7}, util::geo::DPoint{47, 7}}}, - util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{48, 8}, util::geo::DPoint{48, 9}, - util::geo::DPoint{49, 9}, util::geo::DPoint{49, 8}, util::geo::DPoint{48, 8}}}}; - TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, "MULTIPOLYGON(((7 47,8 47,8 48,7 48,7 47)),((8 48,9 48,9 49,8 49,8 48)))"); - TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, - " MULTIPOLYGON(((47 7,47 8,48 8,48 7,47 7))," - "((48 8,48 9,49 9,49 8,48 8)))"); - TEST(getWKT(mpolyWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, - " MULTIPOLYGON(((779236.435553 5942074.072431," - "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," - "779236.435553 5942074.072431)),((890555.926346 6106854.834885,1001875.417139 6106854.834885," - "1001875.417139 6274861.394007,890555.926346 6274861.394007,890555.926346 6106854.834885)))"); - */ util::geo::DMultiPolygon mpolyWGS84{util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{48, 7}, util::geo::DPoint{48, 8}, util::geo::DPoint{47, 8}, util::geo::DPoint{47, 7}, util::geo::DPoint{48, 7}}}, util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{49, 8}, util::geo::DPoint{49, 9}, @@ -811,21 +787,6 @@ void GeoTest::testCRS() { "779236.435553 5942074.072431)))"); // COLLECTION (from WGS84) - /* TODO - util::geo::DCollection colWGS84{util::geo::DPoint{47, 7}, util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{48, 8}}, - util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{47, 8}, - util::geo::DPoint{48, 8}, util::geo::DPoint{48, 7}, util::geo::DPoint{47, 7}}}}; - TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::CRS84), ==, - "GEOMETRYCOLLECTION(POINT(7 47),LINESTRING(7 47,8 48),POLYGON((7 47,8 47,8 48,7 48,7 47)))"); - TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WGS84), ==, - " GEOMETRYCOLLECTION(POINT(47 7)," - "LINESTRING(47 7,48 8),POLYGON((47 7,47 8,48 8,48 7,47 7)))"); - TEST(getWKT(colWGS84, util::geo::CRSType::WGS84, util::geo::CRSType::WEB_MERCATOR), ==, - " GEOMETRYCOLLECTION(POINT(779236.435553 5942074.072431)," - "LINESTRING(779236.435553 5942074.072431,890555.926346 6106854.834885),POLYGON((779236.435553 5942074.072431," - "890555.926346 5942074.072431,890555.926346 6106854.834885,779236.435553 6106854.834885," - "779236.435553 5942074.072431)))"); - */ util::geo::DCollection colWGS84{util::geo::DPoint{47, 7}, util::geo::DLine{util::geo::DPoint{47, 7}, util::geo::DPoint{48, 8}}, util::geo::DPolygon{util::geo::DLine{util::geo::DPoint{48, 7}, util::geo::DPoint{48, 8}, util::geo::DPoint{47, 8}, util::geo::DPoint{47, 7}, util::geo::DPoint{48, 7}}}}; From 81b337592660315f6bdd17b037ed43fe2fd7b460 Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Fri, 21 Aug 2026 10:39:31 +0200 Subject: [PATCH 6/8] Using IRI constants --- geo/Geo.cpp | 10 +++++----- geo/Geo.h | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/geo/Geo.cpp b/geo/Geo.cpp index c3a4028..4475e51 100644 --- a/geo/Geo.cpp +++ b/geo/Geo.cpp @@ -110,15 +110,15 @@ util::geo::CRSType util::geo::getCRSType(const char* c, const char** endr) { return CRS84; // Default. } - if (strncicmp("", c, 46) == 0) { + if (strncicmp(crs84Iri, c, 46) == 0) { if (endr) (*endr) = c + 46; return CRS84; } - if (strncicmp("", c, 44) == 0) { + if (strncicmp(wgs84Iri, c, 44) == 0) { if (endr) (*endr) = c + 44; return WGS84; } - if (strncicmp("", c, 44) == 0) { + if (strncicmp(webMercIri, c, 44) == 0) { if (endr) (*endr) = c + 44; return WEB_MERCATOR; } @@ -135,9 +135,9 @@ std::string util::geo::getCrsIri(util::geo::CRSType targetCRS) { // Not attaching IRI as CRS84 is the default. return ""; case WGS84: - return wgs84Iri; + return std::string{wgs84Iri} + " "; case WEB_MERCATOR: - return webMercIri; + return std::string{webMercIri} + " "; default: throw std::runtime_error("Trying to get CRS IRI for unsupported CRS type."); } diff --git a/geo/Geo.h b/geo/Geo.h index 265c7c9..9bc714f 100644 --- a/geo/Geo.h +++ b/geo/Geo.h @@ -163,8 +163,9 @@ enum CRSType : uint8_t { WEB_MERCATOR = 3, }; -constexpr const char* wgs84Iri = " "; -constexpr const char* webMercIri = " "; +constexpr const char* crs84Iri = ""; +constexpr const char* wgs84Iri = ""; +constexpr const char* webMercIri = ""; uint8_t boolArrToInt8(const std::array arr); From 9e77bc63658b668f68fb57a5006e33f0cb0c690c Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Wed, 26 Aug 2026 18:28:43 +0200 Subject: [PATCH 7/8] remove stale comment --- geo/Geo.tpp | 1 - 1 file changed, 1 deletion(-) diff --git a/geo/Geo.tpp b/geo/Geo.tpp index 39446dc..86d73f6 100644 --- a/geo/Geo.tpp +++ b/geo/Geo.tpp @@ -484,7 +484,6 @@ RotatedBox shrink(const RotatedBox& b, double d) { // _____________________________________________________________________________ template std::string getWKT(const Point& p, uint16_t prec, CRSType currentCRS, CRSType targetCRS, bool hideIri) { - // Project from internal CRS84 to original 'sourceCRS'. auto proj = projectToCRS(p, currentCRS, targetCRS); std::string ret; ret = hideIri ? "POINT(" : getCrsIri(targetCRS) + "POINT("; From 94c17646acc96febf2eecdadc72f44ba6e6351c5 Mon Sep 17 00:00:00 2001 From: Yannik Schnell Date: Thu, 3 Sep 2026 09:59:13 +0200 Subject: [PATCH 8/8] Lengths for CRS IRIs --- geo/Geo.cpp | 12 ++++++------ geo/Geo.h | 9 ++++++--- geo/Geo.tpp | 27 +++++++++++++++------------ 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/geo/Geo.cpp b/geo/Geo.cpp index 4475e51..03f40de 100644 --- a/geo/Geo.cpp +++ b/geo/Geo.cpp @@ -110,16 +110,16 @@ util::geo::CRSType util::geo::getCRSType(const char* c, const char** endr) { return CRS84; // Default. } - if (strncicmp(crs84Iri, c, 46) == 0) { - if (endr) (*endr) = c + 46; + if (strncicmp(crs84Iri, c, crs84IriLen) == 0) { + if (endr) (*endr) = c + crs84IriLen; return CRS84; } - if (strncicmp(wgs84Iri, c, 44) == 0) { - if (endr) (*endr) = c + 44; + if (strncicmp(wgs84Iri, c, wgs84IriLen) == 0) { + if (endr) (*endr) = c + wgs84IriLen; return WGS84; } - if (strncicmp(webMercIri, c, 44) == 0) { - if (endr) (*endr) = c + 44; + if (strncicmp(webMercIri, c, webMercIriLen) == 0) { + if (endr) (*endr) = c + webMercIriLen; return WEB_MERCATOR; } diff --git a/geo/Geo.h b/geo/Geo.h index 9bc714f..8723928 100644 --- a/geo/Geo.h +++ b/geo/Geo.h @@ -163,9 +163,12 @@ enum CRSType : uint8_t { WEB_MERCATOR = 3, }; -constexpr const char* crs84Iri = ""; -constexpr const char* wgs84Iri = ""; -constexpr const char* webMercIri = ""; +constexpr const char crs84Iri[] = ""; +constexpr size_t crs84IriLen = sizeof(crs84Iri) - 1; +constexpr const char wgs84Iri[] = ""; +constexpr size_t wgs84IriLen = sizeof(wgs84Iri) - 1; +constexpr const char webMercIri[] = ""; +constexpr size_t webMercIriLen = sizeof(webMercIri) - 1; uint8_t boolArrToInt8(const std::array arr); diff --git a/geo/Geo.tpp b/geo/Geo.tpp index 86d73f6..27c6f7d 100644 --- a/geo/Geo.tpp +++ b/geo/Geo.tpp @@ -663,9 +663,11 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType currentCRS, CRSTy std::string ret = hideIri ? "POLYGON((" : getCrsIri(targetCRS) + "POLYGON(("; ret.reserve(7 + 2 + p.getOuter().size() * (prec + 3) * 2 + 2); + util::geo::Point front; for (size_t i = 0; i < p.getOuter().size(); i++) { if (i > 0) ret.push_back(','); auto point = projectToCRS(p.getOuter()[i], currentCRS, targetCRS); + if (i == 0) front = point; ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -673,10 +675,9 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType currentCRS, CRSTy if (p.getOuter().front() != p.getOuter().back()) { ret.push_back(','); - auto point = projectToCRS(p.getOuter().front(), currentCRS, targetCRS); - ret.append(formatFloat(point.getX(), prec)); + ret.append(formatFloat(front.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(point.getY(), prec)); + ret.append(formatFloat(front.getY(), prec)); } ret.push_back(')'); @@ -685,6 +686,7 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType currentCRS, CRSTy for (size_t i = 0; i < inner.size(); i++) { if (i > 0) ret.push_back(','); auto point = projectToCRS(inner[i], currentCRS, targetCRS); + if (i == 0) front = point; ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -692,10 +694,9 @@ std::string getWKT(const Polygon& p, uint16_t prec, CRSType currentCRS, CRSTy if (inner.front() != inner.back()) { ret.push_back(','); - auto point = projectToCRS(inner.front(), currentCRS, targetCRS); - ret.append(formatFloat(point.getX(), prec)); + ret.append(formatFloat(front.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(point.getY(), prec)); + ret.append(formatFloat(front.getY(), prec)); } ret.push_back(')'); } @@ -720,9 +721,12 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType cur if (j) ret.push_back(','); ret.push_back('('); ret.push_back('('); + + util::geo::Point front; for (size_t i = 0; i < ls[j].getOuter().size(); i++) { if (i > 0) ret.push_back(','); auto point = projectToCRS(ls[j].getOuter()[i], currentCRS, targetCRS); + if (i == 0) front = point; ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); @@ -730,10 +734,9 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType cur if (ls[j].getOuter().front() != ls[j].getOuter().back()) { ret.push_back(','); - auto point = projectToCRS(ls[j].getOuter().front(), currentCRS, targetCRS); - ret.append(formatFloat(point.getX(), prec)); + ret.append(formatFloat(front.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(point.getY(), prec)); + ret.append(formatFloat(front.getY(), prec)); } ret.push_back(')'); @@ -743,16 +746,16 @@ std::string getWKT(const std::vector>& ls, uint16_t prec, CRSType cur for (size_t i = 0; i < inner.size(); i++) { if (i > 0) ret.push_back(','); auto point = projectToCRS(inner[i], currentCRS, targetCRS); + if (i == 0) front = point; ret.append(formatFloat(point.getX(), prec)); ret.push_back(' '); ret.append(formatFloat(point.getY(), prec)); } if (inner.front() != inner.back()) { ret.push_back(','); - auto point = projectToCRS(inner.front(), currentCRS, targetCRS); - ret.append(formatFloat(point.getX(), prec)); + ret.append(formatFloat(front.getX(), prec)); ret.push_back(' '); - ret.append(formatFloat(point.getY(), prec)); + ret.append(formatFloat(front.getY(), prec)); } ret.push_back(')'); }