diff options
| author | Even Rouault <even.rouault@mines-paris.org> | 2019-03-26 12:07:27 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-03-26 12:07:27 +0100 |
| commit | d21fb4e9abd3246fcbece6724dd3d014c35df25e (patch) | |
| tree | ee4ba388d7d9507397b5cbad5814cb7e1ee540c0 | |
| parent | 66774791d16d1b197911e595aaaceb9690c8ca14 (diff) | |
| parent | 09db4826d4a1e5df900cb4b93a4b3eae2c487cb9 (diff) | |
| download | PROJ-d21fb4e9abd3246fcbece6724dd3d014c35df25e.tar.gz PROJ-d21fb4e9abd3246fcbece6724dd3d014c35df25e.zip | |
Merge pull request #1366 from rouault/ogc_18_010r6_further_fixes
OGC 18-010r6 further fixes regarding WKT2:2018 export
| -rw-r--r-- | include/proj/crs.hpp | 2 | ||||
| -rw-r--r-- | include/proj/io.hpp | 12 | ||||
| -rw-r--r-- | src/iso19111/common.cpp | 2 | ||||
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 88 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 17 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 40 | ||||
| -rw-r--r-- | test/cli/testprojinfo_out.dist | 61 | ||||
| -rw-r--r-- | test/unit/test_crs.cpp | 139 | ||||
| -rw-r--r-- | test/unit/test_factory.cpp | 18 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 44 | ||||
| -rw-r--r-- | test/unit/test_operation.cpp | 4 |
11 files changed, 333 insertions, 94 deletions
diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp index b9594165..ed3463cd 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -503,7 +503,7 @@ class PROJ_GCC_DLL DerivedCRS : virtual public SingleCRS { PROJ_INTERNAL void setDerivingConversionCRS(); PROJ_INTERNAL void baseExportToWKT( - io::WKTFormatter *&formatter, const std::string &keyword, + io::WKTFormatter *formatter, const std::string &keyword, const std::string &baseKeyword) const; // throw(FormattingException) PROJ_INTERNAL bool diff --git a/include/proj/io.hpp b/include/proj/io.hpp index 8cf8e3c4..5386ca6c 100644 --- a/include/proj/io.hpp +++ b/include/proj/io.hpp @@ -195,8 +195,7 @@ class PROJ_GCC_DLL WKTFormatter { WKT2_2018_SIMPLIFIED, /** WKT1 as traditionally output by GDAL, deriving from OGC 01-009. - A notable departuPROJ_GCC_DLLre from WKT1_GDAL with respect to OGC - 01-009 is + A notable departure from WKT1_GDAL with respect to OGC 01-009 is that in WKT1_GDAL, the unit of the PRIMEM value is always degrees. */ WKT1_GDAL, @@ -262,6 +261,13 @@ class PROJ_GCC_DLL WKTFormatter { PROJ_INTERNAL void popOutputId(); PROJ_INTERNAL bool outputId() const; + PROJ_INTERNAL void pushHasId(bool hasId); + PROJ_INTERNAL void popHasId(); + + PROJ_INTERNAL void pushDisableUsage(); + PROJ_INTERNAL void popDisableUsage(); + PROJ_INTERNAL bool outputUsage() const; + PROJ_INTERNAL void pushAxisLinearUnit(const common::UnitOfMeasureNNPtr &unit); PROJ_INTERNAL void popAxisLinearUnit(); @@ -303,6 +309,8 @@ class PROJ_GCC_DLL WKTFormatter { PROJ_INTERNAL bool primeMeridianOrParameterUnitOmittedIfSameAsAxis() const; PROJ_INTERNAL bool primeMeridianInDegree() const; PROJ_INTERNAL bool outputCSUnitOnlyOnceIfSame() const; + PROJ_INTERNAL bool idOnTopLevelOnly() const; + PROJ_INTERNAL bool topLevelHasId() const; /** WKT version. */ enum class Version { diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp index 4b947dc9..d46da0da 100644 --- a/src/iso19111/common.cpp +++ b/src/iso19111/common.cpp @@ -1073,7 +1073,7 @@ void ObjectUsage::setProperties( void ObjectUsage::baseExportToWKT(WKTFormatter *formatter) const { const bool isWKT2 = formatter->version() == WKTFormatter::Version::WKT2; - if (isWKT2 && formatter->outputId()) { + if (isWKT2 && formatter->outputUsage()) { auto l_domains = domains(); if (!l_domains.empty()) { if (formatter->use2018Keywords()) { diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 80c1a572..d7f138a4 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -7639,6 +7639,53 @@ void Transformation::_exportToWKT(io::WKTFormatter *formatter) const { // --------------------------------------------------------------------------- +static void exportSourceCRSAndTargetCRSToWKT(const CoordinateOperation *co, + io::WKTFormatter *formatter) { + auto l_sourceCRS = co->sourceCRS(); + assert(l_sourceCRS); + auto l_targetCRS = co->targetCRS(); + assert(l_targetCRS); + const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; + const bool canExportCRSId = + (isWKT2 && formatter->use2018Keywords() && + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())); + + const bool hasDomains = !co->domains().empty(); + if (hasDomains) { + formatter->pushDisableUsage(); + } + + formatter->startNode(io::WKTConstants::SOURCECRS, false); + if (canExportCRSId && !l_sourceCRS->identifiers().empty()) { + // fake that top node has no id, so that the sourceCRS id is + // considered + formatter->pushHasId(false); + l_sourceCRS->_exportToWKT(formatter); + formatter->popHasId(); + } else { + l_sourceCRS->_exportToWKT(formatter); + } + formatter->endNode(); + + formatter->startNode(io::WKTConstants::TARGETCRS, false); + if (canExportCRSId && !l_targetCRS->identifiers().empty()) { + // fake that top node has no id, so that the targetCRS id is + // considered + formatter->pushHasId(false); + l_targetCRS->_exportToWKT(formatter); + formatter->popHasId(); + } else { + l_targetCRS->_exportToWKT(formatter); + } + formatter->endNode(); + + if (hasDomains) { + formatter->popDisableUsage(); + } +} + +// --------------------------------------------------------------------------- + void SingleOperation::exportTransformationToWKT( io::WKTFormatter *formatter) const { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; @@ -7647,11 +7694,6 @@ void SingleOperation::exportTransformationToWKT( "Transformation can only be exported to WKT2"); } - auto l_sourceCRS = sourceCRS(); - assert(l_sourceCRS); - auto l_targetCRS = targetCRS(); - assert(l_targetCRS); - if (formatter->abridgedTransformation()) { formatter->startNode(io::WKTConstants::ABRIDGEDTRANSFORMATION, !identifiers().empty()); @@ -7672,13 +7714,7 @@ void SingleOperation::exportTransformationToWKT( } if (!formatter->abridgedTransformation()) { - formatter->startNode(io::WKTConstants::SOURCECRS, false); - l_sourceCRS->_exportToWKT(formatter); - formatter->endNode(); - - formatter->startNode(io::WKTConstants::TARGETCRS, false); - l_targetCRS->_exportToWKT(formatter); - formatter->endNode(); + exportSourceCRSAndTargetCRSToWKT(this, formatter); } method()->_exportToWKT(formatter); @@ -9337,20 +9373,34 @@ void ConcatenatedOperation::_exportToWKT(io::WKTFormatter *formatter) const { } } - formatter->startNode(io::WKTConstants::SOURCECRS, false); - sourceCRS()->_exportToWKT(formatter); - formatter->endNode(); + exportSourceCRSAndTargetCRSToWKT(this, formatter); - formatter->startNode(io::WKTConstants::TARGETCRS, false); - targetCRS()->_exportToWKT(formatter); - formatter->endNode(); + const bool canExportOperationId = + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId()); + + const bool hasDomains = !domains().empty(); + if (hasDomains) { + formatter->pushDisableUsage(); + } for (const auto &operation : operations()) { formatter->startNode(io::WKTConstants::STEP, false); - operation->_exportToWKT(formatter); + if (canExportOperationId && !operation->identifiers().empty()) { + // fake that top node has no id, so that the operation id is + // considered + formatter->pushHasId(false); + operation->_exportToWKT(formatter); + formatter->popHasId(); + } else { + operation->_exportToWKT(formatter); + } formatter->endNode(); } + if (hasDomains) { + formatter->popDisableUsage(); + } + ObjectUsage::baseExportToWKT(formatter); formatter->endNode(); } diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 9688883d..2dc6b3bf 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -2421,16 +2421,21 @@ void DerivedCRS::setDerivingConversionCRS() { // --------------------------------------------------------------------------- -void DerivedCRS::baseExportToWKT(io::WKTFormatter *&formatter, +void DerivedCRS::baseExportToWKT(io::WKTFormatter *formatter, const std::string &keyword, const std::string &baseKeyword) const { formatter->startNode(keyword, !identifiers().empty()); formatter->addQuotedString(nameStr()); const auto &l_baseCRS = d->baseCRS_; - formatter->startNode(baseKeyword, !l_baseCRS->identifiers().empty()); + formatter->startNode(baseKeyword, formatter->use2018Keywords() && + !l_baseCRS->identifiers().empty()); formatter->addQuotedString(l_baseCRS->nameStr()); l_baseCRS->exportDatumOrDatumEnsembleToWkt(formatter); + if (formatter->use2018Keywords() && + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())) { + l_baseCRS->formatID(formatter); + } formatter->endNode(); formatter->setUseDerivingConversion(true); @@ -2658,7 +2663,7 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { dynamic_cast<const GeographicCRS *>(l_baseCRS.get())) ? io::WKTConstants::BASEGEOGCRS : io::WKTConstants::BASEGEODCRS, - !l_baseCRS->identifiers().empty()); + formatter->use2018Keywords() && !l_baseCRS->identifiers().empty()); formatter->addQuotedString(l_baseCRS->nameStr()); l_baseCRS->exportDatumOrDatumEnsembleToWkt(formatter); // insert ellipsoidal cs unit when the units of the map @@ -2669,6 +2674,10 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { geodeticCRSAxisList[0]->unit()._exportToWKT(formatter); } l_baseCRS->primeMeridian()->_exportToWKT(formatter); + if (formatter->use2018Keywords() && + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())) { + l_baseCRS->formatID(formatter); + } formatter->endNode(); } else { const auto oldAxisOutputRule = formatter->outputAxis(); @@ -4848,7 +4857,7 @@ DerivedCRSTemplate<DerivedCRSTraits>::create( // --------------------------------------------------------------------------- -static void DerivedCRSTemplateCheckExportToWKT(io::WKTFormatter *&formatter, +static void DerivedCRSTemplateCheckExportToWKT(io::WKTFormatter *formatter, const std::string &crsName, bool wkt2_2018_only) { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 220ee967..578234b4 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -141,6 +141,7 @@ struct WKTFormatter::Private { std::vector<bool> stackHasChild_{}; std::vector<bool> stackHasId_{false}; std::vector<bool> stackEmptyKeyword_{}; + std::vector<bool> stackDisableUsage_{}; std::vector<bool> outputUnitStack_{true}; std::vector<bool> outputIdStack_{true}; std::vector<UnitOfMeasureNNPtr> axisLinearUnitStack_{ @@ -272,6 +273,11 @@ const std::string &WKTFormatter::toString() const { if (d->outputUnitStack_.size() != 1) throw FormattingException( "Unbalanced pushOutputUnit() / popOutputUnit()"); + if (d->stackHasId_.size() != 1) + throw FormattingException("Unbalanced pushHasId() / popHasId()"); + if (!d->stackDisableUsage_.empty()) + throw FormattingException( + "Unbalanced pushDisableUsage() / popDisableUsage()"); return d->result_; } @@ -556,6 +562,28 @@ bool WKTFormatter::outputId() const { // --------------------------------------------------------------------------- +void WKTFormatter::pushHasId(bool hasId) { d->stackHasId_.push_back(hasId); } + +// --------------------------------------------------------------------------- + +void WKTFormatter::popHasId() { d->stackHasId_.pop_back(); } + +// --------------------------------------------------------------------------- + +void WKTFormatter::pushDisableUsage() { d->stackDisableUsage_.push_back(true); } + +// --------------------------------------------------------------------------- + +void WKTFormatter::popDisableUsage() { d->stackDisableUsage_.pop_back(); } + +// --------------------------------------------------------------------------- + +bool WKTFormatter::outputUsage() const { + return outputId() && d->stackDisableUsage_.empty(); +} + +// --------------------------------------------------------------------------- + void WKTFormatter::pushAxisLinearUnit(const UnitOfMeasureNNPtr &unit) { d->axisLinearUnitStack_.push_back(unit); } @@ -634,6 +662,18 @@ bool WKTFormatter::primeMeridianInDegree() const { // --------------------------------------------------------------------------- +bool WKTFormatter::idOnTopLevelOnly() const { + return d->params_.idOnTopLevelOnly_; +} + +// --------------------------------------------------------------------------- + +bool WKTFormatter::topLevelHasId() const { + return d->stackHasId_.size() >= 2 && d->stackHasId_[1]; +} + +// --------------------------------------------------------------------------- + WKTFormatter::Version WKTFormatter::version() const { return d->params_.version_; } diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist index a2e2cab9..eaa10689 100644 --- a/test/cli/testprojinfo_out.dist +++ b/test/cli/testprojinfo_out.dist @@ -193,10 +193,6 @@ COORDINATEOPERATION["Ballpark geographic offset from NAD27 to NAD83", AXIS["geodetic longitude (Lon)",east, ORDER[2], ANGLEUNIT["degree",0.0174532925199433]], - USAGE[ - SCOPE["unknown"], - AREA["North America - NAD27"], - BBOX[7.15,167.65,83.17,-47.74]], ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", @@ -212,10 +208,6 @@ COORDINATEOPERATION["Ballpark geographic offset from NAD27 to NAD83", AXIS["geodetic longitude (Lon)",east, ORDER[2], ANGLEUNIT["degree",0.0174532925199433]], - USAGE[ - SCOPE["unknown"], - AREA["North America - NAD83"], - BBOX[14.92,167.65,86.46,-47.74]], ID["EPSG",4269]]], METHOD["Geographic2D offsets", ID["EPSG",9619]], @@ -265,7 +257,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (3)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", DATUM["North American Datum 1983", @@ -279,7 +272,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (3)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4269]]], METHOD["NTv1", ID["EPSG",9614]], PARAMETERFILE["Latitude and longitude difference file","ntv1_can.dat"], @@ -313,7 +307,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (4)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", DATUM["North American Datum 1983", @@ -327,7 +322,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (4)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4269]]], METHOD["NTv2", ID["EPSG",9615]], PARAMETERFILE["Latitude and longitude difference file","ntv2_0.gsb"], @@ -361,7 +357,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (1)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", DATUM["North American Datum 1983", @@ -375,7 +372,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (1)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4269]]], METHOD["CTABLE2"], PARAMETERFILE["Latitude and longitude difference file","conus"], OPERATIONACCURACY[0.15], @@ -408,7 +406,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (2)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", DATUM["North American Datum 1983", @@ -422,7 +421,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (2)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4269]]], METHOD["CTABLE2"], PARAMETERFILE["Latitude and longitude difference file","alaska"], OPERATIONACCURACY[0.5], @@ -455,7 +455,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (5)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", DATUM["North American Datum 1983", @@ -469,7 +470,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (5)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4269]]], METHOD["NTv1", ID["EPSG",9614]], PARAMETERFILE["Latitude and longitude difference file","GS2783v1.QUE"], @@ -503,7 +505,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (6)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", DATUM["North American Datum 1983", @@ -517,7 +520,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (6)", ANGLEUNIT["degree",0.0174532925199433]], AXIS["geodetic longitude (Lon)",east, ORDER[2], - ANGLEUNIT["degree",0.0174532925199433]]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4269]]], METHOD["NTv2", ID["EPSG",9615]], PARAMETERFILE["Latitude and longitude difference file","QUE27-83.gsb"], @@ -552,10 +556,6 @@ COORDINATEOPERATION["Ballpark geographic offset from NAD27 to NAD83", AXIS["geodetic longitude (Lon)",east, ORDER[2], ANGLEUNIT["degree",0.0174532925199433]], - USAGE[ - SCOPE["unknown"], - AREA["North America - NAD27"], - BBOX[7.15,167.65,83.17,-47.74]], ID["EPSG",4267]]], TARGETCRS[ GEOGCRS["NAD83", @@ -571,10 +571,6 @@ COORDINATEOPERATION["Ballpark geographic offset from NAD27 to NAD83", AXIS["geodetic longitude (Lon)",east, ORDER[2], ANGLEUNIT["degree",0.0174532925199433]], - USAGE[ - SCOPE["unknown"], - AREA["North America - NAD83"], - BBOX[14.92,167.65,86.46,-47.74]], ID["EPSG",4269]]], METHOD["Geographic2D offsets", ID["EPSG",9619]], @@ -633,7 +629,8 @@ PROJCRS["Monte Mario (Rome) / Italy zone 1", ELLIPSOID["International 1924",6378388,297, LENGTHUNIT["metre",1]]], PRIMEM["Rome",12.4523333333333, - ANGLEUNIT["degree",0.0174532925199433]]], + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4806]], CONVERSION["Italy zone 1", METHOD["Transverse Mercator", ID["EPSG",9807]], @@ -711,7 +708,8 @@ COORDINATEOPERATION["RH2000 height to SWEREF99", VDATUM["Rikets hojdsystem 2000"], CS[vertical,1], AXIS["gravity-related height (H)",up, - LENGTHUNIT["metre",1]]]], + LENGTHUNIT["metre",1]], + ID["EPSG",5613]]], TARGETCRS[ GEOGCRS["SWEREF99 (3D)", DATUM["SWEREF99", @@ -728,7 +726,8 @@ COORDINATEOPERATION["RH2000 height to SWEREF99", ANGLEUNIT["degree minute second hemisphere",0.0174532925199433]], AXIS["ellipsoidal height (h)",up, ORDER[3], - LENGTHUNIT["metre",1]]]], + LENGTHUNIT["metre",1]], + ID["EPSG",4377]]], METHOD["GravityRelatedHeight to Geographic3D", ID["PROJ","HEIGHT_TO_GEOGRAPHIC3D"]], PARAMETERFILE["Geoid (height correction) model file","SWEN17_RH2000.gtx"], diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index 4953529c..d7303df9 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -148,32 +148,72 @@ TEST(crs, GeographicCRS_datum_ensemble) { std::vector<DatumNNPtr>{GeodeticReferenceFrame::EPSG_6326, GeodeticReferenceFrame::EPSG_6326}, PositionalAccuracy::create("100")); - auto crs = GeographicCRS::create( - PropertyMap().set(IdentifiedObject::NAME_KEY, "unnamed"), nullptr, - ensemble_vdatum, - EllipsoidalCS::createLatitudeLongitude(UnitOfMeasure::DEGREE)); - WKTFormatterNNPtr f( - WKTFormatter::create(WKTFormatter::Convention::WKT2_2018)); - f->simulCurNodeHasId(); - crs->exportToWKT(f.get()); - auto expected = "GEOGCRS[\"unnamed\",\n" - " ENSEMBLE[\"unnamed\",\n" - " MEMBER[\"World Geodetic System 1984\"],\n" - " MEMBER[\"World Geodetic System 1984\"],\n" - " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" - " LENGTHUNIT[\"metre\",1]],\n" - " ENSEMBLEACCURACY[100]],\n" - " PRIMEM[\"Greenwich\",0,\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" - " CS[ellipsoidal,2],\n" - " AXIS[\"latitude\",north,\n" - " ORDER[1],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" - " AXIS[\"longitude\",east,\n" - " ORDER[2],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]]]"; + { + auto crs = GeographicCRS::create( + PropertyMap() + .set(IdentifiedObject::NAME_KEY, "unnamed") + .set(Identifier::CODESPACE_KEY, "MY_CODESPACE") + .set(Identifier::CODE_KEY, "MY_ID"), + nullptr, ensemble_vdatum, + EllipsoidalCS::createLatitudeLongitude(UnitOfMeasure::DEGREE)); + WKTFormatterNNPtr f( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2018)); + crs->exportToWKT(f.get()); + auto expected = + "GEOGCRS[\"unnamed\",\n" + " ENSEMBLE[\"unnamed\",\n" + " MEMBER[\"World Geodetic System 1984\"],\n" + " MEMBER[\"World Geodetic System 1984\"],\n" + " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ENSEMBLEACCURACY[100]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " CS[ellipsoidal,2],\n" + " AXIS[\"latitude\",north,\n" + " ORDER[1],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " AXIS[\"longitude\",east,\n" + " ORDER[2],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"MY_CODESPACE\",\"MY_ID\"]]"; - EXPECT_EQ(f->toString(), expected); + EXPECT_EQ(f->toString(), expected); + } + + { + auto crs = GeographicCRS::create( + PropertyMap().set(IdentifiedObject::NAME_KEY, "unnamed"), nullptr, + ensemble_vdatum, + EllipsoidalCS::createLatitudeLongitude(UnitOfMeasure::DEGREE)); + WKTFormatterNNPtr f( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2018)); + crs->exportToWKT(f.get()); + auto expected = "GEOGCRS[\"unnamed\",\n" + " ENSEMBLE[\"unnamed\",\n" + " MEMBER[\"World Geodetic System 1984\",\n" + " ID[\"EPSG\",6326]],\n" + " MEMBER[\"World Geodetic System 1984\",\n" + " ID[\"EPSG\",6326]],\n" + " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",7030]],\n" + " ENSEMBLEACCURACY[100]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433],\n" + " ID[\"EPSG\",8901]],\n" + " CS[ellipsoidal,2],\n" + " AXIS[\"latitude\",north,\n" + " ORDER[1],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433,\n" + " ID[\"EPSG\",9122]]],\n" + " AXIS[\"longitude\",east,\n" + " ORDER[2],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433,\n" + " ID[\"EPSG\",9122]]]]"; + + EXPECT_EQ(f->toString(), expected); + } } // --------------------------------------------------------------------------- @@ -1561,6 +1601,52 @@ TEST(crs, projectedCRS_as_WKT2) { // --------------------------------------------------------------------------- +TEST(crs, projectedCRS_as_WKT2_2018) { + auto crs = createProjected(); + + auto expected = + "PROJCRS[\"WGS 84 / UTM zone 31N\",\n" + " BASEGEOGCRS[\"WGS 84\",\n" + " DATUM[\"World Geodetic System 1984\",\n" + " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" + " LENGTHUNIT[\"metre\",1]]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4326]],\n" + " CONVERSION[\"UTM zone 31N\",\n" + " METHOD[\"Transverse Mercator\",\n" + " ID[\"EPSG\",9807]],\n" + " PARAMETER[\"Latitude of natural origin\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433],\n" + " ID[\"EPSG\",8801]],\n" + " PARAMETER[\"Longitude of natural origin\",3,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433],\n" + " ID[\"EPSG\",8802]],\n" + " PARAMETER[\"Scale factor at natural origin\",0.9996,\n" + " SCALEUNIT[\"unity\",1],\n" + " ID[\"EPSG\",8805]],\n" + " PARAMETER[\"False easting\",500000,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8806]],\n" + " PARAMETER[\"False northing\",0,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8807]]],\n" + " CS[Cartesian,2],\n" + " AXIS[\"(E)\",east,\n" + " ORDER[1],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " AXIS[\"(N)\",north,\n" + " ORDER[2],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ID[\"EPSG\",32631]]"; + + EXPECT_EQ( + crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2018).get()), + expected); +} +// --------------------------------------------------------------------------- + TEST(crs, projectedCRS_as_WKT2_simplified) { auto crs = createProjected(); @@ -4522,7 +4608,8 @@ TEST(crs, DerivedVerticalCRS_WKT2) { auto expected = "VERTCRS[\"Derived vertCRS\",\n" " BASEVERTCRS[\"ODN height\",\n" - " VDATUM[\"Ordnance Datum Newlyn\"]],\n" + " VDATUM[\"Ordnance Datum Newlyn\",\n" + " ID[\"EPSG\",5101]]],\n" " DERIVINGCONVERSION[\"unnamed\",\n" " METHOD[\"PROJ unimplemented\"]],\n" " CS[vertical,1],\n" diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index 944e0ebe..f4c560d5 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -734,7 +734,8 @@ TEST(factory, AuthorityFactory_createCoordinateOperation_helmert_15_CF) { " LENGTHUNIT[\"metre\",1]],\n" " AXIS[\"(Z)\",geocentricZ,\n" " ORDER[3],\n" - " LENGTHUNIT[\"metre\",1]]]],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ID[\"EPSG\",5332]]],\n" " TARGETCRS[\n" " GEODCRS[\"GDA94\",\n" " DATUM[\"Geocentric Datum of Australia 1994\",\n" @@ -751,7 +752,8 @@ TEST(factory, AuthorityFactory_createCoordinateOperation_helmert_15_CF) { " LENGTHUNIT[\"metre\",1]],\n" " AXIS[\"(Z)\",geocentricZ,\n" " ORDER[3],\n" - " LENGTHUNIT[\"metre\",1]]]],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ID[\"EPSG\",4938]]],\n" " METHOD[\"Time-dependent Coordinate Frame rotation (geocen)\",\n" " ID[\"EPSG\",1056]],\n" " PARAMETER[\"X-axis translation\",-84.68,\n" @@ -885,7 +887,8 @@ TEST( " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" " AXIS[\"geodetic longitude (Lon)\",east,\n" " ORDER[2],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]]]],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4749]]],\n" " TARGETCRS[\n" " GEOGCRS[\"NEA74 Noumea\",\n" " DATUM[\"NEA74 Noumea\",\n" @@ -899,7 +902,8 @@ TEST( " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" " AXIS[\"geodetic longitude (Lon)\",east,\n" " ORDER[2],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]]]],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4644]]],\n" " METHOD[\"NTv2\",\n" " ID[\"EPSG\",9615]],\n" " PARAMETERFILE[\"Latitude and longitude difference " @@ -953,7 +957,8 @@ TEST(factory, AuthorityFactory_createCoordinateOperation_other_transformation) { " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" " AXIS[\"geodetic longitude (Lon)\",east,\n" " ORDER[2],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]]]],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4818]]],\n" " TARGETCRS[\n" " GEOGCRS[\"S-JTSK\",\n" " DATUM[\"System of the Unified Trigonometrical Cadastral " @@ -968,7 +973,8 @@ TEST(factory, AuthorityFactory_createCoordinateOperation_other_transformation) { " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" " AXIS[\"geodetic longitude (Lon)\",east,\n" " ORDER[2],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]]]],\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4156]]],\n" " METHOD[\"Longitude rotation\",\n" " ID[\"EPSG\",9601]],\n" " PARAMETER[\"Longitude offset\",-17.6666666666667,\n" diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 1d097d9b..17b3c334 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -1663,6 +1663,50 @@ TEST(wkt_parse, wkt2_2018_projected_with_id_in_basegeodcrs) { ASSERT_TRUE(crs != nullptr); ASSERT_EQ(crs->baseCRS()->identifiers().size(), 1U); EXPECT_EQ(crs->baseCRS()->identifiers().front()->code(), "4326"); + + { + auto got_wkt = crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2018).get()); + EXPECT_TRUE(got_wkt.find("ID[\"EPSG\",4326]]") != std::string::npos) + << got_wkt; + } + + { + auto got_wkt = crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2018_SIMPLIFIED) + .get()); + EXPECT_TRUE(got_wkt.find("ID[\"EPSG\",4326]]") == std::string::npos) + << got_wkt; + } +} + +// --------------------------------------------------------------------------- + +TEST(wkt_parse, wkt2_2018_projected_no_id_but_id_in_basegeodcrs) { + auto wkt = "PROJCRS[\"WGS 84 / UTM zone 31N\",\n" + " BASEGEOGCRS[\"WGS 84\",\n" + " DATUM[\"World Geodetic System 1984\",\n" + " ELLIPSOID[\"WGS 84\",6378137,298.257223563]],\n" + " ID[\"EPSG\",4326]],\n" + " CONVERSION[\"UTM zone 31N\",\n" + " METHOD[\"Transverse Mercator\"],\n" + " PARAMETER[\"Latitude of natural origin\",0],\n" + " PARAMETER[\"Longitude of natural origin\",3],\n" + " PARAMETER[\"Scale factor at natural origin\",0.9996],\n" + " PARAMETER[\"False easting\",500000],\n" + " PARAMETER[\"False northing\",0]],\n" + " CS[Cartesian,2],\n" + " AXIS[\"(E)\",east],\n" + " AXIS[\"(N)\",north],\n" + " UNIT[\"metre\",1]]"; + auto obj = WKTParser().createFromWKT(wkt); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + + auto got_wkt = crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2018).get()); + EXPECT_TRUE(got_wkt.find("ID[\"EPSG\",4326]]") != std::string::npos) + << got_wkt; } // --------------------------------------------------------------------------- diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index 9111b862..848fb23b 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -442,7 +442,6 @@ TEST(operation, concatenated_operation) { { auto formatter = WKTFormatter::create(WKTFormatter::Convention::WKT2_2018); - formatter->setOutputId(false); src_wkt = GeographicCRS::EPSG_4326->exportToWKT(formatter.get()); } @@ -450,7 +449,6 @@ TEST(operation, concatenated_operation) { { auto formatter = WKTFormatter::create(WKTFormatter::Convention::WKT2_2018); - formatter->setOutputId(false); dst_wkt = GeographicCRS::EPSG_4979->exportToWKT(formatter.get()); } @@ -458,7 +456,6 @@ TEST(operation, concatenated_operation) { { auto formatter = WKTFormatter::create(WKTFormatter::Convention::WKT2_2018); - formatter->setOutputId(false); step1_wkt = transf_1->exportToWKT(formatter.get()); } @@ -466,7 +463,6 @@ TEST(operation, concatenated_operation) { { auto formatter = WKTFormatter::create(WKTFormatter::Convention::WKT2_2018); - formatter->setOutputId(false); step2_wkt = transf_2->exportToWKT(formatter.get()); } |
