diff options
Diffstat (limited to 'src/iso19111/io.cpp')
| -rw-r--r-- | src/iso19111/io.cpp | 129 |
1 files changed, 113 insertions, 16 deletions
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 50ad5a87..645bec0b 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -89,7 +89,7 @@ static const std::string emptyString{}; // If changing that value, change it in data/projjson.schema.json as well #define PROJJSON_CURRENT_VERSION \ - "https://proj.org/schemas/v0.1/projjson.schema.json" + "https://proj.org/schemas/v0.2/projjson.schema.json" //! @endcond #if 0 @@ -3873,28 +3873,110 @@ CRSNNPtr WKTParser::Private::buildVerticalCRS(const WKTNodeNNPtr &node) { ThrowNotExpectedCSType("vertical"); } + auto &props = buildProperties(node); + + // Deal with Lidar WKT1 VertCRS that embeds geoid model in CRS name, + // following conventions from + // https://pubs.usgs.gov/tm/11b4/pdf/tm11-B4.pdf + // page 9 + if (ci_equal(nodeValue, WKTConstants::VERT_CS)) { + std::string name; + if (props.getStringValue(IdentifiedObject::NAME_KEY, name)) { + std::string geoidName; + for (const char *prefix : + {"NAVD88 - ", "NAVD88 via ", "NAVD88 height - ", + "NAVD88 height (ftUS) - "}) { + if (starts_with(name, prefix)) { + geoidName = name.substr(strlen(prefix)); + auto pos = geoidName.find_first_of(" ("); + if (pos != std::string::npos) { + geoidName.resize(pos); + } + break; + } + } + if (!geoidName.empty()) { + const auto &axis = verticalCS->axisList()[0]; + const auto &dir = axis->direction(); + if (dir == cs::AxisDirection::UP) { + if (axis->unit() == common::UnitOfMeasure::METRE) { + props.set(IdentifiedObject::NAME_KEY, "NAVD88 height"); + props.set(Identifier::CODE_KEY, 5703); + props.set(Identifier::CODESPACE_KEY, Identifier::EPSG); + } else if (axis->unit().name() == "US survey foot") { + props.set(IdentifiedObject::NAME_KEY, + "NAVD88 height (ftUS)"); + props.set(Identifier::CODE_KEY, 6360); + props.set(Identifier::CODESPACE_KEY, Identifier::EPSG); + } + } + PropertyMap propsModel; + propsModel.set(IdentifiedObject::NAME_KEY, toupper(geoidName)); + PropertyMap propsDatum; + propsDatum.set(IdentifiedObject::NAME_KEY, + "North American Vertical Datum 1988"); + propsDatum.set(Identifier::CODE_KEY, 5103); + propsDatum.set(Identifier::CODESPACE_KEY, Identifier::EPSG); + datum = + VerticalReferenceFrame::create(propsDatum).as_nullable(); + const auto dummyCRS = + VerticalCRS::create(PropertyMap(), datum, datumEnsemble, + NN_NO_CHECK(verticalCS)); + const auto model(Transformation::create( + propsModel, dummyCRS, dummyCRS, nullptr, + OperationMethod::create( + PropertyMap(), std::vector<OperationParameterNNPtr>()), + {}, {})); + props.set("GEOID_MODEL", model); + } + } + } + + auto &geoidModelNode = nodeP->lookForChild(WKTConstants::GEOIDMODEL); + if (!isNull(geoidModelNode)) { + auto &propsModel = buildProperties(geoidModelNode); + const auto dummyCRS = VerticalCRS::create( + PropertyMap(), datum, datumEnsemble, NN_NO_CHECK(verticalCS)); + const auto model(Transformation::create( + propsModel, dummyCRS, dummyCRS, nullptr, + OperationMethod::create(PropertyMap(), + std::vector<OperationParameterNNPtr>()), + {}, {})); + props.set("GEOID_MODEL", model); + } + auto crs = nn_static_pointer_cast<CRS>(VerticalCRS::create( - buildProperties(node), datum, datumEnsemble, NN_NO_CHECK(verticalCS))); + props, datum, datumEnsemble, NN_NO_CHECK(verticalCS))); if (!isNull(datumNode)) { auto &extensionNode = datumNode->lookForChild(WKTConstants::EXTENSION); const auto &extensionChildren = extensionNode->GP()->children(); if (extensionChildren.size() == 2) { if (ci_equal(stripQuotes(extensionChildren[0]), "PROJ4_GRIDS")) { - std::string transformationName(crs->nameStr()); - if (!ends_with(transformationName, " height")) { - transformationName += " height"; + const auto gridName(stripQuotes(extensionChildren[1])); + // This is the expansion of EPSG:5703 by old GDAL versions. + // See + // https://trac.osgeo.org/metacrs/changeset?reponame=&new=2281%40geotiff%2Ftrunk%2Flibgeotiff%2Fcsv%2Fvertcs.override.csv&old=1893%40geotiff%2Ftrunk%2Flibgeotiff%2Fcsv%2Fvertcs.override.csv + // It is unlikely that the user really explictly wants this. + if (gridName != "g2003conus.gtx,g2003alaska.gtx," + "g2003h01.gtx,g2003p01.gtx" && + gridName != "g2012a_conus.gtx,g2012a_alaska.gtx," + "g2012a_guam.gtx,g2012a_hawaii.gtx," + "g2012a_puertorico.gtx,g2012a_samoa.gtx") { + std::string transformationName(crs->nameStr()); + if (!ends_with(transformationName, " height")) { + transformationName += " height"; + } + transformationName += " to WGS84 ellipsoidal height"; + auto transformation = Transformation:: + createGravityRelatedHeightToGeographic3D( + PropertyMap().set(IdentifiedObject::NAME_KEY, + transformationName), + crs, GeographicCRS::EPSG_4979, nullptr, gridName, + std::vector<PositionalAccuracyNNPtr>()); + return nn_static_pointer_cast<CRS>(BoundCRS::create( + crs, GeographicCRS::EPSG_4979, transformation)); } - transformationName += " to WGS84 ellipsoidal height"; - auto transformation = - Transformation::createGravityRelatedHeightToGeographic3D( - PropertyMap().set(IdentifiedObject::NAME_KEY, - transformationName), - crs, GeographicCRS::EPSG_4979, nullptr, - stripQuotes(extensionChildren[1]), - std::vector<PositionalAccuracyNNPtr>()); - return nn_static_pointer_cast<CRS>(BoundCRS::create( - crs, GeographicCRS::EPSG_4979, transformation)); } } } @@ -5040,7 +5122,22 @@ VerticalCRSNNPtr JSONParser::buildVerticalCRS(const json &j) { if (!verticalCS) { throw ParsingException("expected a vertical CS"); } - return VerticalCRS::create(buildProperties(j), datum, datumEnsemble, + + auto props = buildProperties(j); + if (j.contains("geoid_model")) { + auto geoidModelJ = getObject(j, "geoid_model"); + auto propsModel = buildProperties(geoidModelJ); + const auto dummyCRS = VerticalCRS::create( + PropertyMap(), datum, datumEnsemble, NN_NO_CHECK(verticalCS)); + const auto model(Transformation::create( + propsModel, dummyCRS, dummyCRS, nullptr, + OperationMethod::create(PropertyMap(), + std::vector<OperationParameterNNPtr>()), + {}, {})); + props.set("GEOID_MODEL", model); + } + + return VerticalCRS::create(props, datum, datumEnsemble, NN_NO_CHECK(verticalCS)); } |
