Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 9.5] WKT1 ESRI export: fix wrong mapping of Lambert Cylindrical Equal Area to Behrmann #4329

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 23 additions & 20 deletions scripts/build_esri_projection_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
# Map methods from pe_list_projection.csv to WKT2 naming

config_str = """

- Equidistant_Cylindrical:
WKT2_name: EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL
Params:
- False_Easting: EPSG_NAME_PARAMETER_FALSE_EASTING
- False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING
- Central_Meridian: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN
- Standard_Parallel_1: EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL

- Plate_Carree:
WKT2_name:
- EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL
Expand All @@ -45,14 +54,6 @@
Cond:
- EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL = 0

- Equidistant_Cylindrical:
WKT2_name: EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL
Params:
- False_Easting: EPSG_NAME_PARAMETER_FALSE_EASTING
- False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING
- Central_Meridian: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN
- Standard_Parallel_1: EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL

- Miller_Cylindrical:
WKT2_name: PROJ_WKT2_NAME_METHOD_MILLER_CYLINDRICAL
Params:
Expand Down Expand Up @@ -168,18 +169,6 @@
- False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING
- Central_Meridian: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN

- Behrmann:
WKT2_name: EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA
Params:
- False_Easting: EPSG_NAME_PARAMETER_FALSE_EASTING
- False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING
- Central_Meridian:
Name: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN
Default: 0.0
- Standard_Parallel_1:
Name: EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL
Default: 30.0

- Winkel_I:
WKT2_name: "Winkel I"
Params:
Expand Down Expand Up @@ -365,6 +354,20 @@
- Central_Meridian: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN
- Standard_Parallel_1: EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL

- Behrmann:
WKT2_name: EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA
Params:
- False_Easting: EPSG_NAME_PARAMETER_FALSE_EASTING
- False_Northing: EPSG_NAME_PARAMETER_FALSE_NORTHING
- Central_Meridian:
Name: EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN
Default: 0.0
- Standard_Parallel_1:
Name: EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL
Default: 30.0
Cond:
- EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL = 30

# No example in pe_list_projection.csv: temptative mapping !
- Hotine_Oblique_Mercator_Two_Point_Center:
WKT2_name: PROJ_WKT2_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN
Expand Down
10 changes: 10 additions & 0 deletions src/iso19111/operation/conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3206,6 +3206,16 @@ static void getESRIMethodNameAndParams(const Conversion *conv,
} else {
esriMethodName = "Stereographic_South_Pole";
}
} else if (esriMapping->epsg_code ==
EPSG_CODE_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA) {
if (std::abs(conv->parameterValueNumeric(
EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
common::UnitOfMeasure::DEGREE) -
30.0) < 1e-10) {
esriMethodName = "Behrmann";
} else {
esriMethodName = "Cylindrical_Equal_Area";
}
}
}
}
Expand Down
40 changes: 20 additions & 20 deletions src/iso19111/operation/esriparammappings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,24 @@ namespace operation {

//! @cond Doxygen_Suppress

const ESRIParamMapping paramsESRI_Plate_Carree[] = {
const ESRIParamMapping paramsESRI_Equidistant_Cylindrical[] = {
{"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},
{"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, "0.0", false},
{nullptr, nullptr, 0, "0.0", false}};

const ESRIParamMapping paramsESRI_Equidistant_Cylindrical[] = {
const ESRIParamMapping paramsESRI_Plate_Carree[] = {
{"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},
{"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, "0.0", false},
{nullptr, nullptr, 0, "0.0", false}};

static const ESRIParamMapping paramsESRI_Miller_Cylindrical[] = {
Expand Down Expand Up @@ -221,17 +221,6 @@ static const ESRIParamMapping paramsESRI_Gall_Stereographic[] = {
EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, "0.0", false},
{nullptr, nullptr, 0, "0.0", false}};

static const ESRIParamMapping paramsESRI_Behrmann[] = {
{"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", true},
{"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, "30.0", true},
{nullptr, nullptr, 0, "0.0", false}};

static const ESRIParamMapping paramsESRI_Winkel_I[] = {
{"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING,
EPSG_CODE_PARAMETER_FALSE_EASTING, "0.0", false},
Expand Down Expand Up @@ -487,6 +476,17 @@ static const ESRIParamMapping paramsESRI_Cylindrical_Equal_Area[] = {
EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, "0.0", false},
{nullptr, nullptr, 0, "0.0", false}};

static const ESRIParamMapping paramsESRI_Behrmann[] = {
{"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", true},
{"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, "30.0", true},
{nullptr, nullptr, 0, "0.0", false}};

static const ESRIParamMapping
paramsESRI_Hotine_Oblique_Mercator_Two_Point_Center[] = {
{"False_Easting", EPSG_NAME_PARAMETER_EASTING_PROJECTION_CENTRE,
Expand Down Expand Up @@ -990,14 +990,14 @@ static const ESRIParamMapping paramsESRI_Peirce_Quincuncial_alt2[] = {
{nullptr, nullptr, 0, "0.0", false}};

static const ESRIMethodMapping esriMappings[] = {
{"Equidistant_Cylindrical", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL,
EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL,
paramsESRI_Equidistant_Cylindrical},
{"Plate_Carree", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL,
EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL, paramsESRI_Plate_Carree},
{"Plate_Carree", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL_SPHERICAL,
EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL_SPHERICAL,
paramsESRI_Plate_Carree},
{"Equidistant_Cylindrical", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL,
EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL,
paramsESRI_Equidistant_Cylindrical},
{"Miller_Cylindrical", PROJ_WKT2_NAME_METHOD_MILLER_CYLINDRICAL, 0,
paramsESRI_Miller_Cylindrical},
{"Mercator", EPSG_NAME_METHOD_MERCATOR_VARIANT_B,
Expand All @@ -1021,8 +1021,6 @@ static const ESRIMethodMapping esriMappings[] = {
{"Eckert_VI", PROJ_WKT2_NAME_METHOD_ECKERT_VI, 0, paramsESRI_Eckert_VI},
{"Gall_Stereographic", PROJ_WKT2_NAME_METHOD_GALL_STEREOGRAPHIC, 0,
paramsESRI_Gall_Stereographic},
{"Behrmann", EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA,
EPSG_CODE_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA, paramsESRI_Behrmann},
{"Winkel_I", "Winkel I", 0, paramsESRI_Winkel_I},
{"Winkel_II", "Winkel II", 0, paramsESRI_Winkel_II},
{"Lambert_Conformal_Conic", EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_1SP,
Expand Down Expand Up @@ -1070,6 +1068,8 @@ static const ESRIMethodMapping esriMappings[] = {
{"Cylindrical_Equal_Area", EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA,
EPSG_CODE_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA,
paramsESRI_Cylindrical_Equal_Area},
{"Behrmann", EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA,
EPSG_CODE_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA, paramsESRI_Behrmann},
{"Hotine_Oblique_Mercator_Two_Point_Center",
PROJ_WKT2_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN, 0,
paramsESRI_Hotine_Oblique_Mercator_Two_Point_Center},
Expand Down
35 changes: 31 additions & 4 deletions test/unit/test_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7791,10 +7791,15 @@ static const struct {
TEST(wkt_parse, esri_projcs) {

for (const auto &projDef : esriProjDefs) {
std::string wkt("PROJCS[\"unnamed\",GEOGCS[\"unnamed\","
"DATUM[\"unnamed\",SPHEROID[\"unnamed\","
"6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],"
"UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"");
std::string wkt("PROJCS[\"");
if (strcmp(projDef.esriProjectionName, "Plate_Carree") == 0)
wkt += "Plate Carree";
else
wkt += "unnamed";
wkt += "\",GEOGCS[\"unnamed\","
"DATUM[\"unnamed\",SPHEROID[\"unnamed\","
"6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],"
"UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"";
wkt += projDef.esriProjectionName;
wkt += "\"],";
for (const auto &param : projDef.esriParams) {
Expand Down Expand Up @@ -7829,6 +7834,28 @@ TEST(wkt_parse, esri_projcs) {
EXPECT_EQ(measure.value(), projDef.wkt2Params[i].second) << wkt;
}
}

auto wkt1Esri = crs->exportToWKT(
WKTFormatter::create(WKTFormatter::Convention::WKT1_ESRI).get());
const char *expectedESRIProjectionName = projDef.esriProjectionName;
// Not totally sure about the below exceptions. They just capture the
// current state of things.
if (strcmp(projDef.esriProjectionName, "Transverse_Mercator_Complex") ==
0)
expectedESRIProjectionName = "Transverse_Mercator";
else if (strcmp(projDef.esriProjectionName,
"Equidistant_Cylindrical_Ellipsoidal") == 0)
expectedESRIProjectionName = "Equidistant_Cylindrical";
else if (strcmp(projDef.esriProjectionName, "Mercator_Variant_C") == 0)
expectedESRIProjectionName = "Mercator";
else if (strcmp(projDef.esriProjectionName, "Gnomonic_Ellipsoidal") ==
0)
expectedESRIProjectionName = "Gnomonic";
EXPECT_TRUE(wkt1Esri.find(std::string("PROJECTION[\"")
.append(expectedESRIProjectionName)) !=
std::string::npos)
<< "input: " << wkt << std::endl
<< "output: " << wkt1Esri;
}
}

Expand Down
Loading