diff options
37 files changed, 933 insertions, 126 deletions
diff --git a/cmake/ProjTest.cmake b/cmake/ProjTest.cmake index 542c7440..c632d539 100644 --- a/cmake/ProjTest.cmake +++ b/cmake/ProjTest.cmake @@ -39,7 +39,7 @@ endfunction() # Create user writable directory for tests add_custom_target(create_tmp_user_writable_dir ALL - COMMAND ${CMAKE_COMMAND} -E make_directory {PROJ_BINARY_DIR}/tmp_user_writable_dir) + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJ_BINARY_DIR}/tmp_user_writable_dir) function(proj_add_gie_network_dependent_test TESTNAME TESTCASE) diff --git a/data/sql/alias_name.sql b/data/sql/alias_name.sql index 5d58135c..0fc8b6e7 100644 --- a/data/sql/alias_name.sql +++ b/data/sql/alias_name.sql @@ -7413,6 +7413,22 @@ INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','8252','NAD83(CSRS) 2010', INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','8253','NAD83(CSRS) 2010','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','8254','NAD83(CSRS) 2010','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','8255','NAD83(CSRS) 2010','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9831','UA_UCS_2000 / LCS_01','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9832','UA_UCS_2000 / LCS_05','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9833','UA_UCS_2000 / LCS_07','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9834','UA_UCS_2000 / LCS_12','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9836','UA_UCS_2000 / LCS_18','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9835','UA_UCS_2000 / LCS_14','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9837','UA_UCS_2000 / LCS_21','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9838','UA_UCS_2000 / LCS_23','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9839','UA_UCS_2000 / LCS_26','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9840','UA_UCS_2000 / LCS_35','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9841','UA_UCS_2000 / LCS_44','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9851','UA_UCS_2000 / LCS_46','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9852','UA_UCS_2000 / LCS_48','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9853','UA_UCS_2000 / LCS_51','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9856','UA_UCS_2000 / LCS_59','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9854','UA_UCS_2000 / LCS_53','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9331','777','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9331','KSA-GRF17 - XYZ','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9332','778','EPSG'); @@ -7421,3 +7437,14 @@ INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9333','779','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9333','KSA-GRF17 - LatLon','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','9335','780','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','9335','KSA-VRF14 - OHt','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9858','UA_UCS_2000 / LCS_63','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9857','UA_UCS_2000 / LCS_61','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9859','UA_UCS_2000 / LCS_65','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9865','UA_UCS_2000 / LCS_85','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9863','UA_UCS_2000 / LCS_74','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9862','UA_UCS_2000 / LCS_73','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9861','UA_UCS_2000 / LCS_71','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9821','UA_UCS_2000 / LCS_32','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9860','UA_UCS_2000 / LCS_68','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9855','UA_UCS_2000 / LCS_56','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9864','UA_UCS_2000 / LCS_80','EPSG'); diff --git a/data/sql/conversion.sql b/data/sql/conversion.sql index 422d240e..206299d9 100644 --- a/data/sql/conversion.sql +++ b/data/sql/conversion.sql @@ -1750,6 +1750,56 @@ INSERT INTO "conversion" VALUES('EPSG','9760','ECML14_NB-TM','In conjunction wit INSERT INTO "usage" VALUES('EPSG','16497','conversion','EPSG','9760','EPSG','4621','EPSG','1141'); INSERT INTO "conversion" VALUES('EPSG','9765','EWR2-TM','In conjunction with transformation ETRS89 to EWR2-IRF (1) (code 9764), emulates the EWR2 Snake projection.','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',51.57,'EPSG','9110','EPSG','8802','Longitude of natural origin',-0.54,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',192519.9715,'EPSG','9001','EPSG','8807','False northing',146942.6806,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); INSERT INTO "usage" VALUES('EPSG','16511','conversion','EPSG','9765','EPSG','4622','EPSG','1141'); +INSERT INTO "conversion" VALUES('EPSG','9796','Local coordinate system of Kyiv','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',30.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16909','conversion','EPSG','9796','EPSG','4650','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9797','Local coordinate system of Crimea region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',34.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16876','conversion','EPSG','9797','EPSG','4648','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9798','Local coordinate system of Vinnytsia region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',28.4,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16877','conversion','EPSG','9798','EPSG','4643','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9799','Local coordinate system of Volyn region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',24.5,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16878','conversion','EPSG','9799','EPSG','4644','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9800','Local coordinate system of Dnipropetrovsk region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',35.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16879','conversion','EPSG','9800','EPSG','4627','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9801','Local coordinate system of Donetsk region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',37.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16880','conversion','EPSG','9801','EPSG','4628','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9802','Local coordinate system of Zhytomyr region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',28.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16881','conversion','EPSG','9802','EPSG','4647','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9803','Local coordinate system of Zakarpattia region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',23.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16882','conversion','EPSG','9803','EPSG','4645','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9804','Local coordinate system of Zaporizhzhia region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',36.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16883','conversion','EPSG','9804','EPSG','4646','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9805','Local coordinate system of Ivano-Frankivsk region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',24.45,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16884','conversion','EPSG','9805','EPSG','4629','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9806','Local coordinate system of Kirovohrad region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',32.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16885','conversion','EPSG','9806','EPSG','4634','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9807','Local coordinate system of Luhansk region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',39.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16886','conversion','EPSG','9807','EPSG','4635','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9808','Local coordinate system of Lviv region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',24.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16887','conversion','EPSG','9808','EPSG','4636','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9809','Local coordinate system of Mykolaiv region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',31.5,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16888','conversion','EPSG','9809','EPSG','4637','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9810','Local coordinate system of Odessa region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',30.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16889','conversion','EPSG','9810','EPSG','4638','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9811','Local coordinate system of Poltava region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',33.5,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16890','conversion','EPSG','9811','EPSG','4639','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9812','Local coordinate system of Rivne and Khmelnytsky regions','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',27.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16908','conversion','EPSG','9812','EPSG','4651','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9813','Local coordinate system of Sumy region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',34.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16895','conversion','EPSG','9813','EPSG','4641','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9814','Local coordinate system of Ternopil region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',25.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16896','conversion','EPSG','9814','EPSG','4642','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9815','Local coordinate system of Kharkiv region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',36.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16897','conversion','EPSG','9815','EPSG','4630','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9816','Local coordinate system of Kherson region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',33.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16898','conversion','EPSG','9816','EPSG','4631','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9817','Local coordinate system of Cherkasy region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',31.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16899','conversion','EPSG','9817','EPSG','4624','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9818','Local coordinate system of Chernivtsi region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',26.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16900','conversion','EPSG','9818','EPSG','4626','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9819','Local coordinate system of Chernihiv region','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',32.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16901','conversion','EPSG','9819','EPSG','4625','EPSG','1207'); +INSERT INTO "conversion" VALUES('EPSG','9820','Local coordinate system of Sevastopol city','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',33.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',300000.0,'EPSG','9001','EPSG','8807','False northing',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','16902','conversion','EPSG','9820','EPSG','4649','EPSG','1207'); INSERT INTO "conversion" VALUES('EPSG','9872','Papua New Guinea Map Grid 1994 zone 57','Grid convergence uses opposite sign convention to UTM.','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',159.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',0.9996,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9001','EPSG','8807','False northing',10000000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); INSERT INTO "usage" VALUES('EPSG','16917','conversion','EPSG','9872','EPSG','4653','EPSG','1092'); INSERT INTO "conversion" VALUES('EPSG','9873','Papua New Guinea Map Grid 1994 zone 58','Grid convergence uses opposite sign convention to UTM.','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',0.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',165.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',0.9996,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9001','EPSG','8807','False northing',10000000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); diff --git a/data/sql/extent.sql b/data/sql/extent.sql index ec9ddb85..73657051 100644 --- a/data/sql/extent.sql +++ b/data/sql/extent.sql @@ -3598,5 +3598,34 @@ INSERT INTO "extent" VALUES('EPSG','4619','Italy - 6°22''E to 18°40''E and nor INSERT INTO "extent" VALUES('EPSG','4620','UK - Tweedmouth to Aberdeen','United Kingdom (UK) - on or related to the complex of rail routes in the East of Scotland, incorporating the route from Tweedbank through the Borders to Edinburgh; the line from Edinburgh to Aberdeen; routes via Kirkaldy and Cowdenbeath; and routes via Leuchars and Perth to Dundee. ',55.55,57.2,-3.55,-1.95,0); INSERT INTO "extent" VALUES('EPSG','4621','UK - Newcastle to Ashington','United Kingdom (UK) - on or related to rail routes from Newcastle Central to Ashington via Benton North Junction, and the section from Bedlington to Morpeth.',54.85,55.3,-1.9,-1.3,0); INSERT INTO "extent" VALUES('EPSG','4622','UK - Oxford to Bedford','United Kingdom (UK) - on or related to East West Rail (Phase 2) routes from Oxford to Bicester, Bletchley and Bedford, and from Claydon Junction to Aylesbury and Princes Risborough.',51.7,52.24,-1.43,-0.36,0); +INSERT INTO "extent" VALUES('EPSG','4623','Ukraine - Kyiv city','Ukraine - Kyiv (Kiev) city.',50.21,50.59,30.23,30.83,0); +INSERT INTO "extent" VALUES('EPSG','4624','Ukraine - Cherkasy oblast','Ukraine - Cherkasy region (oblast).',48.45,50.23,29.6,32.89,0); +INSERT INTO "extent" VALUES('EPSG','4625','Ukraine - Chernihiv oblast','Ukraine - Chernihiv region (oblast).',50.34,52.38,30.48,33.51,0); +INSERT INTO "extent" VALUES('EPSG','4626','Ukraine - Chernivtsi oblast','Ukraine - Chernivtsi region (oblast).',47.72,48.68,24.9,27.53,0); +INSERT INTO "extent" VALUES('EPSG','4627','Ukraine - Dnipropetrovsk oblast','Ukraine - Dnipropetrovsk region (oblast).',47.45,49.19,32.95,36.94,0); +INSERT INTO "extent" VALUES('EPSG','4628','Ukraine - Donetsk oblast','Ukraine - Donetsk region (oblast).',46.86,49.23,36.54,39.09,0); +INSERT INTO "extent" VALUES('EPSG','4629','Ukraine - Ivano-Frankivsk oblast','Ukraine - Ivano-Frankivsk region (oblast).',47.72,49.56,23.53,25.65,0); +INSERT INTO "extent" VALUES('EPSG','4630','Ukraine - Kharkiv oblast','Ukraine - Kharkiv region (oblast).',48.52,50.46,34.84,38.1,0); +INSERT INTO "extent" VALUES('EPSG','4631','Ukraine - Kherson oblast','Ukraine - Kherson region (oblast).',45.75,47.6,31.51,35.1,0); +INSERT INTO "extent" VALUES('EPSG','4632','Ukraine - Khmelnytskyi oblast','Ukraine - Khmelnytskyi region (oblast).',48.45,50.59,26.13,27.9,0); +INSERT INTO "extent" VALUES('EPSG','4633','Ukraine - Kyiv oblast','Ukraine - Kyiv (Kiev) region (oblast).',49.17,51.55,29.26,32.16,0); +INSERT INTO "extent" VALUES('EPSG','4634','Ukraine - Kirovohrad oblast','Ukraine - Kirovohrad region (oblast).',47.74,49.25,29.74,33.9,0); +INSERT INTO "extent" VALUES('EPSG','4635','Ukraine - Luhansk oblast','Ukraine - Luhansk region (oblast).',47.82,50.09,37.83,40.23,0); +INSERT INTO "extent" VALUES('EPSG','4636','Ukraine - Lviv oblast','Ukraine - Lviv region (oblast).',48.71,50.65,22.64,25.42,0); +INSERT INTO "extent" VALUES('EPSG','4637','Ukraine - Mykolaiv oblast','Ukraine - Mykolaiv region (oblast).',46.36,48.23,30.2,33.18,0); +INSERT INTO "extent" VALUES('EPSG','4638','Ukraine - Odessa oblast','Ukraine - Odessa region (oblast).',45.2,48.23,28.21,31.29,0); +INSERT INTO "extent" VALUES('EPSG','4639','Ukraine - Poltava oblast','Ukraine - Poltava region (oblast).',48.74,50.55,32.08,35.48,0); +INSERT INTO "extent" VALUES('EPSG','4640','Ukraine - Rivne oblast','Ukraine - Rivne region (oblast).',50.0,51.95,25.08,27.73,0); +INSERT INTO "extent" VALUES('EPSG','4641','Ukraine - Sumy oblast','Ukraine - Sumy region (oblast).',50.1,52.37,32.93,35.67,0); +INSERT INTO "extent" VALUES('EPSG','4642','Ukraine - Ternopil oblast','Ukraine - Ternopil region (oblast).',48.5,50.27,24.71,26.44,0); +INSERT INTO "extent" VALUES('EPSG','4643','Ukraine - Vinnytsia oblast','Ukraine - Vinnytsia region (oblast).',48.06,49.89,27.37,30.02,0); +INSERT INTO "extent" VALUES('EPSG','4644','Ukraine - Volyn oblast','Ukraine - Volyn region (oblast).',50.28,51.97,23.6,26.1,0); +INSERT INTO "extent" VALUES('EPSG','4645','Ukraine - Zakarpattia oblast','Ukraine - Zakarpattia (Zakarpatska) region (Transcarpathia oblast).',47.89,49.1,22.13,24.62,0); +INSERT INTO "extent" VALUES('EPSG','4646','Ukraine - Zaporizhzhia oblast','Ukraine - Zaporizhzhia region (oblast).',46.07,48.14,34.17,37.24,0); +INSERT INTO "extent" VALUES('EPSG','4647','Ukraine - Zhytomyr oblast','Ukraine - Zhytomyr region (oblast).',49.58,51.68,27.19,29.73,0); +INSERT INTO "extent" VALUES('EPSG','4648','Ukraine - Crimea','Ukraine - Crimea autonomous region.',44.38,46.24,32.47,36.65,0); +INSERT INTO "extent" VALUES('EPSG','4649','Ukraine - Sevastopol','Ukraine - Sevastopol (Sebastopol) city.',44.38,44.84,33.37,33.92,0); +INSERT INTO "extent" VALUES('EPSG','4650','Ukraine - Kyiv city and oblast','Ukraine - Kyiv (Kiev) city and Kyiv region (oblast).',49.17,51.55,29.26,32.16,0); +INSERT INTO "extent" VALUES('EPSG','4651','Ukraine - Rivne and Khmelnytskyi oblasts','Ukraine - Rivne and Khmelnytskyi regions (oblasts).',48.45,51.95,25.08,27.9,0); INSERT INTO "extent" VALUES('EPSG','4653','Papua New Guinea - 156°E to 162°E','Papua New Guinea - between 156°E and 162°E, onshore and offshore.',-14.26,-1.11,156.0,162.0,0); INSERT INTO "extent" VALUES('EPSG','4654','Papua New Guinea - east of 162°E','Papua New Guinea - east of 162°E to EEZ limit.',-4.35,-2.34,162.0,162.8,0); diff --git a/data/sql/metadata.sql b/data/sql/metadata.sql index f3987969..8230e7da 100644 --- a/data/sql/metadata.sql +++ b/data/sql/metadata.sql @@ -9,8 +9,8 @@ INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MAJOR', 1); INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MINOR', 2); -INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.036'); -INSERT INTO "metadata" VALUES('EPSG.DATE', '2021-09-23'); +INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.037'); +INSERT INTO "metadata" VALUES('EPSG.DATE', '2021-10-07'); -- The value of ${PROJ_VERSION} is substituted at build time by the actual -- value. diff --git a/data/sql/projected_crs.sql b/data/sql/projected_crs.sql index 8671ff27..52ff05b2 100644 --- a/data/sql/projected_crs.sql +++ b/data/sql/projected_crs.sql @@ -7335,6 +7335,8 @@ INSERT INTO "projected_crs" VALUES('EPSG','9793','RGF93 v2 / Lambert-93',NULL,'E INSERT INTO "usage" VALUES('EPSG','16614','projected_crs','EPSG','9793','EPSG','1096','EPSG','1142'); INSERT INTO "projected_crs" VALUES('EPSG','9794','RGF93 v2b / Lambert-93',NULL,'EPSG','4499','EPSG','9782','EPSG','18085',NULL,0); INSERT INTO "usage" VALUES('EPSG','16615','projected_crs','EPSG','9794','EPSG','1096','EPSG','1142'); +INSERT INTO "projected_crs" VALUES('EPSG','9821','UCS-2000 / LCS-32 Kyiv region',NULL,'EPSG','4531','EPSG','5561','EPSG','9796',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16867','projected_crs','EPSG','9821','EPSG','4633','EPSG','1207'); INSERT INTO "projected_crs" VALUES('EPSG','9822','RGF93 v2 / CC42',NULL,'EPSG','4499','EPSG','9777','EPSG','18101',NULL,0); INSERT INTO "usage" VALUES('EPSG','16616','projected_crs','EPSG','9822','EPSG','3545','EPSG','1054'); INSERT INTO "projected_crs" VALUES('EPSG','9823','RGF93 v2 / CC43',NULL,'EPSG','4499','EPSG','9777','EPSG','18102',NULL,0); @@ -7353,6 +7355,28 @@ INSERT INTO "projected_crs" VALUES('EPSG','9829','RGF93 v2 / CC49',NULL,'EPSG',' INSERT INTO "usage" VALUES('EPSG','16623','projected_crs','EPSG','9829','EPSG','3552','EPSG','1054'); INSERT INTO "projected_crs" VALUES('EPSG','9830','RGF93 v2 / CC50',NULL,'EPSG','4499','EPSG','9777','EPSG','18109',NULL,0); INSERT INTO "usage" VALUES('EPSG','16624','projected_crs','EPSG','9830','EPSG','3553','EPSG','1054'); +INSERT INTO "projected_crs" VALUES('EPSG','9831','UCS-2000 / LCS-01 Crimea',NULL,'EPSG','4531','EPSG','5561','EPSG','9797',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16766','projected_crs','EPSG','9831','EPSG','4648','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9832','UCS-2000 / LCS-05 Vinnytsia',NULL,'EPSG','4531','EPSG','5561','EPSG','9798',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16767','projected_crs','EPSG','9832','EPSG','4643','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9833','UCS-2000 / LCS-07 Volyn',NULL,'EPSG','4531','EPSG','5561','EPSG','9799',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16768','projected_crs','EPSG','9833','EPSG','4644','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9834','UCS-2000 / LCS-12 Dnipropetrovsk',NULL,'EPSG','4531','EPSG','5561','EPSG','9800',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16769','projected_crs','EPSG','9834','EPSG','4627','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9835','UCS-2000 / LCS-14 Donetsk',NULL,'EPSG','4531','EPSG','5561','EPSG','9801',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16772','projected_crs','EPSG','9835','EPSG','4628','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9836','UCS-2000 / LCS-18 Zhytomyr',NULL,'EPSG','4531','EPSG','5561','EPSG','9802',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16771','projected_crs','EPSG','9836','EPSG','4647','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9837','UCS-2000 / LCS-21 Zakarpattia',NULL,'EPSG','4531','EPSG','5561','EPSG','9803',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16773','projected_crs','EPSG','9837','EPSG','4645','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9838','UCS-2000 / LCS-23 Zaporizhzhia',NULL,'EPSG','4531','EPSG','5561','EPSG','9804',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16774','projected_crs','EPSG','9838','EPSG','4646','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9839','UCS-2000 / LCS-26 Ivano-Frankivsk',NULL,'EPSG','4531','EPSG','5561','EPSG','9805',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16775','projected_crs','EPSG','9839','EPSG','4629','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9840','UCS-2000 / LCS-35 Kirovohrad',NULL,'EPSG','4531','EPSG','5561','EPSG','9806',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16776','projected_crs','EPSG','9840','EPSG','4634','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9841','UCS-2000 / LCS-44 Luhansk',NULL,'EPSG','4531','EPSG','5561','EPSG','9807',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16777','projected_crs','EPSG','9841','EPSG','4635','EPSG','1207'); INSERT INTO "projected_crs" VALUES('EPSG','9842','RGF93 v2b / CC42',NULL,'EPSG','4499','EPSG','9782','EPSG','18101',NULL,0); INSERT INTO "usage" VALUES('EPSG','16625','projected_crs','EPSG','9842','EPSG','3545','EPSG','1054'); INSERT INTO "projected_crs" VALUES('EPSG','9843','RGF93 v2b / CC43',NULL,'EPSG','4499','EPSG','9782','EPSG','18102',NULL,0); @@ -7371,6 +7395,36 @@ INSERT INTO "projected_crs" VALUES('EPSG','9849','RGF93 v2b / CC49',NULL,'EPSG', INSERT INTO "usage" VALUES('EPSG','16632','projected_crs','EPSG','9849','EPSG','3552','EPSG','1054'); INSERT INTO "projected_crs" VALUES('EPSG','9850','RGF93 v2b / CC50',NULL,'EPSG','4499','EPSG','9782','EPSG','18109',NULL,0); INSERT INTO "usage" VALUES('EPSG','16633','projected_crs','EPSG','9850','EPSG','3553','EPSG','1054'); +INSERT INTO "projected_crs" VALUES('EPSG','9851','UCS-2000 / LCS-46 Lviv',NULL,'EPSG','4531','EPSG','5561','EPSG','9808',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16778','projected_crs','EPSG','9851','EPSG','4636','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9852','UCS-2000 / LCS-48 Mykolaiv',NULL,'EPSG','4531','EPSG','5561','EPSG','9809',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16779','projected_crs','EPSG','9852','EPSG','4637','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9853','UCS-2000 / LCS-51 Odessa',NULL,'EPSG','4531','EPSG','5561','EPSG','9810',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16780','projected_crs','EPSG','9853','EPSG','4638','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9854','UCS-2000 / LCS-53 Poltava',NULL,'EPSG','4531','EPSG','5561','EPSG','9811',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16786','projected_crs','EPSG','9854','EPSG','4639','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9855','UCS-2000 / LCS-56 Rivne',NULL,'EPSG','4531','EPSG','5561','EPSG','9812',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16869','projected_crs','EPSG','9855','EPSG','4640','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9856','UCS-2000 / LCS-59 Sumy',NULL,'EPSG','4531','EPSG','5561','EPSG','9813',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16785','projected_crs','EPSG','9856','EPSG','4641','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9857','UCS-2000 / LCS-61 Ternopil',NULL,'EPSG','4531','EPSG','5561','EPSG','9814',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16789','projected_crs','EPSG','9857','EPSG','4642','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9858','UCS-2000 / LCS-63 Kharkiv',NULL,'EPSG','4531','EPSG','5561','EPSG','9815',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16788','projected_crs','EPSG','9858','EPSG','4630','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9859','UCS-2000 / LCS-65 Kherson',NULL,'EPSG','4531','EPSG','5561','EPSG','9816',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16790','projected_crs','EPSG','9859','EPSG','4631','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9860','UCS-2000 / LCS-68 Khmelnytsky',NULL,'EPSG','4531','EPSG','5561','EPSG','9812',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16868','projected_crs','EPSG','9860','EPSG','4632','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9861','UCS-2000 / LCS-71 Cherkasy',NULL,'EPSG','4531','EPSG','5561','EPSG','9817',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16842','projected_crs','EPSG','9861','EPSG','4624','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9862','UCS-2000 / LCS-73 Chernivtsi',NULL,'EPSG','4531','EPSG','5561','EPSG','9818',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16841','projected_crs','EPSG','9862','EPSG','4626','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9863','UCS-2000 / LCS-74 Chernihiv',NULL,'EPSG','4531','EPSG','5561','EPSG','9819',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16840','projected_crs','EPSG','9863','EPSG','4625','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9864','UCS-2000 / LCS-80 Kyiv city',NULL,'EPSG','4531','EPSG','5561','EPSG','9796',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16922','projected_crs','EPSG','9864','EPSG','4623','EPSG','1207'); +INSERT INTO "projected_crs" VALUES('EPSG','9865','UCS-2000 / LCS-85 Sevastopol',NULL,'EPSG','4531','EPSG','5561','EPSG','9820',NULL,0); +INSERT INTO "usage" VALUES('EPSG','16836','projected_crs','EPSG','9865','EPSG','4649','EPSG','1207'); INSERT INTO "projected_crs" VALUES('EPSG','9874','PNG94 / PNGMG94 zone 57',NULL,'EPSG','4400','EPSG','5546','EPSG','9872',NULL,0); INSERT INTO "usage" VALUES('EPSG','16919','projected_crs','EPSG','9874','EPSG','4653','EPSG','1092'); INSERT INTO "projected_crs" VALUES('EPSG','9875','PNG94 / PNGMG94 zone 58',NULL,'EPSG','4400','EPSG','5546','EPSG','9873',NULL,0); diff --git a/docs/source/install.rst b/docs/source/install.rst index 73cc6e00..208b55d4 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -322,33 +322,43 @@ CMake configure options Options to configure a CMake are provided using ``-D<var>=<value>``. All cached entries can be viewed using ``cmake -LAH`` from a build directory. +.. option:: BUILD_APPS=ON + + Build PROJ applications. Default is ON. Control the default value for + BUILD_CCT, BUILD_CS2CS, BUILD_GEOD, BUILD_GIE, BUILD_PROJ, BUILD_PROJINFO + and BUILD_PROJSYNC. + Note that changing its value after having configured once will not change + the value of the individual BUILD_CCT, ... options. + + .. versionchanged:: 8.2 + .. option:: BUILD_CCT=ON - Build :ref:`cct`, default ON. + Build :ref:`cct`, default is the value of BUILD_APPS. .. option:: BUILD_CS2CS=ON - Build :ref:`cs2cs`, default ON. + Build :ref:`cs2cs`,default is the value of BUILD_APPS. .. option:: BUILD_GEOD=ON - Build :ref:`geod`, default ON. + Build :ref:`geod`, default is the value of BUILD_APPS. .. option:: BUILD_GIE=ON - Build :ref:`gie`, default ON. + Build :ref:`gie`, default is the value of BUILD_APPS. .. option:: BUILD_PROJ=ON - Build :ref:`proj`, default ON. + Build :ref:`proj`, default is the value of BUILD_APPS. .. option:: BUILD_PROJINFO=ON - Build :ref:`projinfo`, default ON. + Build :ref:`projinfo`, default is the value of BUILD_APPS. .. option:: BUILD_PROJSYNC=ON - Build :ref:`projsync`, default ON. + Build :ref:`projsync`, default is the value of BUILD_APPS. .. option:: BUILD_SHARED_LIBS diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp index 5a8e75ae..ce950c47 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -142,6 +142,8 @@ class PROJ_GCC_DLL CRS : public common::ObjectUsage, PROJ_INTERNAL bool mustAxisOrderBeSwitchedForVisualization() const; + PROJ_INTERNAL CRSNNPtr applyAxisOrderReversal(const char *nameSuffix) const; + PROJ_FOR_TEST CRSNNPtr normalizeForVisualization() const; PROJ_INTERNAL CRSNNPtr allowNonConformantWKT1Export() const; diff --git a/include/proj/internal/Makefile.am b/include/proj/internal/Makefile.am index 59325667..25b71cc5 100644 --- a/include/proj/internal/Makefile.am +++ b/include/proj/internal/Makefile.am @@ -1,6 +1,7 @@ SUBDIRS = vendor noinst_HEADERS = \ + crs_internal.hpp \ coordinatesystem_internal.hpp \ internal.hpp \ io_internal.hpp \ diff --git a/include/proj/internal/crs_internal.hpp b/include/proj/internal/crs_internal.hpp new file mode 100644 index 00000000..9a68c8b0 --- /dev/null +++ b/include/proj/internal/crs_internal.hpp @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2019 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2021, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef FROM_PROJ_CPP +#error This file should only be included from a PROJ cpp file +#endif + +#ifndef CRS_INTERNAL_HH_INCLUDED +#define CRS_INTERNAL_HH_INCLUDED + +#define NORMALIZED_AXIS_ORDER_SUFFIX_STR \ + " (with axis order normalized for visualization)" + +#define AXIS_ORDER_REVERSED_SUFFIX_STR " (with axis order reversed)" + +#endif // CRS_INTERNAL_HH_INCLUDED diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 534bc311..311cdbac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,20 +3,23 @@ include(lib_proj.cmake) # configure executable build +option(BUILD_APPS + "Build PROJ applications (default value for BUILD_CCT, BUILD_CS2CS, etc.)" ON) + option(BUILD_CCT - "Build cct (coordinate conversion and transformation tool)" ON) + "Build cct (coordinate conversion and transformation tool)" "${BUILD_APPS}") option(BUILD_CS2CS - "Build cs2cs (coordinate systems to coordinate systems translation tool)" ON) + "Build cs2cs (coordinate systems to coordinate systems translation tool)" "${BUILD_APPS}") option(BUILD_GEOD - "Build geod (computation of geodesic lines)" ON) + "Build geod (computation of geodesic lines)" "${BUILD_APPS}") option(BUILD_GIE - "Build gie (geospatial integrity investigation environment)" ON) + "Build gie (geospatial integrity investigation environment)" "${BUILD_APPS}") option(BUILD_PROJ - "Build proj (cartographic projection tool)" ON) + "Build proj (cartographic projection tool)" "${BUILD_APPS}") option(BUILD_PROJINFO - "Build projinfo (SRS and coordinate operation metadata/query tool)" ON) + "Build projinfo (SRS and coordinate operation metadata/query tool)" "${BUILD_APPS}") option(BUILD_PROJSYNC - "Build projsync (synchronize transformation support data)" ON) + "Build projsync (synchronize transformation support data)" "${BUILD_APPS}") if(NOT MSVC) @@ -69,7 +72,8 @@ if(BUILD_PROJINFO) set(BIN_TARGETS ${BIN_TARGETS} binprojinfo) endif() -if(BUILD_GIE) +# Always build gie if testing is requested +if(BUILD_GIE OR BUILD_TESTING) include(bin_gie.cmake) set(BIN_TARGETS ${BIN_TARGETS} gie) endif() diff --git a/src/Makefile.am b/src/Makefile.am index bae922d5..1e847080 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,17 +14,23 @@ include_HEADERS = proj.h proj_experimental.h proj_constants.h geodesic.h \ EXTRA_DIST = bin_cct.cmake bin_gie.cmake bin_cs2cs.cmake \ bin_geod.cmake bin_proj.cmake bin_projinfo.cmake \ - lib_proj.cmake CMakeLists.txt bin_geodtest.cmake \ + lib_proj.cmake \ + check_md5sum.cmake \ + generate_wkt_parser.cmake \ + CMakeLists.txt \ + bin_geodtest.cmake \ bin_projsync.cmake \ tests/geodtest.cpp \ wkt1_grammar.y wkt2_grammar.y apps/emess.h apps/utils.h \ apps/projsync.cpp proj_SOURCES = apps/proj.cpp apps/emess.cpp apps/utils.cpp +invproj_SOURCES = $(proj_SOURCES) projinfo_SOURCES = apps/projinfo.cpp cs2cs_SOURCES = apps/cs2cs.cpp apps/emess.cpp apps/utils.cpp cct_SOURCES = apps/cct.cpp apps/proj_strtod.cpp apps/proj_strtod.h apps/optargpm.h geod_SOURCES = apps/geod.cpp apps/geod_set.cpp apps/geod_interface.cpp apps/geod_interface.h apps/emess.cpp +invgeod_SOURCES = $(geod_SOURCES) if HAVE_CURL projsync_SOURCES = apps/projsync.cpp @@ -33,6 +39,7 @@ PROJSYNC_BIN = projsync endif bin_PROGRAMS = proj geod cs2cs gie cct projinfo $(PROJSYNC_BIN) +noinst_PROGRAMS = invproj invgeod gie_SOURCES = apps/gie.cpp apps/proj_strtod.cpp apps/proj_strtod.h apps/optargpm.h multistresstest_SOURCES = tests/multistresstest.cpp @@ -41,7 +48,9 @@ geodtest_SOURCES = tests/geodtest.cpp cct_LDADD = libproj.la cs2cs_LDADD = libproj.la geod_LDADD = libproj.la +invgeod_LDADD = $(geod_LDADD) proj_LDADD = libproj.la +invproj_LDADD = $(proj_LDADD) projinfo_LDADD = libproj.la gie_LDADD = libproj.la @@ -272,7 +281,6 @@ wkt2_parser: sed "s/\*yyssp = yystate/\*yyssp = (yytype_int16)yystate/" < $(top_srcdir)/src/wkt2_generated_parser.c | sed "s/yyerrorlab:/#if 0\nyyerrorlab:/" | sed "s/yyerrlab1:/#endif\nyyerrlab1:/" | sed "s/for (yylen = 0; yystr\[yylen\]; yylen++)/for (yylen = 0; yystr \&\& yystr\[yylen\]; yylen++)/"| sed "s/return yystpcpy (yyres, yystr) - yyres;/return (YYPTRDIFF_T)(yystpcpy (yyres, yystr) - yyres);/" | sed "s/YYPTRDIFF_T yysize = yyssp - yyss + 1;/YYPTRDIFF_T yysize = (YYPTRDIFF_T)(yyssp - yyss + 1);/"> $(top_srcdir)/src/wkt2_generated_parser.c.tmp mv $(top_srcdir)/src/wkt2_generated_parser.c.tmp $(top_srcdir)/src/wkt2_generated_parser.c - install-exec-local: install-binPROGRAMS rm -f $(DESTDIR)$(bindir)/invproj$(EXEEXT) (cd $(DESTDIR)$(bindir); ln -s proj$(EXEEXT) invproj$(EXEEXT)) diff --git a/src/apps/geod.cpp b/src/apps/geod.cpp index 35a8e826..6e3f059e 100644 --- a/src/apps/geod.cpp +++ b/src/apps/geod.cpp @@ -138,7 +138,8 @@ int main(int argc, char **argv) { if ((emess_dat.Prog_name = strrchr(*argv,'/')) != nullptr) ++emess_dat.Prog_name; else emess_dat.Prog_name = *argv; - inverse = ! strncmp(emess_dat.Prog_name, "inv", 3); + inverse = strncmp(emess_dat.Prog_name, "inv", 3) == 0 || + strncmp(emess_dat.Prog_name, "lt-inv", 6) == 0; // older libtool have a lt- prefix if (argc <= 1 ) { (void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name); diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index 6368ef2c..f93164e0 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -303,7 +303,8 @@ int main(int argc, char **argv) { if ( (emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != nullptr) ++emess_dat.Prog_name; else emess_dat.Prog_name = *argv; - inverse = ! strncmp(emess_dat.Prog_name, "inv", 3); + inverse = strncmp(emess_dat.Prog_name, "inv", 3) == 0 || + strncmp(emess_dat.Prog_name, "lt-inv", 6) == 0; // older libtool have a lt- prefix if (argc <= 1 ) { (void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name); exit (0); diff --git a/src/bin_geod.cmake b/src/bin_geod.cmake index 4ec28b04..3f3f9bf5 100644 --- a/src/bin_geod.cmake +++ b/src/bin_geod.cmake @@ -18,3 +18,38 @@ install(TARGETS geod if(MSVC AND BUILD_SHARED_LIBS) target_compile_definitions(geod PRIVATE PROJ_MSVC_DLL_IMPORT=1) endif() + +# invgeod target: symlink or copy of geod executable + +if(UNIX) + + set(link_target "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/invgeod${CMAKE_EXECUTABLE_SUFFIX}") + set(link_source "geod${CMAKE_EXECUTABLE_SUFFIX}") + + add_custom_command( + OUTPUT ${link_target} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${link_source} ${link_target} + WORKING_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + DEPENDS geod + COMMENT "Generating invgeod" + VERBATIM + ) + + add_custom_target(invgeod ALL DEPENDS ${link_target}) + + install(FILES ${link_target} DESTINATION ${BINDIR}) + +else() + + add_executable(invgeod ${GEOD_SRC} ${GEOD_INCLUDE}) + target_link_libraries(invgeod PRIVATE ${PROJ_LIBRARIES}) + target_compile_options(invgeod PRIVATE ${PROJ_CXX_WARN_FLAGS}) + + install(TARGETS invgeod + DESTINATION ${BINDIR}) + + if(MSVC AND BUILD_SHARED_LIBS) + target_compile_definitions(invgeod PRIVATE PROJ_MSVC_DLL_IMPORT=1) + endif() + +endif() diff --git a/src/bin_gie.cmake b/src/bin_gie.cmake index a26ead3e..6ad7d4ab 100644 --- a/src/bin_gie.cmake +++ b/src/bin_gie.cmake @@ -11,8 +11,10 @@ add_executable(gie ${GIE_SRC} ${GIE_INCLUDE}) target_link_libraries(gie PRIVATE ${PROJ_LIBRARIES}) target_compile_options(gie PRIVATE ${PROJ_CXX_WARN_FLAGS}) -install(TARGETS gie - DESTINATION ${BINDIR}) +if(BUILD_GIE) + install(TARGETS gie + DESTINATION ${BINDIR}) +endif() if(MSVC AND BUILD_SHARED_LIBS) target_compile_definitions(gie PRIVATE PROJ_MSVC_DLL_IMPORT=1) diff --git a/src/bin_proj.cmake b/src/bin_proj.cmake index b5a4c140..2df467af 100644 --- a/src/bin_proj.cmake +++ b/src/bin_proj.cmake @@ -19,3 +19,38 @@ install(TARGETS binproj if(MSVC AND BUILD_SHARED_LIBS) target_compile_definitions(binproj PRIVATE PROJ_MSVC_DLL_IMPORT=1) endif() + +# invproj target: symlink or copy of proj executable + +if(UNIX) + + set(link_target "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/invproj${CMAKE_EXECUTABLE_SUFFIX}") + set(link_source "proj${CMAKE_EXECUTABLE_SUFFIX}") + + add_custom_command( + OUTPUT ${link_target} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${link_source} ${link_target} + WORKING_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + DEPENDS binproj + COMMENT "Generating invproj" + VERBATIM + ) + + add_custom_target(invproj ALL DEPENDS ${link_target}) + + install(FILES ${link_target} DESTINATION ${BINDIR}) + +else() + + add_executable(invproj ${PROJ_SRC}) + target_link_libraries(invproj PRIVATE ${PROJ_LIBRARIES}) + target_compile_options(invproj PRIVATE ${PROJ_CXX_WARN_FLAGS}) + + install(TARGETS invproj + DESTINATION ${BINDIR}) + + if(MSVC AND BUILD_SHARED_LIBS) + target_compile_definitions(invproj PRIVATE PROJ_MSVC_DLL_IMPORT=1) + endif() + +endif() diff --git a/src/check_md5sum.cmake b/src/check_md5sum.cmake new file mode 100644 index 00000000..bab6fc6f --- /dev/null +++ b/src/check_md5sum.cmake @@ -0,0 +1,7 @@ +file(READ "${IN_FILE}" CONTENTS) + +string(MD5 MD5SUM "${CONTENTS}") + +if(NOT("${MD5SUM}" STREQUAL "${EXPECTED_MD5SUM}")) + message(FATAL_ERROR "File ${IN_FILE} has been modified. target ${TARGET} should be manually run. And lib_proj.cmake should be updated with \"${MD5SUM}\"") +endif() diff --git a/src/generate_wkt_parser.cmake b/src/generate_wkt_parser.cmake new file mode 100644 index 00000000..bcfc09be --- /dev/null +++ b/src/generate_wkt_parser.cmake @@ -0,0 +1,18 @@ +message("Generating ${OUT_FILE}") + +execute_process(COMMAND "bison" "--no-lines" "-d" "-p" "${PREFIX}" "-o${OUT_FILE}" "${IN_FILE}" + RESULT_VARIABLE STATUS) + +if(STATUS AND NOT STATUS EQUAL 0) + message(FATAL_ERROR "bison failed") +endif() + +# Post processing of the generated file +# All those replacements are to please MSVC +file(READ ${OUT_FILE} CONTENTS) +string(REPLACE "yyerrorlab:" "#if 0\nyyerrorlab:" CONTENTS "${CONTENTS}") +string(REPLACE "yyerrlab1:" "#endif\nyyerrlab1:" CONTENTS "${CONTENTS}") +string(REPLACE "for (yylen = 0; yystr[yylen]; yylen++)" "for (yylen = 0; yystr && yystr[yylen]; yylen++)" CONTENTS "${CONTENTS}") +string(REPLACE "return yystpcpy (yyres, yystr) - yyres;" "return (YYPTRDIFF_T)(yystpcpy (yyres, yystr) - yyres);" CONTENTS "${CONTENTS}") +string(REPLACE "YYPTRDIFF_T yysize = yyssp - yyss + 1;" "YYPTRDIFF_T yysize = (YYPTRDIFF_T)(yyssp - yyss + 1);" CONTENTS "${CONTENTS}") +file(WRITE "${OUT_FILE}" "${CONTENTS}") diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 9493452c..acf36402 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -8479,7 +8479,12 @@ PJ *proj_crs_get_datum_forced(PJ_CONTEXT *ctx, const PJ *crs) { const auto &datumEnsemble = l_crs->datumEnsemble(); assert(datumEnsemble); auto dbContext = getDBcontextNoException(ctx, __FUNCTION__); - return pj_obj_create(ctx, datumEnsemble->asDatum(dbContext)); + try { + return pj_obj_create(ctx, datumEnsemble->asDatum(dbContext)); + } catch (const std::exception &e) { + proj_log_debug(ctx, __FUNCTION__, e.what()); + return nullptr; + } } // --------------------------------------------------------------------------- diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index b7d57767..575f6e2b 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -43,6 +43,7 @@ #include "proj/util.hpp" #include "proj/internal/coordinatesystem_internal.hpp" +#include "proj/internal/crs_internal.hpp" #include "proj/internal/internal.hpp" #include "proj/internal/io_internal.hpp" @@ -887,51 +888,63 @@ void CRS::setProperties( //! @cond Doxygen_Suppress -CRSNNPtr CRS::normalizeForVisualization() const { +// --------------------------------------------------------------------------- - const auto createProperties = [this](const std::string &newName = - std::string()) { - auto props = util::PropertyMap().set( - common::IdentifiedObject::NAME_KEY, - !newName.empty() - ? newName - : nameStr() + - " (with axis order normalized for visualization)"); - const auto &l_domains = domains(); - if (!l_domains.empty()) { - auto array = util::ArrayOfBaseObject::create(); - for (const auto &domain : l_domains) { - array->add(domain); +CRSNNPtr CRS::applyAxisOrderReversal(const char *nameSuffix) const { + + const auto createProperties = + [this, nameSuffix](const std::string &newNameIn = std::string()) { + std::string newName(newNameIn); + if (newName.empty()) { + newName = nameStr(); + if (ends_with(newName, NORMALIZED_AXIS_ORDER_SUFFIX_STR)) { + newName.resize(newName.size() - + strlen(NORMALIZED_AXIS_ORDER_SUFFIX_STR)); + } else if (ends_with(newName, AXIS_ORDER_REVERSED_SUFFIX_STR)) { + newName.resize(newName.size() - + strlen(AXIS_ORDER_REVERSED_SUFFIX_STR)); + } else { + newName += nameSuffix; + } } - if (!array->empty()) { - props.set(common::ObjectUsage::OBJECT_DOMAIN_KEY, array); + auto props = util::PropertyMap().set( + common::IdentifiedObject::NAME_KEY, newName); + const auto &l_domains = domains(); + if (!l_domains.empty()) { + auto array = util::ArrayOfBaseObject::create(); + for (const auto &domain : l_domains) { + array->add(domain); + } + if (!array->empty()) { + props.set(common::ObjectUsage::OBJECT_DOMAIN_KEY, array); + } } - } - const auto &l_identifiers = identifiers(); - const auto &l_remarks = remarks(); - if (l_identifiers.size() == 1) { - std::string remarks("Axis order reversed compared to "); - remarks += *(l_identifiers[0]->codeSpace()); - remarks += ':'; - remarks += l_identifiers[0]->code(); - if (!l_remarks.empty()) { - remarks += ". "; - remarks += l_remarks; + const auto &l_identifiers = identifiers(); + const auto &l_remarks = remarks(); + if (l_identifiers.size() == 1) { + std::string remarks("Axis order reversed compared to "); + if (!starts_with(l_remarks, remarks)) { + remarks += *(l_identifiers[0]->codeSpace()); + remarks += ':'; + remarks += l_identifiers[0]->code(); + if (!l_remarks.empty()) { + remarks += ". "; + remarks += l_remarks; + } + props.set(common::IdentifiedObject::REMARKS_KEY, remarks); + } + } else if (!l_remarks.empty()) { + props.set(common::IdentifiedObject::REMARKS_KEY, l_remarks); } - props.set(common::IdentifiedObject::REMARKS_KEY, remarks); - } else if (!l_remarks.empty()) { - props.set(common::IdentifiedObject::REMARKS_KEY, l_remarks); - } - return props; - }; + return props; + }; const CompoundCRS *compoundCRS = dynamic_cast<const CompoundCRS *>(this); if (compoundCRS) { const auto &comps = compoundCRS->componentReferenceSystems(); - if (!comps.empty() && - comps[0]->mustAxisOrderBeSwitchedForVisualization()) { + if (!comps.empty()) { std::vector<CRSNNPtr> newComps; - newComps.emplace_back(comps[0]->normalizeForVisualization()); + newComps.emplace_back(comps[0]->applyAxisOrderReversal(nameSuffix)); std::string l_name = newComps.back()->nameStr(); for (size_t i = 1; i < comps.size(); i++) { newComps.emplace_back(comps[i]); @@ -946,16 +959,53 @@ CRSNNPtr CRS::normalizeForVisualization() const { const GeographicCRS *geogCRS = dynamic_cast<const GeographicCRS *>(this); if (geogCRS) { const auto &axisList = geogCRS->coordinateSystem()->axisList(); + auto cs = + axisList.size() == 2 + ? cs::EllipsoidalCS::create(util::PropertyMap(), axisList[1], + axisList[0]) + : cs::EllipsoidalCS::create(util::PropertyMap(), axisList[1], + axisList[0], axisList[2]); + return util::nn_static_pointer_cast<CRS>( + GeographicCRS::create(createProperties(), geogCRS->datum(), + geogCRS->datumEnsemble(), cs)); + } + + const ProjectedCRS *projCRS = dynamic_cast<const ProjectedCRS *>(this); + if (projCRS) { + const auto &axisList = projCRS->coordinateSystem()->axisList(); + auto cs = + axisList.size() == 2 + ? cs::CartesianCS::create(util::PropertyMap(), axisList[1], + axisList[0]) + : cs::CartesianCS::create(util::PropertyMap(), axisList[1], + axisList[0], axisList[2]); + return util::nn_static_pointer_cast<CRS>( + ProjectedCRS::create(createProperties(), projCRS->baseCRS(), + projCRS->derivingConversion(), cs)); + } + + throw util::UnsupportedOperationException( + "axis order reversal not supported on this type of CRS"); +} + +// --------------------------------------------------------------------------- + +CRSNNPtr CRS::normalizeForVisualization() const { + + const CompoundCRS *compoundCRS = dynamic_cast<const CompoundCRS *>(this); + if (compoundCRS) { + const auto &comps = compoundCRS->componentReferenceSystems(); + if (!comps.empty() && + comps[0]->mustAxisOrderBeSwitchedForVisualization()) { + return applyAxisOrderReversal(NORMALIZED_AXIS_ORDER_SUFFIX_STR); + } + } + + const GeographicCRS *geogCRS = dynamic_cast<const GeographicCRS *>(this); + if (geogCRS) { + const auto &axisList = geogCRS->coordinateSystem()->axisList(); if (mustAxisOrderBeSwitchedForVisualizationInternal(axisList)) { - auto cs = axisList.size() == 2 - ? cs::EllipsoidalCS::create(util::PropertyMap(), - axisList[1], axisList[0]) - : cs::EllipsoidalCS::create(util::PropertyMap(), - axisList[1], axisList[0], - axisList[2]); - return util::nn_static_pointer_cast<CRS>( - GeographicCRS::create(createProperties(), geogCRS->datum(), - geogCRS->datumEnsemble(), cs)); + return applyAxisOrderReversal(NORMALIZED_AXIS_ORDER_SUFFIX_STR); } } @@ -963,15 +1013,7 @@ CRSNNPtr CRS::normalizeForVisualization() const { if (projCRS) { const auto &axisList = projCRS->coordinateSystem()->axisList(); if (mustAxisOrderBeSwitchedForVisualizationInternal(axisList)) { - auto cs = - axisList.size() == 2 - ? cs::CartesianCS::create(util::PropertyMap(), axisList[1], - axisList[0]) - : cs::CartesianCS::create(util::PropertyMap(), axisList[1], - axisList[0], axisList[2]); - return util::nn_static_pointer_cast<CRS>( - ProjectedCRS::create(createProperties(), projCRS->baseCRS(), - projCRS->derivingConversion(), cs)); + return applyAxisOrderReversal(NORMALIZED_AXIS_ORDER_SUFFIX_STR); } } @@ -1786,15 +1828,16 @@ static bool exportAsESRIWktCompoundCRSWithEllipsoidalHeight( return false; } const auto l_datum = geodCRS->datumNonNull(formatter->databaseContext()); - auto l_alias = dbContext->getAliasFromOfficialName( + auto l_esri_name = dbContext->getAliasFromOfficialName( l_datum->nameStr(), "geodetic_datum", "ESRI"); - if (l_alias.empty()) { - return false; + if (l_esri_name.empty()) { + l_esri_name = l_datum->nameStr(); } auto authFactory = io::AuthorityFactory::create(NN_NO_CHECK(dbContext), std::string()); auto list = authFactory->createObjectsFromName( - l_alias, {io::AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, + l_esri_name, + {io::AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, false /* approximate=false*/); if (list.empty()) { return false; @@ -1807,11 +1850,39 @@ static bool exportAsESRIWktCompoundCRSWithEllipsoidalHeight( auto vertCRSList = authFactory->createVerticalCRSFromDatum( "ESRI", "from_geogdatum_" + *gdatum_ids[0]->codeSpace() + '_' + gdatum_ids[0]->code()); - if (vertCRSList.size() != 1) { - return false; - } self->demoteTo2D(std::string(), dbContext)->_exportToWKT(formatter); - vertCRSList.front()->_exportToWKT(formatter); + if (vertCRSList.size() == 1) { + vertCRSList.front()->_exportToWKT(formatter); + } else { + // This will not be recognized properly by ESRI software + // See https://github.com/OSGeo/PROJ/issues/2757 + + const auto &axisList = geodCRS->coordinateSystem()->axisList(); + assert(axisList.size() == 3U); + + formatter->startNode(io::WKTConstants::VERTCS, false); + auto vertcs_name = l_esri_name; + if (starts_with(vertcs_name.c_str(), "GCS_")) + vertcs_name = vertcs_name.substr(4); + formatter->addQuotedString(vertcs_name); + + gdatum->_exportToWKT(formatter); + + // Seems to be a constant value... + formatter->startNode(io::WKTConstants::PARAMETER, false); + formatter->addQuotedString("Vertical_Shift"); + formatter->add(0.0); + formatter->endNode(); + + formatter->startNode(io::WKTConstants::PARAMETER, false); + formatter->addQuotedString("Direction"); + formatter->add( + axisList[2]->direction() == cs::AxisDirection::UP ? 1.0 : -1.0); + formatter->endNode(); + + axisList[2]->unit()._exportToWKT(formatter); + formatter->endNode(); + } return true; } @@ -1941,6 +2012,18 @@ void GeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const { aliasFound = true; } } + if (!aliasFound && dbContext) { + auto authFactory = io::AuthorityFactory::create( + NN_NO_CHECK(dbContext), "ESRI"); + aliasFound = + authFactory + ->createObjectsFromName( + l_name, + {io::AuthorityFactory::ObjectType::GEODETIC_CRS}, + false // approximateMatch + ) + .size() == 1; + } if (!aliasFound) { l_name = io::WKTFormatter::morphNameToESRI(l_name); if (!starts_with(l_name, "GCS_")) { @@ -3224,6 +3307,18 @@ void VerticalCRS::_exportToWKT(io::WKTFormatter *formatter) const { aliasFound = true; } } + if (!aliasFound && dbContext) { + auto authFactory = + io::AuthorityFactory::create(NN_NO_CHECK(dbContext), "ESRI"); + aliasFound = + authFactory + ->createObjectsFromName( + l_name, + {io::AuthorityFactory::ObjectType::VERTICAL_CRS}, + false // approximateMatch + ) + .size() == 1; + } if (!aliasFound) { l_name = io::WKTFormatter::morphNameToESRI(l_name); } @@ -3924,10 +4019,24 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { "Projected 3D CRS can only be exported since WKT2:2019"); } - std::string l_alias; + std::string l_esri_name; if (formatter->useESRIDialect() && dbContext) { - l_alias = dbContext->getAliasFromOfficialName(l_name, "projected_crs", - "ESRI"); + l_esri_name = dbContext->getAliasFromOfficialName( + l_name, "projected_crs", "ESRI"); + if (l_esri_name.empty()) { + auto authFactory = + io::AuthorityFactory::create(NN_NO_CHECK(dbContext), "ESRI"); + const bool found = + authFactory + ->createObjectsFromName( + l_name, + {io::AuthorityFactory::ObjectType::PROJECTED_CRS}, + false // approximateMatch + ) + .size() == 1; + if (found) + l_esri_name = l_name; + } } if (!isWKT2 && formatter->useESRIDialect() && !l_identifiers.empty() && @@ -3949,12 +4058,12 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { } } catch (const std::exception &) { } - } else if (!isWKT2 && formatter->useESRIDialect() && !l_alias.empty()) { + } else if (!isWKT2 && formatter->useESRIDialect() && !l_esri_name.empty()) { try { auto res = io::AuthorityFactory::create(NN_NO_CHECK(dbContext), "ESRI") ->createObjectsFromName( - l_alias, + l_esri_name, {io::AuthorityFactory::ObjectType::PROJECTED_CRS}, false); if (res.size() == 1) { @@ -4033,10 +4142,10 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { !l_identifiers.empty()); if (formatter->useESRIDialect()) { - if (l_alias.empty()) { + if (l_esri_name.empty()) { l_name = io::WKTFormatter::morphNameToESRI(l_name); } else { - l_name = l_alias; + l_name = l_esri_name; } } if (!isWKT2 && !formatter->useESRIDialect() && isDeprecated()) { diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index ebef94a2..7c76061e 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -363,6 +363,18 @@ void PrimeMeridian::_exportToWKT( aliasFound = true; } } + if (!aliasFound && dbContext) { + auto authFactory = io::AuthorityFactory::create( + NN_NO_CHECK(dbContext), "ESRI"); + aliasFound = + authFactory + ->createObjectsFromName( + l_name, + {io::AuthorityFactory::ObjectType::PRIME_MERIDIAN}, + false // approximateMatch + ) + .size() == 1; + } if (!aliasFound) { l_name = io::WKTFormatter::morphNameToESRI(l_name); } @@ -820,6 +832,18 @@ void Ellipsoid::_exportToWKT( aliasFound = true; } } + if (!aliasFound && dbContext) { + auto authFactory = io::AuthorityFactory::create( + NN_NO_CHECK(dbContext), "ESRI"); + aliasFound = authFactory + ->createObjectsFromName( + l_name, + {io::AuthorityFactory::ObjectType:: + ELLIPSOID}, + false // approximateMatch + ) + .size() == 1; + } if (!aliasFound) { l_name = io::WKTFormatter::morphNameToESRI(l_name); } @@ -1247,6 +1271,18 @@ void GeodeticReferenceFrame::_exportToWKT( } } } + if (!aliasFound && dbContext) { + auto authFactory = io::AuthorityFactory::create( + NN_NO_CHECK(dbContext), "ESRI"); + aliasFound = authFactory + ->createObjectsFromName( + l_name, + {io::AuthorityFactory::ObjectType:: + GEODETIC_REFERENCE_FRAME}, + false // approximateMatch + ) + .size() == 1; + } if (!aliasFound) { l_name = io::WKTFormatter::morphNameToESRI(l_name); if (!starts_with(l_name, "D_")) { @@ -1985,6 +2021,18 @@ void VerticalReferenceFrame::_exportToWKT( aliasFound = true; } } + if (!aliasFound && dbContext) { + auto authFactory = io::AuthorityFactory::create( + NN_NO_CHECK(dbContext), "ESRI"); + aliasFound = authFactory + ->createObjectsFromName( + l_name, + {io::AuthorityFactory::ObjectType:: + VERTICAL_REFERENCE_FRAME}, + false // approximateMatch + ) + .size() == 1; + } if (!aliasFound) { l_name = io::WKTFormatter::morphNameToESRI(l_name); } diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 24201ee1..9ce642e7 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -3800,6 +3800,39 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard( tryToIdentifyWKT1Method ? getMappingFromWKT1(projectionName) : nullptr; if (mapping) { mapping = selectSphericalOrEllipsoidal(mapping, baseGeodCRS); + } else if (metadata::Identifier::isEquivalentName( + projectionName.c_str(), "Lambert Conformal Conic")) { + // Lambert Conformal Conic or Lambert_Conformal_Conic are respectively + // used by Oracle WKT and Trimble for either LCC 1SP or 2SP, so we + // have to look at parameters to figure out the variant. + bool found2ndStdParallel = false; + bool foundScaleFactor = false; + for (const auto &childNode : projCRSNode->GP()->children()) { + if (ci_equal(childNode->GP()->value(), WKTConstants::PARAMETER)) { + const auto &childNodeChildren = childNode->GP()->children(); + if (childNodeChildren.size() < 2) { + ThrowNotEnoughChildren(WKTConstants::PARAMETER); + } + const std::string wkt1ParameterName( + stripQuotes(childNodeChildren[0])); + if (metadata::Identifier::isEquivalentName( + wkt1ParameterName.c_str(), WKT1_STANDARD_PARALLEL_2)) { + found2ndStdParallel = true; + } else if (metadata::Identifier::isEquivalentName( + wkt1ParameterName.c_str(), WKT1_SCALE_FACTOR)) { + foundScaleFactor = true; + } + } + } + if (found2ndStdParallel && !foundScaleFactor) { + mapping = getMapping(EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP); + } else if (!found2ndStdParallel && foundScaleFactor) { + mapping = getMapping(EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP); + } else if (found2ndStdParallel && foundScaleFactor) { + // Not sure if that happens + mapping = getMapping( + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN); + } } // For Krovak, we need to look at axis to decide between the Krovak and @@ -3833,7 +3866,7 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard( } foundParameters.resize(countParams); } - bool found2ndStdParallel = false; + for (const auto &childNode : projCRSNode->GP()->children()) { if (ci_equal(childNode->GP()->value(), WKTConstants::PARAMETER)) { const auto &childNodeChildren = childNode->GP()->children(); @@ -3886,10 +3919,6 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard( propertiesParameter.set(Identifier::CODESPACE_KEY, Identifier::EPSG); } - if (paramMapping->epsg_code == - EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL) { - found2ndStdParallel = true; - } } propertiesParameter.set(IdentifiedObject::NAME_KEY, parameterName); parameters.push_back( @@ -3906,14 +3935,6 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard( } } - // Oracle WKT: make sure that the 2nd std parallel parameter is found to - // select the LCC_2SP mapping - if (metadata::Identifier::isEquivalentName(wkt1ProjectionName.c_str(), - "Lambert Conformal Conic") && - !found2ndStdParallel) { - propertiesMethod.set(IdentifiedObject::NAME_KEY, wkt1ProjectionName); - } - // Add back important parameters that should normally be present, but // are sometimes missing. Currently we only deal with Scale factor at // natural origin. This is to avoid a default value of 0 to slip in later. diff --git a/src/iso19111/operation/concatenatedoperation.cpp b/src/iso19111/operation/concatenatedoperation.cpp index 185ebb4a..7da561b4 100644 --- a/src/iso19111/operation/concatenatedoperation.cpp +++ b/src/iso19111/operation/concatenatedoperation.cpp @@ -37,6 +37,7 @@ #include "proj/metadata.hpp" #include "proj/util.hpp" +#include "proj/internal/crs_internal.hpp" #include "proj/internal/internal.hpp" #include "proj/internal/io_internal.hpp" @@ -245,15 +246,44 @@ void ConcatenatedOperation::fixStepsDirection( return false; }; + // Apply axis order reversal operation on first operation if needed + // to set CRSs on it + if (operationsInOut.size() >= 1) { + auto &op = operationsInOut.front(); + auto l_sourceCRS = op->sourceCRS(); + auto l_targetCRS = op->targetCRS(); + auto conv = dynamic_cast<const Conversion *>(op.get()); + if (conv && !l_sourceCRS && !l_targetCRS && + isAxisOrderReversal(conv->method()->getEPSGCode())) { + auto reversedCRS = concatOpSourceCRS->applyAxisOrderReversal( + NORMALIZED_AXIS_ORDER_SUFFIX_STR); + op->setCRSs(concatOpSourceCRS, reversedCRS, nullptr); + } + } + + // Apply axis order reversal operation on last operation if needed + // to set CRSs on it + if (operationsInOut.size() >= 2) { + auto &op = operationsInOut.back(); + auto l_sourceCRS = op->sourceCRS(); + auto l_targetCRS = op->targetCRS(); + auto conv = dynamic_cast<const Conversion *>(op.get()); + if (conv && !l_sourceCRS && !l_targetCRS && + isAxisOrderReversal(conv->method()->getEPSGCode())) { + auto reversedCRS = concatOpTargetCRS->applyAxisOrderReversal( + NORMALIZED_AXIS_ORDER_SUFFIX_STR); + op->setCRSs(reversedCRS, concatOpTargetCRS, nullptr); + } + } + for (size_t i = 0; i < operationsInOut.size(); ++i) { auto &op = operationsInOut[i]; auto l_sourceCRS = op->sourceCRS(); auto l_targetCRS = op->targetCRS(); auto conv = dynamic_cast<const Conversion *>(op.get()); if (conv && i == 0 && !l_sourceCRS && !l_targetCRS) { - auto derivedCRS = - dynamic_cast<const crs::DerivedCRS *>(concatOpSourceCRS.get()); - if (derivedCRS) { + if (auto derivedCRS = dynamic_cast<const crs::DerivedCRS *>( + concatOpSourceCRS.get())) { if (i + 1 < operationsInOut.size()) { // use the sourceCRS of the next operation as our target CRS l_targetCRS = operationsInOut[i + 1]->sourceCRS(); diff --git a/src/iso19111/operation/coordinateoperationfactory.cpp b/src/iso19111/operation/coordinateoperationfactory.cpp index b59eeb91..e9bd3cfe 100644 --- a/src/iso19111/operation/coordinateoperationfactory.cpp +++ b/src/iso19111/operation/coordinateoperationfactory.cpp @@ -4347,6 +4347,9 @@ void CoordinateOperationFactory::Private::createOperationsBoundToGeog( const bool heightDepthReversal = ((srcIsUp && dstIsDown) || (srcIsDown && dstIsUp)); + if (convDst == 0) + throw InvalidOperation( + "Conversion factor of target unit is 0"); const double factor = convSrc / convDst; auto conv = Conversion::createChangeVerticalUnit( util::PropertyMap().set( @@ -4460,6 +4463,8 @@ void CoordinateOperationFactory::Private::createOperationsVertToVert( const bool heightDepthReversal = ((srcIsUp && dstIsDown) || (srcIsDown && dstIsUp)); + if (convDst == 0) + throw InvalidOperation("Conversion factor of target unit is 0"); const double factor = convSrc / convDst; if (!equivalentVDatum) { auto name = buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr()); @@ -4557,6 +4562,8 @@ void CoordinateOperationFactory::Private::createOperationsVertToGeogBallpark( const bool heightDepthReversal = ((srcIsUp && dstIsDown) || (srcIsDown && dstIsUp)); + if (convDst == 0) + throw InvalidOperation("Conversion factor of target unit is 0"); const double factor = convSrc / convDst; const auto &sourceCRSExtent = getExtent(sourceCRS); diff --git a/src/iso19111/operation/parammappings.cpp b/src/iso19111/operation/parammappings.cpp index df5ae7c5..240a2b50 100644 --- a/src/iso19111/operation/parammappings.cpp +++ b/src/iso19111/operation/parammappings.cpp @@ -598,11 +598,6 @@ static const MethodMapping projectionMethodMappings[] = { EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, "Lambert_Conformal_Conic_2SP", "lcc", nullptr, paramsLCC2SP}, - // Oracle WKT - {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, - EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, "Lambert Conformal Conic", - "lcc", nullptr, paramsLCC2SP}, - {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, nullptr, // no mapping to WKT1_GDAL diff --git a/src/iso19111/operation/singleoperation.cpp b/src/iso19111/operation/singleoperation.cpp index 2f60828e..4dadfa40 100644 --- a/src/iso19111/operation/singleoperation.cpp +++ b/src/iso19111/operation/singleoperation.cpp @@ -2118,15 +2118,18 @@ bool SingleOperation::exportToPROJStringGeneric( } if (methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT) { - double convFactor = parameterValueNumericAsSI( + const double convFactor = parameterValueNumericAsSI( EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR); - auto uom = common::UnitOfMeasure(std::string(), convFactor, - common::UnitOfMeasure::Type::LINEAR) - .exportToPROJString(); - auto reverse_uom = - common::UnitOfMeasure(std::string(), 1.0 / convFactor, + const auto uom = + common::UnitOfMeasure(std::string(), convFactor, common::UnitOfMeasure::Type::LINEAR) .exportToPROJString(); + const auto reverse_uom = + convFactor == 0.0 + ? std::string() + : common::UnitOfMeasure(std::string(), 1.0 / convFactor, + common::UnitOfMeasure::Type::LINEAR) + .exportToPROJString(); if (uom == "m") { // do nothing } else if (!uom.empty()) { diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 785ec6f0..4ece9094 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -298,6 +298,60 @@ source_group("CMake Files" FILES CMakeLists.txt) # Embed PROJ_LIB data files location add_definitions(-DPROJ_LIB="${CMAKE_INSTALL_PREFIX}/${DATADIR}") + +########################################################### +# targets to refresh wkt1_parser.cpp and wkt2_parser.cpp +########################################################### + +# Those targets need to be run manually each time wkt1_grammar.y / wkt2_grammar.y +# is modified. +# We could of course run them automatically, but that would make building +# PROJ harder. + +# This target checks that wkt1_grammar.y md5sum has not changed +# If it has, then it should be updated and the generate_wkt1_parser target +# should be manually run +add_custom_target(check_wkt1_grammar_md5 ALL + COMMAND ${CMAKE_COMMAND} + "-DIN_FILE=wkt1_grammar.y" + "-DTARGET=generate_wkt1_parser" + "-DEXPECTED_MD5SUM=3a1720c3fa1b759719e33dd558603efb" + -P "${CMAKE_CURRENT_SOURCE_DIR}/check_md5sum.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/wkt1_grammar.y" + VERBATIM) + +add_custom_target(generate_wkt1_parser + COMMAND ${CMAKE_COMMAND} + "-DPREFIX=pj_wkt1_" + "-DIN_FILE=wkt1_grammar.y" + "-DOUT_FILE=wkt1_generated_parser.c" + -P "${CMAKE_CURRENT_SOURCE_DIR}/generate_wkt_parser.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM) + +# This target checks that wkt2_grammar.y md5sum has not changed +# If it has, then it should be updated and the generate_wkt2_parser target +# should be manually run +add_custom_target(check_wkt2_grammar_md5 ALL + COMMAND ${CMAKE_COMMAND} + "-DIN_FILE=wkt2_grammar.y" + "-DTARGET=generate_wkt2_parser" + "-DEXPECTED_MD5SUM=1691b7d213073d5a1b49db2e080bc96e" + -P "${CMAKE_CURRENT_SOURCE_DIR}/check_md5sum.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/wkt2_grammar.y" + VERBATIM) + +add_custom_target(generate_wkt2_parser + COMMAND ${CMAKE_COMMAND} + "-DPREFIX=pj_wkt2_" + "-DIN_FILE=wkt2_grammar.y" + "-DOUT_FILE=wkt2_generated_parser.c" + -P "${CMAKE_CURRENT_SOURCE_DIR}/generate_wkt_parser.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM) + ################################################# ## targets: libproj and proj_config.h ################################################# diff --git a/test/cli/CMakeLists.txt b/test/cli/CMakeLists.txt index 0f86ca3d..b136b05d 100644 --- a/test/cli/CMakeLists.txt +++ b/test/cli/CMakeLists.txt @@ -3,12 +3,14 @@ # set(CS2CS_BIN "cs2cs") set(PROJ_BIN "proj") +set(INVPROJ_BIN "invproj") set(PROJINFO_BIN "projinfo") set(CCT_BIN "cct") set(PROJSYNC_BIN "projsync") proj_add_test_script_sh("test27" PROJ_BIN) proj_add_test_script_sh("test83" PROJ_BIN) proj_add_test_script_sh("testproj" PROJ_BIN) +proj_add_test_script_sh("testinvproj" INVPROJ_BIN) proj_add_test_script_sh("testvarious" CS2CS_BIN) proj_add_test_script_sh("testdatumfile" CS2CS_BIN) proj_add_test_script_sh("testIGNF" CS2CS_BIN) diff --git a/test/cli/Makefile.am b/test/cli/Makefile.am index 46d9d36c..bc840738 100644 --- a/test/cli/Makefile.am +++ b/test/cli/Makefile.am @@ -3,6 +3,7 @@ PROJ_LIB = ../../data/for_tests THIS_DIR = $(top_srcdir)/test/cli EXEPATH = ../../src PROJEXE = $(EXEPATH)/proj +INVPROJEXE = $(EXEPATH)/invproj CS2CSEXE = $(EXEPATH)/cs2cs PROJINFOEXE = $(EXEPATH)/projinfo CCTEXE = $(EXEPATH)/cct @@ -12,6 +13,7 @@ PROJSYNC_EXE = $(EXEPATH)/projsync TEST27 = $(THIS_DIR)/test27 TEST83 = $(THIS_DIR)/test83 TESTPROJ = $(THIS_DIR)/testproj +TESTINVPROJ = $(THIS_DIR)/testinvproj TESTNTV2 = $(THIS_DIR)/testntv2 TESTVARIOUS = $(THIS_DIR)/testvarious TESTFLAKY = $(THIS_DIR)/testflaky @@ -28,6 +30,7 @@ EXTRA_DIST = pj_out27.dist pj_out83.dist td_out.dist \ testprojinfo testprojinfo_out.dist \ testcct testcct_out.dist \ testproj testproj_out.dist \ + testinvproj testinvproj_out.dist \ test_projsync \ CMakeLists.txt @@ -43,6 +46,9 @@ test83-check: testproj-check: PROJ_LIB=$(PROJ_LIB) $(TESTPROJ) $(PROJEXE) +testinvproj-check: + PROJ_LIB=$(PROJ_LIB) $(TESTINVPROJ) $(INVPROJEXE) + testvarious-check: PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY=YES PROJ_LIB=$(PROJ_LIB) $(TESTVARIOUS) $(CS2CSEXE) @@ -67,4 +73,4 @@ testprojsync-check: echo "Skipping testprojsync-check" endif -check-local: testprojinfo-check test27-check test83-check testproj-check testvarious-check testdatumfile-check testign-check testntv2-check testcct-check testprojsync-check +check-local: testprojinfo-check test27-check test83-check testproj-check testinvproj-check testvarious-check testdatumfile-check testign-check testntv2-check testcct-check testprojsync-check diff --git a/test/cli/testinvproj b/test/cli/testinvproj new file mode 100755 index 00000000..878fd118 --- /dev/null +++ b/test/cli/testinvproj @@ -0,0 +1,55 @@ +: +# Script to test invproj exe +# +TEST_CLI_DIR=`dirname $0` +EXE=$1 + +usage() +{ + echo "Usage: ${0} <path to 'invproj' program>" + echo + exit 1 +} + +if test -z "${EXE}"; then + EXE=../../src/invproj +fi + +if test ! -x ${EXE}; then + echo "*** ERROR: Can not find '${EXE}' program!" + exit 1 +fi + +if test -z "${PROJ_LIB}"; then + export PROJ_LIB="`dirname $0`/../../data" +fi + +echo "============================================" +echo "Running ${0} using ${EXE}:" +echo "============================================" + +OUT=testinvproj_out +# +echo "doing tests into file ${OUT}, please wait" +# +$EXE +proj=tmerc +ellps=GRS80 -E -f '%.3f' >${OUT} <<EOF +146339.48 5431555.61 +EOF + +# +# do 'diff' with distribution results +echo "diff ${OUT} with testinvproj_out.dist" +diff -u -b ${OUT} ${TEST_CLI_DIR}/testinvproj_out.dist +if [ $? -ne 0 ] ; then + echo "" + echo "PROBLEMS HAVE OCCURRED" + echo "test file ${OUT} saved" + echo + exit 100 +else + echo "TEST OK" + echo "test file ${OUT} removed" + echo + /bin/rm -f ${OUT} + exit 0 +fi diff --git a/test/cli/testinvproj_out.dist b/test/cli/testinvproj_out.dist new file mode 100644 index 00000000..6b52306f --- /dev/null +++ b/test/cli/testinvproj_out.dist @@ -0,0 +1 @@ +146339.48 5431555.61 2.000 49.000 diff --git a/test/cli/testproj b/test/cli/testproj index 8686224e..d03932fb 100755 --- a/test/cli/testproj +++ b/test/cli/testproj @@ -12,7 +12,7 @@ usage() } if test -z "${EXE}"; then - EXE=../../src/cs2cs + EXE=../../src/proj fi if test ! -x ${EXE}; then diff --git a/test/fuzzers/build.sh b/test/fuzzers/build.sh index 54909fea..25c43fa2 100755 --- a/test/fuzzers/build.sh +++ b/test/fuzzers/build.sh @@ -50,10 +50,20 @@ make -j$(nproc) make install cd .. -./autogen.sh -SQLITE3_CFLAGS=-I/usr/include SQLITE3_LIBS=-lsqlite3 TIFF_CFLAGS=-I$SRC/install/include TIFF_LIBS="-L$SRC/install/lib -ltiff" ./configure --disable-shared --with-curl=$SRC/install/bin/curl-config +mkdir build +cd build +cmake .. -DBUILD_SHARED_LIBS:BOOL=OFF \ + -DCURL_INCLUDE_DIR:PATH="$SRC/install/include" \ + -DCURL_LIBRARY_RELEASE:FILEPATH="$SRC/install/lib/libcurl.a" \ + -DTIFF_INCLUDE_DIR:PATH="$SRC/install/include" \ + -DTIFF_LIBRARY_RELEASE:FILEPATH="$SRC/install/lib/libtiff.a" \ + -DCMAKE_INSTALL_PREFIX=$SRC/install \ + -DBUILD_APPS:BOOL=OFF \ + -DBUILD_TESTING:BOOL=OFF make clean -s make -j$(nproc) -s +make install +cd .. EXTRA_LIBS="-lpthread -Wl,-Bstatic -lsqlite3 -L$SRC/install/lib -ltiff -lcurl -lssl -lcrypto -lz -Wl,-Bdynamic" @@ -66,7 +76,7 @@ build_fuzzer() echo "Building fuzzer $fuzzerName" $CXX $CXXFLAGS -std=c++11 -fvisibility=hidden -Isrc -Iinclude \ $sourceFilename $* -o $OUT/$fuzzerName \ - $LIB_FUZZING_ENGINE src/.libs/libproj.a $EXTRA_LIBS + $LIB_FUZZING_ENGINE "$SRC/install/lib/libproj.a" $EXTRA_LIBS } build_fuzzer proj_crs_to_crs_fuzzer test/fuzzers/proj_crs_to_crs_fuzzer.cpp diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index 987ffe1b..500ff4a4 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -747,6 +747,77 @@ TEST(crs, EPSG_4268_geogcrs_deprecated_as_WKT1_GDAL) { // --------------------------------------------------------------------------- +TEST(crs, ESRI_104971_as_WKT1_ESRI_with_database) { + auto dbContext = DatabaseContext::create(); + auto factory = AuthorityFactory::create(dbContext, "ESRI"); + auto crs = factory->createCoordinateReferenceSystem("104971"); + WKTFormatterNNPtr f(WKTFormatter::create( + WKTFormatter::Convention::WKT1_ESRI, DatabaseContext::create())); + // Check that the _(Sphere) suffix is preserved + EXPECT_EQ(crs->exportToWKT(f.get()), + "GEOGCS[\"Mars_2000_(Sphere)\",DATUM[\"Mars_2000_(Sphere)\"," + "SPHEROID[\"Mars_2000_(Sphere)\",3396190.0,0.0]]," + "PRIMEM[\"Reference_Meridian\",0.0]," + "UNIT[\"Degree\",0.0174532925199433]]"); +} + +// --------------------------------------------------------------------------- + +TEST(crs, + implicit_compound_ESRI_104024_plus_115844_as_WKT1_ESRI_with_database) { + auto dbContext = DatabaseContext::create(); + auto obj = createFromUserInput("ESRI:104024+115844", dbContext); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->coordinateSystem()->axisList().size(), 3U); + WKTFormatterNNPtr f(WKTFormatter::create( + WKTFormatter::Convention::WKT1_ESRI, DatabaseContext::create())); + // Situation where there is no EPSG official name + EXPECT_EQ(crs->exportToWKT(f.get()), + "GEOGCS[\"California_SRS_Epoch_2017.50_(NAD83)\"," + "DATUM[\"California_SRS_Epoch_2017.50_(NAD83)\"," + "SPHEROID[\"GRS_1980\",6378137.0,298.257222101]]," + "PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]]," + "VERTCS[\"California_SRS_Epoch_2017.50_(NAD83)\"," + "DATUM[\"California_SRS_Epoch_2017.50_(NAD83)\"," + "SPHEROID[\"GRS_1980\",6378137.0,298.257222101]]," + "PARAMETER[\"Vertical_Shift\",0.0]," + "PARAMETER[\"Direction\",1.0],UNIT[\"Meter\",1.0]]"); +} + +// --------------------------------------------------------------------------- + +TEST(crs, implicit_compound_ESRI_104971_to_3D_as_WKT1_ESRI_with_database) { + auto dbContext = DatabaseContext::create(); + auto factory = AuthorityFactory::create(dbContext, "ESRI"); + auto crs = factory->createGeographicCRS("104971")->promoteTo3D( + std::string(), dbContext); + WKTFormatterNNPtr f(WKTFormatter::create( + WKTFormatter::Convention::WKT1_ESRI, DatabaseContext::create())); + // Situation where there is no ESRI vertical CRS, but the GEOGCS does exist + // This will be only partly recognized by ESRI software. + // See https://github.com/OSGeo/PROJ/issues/2757 + const char *wkt = "GEOGCS[\"Mars_2000_(Sphere)\"," + "DATUM[\"Mars_2000_(Sphere)\"," + "SPHEROID[\"Mars_2000_(Sphere)\",3396190.0,0.0]]," + "PRIMEM[\"Reference_Meridian\",0.0]," + "UNIT[\"Degree\",0.0174532925199433]]," + "VERTCS[\"Mars_2000_(Sphere)\"," + "DATUM[\"Mars_2000_(Sphere)\"," + "SPHEROID[\"Mars_2000_(Sphere)\",3396190.0,0.0]]," + "PARAMETER[\"Vertical_Shift\",0.0]," + "PARAMETER[\"Direction\",1.0]," + "UNIT[\"Meter\",1.0]]"; + EXPECT_EQ(crs->exportToWKT(f.get()), wkt); + + auto obj2 = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt); + auto crs2 = nn_dynamic_pointer_cast<GeographicCRS>(obj2); + ASSERT_TRUE(crs2 != nullptr); + EXPECT_EQ(crs2->coordinateSystem()->axisList().size(), 3U); +} + +// --------------------------------------------------------------------------- + TEST(crs, IAU_1000_as_WKT2) { auto dbContext = DatabaseContext::create(); auto factory = AuthorityFactory::create(dbContext, "IAU_2015"); @@ -3877,6 +3948,23 @@ TEST(crs, verticalCRS_down_as_WKT1_ESRI) { // --------------------------------------------------------------------------- +TEST(crs, verticalCRS_ESRI_115834_as_WKT1_ESRI_with_database) { + auto dbContext = DatabaseContext::create(); + auto factory = AuthorityFactory::create(dbContext, "ESRI"); + auto crs = factory->createCoordinateReferenceSystem("115834"); + WKTFormatterNNPtr f(WKTFormatter::create( + WKTFormatter::Convention::WKT1_ESRI, DatabaseContext::create())); + // Check that the parentheses in the VERTCS and DATUM names are preserved + EXPECT_EQ(crs->exportToWKT(f.get()), + "VERTCS[\"NAD83(CSRS)v5\"," + "DATUM[\"North_American_Datum_of_1983_(CSRS)_version_5\"," + "SPHEROID[\"GRS_1980\",6378137.0,298.257222101]]," + "PARAMETER[\"Vertical_Shift\",0.0]," + "PARAMETER[\"Direction\",1.0],UNIT[\"Meter\",1.0]]"); +} + +// --------------------------------------------------------------------------- + TEST(crs, verticalCRS_identify_db) { auto dbContext = DatabaseContext::create(); auto factory = AuthorityFactory::create(dbContext, "EPSG"); diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 4e888f2c..196552d4 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -6394,6 +6394,37 @@ TEST(wkt_parse, wkt1_oracle) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_lcc_1sp_without_1sp_suffix) { + // WKT from Trimble + auto wkt = "PROJCS[\"TWM-Madison Co LDP\"," + "GEOGCS[\"WGS 1984\"," + "DATUM[\"WGS 1984\"," + "SPHEROID[\"World Geodetic System 1984\"," + "6378137,298.257223563]]," + "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," + "UNIT[\"Degree\",0.01745329251994," + "AUTHORITY[\"EPSG\",\"9102\"]]," + "AXIS[\"Long\",EAST],AXIS[\"Lat\",NORTH]]," + "PROJECTION[\"Lambert_Conformal_Conic\"]," + "PARAMETER[\"False_Easting\",103000.0000035]," + "PARAMETER[\"False_Northing\",79000.00007055]," + "PARAMETER[\"Latitude_Of_Origin\",38.83333333333]," + "PARAMETER[\"Central_Meridian\",-89.93333333333]," + "PARAMETER[\"Scale_Factor\",1.000019129]," + "UNIT[\"Foot_US\",0.3048006096012,AUTHORITY[\"EPSG\",\"9003\"]]," + "AXIS[\"East\",EAST],AXIS[\"North\",NORTH]]"; + + auto dbContext = DatabaseContext::create(); + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + + EXPECT_EQ(crs->derivingConversion()->method()->nameStr(), + "Lambert Conic Conformal (1SP)"); +} + +// --------------------------------------------------------------------------- + TEST(wkt_parse, invalid) { EXPECT_THROW(WKTParser().createFromWKT(""), ParsingException); EXPECT_THROW(WKTParser().createFromWKT("A"), ParsingException); diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index f76647e2..0e27aa9b 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -5429,6 +5429,20 @@ TEST(operation, normalizeForVisualization) { auto authFactory = AuthorityFactory::create(DatabaseContext::create(), "EPSG"); + const auto checkThroughWKTRoundtrip = [](const CoordinateOperationNNPtr + &opRef) { + auto wkt = opRef->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2019).get()); + auto objFromWkt = WKTParser().createFromWKT(wkt); + auto opFromWkt = + nn_dynamic_pointer_cast<CoordinateOperation>(objFromWkt); + ASSERT_TRUE(opFromWkt != nullptr); + EXPECT_TRUE(opRef->_isEquivalentTo(opFromWkt.get())); + EXPECT_EQ( + opFromWkt->exportToPROJString(PROJStringFormatter::create().get()), + opRef->exportToPROJString(PROJStringFormatter::create().get())); + }; + // Source(geographic) must be inverted { auto src = authFactory->createCoordinateReferenceSystem("4326"); @@ -5443,6 +5457,7 @@ TEST(operation, normalizeForVisualization) { "+proj=pipeline " "+step +proj=unitconvert +xy_in=deg +xy_out=rad " "+step +proj=utm +zone=31 +ellps=WGS84"); + checkThroughWKTRoundtrip(opNormalized); } // Target(geographic) must be inverted @@ -5459,6 +5474,7 @@ TEST(operation, normalizeForVisualization) { "+proj=pipeline " "+step +inv +proj=utm +zone=31 +ellps=WGS84 " "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); + checkThroughWKTRoundtrip(opNormalized); } // Source(geographic) and target(projected) must be inverted @@ -5475,6 +5491,7 @@ TEST(operation, normalizeForVisualization) { "+proj=pipeline " "+step +proj=unitconvert +xy_in=deg +xy_out=rad " "+step +proj=utm +zone=28 +ellps=GRS80"); + checkThroughWKTRoundtrip(opNormalized); } // No inversion |
