Skip to content

Commit

Permalink
WKT ESRI import: support LINUNIT node inside GEOGCS which indicates a…
Browse files Browse the repository at this point in the history
… geographic 3D CRS
  • Loading branch information
rouault committed Jul 9, 2022
1 parent 0574b26 commit da21da6
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 231 deletions.
1 change: 1 addition & 0 deletions include/proj/internal/io_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class WKTConstants {
static const std::string EXTENSION; // WKT1 only - GDAL specific
static const std::string LOCAL_CS; // WKT1 only
static const std::string LOCAL_DATUM; // WKT1 only
static const std::string LINUNIT; // WKT1 ESRI (ArcGIS Pro >= 2.7)

// WKT2 preferred
static const std::string GEODCRS;
Expand Down
11 changes: 11 additions & 0 deletions src/iso19111/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2663,6 +2663,17 @@ WKTParser::Private::buildCS(const WKTNodeNNPtr &node, /* maybe null */
if (unit == UnitOfMeasure::NONE) {
ThrowParsingExceptionMissingUNIT();
}

// ESRI WKT for geographic 3D CRS
auto &linUnitNode =
parentNode->GP()->lookForChild(WKTConstants::LINUNIT);
if (!isNull(linUnitNode)) {
return EllipsoidalCS::
createLongitudeLatitudeEllipsoidalHeight(
unit, buildUnit(linUnitNode,
UnitOfMeasure::Type::LINEAR));
}

// WKT1 --> long/lat
return EllipsoidalCS::createLongitudeLatitude(unit);
}
Expand Down
1 change: 1 addition & 0 deletions src/iso19111/static.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ DEFINE_WKT_CONSTANT(TOWGS84);
DEFINE_WKT_CONSTANT(EXTENSION);
DEFINE_WKT_CONSTANT(LOCAL_CS);
DEFINE_WKT_CONSTANT(LOCAL_DATUM);
DEFINE_WKT_CONSTANT(LINUNIT);

DEFINE_WKT_CONSTANT(GEODCRS);
DEFINE_WKT_CONSTANT(LENGTHUNIT);
Expand Down
2 changes: 1 addition & 1 deletion src/lib_proj.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ add_custom_target(check_wkt1_grammar_md5 ALL
COMMAND ${CMAKE_COMMAND}
"-DIN_FILE=wkt1_grammar.y"
"-DTARGET=generate_wkt1_parser"
"-DEXPECTED_MD5SUM=3a1720c3fa1b759719e33dd558603efb"
"-DEXPECTED_MD5SUM=04ba1095339aeac27105f5782d6297de"
-P "${CMAKE_CURRENT_SOURCE_DIR}/check_md5sum.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/wkt1_grammar.y"
Expand Down
432 changes: 223 additions & 209 deletions src/wkt1_generated_parser.c

Large diffs are not rendered by default.

41 changes: 21 additions & 20 deletions src/wkt1_generated_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
/* Undocumented macros, especially those whose name start with YY_,
are private implementation details. Do not rely on them. */

#ifndef YY_PJ_WKT1_SRC_WKT1_GENERATED_PARSER_H_INCLUDED
# define YY_PJ_WKT1_SRC_WKT1_GENERATED_PARSER_H_INCLUDED
#ifndef YY_PJ_WKT1_WKT1_GENERATED_PARSER_H_INCLUDED
# define YY_PJ_WKT1_WKT1_GENERATED_PARSER_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
Expand All @@ -61,23 +61,24 @@ extern int pj_wkt1_debug;
T_SPHEROID = 266,
T_PRIMEM = 267,
T_UNIT = 268,
T_GEOCCS = 269,
T_AUTHORITY = 270,
T_VERT_CS = 271,
T_VERTCS = 272,
T_VERT_DATUM = 273,
T_VDATUM = 274,
T_COMPD_CS = 275,
T_AXIS = 276,
T_TOWGS84 = 277,
T_FITTED_CS = 278,
T_LOCAL_CS = 279,
T_LOCAL_DATUM = 280,
T_PARAMETER = 281,
T_EXTENSION = 282,
T_STRING = 283,
T_NUMBER = 284,
T_IDENTIFIER = 285
T_LINUNIT = 269,
T_GEOCCS = 270,
T_AUTHORITY = 271,
T_VERT_CS = 272,
T_VERTCS = 273,
T_VERT_DATUM = 274,
T_VDATUM = 275,
T_COMPD_CS = 276,
T_AXIS = 277,
T_TOWGS84 = 278,
T_FITTED_CS = 279,
T_LOCAL_CS = 280,
T_LOCAL_DATUM = 281,
T_PARAMETER = 282,
T_EXTENSION = 283,
T_STRING = 284,
T_NUMBER = 285,
T_IDENTIFIER = 286
};
#endif

Expand All @@ -92,4 +93,4 @@ typedef int YYSTYPE;

int pj_wkt1_parse (pj_wkt1_parse_context *context);

#endif /* !YY_PJ_WKT1_SRC_WKT1_GENERATED_PARSER_H_INCLUDED */
#endif /* !YY_PJ_WKT1_WKT1_GENERATED_PARSER_H_INCLUDED */
13 changes: 12 additions & 1 deletion src/wkt1_grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
%token T_SPHEROID "SPHEROID"
%token T_PRIMEM "PRIMEM"
%token T_UNIT "UNIT"
%token T_LINUNIT "LINUNIT"
%token T_GEOCCS "GEOCCS"
%token T_AUTHORITY "AUTHORITY"
%token T_VERT_CS "VERT_CS"
Expand Down Expand Up @@ -166,7 +167,17 @@ projection:

geographic_cs:
T_GEOGCS begin_node_name',' datum ',' prime_meridian ','
angular_unit opt_twin_axis_extension_authority end_node
angular_unit opt_linunit_or_twin_axis_extension_authority end_node

/* ESRI extension for geographic 3D CRS */
linunit:
T_LINUNIT begin_node_name',' conversion_factor opt_authority end_node

opt_linunit_or_twin_axis_extension_authority:
| ',' linunit opt_authority
| ',' twin_axis opt_extension_authority
| ',' extension opt_authority
| ',' authority

datum:
T_DATUM begin_node_name ',' spheroid opt_towgs84_authority_extension end_node
Expand Down
1 change: 1 addition & 0 deletions src/wkt1_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ static const osr_cs_wkt_tokens tokens[] = {
PAIR(COMPD_CS),
PAIR(AXIS), PAIR(TOWGS84), PAIR(FITTED_CS), PAIR(LOCAL_CS),
PAIR(LOCAL_DATUM),
PAIR(LINUNIT),

PAIR(EXTENSION)};

Expand Down
22 changes: 22 additions & 0 deletions test/unit/test_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,28 @@ TEST(wkt_parse, wkt1_esri_EPSG_4901_grad) {

// ---------------------------------------------------------------------------

TEST(wkt_parse, wkt1_esri_LINUNIT) {
const auto wkt = "GEOGCS[\"WGS_1984_3D\",DATUM[\"D_WGS_1984\","
"SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],"
"PRIMEM[\"Greenwich\",0.0],"
"UNIT[\"Degree\",0.0174532925199433],"
"LINUNIT[\"Meter\",1.0]]";
auto obj = WKTParser()
.attachDatabaseContext(DatabaseContext::create())
.createFromWKT(wkt);
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
const auto &axisList = crs->coordinateSystem()->axisList();
ASSERT_EQ(axisList.size(), 3U);
EXPECT_NEAR(axisList[0]->unit().conversionToSI(), 0.0174532925199433,
1e-15);
EXPECT_NEAR(axisList[1]->unit().conversionToSI(), 0.0174532925199433,
1e-15);
EXPECT_EQ(axisList[2]->unit(), UnitOfMeasure::METRE);
}

// ---------------------------------------------------------------------------

TEST(wkt_parse, wkt2_epsg_org_EPSG_4901_PRIMEM_weird_sexagesimal_DMS) {
// Current epsg.org output may use the EPSG:9110 "sexagesimal DMS"
// unit and a DD.MMSSsss value, but this will likely be changed to
Expand Down

0 comments on commit da21da6

Please sign in to comment.