diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2022-01-07 16:14:01 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2022-01-07 19:52:45 +0100 |
| commit | 3b4d1f324de157f2a29528a2194c6b0b52d2cd14 (patch) | |
| tree | d4a33266afbe0a287148b7da66260b02f97fea54 | |
| parent | cf5aef989b65ed857ed03d2ed3de447daaffe5a3 (diff) | |
| download | PROJ-3b4d1f324de157f2a29528a2194c6b0b52d2cd14.tar.gz PROJ-3b4d1f324de157f2a29528a2194c6b0b52d2cd14.zip | |
Map peirce_q to pseudo WKT2 and ESRI WKT
| -rw-r--r-- | scripts/build_esri_projection_mapping.py | 19 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 2 | ||||
| -rw-r--r-- | src/iso19111/operation/conversion.cpp | 24 | ||||
| -rw-r--r-- | src/iso19111/operation/esriparammappings.cpp | 31 | ||||
| -rw-r--r-- | src/iso19111/operation/parammappings.cpp | 6 | ||||
| -rw-r--r-- | src/proj_constants.h | 3 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 75 |
7 files changed, 159 insertions, 1 deletions
diff --git a/scripts/build_esri_projection_mapping.py b/scripts/build_esri_projection_mapping.py index 30f4ad6c..32920a59 100644 --- a/scripts/build_esri_projection_mapping.py +++ b/scripts/build_esri_projection_mapping.py @@ -710,6 +710,24 @@ config_str = """ - False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING - Central_Meridian: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN +- Peirce_Quincuncial: + - WKT2_name: PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_SQUARE + Params: + - False_Easting: EPSG_NAME_PARAMETER_FALSE_EASTING + - False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING + - Central_Meridian: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN + - Scale_Factor: EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN + - Latitude_Of_Origin: EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN + - Option: 0.0 + + - WKT2_name: PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_DIAMOND + Params: + - False_Easting: EPSG_NAME_PARAMETER_FALSE_EASTING + - False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING + - Central_Meridian: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN + - Scale_Factor: EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN + - Latitude_Of_Origin: EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN + - Option: 1.0 # Missing/unclear mappings @@ -748,7 +766,6 @@ config_str = """ # Polar_Stereographic_Variant_C # Quartic_Authalic_Ellipsoidal # Adams_Square_II -# Peirce_Quincuncial """ diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index ca5a3d97..fc92dbbd 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -10209,6 +10209,8 @@ PROJStringParser::Private::buildProjectedCRS(int iStep, } } else if (param->unit_type == UnitOfMeasure::Type::SCALE) { value = 1; + } else if (step.name == "peirce_q" && proj_name == "lat_0") { + value = 90; } PropertyMap propertiesParameter; diff --git a/src/iso19111/operation/conversion.cpp b/src/iso19111/operation/conversion.cpp index 77e703f3..6bccf182 100644 --- a/src/iso19111/operation/conversion.cpp +++ b/src/iso19111/operation/conversion.cpp @@ -3839,6 +3839,30 @@ void Conversion::_exportToPROJString( formatter->addParam("x_0", falseEasting); formatter->addParam("y_0", falseNorthing); bConversionDone = true; + } else if (ci_equal(methodName, + PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_SQUARE) || + ci_equal(methodName, + PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_DIAMOND)) { + const auto &scaleFactor = parameterValueMeasure( + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN); + if (scaleFactor.unit().type() != common::UnitOfMeasure::Type::UNKNOWN && + std::fabs(scaleFactor.getSIValue() - 1.0) > 1e-10) { + throw io::FormattingException( + "Only scale factor = 1 handled for Peirce Quincuncial"); + } + const double latitudeOfOriginDeg = + parameterValue(EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN) + ->value() + .unit() + .type() != common::UnitOfMeasure::Type::UNKNOWN + ? parameterValueNumeric( + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + common::UnitOfMeasure::DEGREE) + : 90.0; + if (std::fabs(latitudeOfOriginDeg - 90.0) > 1e-10) { + throw io::FormattingException("Only latitude of natural origin = " + "90 handled for Peirce Quincuncial"); + } } else if (formatter->convention() == io::PROJStringFormatter::Convention::PROJ_5 && isZUnitConversion) { diff --git a/src/iso19111/operation/esriparammappings.cpp b/src/iso19111/operation/esriparammappings.cpp index 8021b95f..a6f6c6a1 100644 --- a/src/iso19111/operation/esriparammappings.cpp +++ b/src/iso19111/operation/esriparammappings.cpp @@ -947,6 +947,33 @@ static const ESRIParamMapping paramsESRI_Equal_Earth[] = { EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, "0.0", false}, {nullptr, nullptr, 0, "0.0", false}}; +static const ESRIParamMapping paramsESRI_Peirce_Quincuncial_alt1[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, "0.0", false}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, "0.0", false}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, "0.0", false}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, "0.0", false}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, "0.0", false}, + {"Option", nullptr, 0, "0.0", false}, + {nullptr, nullptr, 0, "0.0", false}}; +static const ESRIParamMapping paramsESRI_Peirce_Quincuncial_alt2[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, "0.0", false}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, "0.0", false}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, "0.0", false}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, "0.0", false}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, "0.0", false}, + {"Option", nullptr, 0, "1.0", false}, + {nullptr, nullptr, 0, "0.0", false}}; + static const ESRIMethodMapping esriMappings[] = { {"Plate_Carree", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL, EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL, paramsESRI_Plate_Carree}, @@ -1115,6 +1142,10 @@ static const ESRIMethodMapping esriMappings[] = { EPSG_CODE_METHOD_COLOMBIA_URBAN, paramsESRI_IGAC_Plano_Cartesiano}, {"Equal_Earth", EPSG_NAME_METHOD_EQUAL_EARTH, EPSG_CODE_METHOD_EQUAL_EARTH, paramsESRI_Equal_Earth}, + {"Peirce_Quincuncial", PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_SQUARE, 0, + paramsESRI_Peirce_Quincuncial_alt1}, + {"Peirce_Quincuncial", PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_DIAMOND, 0, + paramsESRI_Peirce_Quincuncial_alt2}, }; // --------------------------------------------------------------------------- diff --git a/src/iso19111/operation/parammappings.cpp b/src/iso19111/operation/parammappings.cpp index af1309b3..dd94e267 100644 --- a/src/iso19111/operation/parammappings.cpp +++ b/src/iso19111/operation/parammappings.cpp @@ -793,6 +793,12 @@ static const MethodMapping projectionMethodMappings[] = { {PROJ_WKT2_NAME_METHOD_ROBINSON, 0, "Robinson", "robin", nullptr, paramsLonNatOriginLongitudeCentre}, + {PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_SQUARE, 0, nullptr, "peirce_q", + "shape=square", paramsNatOriginScale}, + + {PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_DIAMOND, 0, nullptr, "peirce_q", + "shape=diamond", paramsNatOriginScale}, + {PROJ_WKT2_NAME_METHOD_SINUSOIDAL, 0, "Sinusoidal", "sinu", nullptr, paramsLonNatOriginLongitudeCentre}, diff --git a/src/proj_constants.h b/src/proj_constants.h index 815511fe..1da63474 100644 --- a/src/proj_constants.h +++ b/src/proj_constants.h @@ -248,6 +248,9 @@ #define EPSG_CODE_METHOD_COLOMBIA_URBAN 1052 #define EPSG_NAME_METHOD_COLOMBIA_URBAN "Colombia Urban" +#define PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_SQUARE "Peirce Quincuncial (Square)" +#define PROJ_WKT2_NAME_METHOD_PEIRCE_QUINCUNCIAL_DIAMOND "Peirce Quincuncial (Diamond)" + /* ------------------------------------------------------------------------ */ /* Projection parameters */ diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 5ffa461b..1c7fc812 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -6075,6 +6075,38 @@ static const struct { {"False northing", 2}, }}, + {"Peirce_Quincuncial", + {{"False_Easting", 1}, + {"False_Northing", 2}, + {"Central_Meridian", 3}, + {"Scale_Factor", 4}, + {"Latitude_Of_Origin", 5}, + {"Option", 0}}, + "Peirce Quincuncial (Square)", + { + {"Latitude of natural origin", 5}, + {"Longitude of natural origin", 3}, + {"Scale factor at natural origin", 4}, + {"False easting", 1}, + {"False northing", 2}, + }}, + + {"Peirce_Quincuncial", + {{"False_Easting", 1}, + {"False_Northing", 2}, + {"Central_Meridian", 3}, + {"Scale_Factor", 4}, + {"Latitude_Of_Origin", 5}, + {"Option", 1}}, + "Peirce Quincuncial (Diamond)", + { + {"Latitude of natural origin", 5}, + {"Longitude of natural origin", 3}, + {"Scale factor at natural origin", 4}, + {"False easting", 1}, + {"False northing", 2}, + }}, + { "Unknown_Method", {{"False_Easting", 1}, @@ -9931,6 +9963,49 @@ TEST(io, projparse_ortho_spherical_on_sphere) { // --------------------------------------------------------------------------- +TEST(io, projparse_peirce_q) { + std::string input("+proj=peirce_q +shape=square +type=crs"); + auto obj = PROJStringParser().createFromPROJString(input); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ( + crs->exportToPROJString( + PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4) + .get()), + "+proj=peirce_q +shape=square +lat_0=90 +lon_0=0 +k_0=1 +x_0=0 +y_0=0 " + "+datum=WGS84 +units=m +no_defs +type=crs"); +} + +// --------------------------------------------------------------------------- + +TEST(io, projparse_peirce_q_invalid_lat_0) { + std::string input("+proj=peirce_q +lat_0=0 +shape=square +type=crs"); + auto obj = PROJStringParser().createFromPROJString(input); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_THROW( + crs->exportToPROJString( + PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4) + .get()), + FormattingException); +} + +// --------------------------------------------------------------------------- + +TEST(io, projparse_peirce_q_invalid_k_0) { + std::string input("+proj=peirce_q +k_0=0.5 +shape=square +type=crs"); + auto obj = PROJStringParser().createFromPROJString(input); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_THROW( + crs->exportToPROJString( + PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4) + .get()), + FormattingException); +} + +// --------------------------------------------------------------------------- + TEST(io, projparse_axisswap_unitconvert_longlat_proj) { std::string input = "+type=crs +proj=pipeline +step +proj=axisswap +order=2,1 +step " |
