diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 51ed18e5ce..1d10c1e5d6 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -31,7 +31,7 @@ set(ALL_SQL_IN "${CMAKE_CURRENT_BINARY_DIR}/all.sql.in") set(PROJ_DB "${CMAKE_CURRENT_BINARY_DIR}/proj.db") include(sql_filelist.cmake) -set(PROJ_DB_SQL_EXPECTED_MD5 "5e23b08c318cecbd9cace26233f8f5d4") +set(PROJ_DB_SQL_EXPECTED_MD5 "8145b5734f4007f81b188ac3b690e8b3") add_custom_command( OUTPUT ${PROJ_DB} diff --git a/data/sql/wgs84_realizations_concatenated_operations.sql b/data/sql/wgs84_realizations_concatenated_operations.sql new file mode 100644 index 0000000000..93cf0dd417 --- /dev/null +++ b/data/sql/wgs84_realizations_concatenated_operations.sql @@ -0,0 +1,188 @@ +--- This file has been generated by scripts/build_wgs84_realizations_concatenated_operations.py. DO NOT EDIT ! + +-- Concatenated accuracy is sum of accuracies + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G873','WGS 84 (Transit) to WGS 84 (G873)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7815','EPSG','7658',0.74,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G873',1,'EPSG','9960','forward'); -- WGS 84 (Transit) to WGS 84 (G730) (EPSG:9960), 0.7 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G873',2,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO usage VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G873_USAGE','concatenated_operation','PROJ','WGS_84_TRANSIT_TO_WGS_84_G873', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1150','WGS 84 (Transit) to WGS 84 (G1150)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7815','EPSG','7660',0.77,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1150',1,'EPSG','9960','forward'); -- WGS 84 (Transit) to WGS 84 (G730) (EPSG:9960), 0.7 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1150',2,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1150',3,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO usage VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1150_USAGE','concatenated_operation','PROJ','WGS_84_TRANSIT_TO_WGS_84_G1150', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1674','WGS 84 (Transit) to WGS 84 (G1674)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7815','EPSG','7662',0.79,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1674',1,'EPSG','9960','forward'); -- WGS 84 (Transit) to WGS 84 (G730) (EPSG:9960), 0.7 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1674',2,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1674',3,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1674',4,'EPSG','9963','forward'); -- WGS 84 (G1150) to WGS 84 (G1674) (EPSG:9963), 0.02 m +INSERT INTO usage VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1674_USAGE','concatenated_operation','PROJ','WGS_84_TRANSIT_TO_WGS_84_G1674', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1762','WGS 84 (Transit) to WGS 84 (G1762)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7815','EPSG','7664',0.79,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1762',1,'EPSG','9960','forward'); -- WGS 84 (Transit) to WGS 84 (G730) (EPSG:9960), 0.7 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1762',2,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1762',3,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1762',4,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO usage VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G1762_USAGE','concatenated_operation','PROJ','WGS_84_TRANSIT_TO_WGS_84_G1762', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139','WGS 84 (Transit) to WGS 84 (G2139)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7815','EPSG','9753',0.8,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139',1,'EPSG','9960','forward'); -- WGS 84 (Transit) to WGS 84 (G730) (EPSG:9960), 0.7 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139',2,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139',3,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139',4,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139',5,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139_USAGE','concatenated_operation','PROJ','WGS_84_TRANSIT_TO_WGS_84_G2139', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296','WGS 84 (Transit) to WGS 84 (G2296)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7815','EPSG','10604',0.81,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296',1,'EPSG','9960','forward'); -- WGS 84 (Transit) to WGS 84 (G730) (EPSG:9960), 0.7 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296',2,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296',3,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296',4,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296',5,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296',6,'EPSG','10607','forward'); -- WGS 84 (G2139) to WGS 84 (G2296) (EPSG:10607), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296_USAGE','concatenated_operation','PROJ','WGS_84_TRANSIT_TO_WGS_84_G2296', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1150','WGS 84 (G730) to WGS 84 (G1150)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7656','EPSG','7660',0.07,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1150',1,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1150',2,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO usage VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1150_USAGE','concatenated_operation','PROJ','WGS_84_G730_TO_WGS_84_G1150', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1674','WGS 84 (G730) to WGS 84 (G1674)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7656','EPSG','7662',0.09,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1674',1,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1674',2,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1674',3,'EPSG','9963','forward'); -- WGS 84 (G1150) to WGS 84 (G1674) (EPSG:9963), 0.02 m +INSERT INTO usage VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1674_USAGE','concatenated_operation','PROJ','WGS_84_G730_TO_WGS_84_G1674', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1762','WGS 84 (G730) to WGS 84 (G1762)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7656','EPSG','7664',0.09,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1762',1,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1762',2,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1762',3,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO usage VALUES('PROJ','WGS_84_G730_TO_WGS_84_G1762_USAGE','concatenated_operation','PROJ','WGS_84_G730_TO_WGS_84_G1762', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2139','WGS 84 (G730) to WGS 84 (G2139)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7656','EPSG','9753',0.1,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2139',1,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2139',2,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2139',3,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2139',4,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2139_USAGE','concatenated_operation','PROJ','WGS_84_G730_TO_WGS_84_G2139', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2296','WGS 84 (G730) to WGS 84 (G2296)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7656','EPSG','10604',0.11,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2296',1,'EPSG','9961','forward'); -- WGS 84 (G730) to WGS 84 (G873) (EPSG:9961), 0.04 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2296',2,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2296',3,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2296',4,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2296',5,'EPSG','10607','forward'); -- WGS 84 (G2139) to WGS 84 (G2296) (EPSG:10607), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G730_TO_WGS_84_G2296_USAGE','concatenated_operation','PROJ','WGS_84_G730_TO_WGS_84_G2296', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1674','WGS 84 (G873) to WGS 84 (G1674)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7658','EPSG','7662',0.05,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1674',1,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1674',2,'EPSG','9963','forward'); -- WGS 84 (G1150) to WGS 84 (G1674) (EPSG:9963), 0.02 m +INSERT INTO usage VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1674_USAGE','concatenated_operation','PROJ','WGS_84_G873_TO_WGS_84_G1674', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1762','WGS 84 (G873) to WGS 84 (G1762)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7658','EPSG','7664',0.05,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1762',1,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1762',2,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO usage VALUES('PROJ','WGS_84_G873_TO_WGS_84_G1762_USAGE','concatenated_operation','PROJ','WGS_84_G873_TO_WGS_84_G1762', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2139','WGS 84 (G873) to WGS 84 (G2139)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7658','EPSG','9753',0.06,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2139',1,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2139',2,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2139',3,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2139_USAGE','concatenated_operation','PROJ','WGS_84_G873_TO_WGS_84_G2139', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2296','WGS 84 (G873) to WGS 84 (G2296)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7658','EPSG','10604',0.07,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2296',1,'EPSG','9962','forward'); -- WGS 84 (G873) to WGS 84 (G1150) (EPSG:9962), 0.03 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2296',2,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2296',3,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2296',4,'EPSG','10607','forward'); -- WGS 84 (G2139) to WGS 84 (G2296) (EPSG:10607), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G873_TO_WGS_84_G2296_USAGE','concatenated_operation','PROJ','WGS_84_G873_TO_WGS_84_G2296', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2139','WGS 84 (G1150) to WGS 84 (G2139)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7660','EPSG','9753',0.03,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2139',1,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2139',2,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2139_USAGE','concatenated_operation','PROJ','WGS_84_G1150_TO_WGS_84_G2139', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2296','WGS 84 (G1150) to WGS 84 (G2296)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7660','EPSG','10604',0.04,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2296',1,'EPSG','7668','forward'); -- WGS 84 (G1150) to WGS 84 (G1762) (EPSG:7668), 0.02 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2296',2,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2296',3,'EPSG','10607','forward'); -- WGS 84 (G2139) to WGS 84 (G2296) (EPSG:10607), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G1150_TO_WGS_84_G2296_USAGE','concatenated_operation','PROJ','WGS_84_G1150_TO_WGS_84_G2296', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2139','WGS 84 (G1674) to WGS 84 (G2139)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7662','EPSG','9753',0.02,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2139',1,'EPSG','7667','forward'); -- WGS 84 (G1674) to WGS 84 (G1762) (EPSG:7667), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2139',2,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2139_USAGE','concatenated_operation','PROJ','WGS_84_G1674_TO_WGS_84_G2139', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2296','WGS 84 (G1674) to WGS 84 (G2296)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7662','EPSG','10604',0.03,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2296',1,'EPSG','7667','forward'); -- WGS 84 (G1674) to WGS 84 (G1762) (EPSG:7667), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2296',2,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2296',3,'EPSG','10607','forward'); -- WGS 84 (G2139) to WGS 84 (G2296) (EPSG:10607), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G1674_TO_WGS_84_G2296_USAGE','concatenated_operation','PROJ','WGS_84_G1674_TO_WGS_84_G2296', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + +INSERT INTO concatenated_operation VALUES('PROJ','WGS_84_G1762_TO_WGS_84_G2296','WGS 84 (G1762) to WGS 84 (G2296)','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','7664','EPSG','10604',0.02,NULL,0); +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1762_TO_WGS_84_G2296',1,'EPSG','9756','forward'); -- WGS 84 (G1762) to WGS 84 (G2139) (EPSG:9756), 0.01 m +INSERT INTO concatenated_operation_step VALUES('PROJ','WGS_84_G1762_TO_WGS_84_G2296',2,'EPSG','10607','forward'); -- WGS 84 (G2139) to WGS 84 (G2296) (EPSG:10607), 0.01 m +INSERT INTO usage VALUES('PROJ','WGS_84_G1762_TO_WGS_84_G2296_USAGE','concatenated_operation','PROJ','WGS_84_G1762_TO_WGS_84_G2296', + 'EPSG','1262', -- extent: World + 'EPSG','1027' -- scope: Geodesy +); + diff --git a/data/sql_filelist.cmake b/data/sql_filelist.cmake index 47e1ff86c7..fa4a455ab5 100644 --- a/data/sql_filelist.cmake +++ b/data/sql_filelist.cmake @@ -58,6 +58,7 @@ list(APPEND SQL_FILES "${SQL_DIR}/grid_alternatives.sql" "${SQL_DIR}/grid_alternatives_generated_noaa.sql" "${SQL_DIR}/nadcon5_concatenated_operations.sql" + "${SQL_DIR}/wgs84_realizations_concatenated_operations.sql" "${SQL_DIR}/customizations.sql" "${SQL_DIR}/nkg_post_customizations.sql" "${SQL_DIR}/commit.sql" diff --git a/scripts/build_wgs84_realizations_concatenated_operations.py b/scripts/build_wgs84_realizations_concatenated_operations.py new file mode 100755 index 0000000000..a0cd2a3fc5 --- /dev/null +++ b/scripts/build_wgs84_realizations_concatenated_operations.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +############################################################################### +# $Id$ +# +# Project: PROJ +# Purpose: Populate data/sql/wgs84_realizations_concatenated_operations.sql +# Author: Even Rouault +# +############################################################################### +# Copyright (c) 2025, Even Rouault +# +# SPDX-License-Identifier: MIT +############################################################################### + +import os + +script_dir_name = os.path.dirname(os.path.realpath(__file__)) +sql_dir_name = os.path.join(os.path.dirname(script_dir_name), 'data', 'sql') + +out_filename = os.path.join(sql_dir_name, 'wgs84_realizations_concatenated_operations') + '.sql' +#print(out_filename) + +def sanitize_crs_name_for_code(name): + return name.replace('(', '_').replace(')', '').replace(' ','_').replace('__','_').upper() + +def gen_transformations(sql, transformations, crs_dict): + for i in range(len(transformations)): + if transformations[i][0] == "WGS 84 (G1150)" and transformations[i][1] == "WGS 84 (G1762)": + continue + for j in range(i+1,len(transformations)): + if transformations[j][0] == "WGS 84 (G1150)" and transformations[j][1] == "WGS 84 (G1762)": + continue + source_crs = transformations[i][0] + target_crs = transformations[j][1] + + source_crs_week = 0 if source_crs == "WGS 84 (Transit)" else int(source_crs[len("WGS 84 (G"):-1]) + target_crs_week = int(target_crs[len("WGS 84 (G"):-1]) + + transfm_code = sanitize_crs_name_for_code(source_crs) + "_TO_" + sanitize_crs_name_for_code(target_crs) + transfm_name = f"{source_crs} to {target_crs}" + + source_crs_code = crs_dict[source_crs] + target_crs_code = crs_dict[target_crs] + + step = 0 + steps_sql = [] + total_acc = 0 + for k in range(i,j+1): + source_crs_name = transformations[k][0] + target_crs_name = transformations[k][1] + if source_crs_week <= 1150 and target_crs_week >= 1762 and \ + ((source_crs_name == "WGS 84 (G1150)" and target_crs_name == "WGS 84 (G1674)") or \ + (source_crs_name == "WGS 84 (G1674)" and target_crs_name == "WGS 84 (G1762)")): + continue + step += 1 + step_code = transformations[k][2] + acc = transformations[k][3] + total_acc += acc + steps_sql.append(f"INSERT INTO concatenated_operation_step VALUES('PROJ','{transfm_code}',{step},'EPSG','{step_code}','forward'); -- {source_crs_name} to {target_crs_name} (EPSG:{step_code}), {acc} m\n") + + if len(steps_sql) <= 1: + continue + + total_acc = round(total_acc * 100) / 100.0 + + sql += f"INSERT INTO concatenated_operation VALUES('PROJ','{transfm_code}','{transfm_name}','Transformation based on concatenation of transformations between WGS 84 realizations','EPSG','{source_crs_code}','EPSG','{target_crs_code}',{total_acc},NULL,0);\n" + + for step_sql in steps_sql: + sql += step_sql + + sql += f"INSERT INTO usage VALUES('PROJ','{transfm_code}_USAGE','concatenated_operation','PROJ','{transfm_code}',\n" + sql += " 'EPSG','1262', -- extent: World\n" + sql += " 'EPSG','1027' -- scope: Geodesy\n" + sql += ");\n" + + sql += "\n" + + return sql + +crs_dict = { + "WGS 84 (Transit)": 7815, + "WGS 84 (G730)": 7656, + "WGS 84 (G873)": 7658, + "WGS 84 (G1150)": 7660, + "WGS 84 (G1674)": 7662, + "WGS 84 (G1762)": 7664, + "WGS 84 (G2139)": 9753, + "WGS 84 (G2296)": 10604, +} + +f = open(out_filename, 'wb') +f.write("--- This file has been generated by scripts/build_wgs84_realizations_concatenated_operations.py. DO NOT EDIT !\n\n".encode('UTF-8')) + +f.write("-- Concatenated accuracy is sum of accuracies\n\n".encode('UTF-8')) + +sql = "" + +transformations = [ + ("WGS 84 (Transit)", "WGS 84 (G730)", 9960, 0.7), # regular Helmert + ("WGS 84 (G730)", "WGS 84 (G873)", 9961, 0.04), # regular Helmert + ("WGS 84 (G873)", "WGS 84 (G1150)", 9962, 0.03), # time-dependent Helmert + ("WGS 84 (G1150)", "WGS 84 (G1674)", 9963, 0.02), # time-dependent Helmert + ("WGS 84 (G1150)", "WGS 84 (G1762)", 7668, 0.02), # regular Helmert. Note that it doesn't go through G1674 + ("WGS 84 (G1674)", "WGS 84 (G1762)", 7667, 0.01), # regular Helmert + ("WGS 84 (G1762)", "WGS 84 (G2139)", 9756, 0.01), # regular Helmert + ("WGS 84 (G2139)", "WGS 84 (G2296)", 10607, 0.01), # regular Helmert +] + +sql = gen_transformations(sql, transformations, crs_dict) + +f.write(sql.encode('UTF-8')) + +f.close() diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 5550fd430d..92aa1ed7b9 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -7308,7 +7308,8 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( const std::string &code) { return !(d->run("SELECT 1 FROM coordinate_operation_view WHERE " "(source_crs_auth_name = ? AND source_crs_code = ?) OR " - "(target_crs_auth_name = ? AND target_crs_code = ?)", + "(target_crs_auth_name = ? AND target_crs_code = ?) " + "LIMIT 1", {auth_name, code, auth_name, code}) .empty()); }; @@ -7407,36 +7408,50 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( "AND v2.target_crs_auth_name = ? AND v2.target_crs_code = ? "); std::string minDate; std::string criterionOnIntermediateCRS; + + const auto sourceCRS = d->createFactory(sourceCRSAuthName) + ->createCoordinateReferenceSystem(sourceCRSCode); + const auto targetCRS = d->createFactory(targetCRSAuthName) + ->createCoordinateReferenceSystem(targetCRSCode); + + const bool ETRFtoETRF = starts_with(sourceCRS->nameStr(), "ETRF") && + starts_with(targetCRS->nameStr(), "ETRF"); + if (allowedIntermediateObjectType == ObjectType::GEOGRAPHIC_CRS) { - auto sourceCRS = d->createFactory(sourceCRSAuthName) - ->createGeodeticCRS(sourceCRSCode); - auto targetCRS = d->createFactory(targetCRSAuthName) - ->createGeodeticCRS(targetCRSCode); - const auto &sourceDatum = sourceCRS->datum(); - const auto &targetDatum = targetCRS->datum(); - if (sourceDatum && sourceDatum->publicationDate().has_value() && - targetDatum && targetDatum->publicationDate().has_value()) { - const auto sourceDate(sourceDatum->publicationDate()->toString()); - const auto targetDate(targetDatum->publicationDate()->toString()); - minDate = std::min(sourceDate, targetDate); - // Check that the datum of the intermediateCRS has a publication - // date most recent that the one of the source and the target CRS - // Except when using the usual WGS84 pivot which happens to have a - // NULL publication date. - criterionOnIntermediateCRS = - "AND EXISTS(SELECT 1 FROM geodetic_crs x " - "JOIN geodetic_datum y " - "ON " - "y.auth_name = x.datum_auth_name AND " - "y.code = x.datum_code " - "WHERE " - "x.auth_name = v1.target_crs_auth_name AND " - "x.code = v1.target_crs_code AND " - "x.type IN ('geographic 2D', 'geographic 3D') AND " - "(y.publication_date IS NULL OR " - "(y.publication_date >= '" + - minDate + "'))) "; - } else { + const auto &sourceGeogCRS = + dynamic_cast(sourceCRS.get()); + const auto &targetGeogCRS = + dynamic_cast(targetCRS.get()); + if (sourceGeogCRS && targetGeogCRS) { + const auto &sourceDatum = sourceGeogCRS->datum(); + const auto &targetDatum = targetGeogCRS->datum(); + if (sourceDatum && sourceDatum->publicationDate().has_value() && + targetDatum && targetDatum->publicationDate().has_value()) { + const auto sourceDate( + sourceDatum->publicationDate()->toString()); + const auto targetDate( + targetDatum->publicationDate()->toString()); + minDate = std::min(sourceDate, targetDate); + // Check that the datum of the intermediateCRS has a publication + // date most recent that the one of the source and the target + // CRS Except when using the usual WGS84 pivot which happens to + // have a NULL publication date. + criterionOnIntermediateCRS = + "AND EXISTS(SELECT 1 FROM geodetic_crs x " + "JOIN geodetic_datum y " + "ON " + "y.auth_name = x.datum_auth_name AND " + "y.code = x.datum_code " + "WHERE " + "x.auth_name = v1.target_crs_auth_name AND " + "x.code = v1.target_crs_code AND " + "x.type IN ('geographic 2D', 'geographic 3D') AND " + "(y.publication_date IS NULL OR " + "(y.publication_date >= '" + + minDate + "'))) "; + } + } + if (criterionOnIntermediateCRS.empty()) { criterionOnIntermediateCRS = "AND EXISTS(SELECT 1 FROM geodetic_crs x WHERE " "x.auth_name = v1.target_crs_auth_name AND " @@ -7586,6 +7601,33 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( if (discardSuperseded) { res = filterOutSuperseded(std::move(res)); } + + const auto checkPivotForETRFToETRF = + [ETRFtoETRF, &sourceCRS, + &targetCRS](const crs::CRSPtr &intermediateCRS) { + // Make sure that ETRF2000 to ETRF2014 doesn't go throught ITRF9x or + // ITRF>2014 + if (ETRFtoETRF && intermediateCRS && + starts_with(intermediateCRS->nameStr(), "ITRF")) { + const auto normalizeDate = [](int v) { + return (v >= 80 && v <= 99) ? v + 1900 : v; + }; + const int srcDate = normalizeDate( + atoi(sourceCRS->nameStr().c_str() + strlen("ETRF"))); + const int tgtDate = normalizeDate( + atoi(targetCRS->nameStr().c_str() + strlen("ETRF"))); + const int intermDate = normalizeDate( + atoi(intermediateCRS->nameStr().c_str() + strlen("ITRF"))); + if (srcDate > 0 && tgtDate > 0 && intermDate > 0) { + if (intermDate < std::min(srcDate, tgtDate) || + intermDate > std::max(srcDate, tgtDate)) { + return false; + } + } + } + return true; + }; + for (const auto &row : res) { const auto &table1 = row[0]; const auto &auth_name1 = row[1]; @@ -7604,6 +7646,9 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( targetCRSAuthName, targetCRSCode)) { continue; } + if (!checkPivotForETRFToETRF(op1->targetCRS())) { + continue; + } auto op2 = d->createFactory(auth_name2) ->createCoordinateOperation( @@ -7642,6 +7687,7 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( if (discardSuperseded) { res = filterOutSuperseded(std::move(res)); } + for (const auto &row : res) { const auto &table1 = row[0]; const auto &auth_name1 = row[1]; @@ -7660,6 +7706,9 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( targetCRSAuthName, targetCRSCode)) { continue; } + if (!checkPivotForETRFToETRF(op1->targetCRS())) { + continue; + } auto op2 = d->createFactory(auth_name2) ->createCoordinateOperation( @@ -7737,6 +7786,9 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( targetCRSAuthName, targetCRSCode)) { continue; } + if (!checkPivotForETRFToETRF(op1->sourceCRS())) { + continue; + } auto op2 = d->createFactory(auth_name2) ->createCoordinateOperation( @@ -7793,6 +7845,9 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( targetCRSAuthName, targetCRSCode)) { continue; } + if (!checkPivotForETRFToETRF(op1->sourceCRS())) { + continue; + } auto op2 = d->createFactory(auth_name2) ->createCoordinateOperation( diff --git a/test/cli/test_projinfo.yaml b/test/cli/test_projinfo.yaml index f4760317eb..74e3cbbffb 100644 --- a/test/cli/test_projinfo.yaml +++ b/test/cli/test_projinfo.yaml @@ -1867,3 +1867,26 @@ tests: +step +inv +proj=cart +ellps=WGS84 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 +- comment: > + Test that ETRF2000 to ETRF2014 only goes through ITRF2000, ITRF2008 or ITRF2014, and not ITRF9x or ITRF>2020 + args: -s ETRF2000 -t ETRF2014 --3d --summary --authority EPSG + out: | + Candidate operations found: 6 + unknown id, Conversion from ETRF2000 (geog3D) to ETRF2000 (geocentric) + Inverse of ITRF2014 to ETRF2000 (1) + ITRF2014 to ETRF2014 (2) + Conversion from ETRF2014 (geocentric) to ETRF2014 (geog3D), 0 m, Europe - onshore and offshore - ETRF extent - approximately 16°W to 33°E and 33°N to 84°N., time-dependent operation + unknown id, Conversion from ETRF2000 (geog3D) to ETRF2000 (geocentric) + Inverse of ITRF2014 to ETRF2000 (1) + ITRF2014 to ETRF2014 (1) + Conversion from ETRF2014 (geocentric) to ETRF2014 (geog3D), 0 m, Europe - onshore and offshore - ETRF extent - approximately 16°W to 33°E and 33°N to 84°N., time-dependent operation + unknown id, Conversion from ETRF2000 (geog3D) to ETRF2000 (geocentric) + Inverse of ITRF2008 to ETRF2000 (1) + ITRF2008 to ETRF2014 (1) + Conversion from ETRF2014 (geocentric) to ETRF2014 (geog3D), 0 m, Europe - onshore and offshore - ETRF extent - approximately 16°W to 33°E and 33°N to 84°N., time-dependent operation + unknown id, Conversion from ETRF2000 (geog3D) to ETRF2000 (geocentric) + Inverse of ITRF2005 to ETRF2000 (1) + ITRF2005 to ETRF2014 (1) + Conversion from ETRF2014 (geocentric) to ETRF2014 (geog3D), 0 m, Europe - onshore and offshore - ETRF extent - approximately 16°W to 33°E and 33°N to 84°N., time-dependent operation + unknown id, Conversion from ETRF2000 (geog3D) to ETRF2000 (geocentric) + Inverse of ITRF2000 to ETRF2000 (2) + ITRF2000 to ETRF2014 (1) + Conversion from ETRF2014 (geocentric) to ETRF2014 (geog3D), 0 m, Europe - onshore and offshore - ETRF extent - approximately 16°W to 33°E and 33°N to 84°N., time-dependent operation + unknown id, Conversion from ETRF2000 (geog3D) to ETRF2000 (geocentric) + Inverse of ITRF2000 to ETRF2000 (1) + ITRF2000 to ETRF2014 (1) + Conversion from ETRF2014 (geocentric) to ETRF2014 (geog3D), 0 m, Europe - onshore and offshore - ETRF extent - approximately 16°W to 33°E and 33°N to 84°N., time-dependent operation +- comment: > + Test that ETRF2000-PL to ETRF2014 is not negatively affected by https://github.com/OSGeo/PROJ/pull/4364 changes (the current actual result is not golden in any way, using ETRF2000 to ETRF2014 could probably make sense) + args: -s ETRF2000-PL -t ETRF2014 --summary + out: | + Candidate operations found: 1 + unknown id, ETRF2000-PL to ETRS89 (1) + ETRS89 to ETRF2014, 0.1 m, Poland - onshore and offshore. +- comment: > + Test WGS 84 (G1150) to WGS 84 (G2296) + args: -s "WGS 84 (G1150)" -t "WGS 84 (G2296)" --summary + out: | + Candidate operations found: 1 + unknown id, Conversion from WGS 84 (G1150) (geog2D) to WGS 84 (G1150) (geocentric) + WGS 84 (G1150) to WGS 84 (G1762) (1) + WGS 84 (G1762) to WGS 84 (G2139) (1) + WGS 84 (G2139) to WGS 84 (G2296) (1) + Conversion from WGS 84 (G2296) (geocentric) to WGS 84 (G2296) (geog2D), 0.04 m, World