aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2022-01-07 16:14:01 +0100
committerEven Rouault <even.rouault@spatialys.com>2022-01-07 19:52:45 +0100
commit3b4d1f324de157f2a29528a2194c6b0b52d2cd14 (patch)
treed4a33266afbe0a287148b7da66260b02f97fea54
parentcf5aef989b65ed857ed03d2ed3de447daaffe5a3 (diff)
downloadPROJ-3b4d1f324de157f2a29528a2194c6b0b52d2cd14.tar.gz
PROJ-3b4d1f324de157f2a29528a2194c6b0b52d2cd14.zip
Map peirce_q to pseudo WKT2 and ESRI WKT
-rw-r--r--scripts/build_esri_projection_mapping.py19
-rw-r--r--src/iso19111/io.cpp2
-rw-r--r--src/iso19111/operation/conversion.cpp24
-rw-r--r--src/iso19111/operation/esriparammappings.cpp31
-rw-r--r--src/iso19111/operation/parammappings.cpp6
-rw-r--r--src/proj_constants.h3
-rw-r--r--test/unit/test_io.cpp75
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 "