aboutsummaryrefslogtreecommitdiff
path: root/src/iso19111
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2021-09-02 09:19:22 +0200
committerEven Rouault <even.rouault@spatialys.com>2021-09-02 09:19:22 +0200
commitf19b2948efcb7433d41e51d5128c5baa68261599 (patch)
treebc057566a951b749455c3a32e8b67052ba5a2b62 /src/iso19111
parent1b180864413fa98aed9d79868eec8ceb689421a9 (diff)
downloadPROJ-f19b2948efcb7433d41e51d5128c5baa68261599.tar.gz
PROJ-f19b2948efcb7433d41e51d5128c5baa68261599.zip
Add proj_create_conversion_pole_rotation_netcdf_cf_convention() to address netCDF datasets using a pole rotation method
Diffstat (limited to 'src/iso19111')
-rw-r--r--src/iso19111/c_api.cpp31
-rw-r--r--src/iso19111/crs.cpp4
-rw-r--r--src/iso19111/operation/conversion.cpp63
-rw-r--r--src/iso19111/operation/parammappings.cpp19
4 files changed, 116 insertions, 1 deletions
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index ace699e4..1bf6cbf0 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -7085,6 +7085,37 @@ PJ *proj_create_conversion_pole_rotation_grib_convention(
return nullptr;
}
+// ---------------------------------------------------------------------------
+
+/** \brief Instantiate a conversion based on the Pole Rotation method, using
+ * the conventions of the netCDF CF convention for the netCDF format.
+ *
+ * See
+ * osgeo::proj::operation::Conversion::createPoleRotationNetCDFCFConvention().
+ *
+ * Linear parameters are expressed in (linear_unit_name,
+ * linear_unit_conv_factor).
+ * Angular parameters are expressed in (ang_unit_name, ang_unit_conv_factor).
+ */
+PJ *proj_create_conversion_pole_rotation_netcdf_cf_convention(
+ PJ_CONTEXT *ctx, double grid_north_pole_latitude,
+ double grid_north_pole_longitude, double north_pole_grid_longitude,
+ const char *ang_unit_name, double ang_unit_conv_factor) {
+ SANITIZE_CTX(ctx);
+ try {
+ UnitOfMeasure angUnit(
+ createAngularUnit(ang_unit_name, ang_unit_conv_factor));
+ auto conv = Conversion::createPoleRotationNetCDFCFConvention(
+ PropertyMap(), Angle(grid_north_pole_latitude, angUnit),
+ Angle(grid_north_pole_longitude, angUnit),
+ Angle(north_pole_grid_longitude, angUnit));
+ return proj_create_conversion(ctx, conv);
+ } catch (const std::exception &e) {
+ proj_log_error(ctx, __FUNCTION__, e.what());
+ }
+ return nullptr;
+}
+
/* END: Generated by scripts/create_c_api_projections.py*/
// ---------------------------------------------------------------------------
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 3e825ff0..a15758ab 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -5983,7 +5983,9 @@ void DerivedGeographicCRS::_exportToPROJString(
}
if (ci_equal(methodName,
- PROJ_WKT2_NAME_METHOD_POLE_ROTATION_GRIB_CONVENTION)) {
+ PROJ_WKT2_NAME_METHOD_POLE_ROTATION_GRIB_CONVENTION) ||
+ ci_equal(methodName,
+ PROJ_WKT2_NAME_METHOD_POLE_ROTATION_NETCDF_CF_CONVENTION)) {
l_conv->_exportToPROJString(formatter);
return;
}
diff --git a/src/iso19111/operation/conversion.cpp b/src/iso19111/operation/conversion.cpp
index e884db3c..3cc452f8 100644
--- a/src/iso19111/operation/conversion.cpp
+++ b/src/iso19111/operation/conversion.cpp
@@ -2227,6 +2227,51 @@ ConversionNNPtr Conversion::createPoleRotationGRIBConvention(
// ---------------------------------------------------------------------------
+/** \brief Instantiate a conversion based on the Pole Rotation method, using
+ * the conventions of the netCDF CF convention for the netCDF format.
+ *
+ * Those are mentioned in the Note 2 of
+ * https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#_rotated_pole
+ *
+ * Several conventions for the pole rotation method exists.
+ * The parameters provided in this method are remapped to the PROJ ob_tran
+ * operation with:
+ * <pre>
+ * +proj=ob_tran +o_proj=longlat +o_lon_p=northPoleGridLongitude
+ * +o_lat_p=gridNorthPoleLatitude
+ * +lon_0=180+gridNorthPoleLongitude
+ * </pre>
+ *
+ * Another implementation of that convention is also in the netcdf-java library:
+ * https://github.com/Unidata/netcdf-java/blob/3ce72c0cd167609ed8c69152bb4a004d1daa9273/cdm/core/src/main/java/ucar/unidata/geoloc/projection/RotatedPole.java
+ *
+ * The PROJ implementation of this method assumes a spherical ellipsoid.
+ *
+ * @param properties See \ref general_properties of the conversion. If the name
+ * is not provided, it is automatically set.
+ * @param gridNorthPoleLatitude True latitude of the north pole of the rotated
+ * grid
+ * @param gridNorthPoleLongitude True longitude of the north pole of the rotated
+ * grid.
+ * @param northPoleGridLongitude Longitude of the true north pole in the rotated
+ * grid.
+ * @return a new Conversion.
+ *
+ * @since 8.2
+ */
+ConversionNNPtr Conversion::createPoleRotationNetCDFCFConvention(
+ const util::PropertyMap &properties,
+ const common::Angle &gridNorthPoleLatitude,
+ const common::Angle &gridNorthPoleLongitude,
+ const common::Angle &northPoleGridLongitude) {
+ return create(properties,
+ PROJ_WKT2_NAME_METHOD_POLE_ROTATION_NETCDF_CF_CONVENTION,
+ createParams(gridNorthPoleLatitude, gridNorthPoleLongitude,
+ northPoleGridLongitude));
+}
+
+// ---------------------------------------------------------------------------
+
/** \brief Instantiate a conversion based on the Change of Vertical Unit
* method.
*
@@ -3628,6 +3673,24 @@ void Conversion::_exportToPROJString(
formatter->addParam("o_lat_p", -southPoleLat);
formatter->addParam("lon_0", southPoleLon);
bConversionDone = true;
+ } else if (ci_equal(
+ methodName,
+ PROJ_WKT2_NAME_METHOD_POLE_ROTATION_NETCDF_CF_CONVENTION)) {
+ double gridNorthPoleLatitude = parameterValueNumeric(
+ PROJ_WKT2_NAME_PARAMETER_GRID_NORTH_POLE_LATITUDE_NETCDF_CONVENTION,
+ common::UnitOfMeasure::DEGREE);
+ double gridNorthPoleLongitude = parameterValueNumeric(
+ PROJ_WKT2_NAME_PARAMETER_GRID_NORTH_POLE_LONGITUDE_NETCDF_CONVENTION,
+ common::UnitOfMeasure::DEGREE);
+ double northPoleGridLongitude = parameterValueNumeric(
+ PROJ_WKT2_NAME_PARAMETER_NORTH_POLE_GRID_LONGITUDE_NETCDF_CONVENTION,
+ common::UnitOfMeasure::DEGREE);
+ formatter->addStep("ob_tran");
+ formatter->addParam("o_proj", "longlat");
+ formatter->addParam("o_lon_p", northPoleGridLongitude);
+ formatter->addParam("o_lat_p", gridNorthPoleLatitude);
+ formatter->addParam("lon_0", 180 + gridNorthPoleLongitude);
+ bConversionDone = true;
} else if (ci_equal(methodName, "Adams_Square_II")) {
// Look for ESRI method and parameter names (to be opposed
// to the OGC WKT2 names we use elsewhere, because there's no mapping
diff --git a/src/iso19111/operation/parammappings.cpp b/src/iso19111/operation/parammappings.cpp
index 5999d535..9acc9e93 100644
--- a/src/iso19111/operation/parammappings.cpp
+++ b/src/iso19111/operation/parammappings.cpp
@@ -1305,6 +1305,22 @@ static const ParamMapping *const paramsPoleRotationGRIBConvention[] = {
&paramSouthPoleLatGRIB, &paramSouthPoleLonGRIB, &paramAxisRotationGRIB,
nullptr};
+static const ParamMapping paramGridNorthPoleLatitudeNetCDF = {
+ PROJ_WKT2_NAME_PARAMETER_GRID_NORTH_POLE_LATITUDE_NETCDF_CONVENTION, 0,
+ nullptr, common::UnitOfMeasure::Type::ANGULAR, nullptr};
+
+static const ParamMapping paramGridNorthPoleLongitudeNetCDF = {
+ PROJ_WKT2_NAME_PARAMETER_GRID_NORTH_POLE_LONGITUDE_NETCDF_CONVENTION, 0,
+ nullptr, common::UnitOfMeasure::Type::ANGULAR, nullptr};
+
+static const ParamMapping paramNorthPoleGridLongitudeNetCDF = {
+ PROJ_WKT2_NAME_PARAMETER_NORTH_POLE_GRID_LONGITUDE_NETCDF_CONVENTION, 0,
+ nullptr, common::UnitOfMeasure::Type::ANGULAR, nullptr};
+
+static const ParamMapping *const paramsPoleRotationNetCDFCFConvention[] = {
+ &paramGridNorthPoleLatitudeNetCDF, &paramGridNorthPoleLongitudeNetCDF,
+ &paramNorthPoleGridLongitudeNetCDF, nullptr};
+
static const MethodMapping otherMethodMappings[] = {
{EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT,
EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT, nullptr, nullptr, nullptr,
@@ -1333,6 +1349,9 @@ static const MethodMapping otherMethodMappings[] = {
{PROJ_WKT2_NAME_METHOD_POLE_ROTATION_GRIB_CONVENTION, 0, nullptr, nullptr,
nullptr, paramsPoleRotationGRIBConvention},
+ {PROJ_WKT2_NAME_METHOD_POLE_ROTATION_NETCDF_CF_CONVENTION, 0, nullptr,
+ nullptr, nullptr, paramsPoleRotationNetCDFCFConvention},
+
{EPSG_NAME_METHOD_GEOCENTRIC_TRANSLATION_GEOCENTRIC,
EPSG_CODE_METHOD_GEOCENTRIC_TRANSLATION_GEOCENTRIC, nullptr, nullptr,
nullptr, paramsHelmert3},