Compare commits
82
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a539150fe8 | ||
|
|
cfa19520db | ||
|
|
d1955db87d | ||
|
|
9e1b8ac692 | ||
|
|
5d388a28f1 | ||
|
|
159655ecad | ||
|
|
ea292b0aa3 | ||
|
|
0544964369 | ||
|
|
6cfca76d1b | ||
|
|
d0323a7616 | ||
|
|
642b671254 | ||
|
|
895bca5864 | ||
|
|
3b898c1e1a | ||
|
|
7ade8ef296 | ||
|
|
747f0d5323 | ||
|
|
8bfb760b64 | ||
|
|
f3d79c378c | ||
|
|
3b8377e8b4 | ||
|
|
3e6c789e7d | ||
|
|
e638272843 | ||
|
|
c5170615ab | ||
|
|
aaa90e311d | ||
|
|
becff6864a | ||
|
|
ba700d0248 | ||
|
|
215e6d19b2 | ||
|
|
0fa8862dc0 | ||
|
|
56a39eaf44 | ||
|
|
922185bc9b | ||
|
|
11b63ff6a2 | ||
|
|
1231c55f78 | ||
|
|
cd41b56f99 | ||
|
|
401ca42eeb | ||
|
|
fdeb558166 | ||
|
|
5ed73e514c | ||
|
|
cc6693af26 | ||
|
|
36ff062b83 | ||
|
|
cba8c78a0a | ||
|
|
ced426c8d5 | ||
|
|
037971a375 | ||
|
|
36e3df9b15 | ||
|
|
428e8150be | ||
|
|
08bcb4f928 | ||
|
|
c314ef931c | ||
|
|
252e3d1a56 | ||
|
|
1532683766 | ||
|
|
879b677603 | ||
|
|
0b74725ca6 | ||
|
|
f1963e761b | ||
|
|
5dcd58f16e | ||
|
|
2ade26a374 | ||
|
|
620f7dcb82 | ||
|
|
258080d492 | ||
|
|
a6897da6d9 | ||
|
|
dde3af1ef6 | ||
|
|
db126a6ba1 | ||
|
|
3ec6b92a39 | ||
|
|
028c60f32d | ||
|
|
8fc56a6220 | ||
|
|
d6c5522e9f | ||
|
|
372e2fb062 | ||
|
|
53d8bb5541 | ||
|
|
8de96ede73 | ||
|
|
e291698c47 | ||
|
|
800c06689f | ||
|
|
d4fb7161d5 | ||
|
|
8f7f1c9f25 | ||
|
|
f4eb93c1c4 | ||
|
|
9107ea23a3 | ||
|
|
16cec28e4c | ||
|
|
af0daa6787 | ||
|
|
f74f8a0da6 | ||
|
|
34b8b8fe6f | ||
|
|
83def49fa8 | ||
|
|
b4d1a777b0 | ||
|
|
ae64b7f5f2 | ||
|
|
d700052a76 | ||
|
|
95545fb4f8 | ||
|
|
2f3dcce640 | ||
|
|
cc8970d96e | ||
|
|
6e791c10d5 | ||
|
|
7d3c2425cc | ||
|
|
ea151cd98b |
@@ -291,7 +291,20 @@ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
||||
# Installation
|
||||
################################################################################
|
||||
include(ProjInstallPath)
|
||||
|
||||
# By default GNUInstallDirs will use the upper case project name
|
||||
# for CMAKE_INSTALL_DOCDIR, resulting in something like share/doc/PROJ
|
||||
# instead of share/doc/proj which historically have been the path used
|
||||
# by the project.
|
||||
# Here force the use of a lower case project name and reset after
|
||||
# GNUInstallDirs has done its thing
|
||||
set(PROJECT_NAME_ORIGINAL "${PROJECT_NAME}")
|
||||
string(TOLOWER "${PROJECT_NAME}" PROJECT_NAME)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(PROJECT_NAME "${PROJECT_NAME_ORIGINAL}")
|
||||
|
||||
set(PROJ_DATA_PATH "${CMAKE_INSTALL_FULL_DATADIR}/proj")
|
||||
|
||||
################################################################################
|
||||
|
||||
+17
-5
@@ -90,7 +90,17 @@ else ()
|
||||
set (CMAKE_CROSSCOMPILING_STR "OFF")
|
||||
endif ()
|
||||
|
||||
foreach (PROJECT_VARIANT_NAME ${PROJECT_NAME} ${PROJECT_LEGACY_NAME})
|
||||
# If this is a regular build (PROJECT_SOURCE_DIR == CMAKE_SOURCE_DIR), export legacy files by default
|
||||
# Otherwise, this is embedded in another project, only export PROJ target
|
||||
# cf https://github.com/OSGeo/gdal/issues/5646
|
||||
string(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}" DEFAULT_VAL)
|
||||
option(INSTALL_LEGACY_CMAKE_FILES "Install PROJ4 legacy target CMake files" ${DEFAULT_VAL})
|
||||
|
||||
set(PROJECT_LIST ${PROJECT_NAME})
|
||||
if (INSTALL_LEGACY_CMAKE_FILES)
|
||||
set(PROJECT_LIST "${PROJECT_LIST}" "${PROJECT_LEGACY_NAME}")
|
||||
endif ()
|
||||
foreach (PROJECT_VARIANT_NAME IN LISTS PROJECT_LIST)
|
||||
string (TOLOWER "${PROJECT_VARIANT_NAME}" PROJECT_VARIANT_LOWER)
|
||||
set (CMAKECONFIGSUBDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_VARIANT_LOWER}")
|
||||
# proj-config.cmake for the install tree. It's installed in
|
||||
@@ -117,9 +127,11 @@ foreach (PROJECT_VARIANT_NAME ${PROJECT_NAME} ${PROJECT_LEGACY_NAME})
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
FILE ${PROJECT_NAME_LOWER}-targets.cmake
|
||||
DESTINATION "${CMAKECONFIGSUBDIR}")
|
||||
install(EXPORT targets
|
||||
NAMESPACE ${PROJECT_LEGACY_NAME}::
|
||||
FILE ${PROJECT_LEGACY_LOWER}-targets.cmake
|
||||
DESTINATION "${CMAKECONFIGSUBDIR}")
|
||||
if (INSTALL_LEGACY_CMAKE_FILES)
|
||||
install(EXPORT targets
|
||||
NAMESPACE ${PROJECT_LEGACY_NAME}::
|
||||
FILE ${PROJECT_LEGACY_LOWER}-targets.cmake
|
||||
DESTINATION "${CMAKECONFIGSUBDIR}")
|
||||
endif()
|
||||
endforeach ()
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@ include(CheckFunctionExists)
|
||||
# if C flags have -Werror, temporarily remove these while running some checks
|
||||
string(FIND "${CMAKE_C_FLAGS}" "-Werror" FIND_WERROR)
|
||||
if(FIND_WERROR GREATER_EQUAL 0)
|
||||
string(REPLACE "-Werror" "" _tmp_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
|
||||
# we must be careful about not matching -Werror=something, so let's append
|
||||
# a space at the end of CMAKE_C_FLAGS and match -Werror with a trailing space
|
||||
string(REPLACE "-Werror " " " _tmp_CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ")
|
||||
set(_prev_CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${_tmp_CMAKE_C_FLAGS}")
|
||||
endif()
|
||||
|
||||
@@ -7747,3 +7747,5 @@ INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','20040','SIRGAS-Chile real
|
||||
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','20040','SIRGAS-Chile epoch 2021.00','EPSG');
|
||||
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','20041','SIRGAS-Chile realización 5','EPSG');
|
||||
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','20041','SIRGAS-Chile epoch 2021.00','EPSG');
|
||||
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','20050','NAD83(2011) / Amtrak CS21 (ft)','EPSG');
|
||||
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','20050','ACS21 (ft)','EPSG');
|
||||
|
||||
+2
-2
@@ -73,14 +73,14 @@ FOR EACH ROW BEGIN
|
||||
AND g1.source_crs_code = g2.source_crs_code
|
||||
AND g1.target_crs_auth_name = g2.target_crs_auth_name
|
||||
AND g1.target_crs_code = g2.target_crs_code
|
||||
WHERE g1.auth_name = 'PROJ' AND g1.code NOT LIKE '%_RESTRICTED_TO_VERTCRS%' AND g2.auth_name = 'EPSG')
|
||||
WHERE g1.auth_name = 'PROJ' AND g1.code NOT LIKE '%_RESTRICTED_TO_VERTCRS%' AND g2.auth_name = 'EPSG' AND g2.deprecated = 0)
|
||||
OR EXISTS (SELECT 1 FROM grid_transformation g1
|
||||
JOIN grid_transformation g2
|
||||
ON g1.source_crs_auth_name = g2.target_crs_auth_name
|
||||
AND g1.source_crs_code = g2.target_crs_code
|
||||
AND g1.target_crs_auth_name = g1.source_crs_auth_name
|
||||
AND g1.target_crs_code = g1.source_crs_code
|
||||
WHERE g1.auth_name = 'PROJ' AND g1.code NOT LIKE '%_RESTRICTED_TO_VERTCRS%' AND g2.auth_name = 'EPSG');
|
||||
WHERE g1.auth_name = 'PROJ' AND g1.code NOT LIKE '%_RESTRICTED_TO_VERTCRS%' AND g2.auth_name = 'EPSG' AND g2.deprecated = 0);
|
||||
|
||||
SELECT RAISE(ABORT, 'Arg! there is now a EPSG:102100 object. Hack in createFromUserInput() will no longer work')
|
||||
WHERE EXISTS(SELECT 1 FROM crs_view WHERE auth_name = 'EPSG' AND code = '102100');
|
||||
|
||||
@@ -1836,6 +1836,10 @@ INSERT INTO "conversion" VALUES('EPSG','10131','SPCS83 Alabama East zone (meters
|
||||
INSERT INTO "usage" VALUES('EPSG','11103','conversion','EPSG','10131','EPSG','2154','EPSG','1142');
|
||||
INSERT INTO "conversion" VALUES('EPSG','10132','SPCS83 Alabama West zone (meters)','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',30.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',-87.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',0.999933333,'EPSG','9201','EPSG','8806','False easting',600000.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','11104','conversion','EPSG','10132','EPSG','2155','EPSG','1142');
|
||||
INSERT INTO "conversion" VALUES('EPSG','10147','Brisbane City Survey Grid 2020','Replaces Brisbane City Survey Grid 02 (code 17363) from 2022-07-01.','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',-28.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',153.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',0.99999,'EPSG','9201','EPSG','8806','False easting',150000.0,'EPSG','9001','EPSG','8807','False northing',200000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','18476','conversion','EPSG','10147','EPSG','2990','EPSG','1029');
|
||||
INSERT INTO "conversion" VALUES('EPSG','10148','Amtrak North East Corridor Coordinate System 2021 (International feet)','If using Hotine Oblique Mercator (variant A) method (code 9812), FE = -16,589,516.268572...ft, FN = -9,803,584.307096...ft.','EPSG','9815','Hotine Oblique Mercator (variant B)','EPSG','8811','Latitude of projection centre',40.5,'EPSG','9110','EPSG','8812','Longitude of projection centre',-74.0,'EPSG','9110','EPSG','8813','Azimuth of initial line',58.0,'EPSG','9110','EPSG','8814','Angle from Rectified to Skew Grid',58.0,'EPSG','9110','EPSG','8815','Scale factor on initial line',0.99999,'EPSG','9201','EPSG','8816','Easting at projection centre',1500000.0,'EPSG','9002','EPSG','8817','Northing at projection centre',1500000.0,'EPSG','9002',0);
|
||||
INSERT INTO "usage" VALUES('EPSG','18487','conversion','EPSG','10148','EPSG','4669','EPSG','1141');
|
||||
INSERT INTO "conversion" VALUES('EPSG','10201','Arizona Coordinate System East zone','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',31.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',-110.1,'EPSG','9110','EPSG','8805','Scale factor at natural origin',0.9999,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9003','EPSG','8807','False northing',0.0,'EPSG','9003',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','11105','conversion','EPSG','10201','EPSG','2167','EPSG','1142');
|
||||
INSERT INTO "conversion" VALUES('EPSG','10202','Arizona Coordinate System Central zone','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',31.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',-111.55,'EPSG','9110','EPSG','8805','Scale factor at natural origin',0.9999,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9003','EPSG','8807','False northing',0.0,'EPSG','9003',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
|
||||
@@ -4112,7 +4116,7 @@ INSERT INTO "conversion" VALUES('EPSG','17361','Vicgrid','May also be used to di
|
||||
INSERT INTO "usage" VALUES('EPSG','12537','conversion','EPSG','17361','EPSG','2285','EPSG','1135');
|
||||
INSERT INTO "conversion" VALUES('EPSG','17362','Geoscience Australia Standard National Scale Lambert Projection','Created by Australian Geological Survey Organisation prior to incorporation into Auslig. See also ACRESLC (proj code 4460).','EPSG','9802','Lambert Conic Conformal (2SP)','EPSG','8821','Latitude of false origin',0.0,'EPSG','9102','EPSG','8822','Longitude of false origin',134.0,'EPSG','9102','EPSG','8823','Latitude of 1st standard parallel',-18.0,'EPSG','9102','EPSG','8824','Latitude of 2nd standard parallel',-36.0,'EPSG','9102','EPSG','8826','Easting at false origin',0.0,'EPSG','9001','EPSG','8827','Northing at false origin',0.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','12538','conversion','EPSG','17362','EPSG','2575','EPSG','1236');
|
||||
INSERT INTO "conversion" VALUES('EPSG','17363','Brisbane City Survey Grid 02','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',-28.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',153.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',0.99999,'EPSG','9201','EPSG','8806','False easting',50000.0,'EPSG','9001','EPSG','8807','False northing',100000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
|
||||
INSERT INTO "conversion" VALUES('EPSG','17363','Brisbane City Survey Grid 02','Replaced by BCGS2020 (code 10147) from 2022-07-01.','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',-28.0,'EPSG','9102','EPSG','8802','Longitude of natural origin',153.0,'EPSG','9102','EPSG','8805','Scale factor at natural origin',0.99999,'EPSG','9201','EPSG','8806','False easting',50000.0,'EPSG','9001','EPSG','8807','False northing',100000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','12539','conversion','EPSG','17363','EPSG','2990','EPSG','1029');
|
||||
INSERT INTO "conversion" VALUES('EPSG','17364','New South Wales Lambert','','EPSG','9802','Lambert Conic Conformal (2SP)','EPSG','8821','Latitude of false origin',-33.25,'EPSG','9102','EPSG','8822','Longitude of false origin',147.0,'EPSG','9102','EPSG','8823','Latitude of 1st standard parallel',-30.75,'EPSG','9102','EPSG','8824','Latitude of 2nd standard parallel',-35.75,'EPSG','9102','EPSG','8826','Easting at false origin',9300000.0,'EPSG','9001','EPSG','8827','Northing at false origin',4500000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','12540','conversion','EPSG','17364','EPSG','3139','EPSG','1135');
|
||||
|
||||
@@ -144,6 +144,50 @@ UPDATE grid_transformation SET accuracy = 2.0 WHERE auth_name = 'EPSG' AND code
|
||||
|
||||
UPDATE grid_transformation SET accuracy = 2.0 WHERE auth_name = 'EPSG' AND code = '1462';
|
||||
|
||||
|
||||
-- Create a PROJ copy of EPSG:9123 "NAD83(CSRS) to CGVD28 height (1)" by
|
||||
-- removing the deprecation flag.
|
||||
-- Having a transformation from/to CGVD28 using the "generic" NAD83(CSRS) is much
|
||||
-- more convenient for low accuracy cases like https://github.com/OSGeo/PROJ/issues/3328
|
||||
INSERT INTO grid_transformation SELECT
|
||||
'PROJ' AS auth_name,
|
||||
'EPSG_9123' AS code,
|
||||
name,
|
||||
description || ' Imported from EPSG:9123 with deprecation flag removed by PROJ' AS description,
|
||||
method_auth_name,
|
||||
method_code,
|
||||
method_name,
|
||||
source_crs_auth_name,
|
||||
source_crs_code,
|
||||
target_crs_auth_name,
|
||||
target_crs_code,
|
||||
accuracy,
|
||||
grid_param_auth_name,
|
||||
grid_param_code,
|
||||
grid_param_name,
|
||||
grid_name,
|
||||
grid2_param_auth_name,
|
||||
grid2_param_code,
|
||||
grid2_param_name,
|
||||
grid2_name,
|
||||
interpolation_crs_auth_name,
|
||||
interpolation_crs_code,
|
||||
operation_version,
|
||||
0 AS deprecated
|
||||
FROM grid_transformation WHERE auth_name = 'EPSG' AND code = '9123';
|
||||
|
||||
INSERT INTO usage SELECT
|
||||
'PROJ' AS auth_name,
|
||||
'USAGE_PROJ_EPSG_9123' AS code,
|
||||
object_table_name,
|
||||
'PROJ' AS object_auth_name,
|
||||
'EPSG_9123' AS object_code,
|
||||
extent_auth_name,
|
||||
extent_code,
|
||||
scope_auth_name,
|
||||
scope_code
|
||||
FROM usage WHERE object_table_name = 'grid_transformation' AND object_auth_name = 'EPSG' AND object_code = '9123';
|
||||
|
||||
-- Define the allowed authorities, and their precedence, when researching a
|
||||
-- coordinate operation
|
||||
|
||||
|
||||
+23
-22
@@ -213,7 +213,7 @@ INSERT INTO "extent" VALUES('EPSG','1233','Tokelau','Tokelau - onshore and offsh
|
||||
INSERT INTO "extent" VALUES('EPSG','1234','Tonga','Tonga - onshore and offshore.',-25.68,-14.14,-179.08,-171.28,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1235','Trinidad and Tobago','Trinidad and Tobago - onshore and offshore.',9.83,12.34,-62.09,-57.28,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1236','Tunisia','Tunisia - onshore and offshore.',30.23,38.41,7.49,13.67,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1237','Turkey','Turkey - onshore and offshore.',34.42,43.45,25.62,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1237','Turkey','Türkiye (Turkey) - onshore and offshore.',34.42,43.45,25.62,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1238','Turkmenistan','Turkmenistan - onshore and offshore.',35.14,42.8,51.3,66.68,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1239','Turks and Caicos Islands','Turks and Caicos Islands - onshore and offshore.',20.54,25.07,-72.82,-67.66,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1240','Tuvalu','Tuvalu - onshore and offshore. Funafuti, Nanumanga, Nui, Nanomea, Nurakita, Niutao, Nukufetau, Nukulaelae, and Vaitupu.',-13.24,-4.0,172.73,-176.71,0);
|
||||
@@ -272,7 +272,7 @@ INSERT INTO "extent" VALUES('EPSG','1292','Argentina - Neuquen province','Argent
|
||||
INSERT INTO "extent" VALUES('EPSG','1293','Brazil - Corrego Alegre 1970-1972','Brazil - onshore - west of 54°W and south of 18°S; also south of 15°S between 54°W and 42°W; also east of 42°W.',-33.78,-2.68,-58.16,-34.74,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1294','Portugal - mainland - onshore','Portugal - mainland - onshore.',36.95,42.16,-9.56,-6.19,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1295','Germany - DHDN','Germany - onshore - Baden-Wurtemberg, Bayern, Hessen, Niedersachsen, Nordrhein-Westfalen, Rheinland-Pfalz, Saarland, Schleswig-Holstein. Also former DDR states of Sachsen and Thuringen by transformation.',47.27,55.06,5.87,15.03,1);
|
||||
INSERT INTO "extent" VALUES('EPSG','1296','Europe - ED50 by country','Europe - west: Andorra; Cyprus; Denmark - onshore and offshore; Faroe Islands - onshore; France - offshore; Germany - offshore North Sea; Gibraltar; Greece - offshore; Israel - offshore; Italy including San Marino and Vatican City State; Ireland offshore; Malta; Netherlands - offshore; North Sea; Norway including Svalbard - onshore and offshore; Portugal - mainland - offshore; Spain - onshore; Turkey - onshore and offshore; United Kingdom UKCS offshore east of 6°W including Channel Islands (Guernsey and Jersey). Egypt - Western Desert; Iraq - onshore; Jordan.',25.71,84.73,-16.1,48.61,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1296','Europe - ED50 by country','Europe - west: Andorra; Cyprus; Denmark - onshore and offshore; Faroe Islands - onshore; France - offshore; Germany - offshore North Sea; Gibraltar; Greece - offshore; Israel - offshore; Italy including San Marino and Vatican City State; Ireland offshore; Malta; Netherlands - offshore; North Sea; Norway including Svalbard - onshore and offshore; Portugal - mainland - offshore; Spain - onshore; Türkiye (Turkey) - onshore and offshore; United Kingdom - UKCS offshore east of 6°W including Channel Islands (Guernsey and Jersey). Egypt - Western Desert; Iraq - onshore; Jordan.',25.71,84.73,-16.1,48.61,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1297','Europe - west','Europe - west.',34.88,84.73,-10.56,38.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1298','Europe - ETRF by country','Europe - onshore and offshore: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Cyprus; Czechia; Denmark; Estonia; Faroe Islands; Finland; France; Germany; Gibraltar; Greece; Hungary; Ireland; Italy; Kosovo; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Moldova; Monaco; Montenegro; Netherlands; North Macedonia; Norway including Svalbard and Jan Mayen; Poland; Portugal; Romania; San Marino; Serbia; Slovakia; Slovenia; Spain; Sweden; Switzerland; United Kingdom (UK) including Channel Islands and Isle of Man; Vatican City State.',32.88,84.73,-16.1,40.18,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1299','Europe - EVRF2000','Europe - onshore - Andorra; Austria; Belgium; Bosnia and Herzegovina; Croatia; Czechia; Denmark; Estonia; Finland; France - mainland; Germany; Gibraltar; Hungary; Italy - mainland and Sicily; Latvia; Liechtenstein; Lithuania; Luxembourg; Netherlands; Norway; Poland; Portugal - mainland; Romania; San Marino; Slovakia; Slovenia; Spain - mainland; Sweden; Switzerland; United Kingdom (UK) - Great Britain mainland; Vatican City State.',35.95,71.21,-9.56,31.59,0);
|
||||
@@ -500,13 +500,13 @@ INSERT INTO "extent" VALUES('EPSG','1520','Poland - west of 16.5°E','Poland - o
|
||||
INSERT INTO "extent" VALUES('EPSG','1521','Poland - 16.5°E to 19.5°E','Poland - onshore and offshore between 16°30''E and 19°30''E.',49.39,55.93,16.5,19.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1522','Poland - 19.5°E to 22.5°E','Poland - onshore and offshore between 19°30''E and 22°30''E.',49.09,54.55,19.5,22.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1523','Poland - east of 22.5°E','Poland - east of 22°30''E.',49.0,54.41,22.5,24.15,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1524','Turkey - west of 28.5°E onshore','Turkey west of 28°30''E, onshore.',36.5,42.11,25.62,28.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1525','Turkey - 28.5°E to 31.5°E onshore','Turkey between 28°30''E and 31°30''E, onshore.',36.06,41.46,28.5,31.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1526','Turkey - 31.5°E to 34.5°E onshore','Turkey between 31°30''E and 34°30''E, onshore.',35.97,42.07,31.5,34.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1527','Turkey - 34.5°E to 37.5°E onshore','Turkey between 34°30''E and 37°30''E, onshore.',35.81,42.15,34.5,37.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1528','Turkey - 37.5°E to 40.5°E onshore','Turkey between 37°30''E and 40°30''E, onshore.',36.66,41.19,37.5,40.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1529','Turkey - 40.5°E to 43.5°E onshore','Turkey between 40°30''E and 43°30''E, onshore.',37.02,41.6,40.5,43.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1530','Turkey - east of 43.5°E','Turkey east of 43°30''E.',36.97,41.02,43.5,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1524','Turkey - west of 28.5°E onshore','Türkiye (Turkey) - west of 28°30''E, onshore.',36.5,42.11,25.62,28.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1525','Turkey - 28.5°E to 31.5°E onshore','Türkiye (Turkey) - between 28°30''E and 31°30''E, onshore.',36.06,41.46,28.5,31.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1526','Turkey - 31.5°E to 34.5°E onshore','Türkiye (Turkey) - between 31°30''E and 34°30''E, onshore.',35.97,42.07,31.5,34.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1527','Turkey - 34.5°E to 37.5°E onshore','Türkiye (Turkey) - between 34°30''E and 37°30''E, onshore.',35.81,42.15,34.5,37.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1528','Turkey - 37.5°E to 40.5°E onshore','Türkiye (Turkey) - between 37°30''E and 40°30''E, onshore.',36.66,41.19,37.5,40.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1529','Turkey - 40.5°E to 43.5°E onshore','Türkiye (Turkey) - between 40°30''E and 43°30''E, onshore.',37.02,41.6,40.5,43.5,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1530','Turkey - east of 43.5°E','Türkiye (Turkey) - east of 43°30''E.',36.97,41.02,43.5,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1531','Canada - Maritime Provinces - west of 66°W','Canada - New Brunswick and Nova Scotia - west of 66°W.',43.64,48.07,-69.0,-66.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1532','Canada - Maritime Provinces - east of 66°W','Canada - New Brunswick and Nova Scotia east of 66°W; Prince Edward Island.',43.41,47.98,-66.0,-59.73,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1533','Canada - Prince Edward Island','Canada - Prince Edward Island.',45.9,47.09,-64.49,-61.9,0);
|
||||
@@ -614,10 +614,10 @@ INSERT INTO "extent" VALUES('EPSG','1634','Europe - 0°E to 6°E and ED50 by cou
|
||||
INSERT INTO "extent" VALUES('EPSG','1635','Europe - 6°E to 12°E and ED50 by country','Europe - between 6°E and 12°E - Denmark - onshore and offshore; France - offshore; Germany offshore; Italy - onshore and offshore; Netherlands offshore; Norway including Svalbard - onshore and offshore.',36.53,84.33,5.99,12.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1636','Europe - 12°E to 18°E and ED50 by country','Europe - between 12°E and 18°E onshore and offshore - Denmark (including Bornholm); Italy including San Marino and Vatican City State; Malta; Norway including Svalbard.',34.49,84.42,12.0,18.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1637','Europe - 18°E to 24°E and ED50 by country','Europe - between 18°E and 24°E - Greece - offshore; Italy - onshore and offshore; Norway including Svalbard - onshore and offshore.',33.59,84.54,17.99,24.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1638','Europe - 24°E to 30°E and ED50 by country','Europe - between 24°E and 30°E - Greece - offshore; Norway including Svalbard - onshore and offshore; Turkey - onshore and offshore. Egypt - Western Desert.',25.71,84.73,24.0,30.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1639','Europe - 30°E to 36°E and ED50 by country','Europe - between 30°E and 36°E - Israel - offshore; Jordan; Norway including Svalbard - onshore and offshore; Turkey - onshore and offshore.',29.19,84.7,30.0,36.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1640','Europe - 36°E to 42°E and ED50 by country','Europe - between 36°E and 42°E - Jordan; Norway including Svalbard - offshore; Turkey onshore and offshore.',29.18,79.07,36.0,42.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1641','Europe - 42°E to 48°E and ED50 by country','Europe - between 42°E and 48°E - Turkey.',36.97,41.6,42.0,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1638','Europe - 24°E to 30°E and ED50 by country','Europe - between 24°E and 30°E - Greece - offshore; Norway including Svalbard - onshore and offshore; Türkiye (Turkey) - onshore and offshore. Egypt - Western Desert.',25.71,84.73,24.0,30.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1639','Europe - 30°E to 36°E and ED50 by country','Europe - between 30°E and 36°E - Israel - offshore; Jordan; Norway including Svalbard - onshore and offshore; Türkiye (Turkey) - onshore and offshore.',29.19,84.7,30.0,36.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1640','Europe - 36°E to 42°E and ED50 by country','Europe - between 36°E and 42°E - Jordan; Norway including Svalbard - offshore; Türkiye (Turkey) - onshore and offshore.',29.18,79.07,36.0,42.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1641','Europe - 42°E to 48°E and ED50 by country','Europe - between 42°E and 48°E - Türkiye (Turkey).',36.97,41.6,42.0,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1642','Egypt - east of 33°E onshore','Egypt - east of 33°E - onshore plus offshore Gulf of Suez.',21.97,31.36,33.0,36.95,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1643','Egypt - 29°E to 33°E','Egypt - onshore between 29°E and 33°E, offshore Mediterranean east of 29°E and offshore Gulf of Suez.',21.99,33.82,29.0,34.27,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','1644','Egypt - west of 29°E; north of 28°11''N','Egypt - onshore west of 29°E and north of approximately 28°11''N.',28.18,31.68,24.7,29.0,0);
|
||||
@@ -1044,13 +1044,13 @@ INSERT INTO "extent" VALUES('EPSG','2064','World - N hemisphere - 12°E to 18°E
|
||||
INSERT INTO "extent" VALUES('EPSG','2065','World - S hemisphere - 12°E to 18°E - by country','Between 12°E and 18°E, southern hemisphere between 80°S and equator, onshore and offshore. Angola. Congo. Democratic Republic of the Congo (Zaire). Gabon. Namibia. South Africa.',-80.0,0.0,12.0,18.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2066','World - N hemisphere - 18°E to 24°E - by country','Between 18°E and 24°E, northern hemisphere between equator and 84°N, onshore and offshore. Albania. Belarus. Bosnia and Herzegovina. Bulgaria. Central African Republic. Chad. Croatia. Democratic Republic of the Congo (Zaire). Estonia. Finland. Greece. Hungary. Italy. Kosovo. Latvia. Libya. Lithuania. Montenegro. North Macedonia. Norway, including Svalbard and Bjornoys. Poland. Romania. Russian Federation. Serbia. Slovakia. Sudan. Sweden. Ukraine.',0.0,84.0,18.0,24.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2067','World - S hemisphere - 18°E to 24°E - by country','Between 18°E and 24°E, southern hemisphere between 80°S and equator, onshore and offshore. Angola. Botswana. Democratic Republic of the Congo (Zaire). Namibia. South Africa. Zambia.',-80.0,0.0,18.0,24.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2068','World - N hemisphere - 24°E to 30°E - by country','Between 24°E and 30°E, northern hemisphere between equator and 84°N, onshore and offshore. Belarus. Bulgaria. Central African Republic. Democratic Republic of the Congo (Zaire). Egypt. Estonia. Finland. Greece. Latvia. Lesotho. Libya. Lithuania. Moldova. Norway. Poland. Romania. Russian Federation. Sudan. Svalbard. Turkey. Uganda. Ukraine.',0.0,84.0,24.0,30.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2068','World - N hemisphere - 24°E to 30°E - by country','Between 24°E and 30°E, northern hemisphere between equator and 84°N, onshore and offshore. Belarus. Bulgaria. Central African Republic. Democratic Republic of the Congo (Zaire). Egypt. Estonia. Finland. Greece. Latvia. Lesotho. Libya. Lithuania. Moldova. Norway. Poland. Romania. Russian Federation. Sudan. Svalbard. Türkiye (Turkey). Uganda. Ukraine.',0.0,84.0,24.0,30.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2069','World - S hemisphere - 24°E to 30°E - by country','Between 24°E and 30°E, southern hemisphere between 80°S and equator, onshore and offshore. Botswana. Burundi. Democratic Republic of the Congo (Zaire). Rwanda. South Africa. Tanzania. Uganda. Zambia. Zimbabwe.',-80.0,0.0,24.0,30.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2070','World - N hemisphere - 30°E to 36°E - by country','Between 30°E and 36°E, northern hemisphere between equator and 84°N, onshore and offshore. Belarus. Cyprus. Egypt. Ethiopia. Finland. Israel. Jordan. Kenya. Lebanon. Moldova. Norway. Russian Federation. Saudi Arabia. Sudan. Syria. Turkey. Uganda. Ukraine.',0.0,84.0,30.0,36.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2070','World - N hemisphere - 30°E to 36°E - by country','Between 30°E and 36°E, northern hemisphere between equator and 84°N, onshore and offshore. Belarus. Cyprus. Egypt. Ethiopia. Finland. Israel. Jordan. Kenya. Lebanon. Moldova. Norway. Russian Federation. Saudi Arabia. Sudan. Syria. Türkiye (Turkey). Uganda. Ukraine.',0.0,84.0,30.0,36.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2071','World - S hemisphere - 30°E to 36°E - by country','Between 30°E and 36°E, southern hemisphere between 80°S and equator, onshore and offshore. Burundi. Eswatini (Swaziland). Kenya. Malawi. Mozambique. Rwanda. South Africa. Tanzania. Uganda. Zambia. Zimbabwe.',-80.0,0.0,30.0,36.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2072','World - N hemisphere - 36°E to 42°E - by country','Between 36°E and 42°E, northern hemisphere between equator and 84°N, onshore and offshore. Djibouti. Egypt. Eritrea. Ethiopia. Georgia. Iraq. Jordan. Kenya. Lebanon. Russian Federation. Saudi Arabia. Somalia. Sudan. Syria. Turkey. Ukraine.',0.0,84.0,36.0,42.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2072','World - N hemisphere - 36°E to 42°E - by country','Between 36°E and 42°E, northern hemisphere between equator and 84°N, onshore and offshore. Djibouti. Egypt. Eritrea. Ethiopia. Georgia. Iraq. Jordan. Kenya. Lebanon. Russian Federation. Saudi Arabia. Somalia. Sudan. Syria. Türkiye (Turkey). Ukraine.',0.0,84.0,36.0,42.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2073','World - S hemisphere - 36°E to 42°E - by country','Between 36°E and 42°E, southern hemisphere between 80°S and equator, onshore and offshore. Kenya. Mozambique. Tanzania.',-80.0,0.0,36.0,42.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2074','World - N hemisphere - 42°E to 48°E - by country','Between 42°E and 48°E, northern hemisphere between equator and 84°N, onshore and offshore. Armenia. Azerbaijan. Djibouti. Eritrea. Ethiopia. Georgia. Islamic Republic of Iran. Iraq. kazakhstan. Kuwait. Russian Federation. Saudi Arabia. Somalia. Turkey. Yemen.',0.0,84.0,42.0,48.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2074','World - N hemisphere - 42°E to 48°E - by country','Between 42°E and 48°E, northern hemisphere between equator and 84°N, onshore and offshore. Armenia. Azerbaijan. Djibouti. Eritrea. Ethiopia. Georgia. Islamic Republic of Iran. Iraq. kazakhstan. Kuwait. Russian Federation. Saudi Arabia. Somalia. Türkiye (Turkey). Yemen.',0.0,84.0,42.0,48.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2075','World - S hemisphere - 42°E to 48°E - by country','Between 42°E and 48°E, southern hemisphere between 80°S and equator, onshore and offshore. Madagascar.',-80.0,0.0,42.0,48.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2076','World - N hemisphere - 48°E to 54°E - by country','Between 48°E and 54°E, northern hemisphere between equator and 84°N, onshore and offshore. Azerbaijan. Bahrain. Islamic Republic of Iran. Iraq. Kazakhstan. Kuwait. Oman. Qatar. Russian Federation. Saudi Arabia. Somalia. Turkmenistan. United Arab Emirates. Yemen.',0.0,84.0,48.0,54.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2077','World - S hemisphere - 48°E to 54°E - by country','Between 48°E and 54°E, southern hemisphere between 80°S and equator, onshore and offshore. Madagascar.',-80.0,0.0,48.0,54.0,0);
|
||||
@@ -1806,7 +1806,7 @@ INSERT INTO "extent" VALUES('EPSG','2826','Africa - South Sudan and Sudan - west
|
||||
INSERT INTO "extent" VALUES('EPSG','2827','Africa - South Sudan and Sudan - 24°E to 30°E','South Sudan and Sudan - between 24°E and 30°E.',4.21,22.01,23.99,30.01,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2828','Guadeloupe - St Martin and St Barthelemy - onshore','Guadeloupe - onshore - St Martin and St Barthélemy islands.',17.82,18.17,-63.21,-62.73,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2829','Guadeloupe - Grande-Terre and surrounding islands - onshore','Guadeloupe - onshore - Basse-Terre, Grande-Terre, La Desirade, Marie-Galante, Les Saintes.',15.8,16.55,-61.85,-60.97,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2830','World (by country)','World: Afghanistan, Albania, Algeria, American Samoa, Andorra, Angola, Anguilla, Antarctica, Antigua and Barbuda, Argentina, Armenia, Aruba, Australia, Austria, Azerbaijan, Bahamas, Bahrain, Bangladesh, Barbados, Belgium, Belgium, Belize, Benin, Bermuda, Bhutan, Bolivia, Bonaire, Saint Eustasius and Saba, Bosnia and Herzegovina, Botswana, Bouvet Island, Brazil, British Indian Ocean Territory, British Virgin Islands, Brunei Darussalam, Bulgaria, Burkina Faso, Burundi, Cambodia, Cameroon, Canada, Cape Verde, Cayman Islands, Central African Republic, Chad, Chile, China, Christmas Island, Cocos (Keeling) Islands, Comoros, Congo, Cook Islands, Costa Rica, Côte d''Ivoire (Ivory Coast), Croatia, Cuba, Curacao, Cyprus, Czechia, Denmark, Djibouti, Dominica, Dominican Republic, East Timor, Ecuador, Egypt, El Salvador, Equatorial Guinea, Eritrea, Estonia, Eswatini (Swaziland), Ethiopia, Falkland Islands (Malvinas), Faroe Islands, Fiji, Finland, France, French Guiana, French Polynesia, French Southern Territories, Gabon, Gambia, Georgia, Germany, Ghana, Gibraltar, Greece, Greenland, Grenada, Guadeloupe, Guam, Guatemala, Guinea, Guinea-Bissau, Guyana, Haiti, Heard Island and McDonald Islands, Holy See (Vatican City State), Honduras, China - Hong Kong, Hungary, Iceland, India, Indonesia, Islamic Republic of Iran, Iraq, Ireland, Israel, Italy, Jamaica, Japan, Jordan, Kazakhstan, Kenya, Kiribati, Democratic People''s Republic of Korea (North Korea), Republic of Korea (South Korea), Kosovo, Kuwait, Kyrgyzstan, Lao People''s Democratic Republic (Laos), Latvia, Lebanon, Lesotho, Liberia, Libyan Arab Jamahiriya, Liechtenstein, Lithuania, Luxembourg, China - Macao, Madagascar, Malawi, Malaysia, Maldives, Mali, Malta, Marshall Islands, Martinique, Mauritania, Mauritius, Mayotte, Mexico, Federated States of Micronesia, Monaco, Mongolia, Montenegro, Montserrat, Morocco, Mozambique, Myanmar (Burma), Namibia, Nauru, Nepal, Netherlands, New Caledonia, New Zealand, Nicaragua, Niger, Nigeria, Niue, Norfolk Island, North Macedonia, Northern Mariana Islands, Norway, Oman, Pakistan, Palau, Panama, Papua New Guinea (PNG), Paraguay, Peru, Philippines, Pitcairn, Poland, Portugal, Puerto Rico, Qatar, Reunion, Romania, Russian Federation, Rwanda, St Barthelemy, St Kitts and Nevis, St Helena, Ascension and Tristan da Cunha, St Lucia, St Martin, St Pierre and Miquelon, Saint Vincent and the Grenadines, Samoa, San Marino, Sao Tome and Principe, Saudi Arabia, Senegal, Serbia, Seychelles, Sierra Leone, Singapore, Slovakia (Slovak Republic), Slovenia, St Maarten, Solomon Islands, Somalia, South Africa, South Georgia and the South Sandwich Islands, South Sudan, Spain, Sri Lanka, Sudan, Suriname, Svalbard and Jan Mayen, Sweden, Switzerland, Syrian Arab Republic, Taiwan, Tajikistan, United Republic of Tanzania, Thailand, The Democratic Republic of the Congo (Zaire), Togo, Tokelau, Tonga, Trinidad and Tobago, Tunisia, Turkey, Turkmenistan, Turks and Caicos Islands, Tuvalu, Uganda, Ukraine, United Arab Emirates (UAE), United Kingdom (UK), United States (USA), United States Minor Outlying Islands, Uruguay, Uzbekistan, Vanuatu, Venezuela, Vietnam, US Virgin Islands, Wallis and Futuna, Western Sahara, Yemen, Zambia, Zimbabwe.',-90.0,90.0,-180.0,180.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2830','World (by country)','World: Afghanistan, Albania, Algeria, American Samoa, Andorra, Angola, Anguilla, Antarctica, Antigua and Barbuda, Argentina, Armenia, Aruba, Australia, Austria, Azerbaijan, Bahamas, Bahrain, Bangladesh, Barbados, Belgium, Belgium, Belize, Benin, Bermuda, Bhutan, Bolivia, Bonaire, Saint Eustasius and Saba, Bosnia and Herzegovina, Botswana, Bouvet Island, Brazil, British Indian Ocean Territory, British Virgin Islands, Brunei Darussalam, Bulgaria, Burkina Faso, Burundi, Cambodia, Cameroon, Canada, Cape Verde, Cayman Islands, Central African Republic, Chad, Chile, China, Christmas Island, Cocos (Keeling) Islands, Comoros, Congo, Cook Islands, Costa Rica, Côte d''Ivoire (Ivory Coast), Croatia, Cuba, Curacao, Cyprus, Czechia, Denmark, Djibouti, Dominica, Dominican Republic, East Timor, Ecuador, Egypt, El Salvador, Equatorial Guinea, Eritrea, Estonia, Eswatini (Swaziland), Ethiopia, Falkland Islands (Malvinas), Faroe Islands, Fiji, Finland, France, French Guiana, French Polynesia, French Southern Territories, Gabon, Gambia, Georgia, Germany, Ghana, Gibraltar, Greece, Greenland, Grenada, Guadeloupe, Guam, Guatemala, Guinea, Guinea-Bissau, Guyana, Haiti, Heard Island and McDonald Islands, Holy See (Vatican City State), Honduras, China - Hong Kong, Hungary, Iceland, India, Indonesia, Islamic Republic of Iran, Iraq, Ireland, Israel, Italy, Jamaica, Japan, Jordan, Kazakhstan, Kenya, Kiribati, Democratic People''s Republic of Korea (North Korea), Republic of Korea (South Korea), Kosovo, Kuwait, Kyrgyzstan, Lao People''s Democratic Republic (Laos), Latvia, Lebanon, Lesotho, Liberia, Libyan Arab Jamahiriya, Liechtenstein, Lithuania, Luxembourg, China - Macao, Madagascar, Malawi, Malaysia, Maldives, Mali, Malta, Marshall Islands, Martinique, Mauritania, Mauritius, Mayotte, Mexico, Federated States of Micronesia, Monaco, Mongolia, Montenegro, Montserrat, Morocco, Mozambique, Myanmar (Burma), Namibia, Nauru, Nepal, Netherlands, New Caledonia, New Zealand, Nicaragua, Niger, Nigeria, Niue, Norfolk Island, North Macedonia, Northern Mariana Islands, Norway, Oman, Pakistan, Palau, Panama, Papua New Guinea (PNG), Paraguay, Peru, Philippines, Pitcairn, Poland, Portugal, Puerto Rico, Qatar, Reunion, Romania, Russian Federation, Rwanda, St Barthelemy, St Kitts and Nevis, St Helena, Ascension and Tristan da Cunha, St Lucia, St Martin, St Pierre and Miquelon, Saint Vincent and the Grenadines, Samoa, San Marino, Sao Tome and Principe, Saudi Arabia, Senegal, Serbia, Seychelles, Sierra Leone, Singapore, Slovakia (Slovak Republic), Slovenia, St Maarten, Solomon Islands, Somalia, South Africa, South Georgia and the South Sandwich Islands, South Sudan, Spain, Sri Lanka, Sudan, Suriname, Svalbard and Jan Mayen, Sweden, Switzerland, Syrian Arab Republic, Taiwan, Tajikistan, United Republic of Tanzania, Thailand, The Democratic Republic of the Congo (Zaire), Togo, Tokelau, Tonga, Trinidad and Tobago, Tunisia, Türkiye (Turkey), Turkmenistan, Turks and Caicos Islands, Tuvalu, Uganda, Ukraine, United Arab Emirates (UAE), United Kingdom (UK), United States (USA), United States Minor Outlying Islands, Uruguay, Uzbekistan, Vanuatu, Venezuela, Vietnam, US Virgin Islands, Wallis and Futuna, Western Sahara, Yemen, Zambia, Zimbabwe.',-90.0,90.0,-180.0,180.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2831','Canada - Atlantic offshore','Canada - offshore Newfoundland and Labrador, New Brunswick and Nova Scotia - west of 44°W and north of 40°N.',40.0,64.21,-67.75,-43.99,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2832','Canada - British Columbia','Canada - British Columbia.',48.25,60.01,-139.04,-114.08,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2833','Sweden - 12 00','Sweden - communes west of approximately 12°45''E and south of approximately 60°N. See information source for map.',56.74,60.13,10.93,13.11,0);
|
||||
@@ -1857,7 +1857,7 @@ INSERT INTO "extent" VALUES('EPSG','2877','Slovenia - Slovenska Bistrica','Slove
|
||||
INSERT INTO "extent" VALUES('EPSG','2878','Slovenia - Slovenske Gorice','Slovenia - Slovenske Gorice (the Slovene Humpback) with the broad region of Ormoz.',46.29,46.76,15.9,16.3,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2879','Germany - offshore North Sea','Germany - offshore North Sea.',53.6,55.92,3.34,8.88,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2880','Antarctica - Australian sector north of 80°S','Antarctica - north of 80°S and between 45°E and 136°E and between 142°E and 160°E - Australian sector north of 80°S.',-80.0,-60.0,45.0,160.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2881','Europe - LCC & LAEA','Europe - European Union (EU) countries and candidates. Europe - onshore and offshore: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Cyprus; Czechia; Denmark; Estonia; Faroe Islands; Finland; France; Germany; Gibraltar; Greece; Hungary; Iceland; Ireland; Italy; Kosovo; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Monaco; Montenegro; Netherlands; North Macedonia; Norway including Svalbard and Jan Mayen; Poland; Portugal including Madeira and Azores; Romania; San Marino; Serbia; Slovakia; Slovenia; Spain including Canary Islands; Sweden; Switzerland; Turkey; United Kingdom (UK) including Channel Islands and Isle of Man; Vatican City State.',24.6,84.73,-35.58,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2881','Europe - LCC & LAEA','Europe - European Union (EU) countries and candidates. Europe - onshore and offshore: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Cyprus; Czechia; Denmark; Estonia; Faroe Islands; Finland; France; Germany; Gibraltar; Greece; Hungary; Iceland; Ireland; Italy; Kosovo; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Monaco; Montenegro; Netherlands; North Macedonia; Norway including Svalbard and Jan Mayen; Poland; Portugal including Madeira and Azores; Romania; San Marino; Serbia; Slovakia; Slovenia; Spain including Canary Islands; Sweden; Switzerland; Türkiye (Turkey); United Kingdom (UK) including Channel Islands and Isle of Man; Vatican City State.',24.6,84.73,-35.58,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2882','Italy - Adriatic - North Ancona','Italy - offshore - Adriatic Sea - North Ancona.',43.62,45.73,12.22,13.96,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2883','Italy - Adriatic - South Ancona / North Gargano','Italy - offshore - Adriatic Sea - South Ancona and North Gargano.',41.95,44.04,13.61,16.14,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2884','Italy - Adriatic - South Gargano','Italy - offshore - Adriatic Sea - South Gargano.',40.72,42.28,15.95,18.63,0);
|
||||
@@ -1872,7 +1872,7 @@ INSERT INTO "extent" VALUES('EPSG','2892','Guadeloupe - Grande-Terre and Basse-T
|
||||
INSERT INTO "extent" VALUES('EPSG','2893','Guadeloupe - La Desirade - onshore','Guadeloupe - onshore - La Desirade.',16.26,16.38,-61.13,-60.97,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2894','Guadeloupe - Marie-Galante - onshore','Guadeloupe - onshore - Marie-Galante.',15.8,16.05,-61.39,-61.13,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2895','Guadeloupe - Les Saintes - onshore','Guadeloupe - onshore - Les Saintes.',15.8,15.94,-61.68,-61.52,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2896','Asia - Middle East - Israel, Palestine Territory, Turkey - offshore','Israel and Palestine Territory - offshore Mediterranean Sea; Turkey - offshore Black Sea.',31.35,43.45,28.03,41.47,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2896','Asia - Middle East - Israel, Palestine Territory, Turkey - offshore','Israel and Palestine Territory - offshore Mediterranean Sea; Türkiye (Turkey) - offshore Black Sea.',31.35,43.45,28.03,41.47,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2897','Asia - Middle East - Israel and Palestine Territory offshore','Israel and Palestine Territory - offshore Mediterranean Sea.',31.33,33.1,33.5,35.1,1);
|
||||
INSERT INTO "extent" VALUES('EPSG','2898','Germany - Berlin','Germany - Berlin.',52.33,52.65,13.09,13.76,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2899','Australia - 126°E to 132°E, 8°S to 12°S (SC52) onshore','Australia - onshore mainland between 8°S and 12°S and 126°E and 132°E.',-12.0,-11.07,131.02,132.0,0);
|
||||
@@ -1966,7 +1966,7 @@ INSERT INTO "extent" VALUES('EPSG','2986','Australia - SA','Australia - South Au
|
||||
INSERT INTO "extent" VALUES('EPSG','2987','Libya - Amal','Libya - Amal field.',29.1,29.8,20.8,21.4,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2988','Channel Islands - Jersey, Les Ecrehos and Les Minquiers','Channel Islands - Jersey, Les Ecrehos and Les Minquiers - onshore and offshore.',48.77,49.44,-2.72,-1.81,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2989','Channel Islands - Guernsey, Alderney, Sark','Channel Islands - Guernsey, Alderney, Sark, Herm, Brecqhou, Jethou, Lihou - onshore and offshore.',49.11,50.16,-3.73,-2.02,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2990','Australia - Brisbane','Australia - Brisbane area. Local authorities in south-east Queensland: Gold Coast, Logan, Beaudesert, Redcliffe, Redlands, Pine Rivers, Caboolture, Caloundra, Maroochy, Noosa, Maryborough; local authorities in north-east New South Wales: Tweed, Byron, Lismore, Ballina and Richmond Valley.',-29.88,-24.64,151.19,153.69,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2990','Australia - Brisbane','Australia - Brisbane and surrounding area. Also applicable in other local authorities in south-east Queensland (Gold Coast, Logan, Ipswich, Scenic Rim, Redland, Moreton Bay, Sunshine Coast, Noosa, eastern part of Gympie, eastern part of Fraser Coast) and north-east New South Wales (Tweed, Byron, Lismore, Kyogle, Ballina and Richmond Valley).',-29.36,-24.64,152.37,153.69,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2991','Antarctica - 60°S to 64°S, 72°W to 60°W (SP19-20)','Antarctica - 60°S to 64°S and 72°W to 60°W.',-64.0,-60.0,-72.0,-60.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2992','Antarctica - 60°S to 64°S, 60°W to 48°W (SP21-22)','Antarctica - 60°S to 64°S and 60°W to 48°W.',-64.0,-60.0,-60.0,-48.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','2993','Antarctica - 60°S to 64°S, 48°W to 36°W (SP23-24)','Antarctica - 60°S to 64°S and 48°W to 36°W.',-64.0,-60.0,-48.0,-36.0,0);
|
||||
@@ -2298,7 +2298,7 @@ INSERT INTO "extent" VALUES('EPSG','3318','East Timor - onshore','Timor-Leste (E
|
||||
INSERT INTO "extent" VALUES('EPSG','3319','Togo - onshore','Togo - onshore.',6.05,11.14,-0.15,1.8,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','3320','Tokelau - onshore','Tokelau - onshore.',-9.27,-9.12,-171.92,-171.79,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','3321','Tonga - onshore','Tonga - onshore.',-21.32,-18.51,-175.42,-173.85,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','3322','Turkey - onshore','Turkey - onshore.',35.81,42.15,25.62,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','3322','Turkey - onshore','Türkiye (Turkey) - onshore.',35.81,42.15,25.62,44.83,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','3323','Turks and Caicos Islands - onshore','Turks and Caicos Islands - onshore.',21.38,22.01,-72.09,-71.07,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','3324','Ukraine - onshore','Ukraine - onshore.',44.32,52.38,22.15,40.18,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','3325','UAE - onshore','United Arab Emirates (UAE) - onshore. Abu Dhabi, Dubai, Sharjah, Umm al Qaywayn, Al Fujairah, Ras al Khaymah.',22.63,26.1,51.56,56.44,0);
|
||||
@@ -3643,3 +3643,4 @@ INSERT INTO "extent" VALUES('EPSG','4664','UK - Inverness to Thurso','United Kin
|
||||
INSERT INTO "extent" VALUES('EPSG','4665','UK - Motherwell to Inverness','United Kingdom (UK) - on or related to the Scottish central mainline rail route from Motherwell through Perth and Pitlochry to Inverness.',55.7,57.55,-4.4,-3.3,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','4666','UK - Manchester, Wigan and Chester','United Kingdom (UK) - on or related to the rail route from Manchester via Wigan and Liverpool to Chester.',53.09,53.65,-3.15,-2.1,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','4667','Chile - west of 108°W','Chile - Easter Island onshore and offshore - west of 108°W.',-30.54,-23.72,-113.21,-108.0,0);
|
||||
INSERT INTO "extent" VALUES('EPSG','4669','USA - Amtrak NE corridor','United States (USA) - parts of Connecticut, Delaware, District of Columbia, Maryland, Massachusetts, New Jersey, New York, Pennsylvania, Rhode Island and Virginia on or related to the Amtrak northeast corridor rail route from Boston to Washington DC via New York and Philadelphia.',38.64,42.74,-78.51,-70.48,0);
|
||||
|
||||
@@ -1597,7 +1597,7 @@ INSERT INTO "usage" VALUES('EPSG','5429','geodetic_crs','EPSG','7685','EPSG','11
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','7686','Kyrg-06',NULL,'geographic 2D','EPSG','6422','EPSG','1160',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','5430','geodetic_crs','EPSG','7686','EPSG','1137','EPSG','1183');
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','7789','ITRF2014',NULL,'geocentric','EPSG','6500','EPSG','1165',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','5473','geodetic_crs','EPSG','7789','EPSG','2830','EPSG','1027');
|
||||
INSERT INTO "usage" VALUES('EPSG','5473','geodetic_crs','EPSG','7789','EPSG','1262','EPSG','1027');
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','7796','BGS2005',NULL,'geocentric','EPSG','6500','EPSG','1167',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','5479','geodetic_crs','EPSG','7796','EPSG','1056','EPSG','1027');
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','7797','BGS2005',NULL,'geographic 3D','EPSG','6423','EPSG','1167',NULL,0);
|
||||
@@ -2131,7 +2131,7 @@ INSERT INTO "usage" VALUES('EPSG','15341','geodetic_crs','EPSG','9739','EPSG','4
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','9753','WGS 84 (G2139)',NULL,'geocentric','EPSG','6500','EPSG','1309',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','16657','geodetic_crs','EPSG','9753','EPSG','1262','EPSG','1176');
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','9754','WGS 84 (G2139)',NULL,'geographic 3D','EPSG','6423','EPSG','1309',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','16853','geodetic_crs','EPSG','9754','EPSG','1262','EPSG','1176');
|
||||
INSERT INTO "usage" VALUES('EPSG','16853','geodetic_crs','EPSG','9754','EPSG','2830','EPSG','1176');
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','9755','WGS 84 (G2139)',NULL,'geographic 2D','EPSG','6422','EPSG','1309',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','16852','geodetic_crs','EPSG','9755','EPSG','1262','EPSG','1176');
|
||||
INSERT INTO "geodetic_crs" VALUES('EPSG','9758','ECML14_NB-IRF',NULL,'geographic 2D','EPSG','6422','EPSG','1310',NULL,0);
|
||||
|
||||
@@ -47,7 +47,8 @@ VALUES
|
||||
('CGG2013an83.byn','ca_nrc_CGG2013an83.tif','CGG2013an83.gtx','GTiff','geoid_like',0,NULL,'https://cdn.proj.org/ca_nrc_CGG2013an83.tif',1,1,NULL),
|
||||
('CGG2013i83.byn','ca_nrc_CGG2013i08.tif','CGG2013i08.gtx','GTiff','geoid_like',0,NULL,'https://cdn.proj.org/ca_nrc_CGG2013i08.tif',1,1,NULL),
|
||||
('CGG2013n83.byn','ca_nrc_CGG2013n83.tif','CGG2013n83.gtx','GTiff','geoid_like',0,NULL,'https://cdn.proj.org/ca_nrc_CGG2013n83.tif',1,1,NULL),
|
||||
('HT2_0.byn','ca_nrc_HT2_2010v70.tif','HT2_2010v70.gtx','GTiff','geoid_like',0,NULL,'https://cdn.proj.org/ca_nrc_HT2_2010v70.tif',1,1,NULL), -- deprecated name
|
||||
('HT2_0.byn','ca_nrc_HT2_2010v70.tif','HT2_2010v70.gtx','GTiff','geoid_like',0,NULL,'https://cdn.proj.org/ca_nrc_HT2_2010v70.tif',1,1,NULL), -- deprecated name. dubious mapping !!!
|
||||
('HT2_1997.byn','ca_nrc_HT2_2010v70.tif',NULL,'GTiff','geoid_like',0,NULL,'https://cdn.proj.org/ca_nrc_HT2_2010v70.tif',1,1,NULL), -- dubious mapping !!!
|
||||
('HT2_2010v70.byn','ca_nrc_HT2_2010v70.tif','HT2_2010v70.gtx','GTiff','geoid_like',0,NULL,'https://cdn.proj.org/ca_nrc_HT2_2010v70.tif',1,1,NULL),
|
||||
('HT2_2010v70_CGG2013a.byn','ca_nrc_HT2_2010v70_CGG2013a.tif',NULL,'GTiff','vgridshift',0,NULL,'https://cdn.proj.org/ca_nrc_HT2_2010v70_CGG2013a.tif',1,1,NULL),
|
||||
-- the PROJ grid is the reverse way of the EPSG one
|
||||
|
||||
@@ -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.074');
|
||||
INSERT INTO "metadata" VALUES('EPSG.DATE', '2022-08-01');
|
||||
INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.076');
|
||||
INSERT INTO "metadata" VALUES('EPSG.DATE', '2022-08-31');
|
||||
|
||||
-- The value of ${PROJ_VERSION} is substituted at build time by the actual
|
||||
-- value.
|
||||
|
||||
@@ -7510,10 +7510,14 @@ INSERT INTO "projected_crs" VALUES('EPSG','20032','Pulkovo 1995 / Gauss-Kruger z
|
||||
INSERT INTO "usage" VALUES('EPSG','6205','projected_crs','EPSG','20032','EPSG','1791','EPSG','1211');
|
||||
INSERT INTO "projected_crs" VALUES('EPSG','20042','SIRGAS-Chile 2021 / UTM zone 12S',NULL,'EPSG','4400','EPSG','20041','EPSG','16112',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','18383','projected_crs','EPSG','20042','EPSG','4667','EPSG','1142');
|
||||
INSERT INTO "projected_crs" VALUES('EPSG','20047','GDA2020 / BCSG2020',NULL,'EPSG','4400','EPSG','7844','EPSG','10147',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','18477','projected_crs','EPSG','20047','EPSG','2990','EPSG','1029');
|
||||
INSERT INTO "projected_crs" VALUES('EPSG','20048','SIRGAS-Chile 2021 / UTM zone 18S',NULL,'EPSG','4400','EPSG','20041','EPSG','16118',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','18384','projected_crs','EPSG','20048','EPSG','3829','EPSG','1142');
|
||||
INSERT INTO "projected_crs" VALUES('EPSG','20049','SIRGAS-Chile 2021 / UTM zone 19S',NULL,'EPSG','4400','EPSG','20041','EPSG','16119',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','18385','projected_crs','EPSG','20049','EPSG','3811','EPSG','1142');
|
||||
INSERT INTO "projected_crs" VALUES('EPSG','20050','NAD83(2011) / Amtrak NECCS21 (ft)',NULL,'EPSG','4495','EPSG','6318','EPSG','10148',NULL,0);
|
||||
INSERT INTO "usage" VALUES('EPSG','18480','projected_crs','EPSG','20050','EPSG','4669','EPSG','1141');
|
||||
INSERT INTO "projected_crs" VALUES('EPSG','20064','Pulkovo 1995 / Gauss-Kruger 4N',NULL,'EPSG','4530','EPSG','4200','EPSG','16304',NULL,1);
|
||||
INSERT INTO "usage" VALUES('EPSG','6206','projected_crs','EPSG','20064','EPSG','1763','EPSG','1209');
|
||||
INSERT INTO "projected_crs" VALUES('EPSG','20065','Pulkovo 1995 / Gauss-Kruger 5N',NULL,'EPSG','4530','EPSG','4200','EPSG','16305',NULL,1);
|
||||
|
||||
@@ -149,7 +149,7 @@ Examples
|
||||
|
||||
projsync --all
|
||||
|
||||
2. Download resource files covering specified point and attributing to an agency
|
||||
2. Download resource files covering specified point and attributed to an agency
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
|
||||
@@ -17,16 +17,18 @@ contributor the community is always very welcoming.
|
||||
code_of_conduct
|
||||
rfc/index
|
||||
|
||||
Conference
|
||||
----------
|
||||
.. Below section commented. to be refreshed for FOSS4G 2023
|
||||
|
||||
.. image:: ../../images/foss4g2021.jpg
|
||||
:alt: FOSS4G 2021
|
||||
:target: https://2021.foss4g.org/
|
||||
Conference
|
||||
----------
|
||||
|
||||
`FOSS4G 2021 <https://2021.foss4g.org/>`_ is the leading annual conference for
|
||||
free and open source geospatial software. It will include presentations related
|
||||
to PROJ, and some of the PROJ development community will be attending. It is the
|
||||
event for those interested in PROJ, other FOSS geospatial technologies and the
|
||||
community around them. The conference will due to COVID-19 be held in a virtual
|
||||
setting September 27th - October 2nd, 2021.
|
||||
.. image:: ../../images/foss4g2021.jpg
|
||||
:alt: FOSS4G 2021
|
||||
:target: https://2021.foss4g.org/
|
||||
|
||||
`FOSS4G 2021 <https://2021.foss4g.org/>`_ is the leading annual conference for
|
||||
free and open source geospatial software. It will include presentations related
|
||||
to PROJ, and some of the PROJ development community will be attending. It is the
|
||||
event for those interested in PROJ, other FOSS geospatial technologies and the
|
||||
community around them. The conference will due to COVID-19 be held in a virtual
|
||||
setting September 27th - October 2nd, 2021.
|
||||
|
||||
+1
-1
@@ -206,7 +206,7 @@ html_context = {
|
||||
'github_user': 'OSGeo',
|
||||
'github_repo': 'PROJ',
|
||||
# TODO: edit when switching active branch
|
||||
'github_version': '9.0/docs/source/',
|
||||
'github_version': '9.1/docs/source/',
|
||||
}
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
|
||||
@@ -11,6 +11,12 @@ Python
|
||||
`pyproj <https://pypi.python.org/pypi/pyproj>`_:
|
||||
Python interface (wrapper for PROJ)
|
||||
|
||||
Java
|
||||
====
|
||||
|
||||
`PROJ-JNI <https://github.com/OSGeo/PROJ-JNI>`_:
|
||||
Java Native Interface for PROJ
|
||||
|
||||
Ruby
|
||||
=======
|
||||
|
||||
|
||||
@@ -201,8 +201,8 @@ paragraph for more details.
|
||||
- ALLOW_BALLPARK=YES/NO: can be set to NO to disallow the use of
|
||||
:term:`Ballpark transformation` in the candidate coordinate operations.
|
||||
|
||||
- FORCE_OVER=YES/NO: can be set to YES to force the +over flag on the transformation
|
||||
returned by this function.
|
||||
- FORCE_OVER=YES/NO: can be set to YES to force the ``+over`` flag on the transformation
|
||||
returned by this function. See :ref:`longitude_wrapping`
|
||||
|
||||
.. doxygenfunction:: proj_normalize_for_visualization
|
||||
:project: doxygen_api
|
||||
|
||||
@@ -13,8 +13,8 @@ distribution of the source code and various resource file archives. See
|
||||
Current Release
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
* **2022-06-15** `proj-9.0.1.tar.gz`_ (`md5`_)
|
||||
* **2022-06-15** `proj-data-1.10.tar.gz`_
|
||||
* **2022-09-01** `proj-9.1.0.tar.gz`_ (`md5`_)
|
||||
* **2022-09-01** `proj-data-1.11.tar.gz`_
|
||||
* **PDF Manual** `proj.pdf`_
|
||||
|
||||
.. note::
|
||||
@@ -28,6 +28,7 @@ Current Release
|
||||
Past Releases
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
* **2022-06-15** `proj-9.0.1.tar.gz`_
|
||||
* **2022-03-01** `proj-9.0.0.tar.gz`_
|
||||
* **2022-01-01** `proj-8.2.1.tar.gz`_
|
||||
* **2021-11-01** `proj-8.2.0.tar.gz`_
|
||||
@@ -57,6 +58,7 @@ Past Releases
|
||||
* **2015-09-13** `proj-4.9.2.tar.gz`_
|
||||
* **2015-03-04** `proj-4.9.1.tar.gz`_
|
||||
|
||||
* **2022-06-15** `proj-data-1.10.tar.gz`_
|
||||
* **2022-03-01** `proj-data-1.9.tar.gz`_
|
||||
* **2021-11-01** `proj-data-1.8.tar.gz`_
|
||||
* **2021-07-01** `proj-data-1.7.tar.gz`_
|
||||
@@ -88,8 +90,9 @@ Past Releases
|
||||
* **2018-03-01** `proj-datumgrid-oceania-1.1.zip`_
|
||||
* **2018-03-01** `proj-datumgrid-oceania-1.0.zip`_
|
||||
|
||||
.. _`proj-9.1.0.tar.gz`: https://download.osgeo.org/proj/proj-9.1.0.tar.gz
|
||||
.. _`md5`: https://download.osgeo.org/proj/proj-9.1.0.tar.gz.md5
|
||||
.. _`proj-9.0.1.tar.gz`: https://download.osgeo.org/proj/proj-9.0.1.tar.gz
|
||||
.. _`md5`: https://download.osgeo.org/proj/proj-9.0.1.tar.gz.md5
|
||||
.. _`proj-9.0.0.tar.gz`: https://download.osgeo.org/proj/proj-9.0.0.tar.gz
|
||||
.. _`proj-8.2.1.tar.gz`: https://download.osgeo.org/proj/proj-8.2.1.tar.gz
|
||||
.. _`proj-8.2.0.tar.gz`: https://download.osgeo.org/proj/proj-8.2.0.tar.gz
|
||||
@@ -120,6 +123,7 @@ Past Releases
|
||||
.. _`proj-4.9.2.tar.gz`: https://download.osgeo.org/proj/proj-4.9.2.tar.gz
|
||||
.. _`proj-4.9.3.tar.gz`: https://download.osgeo.org/proj/proj-4.9.3.tar.gz
|
||||
|
||||
.. _`proj-data-1.11.tar.gz`: https://download.osgeo.org/proj/proj-data-1.11.tar.gz
|
||||
.. _`proj-data-1.10.tar.gz`: https://download.osgeo.org/proj/proj-data-1.10.tar.gz
|
||||
.. _`proj-data-1.9.tar.gz`: https://download.osgeo.org/proj/proj-data-1.9.tar.gz
|
||||
.. _`proj-data-1.8.tar.gz`: https://download.osgeo.org/proj/proj-data-1.8.tar.gz
|
||||
|
||||
@@ -194,3 +194,14 @@ call the software PROJ.
|
||||
Use of name PROJ.4 is now strictly reserved for describing legacy behavior
|
||||
of the software, e.g. "PROJ.4 strings" as seen in :program:`projinfo`
|
||||
output.
|
||||
|
||||
|
||||
Who uses PROJ ?
|
||||
---------------
|
||||
|
||||
See :ref:`users`
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
users
|
||||
|
||||
@@ -19,6 +19,7 @@ PROJ
|
||||
development/index
|
||||
specifications/index
|
||||
community/index
|
||||
tutorials/index
|
||||
faq
|
||||
glossary
|
||||
zreferences
|
||||
|
||||
@@ -3,6 +3,99 @@
|
||||
News
|
||||
###############################################################################
|
||||
|
||||
9.1.0 Release Notes
|
||||
+++++++++++++++++++
|
||||
*September 1st 2022*
|
||||
|
||||
Updates
|
||||
--------
|
||||
|
||||
* Database:
|
||||
|
||||
* Database: update to EPSG v10.074 (`#3273 <https://github.com/OSGeo/PROJ/issues/3273>`_)
|
||||
|
||||
* Update ESRI objects to version 3.0.0 (`#3257 <https://github.com/OSGeo/PROJ/issues/3257>`_)
|
||||
|
||||
* Generate null transformation between geodetic/vertical datum ensemble and its members (`#3266 <https://github.com/OSGeo/PROJ/issues/3266>`_)
|
||||
|
||||
* Add ``fk delete cascade`` to database tables for improved customizability of the database (`#3237 <https://github.com/OSGeo/PROJ/issues/3237>`_)
|
||||
|
||||
* Add Svalbard geoid grid ``no_kv_arcgp-2006-sk`` to grid alternatives (`#3292 <https://github.com/OSGeo/PROJ/issues/3292>`_)
|
||||
|
||||
* Added French grid ``fr_ign_RAF20`` to grid alternatives (`#3228 <https://github.com/OSGeo/PROJ/issues/3228>`_)
|
||||
|
||||
* WKT & PROJJSON:
|
||||
|
||||
* WKT2 parser: allow unit-less PARAMETER for coordinate operations (`#3271 <https://github.com/OSGeo/PROJ/issues/3271>`_)
|
||||
|
||||
* WKT and PROJJSON adjustments (`#3234 <https://github.com/OSGeo/PROJ/issues/3234>`_)
|
||||
|
||||
* Bump PROJJSON to v0.5 (`#3216 <https://github.com/OSGeo/PROJ/issues/3216>`_)
|
||||
|
||||
* Change order of horizontal and vertical operations when dealing with WKT1 / PROJ4 compound CRS (`#3127 <https://github.com/OSGeo/PROJ/issues/3127>`_)
|
||||
|
||||
* Coordinate Operations:
|
||||
|
||||
* Implement Vertical Offset and slope transformation method (`#3200 <https://github.com/OSGeo/PROJ/issues/3200>`_)
|
||||
|
||||
* Add Interrupted Mollweide (land and ocean view) projections (`#3139 <https://github.com/OSGeo/PROJ/issues/3139>`_)
|
||||
|
||||
* Add invertible Horner polynomials (`#3133 <https://github.com/OSGeo/PROJ/issues/3133>`_)
|
||||
|
||||
* Optimizations:
|
||||
|
||||
* NTv2 and GTX grid readers: add a cache of lines to speed-up (`#3241 <https://github.com/OSGeo/PROJ/issues/3241>`_)
|
||||
|
||||
* :cpp:func:`IComparable::isEquivalentTo()` optimizations (`#3233 <https://github.com/OSGeo/PROJ/issues/3233>`_)
|
||||
|
||||
+ Various Updates:
|
||||
|
||||
* :cpp:func:`createOperations()` / :c:func:`proj_trans()`: better take into account area of interest name / do not only keep first returned coordinate operation (`#3282 <https://github.com/OSGeo/PROJ/issues/3282>`_)
|
||||
|
||||
* :cpp:func:`createOperations()`: take into account axis unit and inversion of target DerivedProjectedCRS (`#3281 <https://github.com/OSGeo/PROJ/issues/3281>`_)
|
||||
|
||||
* Allow a Compound CRS with derived projected (`#3283 <https://github.com/OSGeo/PROJ/issues/3283>`_)
|
||||
|
||||
* Make "Vertical Offset and Slope" method usable as a deriving conversion of a DerivedVerticalCRS (`#3270 <https://github.com/OSGeo/PROJ/issues/3270>`_)
|
||||
|
||||
* PROJ pipeline generator: recognize opposite Helmert transformations using a different convention (`#3265 <https://github.com/OSGeo/PROJ/issues/3265>`_)
|
||||
|
||||
* :cpp:func:`createOperations()`: prefer simpler pipelines / affects WGS 84 to GDA94/GDA2020 (`#3248 <https://github.com/OSGeo/PROJ/issues/3248>`_)
|
||||
|
||||
* Make it possible to determine which grid files were actually used during a transformation (`#3180 <https://github.com/OSGeo/PROJ/issues/3180>`_)
|
||||
|
||||
* Transformation: no longer do vertical trasnformation when doing compound CRS to 2D CRS / add --3d to cs2cs (`#3119 <https://github.com/OSGeo/PROJ/issues/3119>`_)
|
||||
|
||||
* Deprecate PROJ4 CMake name (`#3094 <https://github.com/OSGeo/PROJ/issues/3094>`_)
|
||||
|
||||
* Use GNUInstallDirs for CMake install locations (`#3100 <https://github.com/OSGeo/PROJ/issues/3100>`_)
|
||||
|
||||
* Introduce ``PROJ_DATA``` environment variable to deprecate ``PROJ_LIB`` (`#3253 <https://github.com/OSGeo/PROJ/issues/3253>`_)
|
||||
|
||||
|
||||
Bug fixes
|
||||
----------
|
||||
|
||||
* :program:`projinfo`: fix crash on --list-crs when proj.db cannot be opened (`#3290 <https://github.com/OSGeo/PROJ/issues/3290>`_)
|
||||
|
||||
* :cpp:func:`getCRSInfoList()`: fix retrieval of projected_crs given by text_definition only (`#3289 <https://github.com/OSGeo/PROJ/issues/3289>`_)
|
||||
|
||||
* WKT parser: fix issue when parsing some WKT1 with Hotine_Oblique_Mercator_Azimuth_Center and ignoring rectified_grid_angle (`#3280 <https://github.com/OSGeo/PROJ/issues/3280>`_)
|
||||
|
||||
* WKT1 import: better deal when the angular unit of the GEOGCS[] of the PROJCS[] doesn't match the one from the database (`#3274 <https://github.com/OSGeo/PROJ/issues/3274>`_)
|
||||
|
||||
* :cpp:func:`createOperations()`: avoid potential infinite recursions (`#3264 <https://github.com/OSGeo/PROJ/issues/3264>`_)
|
||||
|
||||
* WKT ESRI: fix related to projected CRS export and add support for geographic 3D CRS with LINUNIT node (`#3256 <https://github.com/OSGeo/PROJ/issues/3256>`_)
|
||||
|
||||
* :c:func:`proj_grid_info()`: make it work again with remote grids (`#3239 <https://github.com/OSGeo/PROJ/issues/3239>`_)
|
||||
|
||||
* :cpp:func:`createOperations()`: fix projected CRS with non-metre horiz&vertical unit and towgs84 to gencentric CRS (`#3231 <https://github.com/OSGeo/PROJ/issues/3231>`_)
|
||||
|
||||
* :cpp:func:`createOperations()`: fix infinite recursion in a complex case (`#3226 <https://github.com/OSGeo/PROJ/issues/3226>`_)
|
||||
|
||||
|
||||
|
||||
9.0.1 Release Notes
|
||||
+++++++++++++++++++
|
||||
*June 15th 2022*
|
||||
|
||||
@@ -3,3 +3,11 @@
|
||||
Latitude of projection center.
|
||||
|
||||
*Defaults to 0.0.*
|
||||
|
||||
.. note::
|
||||
The default convention is to interpret this value as decimal degrees. To
|
||||
specify radians instead, follow the value with the "r" character.
|
||||
|
||||
Example: `+lat_0=1.5708r`
|
||||
|
||||
See :ref:`Projection Units <projection_units>` for more information.
|
||||
|
||||
@@ -3,3 +3,11 @@
|
||||
First standard parallel.
|
||||
|
||||
*Defaults to 0.0.*
|
||||
|
||||
.. note::
|
||||
The default convention is to interpret this value as decimal degrees. To
|
||||
specify radians instead, follow the value with the "r" character.
|
||||
|
||||
Example: `+lat_1=1.5708r`
|
||||
|
||||
See :ref:`Projection Units <projection_units>` for more information.
|
||||
|
||||
@@ -3,3 +3,11 @@
|
||||
Second standard parallel.
|
||||
|
||||
*Defaults to 0.0.*
|
||||
|
||||
.. note::
|
||||
The default convention is to interpret this value as decimal degrees. To
|
||||
specify radians instead, follow the value with the "r" character.
|
||||
|
||||
Example: `+lat_2=1.5708r`
|
||||
|
||||
See :ref:`Projection Units <projection_units>` for more information.
|
||||
|
||||
@@ -4,3 +4,11 @@
|
||||
Takes precedence over ``+k_0`` if both options are used together.
|
||||
|
||||
*Defaults to 0.0.*
|
||||
|
||||
.. note::
|
||||
The default convention is to interpret this value as decimal degrees. To
|
||||
specify radians instead, follow the value with the "r" character.
|
||||
|
||||
Example: `+lat_ts=1.5708r`
|
||||
|
||||
See :ref:`Projection Units <projection_units>` for more information.
|
||||
|
||||
@@ -3,3 +3,11 @@
|
||||
Longitude of projection center.
|
||||
|
||||
*Defaults to 0.0.*
|
||||
|
||||
.. note::
|
||||
The default convention is to interpret this value as decimal degrees. To
|
||||
specify radians instead, follow the value with the "r" character.
|
||||
|
||||
Example: `+lon_0=1.5708r`
|
||||
|
||||
See :ref:`Projection Units <projection_units>` for more information.
|
||||
|
||||
@@ -50,7 +50,9 @@ Required
|
||||
|
||||
.. option:: +model=<filename>
|
||||
|
||||
Filename to the JSON master file for the deformation model.
|
||||
Filename to the JSON master file for the deformation model. This file must validate
|
||||
against the `deformation_model.schema.json <https://raw.githubusercontent.com/OSGeo/PROJ/master/data/deformation_model.schema.json>`__
|
||||
JSON schema.
|
||||
|
||||
|
||||
Example
|
||||
|
||||
@@ -32,13 +32,11 @@ deformations can be modelled and then applied to the coordinates so that
|
||||
they represent the physical world better. In PROJ this is done with the deformation
|
||||
operation.
|
||||
|
||||
The horizontal grid is stored in CTable2 format and the vertical grid is stored in the
|
||||
GTX format. Both grids are expected to contain grid-values in units of
|
||||
mm/year. GDAL both reads and writes both file formats. Using GDAL for
|
||||
construction of new grids is recommended.
|
||||
|
||||
Starting with PROJ 7.0, use of a GeoTIFF format is recommended to store both
|
||||
the horizontal and vertical velocities.
|
||||
Starting with PROJ 7.0, it is recommended to store both the horizontal and vertical
|
||||
velocities in a single GeoTIFF file (:ref:`geodetictiffgrids`).
|
||||
Grid values are expected to be in units of mm/year. Using GDAL for construction of new grids is recommended.
|
||||
Prior to PROJ 7.0, the horizontal grid used to be stored in CTable2 format and the
|
||||
vertical grid in the GTX format. Both grids GDAL both reads and writes both file formats.
|
||||
|
||||
More complex deformations can be done with the :ref:`Multi-component time-based deformation model <defmodel>` transformation.
|
||||
|
||||
@@ -83,35 +81,11 @@ model. The first use of the deformation operation is::
|
||||
|
||||
Here we set the central epoch of the transformation, 2000.0. The observation epoch
|
||||
is expected as part of the input coordinate tuple. The deformation model is
|
||||
described by two grids, specified with :option:`+xy_grids` and :option:`+z_grids`.
|
||||
The first is the horizontal part of the model and the second is the vertical
|
||||
component.
|
||||
described by a single grid, specified with :option:`+grids`.
|
||||
|
||||
Parameters
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. option:: +xy_grids=<list>
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an ``@`` the
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids for the horizontal component of a deformation model is expected to be
|
||||
in CTable2 format.
|
||||
|
||||
.. note:: :option:`+xy_grids` is mutually exclusive with :option:`+grids`
|
||||
|
||||
.. option:: +z_grids=<list>
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an `@` the
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids for the vertical component of a deformation model is expected to be
|
||||
in either GTX format.
|
||||
|
||||
.. note:: :option:`+z_grids` is mutually exclusive with :option:`+grids`
|
||||
|
||||
.. option:: +grids=<list>
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
@@ -120,7 +94,7 @@ Parameters
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids should be in GeoTIFF format with the first 3 components being
|
||||
Grids should be in GeoTIFF format (:ref:`geodetictiffgrids`) with the first 3 components being
|
||||
respectively the easting, northing and up velocities in mm/year.
|
||||
Setting the Description and Unit Type GDAL band metadata items is strongly
|
||||
recommended, so that gdalinfo reports:
|
||||
@@ -159,6 +133,33 @@ Parameters
|
||||
|
||||
.. note:: :option:`+dt` is mutually exclusive with :option:`+t_epoch`
|
||||
|
||||
.. option:: +xy_grids=<list>
|
||||
|
||||
.. deprecated:: 7.0
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an ``@`` the
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids for the horizontal component of a deformation model is expected to be
|
||||
in CTable2 format.
|
||||
|
||||
.. note:: :option:`+xy_grids` is mutually exclusive with :option:`+grids`
|
||||
|
||||
.. option:: +z_grids=<list>
|
||||
|
||||
.. deprecated:: 7.0
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an `@` the
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids for the vertical component of a deformation model is expected to be
|
||||
in either GTX format.
|
||||
|
||||
.. note:: :option:`+z_grids` is mutually exclusive with :option:`+grids`
|
||||
|
||||
|
||||
Mathematical description
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ is not found in the PROJ search path. The list of grids is prioritized so that
|
||||
grids in the start of the list takes precedence over the grids in the back of the
|
||||
list.
|
||||
|
||||
PROJ supports CTable2, NTv1 and NTv2 files for horizontal grid corrections. Details
|
||||
PROJ supports GeoTIFF (:ref:`geodetictiffgrids`), CTable2 and NTv2 files for horizontal grid corrections. Details
|
||||
about all three formats can be found in the GDAL documentation and/or driver source
|
||||
code. GDAL reads and writes all three formats. Using GDAL for construction of
|
||||
new grids is recommended.
|
||||
@@ -106,7 +106,8 @@ Required
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids are expected to be in CTable2, NTv1 or NTv2 format.
|
||||
Grids are expected to be in GeoTIFF (:ref:`geodetictiffgrids`) or NTv2 format (or CTable2 for legacy
|
||||
grids)
|
||||
|
||||
Optional
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
@@ -40,8 +40,8 @@ is not found in the PROJ search path. The list of grids is prioritized so that
|
||||
grids in the start of the list takes precedence over the grids in the back of the
|
||||
list.
|
||||
|
||||
PROJ supports the GTX file format for vertical grid corrections. Details
|
||||
about all the format can be found in the GDAL documentation. GDAL both reads and
|
||||
PROJ supports the GeoTIFF (:ref:`geodetictiffgrids`) and GTX file formats for vertical grid corrections. Details
|
||||
about all the formats can be found in the GDAL documentation. GDAL both reads and
|
||||
writes the format. Using GDAL for construction of new grids is recommended.
|
||||
|
||||
Temporal gridshifting
|
||||
@@ -105,7 +105,7 @@ Required
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids are expected to be in GTX format.
|
||||
Grids are expected to be in GeoTIFF (:ref:`geodetictiffgrids`) or GTX formats.
|
||||
|
||||
Optional
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
@@ -68,7 +68,7 @@ Required
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids are expected to be in GeoTIFF format. If no metadata is provided,
|
||||
Grids are expected to be in GeoTIFF format (:ref:`geodetictiffgrids`). If no metadata is provided,
|
||||
the first, second and third samples are assumed to be the geocentric
|
||||
translation along X, Y and Z axis respectively, in metres.
|
||||
|
||||
|
||||
@@ -214,7 +214,8 @@ is an easy way to inspect such grid files:
|
||||
|
||||
- ``HORIZONTAL_OFFSET``: implies the presence of at least two samples.
|
||||
The first sample must contain the latitude offset and the second
|
||||
sample must contain the longitude offset.
|
||||
sample must contain the longitude offset. The offset may also be expressed
|
||||
as a speed per year for temporal gridshifting.
|
||||
Corresponds to PROJ :ref:`hgridshift` method.
|
||||
|
||||
- ``VERTICAL_OFFSET_GEOGRAPHIC_TO_VERTICAL``: implies the presence of at least one sample.
|
||||
@@ -330,6 +331,7 @@ is an easy way to inspect such grid files:
|
||||
|
||||
- ``degree``
|
||||
- ``arc-second`` (default value assumed if absent for longitude and latitude offset samples of horizontal shift grid files, and value used for files stored on PROJ CDN)
|
||||
- ``arc-seconds per year`` (when used with the :ref:`hgridshift` method with temporal gridshifting)
|
||||
|
||||
For velocity units:
|
||||
|
||||
@@ -643,3 +645,9 @@ been converted from https://github.com/OSGeo/proj-datumgrid/blob/master/north-am
|
||||
|
||||
It contains 114 subgrids. All essential metadata to list the subgrids and their
|
||||
georeferencing is contained within the first 40 KB of the file.
|
||||
|
||||
Revisions
|
||||
+++++++++
|
||||
|
||||
* v0.2: addition of "arc-seconds per year" as a valid unit (PROJ 9.1.1)
|
||||
* v0.1: initial version for PROJ 7.0
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
.. _euref2019_answers:
|
||||
|
||||
Answers to the PROJ tutorial exercises
|
||||
++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Projections1: UTM
|
||||
-------------------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +proj=utm +zone=35
|
||||
2. +proj=utm +zone=60 +south
|
||||
3. +proj=utm +zone=35 +ellps=intl
|
||||
|
||||
|
||||
Projections2: LCC
|
||||
-------------------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +proj=lcc +lat_1=59.8
|
||||
2. +proj=lcc +lat_1=59.8 +k_0=0.99998
|
||||
3. +proj=lcc +lat_1=59.437 +lat_2=60.171
|
||||
4. +proj=lcc +lat_1=59.8 +lat_0=59.8 +lon_0=24.8
|
||||
5. +proj=lcc +lat_1=59.8 +lat_0=59.8 +lon_0=24.8 +x_0=1000000 +y_0=1000000
|
||||
|
||||
|
||||
|
||||
Ellipsoids
|
||||
-----------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +R=1
|
||||
2. +ellps=intl
|
||||
3. +a=6378388.0 +rf=297.0
|
||||
4. +a=6378206.4 +b=6356583.8
|
||||
|
||||
|
||||
Helmert
|
||||
--------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +proj=helmert +x=-97 +y=-103 +z=-120
|
||||
2. +proj=helmert +x=-81.1 +y=-89.4 +z=-115.8 +rx=0.485 +ry=0.024 +rz=0.413 +s=-0.54 +convention=position_vector
|
||||
3a. +proj=helmert +x=582 +y=105 +z=414 +rx=-1.04 +ry=-0.35 +rz=3.08 +s=8.3
|
||||
3b. +proj=helmert +x=582 +y=105 +z=414 +rx=1.04 +ry=0.35 +rz=-3.08 +s=8.3
|
||||
1. +proj=helmert +convention=position_vector +x=-0.0016 +y=-0.0019 +z=-0.0024 +s=2e-05 +dz=0.0001 +ds=-3e-05 +t_epoch=2010
|
||||
|
||||
|
||||
Conversions
|
||||
------------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +proj=unitconvert +xy_in=m +xy_out=us-ft
|
||||
2. +proj=axisswap +order=2,1
|
||||
3. +proj=cart +ellps=intl
|
||||
|
||||
|
||||
Gridshifts
|
||||
-----------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +proj=hgridshift +grids=de_adv_BETA2007.tif
|
||||
2. +proj=vgridshift +grids=us_nga_egm96_15.tif
|
||||
|
||||
Pipelines
|
||||
----------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +proj=pipeline +ellps=GRS80
|
||||
+step +proj=cart
|
||||
+step +proj=helmert +x=100 +y=200 +z=300 +convention=position_vector
|
||||
+step +inv +proj=cart
|
||||
|
||||
2. +proj=pipeline
|
||||
+step +proj=hgridshift +grids=de_adv_BETA2007.tif
|
||||
+step +proj=vgridshift +grids=us_nga_egm96_15.tif
|
||||
|
||||
2.1: In principle, yes - practically, no.
|
||||
2.2: Which grids is applied first depends on how the systems are defined.
|
||||
If a geoid model is fitted to a certain datum, you need to make sure that
|
||||
the input to the vgridshift operation is in that datum. That is your
|
||||
responsibility to check - PROJ can't figure that out on its own. In this
|
||||
case, the EGM96 geoid is fitted to WGS84. The BETA2007 grid results in
|
||||
ETRS89 coordinates which for all but the most high accuracy application
|
||||
can be regarded as equivalent to WGS84. Hence we do the horizontal grid
|
||||
shift first.
|
||||
|
||||
3. +proj=pipeline
|
||||
+step +inv +proj=utm +zone=32
|
||||
+step +proj=cart +ellps=intl
|
||||
+step +proj=helmert +x=-81.1 +y=-89.4 +z=-115.8
|
||||
+rx=0.485 +ry=0.024 +rz=0.413 +s=-0.54 +convention=position_vector
|
||||
+step +inv +proj=cart +ellps=GRS80
|
||||
+step +proj=utm +zone=33
|
||||
|
||||
|
||||
4. +proj=pipeline
|
||||
+step +proj=axisswap +order=2,1
|
||||
+step +proj=unitconvert +xy_in=deg +xy_out=rad
|
||||
+step +proj=push +v_3 +step +proj=cart +ellps=bessel
|
||||
+step +proj=helmert +x=598.1 +y=73.7 +z=418.2
|
||||
+rx=0.202 +ry=0.045 +rz=-2.455 +s=6.7 +convention=position_vector
|
||||
+step +inv +proj=cart +ellps=GRS80
|
||||
+step +proj=pop +v_3
|
||||
+step +proj=unitconvert +xy_in=rad +xy_out=deg
|
||||
+step +proj=axisswap +order=2,1
|
||||
|
||||
4.1: Latitude (deg), longitude (deg), height (m)
|
||||
4.2: Latitude (deg), longitude (deg), height (m)
|
||||
4.3: Retain the original height of the input coordinate:
|
||||
Without the push/pop steps the height would be affected by
|
||||
the Helmert step.
|
||||
|
||||
Projections3: Tranverse Mercator
|
||||
---------------------------------
|
||||
|
||||
.. code-block::
|
||||
|
||||
1. +proj=tmerc
|
||||
2. +proj=tmerc +k_0=0.9996 +lon_0=27 +x_0=500000
|
||||
3a. 1 cm
|
||||
3b. 250 km
|
||||
3c. 100 km
|
||||
3d. 10 km
|
||||
3e. 500 m
|
||||
3f. 2 m
|
||||
3g. 5 um
|
||||
@@ -0,0 +1,118 @@
|
||||
###############################################################################
|
||||
|
||||
Coordinate Conversions
|
||||
|
||||
In ISO19111 terms, a coordinate conversion is an operation that changes
|
||||
coordinates in a source coordinate reference system to coordinates in a target
|
||||
coordinate reference system in which both coordinate reference systems are based
|
||||
on the same datum. Technically this is also true for PROJ although the term is
|
||||
usually narrowed a bit, excluding projections since those are the origin of
|
||||
PROJ they get special treatment.
|
||||
|
||||
In this exercise we will be looking at three coordinate conversions that in
|
||||
combination with other operations are very powerful: Unit conversions, axis
|
||||
swapping and geodetic to cartesian conversion. Here we only look at the
|
||||
conversions by themselves which isn't particularly useful, apart from the
|
||||
educational purpose. When used in transformation pipelines they reveal their
|
||||
true power. We will explore that further in the pipelines.gie exercises.
|
||||
|
||||
See [0] for a list of all conversions available in PROJ.
|
||||
|
||||
[0] https://proj.org/operations/conversions/index.html
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
|
||||
1. Unit conversion from meters to feet
|
||||
-------------------------------------------------------------------------------
|
||||
Many projected coordinate systems are defined in terms of units other than the
|
||||
meter. In this exercise we will transform the horizontal part of a coordinate
|
||||
from meters to feet.
|
||||
|
||||
Hints:
|
||||
|
||||
- Consult the documentation to find out how to set up the transformation:
|
||||
https://proj.org/operations/conversions/unitconvert.html
|
||||
|
||||
- You can use `proj -lu` to learn which units is supported by PROJ.
|
||||
|
||||
- Note that the horizontal, vertical and temporal parts are treated
|
||||
separately by the unit convert operator.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
accept 100.0 123.0 432.0
|
||||
expect 328.0833 403.5425 432.0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
2. Swapping axes
|
||||
-------------------------------------------------------------------------------
|
||||
Many coordinate reference systems are defined such that the axis order is
|
||||
different than the (east, north, up, time) PROJ defaults to. An example of this
|
||||
is the standard representation of a latitude/longitude-pair, where the north
|
||||
component of the coordinate comes first. For this reason we need an operation
|
||||
that can swap the axes around so that a given coordinate reference system can
|
||||
be represented correctly, conforming to the intention of the defining authority.
|
||||
|
||||
Set up an operation that puts a longitude/latitude pair on the standard
|
||||
latitude/longitude form.
|
||||
|
||||
Hints:
|
||||
|
||||
- Consult the documentation to find out how to set up the transformation:
|
||||
https://proj.org/operations/conversions/axisswap.html
|
||||
|
||||
- Remember that the axisswap operation doesn't know anything about the
|
||||
nature of the coordinate that is passed to it - it only cares about the
|
||||
the order of the input.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
accept 140.0 75.0 # somewhere in Siberia
|
||||
expect 75.0 140.0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
3. Geodetic to cartesian conversion
|
||||
-------------------------------------------------------------------------------
|
||||
Some transformations, most notably the Helmert transformation, operates on
|
||||
cartesian geocentric coordinates. Geodetic coordinates (latitude and longitude)
|
||||
is the most commonly used coordinate representation. It is only natural to have
|
||||
a way to convert between the two representations.
|
||||
|
||||
Set up a transformation that convert geodetic coordinates to cartesian
|
||||
geocentric coordinates on the Hayford ellipsoid.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- Consult the documentation to find out how to set up the transformation:
|
||||
https://proj.org/operations/conversions/cart.html
|
||||
|
||||
- Remember that `proj -le` returns a list of available ellipsoid models
|
||||
|
||||
- Remember that the Hayford ellipsoid is known under a number of other
|
||||
names - most of them including the term "international".
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
accept 24.745 59.437 0 # Talinn, Estonia
|
||||
expect 2952883.7000 1360985.5908 5468966.6589
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,94 @@
|
||||
.. _euref2019_conversions:
|
||||
|
||||
Coordinate conversions
|
||||
++++++++++++++++++++++++++++
|
||||
|
||||
In ISO19111 terms, a coordinate conversion is an operation that changes
|
||||
coordinates in a source coordinate reference system to coordinates in a target
|
||||
coordinate reference system in which both coordinate reference systems are based
|
||||
on the same datum. Technically this is also true for PROJ although the term is
|
||||
usually narrowed a bit, excluding projections since those are the origin of
|
||||
PROJ they get special treatment.
|
||||
|
||||
In this exercise we will be looking at three coordinate conversions that in
|
||||
combination with other operations are very powerful: Unit conversions, axis
|
||||
swapping and geodetic to cartesian conversion. Here we only look at the
|
||||
conversions by themselves which isn't particularly useful, apart from the
|
||||
educational purpose. When used in transformation pipelines they reveal their
|
||||
true power. We will explore that further in the pipelines.gie exercises.
|
||||
|
||||
See :ref:`conversions_list` for a list of all conversions available in PROJ.
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`conversions.gie <conversions.gie>`.
|
||||
|
||||
1. Unit conversion from meters to feet
|
||||
----------------------------------------
|
||||
|
||||
Many projected coordinate systems are defined in terms of units other than the
|
||||
meter. In this exercise we will transform the horizontal part of a coordinate
|
||||
from meters to feet.
|
||||
|
||||
.. hint::
|
||||
|
||||
Consult :ref:`unitconvert` to find out how to set up the transformation
|
||||
|
||||
.. hint:: You can use ``proj -lu`` to learn which units is supported by PROJ.
|
||||
|
||||
.. hint::
|
||||
|
||||
Note that the horizontal, vertical and temporal parts are treated
|
||||
separately by the unit convert operator.
|
||||
|
||||
.. literalinclude:: conversions.gie
|
||||
:lines: 45-49
|
||||
|
||||
|
||||
2. Swapping axes
|
||||
------------------
|
||||
|
||||
Many coordinate reference systems are defined such that the axis order is
|
||||
different than the (east, north, up, time) PROJ defaults to. An example of this
|
||||
is the standard representation of a latitude/longitude-pair, where the north
|
||||
component of the coordinate comes first. For this reason we need an operation
|
||||
that can swap the axes around so that a given coordinate reference system can
|
||||
be represented correctly, conforming to the intention of the defining authority.
|
||||
|
||||
Set up an operation that puts a longitude/latitude pair on the standard
|
||||
latitude/longitude form.
|
||||
|
||||
.. hint::
|
||||
|
||||
Consult :ref:`axisswap` to find out how to set up the transformation
|
||||
|
||||
.. hint::
|
||||
|
||||
Remember that the axisswap operation doesn't know anything about the
|
||||
nature of the coordinate that is passed to it - it only cares about the
|
||||
the order of the input.
|
||||
|
||||
.. literalinclude:: conversions.gie
|
||||
:lines: 77-81
|
||||
|
||||
3. Geodetic to cartesian conversion
|
||||
------------------------------------
|
||||
Some transformations, most notably the Helmert transformation, operate on
|
||||
cartesian geocentric coordinates. Geodetic coordinates (latitude and longitude)
|
||||
is the most commonly used coordinate representation. It is only natural to have
|
||||
a way to convert between the two representations.
|
||||
|
||||
Set up a transformation that convert geodetic coordinates to cartesian
|
||||
geocentric coordinates on the Hayford ellipsoid.
|
||||
|
||||
.. hint::
|
||||
|
||||
Consult :ref:`cart` to find out how to set up the transformation
|
||||
|
||||
.. hint:: Remember that `proj -le` returns a list of available ellipsoid models
|
||||
|
||||
.. hint::
|
||||
Remember that the Hayford ellipsoid is known under a number of other
|
||||
names - most of them including the term "international".
|
||||
|
||||
|
||||
.. literalinclude:: conversions.gie
|
||||
:lines: 109-113
|
||||
@@ -0,0 +1,81 @@
|
||||
###############################################################################
|
||||
|
||||
Specifying ellipsoid models
|
||||
|
||||
In this exercise we will introduce some of the many ways one can specify the
|
||||
ellipsoid model used in projections and transformations.
|
||||
|
||||
We will be using the Mercator projection to illustrate the different ellipsoid
|
||||
settings, but note that the same parameter settings can be used for setting
|
||||
the ellipsoid used for most PROJ projections and transformations.
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
|
||||
1. Use a sphere of radius 1 as the ellipsoid model:
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
* Check the Mercator documentation to find out how to specify an ellipsoid:
|
||||
https://proj.org/operations/projections/merc.html
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation +proj=merc <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.745 59.437 # Talinn
|
||||
expect 0.4319 1.2975
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
2. Specify the Hayford (International) ellipsoid
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
* Check the Mercator documentation to find out how to specify an ellipsoid:
|
||||
https://proj.org/operations/projections/merc.html
|
||||
|
||||
* Running `proj -le` will return a list of ellipsoids and their parameters.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation +proj=merc <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.745 59.437 # Talinn
|
||||
expect 2754709.2020 8238786.4803
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
3. Specify the Hayford ellipsoid by its semimajor axis radius and inverse
|
||||
flattening
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
* Find the parameters in the list returned by `proj -le`
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation +proj=merc <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.745 59.437 # Talinn
|
||||
expect 2754709.2020 8238786.4803
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
4. Set the Clarke 1866 ellipsoid by its semimajor and semiminor axis radii
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation +proj=merc <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.745 59.437 # Talinn
|
||||
expect 2754630.7723 8238298.4968
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,57 @@
|
||||
.. euref2019_ellipsoids:
|
||||
|
||||
Specifying ellipsoid models
|
||||
+++++++++++++++++++++++++++
|
||||
|
||||
In this exercise we will introduce some of the many ways one can specify the
|
||||
ellipsoid model used in projections and transformations.
|
||||
|
||||
We will be using the Mercator projection to illustrate the different ellipsoid
|
||||
settings, but note that the same parameter settings can be used for setting
|
||||
the ellipsoid used for most PROJ projections and transformations.
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`ellipsoids.gie <ellipsoids.gie>`.
|
||||
|
||||
|
||||
Exercise 1: Ellipsoid radius
|
||||
-----------------------------
|
||||
|
||||
Use a sphere of radius 1 as the ellipsoid model
|
||||
|
||||
.. hint::
|
||||
|
||||
Check the :ref:`Mercator documentation <merc>` to find out how to specify an ellipsoid
|
||||
|
||||
.. literalinclude:: ellipsoids.gie
|
||||
:lines: 24-28
|
||||
|
||||
Exercise 2. Specifying a ellipsoid
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Set up a Mercator projection that uses the Hayford (International) ellipsoid
|
||||
|
||||
.. hint::
|
||||
Check the :ref:`Mercator documentation <merc>` to find out how to specify an ellipsoid
|
||||
|
||||
.. hint:: Running ``proj -le`` will return a list of ellipsoids and their parameters.
|
||||
|
||||
.. literalinclude:: ellipsoids.gie
|
||||
:lines: 43-47
|
||||
|
||||
Exercise 3. Semimajor axis and inverse flattening
|
||||
---------------------------------------------------------------------------------------------
|
||||
|
||||
Specify the Hayford ellipsoid by its semimajor axis radius and inverse flattening
|
||||
|
||||
.. hint:: Find the parameters in the list returned by ``proj -le``
|
||||
|
||||
.. literalinclude:: ellipsoids.gie
|
||||
:lines: 61-65
|
||||
|
||||
Exercise 4. Semimajor and semiminor ellipsoid axes
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
Set the Clarke 1866 ellipsoid by its semimajor and semiminor axis radii
|
||||
|
||||
.. literalinclude:: ellipsoids.gie
|
||||
:lines: 73-77
|
||||
@@ -0,0 +1,10 @@
|
||||
<gie>
|
||||
|
||||
operation +proj=utm +zone=22
|
||||
#tolerance <your answer here>
|
||||
tolerance 1 nm
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland (~30 degrees from central meridian)
|
||||
roundtrip 1000
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,86 @@
|
||||
###############################################################################
|
||||
|
||||
Grid shifting
|
||||
|
||||
Sometimes it is simpler to define a transformation as a gridded model of
|
||||
displacements rather than a mathematical model. This approach, pioneered
|
||||
by the US National Geodetic Survey in their 1980s era transformation from
|
||||
the old NAD27 datum to the (back then) new NAD83, has become increasingly
|
||||
popular as disk space and CPU cycles have gotten cheaper.
|
||||
|
||||
Gridded models of displacements offer the ability to make local adjustments
|
||||
that are not possible with e.g. a Helmert transformation. This fact is
|
||||
especially leveraged in transformations of heights since the geoid is too
|
||||
bumpy to retain enough detail with a simple mathematical definition.
|
||||
|
||||
The main problem with grid shifting is availability of the grids needed for a
|
||||
given transformation. The PROJ package requires that the PROJ-data package
|
||||
[0] is installed alongside it.
|
||||
|
||||
[0] https://proj.org/resource_files.html
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
|
||||
1. Horizontal gridshifting
|
||||
-------------------------------------------------------------------------------
|
||||
In this exercise we will apply a horizontal grid shift as it is done in the
|
||||
transformation from the German DHDN to ETRS89 transformation [0].
|
||||
|
||||
Define the operation that converts from DE_DHDN to ETRS89 using a gridshift.
|
||||
|
||||
Hints:
|
||||
|
||||
- Consult the documentation to find out how to set up the transformation:
|
||||
https://proj.org/operations/transformations/hgridshift.html
|
||||
|
||||
- Find the relevant grid name by inspecting the output of
|
||||
|
||||
projinfo -s DHDN -t ETRS89 -o WKT2_2019
|
||||
|
||||
Note that two operations are returned, look for the one which uses the
|
||||
"HORIZONTAL_SHIFT_GTIFF" method.
|
||||
|
||||
[0] http://crs.bkg.bund.de/crseu/crs/descrtrans/BeTA/de_dhdn2etrs_beta.php
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
accept 13.0 52.0 0.0
|
||||
expect 12.9983317082 51.9986488216 0.0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
2. Vertical gridshifting
|
||||
-------------------------------------------------------------------------------
|
||||
The most common use case for vertical grid shifts is transformation from
|
||||
ellipsoidal heights to physical heights. In most cases this is equivalent to
|
||||
applying an offset from a geoid model, which is exactly what we will do in this
|
||||
exercise.
|
||||
|
||||
Set up an operation that transforms ellipsoidal heights to physical heights
|
||||
using the EGM96 model.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- Consult the documentation to find out how to set up the transformation:
|
||||
https://proj.org/operations/transformations/vgridshift.html
|
||||
|
||||
- The relevant grid name is "us_nga_egm96_15.tif"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
accept 13.0 52.0 100.0
|
||||
expect 13.0 52.0 58.1917
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,62 @@
|
||||
.. euref2019_gridshift:
|
||||
|
||||
Gridshifting
|
||||
+++++++++++++
|
||||
|
||||
Sometimes it is simpler to define a transformation as a gridded model of
|
||||
displacements rather than a mathematical model. This approach, pioneered
|
||||
by the US National Geodetic Survey in their 1980s era transformation from
|
||||
the old NAD27 datum to the (back then) new NAD83, has become increasingly
|
||||
popular as disk space and CPU cycles have gotten cheaper.
|
||||
|
||||
Gridded models of displacements offer the ability to make local adjustments
|
||||
that are not possible with e.g. a Helmert transformation. This fact is
|
||||
especially leveraged in transformations of heights since the geoid is too
|
||||
bumpy to retain enough detail with a simple mathematical definition.
|
||||
|
||||
The main problem with grid shifting is availability of the grids needed for a
|
||||
given transformation. The PROJ package requires that the
|
||||
:ref:`PROJ-data package <datumgrid>` is installed alongside it.
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`gridshift.gie <gridshift.gie>`.
|
||||
|
||||
Exercises 1. Horizontal gridshifting
|
||||
-------------------------------------
|
||||
|
||||
In this exercise we will apply a horizontal grid shift as it is done in the
|
||||
transformation from the `German DHDN to ETRS89 transformation <http://crs.bkg.bund.de/crseu/crs/descrtrans/BeTA/de_dhdn2etrs_beta.php>`_.
|
||||
|
||||
Define the operation that converts from DE_DHDN to ETRS89 using a gridshift.
|
||||
|
||||
.. hint:: See :ref:`hgridshift`
|
||||
|
||||
.. hint::
|
||||
|
||||
Find the relevant grid name by inspecting the output of
|
||||
|
||||
``projinfo -s DHDN -t ETRS89 -o WKT2_2019``
|
||||
|
||||
Note that two operations are returned, look for the one which uses the
|
||||
"NTv2" method.
|
||||
|
||||
.. literalinclude:: gridshift.gie
|
||||
:lines: 49-53
|
||||
|
||||
2. Vertical gridshifting
|
||||
-------------------------
|
||||
|
||||
The most common use case for vertical grid shifts is transformation from
|
||||
ellipsoidal heights to physical heights. In most cases this is equivalent to
|
||||
applying an offset from a geoid model, which is exactly what we will do in this
|
||||
exercise.
|
||||
|
||||
Set up an operation that transforms ellipsoidal heights to physical heights
|
||||
using the EGM96 model.
|
||||
|
||||
|
||||
.. hint:: See :ref:`vgridshift`
|
||||
|
||||
.. hint:: The relevant grid name is "us_nga_egm96_15.tif"
|
||||
|
||||
.. literalinclude:: gridshift.gie
|
||||
:lines: 78-82
|
||||
@@ -0,0 +1,172 @@
|
||||
###############################################################################
|
||||
|
||||
The Helmert transformation
|
||||
|
||||
In this set of exercises we investigate the Helmert Transformation and some of
|
||||
its properties. The Helmert transformation covers a wide range of configurations,
|
||||
from simple translations of coordinates to the fully-fledged spatiotemporal
|
||||
transformation. Wikipedia [0] and the PROJ documentation offer technical
|
||||
details on the transformation [1]
|
||||
|
||||
The Helmert transformation works on geocentric, cartesian coordinates. See the
|
||||
"conversions.gie" exercise for more info. In this exercise all coordinates are
|
||||
already given as cartesian coordinates, so you only need to focus on the actual
|
||||
transformation setup.
|
||||
|
||||
|
||||
[0] https://en.wikipedia.org/wiki/Helmert_transformation
|
||||
[1] https://proj.org/operations/transformations/helmert.html
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
|
||||
1. Simple coordinate translation
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The most basic application of the Helmert transformation is a translation of
|
||||
the x-, y- and z-components of the coordinate. This is rarely a good fit for
|
||||
large areas but locally a 3 parameter Helmert shift can be very effective. Even
|
||||
though the 3 parameter translation doesn't fit particularly well in large areas
|
||||
of use it is still commonly used between legacy and modern systems. In this
|
||||
exercise we will use a transformation between ED50 in Italy (Sardinia) and
|
||||
WGS84.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- You can find the transformations parameters by running the following
|
||||
command:
|
||||
|
||||
projinfo -o WKT2_2019 -k operation EPSG:1142
|
||||
|
||||
which returns the WKT2 definition of the transformation.
|
||||
|
||||
- Remember that the input to the Helmert transform is cartesian geocentric
|
||||
coordinates (x, y z).
|
||||
|
||||
- Consult the documentation to find out how to set up the transformation:
|
||||
https://proj.org/operations/transformations/helmert.html
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 m
|
||||
|
||||
accept 4826177.7574 4049643.9762 991162.2529 # Sardinia (40N, 9E)
|
||||
expect 4826080.7574 4049540.9762 991042.2529
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
2. Translation and rotation
|
||||
-------------------------------------------------------------------------------
|
||||
For larger areas it is not enough to just rely on translation of coordinates.
|
||||
In that case the solution is to include rotations of the axes and a scale
|
||||
adjustment.
|
||||
The rotational aspect of the transformation is handled by a set of three
|
||||
rotation matrices. Two conventions for the application of the rotations are
|
||||
in common use: Position Vector and Coordinate Frame. In this exercise we will
|
||||
using Position Vector. See the PROJ documentation on the Helmert transformation
|
||||
for further detail.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- You can find the transformations parameters by running the following
|
||||
command:
|
||||
|
||||
projinfo -o WKT2_2019 -k operation EPSG:1626
|
||||
|
||||
- Remember to specify the rotation convention with +convention
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 m
|
||||
|
||||
accept 3496723.5936 743251.5442 5264442.2361
|
||||
expect 3496639.7297 743156.3657 5264324.9341
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
3. Position vector/Coordinate frame
|
||||
-------------------------------------------------------------------------------
|
||||
Effectively, the difference between the two rotation conventions is the sign of
|
||||
the rotation parameters. In this exercise we will examine this property by
|
||||
looking at a transformation between the German DHDN reference system and ETRS89.
|
||||
|
||||
First find the parameters for the EPSG:1309 transformation. In 3a below, enter
|
||||
the parameters as reported by projinfo (using the coordinate frame convention).
|
||||
Adapt the parameters to the position vector convention in 3b.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- You can find the transformations parameters by running the following
|
||||
command:
|
||||
|
||||
projinfo -o WKT2_2019 -k operation EPSG:1309
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
* 3a:
|
||||
operation <your answer here> +convention=coordinate_frame
|
||||
|
||||
accept 4067886.6403 571704.1839 4862789.0376
|
||||
expect 4068519.1921 571728.6671 4863239.3787
|
||||
|
||||
* 3b:
|
||||
operation <your answer here> +convention=position_vector
|
||||
tolerance 1 m
|
||||
|
||||
accept 4067886.6403 571704.1839 4862789.0376
|
||||
expect 4068519.1921 571728.6671 4863239.3787
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
4. Kinematic transformation between ITRF2008 and ITRF2014
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The Helmert transformation also exists in a kinematic, or spatiotemporal,
|
||||
version. This takes the evolution of a coordinate reference system over time
|
||||
into account as well. This is done by pivoting about a reference epoch. The
|
||||
14-parameter spatiotemporal Helmert is used when super high accuracy
|
||||
transformations are needed. A good example of such a use case is transformations
|
||||
between various realizations of ITRS and ETRS89. In this exercise we look at the
|
||||
transformation from ITRF2008 to ITRF2014.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- You can find the transformations parameters by running the following
|
||||
command:
|
||||
|
||||
projinfo -o WKT2_2019 -s ITRF2008 -t ITRF2014
|
||||
|
||||
which returns the WKT2 definition of the transformation.
|
||||
|
||||
- Not all parameters need to be set.
|
||||
|
||||
- Pay attention to the units of the parameteres output by projinfo,
|
||||
you may have to convert them to standard units (e.g. mm -> m).
|
||||
|
||||
- Note that the coordinates in the test now also includes a time tag in the
|
||||
form of a decimalyear - This is always needed when doing spatiotemporal
|
||||
transformations in PROJ. The time tag is the observation time of the
|
||||
coordinate. Note that the time component of the coordinate is never
|
||||
affected by the transformation.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
|
||||
accept 2952736.3768 1360917.6894 5468849.5615 2019.5
|
||||
expect 2952736.3744 1360917.6871 5468849.5586 2019.5
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,132 @@
|
||||
.. _euref2019_helmert:
|
||||
|
||||
The Helmert transformation
|
||||
++++++++++++++++++++++++++++
|
||||
|
||||
In this set of exercises we investigate the Helmert Transformation and some of
|
||||
its properties. The Helmert transformation covers a wide range of configurations,
|
||||
from simple translations of coordinates to the fully-fledged spatiotemporal
|
||||
transformation. Consult `Wikipedia <https://en.wikipedia.org/wiki/Helmert_transformation>`_
|
||||
and :ref:`helmert` for in-depth technical details on the transformation.
|
||||
|
||||
The Helmert transformation works on geocentric, cartesian coordinates. See the
|
||||
:ref:`euref2019_conversions` exercise for more info. In this exercise all coordinates are
|
||||
already given as cartesian coordinates, so you only need to focus on the actual
|
||||
transformation setup.
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`helmert.gie <helmert.gie>`.
|
||||
|
||||
1. Simple coordinate translation
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The most basic application of the Helmert transformation is a translation of
|
||||
the x-, y- and z-components of the coordinate. This is rarely a good fit for
|
||||
large areas but locally a 3 parameter Helmert shift can be very effective. Even
|
||||
though the 3 parameter translation doesn't fit particularly well in large areas
|
||||
of use it is still commonly used between legacy and modern systems. In this
|
||||
exercise we will use a transformation between ED50 in Italy (Sardinia) and
|
||||
WGS84.
|
||||
|
||||
|
||||
.. hint::
|
||||
You can find the transformations parameters by running the following
|
||||
command::
|
||||
|
||||
projinfo -o WKT2_2019 -k operation EPSG:1142
|
||||
|
||||
which returns the WKT2 definition of the transformation.
|
||||
|
||||
.. hint::
|
||||
Remember that the input to the Helmert transform is cartesian geocentric
|
||||
coordinates (x, y z).
|
||||
|
||||
.. hint::
|
||||
See :ref:`helmert` to find out how to set up the transformation
|
||||
|
||||
.. literalinclude:: helmert.gie
|
||||
:lines: 53-57
|
||||
|
||||
2. Translation and rotation
|
||||
------------------------------
|
||||
|
||||
For larger areas it is not enough to just rely on translation of coordinates.
|
||||
In that case the solution is to include rotations of the axes and a scale
|
||||
adjustment.
|
||||
The rotational aspect of the transformation is handled by a set of three
|
||||
rotation matrices. Two conventions for the application of the rotations are
|
||||
in common use: Position Vector and Coordinate Frame. In this exercise we will
|
||||
using Position Vector. See the PROJ documentation on the Helmert transformation
|
||||
for further detail.
|
||||
|
||||
|
||||
.. hint::
|
||||
|
||||
You can find the transformations parameters by running the following
|
||||
command::
|
||||
|
||||
projinfo -o WKT2_2019 -k operation EPSG:1626
|
||||
|
||||
.. hint:: Remember to specify the rotation convention with +convention
|
||||
|
||||
.. literalinclude:: helmert.gie
|
||||
:lines: 85-89
|
||||
|
||||
3. Position vector/Coordinate frame
|
||||
------------------------------------
|
||||
|
||||
Effectively, the difference between the two rotation conventions is the sign of
|
||||
the rotation parameters. In this exercise we will examine this property by
|
||||
looking at a transformation between the German DHDN reference system and ETRS89.
|
||||
|
||||
First find the parameters for the EPSG:1309 transformation. In 3a below, enter
|
||||
the parameters as reported by projinfo (using the coordinate frame convention).
|
||||
Adapt the parameters to the position vector convention in 3b.
|
||||
|
||||
.. hint::
|
||||
|
||||
You can find the transformations parameters by running the following
|
||||
command::
|
||||
|
||||
projinfo -o WKT2_2019 -k operation EPSG:1309
|
||||
|
||||
.. literalinclude:: helmert.gie
|
||||
:lines: 114-125
|
||||
|
||||
4. Kinematic transformation between ITRF2008 and ITRF2014
|
||||
----------------------------------------------------------
|
||||
|
||||
The Helmert transformation also exists in a kinematic, or spatiotemporal,
|
||||
version. This takes the evolution of a coordinate reference system over time
|
||||
into account as well. This is done by pivoting about a reference epoch. The
|
||||
14-parameter spatiotemporal Helmert is used when super high accuracy
|
||||
transformations are needed. A good example of such a use case is transformations
|
||||
between various realizations of ITRS and ETRS89. In this exercise we look at the
|
||||
transformation from ITRF2008 to ITRF2014.
|
||||
|
||||
.. hint::
|
||||
|
||||
You can find the transformations parameters by running the following
|
||||
command::
|
||||
|
||||
projinfo -o WKT2_2019 -s ITRF2008 -t ITRF2014
|
||||
|
||||
which returns the WKT2 definition of the transformation.
|
||||
|
||||
.. hint:: Not all parameters need to be set.
|
||||
|
||||
.. hint::
|
||||
|
||||
Pay attention to the units of the parameters output by projinfo,
|
||||
you may have to convert them to standard units (e.g. mm -> m).
|
||||
|
||||
.. hint::
|
||||
|
||||
Note that the coordinates in the test now also includes a time tag in the
|
||||
form of a decimalyear - This is always needed when doing spatiotemporal
|
||||
transformations in PROJ. The time tag is the observation time of the
|
||||
coordinate. Note that the time component of the coordinate is never
|
||||
affected by the transformation.
|
||||
|
||||
|
||||
.. literalinclude:: helmert.gie
|
||||
:lines: 164-169
|
||||
@@ -0,0 +1,171 @@
|
||||
###############################################################################
|
||||
|
||||
Transformation Pipelines
|
||||
|
||||
In these exercises we will learn how to use Transformation Pipelines.
|
||||
Transformation Pipelines is a powerful construct in PROJ that allow users to
|
||||
combine several operations into one "super operation". Pipelines are used
|
||||
extensively internally in PROJ when a user asks for a transformation between
|
||||
two CRS's (for example when using cs2cs). However, users can also write their
|
||||
own custom pipelines for specific purposes.
|
||||
|
||||
Before moving on to the exercises below, familiarize yourself with the pipeline
|
||||
operation in the documentation [0]. Pay special attention to the rules that
|
||||
govern the use of the pipeline operation.
|
||||
|
||||
|
||||
[0] https://proj.org/operations/pipeline.html
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
|
||||
1. Geodetic -> Helmert -> Geodetic
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The signature use case for transformation pipelines is the Helmert
|
||||
transformation of geodetic coordinates.
|
||||
|
||||
As we have seen in the previous exercises, fundamentally, the Helmert
|
||||
operation works on cartesian coordinates. So when the input coordinates
|
||||
are geodetic, we must convert them to the cartesian space before
|
||||
applying the Helmert transformation.
|
||||
|
||||
Similarly, we must convert the transformed cartesian coordinates back to
|
||||
geodetic space to be able to compare the coordinates before and after
|
||||
transformation.
|
||||
|
||||
With that in mind, now create a transformation pipeline that takes geodetic
|
||||
(longitude/latitude) coordinates, applies a Helmert transform, and returns
|
||||
geodetic coordinates (in a different datum).
|
||||
|
||||
To keep it simple we will use the GRS80 ellipsoid for both input and output
|
||||
datum, and a basic 3 parameter transformation, with translations 100,200,300,
|
||||
and using the position vector convention.
|
||||
|
||||
Hints:
|
||||
|
||||
- Remember that in a pipeline step, the inverse of an operation is
|
||||
selected by adding "+inv" to the parameter list of the operation.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 m
|
||||
|
||||
accept 12.0 53.0 75.0
|
||||
expect 12.00260406 53.00062190 398.48468
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
2. Sequential grid shifts
|
||||
-------------------------------------------------------------------------------
|
||||
Create a transformation that applies both a horizontal and a vertical grid
|
||||
adjustment. Use the de_adv_BETA2007.tif and the us_nga_egm96_15.tif grids.
|
||||
|
||||
a. Does it matter which grid is applied first?
|
||||
b. If yes, which goes first? Why?
|
||||
|
||||
Hints:
|
||||
|
||||
- Relevant documentation:
|
||||
|
||||
https://proj.org/operations/transformations/hgridshift.html
|
||||
https://proj.org/operations/transformations/vgridshift.html
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 12.0 53.0 75.0
|
||||
expect 11.99846399 52.99852627 34.541488647
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
3. ED50/UTM32 -> ETRS89/UTM33
|
||||
-------------------------------------------------------------------------------
|
||||
A transformation from one coordinate reference system to another. A very common
|
||||
use case of transformation pipelines.
|
||||
|
||||
In this exercise we have UTM Zone 32 coordinates related to the ED50 datum,
|
||||
which we want to transform to UTM Zone 33 related to ETRS89.
|
||||
|
||||
The transformation goes:
|
||||
|
||||
back-projection -> geodetic to cartesian conversion -> Helmert transformation ->
|
||||
cartesian to geodetic conversion -> re-projection
|
||||
|
||||
... a very common recipe for transformations between projected coordinate systems.
|
||||
|
||||
Hints:
|
||||
|
||||
- Find the relevant Helmert parameters by running:
|
||||
|
||||
projinfo -k operation EPSG:1626 -o WKT2_2019
|
||||
|
||||
- If you can't remember which ellipsoids is used by ED50 and ETRS89
|
||||
you can look them up with
|
||||
|
||||
projinfo <datum>
|
||||
|
||||
- Relevant documentation:
|
||||
|
||||
https://proj.org/operations/projections/utm.html
|
||||
https://proj.org/operations/conversions/cart.html
|
||||
https://proj.org/operations/transformations/helmert.html
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 687080.63 6210278.55 0
|
||||
expect 312871.16 6210214.58 34.08
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
4. A pipeline from the Real World
|
||||
-------------------------------------------------------------------------------
|
||||
The transformation between the German DHDN and ETRS89 is a transformation
|
||||
pipeline consisting of eight steps. Lookup the transformation with projinfo:
|
||||
|
||||
projinfo -k operation EPSG:1776
|
||||
|
||||
and copy and paste the pipeline definition as your answer below. Try to decipher
|
||||
the pipeline and answer the following questions:
|
||||
|
||||
a. What is the input coordinate type and units?
|
||||
b. What is the output coordinate type and units?
|
||||
c. What is the purpose of the +proj=push and +proj=pop steps?
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- A pipeline definition can span several lines in the gie format. Use this
|
||||
to your advantage and put each step on it's own separate line for easier
|
||||
reading
|
||||
|
||||
- You can use projinfo to get more knowledge about a particular CRS:
|
||||
|
||||
projinfo <CRS name or code>
|
||||
|
||||
- Consult the documentation to find out how to set up the transformation:
|
||||
https://proj.org/operations/conversions/push.html
|
||||
https://proj.org/operations/conversions/pop.html
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 3 m
|
||||
|
||||
accept 12.0 53.0 75.0
|
||||
expect 12.0032 52.9953 75.0000
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,139 @@
|
||||
.. euref2019_pipelines:
|
||||
|
||||
Transformation pipelines
|
||||
++++++++++++++++++++++++++++
|
||||
|
||||
In these exercises we will learn how to use Transformation Pipelines.
|
||||
Transformation Pipelines is a powerful construct in PROJ that allow users to
|
||||
combine several operations into one "super operation". Pipelines are used
|
||||
extensively internally in PROJ when a user asks for a transformation between
|
||||
two CRS's (for example when using :program:`cs2cs`). However, users can also write their
|
||||
own custom pipelines for specific purposes.
|
||||
|
||||
Before moving on to the exercises below, familiarize yourself with the
|
||||
:ref:`pipeline operation in the documentation<pipeline>`. Pay special attention to the rules that
|
||||
govern the use of the pipeline operation.
|
||||
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`pipelines.gie <pipelines.gie>`.
|
||||
|
||||
1. Geodetic -> Helmert -> Geodetic
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The signature use case for transformation pipelines is the Helmert
|
||||
transformation of geodetic coordinates.
|
||||
|
||||
As we have seen in the previous exercises, fundamentally, the Helmert
|
||||
operation works on cartesian coordinates. So when the input coordinates
|
||||
are geodetic, we must convert them to the cartesian space before
|
||||
applying the Helmert transformation.
|
||||
|
||||
Similarly, we must convert the transformed cartesian coordinates back to
|
||||
geodetic space to be able to compare the coordinates before and after
|
||||
transformation.
|
||||
|
||||
With that in mind, now create a transformation pipeline that take geodetic
|
||||
(longitude/latitude) coordinates, applies a Helmert transform, and returns
|
||||
geodetic coordinates (in a different datum).
|
||||
|
||||
To keep it simple we will use the GRS80 ellipsoid for both input and output
|
||||
datum, and a basic 3 parameter transformation, with translations 100,200,300,
|
||||
and using the position vector convention.
|
||||
|
||||
.. hint::
|
||||
Remember that in a pipeline step, the inverse of an operation is
|
||||
selected by adding ``+inv`` to the parameter list of the operation.
|
||||
|
||||
.. literalinclude:: pipelines.gie
|
||||
:lines: 53-57
|
||||
|
||||
|
||||
2. Sequential grid shifts
|
||||
-------------------------------------------------------------------------------
|
||||
Create a transformation that applies both a horizontal and a vertical grid
|
||||
adjustment. Use the ``de_adv_BETA2007.tif`` and the ``us_nga_egm96_15.tif`` grids.
|
||||
|
||||
#. Does it matter which grid is applied first?
|
||||
#. If yes, which goes first? Why?
|
||||
|
||||
.. hint:: See :ref:`hgridshift` and :ref:`vgridshift`
|
||||
|
||||
.. literalinclude:: pipelines.gie
|
||||
:lines: 78-82
|
||||
|
||||
3. ED50/UTM32 -> ETRS89/UTM33
|
||||
-------------------------------
|
||||
|
||||
A transformation from one coordinate reference system to another. A very common
|
||||
use case of transformation pipelines.
|
||||
|
||||
In this exercise we have UTM Zone 32 coordinates related to the ED50 datum,
|
||||
which we want to transform to UTM Zone 33 related to ETRS89.
|
||||
|
||||
The transformation goes
|
||||
|
||||
#. Back-projection
|
||||
#. Geodetic to cartesian conversion
|
||||
#. Helmert transformation
|
||||
#. Cartesian to geodetic conversion
|
||||
#. Re-projection
|
||||
|
||||
which is a very common recipe for transformations between projected coordinate systems.
|
||||
|
||||
.. hint::
|
||||
|
||||
Find the relevant Helmert parameters by running::
|
||||
|
||||
projinfo -k operation EPSG:1626 -o WKT2_2019
|
||||
|
||||
.. hint::
|
||||
|
||||
If you can't remember which ellipsoids is used by ED50 and ETRS89
|
||||
you can look them up with::
|
||||
|
||||
projinfo <datum>
|
||||
|
||||
.. hint::
|
||||
|
||||
Relevant documentation:
|
||||
|
||||
#. :ref:`utm`
|
||||
#. :ref:`cart`
|
||||
#. :ref:`helmert`
|
||||
|
||||
.. literalinclude:: pipelines.gie
|
||||
:lines: 121-125
|
||||
|
||||
|
||||
4. A pipeline from the Real World
|
||||
----------------------------------
|
||||
|
||||
The transformation between the German DHDN and ETRS89 is a transformation
|
||||
pipeline consisting of eight steps. Lookup the transformation with projinfo::
|
||||
|
||||
projinfo -k operation EPSG:1776
|
||||
|
||||
and copy and paste the pipeline definition as your answer below. Try to decipher
|
||||
the pipeline and answer the following questions:
|
||||
|
||||
#. What is the input coordinate type and units?
|
||||
#. What is the output coordinate type and units?
|
||||
#. What is the purpose of the +proj=push and +proj=pop steps?
|
||||
|
||||
|
||||
.. hint::
|
||||
A pipeline definition can span several lines in the gie format. Use this
|
||||
to your advantage and put each step on it's own separate line for easier
|
||||
reading
|
||||
|
||||
.. hint::
|
||||
You can use projinfo to get more knowledge about a particular CRS::
|
||||
|
||||
projinfo <CRS name or code>
|
||||
|
||||
.. hint::
|
||||
Look at :ref:`push` and :ref:`pop` to find out how to set up the transformation
|
||||
|
||||
|
||||
.. literalinclude:: pipelines.gie
|
||||
:lines: 162-166
|
||||
@@ -0,0 +1,71 @@
|
||||
###############################################################################
|
||||
|
||||
The UTM Projection
|
||||
|
||||
In this exercise we will learn how to define a simple projection using PROJ.
|
||||
We will investigate a few aspects of the UTM projection, as well as learn how
|
||||
to use a different ellipsoid than the default (GRS80).
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
|
||||
1. Set up a UTM projection for use in Estonia.
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
* Consult the documentation at
|
||||
https://proj.org/operations/projections/utm.html
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.745 59.437 # Talinn, Estonia
|
||||
expect 372106.37 6590881.40
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
2. Set up a UTM projection for use on the North Island of New Zealand
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
* Consult the documentation at
|
||||
https://proj.org/operations/projections/utm.html
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 174.740 -36.841 # Auckland, New Zealand
|
||||
expect 298481.34 5920382.04
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
3. Set up a UTM projection based on the Hayford ellipsoid for use in Estonia
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
* Consult the documentation at
|
||||
https://proj.org/operations/projections/utm.html
|
||||
|
||||
* A list of available ellipsoids can be seen by running the command:
|
||||
|
||||
proj -le
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.745 59.437 # Talinn, Estonia
|
||||
expect 372099.99 6591034.35
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,44 @@
|
||||
.. euref2019_projections1:
|
||||
|
||||
The UTM projection
|
||||
++++++++++++++++++
|
||||
|
||||
In this exercise we will learn how to define a simple projection using PROJ.
|
||||
We will investigate a few aspects of the UTM projection, as well as learn how
|
||||
to use a different ellipsoid than the default (GRS80).
|
||||
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`projections1.gie <projections1.gie>`.
|
||||
|
||||
Exercise 1: Setting up a projection
|
||||
-----------------------------------
|
||||
|
||||
Set up a UTM projection for use in Estonia.
|
||||
|
||||
.. hint:: See :ref:`UTM` for more on the projection
|
||||
|
||||
.. literalinclude:: projections1.gie
|
||||
:lines: 21-25
|
||||
|
||||
Exercise 2: UTM on the southern hemisphere
|
||||
-------------------------------------------
|
||||
|
||||
Set up a UTM projection for use on the North Island of New Zealand.
|
||||
|
||||
.. hint:: See :ref:`UTM` for more on the projection
|
||||
|
||||
|
||||
.. literalinclude:: projections1.gie
|
||||
:lines: 40-44
|
||||
|
||||
Exercise 3: Using a non-standard ellipsoid
|
||||
-------------------------------------------
|
||||
|
||||
Set up a UTM projection based on the Hayford ellipsoid for use in Estonia.
|
||||
|
||||
.. hint:: See :ref:`UTM` for more on the projection
|
||||
|
||||
.. hint:: Run ``proj -le`` to get a list of available ellipsoids
|
||||
|
||||
.. literalinclude:: projections1.gie
|
||||
:lines: 63-67
|
||||
@@ -0,0 +1,173 @@
|
||||
###############################################################################
|
||||
|
||||
The Lambert Conic Conformal projection
|
||||
|
||||
In this exercise we will introduce the Lambert Conic Conformal (LCC) projection
|
||||
as well as general map projection concepts such as projection center, scale
|
||||
factor, false easting/northing and ellipsoid models.
|
||||
|
||||
We will do so by defining various versions of the LCC optimised for use in and
|
||||
around the Gulf of Finland.
|
||||
|
||||
In case you are not familiar with the LCC projection, Wikipedia [0] describes
|
||||
the Lambert Conic Conformal projection as:
|
||||
|
||||
"A Lambert conformal conic projection (LCC) is a conic map projection used for
|
||||
aeronautical charts, portions of the State Plane Coordinate System, and many
|
||||
national and regional mapping systems. It is one of seven projections introduced
|
||||
by Johann Heinrich Lambert in his 1772 publication Anmerkungen und Zusätze zur
|
||||
Entwerfung der Land- und Himmelscharten (Notes and Comments on the Composition
|
||||
of Terrestrial and Celestial Maps).
|
||||
|
||||
Conceptually, the projection seats a cone over the sphere of the Earth and
|
||||
projects the surface conformally onto the cone. The cone is unrolled, and the
|
||||
parallel that was touching the sphere is assigned unit scale. That parallel is
|
||||
called the reference parallel or standard parallel.
|
||||
|
||||
By scaling the resulting map, two parallels can be assigned unit scale, with
|
||||
scale decreasing between the two parallels and increasing outside them. This
|
||||
gives the map two standard parallels. In this way, deviation from unit scale can
|
||||
be minimized within a region of interest that lies largely between the two
|
||||
standard parallels. Unlike other conic projections, no true secant form of the
|
||||
projection exists because using a secant cone does not yield the same scale
|
||||
along both standard parallels"
|
||||
|
||||
[0] https://en.wikipedia.org/wiki/Lambert_conformal_conic_projection
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
1. Set up a LCC projection with one standard parallel placed halfway between
|
||||
Helsinki and Tallinn.
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
- Approximate location of Helsinki: 60.171N 24.938E
|
||||
- Approximate location of Tallinn: 59.437N 24.745E
|
||||
- Approximate mid point between Helsinki and Tallinn: 59.8N 24.8E
|
||||
|
||||
- The PROJ documentation for LCC is found at
|
||||
https://proj.org/operations/projections/lcc.html
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.938 60.171 # Helsinki
|
||||
expect 1351962.01 298663.54
|
||||
|
||||
accept 24.745 59.437 # Tallinn
|
||||
expect 1371811.19 218598.22
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
2. Improve the distance distortion of the projection.
|
||||
------------------------------------------------------------------------------
|
||||
The projection defined above is conformal, i.e. has no angular distortions
|
||||
for infinitesimal objects - but there is a minor distortion of distances.
|
||||
This cannot be avoided in general, but locally distortions can be minimized
|
||||
by adjusting the scale factor.
|
||||
|
||||
With the default factor of 1, the distance error is 0 for (infinitesimal)
|
||||
line segments at the latitude of the standard parallel.
|
||||
|
||||
By reducing the scale factor, the line of zero distance distortion degenerates
|
||||
into two lines, north and south of the standard parallel.
|
||||
|
||||
For the abovementioned point in Tallinn, the distance error is around 0.002%,
|
||||
but this can be reduced to zero by varying the scaling factor.
|
||||
|
||||
Even by trial and error it is not hard to reduce it to a few millionths of a
|
||||
percent. So try to find a more optimal scaling factor by trial and error using
|
||||
the projection analysis functionality of the proj application.
|
||||
|
||||
Hints:
|
||||
|
||||
- Modify and use the command below to find a better scaling factor:
|
||||
|
||||
. echo 24.745 59.437 | proj -V <your projection setup here>
|
||||
|
||||
- Look for the lines displaying the meridian and parallel scale.
|
||||
- Consult the LCC documentation to find out how to set the scaling factor.
|
||||
- Scaling factors usually deviates from unity by the order of 1e-3 to 1e-5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 um
|
||||
|
||||
accept 24.745 59.437
|
||||
expect 1371783.759883408 218593.850591891
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
3. Set up a similar LCC projection, this time using two standard parallels.
|
||||
The first passing through Helsinki, the second through Tallinn.
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
- Approximate location of Helsinki: 60.171N 24.938E
|
||||
- Approximate location of Talinn: 59.437N 24.745E
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.8 59.8
|
||||
expect 1359907.80 8024082.260
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
4. Change the projection center to the midway point between Helsinki and Tallinn
|
||||
------------------------------------------------------------------------------
|
||||
By changing the projection center we move the origin of the output
|
||||
coordinates to be coinciding with the position where the projection is
|
||||
most accurate.
|
||||
|
||||
Hints:
|
||||
|
||||
- Start with the projection you designed in exercise 1 above
|
||||
- The mid point between Helsinki and Tallinn is roughly 59.8N 24.8E
|
||||
- The LCC documentation explains how to change the projection center
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.8 59.8
|
||||
expect 0.0 0.0
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
5. Introduce false eastings and northings
|
||||
------------------------------------------------------------------------------'
|
||||
Oftentimes it is preferable to keep coordinate values positive even when
|
||||
moving west and south of the projection center. This can be achieved by
|
||||
introducing false easting and northing. Add false easting and northing
|
||||
of 1000000
|
||||
|
||||
Hints:
|
||||
|
||||
- The LCC documentation explains how to set false easting/northing
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 cm
|
||||
|
||||
accept 24.8 59.8
|
||||
expect 1000000.00 1000000.00
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,145 @@
|
||||
.. euref2019_projections2:
|
||||
|
||||
The Lambert Conic Conformal projection
|
||||
++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
In this exercise we will introduce the Lambert Conic Conformal (LCC) projection
|
||||
as well as general map projection concepts such as projection center, scale
|
||||
factor, false easting/northing and ellipsoid models.
|
||||
|
||||
We will do so by defining various versions of the LCC optimised for use in and
|
||||
around the Gulf of Finland.
|
||||
|
||||
In case you are not familiar with the LCC projection, `Wikipedia`_ describes
|
||||
the Lambert Conic Conformal projection as:
|
||||
|
||||
"A Lambert conformal conic projection (LCC) is a conic map projection used for
|
||||
aeronautical charts, portions of the State Plane Coordinate System, and many
|
||||
national and regional mapping systems. It is one of seven projections introduced
|
||||
by Johann Heinrich Lambert in his 1772 publication Anmerkungen und Zusätze zur
|
||||
Entwerfung der Land- und Himmelscharten (Notes and Comments on the Composition
|
||||
of Terrestrial and Celestial Maps).
|
||||
|
||||
Conceptually, the projection seats a cone over the sphere of the Earth and
|
||||
projects the surface conformally onto the cone. The cone is unrolled, and the
|
||||
parallel that was touching the sphere is assigned unit scale. That parallel is
|
||||
called the reference parallel or standard parallel.
|
||||
|
||||
By scaling the resulting map, two parallels can be assigned unit scale, with
|
||||
scale decreasing between the two parallels and increasing outside them. This
|
||||
gives the map two standard parallels. In this way, deviation from unit scale can
|
||||
be minimized within a region of interest that lies largely between the two
|
||||
standard parallels. Unlike other conic projections, no true secant form of the
|
||||
projection exists because using a secant cone does not yield the same scale
|
||||
along both standard parallels"
|
||||
|
||||
.. _`Wikipedia`: https://en.wikipedia.org/wiki/Lambert_conformal_conic_projection
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`projections2.gie <projections2.gie>`.
|
||||
|
||||
Exercise 1: Standard parallel
|
||||
------------------------------
|
||||
|
||||
Set up a LCC projection with one standard parallel placed halfway between
|
||||
Helsinki and Tallinn.
|
||||
|
||||
.. hint::
|
||||
|
||||
* Approximate location of Helsinki: 60.171N 24.938E
|
||||
* Approximate location of Tallinn: 59.437N 24.745E
|
||||
* Approximate mid point between Helsinki and Tallinn: 59.8N 24.8E
|
||||
|
||||
|
||||
.. hint:: See :ref:`lcc` for more on the Lambert Conformal Conic projection
|
||||
|
||||
|
||||
.. literalinclude:: projections2.gie
|
||||
:lines: 54-61
|
||||
|
||||
Exercise 2: Distance distortion
|
||||
--------------------------------
|
||||
|
||||
Improve the distance distortion of the projection.
|
||||
|
||||
The projection defined above is conformal, i.e. has no angular distortions
|
||||
for infinitesimal objects - but there is a minor distortion of distances.
|
||||
This cannot be avoided in general, but locally distortions can be minimized
|
||||
by adjusting the scale factor.
|
||||
|
||||
With the default factor of 1, the distance error is 0 for (infinitesimal)
|
||||
line segments at the latitude of the standard parallel.
|
||||
|
||||
By reducing the scale factor, the line of zero distance distortion degenerates
|
||||
into two lines, north and south of the standard parallel.
|
||||
|
||||
For the abovementioned point in Tallinn, the distance error is around 0.002%,
|
||||
but this can be reduced to zero by varying the scaling factor.
|
||||
|
||||
Even by trial and error it is not hard to reduce it to a few millionths of a
|
||||
percent. So try to find a more optimal scaling factor by trial and error using
|
||||
the projection analysis functionality of the proj application.
|
||||
|
||||
.. hint::
|
||||
|
||||
Modify and use the command below to find a better scaling factor::
|
||||
|
||||
echo 24.745 59.437 | proj -V <your projection setup here>
|
||||
|
||||
.. hint:: Look for the lines displaying the meridian and parallel scale.
|
||||
|
||||
.. hint:: Consult the LCC documentation to find out how to set the scaling factor.
|
||||
|
||||
.. hint:: Scaling factors usually deviates from unity by the order of 1e-3 to 1e-5
|
||||
|
||||
|
||||
.. literalinclude:: projections2.gie
|
||||
:lines: 99-103
|
||||
|
||||
Exercise 3: Using two standard parallels
|
||||
-----------------------------------------
|
||||
|
||||
Set up a similar LCC projection, this time using two standard parallels.
|
||||
The first passing through Helsinki, the second through Tallinn.
|
||||
|
||||
.. hint::
|
||||
|
||||
* Approximate location of Helsinki: 60.171N 24.938E
|
||||
* Approximate location of Talinn: 59.437N 24.745E
|
||||
|
||||
.. literalinclude:: projections2.gie
|
||||
:lines: 119-123
|
||||
|
||||
Exercise 4: Projection center
|
||||
-----------------------------
|
||||
|
||||
Change the projection center to the midway point between Helsinki and Tallinn.
|
||||
|
||||
By changing the projection center we move the origin of the output
|
||||
coordinates to be coinciding with the position where the projection is
|
||||
most accurate.
|
||||
|
||||
.. hint:: Start with the projection you designed in exercise 1 above
|
||||
|
||||
.. hint:: The mid point between Helsinki and Tallinn is roughly 59.8N 24.8E
|
||||
|
||||
.. hint:: :ref:`LCC` explains how to change the projection center
|
||||
|
||||
|
||||
.. literalinclude:: projections2.gie
|
||||
:lines: 143-147
|
||||
|
||||
|
||||
Exercie 5: False easting and northing
|
||||
--------------------------------------
|
||||
|
||||
Introduce false eastings and northings.
|
||||
|
||||
Oftentimes it is preferable to keep coordinate values positive even when
|
||||
moving west and south of the projection center. This can be achieved by
|
||||
introducing false easting and northing. Add false easting and northing
|
||||
of 1000000
|
||||
|
||||
.. hint:: :ref:`LCC` explains how to set false easting/northing
|
||||
|
||||
.. literalinclude:: projections2.gie
|
||||
:lines: 165-169
|
||||
@@ -0,0 +1,175 @@
|
||||
###############################################################################
|
||||
|
||||
The Transverse Mercator projection
|
||||
|
||||
In this exercise we will introduce the Transverse Mercator projection, the
|
||||
UTM projection and the relationship between the two.
|
||||
|
||||
In addition we will investigate the differences between the two Transverse
|
||||
Mercator implementations available in PROJ and when one should be used in
|
||||
favour of the other.
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
|
||||
1. Set up a Transverse Mercator projection using the default parameters.
|
||||
-------------------------------------------------------------------------------
|
||||
Hints:
|
||||
|
||||
* Consult the documentation at
|
||||
https://proj.org/operations/projections/tmerc.html
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
accept 24.745 56.437 # Talinn, Estonia
|
||||
expect 1506742.2481 6535299.3398
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
2. Use the Transverse Mercator to model the UTM projection
|
||||
-------------------------------------------------------------------------------
|
||||
The backbone of the UTM projection is a Transverse Mercator projection. In
|
||||
this exercise we will model the behaviour of the UTM projection using the
|
||||
Transverse Mercator.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
- Remember that the UTM projection on the Northern Hemisphere uses a scale
|
||||
factor of 0.9996, a false easting of 500000 and a false northing of 0.
|
||||
UTM on the Southern Hemisphere is similar but with a false northing of
|
||||
10000000.
|
||||
|
||||
- The projection center is determined from the UTM zone and can be
|
||||
determined by zone*6 - 183
|
||||
|
||||
- Tranverse Mercator parameters are documented at
|
||||
https://proj.org/operations/projections/tmerc.html
|
||||
|
||||
- For more info, see
|
||||
* https://proj.org/operations/projections/utm.html
|
||||
* https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
operation <your answer here>
|
||||
tolerance 1 mm
|
||||
|
||||
accept 24.745 56.437 # Talinn, Estonia
|
||||
expect 360965.5942 6256998.5609
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
3. Explore the less accurate, but faster, version of the Tranverse Mercator
|
||||
-------------------------------------------------------------------------------
|
||||
As mentioned in the introduction to this set of exercises, two versions of the
|
||||
Transverse Mercator is implemented in PROJ. The default uses the Engsager/Poder
|
||||
algorithm which is accurate far away from the central meridian of the
|
||||
projection. The downside to this accuracy is that the algorithm is slower. The
|
||||
alternative algorithm, which is toggled by the +approx parameter, is faster but
|
||||
usage is recommended only within a few degrees away from the central meridian.
|
||||
|
||||
In this and the following exercises we will explore the accuracy of the two
|
||||
algorithms by checking the roundtrip stability of a number of transformations.
|
||||
A coordinate in Greenland will be used, as it is common practice to store
|
||||
geospatial data covering the whole country in the same UTM zone. This is only
|
||||
possible when using the correct algorithm. For the sake of simplicity,
|
||||
all operations in the following exercises are expressed as UTM projections. The
|
||||
UTM projection also has the +approx parameter which toggles the use of the
|
||||
faster, less accurate transverse mercator algorithm.
|
||||
|
||||
We will try to determine the approximate roundtrip accuracy of the +approx
|
||||
algorithm several UTM zones away from the actual zone for the given coordinate.
|
||||
For all the exercises below the aim is to find the lowest tolerance for each
|
||||
roundtrip test. You can of course make alle tests pass by setting a tolerance of
|
||||
1000 km - that's not the point: How low can you go?
|
||||
|
||||
After you have answered all ex. 3 questions below, based on your findings
|
||||
consider in which situation use of each of the algorithms is appropriate.
|
||||
|
||||
Hints:
|
||||
|
||||
- gie accepts most common SI unit prefixes to the meter when specifying
|
||||
the tolerance, e.g. km, m, dm, cm, mm, um, nm.
|
||||
|
||||
- Look at the output gie produces - the difference between the actual result
|
||||
and the expected result is reported when tests fail.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
* 3a. As a baseline, determine the roundtrip accuracy of the default algorirthm
|
||||
using UTM zone 22:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
operation +proj=utm +zone=22
|
||||
tolerance <your answer here> # Hint: You can go *very* low here
|
||||
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland (~30 degrees from central meridian)
|
||||
roundtrip 1000
|
||||
|
||||
* 3b. Determine the roundtrip accuracy of the "+approx" algorithm using UTM zone 22:
|
||||
-------------------------------------------------------------------------------
|
||||
operation +proj=utm +zone=22 +approx
|
||||
tolerance <your answer here>
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland (~30 degrees from central meridian)
|
||||
roundtrip 1000
|
||||
|
||||
|
||||
* 3c. Determine the roundtrip accuracy of the "+approx" algorithm using UTM zone 23:
|
||||
-------------------------------------------------------------------------------
|
||||
operation +proj=utm +zone=23 +approx
|
||||
tolerance <your answer here>
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland
|
||||
roundtrip 1000
|
||||
|
||||
|
||||
* 3d. Determine the roundtrip accuracy of the "+approx" algorithm using UTM zone 24:
|
||||
-------------------------------------------------------------------------------
|
||||
operation +proj=utm +zone=24 +approx
|
||||
tolerance <your answer here>
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland
|
||||
roundtrip 1000
|
||||
|
||||
|
||||
* 3e. Determine the roundtrip accuracy of the "+approx" algorithm using UTM zone 25:
|
||||
-------------------------------------------------------------------------------
|
||||
operation +proj=utm +zone=25 +approx
|
||||
tolerance <your answer here>
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland
|
||||
roundtrip 1000
|
||||
|
||||
|
||||
* 3f. Determine the roundtrip accuracy of the "+approx" algorithm using UTM zone 26:
|
||||
-------------------------------------------------------------------------------
|
||||
operation +proj=utm +zone=26 +approx
|
||||
tolerance <your answer here>
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland
|
||||
roundtrip 1000
|
||||
|
||||
|
||||
* 3g. Determine the roundtrip accuracy of the "+approx" algorithm using UTM zone 27:
|
||||
-------------------------------------------------------------------------------
|
||||
operation +proj=utm +zone=27 +approx
|
||||
tolerance <your answer here>
|
||||
|
||||
accept -20.0 74 # Daneborg, Greenland
|
||||
roundtrip 1000
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,141 @@
|
||||
.. _euref2019_projections3:
|
||||
|
||||
The Transverse Mercator projection
|
||||
+++++++++++++++++++++++++++++++++++
|
||||
|
||||
In this exercise we will introduce the Transverse Mercator projection, the
|
||||
UTM projection and the relationship between the two.
|
||||
|
||||
In addition we will investigate the differences between the two Transverse
|
||||
Mercator implementations available in PROJ and when one should be used in
|
||||
favour of the other.
|
||||
|
||||
Download the :program:`gie` file for the exercise: :download:`projections3.gie <projections3.gie>`.
|
||||
|
||||
Exercise 1. Transverse Mercator with default parameters
|
||||
--------------------------------------------------------
|
||||
|
||||
Set up a Transverse Mercator projection using the default parameters.
|
||||
|
||||
.. hint:: Consult :ref:`tmerc`
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 25-29
|
||||
|
||||
Exercise 2: Use the Transverse Mercator to model the UTM projection
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The backbone of the UTM projection is a Transverse Mercator projection. In
|
||||
this exercise we will model the behaviour of the UTM projection using the
|
||||
Transverse Mercator.
|
||||
|
||||
|
||||
.. hint::
|
||||
Remember that the UTM projection on the Northern Hemisphere uses a scale
|
||||
factor of 0.9996, a false easting of 500000 and a false northing of 0.
|
||||
UTM on the Southern Hemisphere is similar but with a false northing of
|
||||
10000000.
|
||||
|
||||
.. hint::
|
||||
The projection center is determined from the UTM zone and can be
|
||||
determined by zone*6 - 183
|
||||
|
||||
.. hint:: Tranverse Mercator parameters are documented at :ref:`tmerc`
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 60-64
|
||||
|
||||
Exercise 3: The less accurate, but faster, version of the Tranverse Mercator
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
As mentioned in the introduction to this set of exercises, two versions of the
|
||||
Transverse Mercator is implemented in PROJ. The default uses the Engsager/Poder
|
||||
algorithm which is accurate far away from the central meridian of the
|
||||
projection. The downside to this accuracy is that the algorithm is slower. The
|
||||
alternative algorithm, which is toggled by the +approx parameter, is faster but
|
||||
usage is recommended only within a few degrees away from the central meridian.
|
||||
|
||||
In this and the following exercises we will explore the accuracy of the two
|
||||
algorithms by checking the roundtrip stability of a number of transformations.
|
||||
A coordinate in Greenland will be used, as it is common practice to store
|
||||
geospatial data covering the whole country in the same UTM zone. This is only
|
||||
possible when using the correct algorithm. For the sake of simplicity,
|
||||
all operations in the following exercises are expressed as UTM projections. The
|
||||
UTM projection also has the +approx parameter which toggles the use of the
|
||||
faster, less accurate transverse mercator algorithm.
|
||||
|
||||
We will try to determine the approximate roundtrip accuracy of the +approx
|
||||
algorithm several UTM zones away from the actual zone for the given coordinate.
|
||||
For all the exercises below the aim is to find the lowest tolerance for each
|
||||
roundtrip test. You can of course make alle tests pass by setting a tolerance of
|
||||
1000 km - that's not the point: How low can you go?
|
||||
|
||||
After you have answered all exercise 3 questions below, based on your findings
|
||||
consider in which situation use of each of the algorithms is appropriate.
|
||||
|
||||
.. hint::
|
||||
:program:`gie` accepts most common SI unit prefixes to the meter when
|
||||
specifying the tolerance, e.g. km, m, dm, cm, mm, um, nm.
|
||||
|
||||
.. hint::
|
||||
Look at the output :program:`gie` produces - the difference between the
|
||||
actual result and the expected result is reported when tests fail.
|
||||
|
||||
Exercise 3a
|
||||
===========
|
||||
|
||||
As a baseline, determine the roundtrip accuracy of the default algorirthm
|
||||
using UTM zone 22.
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 112-117
|
||||
|
||||
Exercise 3b
|
||||
===========
|
||||
|
||||
Determine the roundtrip accuracy of the ``+approx`` algorithm using UTM zone 22:
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 121-125
|
||||
|
||||
Exercise 3c
|
||||
===========
|
||||
|
||||
Determine the roundtrip accuracy of the ``+approx`` algorithm using UTM zone 23.
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 130-134
|
||||
|
||||
Exercise 3d
|
||||
===========
|
||||
|
||||
Determine the roundtrip accuracy of the ``+approx`` algorithm using UTM zone 24:
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 139-143
|
||||
|
||||
Exercise 3e
|
||||
============
|
||||
|
||||
Determine the roundtrip accuracy of the ``+approx`` algorithm using UTM zone 25:
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 148-152
|
||||
|
||||
|
||||
Exercise 3f
|
||||
===========
|
||||
|
||||
Determine the roundtrip accuracy of the ``+approx`` algorithm using UTM zone 26:
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 157-161
|
||||
|
||||
Exercise 3g
|
||||
============
|
||||
|
||||
Determine the roundtrip accuracy of the ``+approx`` algorithm using UTM zone 27:
|
||||
|
||||
.. literalinclude:: projections3.gie
|
||||
:lines: 166-170
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
.. _transformation_tutorial:
|
||||
|
||||
================================================================================
|
||||
Transformation tutorial
|
||||
================================================================================
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This tutorial was developed for the EUREF 2019 Symposium as an introduction
|
||||
to geodetic transformations in PROJ. The intended audience was geodesist in
|
||||
governmental geodetic agencies but the tutorial should be of interest to a
|
||||
broader group of people within GIS, remote sensing and related fields.
|
||||
|
||||
The tutorials gives insight into how transformations are set up using the
|
||||
"PROJ language" as well as introduce most of the command line applications
|
||||
packaged with PROJ. In the tutorial properties of several common projections
|
||||
and transformations are investigated.
|
||||
|
||||
The tutorial requires a working installation of PROJ. Consult the
|
||||
:ref:`chapter on installing PROJ <install>`.
|
||||
|
||||
How to fill out the PROJ tutorial exercises
|
||||
-------------------------------------------
|
||||
|
||||
All the exercises are made as :program:`gie` tests where one or more inputs are
|
||||
missing. Replace occurrences of ``<your answer here>`` with the relevant input.
|
||||
Below is an annotated example of a complete :program:`gie` test. Your objective is to fill
|
||||
out the exercises from 1 and onwards in a similar fashion.
|
||||
|
||||
Below is a simple exercise before the answer has been filled in::
|
||||
|
||||
1. Set up an operation that returns the input it is given
|
||||
-------------------------------------------------------------------------------
|
||||
operation <your answer here>
|
||||
tolerance 10 mm
|
||||
|
||||
accept 12.3 45.6
|
||||
expect 12.3 45.6
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
An annotated answer could look like this::
|
||||
|
||||
<gie>
|
||||
operation +proj=latlon # The latlon "projection" returns the same output as
|
||||
# given in the input
|
||||
tolerance 10 mm
|
||||
|
||||
accept 12.3 45.6
|
||||
expect 12.3 45.6
|
||||
</gie>
|
||||
|
||||
The :program:`gie` application can be used to check if the exercise has been answered
|
||||
correctly::
|
||||
|
||||
gie exercises\<exercise_name>.gie
|
||||
|
||||
If all answers are correct :program:`gie` will return output similar to::
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Reading file 'exercises\instructions.md'
|
||||
-------------------------------------------------------------------------------
|
||||
total: 1 tests succeeded, 0 tests skipped, 0 tests failed.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
If incorrect, :program:`gie` will output something like::
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Reading file 'exercises\instructions.md'
|
||||
-----
|
||||
FAILURE in instructions.md(48):
|
||||
expected: 12.3 45.6
|
||||
got: 1369229.736757265171 5685937.873489554040
|
||||
deviation: 999999999.999000 mm, expected: 10.000000 mm
|
||||
-------------------------------------------------------------------------------
|
||||
total: 0 tests succeeded, 0 tests skipped, 1 tests FAILED!
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Where the number of failing exercises (or tests in :program:`gie` terminology)
|
||||
is given, as well as the line number of the failing test (in parenthesis after
|
||||
the file name).
|
||||
|
||||
Exercises
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
exercises/projections1
|
||||
exercises/projections2
|
||||
exercises/ellipsoids
|
||||
exercises/gridshift
|
||||
exercises/helmert
|
||||
exercises/conversions
|
||||
exercises/pipelines
|
||||
exercises/projections3
|
||||
answers
|
||||
@@ -0,0 +1,165 @@
|
||||
###############################################################################
|
||||
|
||||
Exercise: Geodesics and planar approximations using PROJ and GEOD
|
||||
|
||||
Thomas Knudsen, thokn@sdfe.dk, 2019-05-08
|
||||
|
||||
The PROJ system supports computations with geodesics [0], through API calls or
|
||||
through the "geod" command line interface [1]. The GIE test authoring tool does,
|
||||
however, not directly support geodesics, so this exercise will proceed mostly
|
||||
by having you copy sample commands from the text onto the command line, and
|
||||
copying results from the command line back into this file.
|
||||
|
||||
[0] https://proj.org/geodesic.html
|
||||
[1] https://proj.org/apps/geod.html
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
1. Objective
|
||||
------------------------------------------------------------------------------
|
||||
The objective of this exercise is to investigate how well a straight line in
|
||||
a projected plane approximates the geodesic between the same end points.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
2. The geodesic
|
||||
------------------------------------------------------------------------------
|
||||
The geodesic we will consider runs from Helsinki to Tallinn, using the
|
||||
coordinates from the LCC exercise:
|
||||
|
||||
Helsinki 60.171 N 24.938 E
|
||||
Tallinn 59.437 N 24.745 E
|
||||
|
||||
So to save some typing, let's define some environment variables:
|
||||
|
||||
set HEL=60.171 24.938
|
||||
set TAL=59.437 24.745
|
||||
|
||||
(i.e. mark, copy, and paste these lines into the command prompt)
|
||||
|
||||
First, we want to solve the "inverse geodetic problem" for the geodesic,
|
||||
i.e. finding the azimuth and distance between the two points:
|
||||
|
||||
echo %HEL% %TAL% | geod -I +ellps=GRS80
|
||||
|
||||
where the "-I" option indicates "the inverse geodetic problem".
|
||||
NOTE: This is Windows syntax - Unix users use $HEL, etc.
|
||||
|
||||
geod replies with these 3 numbers:
|
||||
|
||||
-172d22'12.772" 7d27'46.693" 82488.500
|
||||
|
||||
The first is the forward azimuth from Helsinki to Tallinn, the second is the
|
||||
return azimuth, while the third is the distance in meters.
|
||||
|
||||
We would actually rather have the azimuths in fractional degrees, so we provide
|
||||
an explicit output format, using the -f option to geod:
|
||||
|
||||
echo %HEL% %TAL% | geod -I -f "%.12f" +ellps=GRS80
|
||||
|
||||
getting us:
|
||||
|
||||
-172.370214337896 7.462970382137 82488.500
|
||||
|
||||
We assert that the planar approximation is worst at the midpoint of the
|
||||
geodesic, i.e. (82488.5 m) / 2 = 41244.25 m, from Helsinki. So now, we
|
||||
want to find the coordinates of this point, by solving the "direct geodetic
|
||||
problem":
|
||||
|
||||
echo %HEL% -172.370214337896 41244.25 | geod -f "%.12f" +ellps=GRS80
|
||||
|
||||
resulting in:
|
||||
|
||||
59.804045696236 24.840439590098 7.545306054713
|
||||
|
||||
i.e. the latitude, the longitude, and the return azimuth of the mid point
|
||||
of the geodesic.
|
||||
|
||||
Now, for convenience, define this environment variable:
|
||||
|
||||
set MID=59.804045696236 24.840439590098
|
||||
|
||||
NOTE: You can save a bit of manual copying by capturing the geod output into
|
||||
the clipboard, using the "clip" command, i.e. by appending
|
||||
|
||||
| clip
|
||||
|
||||
to the geod command above.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3. The planar approximation
|
||||
------------------------------------------------------------------------------
|
||||
We will be working on ETRS89/UTM35 coordinates, so first define an environment
|
||||
variable, to save some typing:
|
||||
|
||||
set utm35=proj -rs +proj=utm +zone=35 +ellps=GRS80
|
||||
|
||||
NOTE: The -rs option switches the proj coordinate i/o order to latitude/longitude
|
||||
and northing/easting, respectively. We do this to comply with the expected order
|
||||
for the geod program.
|
||||
|
||||
Now, find the UTM coordinates of the two end points:
|
||||
|
||||
echo %HEL% | %utm35%
|
||||
echo %TAL% | %utm35%
|
||||
|
||||
Type the two projected coordinate tuples here:
|
||||
|
||||
Helsinki, UTM: <your result here>
|
||||
Tallinn, UTM: <your result here>
|
||||
|
||||
Compute the mean of the northings, and the mean of the eastings, to obtain the
|
||||
planar approximation of the mid point
|
||||
|
||||
NOTE: you can use python as a makeshift command line calculator by saying:
|
||||
|
||||
python -c print((4+8)/2)
|
||||
|
||||
Now, compute the geographical coordinates corresponding to the UTM mid point:
|
||||
|
||||
echo <your northing your easting> | %utm35% -f "%.12f" -I
|
||||
|
||||
(note the -I option for doing the inverse projection)
|
||||
|
||||
For convenience define:
|
||||
|
||||
set MID_APPROX=<your result here>
|
||||
|
||||
Finally, compute the distance between the geodesic mid point and its planar
|
||||
approximation, by stating it as another case of the inverse geodetic problem:
|
||||
|
||||
echo %MID% %MID_APPROX% | geod -I +ellps=GRS80
|
||||
|
||||
resulting in:
|
||||
|
||||
107d0'16.673" -72d59'43.193" 2.527
|
||||
|
||||
i.e. a deviation of 2.5 m over a stretch of about 85 km.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
4. Suggested meditations
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Consider these aspects:
|
||||
|
||||
1. Given that geod is available, fast, and reliable - is it really worth the
|
||||
effort doing approximate calculations in the projected plane?
|
||||
|
||||
2. geod includes functionality for computing intermediate points along a
|
||||
geodesic. Check the manual ([1] above), especially the description of the
|
||||
"n_S" option, and try to compute the geodesic mid point directly, by
|
||||
setting n_S=2.
|
||||
|
||||
3. One should actually expect the result of meditation 2 above to be slightly
|
||||
superior to the result obtained in the exercise. Why?
|
||||
|
||||
4. While gie does not directly support tests of geodesic computations, a
|
||||
number of the partial tasks above could evidently be stated as gie tests.
|
||||
Try to do that in the <gie>/</gie> section below
|
||||
|
||||
###############################################################################
|
||||
<gie>
|
||||
|
||||
</gie>
|
||||
@@ -0,0 +1,179 @@
|
||||
.. _geodesics_tutorial:
|
||||
|
||||
Geodesics and planar approximations using PROJ and geod
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The PROJ system supports computations with :ref:`geodesic`, through API calls or
|
||||
through the :ref:`geod` command line interface. This exercise will proceed mostly
|
||||
by having you copy sample commands from the text onto the command line, and
|
||||
noting the results.
|
||||
|
||||
The tutorial is written with the Windows command line in mind but it should
|
||||
be straight forward to use it on Unix-based systems as well.
|
||||
|
||||
.. hint::
|
||||
|
||||
Users of Unix-based systems can replace ``set`` with ``export`` and ``%VAR%``
|
||||
with ``$VAR`` to follow the tutorial.
|
||||
|
||||
1. Objective
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The objective of this exercise is to investigate how well a straight line in
|
||||
a projected plane approximates the geodesic between the same end points.
|
||||
|
||||
|
||||
2. The geodesic
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The geodesic we will consider runs from Helsinki to Tallinn, using the
|
||||
following coordinates:
|
||||
|
||||
.. code-block::
|
||||
|
||||
Helsinki 60.171 N 24.938 E
|
||||
Tallinn 59.437 N 24.745 E
|
||||
|
||||
So to save some typing, let's define some environment variables. On Windows:
|
||||
|
||||
.. code-block::
|
||||
|
||||
set HEL="60.171 24.938"
|
||||
set TAL="59.437 24.745"
|
||||
|
||||
.. code-block::
|
||||
|
||||
export HEL="60.171 24.938"
|
||||
export TAL="59.437 24.745"
|
||||
|
||||
(i.e. mark, copy, and paste these lines into the command prompt)
|
||||
|
||||
First, we want to solve the "inverse geodetic problem" for the geodesic,
|
||||
i.e. finding the azimuth and distance between the two points::
|
||||
|
||||
echo %HEL% %TAL% | geod -I +ellps=GRS80
|
||||
|
||||
where the ``-I`` option indicates "the inverse geodetic problem".
|
||||
|
||||
:program:`geod` replies with these 3 numbers::
|
||||
|
||||
-172d22'12.772" 7d27'46.693" 82488.500
|
||||
|
||||
The first is the forward azimuth from Helsinki to Tallinn, the second is the
|
||||
return azimuth, while the third is the distance in meters.
|
||||
|
||||
We would actually rather have the azimuths in fractional degrees, so we provide
|
||||
an explicit output format, using the ``-f`` option to geod::
|
||||
|
||||
echo %HEL% %TAL% | geod -I -f "%.12f" +ellps=GRS80
|
||||
|
||||
getting us::
|
||||
|
||||
-172.370214337896 7.462970382137 82488.500
|
||||
|
||||
We assert that the planar approximation is worst at the midpoint of the
|
||||
geodesic, i.e. ``(82488.5 m) / 2 = 41244.25 m``, from Helsinki. So now, we
|
||||
want to find the coordinates of this point, by solving the "direct geodetic
|
||||
problem"::
|
||||
|
||||
echo %HEL% -172.370214337896 41244.25 | geod -f "%.12f" +ellps=GRS80
|
||||
|
||||
resulting in::
|
||||
|
||||
59.804045696236 24.840439590098 7.545306054713
|
||||
|
||||
i.e. the latitude, the longitude, and the return azimuth of the mid point
|
||||
of the geodesic.
|
||||
|
||||
Now, for convenience, define this environment variable::
|
||||
|
||||
set MID="59.804045696236 24.840439590098"
|
||||
|
||||
.. note::
|
||||
|
||||
You can save a bit of manual copying by capturing the geod output into
|
||||
the clipboard, using the "clip" command on Windows, i.e. by appending ``| clip``
|
||||
|
||||
to the ``geod`` command above.
|
||||
|
||||
|
||||
1. The planar approximation
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
We will be working on ETRS89/UTM35 coordinates, so first define an environment
|
||||
variable, to save some typing::
|
||||
|
||||
set utm35=proj -rs +proj=utm +zone=35 +ellps=GRS80
|
||||
|
||||
.. note::
|
||||
The ``-rs`` option switches the proj coordinate i/o order to latitude/longitude
|
||||
and northing/easting, respectively. We do this to comply with the expected order
|
||||
for the geod program.
|
||||
|
||||
Now, find the UTM coordinates of the two end points::
|
||||
|
||||
echo %HEL% | %utm35%
|
||||
echo %TAL% | %utm35%
|
||||
|
||||
Note your results and compute the mean of the northings, and the mean of the eastings,
|
||||
to obtain the planar approximation of the mid point
|
||||
|
||||
.. hint::
|
||||
you can use python as a makeshift command line calculator by saying::
|
||||
|
||||
python -c print((4+8)/2)
|
||||
|
||||
Now, compute the geographical coordinates corresponding to the UTM mid point::
|
||||
|
||||
echo <your northing your easting> | %utm35% -f "%.12f" -I
|
||||
|
||||
(note the -I option for doing the inverse projection)
|
||||
|
||||
For convenience define::
|
||||
|
||||
set MID_APPROX=<your result here>
|
||||
|
||||
Finally, compute the distance between the geodesic mid point and its planar
|
||||
approximation, by stating it as another case of the inverse geodetic problem::
|
||||
|
||||
echo %MID% %MID_APPROX% | geod -I +ellps=GRS80
|
||||
|
||||
resulting in::
|
||||
|
||||
107d0'16.673" -72d59'43.193" 2.527
|
||||
|
||||
i.e. a deviation of 2.5 m over a stretch of about 85 km.
|
||||
|
||||
|
||||
4. Suggested meditations
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Consider these aspects:
|
||||
|
||||
#. Given that geod is available, fast, and reliable - is it really worth the
|
||||
effort doing approximate calculations in the projected plane?
|
||||
|
||||
#. :program:`geod` includes functionality for computing intermediate points along a
|
||||
geodesic. Check the manual, especially the description of the
|
||||
``n_S`` option, and try to compute the geodesic mid point directly, by
|
||||
setting ``n_S=2``.
|
||||
|
||||
#. One should actually expect the result of meditation 2 above to be slightly
|
||||
superior to the result obtained in the exercise. Why?
|
||||
|
||||
|
||||
Answers
|
||||
------------
|
||||
|
||||
.. code-block::
|
||||
|
||||
Helsinki, UTM: 6672241.54 385592.95
|
||||
Tallinn, UTM: 6590881.40 372106.37
|
||||
Mid point, UTM: 6631561.47 378849.66
|
||||
Mid point, GEO: 59.804039062602 24.840482644156
|
||||
|
||||
Meditations:
|
||||
|
||||
#. Probably not
|
||||
#. ``geod +lat_1=60.171 +lon_1=24.938 +lat_2=59.437 +lon_2=24.745 +n_S=2 +ellps=GRS80 -f "%.12f"``
|
||||
#. Avoids a bit of truncation of the azimuth, and *may* use a slightly superior algorithm (check the code!)
|
||||
@@ -0,0 +1,12 @@
|
||||
.. _tutorials:
|
||||
|
||||
================================================================================
|
||||
Tutorials
|
||||
================================================================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
EUREF2019/index
|
||||
geodesics
|
||||
|
||||
@@ -38,6 +38,8 @@ documenting the individual :doc:`projections<../operations/projections/index>`.
|
||||
|
||||
In the sections below most of the parameters are explained in details.
|
||||
|
||||
.. _projection_units:
|
||||
|
||||
Units
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
@@ -64,6 +66,32 @@ Scaling of output units can be done by applying the ``+k_0`` argument. The
|
||||
returned coordinates are scaled by the value assigned with the ``+k_0``
|
||||
parameter.
|
||||
|
||||
Input units for parameters that can be understood to be either decimal degrees or
|
||||
radians are interpreted to be decimal degrees by convention.
|
||||
|
||||
Explict specification of input units can be accomplished by adding the appropriate
|
||||
suffix to input values.
|
||||
|
||||
|
||||
+----------------+---------------------+
|
||||
| Suffix | Unit |
|
||||
+================+=====================+
|
||||
| d | Decimal degrees |
|
||||
+----------------+ +
|
||||
| D | |
|
||||
+----------------+ +
|
||||
| ° | |
|
||||
+----------------+---------------------+
|
||||
| r | Radians |
|
||||
+----------------+ +
|
||||
| R | |
|
||||
+----------------+---------------------+
|
||||
|
||||
Example of use. The longitude of the central meridian ``+lon_0=90``, can also be expressed more explictly
|
||||
with units of decimal degrees as ``+lon_0=90d`` or in radian
|
||||
units as ``+lon_0=1.5708r`` (approximately).
|
||||
|
||||
|
||||
False Easting/Northing
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
@@ -72,16 +100,22 @@ Virtually all coordinate systems allow for the presence of a false easting
|
||||
meters even if the coordinate system is some other units. Some coordinate
|
||||
systems (such as UTM) have implicit false easting and northing values.
|
||||
|
||||
.. _longitude_wrapping:
|
||||
|
||||
Longitude Wrapping
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
By default PROJ wraps output longitudes in the range -180 to 180. The ``+over``
|
||||
switch can be used to disable the default wrapping which is done at a low level
|
||||
in ``pj_inv()``. This is particularly useful with projections like the
|
||||
:doc:`equidistant cylindrical<../operations/projections/eqc>`
|
||||
where it would be desirable for X values past -20000000 (roughly) to continue
|
||||
:ref:`eqc` or :ref:`merc`
|
||||
where it could be desirable for X values past -20000000 (roughly) to continue
|
||||
past -180 instead of wrapping to +180.
|
||||
|
||||
Note however that for most projections where the 180 meridian does not project
|
||||
to a straight line, ``+over`` will have no effect or will not lead to expected
|
||||
results.
|
||||
|
||||
The ``+lon_wrap`` option can be used to provide an alternative means of doing
|
||||
longitude wrapping within ``pj_transform()``. The argument to this option is a
|
||||
center longitude. So ``+lon_wrap=180`` means wrap longitudes in the range 0 to
|
||||
@@ -159,5 +193,3 @@ They can be combined in +axis in forms like:
|
||||
|
||||
The ``+axis`` argument does not work with the :program:`proj` command line
|
||||
utility.
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ geodetic transformations of varying complexity can be performed.
|
||||
In PROJ, two frameworks for geodetic transformations exists, the
|
||||
*PROJ 4.x/5.x* / :program:`cs2cs` / :c:func:`pj_transform`
|
||||
framework and the *transformation pipelines* framework. The first is the original,
|
||||
and limited, framework for doing geodetic transforms in PROJ The latter is a
|
||||
and limited, framework for doing geodetic transforms in PROJ. The latter is a
|
||||
newer addition that aims to be a more complete transformation framework. Both are
|
||||
described in the sections below. Large portions of the text are based on
|
||||
:cite:`EversKnudsen2017`.
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
.. _users:
|
||||
|
||||
================================================================================
|
||||
Software and organizations using or contributing to PROJ
|
||||
================================================================================
|
||||
|
||||
Free and open source software
|
||||
-----------------------------
|
||||
|
||||
- `GDAL <https://gdal.org>`_ Translator library for raster and vector geospatial data formats, used by > 100 other software
|
||||
- `GRASS GIS <http://grass.osgeo.org>`_ A raster/vector open source GIS
|
||||
- `libgeotiff <https://github.com/OSGeo/libgeotiff>`_ Library to read/write GeoTIFF keys
|
||||
- `MapServer <http://mapserver.org/index.html>`_ A popular web mapping application
|
||||
- `PDAL <https://pdal.io>`_ Point Cloud Data Abstraction Library
|
||||
- `PostGIS <http://www.postgis.net>`_ Spatial database extender for PostgreSQL
|
||||
- `QGIS <http://www.qgis.org>`_ A cross platform desktop GIS.
|
||||
- `QField <http://qfield.org>`_ Mobile data collection app for Android, iOS and Windows.
|
||||
- `R <http://www.r-project.org>`_ A free software environment for statistical computing and graphics
|
||||
- `mundipy <https://docs.mundi.ai>`_ A Python framework for spatial data analysis
|
||||
|
||||
PROJ bindings in other languages
|
||||
--------------------------------
|
||||
|
||||
See :ref:`bindings`
|
||||
|
||||
|
||||
Proprietary licensed software
|
||||
-----------------------------
|
||||
|
||||
- `FME <http://www.safe.com>`_ A GIS translator package. Includes a PROJ based transformer.
|
||||
- `Avenza Maps <https://www.avenzamaps.com>`_ Top mobile mapping app for offline navigation and data collection.
|
||||
- `Bunting Labs <https://buntinglabs.com/>`_ No-code GIS infrastructure
|
||||
|
||||
Geodetic organizations
|
||||
----------------------
|
||||
|
||||
- `Agency for Data Supply and Infrastructure of Denmark (SDFI) <https://eng.sdfi.dk/>`_
|
||||
- `Land Information New Zealand (LINZ) <https://www.linz.govt.nz/>`_
|
||||
- `National Land Survey of Finland (NLS) <https://www.maanmittauslaitos.fi/en>`_
|
||||
- `National Land Survey of Iceland (NLS) <https://www.lmi.is/>`_
|
||||
- `Netherlands Partnership Geodetic Infrastructure (NSGI) <https://www.nsgi.nl/>`_
|
||||
|
||||
* `Netherlands' Cadastre, Land Registry and Mapping Agency (Kadaster) <https://www.kadaster.nl/about-us>`_
|
||||
* `Directorate-General for Public Works and Water Management (Rijkswaterstaat) <https://www.rijkswaterstaat.nl/en>`_
|
||||
* `Hydrographic Service of the Royal Netherlands Navy <https://english.defensie.nl/organisation/navy/navy-units/hydrographic-service/>`_
|
||||
|
||||
- `Nordic Geodetic commission (NKG) <https://www.nordicgeodeticcommission.com/>`_
|
||||
- `Norwegian Mapping Authority (Kartverket) <https://kartverket.no/en>`_
|
||||
- `Swedish mapping, cadastral and land registration authority (Lantmäteriet) <https://www.lantmateriet.se/>`_
|
||||
- `USGS <https://www.usgs.gov/>`_: PROJ initial author, Gerald E. Evenden, worked at USGS
|
||||
|
||||
Public organizations
|
||||
--------------------
|
||||
|
||||
- `Istituto Nazioanle di Astrofisica (INAF) <https://www.inaf.it/>`_ : `Planetary Mapping and GIS Laboratory <https://gislab.iaps.inaf.it/>`_
|
||||
- `Ecole Nationale des Sciences Géographiques (ENSG-géomatique) <https://www.ensg.eu/>`_ : French geomatic school which depends on the National Institute of Geographic and Forest Information (IGN)
|
||||
|
||||
(add yourself here if you are a direct user of PROJ API or utilities)
|
||||
|
||||
Private organizations
|
||||
---------------------
|
||||
|
||||
(add yourself here if you are a direct user of PROJ API or utilities)
|
||||
|
||||
Sponsors
|
||||
--------
|
||||
|
||||
PROJ development, as an upstream dependency of GDAL, benefits from funding
|
||||
brought by its `sponsors <https://gdal.org/sponsors/>`_
|
||||
@@ -1376,6 +1376,23 @@ class PROJ_GCC_DLL Conversion : public SingleOperation {
|
||||
PROJ_DLL static ConversionNNPtr
|
||||
createGeographicGeocentric(const util::PropertyMap &properties);
|
||||
|
||||
PROJ_DLL static ConversionNNPtr
|
||||
createGeographic2DOffsets(const util::PropertyMap &properties,
|
||||
const common::Angle &offsetLat,
|
||||
const common::Angle &offsetLon);
|
||||
|
||||
PROJ_DLL static ConversionNNPtr createGeographic3DOffsets(
|
||||
const util::PropertyMap &properties, const common::Angle &offsetLat,
|
||||
const common::Angle &offsetLon, const common::Length &offsetHeight);
|
||||
|
||||
PROJ_DLL static ConversionNNPtr createGeographic2DWithHeightOffsets(
|
||||
const util::PropertyMap &properties, const common::Angle &offsetLat,
|
||||
const common::Angle &offsetLon, const common::Length &offsetHeight);
|
||||
|
||||
PROJ_DLL static ConversionNNPtr
|
||||
createVerticalOffset(const util::PropertyMap &properties,
|
||||
const common::Length &offsetHeight);
|
||||
|
||||
PROJ_DLL ConversionPtr convertToOtherMethod(int targetEPSGCode) const;
|
||||
|
||||
PROJ_PRIVATE :
|
||||
@@ -1617,6 +1634,9 @@ class PROJ_GCC_DLL Transformation : public SingleOperation {
|
||||
demoteTo2D(const std::string &newName,
|
||||
const io::DatabaseContextPtr &dbContext) const;
|
||||
|
||||
PROJ_INTERNAL static bool
|
||||
isGeographic3DToGravityRelatedHeight(const OperationMethodNNPtr &method,
|
||||
bool allowInverse);
|
||||
//! @endcond
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1273,6 +1273,10 @@ class PROJ_GCC_DLL DerivedProjectedCRS final : public DerivedCRS {
|
||||
const operation::ConversionNNPtr &derivingConversionIn,
|
||||
const cs::CoordinateSystemNNPtr &csIn);
|
||||
|
||||
PROJ_DLL DerivedProjectedCRSNNPtr
|
||||
demoteTo2D(const std::string &newName,
|
||||
const io::DatabaseContextPtr &dbContext) const;
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
|
||||
const override; // throw(io::FormattingException)
|
||||
|
||||
@@ -136,6 +136,7 @@ osgeo::proj::crs::DerivedGeographicCRS::demoteTo2D(std::string const&, std::shar
|
||||
osgeo::proj::crs::DerivedGeographicCRS::~DerivedGeographicCRS()
|
||||
osgeo::proj::crs::DerivedProjectedCRS::baseCRS() const
|
||||
osgeo::proj::crs::DerivedProjectedCRS::create(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::ProjectedCRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::Conversion> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::cs::CoordinateSystem> > const&)
|
||||
osgeo::proj::crs::DerivedProjectedCRS::demoteTo2D(std::string const&, std::shared_ptr<osgeo::proj::io::DatabaseContext> const&) const
|
||||
osgeo::proj::crs::DerivedProjectedCRS::~DerivedProjectedCRS()
|
||||
osgeo::proj::crs::DerivedVerticalCRS::baseCRS() const
|
||||
osgeo::proj::crs::DerivedVerticalCRS::create(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::VerticalCRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::Conversion> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::cs::VerticalCS> > const&)
|
||||
@@ -543,6 +544,9 @@ osgeo::proj::operation::Conversion::createEquidistantCylindrical(osgeo::proj::ut
|
||||
osgeo::proj::operation::Conversion::createEquidistantCylindricalSpherical(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createGall(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createGaussSchreiberTransverseMercator(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Scale const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createGeographic2DOffsets(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&)
|
||||
osgeo::proj::operation::Conversion::createGeographic2DWithHeightOffsets(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createGeographic3DOffsets(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createGeographicGeocentric(osgeo::proj::util::PropertyMap const&)
|
||||
osgeo::proj::operation::Conversion::createGeostationarySatelliteSweepX(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createGeostationarySatelliteSweepY(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
@@ -590,6 +594,7 @@ osgeo::proj::operation::Conversion::createTunisiaMappingGrid(osgeo::proj::util::
|
||||
osgeo::proj::operation::Conversion::createTwoPointEquidistant(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createUTM(osgeo::proj::util::PropertyMap const&, int, bool)
|
||||
osgeo::proj::operation::Conversion::createVanDerGrinten(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createVerticalOffset(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createVerticalPerspective(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createWagnerIII(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
osgeo::proj::operation::Conversion::createWagnerII(osgeo::proj::util::PropertyMap const&, osgeo::proj::common::Angle const&, osgeo::proj::common::Length const&, osgeo::proj::common::Length const&)
|
||||
|
||||
+36
-21
@@ -91,8 +91,9 @@ static void logger(void *data, int level, const char *msg);
|
||||
static void print(PJ_LOG_LEVEL log_level, const char *fmt, ...);
|
||||
|
||||
/* Prototypes from functions in this file */
|
||||
char *column (char *buf, int n);
|
||||
PJ_COORD parse_input_line (char *buf, int *columns, double fixed_height, double fixed_time);
|
||||
static const char *column (const char *buf, int n);
|
||||
static char *column (char *buf, int n);
|
||||
PJ_COORD parse_input_line (const char *buf, int *columns, double fixed_height, double fixed_time);
|
||||
|
||||
|
||||
static const char usage[] = {
|
||||
@@ -203,9 +204,6 @@ int main(int argc, char **argv) {
|
||||
OPTARGS *o;
|
||||
char blank_comment[] = "";
|
||||
char whitespace[] = " ";
|
||||
char *comment;
|
||||
char *comment_delimiter;
|
||||
char *buf;
|
||||
int i, nfields = 4, skip_lines = 0, verbose;
|
||||
double fixed_z = HUGE_VAL, fixed_time = HUGE_VAL;
|
||||
int decimals_angles = 10;
|
||||
@@ -386,7 +384,8 @@ int main(int argc, char **argv) {
|
||||
direction = PJ_FWD;
|
||||
|
||||
/* Allocate input buffer */
|
||||
buf = static_cast<char*>(calloc (1, 10000));
|
||||
constexpr int BUFFER_SIZE = 10000;
|
||||
char* buf = static_cast<char*>(calloc (1, BUFFER_SIZE));
|
||||
if (nullptr==buf) {
|
||||
print (PJ_LOG_ERROR, "%s: Out of memory", o->progname);
|
||||
proj_destroy (P);
|
||||
@@ -398,30 +397,43 @@ int main(int argc, char **argv) {
|
||||
|
||||
|
||||
/* Loop over all records of all input files */
|
||||
int previous_index = -1;
|
||||
while (opt_input_loop (o, optargs_file_format_text)) {
|
||||
int err;
|
||||
void *ret = fgets (buf, 10000, o->input);
|
||||
char *c = column (buf, 1);
|
||||
char *bufptr = fgets (buf, BUFFER_SIZE - 1, o->input);
|
||||
opt_eof_handler (o);
|
||||
if (nullptr==ret) {
|
||||
if (nullptr==bufptr) {
|
||||
print (PJ_LOG_ERROR, "Read error in record %d", (int) o->record_index);
|
||||
continue;
|
||||
}
|
||||
point = parse_input_line (buf, columns_xyzt, fixed_z, fixed_time);
|
||||
|
||||
const bool bFirstLine = o->input_index != previous_index;
|
||||
previous_index = o->input_index;
|
||||
if( bFirstLine &&
|
||||
static_cast<uint8_t>(bufptr[0]) == 0xEF &&
|
||||
static_cast<uint8_t>(bufptr[1]) == 0xBB &&
|
||||
static_cast<uint8_t>(bufptr[2]) == 0xBF )
|
||||
{
|
||||
// Skip UTF-8 Byte Order Marker (BOM)
|
||||
bufptr += 3;
|
||||
}
|
||||
|
||||
point = parse_input_line (bufptr, columns_xyzt, fixed_z, fixed_time);
|
||||
if (skip_lines > 0) {
|
||||
skip_lines--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if it's a comment or blank line, we reflect it */
|
||||
const char *c = column (bufptr, 1);
|
||||
if (c && ((*c=='\0') || (*c=='#'))) {
|
||||
fprintf (fout, "%s", buf);
|
||||
fprintf (fout, "%s", bufptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (HUGE_VAL==point.xyzt.x) {
|
||||
/* otherwise, it must be a syntax error */
|
||||
print (PJ_LOG_NONE, "# Record %d UNREADABLE: %s", (int) o->record_index, buf);
|
||||
print (PJ_LOG_NONE, "# Record %d UNREADABLE: %s", (int) o->record_index, bufptr);
|
||||
print (PJ_LOG_ERROR, "%s: Could not parse file '%s' line %d", o->progname, opt_filename (o), opt_record (o));
|
||||
continue;
|
||||
}
|
||||
@@ -437,27 +449,27 @@ int main(int argc, char **argv) {
|
||||
if (HUGE_VAL==point.xyzt.x) {
|
||||
/* transformation error */
|
||||
print (PJ_LOG_NONE, "# Record %d TRANSFORMATION ERROR: %s (%s)",
|
||||
(int) o->record_index, buf, proj_errno_string (proj_errno(P)));
|
||||
(int) o->record_index, bufptr, proj_errno_string (proj_errno(P)));
|
||||
proj_errno_restore (P, err);
|
||||
continue;
|
||||
}
|
||||
proj_errno_restore (P, err);
|
||||
|
||||
/* handle comment string */
|
||||
comment = column(buf, nfields+1);
|
||||
char* comment = column(bufptr, nfields+1);
|
||||
if (opt_given(o, "c")) {
|
||||
/* what number is the last coordinate column in the input data? */
|
||||
int colmax = 0;
|
||||
for (i=0; i<4; i++)
|
||||
colmax = MAX(colmax, columns_xyzt[i]);
|
||||
comment = column(buf, colmax+1);
|
||||
comment = column(bufptr, colmax+1);
|
||||
}
|
||||
/* remove the line feed from comment, as logger() above, invoked
|
||||
by print() below (output), will add one */
|
||||
size_t len = strlen(comment);
|
||||
if (len >= 1)
|
||||
comment[len - 1] = '\0';
|
||||
comment_delimiter = *comment ? whitespace : blank_comment;
|
||||
const char* comment_delimiter = *comment ? whitespace : blank_comment;
|
||||
|
||||
/* Time to print the result */
|
||||
/* use same arguments to printf format string for both radians and
|
||||
@@ -500,7 +512,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
|
||||
/* return a pointer to the n'th column of buf */
|
||||
char *column (char *buf, int n) {
|
||||
static const char *column (const char *buf, int n) {
|
||||
int i;
|
||||
if (n <= 0)
|
||||
return buf;
|
||||
@@ -515,19 +527,22 @@ char *column (char *buf, int n) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *column (char *buf, int n) {
|
||||
return const_cast<char*>(column(const_cast<const char*>(buf), n));
|
||||
}
|
||||
|
||||
/* column to double */
|
||||
static double cold (char *args, int col) {
|
||||
static double cold (const char *args, int col) {
|
||||
char *endp;
|
||||
char *target;
|
||||
double d;
|
||||
target = column (args, col);
|
||||
const char* target = column (args, col);
|
||||
d = proj_strtod (target, &endp);
|
||||
if (endp==target)
|
||||
return HUGE_VAL;
|
||||
return d;
|
||||
}
|
||||
|
||||
PJ_COORD parse_input_line (char *buf, int *columns, double fixed_height, double fixed_time) {
|
||||
PJ_COORD parse_input_line (const char *buf, int *columns, double fixed_height, double fixed_time) {
|
||||
PJ_COORD err = proj_coord (HUGE_VAL, HUGE_VAL, HUGE_VAL, HUGE_VAL);
|
||||
PJ_COORD result = err;
|
||||
int prev_errno = errno;
|
||||
|
||||
+66
-2
@@ -99,13 +99,25 @@ static void process(FILE *fid)
|
||||
{
|
||||
char line[MAX_LINE + 3], *s, pline[40];
|
||||
PJ_UV data;
|
||||
bool bFirstLine = true;
|
||||
|
||||
for (;;) {
|
||||
for (;; bFirstLine = false ) {
|
||||
double z;
|
||||
|
||||
++emess_dat.File_line;
|
||||
if (!(s = fgets(line, MAX_LINE, fid)))
|
||||
break;
|
||||
|
||||
if( bFirstLine &&
|
||||
static_cast<uint8_t>(s[0]) == 0xEF &&
|
||||
static_cast<uint8_t>(s[1]) == 0xBB &&
|
||||
static_cast<uint8_t>(s[2]) == 0xBF )
|
||||
{
|
||||
// Skip UTF-8 Byte Order Marker (BOM)
|
||||
s += 3;
|
||||
}
|
||||
const char* pszLineAfterBOM = s;
|
||||
|
||||
if (!strchr(s, '\n')) { /* overlong line */
|
||||
int c;
|
||||
(void)strcat(s, "\n");
|
||||
@@ -151,7 +163,7 @@ static void process(FILE *fid)
|
||||
char temp;
|
||||
temp = *s;
|
||||
*s = '\0';
|
||||
(void)fputs(line, stdout);
|
||||
(void)fputs(pszLineAfterBOM, stdout);
|
||||
*s = temp;
|
||||
putchar('\t');
|
||||
}
|
||||
@@ -332,6 +344,25 @@ static std::string get_geog_crs_proj_string_from_proj_crs(PJ *src,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static bool is3DCRS(const PJ* crs) {
|
||||
auto type = proj_get_type(crs);
|
||||
if( type == PJ_TYPE_COMPOUND_CRS )
|
||||
return true;
|
||||
if( type == PJ_TYPE_GEOGRAPHIC_3D_CRS )
|
||||
return true;
|
||||
if( type == PJ_TYPE_GEODETIC_CRS || type == PJ_TYPE_PROJECTED_CRS )
|
||||
{
|
||||
auto cs = proj_crs_get_coordinate_system(nullptr, crs);
|
||||
assert(cs);
|
||||
const bool ret = proj_cs_get_axis_count(nullptr, cs) == 3;
|
||||
proj_destroy(cs);
|
||||
return ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* main() */
|
||||
/************************************************************************/
|
||||
@@ -808,6 +839,39 @@ int main(int argc, char **argv) {
|
||||
proj_destroy(dst);
|
||||
dst = dst3D;
|
||||
}
|
||||
} else {
|
||||
// Auto-promote source/target CRS if it is specified by its name,
|
||||
// if it has a known 3D version of it and that the other CRS is 3D.
|
||||
// e.g cs2cs "WGS 84 + EGM96 height" "WGS 84"
|
||||
if (is3DCRS(dst) && !is3DCRS(src) &&
|
||||
proj_get_id_code(src, 0) != nullptr &&
|
||||
Identifier::isEquivalentName(fromStr.c_str(),
|
||||
proj_get_name(src))) {
|
||||
auto promoted = proj_crs_promote_to_3D(nullptr, nullptr, src);
|
||||
if (promoted)
|
||||
{
|
||||
if (proj_get_id_code(promoted, 0) != nullptr) {
|
||||
proj_destroy(src);
|
||||
src = promoted;
|
||||
} else {
|
||||
proj_destroy(promoted);
|
||||
}
|
||||
}
|
||||
} else if (is3DCRS(src) && !is3DCRS(dst) &&
|
||||
proj_get_id_code(dst, 0) != nullptr &&
|
||||
Identifier::isEquivalentName(toStr.c_str(),
|
||||
proj_get_name(dst))) {
|
||||
auto promoted = proj_crs_promote_to_3D(nullptr, nullptr, dst);
|
||||
if (promoted)
|
||||
{
|
||||
if (proj_get_id_code(promoted, 0) != nullptr) {
|
||||
proj_destroy(dst);
|
||||
dst = promoted;
|
||||
} else {
|
||||
proj_destroy(promoted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string authorityOption; /* keep this variable in this outer scope ! */
|
||||
|
||||
+41
-2
@@ -804,6 +804,20 @@ static void outputOperationSummary(
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static bool is3DCRS(const CRSPtr &crs) {
|
||||
if (dynamic_cast<CompoundCRS *>(crs.get()))
|
||||
return true;
|
||||
auto geodCRS = dynamic_cast<GeodeticCRS *>(crs.get());
|
||||
if (geodCRS)
|
||||
return geodCRS->coordinateSystem()->axisList().size() == 3U;
|
||||
auto projCRS = dynamic_cast<ProjectedCRS *>(crs.get());
|
||||
if (projCRS)
|
||||
return projCRS->coordinateSystem()->axisList().size() == 3U;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void outputOperations(
|
||||
DatabaseContextPtr dbContext, const std::string &sourceCRSStr,
|
||||
const std::string &targetCRSStr, const ExtentPtr &bboxFilter,
|
||||
@@ -825,7 +839,6 @@ static void outputOperations(
|
||||
std::cerr << "source CRS string is not a CRS" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
auto nnSourceCRS = NN_NO_CHECK(sourceCRS);
|
||||
|
||||
auto targetObj =
|
||||
buildObject(dbContext, targetCRSStr, "crs", "target CRS", false,
|
||||
@@ -836,8 +849,34 @@ static void outputOperations(
|
||||
std::cerr << "target CRS string is not a CRS" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
auto nnTargetCRS = NN_NO_CHECK(targetCRS);
|
||||
|
||||
if (dbContext && !promoteTo3D) {
|
||||
// Auto-promote source/target CRS if it is specified by its name,
|
||||
// if it has a known 3D version of it and that the other CRS is 3D.
|
||||
// e.g projinfo -s "WGS 84 + EGM96 height" -t "WGS 84"
|
||||
if (is3DCRS(targetCRS) && !is3DCRS(sourceCRS) &&
|
||||
!sourceCRS->identifiers().empty() &&
|
||||
Identifier::isEquivalentName(sourceCRSStr.c_str(),
|
||||
sourceCRS->nameStr().c_str())) {
|
||||
auto promoted =
|
||||
sourceCRS->promoteTo3D(std::string(), dbContext).as_nullable();
|
||||
if (!promoted->identifiers().empty()) {
|
||||
sourceCRS = promoted;
|
||||
}
|
||||
} else if (is3DCRS(sourceCRS) && !is3DCRS(targetCRS) &&
|
||||
!targetCRS->identifiers().empty() &&
|
||||
Identifier::isEquivalentName(targetCRSStr.c_str(),
|
||||
targetCRS->nameStr().c_str())) {
|
||||
auto promoted =
|
||||
targetCRS->promoteTo3D(std::string(), dbContext).as_nullable();
|
||||
if (!promoted->identifiers().empty()) {
|
||||
targetCRS = promoted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto nnSourceCRS = NN_NO_CHECK(sourceCRS);
|
||||
auto nnTargetCRS = NN_NO_CHECK(targetCRS);
|
||||
std::vector<CoordinateOperationNNPtr> list;
|
||||
size_t spatialCriterionPartialIntersectionResultCount = 0;
|
||||
bool spatialCriterionPartialIntersectionMoreRelevant = false;
|
||||
|
||||
+2
-1
@@ -2400,7 +2400,8 @@ GTiffHGridShiftSet::open(PJ_CONTEXT *ctx, std::unique_ptr<File> fp,
|
||||
return nullptr;
|
||||
}
|
||||
if (!unitLatShift.empty()) {
|
||||
if (unitLatShift == "arc-second") {
|
||||
if (unitLatShift == "arc-second" ||
|
||||
unitLatShift == "arc-seconds per year") {
|
||||
convFactorToRadian = ARC_SECOND_TO_RADIAN;
|
||||
} else if (unitLatShift == "radian") {
|
||||
convFactorToRadian = 1.0;
|
||||
|
||||
@@ -8825,6 +8825,7 @@ PJ *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ *obj) {
|
||||
pjNew->descr = "Set of coordinate operations";
|
||||
pjNew->left = obj->left;
|
||||
pjNew->right = obj->right;
|
||||
pjNew->over = obj->over;
|
||||
|
||||
for (const auto &alt : obj->alternativeCoordinateOperations) {
|
||||
auto co = dynamic_cast<const CoordinateOperation *>(
|
||||
@@ -8857,11 +8858,14 @@ PJ *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ *obj) {
|
||||
std::swap(maxxDst, maxyDst);
|
||||
}
|
||||
}
|
||||
auto pjNormalized =
|
||||
pj_obj_create(ctx, co->normalizeForVisualization());
|
||||
pjNormalized->over = alt.pj->over;
|
||||
pjNew->alternativeCoordinateOperations.emplace_back(
|
||||
alt.idxInOriginalList, minxSrc, minySrc, maxxSrc,
|
||||
maxySrc, minxDst, minyDst, maxxDst, maxyDst,
|
||||
pj_obj_create(ctx, co->normalizeForVisualization()),
|
||||
co->nameStr(), alt.accuracy, alt.isOffshore);
|
||||
pjNormalized, co->nameStr(), alt.accuracy,
|
||||
alt.isOffshore);
|
||||
}
|
||||
}
|
||||
return pjNew.release();
|
||||
@@ -8890,7 +8894,9 @@ PJ *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ *obj) {
|
||||
return nullptr;
|
||||
}
|
||||
try {
|
||||
return pj_obj_create(ctx, co->normalizeForVisualization());
|
||||
auto pjNormalized = pj_obj_create(ctx, co->normalizeForVisualization());
|
||||
pjNormalized->over = obj->over;
|
||||
return pjNormalized;
|
||||
} catch (const std::exception &e) {
|
||||
proj_log_debug(ctx, __FUNCTION__, e.what());
|
||||
return nullptr;
|
||||
|
||||
@@ -368,6 +368,16 @@ CRSNNPtr CRS::alterCSLinearUnit(const common::UnitOfMeasure &unit) const {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto derivedProjCRS = dynamic_cast<const DerivedProjectedCRS *>(this);
|
||||
if (derivedProjCRS) {
|
||||
return DerivedProjectedCRS::create(
|
||||
createPropertyMap(this), derivedProjCRS->baseCRS(),
|
||||
derivedProjCRS->derivingConversion(),
|
||||
derivedProjCRS->baseCRS()->coordinateSystem()->alterUnit(unit));
|
||||
}
|
||||
}
|
||||
|
||||
return NN_NO_CHECK(
|
||||
std::dynamic_pointer_cast<CRS>(shared_from_this().as_nullable()));
|
||||
}
|
||||
@@ -1260,6 +1270,23 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName,
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto derivedProjCRS =
|
||||
dynamic_cast<const DerivedProjectedCRS *>(this)) {
|
||||
const auto &axisList = derivedProjCRS->coordinateSystem()->axisList();
|
||||
if (axisList.size() == 2) {
|
||||
auto cs = cs::CartesianCS::create(util::PropertyMap(), axisList[0],
|
||||
axisList[1],
|
||||
verticalAxisIfNotAlreadyPresent);
|
||||
auto baseProj3DCRS = util::nn_dynamic_pointer_cast<ProjectedCRS>(
|
||||
derivedProjCRS->baseCRS()->promoteTo3D(
|
||||
std::string(), dbContext, verticalAxisIfNotAlreadyPresent));
|
||||
return util::nn_static_pointer_cast<CRS>(
|
||||
DerivedProjectedCRS::create(
|
||||
createProperties(), NN_CHECK_THROW(baseProj3DCRS),
|
||||
derivedProjCRS->derivingConversion(), cs));
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto geogCRS = dynamic_cast<const GeographicCRS *>(this)) {
|
||||
const auto &axisList = geogCRS->coordinateSystem()->axisList();
|
||||
if (axisList.size() == 2) {
|
||||
@@ -1358,6 +1385,11 @@ CRSNNPtr CRS::demoteTo2D(const std::string &newName,
|
||||
return derivedGeogCRS->demoteTo2D(newName, dbContext);
|
||||
}
|
||||
|
||||
else if (auto derivedProjCRS =
|
||||
dynamic_cast<const DerivedProjectedCRS *>(this)) {
|
||||
return derivedProjCRS->demoteTo2D(newName, dbContext);
|
||||
}
|
||||
|
||||
else if (auto geogCRS = dynamic_cast<const GeographicCRS *>(this)) {
|
||||
return geogCRS->demoteTo2D(newName, dbContext);
|
||||
}
|
||||
@@ -3674,6 +3706,10 @@ bool VerticalCRS::_isEquivalentTo(
|
||||
const util::IComparable *other, util::IComparable::Criterion criterion,
|
||||
const io::DatabaseContextPtr &dbContext) const {
|
||||
auto otherVertCRS = dynamic_cast<const VerticalCRS *>(other);
|
||||
if (otherVertCRS == nullptr ||
|
||||
!util::isOfExactType<VerticalCRS>(*otherVertCRS)) {
|
||||
return false;
|
||||
}
|
||||
// TODO test geoidModel and velocityModel
|
||||
return otherVertCRS != nullptr &&
|
||||
SingleCRS::baseIsEquivalentTo(other, criterion, dbContext);
|
||||
@@ -6493,6 +6529,39 @@ DerivedProjectedCRSNNPtr DerivedProjectedCRS::create(
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** \brief Return a variant of this CRS "demoted" to a 2D one, if not already
|
||||
* the case.
|
||||
*
|
||||
*
|
||||
* @param newName Name of the new CRS. If empty, nameStr() will be used.
|
||||
* @param dbContext Database context to look for potentially already registered
|
||||
* 2D CRS. May be nullptr.
|
||||
* @return a new CRS demoted to 2D, or the current one if already 2D or not
|
||||
* applicable.
|
||||
* @since 9.1.1
|
||||
*/
|
||||
DerivedProjectedCRSNNPtr
|
||||
DerivedProjectedCRS::demoteTo2D(const std::string &newName,
|
||||
const io::DatabaseContextPtr &dbContext) const {
|
||||
|
||||
const auto &axisList = coordinateSystem()->axisList();
|
||||
if (axisList.size() == 3) {
|
||||
auto cs = cs::CartesianCS::create(util::PropertyMap(), axisList[0],
|
||||
axisList[1]);
|
||||
auto baseProj2DCRS = util::nn_dynamic_pointer_cast<ProjectedCRS>(
|
||||
baseCRS()->demoteTo2D(std::string(), dbContext));
|
||||
return DerivedProjectedCRS::create(
|
||||
util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
|
||||
!newName.empty() ? newName : nameStr()),
|
||||
NN_CHECK_THROW(baseProj2DCRS), derivingConversion(), cs);
|
||||
}
|
||||
|
||||
return NN_NO_CHECK(std::dynamic_pointer_cast<DerivedProjectedCRS>(
|
||||
shared_from_this().as_nullable()));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
void DerivedProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
|
||||
const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2;
|
||||
|
||||
+212
-32
@@ -1472,10 +1472,6 @@ struct WKTParser::Private {
|
||||
|
||||
CRSPtr buildCRS(const WKTNodeNNPtr &node);
|
||||
|
||||
CRSPtr dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
std::vector<OperationParameterNNPtr> ¶meters,
|
||||
std::vector<ParameterValueNNPtr> &values);
|
||||
|
||||
TransformationNNPtr buildCoordinateOperation(const WKTNodeNNPtr &node);
|
||||
|
||||
ConcatenatedOperationNNPtr
|
||||
@@ -3205,6 +3201,14 @@ CRSNNPtr WKTParser::Private::buildDerivedGeodeticCRS(const WKTNodeNNPtr &node) {
|
||||
|
||||
auto ellipsoidalCS = nn_dynamic_pointer_cast<EllipsoidalCS>(cs);
|
||||
if (ellipsoidalCS) {
|
||||
|
||||
if (ellipsoidalCS->axisList().size() == 3 &&
|
||||
baseGeodCRS->coordinateSystem()->axisList().size() == 2) {
|
||||
baseGeodCRS =
|
||||
NN_NO_CHECK(util::nn_dynamic_pointer_cast<GeodeticCRS>(
|
||||
baseGeodCRS->promoteTo3D(std::string(), dbContext_)));
|
||||
}
|
||||
|
||||
return DerivedGeographicCRS::create(buildProperties(node), baseGeodCRS,
|
||||
derivingConversion,
|
||||
NN_NO_CHECK(ellipsoidalCS));
|
||||
@@ -3337,6 +3341,11 @@ void WKTParser::Private::consumeParameters(
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static CRSPtr dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
DatabaseContextPtr &dbContext,
|
||||
std::vector<OperationParameterNNPtr> ¶meters,
|
||||
std::vector<ParameterValueNNPtr> &values);
|
||||
|
||||
ConversionNNPtr
|
||||
WKTParser::Private::buildConversion(const WKTNodeNNPtr &node,
|
||||
const UnitOfMeasure &defaultLinearUnit,
|
||||
@@ -3371,8 +3380,8 @@ WKTParser::Private::buildConversion(const WKTNodeNNPtr &node,
|
||||
->inverse()));
|
||||
}
|
||||
auto conv = Conversion::create(convProps, methodProps, parameters, values);
|
||||
auto interpolationCRS =
|
||||
dealWithEPSGCodeForInterpolationCRSParameter(parameters, values);
|
||||
auto interpolationCRS = dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
dbContext_, parameters, values);
|
||||
if (interpolationCRS)
|
||||
conv->setInterpolationCRS(interpolationCRS);
|
||||
return conv;
|
||||
@@ -3380,12 +3389,13 @@ WKTParser::Private::buildConversion(const WKTNodeNNPtr &node,
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
CRSPtr WKTParser::Private::dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
static CRSPtr dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
DatabaseContextPtr &dbContext,
|
||||
std::vector<OperationParameterNNPtr> ¶meters,
|
||||
std::vector<ParameterValueNNPtr> &values) {
|
||||
// Transform EPSG hacky PARAMETER["EPSG code for Interpolation CRS",
|
||||
// crs_epsg_code] into proper interpolation CRS
|
||||
if (dbContext_ != nullptr) {
|
||||
if (dbContext != nullptr) {
|
||||
for (size_t i = 0; i < parameters.size(); ++i) {
|
||||
const auto &l_name = parameters[i]->nameStr();
|
||||
const auto epsgCode = parameters[i]->getEPSGCode();
|
||||
@@ -3398,7 +3408,7 @@ CRSPtr WKTParser::Private::dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
static_cast<int>(values[i]->value().getSIValue());
|
||||
try {
|
||||
auto authFactory = AuthorityFactory::create(
|
||||
NN_NO_CHECK(dbContext_), Identifier::EPSG);
|
||||
NN_NO_CHECK(dbContext), Identifier::EPSG);
|
||||
auto interpolationCRS =
|
||||
authFactory
|
||||
->createGeographicCRS(internal::toString(code))
|
||||
@@ -3461,8 +3471,8 @@ WKTParser::Private::buildCoordinateOperation(const WKTNodeNNPtr &node) {
|
||||
defaultAngularUnit);
|
||||
|
||||
if (interpolationCRS == nullptr)
|
||||
interpolationCRS =
|
||||
dealWithEPSGCodeForInterpolationCRSParameter(parameters, values);
|
||||
interpolationCRS = dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
dbContext_, parameters, values);
|
||||
|
||||
std::vector<PositionalAccuracyNNPtr> accuracies;
|
||||
auto &accuracyNode = nodeP->lookForChild(WKTConstants::OPERATIONACCURACY);
|
||||
@@ -4883,6 +4893,50 @@ CRSNNPtr WKTParser::Private::buildCompoundCRS(const WKTNodeNNPtr &node) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static TransformationNNPtr buildTransformationForBoundCRS(
|
||||
DatabaseContextPtr &dbContext,
|
||||
const util::PropertyMap &abridgedNodeProperties,
|
||||
const util::PropertyMap &methodNodeProperties, const CRSNNPtr &sourceCRS,
|
||||
const CRSNNPtr &targetCRS, std::vector<OperationParameterNNPtr> ¶meters,
|
||||
std::vector<ParameterValueNNPtr> &values) {
|
||||
|
||||
auto interpolationCRS = dealWithEPSGCodeForInterpolationCRSParameter(
|
||||
dbContext, parameters, values);
|
||||
|
||||
const auto sourceTransformationCRS(
|
||||
createBoundCRSSourceTransformationCRS(sourceCRS, targetCRS));
|
||||
auto transformation = Transformation::create(
|
||||
abridgedNodeProperties, sourceTransformationCRS, targetCRS,
|
||||
interpolationCRS, methodNodeProperties, parameters, values,
|
||||
std::vector<PositionalAccuracyNNPtr>());
|
||||
|
||||
// If the transformation is a "Geographic3D to GravityRelatedHeight" one,
|
||||
// then the sourceCRS is expected to be a GeographicCRS and the target a
|
||||
// VerticalCRS. Due to how things work in a BoundCRS, we have the opposite,
|
||||
// so use our "GravityRelatedHeight to Geographic3D" method instead.
|
||||
if (Transformation::isGeographic3DToGravityRelatedHeight(
|
||||
transformation->method(), true) &&
|
||||
dynamic_cast<VerticalCRS *>(sourceTransformationCRS.get()) &&
|
||||
dynamic_cast<GeographicCRS *>(targetCRS.get())) {
|
||||
auto fileParameter = transformation->parameterValue(
|
||||
EPSG_NAME_PARAMETER_GEOID_CORRECTION_FILENAME,
|
||||
EPSG_CODE_PARAMETER_GEOID_CORRECTION_FILENAME);
|
||||
if (fileParameter &&
|
||||
fileParameter->type() == ParameterValue::Type::FILENAME) {
|
||||
auto filename = fileParameter->valueFile();
|
||||
|
||||
transformation =
|
||||
Transformation::createGravityRelatedHeightToGeographic3D(
|
||||
abridgedNodeProperties, sourceTransformationCRS, targetCRS,
|
||||
interpolationCRS, filename,
|
||||
std::vector<PositionalAccuracyNNPtr>());
|
||||
}
|
||||
}
|
||||
return transformation;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
BoundCRSNNPtr WKTParser::Private::buildBoundCRS(const WKTNodeNNPtr &node) {
|
||||
const auto *nodeP = node->GP();
|
||||
auto &abridgedNode =
|
||||
@@ -4926,15 +4980,11 @@ BoundCRSNNPtr WKTParser::Private::buildBoundCRS(const WKTNodeNNPtr &node) {
|
||||
consumeParameters(abridgedNode, true, parameters, values, defaultLinearUnit,
|
||||
defaultAngularUnit);
|
||||
|
||||
auto interpolationCRS =
|
||||
dealWithEPSGCodeForInterpolationCRSParameter(parameters, values);
|
||||
|
||||
const auto sourceTransformationCRS(
|
||||
createBoundCRSSourceTransformationCRS(sourceCRS, targetCRS));
|
||||
auto transformation = Transformation::create(
|
||||
buildProperties(abridgedNode), sourceTransformationCRS,
|
||||
NN_NO_CHECK(targetCRS), interpolationCRS, buildProperties(methodNode),
|
||||
parameters, values, std::vector<PositionalAccuracyNNPtr>());
|
||||
const auto nnSourceCRS = NN_NO_CHECK(sourceCRS);
|
||||
const auto nnTargetCRS = NN_NO_CHECK(targetCRS);
|
||||
const auto transformation = buildTransformationForBoundCRS(
|
||||
dbContext_, buildProperties(abridgedNode), buildProperties(methodNode),
|
||||
nnSourceCRS, nnTargetCRS, parameters, values);
|
||||
|
||||
return BoundCRS::create(buildProperties(node, false, false),
|
||||
NN_NO_CHECK(sourceCRS), NN_NO_CHECK(targetCRS),
|
||||
@@ -5145,6 +5195,13 @@ WKTParser::Private::buildDerivedProjectedCRS(const WKTNodeNNPtr &node) {
|
||||
ThrowMissing(WKTConstants::CS_);
|
||||
}
|
||||
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
|
||||
|
||||
if (cs->axisList().size() == 3 &&
|
||||
baseProjCRS->coordinateSystem()->axisList().size() == 2) {
|
||||
baseProjCRS = NN_NO_CHECK(util::nn_dynamic_pointer_cast<ProjectedCRS>(
|
||||
baseProjCRS->promoteTo3D(std::string(), dbContext_)));
|
||||
}
|
||||
|
||||
return DerivedProjectedCRS::create(buildProperties(node), baseProjCRS,
|
||||
conversion, cs);
|
||||
}
|
||||
@@ -6229,12 +6286,9 @@ BoundCRSNNPtr JSONParser::buildBoundCRS(const json &j) {
|
||||
values.emplace_back(ParameterValue::create(getMeasure(param)));
|
||||
}
|
||||
|
||||
const auto sourceTransformationCRS(
|
||||
createBoundCRSSourceTransformationCRS(sourceCRS, targetCRS));
|
||||
auto transformation = Transformation::create(
|
||||
buildProperties(transformationJ), sourceTransformationCRS, targetCRS,
|
||||
nullptr, buildProperties(methodJ), parameters, values,
|
||||
std::vector<PositionalAccuracyNNPtr>());
|
||||
const auto transformation = buildTransformationForBoundCRS(
|
||||
dbContext_, buildProperties(transformationJ), buildProperties(methodJ),
|
||||
sourceCRS, targetCRS, parameters, values);
|
||||
|
||||
return BoundCRS::create(buildProperties(j,
|
||||
/* removeInverseOf= */ false,
|
||||
@@ -7283,6 +7337,24 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
|
||||
}
|
||||
}
|
||||
|
||||
// If there's exactly only one object whose name is equivalent
|
||||
// to the user input, return it.
|
||||
IdentifiedObjectPtr identifiedObj;
|
||||
for (const auto &obj : res) {
|
||||
if (Identifier::isEquivalentName(obj->nameStr().c_str(),
|
||||
objectName.c_str())) {
|
||||
if (identifiedObj == nullptr) {
|
||||
identifiedObj = obj.as_nullable();
|
||||
} else {
|
||||
identifiedObj = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (identifiedObj) {
|
||||
return identifiedObj;
|
||||
}
|
||||
|
||||
std::string msg("several objects matching this name: ");
|
||||
bool first = true;
|
||||
for (const auto &obj : res) {
|
||||
@@ -8618,7 +8690,8 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
if (ok && iterNext != steps.end()) {
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "axisswap" &&
|
||||
@@ -8628,7 +8701,8 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
if (ok && iterNext != steps.end()) {
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "unitconvert" &&
|
||||
@@ -8640,7 +8714,8 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
}
|
||||
}
|
||||
auto iterVgridshift = iterNext;
|
||||
if (ok && iterNext != steps.end()) {
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "vgridshift") {
|
||||
@@ -8648,7 +8723,8 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
if (ok && iterNext != steps.end()) {
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "unitconvert" &&
|
||||
@@ -8659,7 +8735,8 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
if (ok && iterNext != steps.end()) {
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "axisswap" &&
|
||||
@@ -8669,7 +8746,8 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
if (ok && iterNext != steps.end()) {
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "pop" &&
|
||||
@@ -8677,6 +8755,7 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
nextStep.paramValues[0].keyEquals("v_1") &&
|
||||
nextStep.paramValues[1].keyEquals("v_2")) {
|
||||
ok = true;
|
||||
// iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
@@ -8688,6 +8767,107 @@ const std::string &PROJStringFormatter::toString() const {
|
||||
}
|
||||
}
|
||||
|
||||
// +step +proj=axisswap +order=2,1
|
||||
// +step +proj=unitconvert +xy_in=deg +xy_out=rad
|
||||
// +step +proj=vgridshift ...
|
||||
// +step +proj=unitconvert +xy_in=rad +xy_out=deg
|
||||
// +step +proj=axisswap +order=2,1
|
||||
// +step +proj=push +v_1 +v_2
|
||||
// +step +proj=axisswap +order=2,1
|
||||
// +step +proj=unitconvert +xy_in=deg +xy_out=rad
|
||||
// ==>
|
||||
// +step +proj=push +v_1 +v_2
|
||||
// +step +proj=axisswap +order=2,1
|
||||
// +step +proj=unitconvert +xy_in=deg +xy_out=rad
|
||||
// +step +proj=vgridshift ...
|
||||
|
||||
if (prevStep.name == "axisswap" && prevStepParamCount == 1 &&
|
||||
prevStep.paramValues[0].equals("order", "2,1") &&
|
||||
curStep.name == "unitconvert" && curStepParamCount == 2 &&
|
||||
!curStep.inverted &&
|
||||
curStep.paramValues[0].equals("xy_in", "deg") &&
|
||||
curStep.paramValues[1].equals("xy_out", "rad")) {
|
||||
auto iterNext = std::next(iterCur);
|
||||
bool ok = false;
|
||||
auto iterVgridshift = iterNext;
|
||||
if (iterNext != steps.end()) {
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "vgridshift") {
|
||||
ok = true;
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "unitconvert" && !nextStep.inverted &&
|
||||
nextStep.paramValues.size() == 2 &&
|
||||
nextStep.paramValues[0].equals("xy_in", "rad") &&
|
||||
nextStep.paramValues[1].equals("xy_out", "deg")) {
|
||||
ok = true;
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "axisswap" &&
|
||||
nextStep.paramValues.size() == 1 &&
|
||||
nextStep.paramValues[0].equals("order", "2,1")) {
|
||||
ok = true;
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
auto iterPush = iterNext;
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "push" &&
|
||||
nextStep.paramValues.size() == 2 &&
|
||||
nextStep.paramValues[0].keyEquals("v_1") &&
|
||||
nextStep.paramValues[1].keyEquals("v_2")) {
|
||||
ok = true;
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "axisswap" &&
|
||||
nextStep.paramValues.size() == 1 &&
|
||||
nextStep.paramValues[0].equals("order", "2,1")) {
|
||||
ok = true;
|
||||
iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
ok &= iterNext != steps.end();
|
||||
if (ok) {
|
||||
ok = false;
|
||||
auto &nextStep = *iterNext;
|
||||
if (nextStep.name == "unitconvert" &&
|
||||
nextStep.paramValues.size() == 2 &&
|
||||
!nextStep.inverted &&
|
||||
nextStep.paramValues[0].equals("xy_in", "deg") &&
|
||||
nextStep.paramValues[1].equals("xy_out", "rad")) {
|
||||
ok = true;
|
||||
// iterNext = std::next(iterNext);
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
auto stepVgridshift = *iterVgridshift;
|
||||
steps.erase(iterPrev, iterPush);
|
||||
steps.insert(std::next(iterNext), stepVgridshift);
|
||||
iterPrev = iterPush;
|
||||
iterCur = std::next(iterPush);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
++iterCur;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3465,12 +3465,16 @@ void Conversion::_exportToPROJString(
|
||||
methodEPSGCode == EPSG_CODE_METHOD_AFFINE_PARAMETRIC_TRANSFORMATION;
|
||||
const bool isGeographicGeocentric =
|
||||
methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC_GEOCENTRIC;
|
||||
const bool isGeographicOffsets =
|
||||
methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC2D_OFFSETS ||
|
||||
methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC3D_OFFSETS ||
|
||||
methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC2D_WITH_HEIGHT_OFFSETS;
|
||||
const bool isHeightDepthReversal =
|
||||
methodEPSGCode == EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL;
|
||||
const bool applySourceCRSModifiers =
|
||||
!isZUnitConversion && !isAffineParametric &&
|
||||
!isAxisOrderReversal(methodEPSGCode) && !isGeographicGeocentric &&
|
||||
!isHeightDepthReversal;
|
||||
!isGeographicOffsets && !isHeightDepthReversal;
|
||||
bool applyTargetCRSModifiers = applySourceCRSModifiers;
|
||||
|
||||
if (formatter->getCRSExport()) {
|
||||
@@ -4256,5 +4260,110 @@ ConversionNNPtr Conversion::identify() const {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** \brief Instantiate a conversion with method Geographic 2D offsets
|
||||
*
|
||||
* This method is defined as [EPSG:9619]
|
||||
* (https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::9619)
|
||||
* *
|
||||
* @param properties See \ref general_properties of the conversion.
|
||||
* At minimum the name should be defined.
|
||||
* @param offsetLat Latitude offset to add.
|
||||
* @param offsetLon Longitude offset to add.
|
||||
* @return new conversion.
|
||||
*/
|
||||
ConversionNNPtr
|
||||
Conversion::createGeographic2DOffsets(const util::PropertyMap &properties,
|
||||
const common::Angle &offsetLat,
|
||||
const common::Angle &offsetLon) {
|
||||
return create(
|
||||
properties,
|
||||
createMethodMapNameEPSGCode(EPSG_CODE_METHOD_GEOGRAPHIC2D_OFFSETS),
|
||||
VectorOfParameters{
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_LATITUDE_OFFSET),
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_LONGITUDE_OFFSET)},
|
||||
VectorOfValues{offsetLat, offsetLon});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** \brief Instantiate a conversion with method Geographic 3D offsets
|
||||
*
|
||||
* This method is defined as [EPSG:9660]
|
||||
* (https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::9660)
|
||||
* *
|
||||
* @param properties See \ref general_properties of the Conversion.
|
||||
* At minimum the name should be defined.
|
||||
* @param offsetLat Latitude offset to add.
|
||||
* @param offsetLon Longitude offset to add.
|
||||
* @param offsetHeight Height offset to add.
|
||||
* @return new Conversion.
|
||||
*/
|
||||
ConversionNNPtr Conversion::createGeographic3DOffsets(
|
||||
const util::PropertyMap &properties, const common::Angle &offsetLat,
|
||||
const common::Angle &offsetLon, const common::Length &offsetHeight) {
|
||||
return create(
|
||||
properties,
|
||||
createMethodMapNameEPSGCode(EPSG_CODE_METHOD_GEOGRAPHIC3D_OFFSETS),
|
||||
VectorOfParameters{
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_LATITUDE_OFFSET),
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_LONGITUDE_OFFSET),
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_VERTICAL_OFFSET)},
|
||||
VectorOfValues{offsetLat, offsetLon, offsetHeight});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** \brief Instantiate a conversion with method Geographic 2D with
|
||||
* height
|
||||
* offsets
|
||||
*
|
||||
* This method is defined as [EPSG:9618]
|
||||
* (https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::9618)
|
||||
* *
|
||||
* @param properties See \ref general_properties of the Conversion.
|
||||
* At minimum the name should be defined.
|
||||
* @param offsetLat Latitude offset to add.
|
||||
* @param offsetLon Longitude offset to add.
|
||||
* @param offsetHeight Geoid undulation to add.
|
||||
* @return new Conversion.
|
||||
*/
|
||||
ConversionNNPtr Conversion::createGeographic2DWithHeightOffsets(
|
||||
const util::PropertyMap &properties, const common::Angle &offsetLat,
|
||||
const common::Angle &offsetLon, const common::Length &offsetHeight) {
|
||||
return create(
|
||||
properties,
|
||||
createMethodMapNameEPSGCode(
|
||||
EPSG_CODE_METHOD_GEOGRAPHIC2D_WITH_HEIGHT_OFFSETS),
|
||||
VectorOfParameters{
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_LATITUDE_OFFSET),
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_LONGITUDE_OFFSET),
|
||||
createOpParamNameEPSGCode(EPSG_CODE_PARAMETER_GEOID_UNDULATION)},
|
||||
VectorOfValues{offsetLat, offsetLon, offsetHeight});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** \brief Instantiate a conversion with method Vertical Offset.
|
||||
*
|
||||
* This method is defined as [EPSG:9616]
|
||||
* (https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::9616)
|
||||
* *
|
||||
* @param properties See \ref general_properties of the Conversion.
|
||||
* At minimum the name should be defined.
|
||||
* @param offsetHeight Geoid undulation to add.
|
||||
* @return new Conversion.
|
||||
*/
|
||||
ConversionNNPtr
|
||||
Conversion::createVerticalOffset(const util::PropertyMap &properties,
|
||||
const common::Length &offsetHeight) {
|
||||
return create(properties,
|
||||
createMethodMapNameEPSGCode(EPSG_CODE_METHOD_VERTICAL_OFFSET),
|
||||
VectorOfParameters{createOpParamNameEPSGCode(
|
||||
EPSG_CODE_PARAMETER_VERTICAL_OFFSET)},
|
||||
VectorOfValues{offsetHeight});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
} // namespace operation
|
||||
NS_PROJ_END
|
||||
|
||||
@@ -1814,6 +1814,56 @@ CoordinateOperationFactory::Private::findOpsInRegistryDirectTo(
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static std::vector<crs::GeodeticCRSNNPtr>
|
||||
findCandidateGeodCRSForDatum(const io::AuthorityFactoryPtr &authFactory,
|
||||
const crs::GeodeticCRS *crs,
|
||||
const datum::GeodeticReferenceFrame *datum) {
|
||||
std::vector<crs::GeodeticCRSNNPtr> candidates;
|
||||
assert(datum);
|
||||
const auto &ids = datum->identifiers();
|
||||
const auto &datumName = datum->nameStr();
|
||||
if (!ids.empty()) {
|
||||
for (const auto &id : ids) {
|
||||
const auto &authName = *(id->codeSpace());
|
||||
const auto &code = id->code();
|
||||
if (!authName.empty()) {
|
||||
const auto crsIds = crs->identifiers();
|
||||
const auto tmpFactory =
|
||||
(crsIds.size() == 1 &&
|
||||
*(crsIds.front()->codeSpace()) == authName)
|
||||
? io::AuthorityFactory::create(
|
||||
authFactory->databaseContext(), authName)
|
||||
.as_nullable()
|
||||
: authFactory;
|
||||
auto l_candidates = tmpFactory->createGeodeticCRSFromDatum(
|
||||
authName, code, std::string());
|
||||
for (const auto &candidate : l_candidates) {
|
||||
candidates.emplace_back(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (datumName != "unknown" && datumName != "unnamed") {
|
||||
auto matches = authFactory->createObjectsFromName(
|
||||
datumName,
|
||||
{io::AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, false,
|
||||
2);
|
||||
if (matches.size() == 1) {
|
||||
const auto &match = matches.front();
|
||||
if (datum->_isEquivalentTo(
|
||||
match.get(), util::IComparable::Criterion::EQUIVALENT) &&
|
||||
!match->identifiers().empty()) {
|
||||
return findCandidateGeodCRSForDatum(
|
||||
authFactory, crs,
|
||||
dynamic_cast<const datum::GeodeticReferenceFrame *>(
|
||||
match.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
// Look in the authority registry for operations from sourceCRS to targetCRS
|
||||
@@ -1834,9 +1884,59 @@ CoordinateOperationFactory::Private::findsOpsInRegistryWithIntermediate(
|
||||
assert(authFactory);
|
||||
|
||||
std::list<std::pair<std::string, std::string>> sourceIds;
|
||||
std::list<std::pair<std::string, std::string>> targetIds;
|
||||
buildCRSIds(sourceCRS, context, sourceIds);
|
||||
if (sourceIds.empty()) {
|
||||
auto geodSrc = dynamic_cast<crs::GeodeticCRS *>(sourceCRS.get());
|
||||
if (geodSrc) {
|
||||
const auto candidatesSrcGeod(findCandidateGeodCRSForDatum(
|
||||
authFactory, geodSrc,
|
||||
geodSrc
|
||||
->datumNonNull(authFactory->databaseContext().as_nullable())
|
||||
.get()));
|
||||
std::vector<CoordinateOperationNNPtr> res;
|
||||
for (const auto &candidateSrcGeod : candidatesSrcGeod) {
|
||||
if (candidateSrcGeod->coordinateSystem()->axisList().size() ==
|
||||
geodSrc->coordinateSystem()->axisList().size() &&
|
||||
((dynamic_cast<crs::GeographicCRS *>(sourceCRS.get()) !=
|
||||
nullptr) ==
|
||||
(dynamic_cast<crs::GeographicCRS *>(
|
||||
candidateSrcGeod.get()) != nullptr))) {
|
||||
const auto opsWithIntermediate =
|
||||
findsOpsInRegistryWithIntermediate(
|
||||
candidateSrcGeod, targetCRS, context,
|
||||
useCreateBetweenGeodeticCRSWithDatumBasedIntermediates);
|
||||
if (!opsWithIntermediate.empty()) {
|
||||
const auto opsFirst = createOperations(
|
||||
sourceCRS, candidateSrcGeod, context);
|
||||
for (const auto &opFirst : opsFirst) {
|
||||
for (const auto &opSecond : opsWithIntermediate) {
|
||||
try {
|
||||
res.emplace_back(
|
||||
ConcatenatedOperation::
|
||||
createComputeMetadata(
|
||||
{opFirst, opSecond},
|
||||
disallowEmptyIntersection));
|
||||
} catch (
|
||||
const InvalidOperationEmptyIntersection &) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!res.empty())
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::vector<CoordinateOperationNNPtr>();
|
||||
}
|
||||
|
||||
std::list<std::pair<std::string, std::string>> targetIds;
|
||||
buildCRSIds(targetCRS, context, targetIds);
|
||||
if (targetIds.empty()) {
|
||||
return applyInverse(findsOpsInRegistryWithIntermediate(
|
||||
targetCRS, sourceCRS, context,
|
||||
useCreateBetweenGeodeticCRSWithDatumBasedIntermediates));
|
||||
}
|
||||
|
||||
const auto gridAvailabilityUse = context.context->getGridAvailabilityUse();
|
||||
for (const auto &idSrc : sourceIds) {
|
||||
@@ -2099,7 +2199,17 @@ struct MyPROJStringExportableHorizVerticalHorizPROJBased final
|
||||
->demoteTo2D(std::string(), nullptr)
|
||||
.get(),
|
||||
util::IComparable::Criterion::EQUIVALENT)) {
|
||||
const int methodEPSGCode = transf->method()->getEPSGCode();
|
||||
int methodEPSGCode = transf->method()->getEPSGCode();
|
||||
if (methodEPSGCode == 0) {
|
||||
// If the transformation is actually an inverse transformation,
|
||||
// we will not get the EPSG code. So get the forward
|
||||
// transformation.
|
||||
const auto invTrans = transf->inverse();
|
||||
const auto invTransAsTrans =
|
||||
dynamic_cast<Transformation *>(invTrans.get());
|
||||
if (invTransAsTrans)
|
||||
methodEPSGCode = invTransAsTrans->method()->getEPSGCode();
|
||||
}
|
||||
|
||||
const bool bGeocentricTranslation =
|
||||
methodEPSGCode ==
|
||||
@@ -2649,56 +2759,6 @@ static bool hasIdentifiers(const CoordinateOperationNNPtr &op) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static std::vector<crs::CRSNNPtr>
|
||||
findCandidateGeodCRSForDatum(const io::AuthorityFactoryPtr &authFactory,
|
||||
const crs::GeodeticCRS *crs,
|
||||
const datum::GeodeticReferenceFrame *datum) {
|
||||
std::vector<crs::CRSNNPtr> candidates;
|
||||
assert(datum);
|
||||
const auto &ids = datum->identifiers();
|
||||
const auto &datumName = datum->nameStr();
|
||||
if (!ids.empty()) {
|
||||
for (const auto &id : ids) {
|
||||
const auto &authName = *(id->codeSpace());
|
||||
const auto &code = id->code();
|
||||
if (!authName.empty()) {
|
||||
const auto crsIds = crs->identifiers();
|
||||
const auto tmpFactory =
|
||||
(crsIds.size() == 1 &&
|
||||
*(crsIds.front()->codeSpace()) == authName)
|
||||
? io::AuthorityFactory::create(
|
||||
authFactory->databaseContext(), authName)
|
||||
.as_nullable()
|
||||
: authFactory;
|
||||
auto l_candidates = tmpFactory->createGeodeticCRSFromDatum(
|
||||
authName, code, std::string());
|
||||
for (const auto &candidate : l_candidates) {
|
||||
candidates.emplace_back(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (datumName != "unknown" && datumName != "unnamed") {
|
||||
auto matches = authFactory->createObjectsFromName(
|
||||
datumName,
|
||||
{io::AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, false,
|
||||
2);
|
||||
if (matches.size() == 1) {
|
||||
const auto &match = matches.front();
|
||||
if (datum->_isEquivalentTo(
|
||||
match.get(), util::IComparable::Criterion::EQUIVALENT) &&
|
||||
!match->identifiers().empty()) {
|
||||
return findCandidateGeodCRSForDatum(
|
||||
authFactory, crs,
|
||||
dynamic_cast<const datum::GeodeticReferenceFrame *>(
|
||||
match.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void CoordinateOperationFactory::Private::setCRSs(
|
||||
CoordinateOperation *co, const crs::CRSNNPtr &sourceCRS,
|
||||
const crs::CRSNNPtr &targetCRS) {
|
||||
@@ -4001,6 +4061,10 @@ void CoordinateOperationFactory::Private::createOperationsGeodToGeod(
|
||||
res.emplace_back(
|
||||
Conversion::createGeographicGeocentric(sourceCRS, targetCRS));
|
||||
} else if (isSrcGeocentric && geogDst) {
|
||||
#if 0
|
||||
// The below logic was used between PROJ >= 6.0 and < 9.2
|
||||
// It assumed that the geocentric origin of the 2 datums
|
||||
// matched.
|
||||
std::string interm_crs_name(geogDst->nameStr());
|
||||
interm_crs_name += " (geocentric)";
|
||||
auto interm_crs =
|
||||
@@ -4017,15 +4081,42 @@ void CoordinateOperationFactory::Private::createOperationsGeodToGeod(
|
||||
createBallparkGeocentricTranslation(sourceCRS, interm_crs);
|
||||
auto opSecond =
|
||||
Conversion::createGeographicGeocentric(interm_crs, targetCRS);
|
||||
res.emplace_back(ConcatenatedOperation::createComputeMetadata(
|
||||
{opFirst, opSecond}, disallowEmptyIntersection));
|
||||
#else
|
||||
// The below logic is used since PROJ >= 9.2. It emulates the
|
||||
// behavior of PROJ < 6 by converting from the source geocentric CRS
|
||||
// to its corresponding geographic CRS, and then doing a null
|
||||
// geographic offset between that CRS and the target geographic CRS
|
||||
std::string interm_crs_name(geodSrc->nameStr());
|
||||
interm_crs_name += " (geographic)";
|
||||
auto interm_crs = util::nn_static_pointer_cast<crs::CRS>(
|
||||
crs::GeographicCRS::create(
|
||||
addDomains(util::PropertyMap().set(
|
||||
common::IdentifiedObject::NAME_KEY,
|
||||
interm_crs_name),
|
||||
geodSrc),
|
||||
geodSrc->datum(), geodSrc->datumEnsemble(),
|
||||
cs::EllipsoidalCS::createLongitudeLatitudeEllipsoidalHeight(
|
||||
common::UnitOfMeasure::DEGREE,
|
||||
common::UnitOfMeasure::METRE)));
|
||||
auto opFirst =
|
||||
Conversion::createGeographicGeocentric(sourceCRS, interm_crs);
|
||||
auto opsSecond = createOperations(interm_crs, targetCRS, context);
|
||||
for (const auto &opSecond : opsSecond) {
|
||||
try {
|
||||
res.emplace_back(
|
||||
ConcatenatedOperation::createComputeMetadata(
|
||||
{opFirst, opSecond}, disallowEmptyIntersection));
|
||||
} catch (const InvalidOperationEmptyIntersection &) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Apply previous case in reverse way
|
||||
std::vector<CoordinateOperationNNPtr> resTmp;
|
||||
createOperationsGeodToGeod(targetCRS, sourceCRS, context, geodDst,
|
||||
geodSrc, resTmp);
|
||||
assert(resTmp.size() == 1);
|
||||
res.emplace_back(resTmp.front()->inverse());
|
||||
resTmp = applyInverse(resTmp);
|
||||
res.insert(res.end(), resTmp.begin(), resTmp.end());
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -1842,9 +1842,8 @@ _getHeightToGeographic3DFilename(const SingleOperation *op, bool allowInverse) {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
static bool
|
||||
isGeographic3DToGravityRelatedHeight(const OperationMethodNNPtr &method,
|
||||
bool allowInverse) {
|
||||
bool Transformation::isGeographic3DToGravityRelatedHeight(
|
||||
const OperationMethodNNPtr &method, bool allowInverse) {
|
||||
const auto &methodName = method->nameStr();
|
||||
static const char *const methodCodes[] = {
|
||||
"1025", // Geographic3D to GravityRelatedHeight (EGM2008)
|
||||
@@ -2155,7 +2154,7 @@ TransformationNNPtr SingleOperation::substitutePROJAlternativeGridNames(
|
||||
}
|
||||
}
|
||||
|
||||
if (isGeographic3DToGravityRelatedHeight(method(), false)) {
|
||||
if (Transformation::isGeographic3DToGravityRelatedHeight(method(), false)) {
|
||||
const auto &fileParameter =
|
||||
parameterValue(EPSG_NAME_PARAMETER_GEOID_CORRECTION_FILENAME,
|
||||
EPSG_CODE_PARAMETER_GEOID_CORRECTION_FILENAME);
|
||||
@@ -3648,7 +3647,7 @@ bool SingleOperation::exportToPROJStringGeneric(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isGeographic3DToGravityRelatedHeight(method(), true)) {
|
||||
if (Transformation::isGeographic3DToGravityRelatedHeight(method(), true)) {
|
||||
auto fileParameter =
|
||||
parameterValue(EPSG_NAME_PARAMETER_GEOID_CORRECTION_FILENAME,
|
||||
EPSG_CODE_PARAMETER_GEOID_CORRECTION_FILENAME);
|
||||
@@ -3752,16 +3751,21 @@ bool SingleOperation::exportToPROJStringGeneric(
|
||||
double offsetDeg =
|
||||
parameterValueNumeric(EPSG_CODE_PARAMETER_LONGITUDE_OFFSET,
|
||||
common::UnitOfMeasure::DEGREE);
|
||||
|
||||
auto l_sourceCRS = sourceCRS();
|
||||
auto sourceCRSGeog =
|
||||
dynamic_cast<const crs::GeographicCRS *>(sourceCRS().get());
|
||||
l_sourceCRS ? extractGeographicCRSIfGeographicCRSOrEquivalent(
|
||||
NN_NO_CHECK(l_sourceCRS))
|
||||
: nullptr;
|
||||
if (!sourceCRSGeog) {
|
||||
throw io::FormattingException(
|
||||
concat("Can apply ", methodName, " only to GeographicCRS"));
|
||||
}
|
||||
|
||||
auto l_targetCRS = targetCRS();
|
||||
auto targetCRSGeog =
|
||||
dynamic_cast<const crs::GeographicCRS *>(targetCRS().get());
|
||||
l_targetCRS ? extractGeographicCRSIfGeographicCRSOrEquivalent(
|
||||
NN_NO_CHECK(l_targetCRS))
|
||||
: nullptr;
|
||||
if (!targetCRSGeog) {
|
||||
throw io::FormattingException(
|
||||
concat("Can apply ", methodName + " only to GeographicCRS"));
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
/*! @cond Doxygen_Suppress */
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
@@ -277,6 +278,14 @@ void CPLJSonStreamingWriter::Add(double dfVal, int nPrecision)
|
||||
{
|
||||
Print( dfVal > 0 ? "\"Infinity\"" : "\"-Infinity\"" );
|
||||
}
|
||||
else if( dfVal >= std::numeric_limits<int>::min() &&
|
||||
dfVal <= std::numeric_limits<int>::max() &&
|
||||
static_cast<int>(dfVal) == dfVal )
|
||||
{
|
||||
// Avoid rounding issues on some platforms like armel, with numbers
|
||||
// like 2005. See https://github.com/OSGeo/PROJ/issues/3297
|
||||
Print(CPLSPrintf("%d", static_cast<int>(dfVal)));
|
||||
}
|
||||
else
|
||||
{
|
||||
char szFormatting[10];
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
add_executable(geodtest geodtest.c)
|
||||
target_link_libraries(geodtest ${PROJ_LIBRARIES})
|
||||
if(HAVE_LIBM)
|
||||
target_link_libraries(geodtest m)
|
||||
endif()
|
||||
|
||||
add_executable(geodsigntest geodsigntest.c)
|
||||
# geodsigntest includes geodesic.c directly so it doesn't need to link
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
0 3 0
|
||||
@@ -159,6 +159,9 @@ echo "Test cct with WKT in a file" >> ${OUT}
|
||||
echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE @in.wkt >>${OUT}
|
||||
rm in.wkt
|
||||
|
||||
echo "Test cct with input file with UTF-8 BOM marker" >> ${OUT}
|
||||
$EXE +proj=noop ${TEST_CLI_DIR}/input_with_utf8_bom.txt >> ${OUT}
|
||||
|
||||
# do 'diff' with distribution results
|
||||
echo "diff ${OUT} with testcct_out.dist"
|
||||
diff -u ${OUT} ${TEST_CLI_DIR}/testcct_out.dist
|
||||
|
||||
@@ -24,3 +24,5 @@ Test cct with object code initialization and file input
|
||||
3541658.5334 948984.5160 5201383.7251 2020.5000
|
||||
Test cct with WKT in a file
|
||||
3541657.9112 948983.7503 5201383.2482 2020.5000
|
||||
Test cct with input file with UTF-8 BOM marker
|
||||
0.0000 3.0000 0.0000 inf
|
||||
|
||||
@@ -131,6 +131,14 @@ echo "Testing EPSG:32631 --3d" >> ${OUT}
|
||||
$EXE EPSG:32631 --3d >>${OUT} 2>&1
|
||||
echo "" >>${OUT}
|
||||
|
||||
echo "Testing -s "WGS 84" -t "WGS 84 + EGM96 height" --hide-ballpark --summary" >> ${OUT}
|
||||
$EXE -s "WGS 84" -t "WGS 84 + EGM96 height" --hide-ballpark --summary >>${OUT} 2>&1
|
||||
echo "" >>${OUT}
|
||||
|
||||
echo "Testing -s "WGS 84 + EGM96 height" -t "WGS 84" --hide-ballpark --summary" >> ${OUT}
|
||||
$EXE -s "WGS 84 + EGM96 height" -t "WGS 84" --hide-ballpark --summary >>${OUT} 2>&1
|
||||
echo "" >>${OUT}
|
||||
|
||||
echo "Testing -s EPSG:32631 -t EPSG:4326+3855 --summary" >> ${OUT}
|
||||
$EXE -s EPSG:32631 -t EPSG:4326+3855 --summary >>${OUT} 2>&1
|
||||
echo "" >>${OUT}
|
||||
|
||||
@@ -1240,6 +1240,14 @@ PROJCRS["WGS 84 / UTM zone 31N",
|
||||
BBOX[0,0,84,6]],
|
||||
REMARK["Promoted to 3D from EPSG:32631"]]
|
||||
|
||||
Testing -s WGS 84 -t WGS 84 + EGM96 height --hide-ballpark --summary
|
||||
Candidate operations found: 1
|
||||
unknown id, WGS 84 to EGM96 height (1), 1 m, World.
|
||||
|
||||
Testing -s WGS 84 + EGM96 height -t WGS 84 --hide-ballpark --summary
|
||||
Candidate operations found: 1
|
||||
unknown id, Inverse of WGS 84 to EGM96 height (1), 1 m, World.
|
||||
|
||||
Testing -s EPSG:32631 -t EPSG:4326+3855 --summary
|
||||
Candidate operations found: 1
|
||||
unknown id, Inverse of UTM zone 31N + Inverse of Null geographic offset from WGS 84 to WGS 84, 0 m, World.
|
||||
|
||||
@@ -1052,6 +1052,19 @@ $EXE -E EPSG:4326 "NAD83(HARN)" >> ${OUT} <<EOF
|
||||
34 -120
|
||||
EOF
|
||||
|
||||
echo "##############################################################" >> ${OUT}
|
||||
echo "Check that we promote CRS specified by name to 3D when the other one is 3D" >> ${OUT}
|
||||
$EXE -d 3 -E "WGS 84" "WGS 84 + EGM96 height" >> ${OUT} <<EOF
|
||||
49 2 50
|
||||
EOF
|
||||
|
||||
$EXE -d 3 -E "WGS 84 + EGM96 height" "WGS 84" >> ${OUT} <<EOF
|
||||
49 2 0
|
||||
EOF
|
||||
|
||||
echo "##############################################################" >> ${OUT}
|
||||
echo "Test input file with UTF-8 BOM marker" >> ${OUT}
|
||||
$EXE -d 3 -E EPSG:4326 EPSG:32631 ${TEST_CLI_DIR}/input_with_utf8_bom.txt >> ${OUT}
|
||||
|
||||
# Done!
|
||||
# do 'diff' with distribution results
|
||||
|
||||
@@ -506,3 +506,10 @@ Check that we can use a transformation spanning the antimeridian (should use Pul
|
||||
##############################################################
|
||||
Check that we select the operation that has the smallest area of use, when 2 have the same accuracy
|
||||
34 -120 33d59'59.983"N 119d59'59.955"W 0.000
|
||||
##############################################################
|
||||
Check that we promote CRS specified by name to 3D when the other one is 3D
|
||||
49 2 50 49.000 2.000 4.936
|
||||
49 2 0 49.000 2.000 45.064
|
||||
##############################################################
|
||||
Test input file with UTF-8 BOM marker
|
||||
0 3 0 500000.000 0.000 0.000
|
||||
|
||||
@@ -1105,6 +1105,10 @@ TEST(gie, proj_create_crs_to_crs_from_pj_force_over) {
|
||||
EXPECT_NEAR(input_over.xyz.x, input_over_inv.xyz.x, 1e-8);
|
||||
EXPECT_NEAR(input_over.xyz.y, input_over_inv.xyz.y, 1e-8);
|
||||
|
||||
auto Pnormalized = proj_normalize_for_visualization(ctx, P);
|
||||
ASSERT_TRUE(Pnormalized->over);
|
||||
proj_destroy(Pnormalized);
|
||||
|
||||
proj_destroy(P);
|
||||
}
|
||||
|
||||
@@ -1196,6 +1200,13 @@ TEST(gie, proj_create_crs_to_crs_from_pj_force_over) {
|
||||
EXPECT_NEAR(output_over.xyz.x, 4980122.749364435, 1e-8);
|
||||
EXPECT_NEAR(output_over.xyz.y, 14467212.882603768, 1e-8);
|
||||
|
||||
auto Pnormalized = proj_normalize_for_visualization(ctx, P);
|
||||
ASSERT_TRUE(Pnormalized->over);
|
||||
for (const auto &op : Pnormalized->alternativeCoordinateOperations) {
|
||||
ASSERT_TRUE(op.pj->over);
|
||||
}
|
||||
proj_destroy(Pnormalized);
|
||||
|
||||
proj_destroy(P);
|
||||
}
|
||||
|
||||
|
||||
+67
-4
@@ -5962,6 +5962,19 @@ TEST(crs, parametricCRS_WKT1) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(crs, derivedVerticalCRS_basic) {
|
||||
|
||||
auto crs = createDerivedVerticalCRS();
|
||||
EXPECT_TRUE(crs->isEquivalentTo(crs.get()));
|
||||
EXPECT_TRUE(crs->shallowClone()->isEquivalentTo(crs.get()));
|
||||
EXPECT_TRUE(!crs->isEquivalentTo(createUnrelatedObject().get()));
|
||||
|
||||
EXPECT_FALSE(crs->isEquivalentTo(crs->baseCRS().get()));
|
||||
EXPECT_FALSE(crs->baseCRS()->isEquivalentTo(crs.get()));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(crs, DerivedVerticalCRS_WKT2) {
|
||||
|
||||
auto expected = "VERTCRS[\"Derived vertCRS\",\n"
|
||||
@@ -5976,10 +5989,6 @@ TEST(crs, DerivedVerticalCRS_WKT2) {
|
||||
" ID[\"EPSG\",9001]]]]";
|
||||
|
||||
auto crs = createDerivedVerticalCRS();
|
||||
EXPECT_TRUE(crs->isEquivalentTo(crs.get()));
|
||||
EXPECT_TRUE(crs->shallowClone()->isEquivalentTo(crs.get()));
|
||||
EXPECT_TRUE(!crs->isEquivalentTo(createUnrelatedObject().get()));
|
||||
|
||||
EXPECT_EQ(crs->exportToWKT(
|
||||
WKTFormatter::create(WKTFormatter::Convention::WKT2).get()),
|
||||
expected);
|
||||
@@ -6484,6 +6493,19 @@ TEST(crs, crs_alterCSLinearUnit) {
|
||||
EXPECT_EQ(cs->axisList()[1]->unit().conversionToSI(), 2);
|
||||
}
|
||||
|
||||
{
|
||||
auto crs = createDerivedProjectedCRS()->alterCSLinearUnit(
|
||||
UnitOfMeasure("my unit", 2));
|
||||
auto derivedProjCRS = dynamic_cast<DerivedProjectedCRS *>(crs.get());
|
||||
ASSERT_TRUE(derivedProjCRS != nullptr);
|
||||
auto cs = derivedProjCRS->coordinateSystem();
|
||||
ASSERT_EQ(cs->axisList().size(), 2U);
|
||||
EXPECT_EQ(cs->axisList()[0]->unit().name(), "my unit");
|
||||
EXPECT_EQ(cs->axisList()[0]->unit().conversionToSI(), 2);
|
||||
EXPECT_EQ(cs->axisList()[1]->unit().name(), "my unit");
|
||||
EXPECT_EQ(cs->axisList()[1]->unit().conversionToSI(), 2);
|
||||
}
|
||||
|
||||
{
|
||||
auto crs = GeodeticCRS::EPSG_4978->alterCSLinearUnit(
|
||||
UnitOfMeasure("my unit", 2));
|
||||
@@ -6791,6 +6813,47 @@ TEST(crs, promoteTo3D_and_demoteTo2D) {
|
||||
EXPECT_TRUE(demoted->demoteTo2D(std::string(), nullptr)
|
||||
->isEquivalentTo(demoted.get()));
|
||||
}
|
||||
|
||||
{
|
||||
auto crs = createDerivedProjectedCRS();
|
||||
auto crs3D = crs->promoteTo3D(std::string(), dbContext);
|
||||
auto crs3DAsDerivedProj =
|
||||
nn_dynamic_pointer_cast<DerivedProjectedCRS>(crs3D);
|
||||
ASSERT_TRUE(crs3DAsDerivedProj != nullptr);
|
||||
EXPECT_EQ(crs3DAsDerivedProj->baseCRS()
|
||||
->coordinateSystem()
|
||||
->axisList()
|
||||
.size(),
|
||||
3U);
|
||||
EXPECT_EQ(crs3DAsDerivedProj->coordinateSystem()->axisList().size(),
|
||||
3U);
|
||||
EXPECT_TRUE(crs3DAsDerivedProj->promoteTo3D(std::string(), nullptr)
|
||||
->isEquivalentTo(crs3DAsDerivedProj.get()));
|
||||
|
||||
// Check that importing an exported DerivedProjected 3D CRS as WKT keeps
|
||||
// the 3D aspect of the baseCRS (see #3340)
|
||||
{
|
||||
WKTFormatterNNPtr f(
|
||||
WKTFormatter::create(WKTFormatter::Convention::WKT2_2019));
|
||||
crs3DAsDerivedProj->exportToWKT(f.get());
|
||||
auto obj = WKTParser().createFromWKT(f->toString());
|
||||
auto crsFromWkt = nn_dynamic_pointer_cast<DerivedProjectedCRS>(obj);
|
||||
ASSERT_TRUE(crsFromWkt != nullptr);
|
||||
EXPECT_EQ(crsFromWkt->coordinateSystem()->axisList().size(), 3U);
|
||||
EXPECT_EQ(
|
||||
crsFromWkt->baseCRS()->coordinateSystem()->axisList().size(),
|
||||
3U);
|
||||
}
|
||||
|
||||
auto demoted = crs3DAsDerivedProj->demoteTo2D(std::string(), dbContext);
|
||||
EXPECT_EQ(demoted->baseCRS()->coordinateSystem()->axisList().size(),
|
||||
2U);
|
||||
EXPECT_EQ(demoted->coordinateSystem()->axisList().size(), 2U);
|
||||
EXPECT_TRUE(demoted->isEquivalentTo(
|
||||
crs.get(), IComparable::Criterion::EQUIVALENT));
|
||||
EXPECT_TRUE(demoted->demoteTo2D(std::string(), nullptr)
|
||||
->isEquivalentTo(demoted.get()));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
+63
-9
@@ -8942,6 +8942,49 @@ TEST(io, projstringformatter_optim_hgridshift_vgridshift_hgridshift_inv) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(io, projstringformatter_optim_as_uc_vgridshift_uc_as_push_as_uc) {
|
||||
// Nominal case
|
||||
{
|
||||
auto fmt = PROJStringFormatter::create();
|
||||
fmt->addStep("axisswap");
|
||||
fmt->addParam("order", "2,1");
|
||||
|
||||
fmt->addStep("unitconvert");
|
||||
fmt->addParam("xy_in", "deg");
|
||||
fmt->addParam("xy_out", "rad");
|
||||
|
||||
fmt->addStep("vgridshift");
|
||||
fmt->addParam("grids", "foo");
|
||||
|
||||
fmt->addStep("unitconvert");
|
||||
fmt->addParam("xy_in", "rad");
|
||||
fmt->addParam("xy_out", "deg");
|
||||
|
||||
fmt->addStep("axisswap");
|
||||
fmt->addParam("order", "2,1");
|
||||
|
||||
fmt->addStep("push");
|
||||
fmt->addParam("v_1");
|
||||
fmt->addParam("v_2");
|
||||
|
||||
fmt->addStep("axisswap");
|
||||
fmt->addParam("order", "2,1");
|
||||
|
||||
fmt->addStep("unitconvert");
|
||||
fmt->addParam("xy_in", "deg");
|
||||
fmt->addParam("xy_out", "rad");
|
||||
|
||||
EXPECT_EQ(fmt->toString(),
|
||||
"+proj=pipeline "
|
||||
"+step +proj=push +v_1 +v_2 "
|
||||
"+step +proj=axisswap +order=2,1 "
|
||||
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
|
||||
"+step +proj=vgridshift +grids=foo");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(io, projparse_longlat) {
|
||||
|
||||
auto expected = "GEODCRS[\"unknown\",\n"
|
||||
@@ -11062,10 +11105,11 @@ TEST(io, projparse_cart_unit) {
|
||||
GeographicCRS::EPSG_4326, NN_NO_CHECK(crs));
|
||||
ASSERT_TRUE(op != nullptr);
|
||||
EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
|
||||
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=cart "
|
||||
"+ellps=WGS84 +step +proj=unitconvert +xy_in=m +z_in=m "
|
||||
"+xy_out=km +z_out=km");
|
||||
"+proj=pipeline "
|
||||
"+step +proj=axisswap +order=2,1 "
|
||||
"+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m "
|
||||
"+step +proj=cart +ellps=WGS84 "
|
||||
"+step +proj=unitconvert +xy_in=m +z_in=m +xy_out=km +z_out=km");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -11080,11 +11124,13 @@ TEST(io, projparse_cart_unit_numeric) {
|
||||
auto op = CoordinateOperationFactory::create()->createOperation(
|
||||
GeographicCRS::EPSG_4326, NN_NO_CHECK(crs));
|
||||
ASSERT_TRUE(op != nullptr);
|
||||
EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
|
||||
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=cart "
|
||||
"+ellps=WGS84 +step +proj=unitconvert +xy_in=m +z_in=m "
|
||||
"+xy_out=500 +z_out=500");
|
||||
EXPECT_EQ(
|
||||
op->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
"+proj=pipeline "
|
||||
"+step +proj=axisswap +order=2,1 "
|
||||
"+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m "
|
||||
"+step +proj=cart +ellps=WGS84 "
|
||||
"+step +proj=unitconvert +xy_in=m +z_in=m +xy_out=500 +z_out=500");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -11865,6 +11911,14 @@ TEST(io, createFromUserInput) {
|
||||
EXPECT_NO_THROW(createFromUserInput("WGS84 UTM zone 31N", dbContext));
|
||||
EXPECT_NO_THROW(createFromUserInput("ID74", dbContext));
|
||||
|
||||
{
|
||||
// Approximate match of a vertical CRS
|
||||
auto obj = createFromUserInput("NGF IGN69 height", dbContext);
|
||||
auto crs = nn_dynamic_pointer_cast<VerticalCRS>(obj);
|
||||
EXPECT_TRUE(crs != nullptr);
|
||||
EXPECT_EQ(crs->nameStr(), "NGF-IGN69 height");
|
||||
}
|
||||
|
||||
{
|
||||
// Exact match on each piece of the compound CRS
|
||||
auto obj = createFromUserInput("WGS 84 + EGM96 height", dbContext);
|
||||
|
||||
@@ -550,7 +550,7 @@ TEST(operation, geogCRS_to_geogCRS_context_helmert_geog3D_to_geocentirc) {
|
||||
authFactory->createCoordinateReferenceSystem("4939"),
|
||||
// GDA2020 geocentric
|
||||
authFactory->createCoordinateReferenceSystem("7842"), ctxt);
|
||||
ASSERT_EQ(list.size(), 1U);
|
||||
ASSERT_GE(list.size(), 1U);
|
||||
|
||||
// Check there is no push / pop of v_3
|
||||
EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
@@ -635,6 +635,73 @@ TEST(operation, geogCRS_to_geogCRS_context_datum_ensemble) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(operation, geogCRS_to_derived_geogCRS_3D) {
|
||||
auto authFactory =
|
||||
AuthorityFactory::create(DatabaseContext::create(), "EPSG");
|
||||
auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0);
|
||||
ctxt->setSpatialCriterion(
|
||||
CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
|
||||
|
||||
auto dst_wkt =
|
||||
"GEOGCRS[\"CH1903+ with 10m offset on ellipsoidal height\",\n"
|
||||
" BASEGEOGCRS[\"CH1903+\",\n"
|
||||
" DATUM[\"CH1903+\",\n"
|
||||
" ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128,\n"
|
||||
" LENGTHUNIT[\"metre\",1]],\n"
|
||||
" ID[\"EPSG\",6150]],\n"
|
||||
" PRIMEM[\"Greenwich\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8901]]],\n"
|
||||
" DERIVINGCONVERSION[\"Offset on ellipsoidal height\",\n"
|
||||
" METHOD[\"Geographic3D offsets\",\n"
|
||||
" ID[\"EPSG\",9660]],\n"
|
||||
" PARAMETER[\"Latitude offset\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8601]],\n"
|
||||
" PARAMETER[\"Longitude offset\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8602]],\n"
|
||||
" PARAMETER[\"Vertical Offset\",10,\n"
|
||||
" LENGTHUNIT[\"metre\",1],\n"
|
||||
" ID[\"EPSG\",8603]]],\n"
|
||||
" CS[ellipsoidal,3],\n"
|
||||
" AXIS[\"geodetic latitude (Lat)\",north,\n"
|
||||
" ORDER[1],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
|
||||
" ID[\"EPSG\",9122]]],\n"
|
||||
" AXIS[\"geodetic longitude (Lon)\",east,\n"
|
||||
" ORDER[2],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
|
||||
" ID[\"EPSG\",9122]]],\n"
|
||||
" AXIS[\"ellipsoidal height (h)\",up,\n"
|
||||
" ORDER[3],\n"
|
||||
" LENGTHUNIT[\"metre\",1,\n"
|
||||
" ID[\"EPSG\",9001]]]]";
|
||||
auto dstObj = WKTParser().createFromWKT(dst_wkt);
|
||||
auto dstCRS = nn_dynamic_pointer_cast<CRS>(dstObj);
|
||||
ASSERT_TRUE(dstCRS != nullptr);
|
||||
|
||||
auto list = CoordinateOperationFactory::create()->createOperations(
|
||||
authFactory->createCoordinateReferenceSystem("4979"), // WGS 84 3D
|
||||
NN_NO_CHECK(dstCRS), ctxt);
|
||||
ASSERT_GE(list.size(), 1U);
|
||||
EXPECT_EQ(
|
||||
list[0]->nameStr(),
|
||||
"Inverse of CH1903+ to WGS 84 (1) + Offset on ellipsoidal height");
|
||||
EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
"+proj=pipeline "
|
||||
"+step +proj=axisswap +order=2,1 "
|
||||
"+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m "
|
||||
"+step +proj=cart +ellps=WGS84 "
|
||||
"+step +proj=helmert +x=-674.374 +y=-15.056 +z=-405.346 "
|
||||
"+step +inv +proj=cart +ellps=bessel "
|
||||
"+step +proj=geogoffset +dlat=0 +dlon=0 +dh=10 "
|
||||
"+step +proj=unitconvert +xy_in=rad +z_in=m +xy_out=deg +z_out=m "
|
||||
"+step +proj=axisswap +order=2,1");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(operation, vertCRS_to_geogCRS_context) {
|
||||
auto authFactory =
|
||||
AuthorityFactory::create(DatabaseContext::create(), "EPSG");
|
||||
@@ -1331,13 +1398,13 @@ TEST(operation, geocentricCRS_to_geogCRS_different_datum) {
|
||||
createGeocentricDatumWGS84(), GeographicCRS::EPSG_4269);
|
||||
ASSERT_TRUE(op != nullptr);
|
||||
EXPECT_EQ(op->nameStr(),
|
||||
"Ballpark geocentric translation from WGS 84 to NAD83 "
|
||||
"(geocentric) + Conversion from NAD83 "
|
||||
"(geocentric) to NAD83");
|
||||
"Conversion from WGS 84 to WGS 84 (geographic) + "
|
||||
"Ballpark geographic offset from WGS 84 (geographic) to NAD83");
|
||||
EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
"+proj=pipeline +step +inv +proj=cart +ellps=GRS80 +step "
|
||||
"+proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap "
|
||||
"+order=2,1");
|
||||
"+proj=pipeline "
|
||||
"+step +inv +proj=cart +ellps=WGS84 "
|
||||
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
|
||||
"+step +proj=axisswap +order=2,1");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1347,13 +1414,14 @@ TEST(operation, geogCRS_to_geocentricCRS_different_datum) {
|
||||
auto op = CoordinateOperationFactory::create()->createOperation(
|
||||
GeographicCRS::EPSG_4269, createGeocentricDatumWGS84());
|
||||
ASSERT_TRUE(op != nullptr);
|
||||
EXPECT_EQ(op->nameStr(), "Conversion from NAD83 to NAD83 (geocentric) + "
|
||||
"Ballpark geocentric translation from NAD83 "
|
||||
"(geocentric) to WGS 84");
|
||||
EXPECT_EQ(op->nameStr(),
|
||||
"Ballpark geographic offset from NAD83 to WGS 84 (geographic) + "
|
||||
"Conversion from WGS 84 (geographic) to WGS 84");
|
||||
EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
|
||||
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=cart "
|
||||
"+ellps=GRS80");
|
||||
"+proj=pipeline "
|
||||
"+step +proj=axisswap +order=2,1 "
|
||||
"+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m "
|
||||
"+step +proj=cart +ellps=WGS84");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1766,6 +1834,87 @@ TEST(operation, geogCRS_to_geogCRS_WGS84_to_GDA2020) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(operation, geogCRS_to_geogCRS_with_intermediate_no_ids) {
|
||||
|
||||
auto dbContext = DatabaseContext::create();
|
||||
auto authFactory = AuthorityFactory::create(dbContext, std::string());
|
||||
auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0);
|
||||
ctxt->setSpatialCriterion(
|
||||
CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
|
||||
ctxt->setGridAvailabilityUse(
|
||||
CoordinateOperationContext::GridAvailabilityUse::
|
||||
IGNORE_GRID_AVAILABILITY);
|
||||
|
||||
auto objSrc = WKTParser().createFromWKT(
|
||||
"GEOGCRS[\"input\",\n"
|
||||
" DATUM[\"International Terrestrial Reference Frame 2014\",\n"
|
||||
" ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n"
|
||||
" LENGTHUNIT[\"metre\",1]],\n"
|
||||
" ID[\"EPSG\",1165]],\n"
|
||||
" PRIMEM[\"Greenwich\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8901]],\n"
|
||||
" CS[ellipsoidal,3],\n"
|
||||
" AXIS[\"longitude\",east,\n"
|
||||
" ORDER[1],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
|
||||
" ID[\"EPSG\",9122]]],\n"
|
||||
" AXIS[\"latitude\",north,\n"
|
||||
" ORDER[2],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
|
||||
" ID[\"EPSG\",9122]]],\n"
|
||||
" AXIS[\"ellipsoidal height (h)\",up,\n"
|
||||
" ORDER[3],\n"
|
||||
" LENGTHUNIT[\"metre\",1]]]");
|
||||
auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
|
||||
ASSERT_TRUE(src != nullptr);
|
||||
|
||||
auto objDest = WKTParser().createFromWKT(
|
||||
"GEOGCRS[\"output\",\n"
|
||||
" DATUM[\"Estonia 1997\",\n"
|
||||
" ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n"
|
||||
" LENGTHUNIT[\"metre\",1]],\n"
|
||||
" ID[\"EPSG\",6180]],\n"
|
||||
" PRIMEM[\"Greenwich\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8901]],\n"
|
||||
" CS[ellipsoidal,3],\n"
|
||||
" AXIS[\"longitude\",east,\n"
|
||||
" ORDER[1],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
|
||||
" ID[\"EPSG\",9122]]],\n"
|
||||
" AXIS[\"latitude\",north,\n"
|
||||
" ORDER[2],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
|
||||
" ID[\"EPSG\",9122]]],\n"
|
||||
" AXIS[\"ellipsoidal height (h)\",up,\n"
|
||||
" ORDER[3],\n"
|
||||
" LENGTHUNIT[\"metre\",1]]]");
|
||||
auto dest = nn_dynamic_pointer_cast<CRS>(objDest);
|
||||
ASSERT_TRUE(dest != nullptr);
|
||||
|
||||
{
|
||||
auto list = CoordinateOperationFactory::create()->createOperations(
|
||||
NN_NO_CHECK(src), NN_NO_CHECK(dest), ctxt);
|
||||
ASSERT_GE(list.size(), 1U);
|
||||
// Test that a non-noop operation is returned
|
||||
EXPECT_EQ(
|
||||
list[0]->nameStr(),
|
||||
"axis order change (geographic3D horizontal) + "
|
||||
"Conversion from ITRF2014 (geog3D) to ITRF2014 (geocentric) + "
|
||||
"ITRF2014 to ETRF2014 (1) + "
|
||||
"Inverse of NKG_ETRF14 to ETRF2014 + "
|
||||
"NKG_ETRF14 to ETRF96@2000.0 + "
|
||||
"ETRF96@2000.0 to ETRF96@1997.56 + "
|
||||
"Conversion from ETRS89 (geocentric) to ETRS89 (geog2D) + "
|
||||
"Inverse of EST97 to ETRS89 (1) + "
|
||||
"Null geographic offset from EST97 (geog2D) to EST97 (geog3D) + "
|
||||
"axis order change (geographic3D horizontal)");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static ProjectedCRSNNPtr createUTM31_WGS84() {
|
||||
return ProjectedCRS::create(
|
||||
PropertyMap(), GeographicCRS::EPSG_4326,
|
||||
@@ -4991,6 +5140,63 @@ TEST(operation, compoundCRS_to_compoundCRS_issue_2720) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(operation, compoundCRS_to_compoundCRS_issue_3328) {
|
||||
auto authFactory =
|
||||
AuthorityFactory::create(DatabaseContext::create(), std::string());
|
||||
// "WGS 84 + EGM96 height"
|
||||
auto srcObj = createFromUserInput("EPSG:4326+5773",
|
||||
authFactory->databaseContext(), false);
|
||||
auto src = nn_dynamic_pointer_cast<CRS>(srcObj);
|
||||
ASSERT_TRUE(src != nullptr);
|
||||
|
||||
// "WGS 84 + CGVD28 height"
|
||||
auto dstObj = createFromUserInput("EPSG:4326+5713",
|
||||
authFactory->databaseContext(), false);
|
||||
auto dst = nn_dynamic_pointer_cast<CRS>(dstObj);
|
||||
ASSERT_TRUE(dst != nullptr);
|
||||
|
||||
auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0);
|
||||
ctxt->setGridAvailabilityUse(
|
||||
CoordinateOperationContext::GridAvailabilityUse::
|
||||
IGNORE_GRID_AVAILABILITY);
|
||||
ctxt->setSpatialCriterion(
|
||||
CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
|
||||
auto list = CoordinateOperationFactory::create()->createOperations(
|
||||
NN_NO_CHECK(src), NN_NO_CHECK(dst), ctxt);
|
||||
ASSERT_GE(list.size(), 1U);
|
||||
EXPECT_EQ(list[0]->nameStr(), "Inverse of WGS 84 to EGM96 height (1) + "
|
||||
"Inverse of NAD83(CSRS) to WGS 84 (2) + "
|
||||
"NAD83(CSRS) to CGVD28 height (1) + "
|
||||
"NAD83(CSRS) to WGS 84 (2)");
|
||||
EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()),
|
||||
"+proj=pipeline "
|
||||
"+step +proj=push +v_1 +v_2 "
|
||||
"+step +proj=axisswap +order=2,1 "
|
||||
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
|
||||
"+step +proj=vgridshift +grids=us_nga_egm96_15.tif +multiplier=1 "
|
||||
"+step +proj=cart +ellps=WGS84 "
|
||||
"+step +inv +proj=helmert +x=-0.991 +y=1.9072 +z=0.5129 "
|
||||
"+rx=-0.0257899075194932 "
|
||||
"+ry=-0.0096500989602704 +rz=-0.0116599432323421 +s=0 "
|
||||
"+convention=coordinate_frame "
|
||||
"+step +inv +proj=cart +ellps=GRS80 "
|
||||
"+step +inv +proj=vgridshift +grids=ca_nrc_HT2_2010v70.tif "
|
||||
"+multiplier=1 "
|
||||
"+step +proj=push +v_3 "
|
||||
"+step +proj=cart +ellps=GRS80 "
|
||||
"+step +proj=helmert +x=-0.991 +y=1.9072 +z=0.5129 "
|
||||
"+rx=-0.0257899075194932 "
|
||||
"+ry=-0.0096500989602704 +rz=-0.0116599432323421 +s=0 "
|
||||
"+convention=coordinate_frame "
|
||||
"+step +inv +proj=cart +ellps=WGS84 "
|
||||
"+step +proj=pop +v_3 "
|
||||
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
|
||||
"+step +proj=axisswap +order=2,1 "
|
||||
"+step +proj=pop +v_1 +v_2");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(
|
||||
operation,
|
||||
compoundCRS_to_compoundCRS_concatenated_operation_with_two_vert_transformation_and_ballpark_geog) {
|
||||
@@ -6593,6 +6799,151 @@ TEST(operation,
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(operation, compoundCRS_of_bound_horizCRS_and_bound_vertCRS_to_geogCRS) {
|
||||
auto authFactory =
|
||||
AuthorityFactory::create(DatabaseContext::create(), "EPSG");
|
||||
auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0);
|
||||
ctxt->setGridAvailabilityUse(
|
||||
CoordinateOperationContext::GridAvailabilityUse::
|
||||
IGNORE_GRID_AVAILABILITY);
|
||||
auto wkt =
|
||||
"COMPOUNDCRS[\"CH1903 / LV03 + EGM96 height\",\n"
|
||||
" BOUNDCRS[\n"
|
||||
" SOURCECRS[\n"
|
||||
" PROJCRS[\"CH1903 / LV03\",\n"
|
||||
" BASEGEOGCRS[\"CH1903\",\n"
|
||||
" DATUM[\"CH1903\",\n"
|
||||
" ELLIPSOID[\"Bessel "
|
||||
"1841\",6377397.155,299.1528128,\n"
|
||||
" LENGTHUNIT[\"metre\",1]]],\n"
|
||||
" PRIMEM[\"Greenwich\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
|
||||
" ID[\"EPSG\",4149]],\n"
|
||||
" CONVERSION[\"Swiss Oblique Mercator 1903M\",\n"
|
||||
" METHOD[\"Hotine Oblique Mercator (variant B)\",\n"
|
||||
" ID[\"EPSG\",9815]],\n"
|
||||
" PARAMETER[\"Latitude of projection "
|
||||
"centre\",46.9524055555556,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8811]],\n"
|
||||
" PARAMETER[\"Longitude of projection "
|
||||
"centre\",7.43958333333333,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8812]],\n"
|
||||
" PARAMETER[\"Azimuth of initial line\",90,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8813]],\n"
|
||||
" PARAMETER[\"Angle from Rectified to Skew "
|
||||
"Grid\",90,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433],\n"
|
||||
" ID[\"EPSG\",8814]],\n"
|
||||
" PARAMETER[\"Scale factor on initial line\",1,\n"
|
||||
" SCALEUNIT[\"unity\",1],\n"
|
||||
" ID[\"EPSG\",8815]],\n"
|
||||
" PARAMETER[\"Easting at projection "
|
||||
"centre\",600000,\n"
|
||||
" LENGTHUNIT[\"metre\",1],\n"
|
||||
" ID[\"EPSG\",8816]],\n"
|
||||
" PARAMETER[\"Northing at projection "
|
||||
"centre\",200000,\n"
|
||||
" LENGTHUNIT[\"metre\",1],\n"
|
||||
" ID[\"EPSG\",8817]]],\n"
|
||||
" CS[Cartesian,2],\n"
|
||||
" AXIS[\"easting (Y)\",east,\n"
|
||||
" ORDER[1],\n"
|
||||
" LENGTHUNIT[\"metre\",1]],\n"
|
||||
" AXIS[\"northing (X)\",north,\n"
|
||||
" ORDER[2],\n"
|
||||
" LENGTHUNIT[\"metre\",1]]]],\n"
|
||||
" TARGETCRS[\n"
|
||||
" GEOGCRS[\"WGS 84\",\n"
|
||||
" DATUM[\"World Geodetic System 1984\",\n"
|
||||
" ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
|
||||
" LENGTHUNIT[\"metre\",1]]],\n"
|
||||
" PRIMEM[\"Greenwich\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
|
||||
" CS[ellipsoidal,2],\n"
|
||||
" AXIS[\"latitude\",north,\n"
|
||||
" ORDER[1],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
|
||||
" AXIS[\"longitude\",east,\n"
|
||||
" ORDER[2],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
|
||||
" ID[\"EPSG\",4326]]],\n"
|
||||
" ABRIDGEDTRANSFORMATION[\"CH1903 to WGS 84 (2)\",\n"
|
||||
" VERSION[\"BfL-CH 2\"],\n"
|
||||
" METHOD[\"Geocentric translations (geog2D domain)\",\n"
|
||||
" ID[\"EPSG\",9603]],\n"
|
||||
" PARAMETER[\"X-axis translation\",674.374,\n"
|
||||
" ID[\"EPSG\",8605]],\n"
|
||||
" PARAMETER[\"Y-axis translation\",15.056,\n"
|
||||
" ID[\"EPSG\",8606]],\n"
|
||||
" PARAMETER[\"Z-axis translation\",405.346,\n"
|
||||
" ID[\"EPSG\",8607]]]],\n"
|
||||
" BOUNDCRS[\n"
|
||||
" SOURCECRS[\n"
|
||||
" VERTCRS[\"EGM96 height\",\n"
|
||||
" VDATUM[\"EGM96 geoid\"],\n"
|
||||
" CS[vertical,1],\n"
|
||||
" AXIS[\"gravity-related height (H)\",up,\n"
|
||||
" LENGTHUNIT[\"metre\",1]],\n"
|
||||
" USAGE[\n"
|
||||
" SCOPE[\"Geodesy.\"],\n"
|
||||
" AREA[\"World.\"],\n"
|
||||
" BBOX[-90,-180,90,180]],\n"
|
||||
" ID[\"EPSG\",5773]]],\n"
|
||||
" TARGETCRS[\n"
|
||||
" GEOGCRS[\"WGS 84\",\n"
|
||||
" DATUM[\"World Geodetic System 1984\",\n"
|
||||
" ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
|
||||
" LENGTHUNIT[\"metre\",1]]],\n"
|
||||
" PRIMEM[\"Greenwich\",0,\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
|
||||
" CS[ellipsoidal,3],\n"
|
||||
" AXIS[\"latitude\",north,\n"
|
||||
" ORDER[1],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
|
||||
" AXIS[\"longitude\",east,\n"
|
||||
" ORDER[2],\n"
|
||||
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
|
||||
" AXIS[\"ellipsoidal height\",up,\n"
|
||||
" ORDER[3],\n"
|
||||
" LENGTHUNIT[\"metre\",1]],\n"
|
||||
" ID[\"EPSG\",4979]]],\n"
|
||||
" ABRIDGEDTRANSFORMATION[\"WGS 84 to EGM96 height (1)\",\n"
|
||||
" METHOD[\"Geographic3D to GravityRelatedHeight (EGM)\",\n"
|
||||
" ID[\"EPSG\",9661]],\n"
|
||||
" PARAMETERFILE[\"Geoid (height correction) model "
|
||||
"file\",\"us_nga_egm96_15.tif\"]]]]";
|
||||
auto srcObj =
|
||||
createFromUserInput(wkt, authFactory->databaseContext(), false);
|
||||
auto src = nn_dynamic_pointer_cast<CRS>(srcObj);
|
||||
ASSERT_TRUE(src != nullptr);
|
||||
// WGS 84 3D
|
||||
auto dst = authFactory->createCoordinateReferenceSystem("4979");
|
||||
|
||||
auto list = CoordinateOperationFactory::create()->createOperations(
|
||||
NN_NO_CHECK(src), dst, ctxt);
|
||||
ASSERT_EQ(list.size(), 1U);
|
||||
auto op_proj =
|
||||
list[0]->exportToPROJString(PROJStringFormatter::create().get());
|
||||
EXPECT_EQ(op_proj,
|
||||
"+proj=pipeline "
|
||||
"+step +inv +proj=somerc +lat_0=46.9524055555556 "
|
||||
"+lon_0=7.43958333333333 +k_0=1 "
|
||||
"+x_0=600000 +y_0=200000 +ellps=bessel "
|
||||
"+step +proj=push +v_3 "
|
||||
"+step +proj=cart +ellps=bessel "
|
||||
"+step +proj=helmert +x=674.374 +y=15.056 +z=405.346 "
|
||||
"+step +inv +proj=cart +ellps=WGS84 "
|
||||
"+step +proj=pop +v_3 "
|
||||
"+step +proj=vgridshift +grids=us_nga_egm96_15.tif +multiplier=1 "
|
||||
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
|
||||
"+step +proj=axisswap +order=2,1");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(operation, compoundCRS_from_WKT2_to_geogCRS_3D_context) {
|
||||
auto authFactory =
|
||||
AuthorityFactory::create(DatabaseContext::create(), "EPSG");
|
||||
|
||||
@@ -5,7 +5,7 @@ set -e
|
||||
echo "$TRAVIS_SECURE_ENV_VARS"
|
||||
./travis/build_docs.sh
|
||||
# Only build and publish docs when changes are made on most recent maintenance branch
|
||||
if test "$TRAVIS_SECURE_ENV_VARS" = "true" -a "$TRAVIS_BRANCH" = "9.0"; then
|
||||
if test "$TRAVIS_SECURE_ENV_VARS" = "true" -a "$TRAVIS_BRANCH" = "9.1"; then
|
||||
echo "publish website";
|
||||
./travis/add_deploy_key.sh;
|
||||
./travis/deploy_website.sh $TRAVIS_BUILD_DIR/docs/build /tmp;
|
||||
|
||||
Reference in New Issue
Block a user