1 : /**********************************************************************
2 : * $Id: geoconcept_syscoord.c
3 : *
4 : * Name: geoconcept_syscoord.c
5 : * Project: OpenGIS Simple Features Reference Implementation
6 : * Purpose: Implements translation between Geoconcept SysCoord
7 : * and OGRSpatialRef format
8 : * Language: C
9 : *
10 : **********************************************************************
11 : * Copyright (c) 2007, Geoconcept and IGN
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : **********************************************************************/
31 :
32 : #include "geoconcept_syscoord.h"
33 : #include "cpl_string.h"
34 :
35 0 : GCSRS_CVSID("$Id: geoconcept_syscoord.c,v 1.0.0 2007-12-24 15:40:28 drichard Exp $")
36 :
37 : #ifndef PI
38 : #define PI 3.14159265358979323846
39 : #endif
40 :
41 :
42 : /* -------------------------------------------------------------------- */
43 : /* GCSRS globals */
44 : /* -------------------------------------------------------------------- */
45 :
46 : /*
47 : * The following information came from GEO CONCEPT PROJECTION files,
48 : * aka GCP files.
49 : * A lot of information has been added to these GCP. There are mostly
50 : * noticed as FIXME in the source.
51 : */
52 :
53 : static GCSysCoord gk_asSysCoordList[]=
54 : /*
55 : * pszSysCoordName, pszUnit, dfPM, dfLambda0, dfPhi0, dfk0, dfX0, dfY0, dfPhi1, dfPhi2, nDatumID, nProjID, coordSystemID, timeZoneValue
56 : *
57 : * #12, #14, #15, #17 : parameters listed below are "generic" ...
58 : *
59 : * Geoconcept uses cos(lat_ts) as scale factor, but cos(lat_ts)==cos(-lat_ts) : I then set dfPhi1 with lat_ts
60 : */
61 : {
62 : {"Lambert 2 extended", NULL, 2.337229166667, 0.000000000, 46.80000000,0.99987742000, 600000.000, 2200000.000, 0.0, 0.0, 13, 2, 1,-1},
63 : {"Lambert 1", NULL, 2.337229166667, 0.000000000, 49.50000000,0.99987734000, 600000.000, 200000.000, 0.0, 0.0, 13, 2, 2,-1},
64 : {"Lambert 2", NULL, 2.337229166667, 0.000000000, 46.80000000,0.99987742000, 600000.000, 200000.000, 0.0, 0.0, 13, 2, 3,-1},
65 : {"Lambert 3", NULL, 2.337229166667, 0.000000000, 44.10000000,0.99987750000, 600000.000, 200000.000, 0.0, 0.0, 13, 2, 4,-1},
66 : {"Lambert 4", NULL, 2.337229166667, 0.000000000, 42.16500000,0.99994471000, 234.358, 185861.369, 0.0, 0.0, 13, 2, 5,-1},
67 : {"Bonne NTF", NULL, 2.337222222222, 0.000000000, 48.86000000,1.00000000000, 0.000, 0.000, 0.0, 0.0, 1, 3, 11,-1},
68 : {"UTM Nord - ED50", NULL, 0.000000000000, 0.000000000, 0.00000000,0.99960000000, 500000.000, 0.000, 0.0, 0.0, 14, 1, 12, 0},
69 : {"Plate carrée", NULL, 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 11, 4, 13,-1},
70 : {"MGRS (Military UTM)", NULL, 0.000000000000, 0.000000000, 0.00000000,0.99960000000, 0.000, 0.000, 0.0, 0.0, 4, 11, 14,-1},
71 : {"UTM Sud - WGS84", NULL, 0.000000000000, 0.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0, 4, 1, 15, 0},
72 : {"National GB projection", NULL, 0.000000000000, -2.000000000, 49.00000000,0.99960127170, 400000.000, -100000.000, 0.0, 0.0, 12, 12, 16,-1},
73 : {"UTM Nord - WGS84", NULL, 0.000000000000, 0.000000000, 0.00000000,0.99960000000, 500000.000, 0.000, 0.0, 0.0, 4, 1, 17, 0},
74 : {"UTM Nord - WGS84", NULL, 0.000000000000, 0.000000000, 0.00000000,0.99960000000, 500000.000, 0.000, 0.0, 0.0,9990, 1, 17, 0},
75 : {"Lambert 2 étendu - sans grille", NULL, 2.337229166667, 0.000000000, 46.80000000,0.99987742000, 600000.000, 2200000.000, 0.0, 0.0, 1, 2, 91,-1},
76 : {"Lambert 1 - sans grille", NULL, 2.337229166667, 0.000000000, 49.50000000,0.99987734000, 600000.000, 200000.000, 0.0, 0.0, 1, 2, 92,-1},
77 : {"Lambert 2 - sans grille", NULL, 2.337229166667, 0.000000000, 46.80000000,0.99987742000, 600000.000, 200000.000, 0.0, 0.0, 1, 2, 93,-1},
78 : {"Lambert 3 - sans grille", NULL, 2.337229166667, 0.000000000, 44.10000000,0.99987750000, 600000.000, 200000.000, 0.0, 0.0, 1, 2, 94,-1},
79 : {"Lambert 4 - sans grille", NULL, 2.337229166667, 0.000000000, 42.16500000,0.99994471000, 234.358, 185861.369, 0.0, 0.0, 1, 2, 95,-1},
80 : {"(Long/Lat) NTF", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 1, 0, 100,-1},
81 : {"(Long/Lat) WGS84", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 4, 0, 101,-1},
82 : {"(Long/Lat) ED50", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 14, 0, 102,-1},
83 : {"(Long/Lat) Australian 1984", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 7, 0, 103,-1},
84 : {"(Long/Lat) Airy", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 12, 0, 104,-1},
85 : {"(Long/Lat) NTF Paris (gr)", "gr", 2.337229166667, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 1, 0, 105,-1},
86 : {"(Long/Lat) WGS 72", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 3, 0, 107,-1},
87 : {"Geoportail MILLER", NULL, 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 4, 24, 222,-1},
88 : {"IGN-RRAFGUADU20", NULL, 0.000000000000, -63.000000000, 0.00000000,0.99960000000, 500000.000, 0.000, 0.0, 0.0,9984, 1, 501,-1},/* FIXME does not exist in IGNF, use IGN-UTM20W84GUAD instead */
89 : {"IGN-RRAFMARTU20", NULL, 0.000000000000, -63.000000000, 0.00000000,0.99960000000, 500000.000, 0.000, 0.0, 0.0,9984, 1, 502,-1},/* FIXME does not exist in IGNF, use IGN-UTM20W84MART instead, never reached cause identical to 501:-1 */
90 : {"IGN-RGM04UTM38S", NULL, 0.000000000000, 45.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 503,-1},/* FIXME 5030 datum changed into 9984 */
91 : {"IGN-RGR92UTM40S", NULL, 0.000000000000, 57.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 504,-1},
92 : {"IGN-UTM22RGFG95", NULL, 0.000000000000, -51.000000000, 0.00000000,0.99960000000, 500000.000, 0.000, 0.0, 0.0,9984, 1, 505,-1},
93 : {"IGN-UTM01SWG84", NULL, 0.000000000000,-177.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 506,-1},/* never reached cause identical to 15:1 */
94 : {"IGN-RGSPM06U21", NULL, 0.000000000000, -57.000000000, 0.00000000,0.99960000000, 500000.000, 0.000, 0.0, 0.0,9984, 1, 507,-1},
95 : {"IGN-RGPFUTM5S", NULL, 0.000000000000,-153.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 508,-1},
96 : {"IGN-RGPFUTM6S", NULL, 0.000000000000,-147.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 509,-1},
97 : {"IGN-RGPFUTM7S", NULL, 0.000000000000,-141.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 510,-1},
98 : {"IGN-CROZ63UTM39S", NULL, 0.000000000000, 51.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9983, 1, 511,-1},
99 : {"IGN-WGS84UTM1S", NULL, 0.000000000000,-177.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0, 4, 1, 512,-1},
100 : {"IGN-RGNCUTM57S", NULL, 0.000000000000, 159.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 513,-1},
101 : {"IGN-RGNCUTM58S", NULL, 0.000000000000, 165.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 514,-1},
102 : {"IGN-RGNCUTM59S", NULL, 0.000000000000, 171.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9984, 1, 515,-1},
103 : {"IGN-KERG62UTM42S", NULL, 0.000000000000, 69.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0,9988, 1, 516,-1},
104 : {"IGN-REUN47GAUSSL", NULL, 0.000000000000, 55.533333333,-21.11666667,1.00000000000, 160000.000, 50000.000, 0.0, 0.0, 2, 19, 520,-1},
105 : {"Lambert 1 Carto", NULL, 2.337229166667, 0.000000000, 49.50000000,0.99987734000, 600000.000, 1200000.000, 0.0, 0.0, 13, 2, 1002,-1},
106 : {"Lambert 2 Carto", NULL, 2.337229166667, 0.000000000, 46.80000000,0.99987742000, 600000.000, 2200000.000, 0.0, 0.0, 13, 2, 1003,-1},/* never reached cause identical to 1:-1 */
107 : {"Lambert 3 Carto", NULL, 2.337229166667, 0.000000000, 44.10000000,0.99987750000, 600000.000, 3200000.000, 0.0, 0.0, 13, 2, 1004,-1},
108 : {"Lambert 4 Carto", NULL, 2.337229166667, 0.000000000, 42.16500000,0.99994471000, 234.358, 4185861.369, 0.0, 0.0, 13, 2, 1005,-1},
109 : {"Lambert 93", NULL, 0.000000000000, 3.000000000, 46.50000000,0.00000000000, 700000.000, 6600000.000, 44.0, 49.0,9984, 18, 1006,-1},
110 : {"IGN-RGNCLAM", NULL, 0.000000000000, 166.000000000,-21.30000000,0.00000000000, 400000.000, 300000.000,-20.4,-22.2,9984, 18, 1007,-1},/* Added in GCP */
111 : {"Lambert 1 Carto - sans grille", NULL, 2.337229166667, 0.000000000, 49.50000000,0.99987734000, 600000.000, 1200000.000, 0.0, 0.0, 1, 2, 1092,-1},
112 : {"Lambert 2 Carto - sans grille", NULL, 2.337229166667, 0.000000000, 46.80000000,0.99987742000, 600000.000, 2200000.000, 0.0, 0.0, 1, 2, 1093,-1},
113 : {"Lambert 3 Carto - sans grille", NULL, 2.337229166667, 0.000000000, 44.10000000,0.99987750000, 600000.000, 3200000.000, 0.0, 0.0, 1, 2, 1094,-1},
114 : {"Lambert 4 Carto - sans grille", NULL, 2.337229166667, 0.000000000, 42.16500000,0.99994471000, 234.358, 185861.369, 0.0, 0.0, 1, 2, 1095,-1},
115 : {"Suisse", NULL, 0.000000000000, 7.439583333, 46.95240556,1.00000000000, 600000.000, 200000.000, 0.0, 0.0, 2, 25, 1556,-1},
116 : {"Geoportail France", NULL, 0.000000000000, 0.000000000, 0.00000000,0.68835457569, 0.000, 0.000, 46.5, 0.0,9984, 26, 2012,-1},
117 : {"Geoportail Antilles", NULL, 0.000000000000, 0.000000000, 0.00000000,0.96592582629, 0.000, 0.000, 15.0, 0.0,9984, 26, 2016,-1},
118 : {"Geoportail Guyane", NULL, 0.000000000000, 0.000000000, 0.00000000,0.99756405026, 0.000, 0.000, 4.0, 0.0,9984, 26, 2017,-1},
119 : {"Geoportail Reunion", NULL, 0.000000000000, 0.000000000, 0.00000000,0.93358042649, 0.000, 0.000,-21.0, 0.0,9984, 26, 2018,-1},
120 : {"Geoportail Mayotte", NULL, 0.000000000000, 0.000000000, 0.00000000,0.97814760073, 0.000, 0.000,-12.0, 0.0,9984, 26, 2019,-1},
121 : {"Geoportail ST Pierre et Miquelon",NULL, 0.000000000000, 0.000000000, 0.00000000,0.68199836006, 0.000, 0.000, 47.0, 0.0,9984, 26, 2020,-1},
122 : {"Geoportail Nouvelle Caledonie", NULL, 0.000000000000, 0.000000000, 0.00000000,0.92718385456, 0.000, 0.000,-22.0, 0.0,9984, 26, 2021,-1},
123 : {"Geoportail Wallis", NULL, 0.000000000000, 0.000000000, 0.00000000,0.97029572627, 0.000, 0.000,-14.0, 0.0,9984, 26, 2022,-1},
124 : {"Geoportail Polynesie", NULL, 0.000000000000, 0.000000000, 0.00000000,0.96592582628, 0.000, 0.000,-15.0, 0.0,9984, 26, 2023,-1},
125 : {"Mercator sur sphère WGS84", NULL, 0.000000000000, 0.000000000, 0.00000000,1.00000000000, 0.000, 0.000, 0.0, 0.0,2015, 21, 2027,-1},
126 : {"(Long/Lat) RGF 93", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 13, 0, 2028,-1},
127 : {"(Long/Lat) ITRS-89", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0, 2028,-1},
128 : {"Geoportail Crozet", NULL, 0.000000000000, 0.000000000, 0.00000000,0.69465837046, 0.000, 0.000,-46.0, 0.0,9984, 26, 2040,-1},/* FIXME : wrong scale factor was 0.69088241108 */
129 : {"Geoportail Kerguelen", NULL, 0.000000000000, 0.000000000, 0.00000000,0.64944804833, 0.000, 0.000,-49.5, 0.0,9984, 26, 2042,-1},/* FIXME : wrong scale factor was 0.67815966987 */
130 : {"Lambert CC 42", NULL, 0.000000000000, 3.000000000, 42.00000000,0.00000000000,1700000.000, 1200000.000, 41.2, 42.8,9984, 18, 2501,-1},
131 : {"Lambert CC 43", NULL, 0.000000000000, 3.000000000, 43.00000000,0.00000000000,1700000.000, 2200000.000, 42.2, 43.8,9984, 18, 2502,-1},
132 : {"Lambert CC 44", NULL, 0.000000000000, 3.000000000, 44.00000000,0.00000000000,1700000.000, 3200000.000, 43.2, 44.8,9984, 18, 2503,-1},
133 : {"Lambert CC 45", NULL, 0.000000000000, 3.000000000, 45.00000000,0.00000000000,1700000.000, 4200000.000, 44.2, 45.8,9984, 18, 2504,-1},
134 : {"Lambert CC 46", NULL, 0.000000000000, 3.000000000, 46.00000000,0.00000000000,1700000.000, 5200000.000, 45.2, 46.8,9984, 18, 2505,-1},
135 : {"Lambert CC 47", NULL, 0.000000000000, 3.000000000, 47.00000000,0.00000000000,1700000.000, 6200000.000, 46.2, 47.8,9984, 18, 2506,-1},
136 : {"Lambert CC 48", NULL, 0.000000000000, 3.000000000, 48.00000000,0.00000000000,1700000.000, 7200000.000, 47.2, 48.8,9984, 18, 2507,-1},
137 : {"Lambert CC 49", NULL, 0.000000000000, 3.000000000, 49.00000000,0.00000000000,1700000.000, 8200000.000, 48.2, 49.8,9984, 18, 2508,-1},
138 : {"Lambert CC 50", NULL, 0.000000000000, 3.000000000, 50.00000000,0.00000000000,1700000.000, 9200000.000, 49.2, 50.8,9984, 18, 2509,-1},
139 : {"(Long/Lat) IGN-RGM04GEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0,10001,-1},
140 : {"(Long/Lat) IGN-RGFG95GEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0,10002,-1},/* never reached, identical to 10001:-1 */
141 : {"(Long/Lat) IGN-WGS84RRAFGEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0,10003,-1},/* never reached, identical to 10001:-1 */
142 : {"(Long/Lat) IGN-RGR92GEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0,10004,-1},/* never reached, identical to 10001:-1 */
143 : {"(Long/Lat) IGN-WGS84G", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 4, 0,10005,-1},
144 : {"(Long/Lat) CROZ63GEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, 4, 0,10006,-1},
145 : {"(Long/Lat) RGSPM06GEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0,10007,-1},/* never reached, identical to 10001:-1 */
146 : {"(Long/Lat) RGPFGEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0,10008,-1},/* never reached, identical to 10001:-1 */
147 : {"(Long/Lat) RGNCGEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9984, 0,10009,-1},/* never reached, identical to 10001:-1 */
148 : {"(Long/Lat) KER62GEO", "d", 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0,9988, 0,10010,-1},
149 : {"UTM Sud - ED50", NULL, 0.000000000000, 0.000000000, 0.00000000,0.99960000000, 500000.000,10000000.000, 0.0, 0.0, 14, 1,99912, 0},/* FIXME allow retrieving 12:0 - See _findSysCoord_GCSRS() */
150 : {NULL, NULL, 0.000000000000, 0.000000000, 0.00000000,0.00000000000, 0.000, 0.000, 0.0, 0.0, -1, -1, -1,-1}
151 : };
152 :
153 : static GCProjectionInfo gk_asProjList[]=
154 : /*
155 : * pszProjName, nSphere, nProjID
156 : */
157 : {
158 : {"Geographic shift", 0, 0},
159 : {"UTM", 0, 1},
160 : {"Lambert Conform Conic", 0, 2},
161 : {"Bonne", 0, 3},
162 : {"Plate carrée", 0, 4},
163 : {"MGRS (Military UTM)", 0, 11},
164 : {"Transversal Mercator", 0, 12},
165 : {"Lambert secant", 0, 18},
166 : {"Gauss Laborde", 1, 19},
167 : {"Polyconic", 0, 20},
168 : {"Direct Mercator", 0, 21},
169 : {"Stereographic oblic", 1, 22},
170 : {"Miller", 0, 24},
171 : {"Mercator oblic", 1, 25},
172 : {"Equi rectangular", 1, 26},
173 :
174 : {NULL, 0, -1}
175 : };
176 :
177 : static GCDatumInfo gk_asDatumList[]=
178 : /*
179 : * pszDatumName, dfShiftX, dfShiftY, dfShiftZ, dfRotX, dfRotY, dfRotZ, dfScaleFactor, dfFA, dfFlattening, nEllipsoidID, nDatumID
180 : */
181 : /*
182 : * Wrong dx, dy, dz :
183 : * IGN-RGM04GEO, was -217, -216, 67
184 : * IGN-RGFG95GEO, was -2, -2, 2
185 : * IGN-RGSPM06GEO, was -125.593, 143.763, -194.558
186 : *
187 : * #1 and #13 are identical
188 : * #8, #11, #2015 are spherical views of #4
189 : * #5030, #5031 and #5032 are identical
190 : * FIXME : #5030, #5031, #5032 are ITRS89 compliant, so "compatible" with #4, better use #9999 as ellipsoid
191 : * FIXME : #9999 to #9986 added
192 : */
193 : {
194 : {"NTF (Clarke 1880)", -168.0000, -60.0000, 320.0000, 0.00000, 0.00000, 0.00000, 0.0, -112.200,-54.7388e-6, 3, 1},
195 : {"ED50 France (International 1909)", -84.0000, -97.0000,-117.0000, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5, 2},
196 : {"WGS 72", 0.0000, 12.0000, 6.0000, 0.00000, 0.00000, 0.00000, 0.0, 2.000, 0.0312e-6, 6, 3},
197 : {"WGS_1984", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 9999, 4},
198 : {"ED 79", -83.0000, -95.0000,-116.0000, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5, 5},
199 : {"Australian Geodetic 1966", -133.0000, -48.0000, 148.0000, 0.00000, 0.00000, 0.00000, 0.0, -23.000, -0.0081e-6, 7, 6},
200 : {"Australian Geodetic 1984", -134.0000, -48.0000, 149.0000, 0.00000, 0.00000, 0.00000, 0.0, -23.000, -0.0081e-6, 7, 7},
201 : {"Sphere", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 1, 8},
202 : {"Sphere DCW", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 1, 11},
203 : {"Airy", 375.0000,-111.0000, 431.0000, 0.00000, 0.00000, 0.00000, 0.0, 573.604, 11.96002325e-6, 8, 12},
204 : {"NTF-Grille", -168.0000, -60.0000, 320.0000, 0.00000, 0.00000, 0.00000, 0.0, -112.200,-54.7388e-6, 3, 13},
205 : {"ED50 (International 1909)", -87.0000, -98.0000,-121.0000, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5, 14},
206 : {"WGS 84 sur sphere", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 1,2015},
207 : {"IGN-RGM04GEO", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 4,5030},
208 : {"IGN-RGFG95GEO", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 4,5031},
209 : {"IGN-RGSPM06GEO", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 4,5032},
210 : {"IGN-WALL78", 253.0000,-133.0000,-127.0000, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5,9999},/* FIXME */
211 : {"IGN-TAHA", 72.4380, 345.9180, 79.4860,-1.60450,-0.88230, -0.55650, 1.3746e-6, -251.000,-14.1927e-6, 5,9998},/* FIXME */
212 : {"IGN-MOOREA87", 215.9820, 149.5930, 176.2290, 3.26240, 1.69200, 1.15710, 10.47730e-6,-251.000,-14.1927e-6, 5,9997},/* FIXME */
213 : {"IGN-TAHI51", 162.0000, 117.0000, 154.0000, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5,9996},/* FIXME */
214 : {"IGN-NUKU72", 165.7320, 216.7200, 180.5050,-0.64340,-0.45120, -0.07910, 7.42040e-6,-251.000,-14.1927e-6, 5,9995},/* FIXME */
215 : {"IGN-IGN63", 410.7210, 55.0490, 80.7460,-2.57790,-2.35140, -0.66640, 17.33110e-6,-251.000,-14.1927e-6, 5,9994},/* FIXME */
216 : {"IGN-MART38", 126.9260, 547.9390, 130.4090,-2.78670, 5.16124, -0.85844, 13.82265e-6,-251.000,-14.1927e-6, 5,9993},/* FIXME */
217 : {"IGN-GUAD48", -472.2900, -5.6300,-304.1200, 0.43620,-0.83740, 0.25630, 1.89840e-6,-251.000,-14.1927e-6, 5,9992},/* FIXME */
218 : {"IGN-GUADFM49", 136.5960, 248.1480,-429.7890, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5,9991},/* FIXME */
219 : {"IGN-STPM50", -95.5930, 573.7630, 173.4420,-0.96020, 1.25100, -1.39180, 42.62650e-6, -69.400,-37.2957e-6, 2,9990},/* FIXME */
220 : {"IGN-CSG67", -193.0660, 236.9930, 105.4470, 0.48140,-0.80740, 0.12760, 1.56490e-6,-251.000,-14.1927e-6, 5,9989},/* FIXME */
221 : {"IGN-KERG62", 145.0000,-187.0000, 103.0000, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5,9988},/* FIXME */
222 : {"IGN-REUN47", 789.5240,-626.4860, -89.9040, 0.60060,76.79460,-10.57880,-32.32410e-6,-251.000,-14.1927e-6, 5,9987},/* FIXME */
223 : {"IGN-MAYO50", -599.9280,-275.5520,-195.6650, 0.08350, 0.47150, -0.06020,-49.28140e-6,-251.000,-14.1927e-6, 5,9986},/* FIXME */
224 : {"IGN-TAHI79", 221.5250, 152.9480, 176.7680, 2.38470, 1.38960, 0.87700, 11.47410e-6,-251.000,-14.1927e-6, 5,9985},/* FIXME */
225 : {"ITRS-89", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, 4,9984},
226 : {"IGN-CROZ63", 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, -251.000,-14.1927e-6, 5,9983},/* FIXME added cause the Bursa-Wolf parameters are not known */
227 :
228 : {NULL, 0.0000, 0.0000, 0.0000, 0.00000, 0.00000, 0.00000, 0.0, 0.000, 0.0, -1, -1}
229 : };
230 :
231 : static GCSpheroidInfo gk_asSpheroidList[]=
232 : /*
233 : * pszSpheroidName, dfA, dfE, nEllipsoidID
234 : *
235 : * cause Geoconcept assimilates WGS84 and GRS80, WGS84 is added to the list
236 : */
237 : {
238 : {"Sphere", 6378137.0000, 0.00000000000000, 1},
239 : {"Clarke 1866", 6378206.4000, 0.08227185423947, 2},/* Wrong, semi-major was 6378249.4000 */
240 : {"Clarke 1880", 6378249.2000, 0.08248325676300, 3},/* Wrong, excentricity was 0.082483256945 */
241 : {"GRS 80", 6378137.0000, 0.08181919104300, 4},/* Wrong, excentricity was 0.081819191060 */
242 : {"International 1909", 6378388.0000, 0.08199188997900, 5},
243 : {"WGS 72", 6378135.0000, 0.08181881201777, 6},
244 : {"Australian National", 6378160.0000, 0.08182017998700, 7},
245 : {"Airy", 6377563.3960, 0.08167337387420, 8},
246 : {"WGS 84", 6378137.0000, 0.08181919084262,9999},
247 :
248 : {NULL, 0, 0, -1}
249 : };
250 :
251 : /* -------------------------------------------------------------------- */
252 : /* GCSRS API Prototypes */
253 : /* -------------------------------------------------------------------- */
254 :
255 : /* -------------------------------------------------------------------- */
256 16 : static int GCSRSAPI_CALL _areCompatibleSpheroids_GCSRS ( id1, id2 )
257 : {
258 16 : if( id1==id2 ) return TRUE;
259 :
260 14 : switch( id1 )
261 : {
262 : case 4 :
263 : case 9999 :
264 2 : switch( id2 )
265 : {
266 : case 4 :
267 : case 9999 :
268 2 : return TRUE;
269 : default :
270 : break;
271 : }
272 : break;
273 : default :
274 : break;
275 : }
276 :
277 12 : return FALSE;
278 : }/* _areCompatibleSpheroids_GCSRS */
279 :
280 : /* -------------------------------------------------------------------- */
281 88 : static int GCSRSAPI_CALL _areCompatibleDatums_GCSRS ( id1, id2 )
282 : {
283 88 : if( id1==id2 ) return TRUE;
284 :
285 80 : switch( id1 )
286 : {
287 : case 1 : /* NTF */
288 : case 13 :
289 22 : switch( id2 )
290 : {
291 : case 1 :
292 : case 13 :
293 0 : return TRUE;
294 : default :
295 : break;
296 : }
297 22 : break;
298 : case 2 : /* ED50 */
299 : case 14 :
300 : case 9983 :
301 : case 9985 :
302 : case 9986 :
303 : case 9987 :
304 : case 9989 :
305 : case 9991 :
306 : case 9992 :
307 : case 9993 :
308 : case 9994 :
309 : case 9995 :
310 : case 9997 :
311 : case 9998 :
312 : case 9999 :
313 6 : switch( id2 )
314 : {
315 : case 2 :
316 : case 14 :
317 : case 9983 :
318 : case 9985 :
319 : case 9986 :
320 : case 9987 :
321 : case 9989 :
322 : case 9991 :
323 : case 9992 :
324 : case 9993 :
325 : case 9994 :
326 : case 9995 :
327 : case 9997 :
328 : case 9998 :
329 : case 9999 :
330 0 : return TRUE;
331 : default :
332 : break;
333 : }
334 6 : break;
335 : case 4 : /* WGS84 - ITRS89 */
336 : case 8 :
337 : case 11 :
338 : case 2015 :
339 : case 5030 :
340 : case 5031 :
341 : case 5032 :
342 : case 9984 :
343 45 : switch( id2 )
344 : {
345 : case 4 :
346 : case 8 :
347 : case 11 :
348 : case 2015 :
349 : case 5030 :
350 : case 5031 :
351 : case 5032 :
352 : case 9984 :
353 45 : return TRUE;
354 : default :
355 : break;
356 : }
357 : break;
358 : default :
359 : break;
360 : }
361 :
362 35 : return FALSE;
363 : }/* _areCompatibleDatums_GCSRS */
364 :
365 : #define _CPLDebugSpheroid_GCSRS(e) \
366 : CPLDebug( "GEOCONCEPT", "SemiMajor:%.4f;Excentricity:%.10f;",\
367 : GetInfoSpheroidSemiMajor_GCSRS(e),\
368 : GetInfoSpheroidExcentricity_GCSRS(e)\
369 : );
370 :
371 : /* -------------------------------------------------------------------- */
372 1 : static GCSpheroidInfo GCSRSAPI_CALL1(*) _findSpheroid_GCSRS ( double a, double rf )
373 : {
374 1 : int iSpheroid, iResol= 0, nResol= 2;
375 : GCSpheroidInfo* ell;
376 1 : double e, p[]= {1e-10, 1e-8};
377 :
378 : /* f = 1 - sqrt(1 - e^2) */
379 1 : e= 1.0/rf;
380 1 : e= sqrt(e*(2.0-e));
381 : ell_relax:
382 10 : for( iSpheroid= 0, ell= &(gk_asSpheroidList[0]);
383 9 : GetInfoSpheroidID_GCSRS(ell)!=-1;
384 8 : iSpheroid++, ell= &(gk_asSpheroidList[iSpheroid]) )
385 : {
386 9 : if( fabs(GetInfoSpheroidSemiMajor_GCSRS(ell) - a) > 1e-4 ) continue;
387 3 : if( fabs(GetInfoSpheroidExcentricity_GCSRS(ell) - e) > p[iResol] ) continue;
388 1 : break;
389 : }
390 1 : if( GetInfoSpheroidID_GCSRS(ell)==-1 && iResol!=nResol-1 )
391 : {
392 0 : iResol++;
393 0 : goto ell_relax;
394 : }
395 :
396 1 : return ell;
397 : }/* _findSpheroid_GCSRS */
398 :
399 : #define _CPLDebugDatum_GCSRS(d) \
400 : CPLDebug( "GEOCONCEPT", "ID:%d;ShiftX:%.4f;ShiftY:%.4f;ShiftZ:%.4f;DiffA:%.4f;DiffFlattening:%.7f;",\
401 : GetInfoDatumID_GCSRS((d)),\
402 : GetInfoDatumShiftX_GCSRS((d)),\
403 : GetInfoDatumShiftY_GCSRS((d)),\
404 : GetInfoDatumShiftZ_GCSRS((d)),\
405 : GetInfoDatumDiffA_GCSRS((d)),\
406 : GetInfoDatumDiffFlattening_GCSRS((d))\
407 : );
408 :
409 : /* -------------------------------------------------------------------- */
410 1 : static GCDatumInfo GCSRSAPI_CALL1(*) _findDatum_GCSRS ( double dx,
411 : double dy,
412 : double dz,
413 : double a,
414 : double f )
415 : {
416 1 : int iDatum, bRelax= FALSE;
417 : GCDatumInfo* datum;
418 :
419 : datum_relax:
420 5 : for( iDatum= 0, datum= &(gk_asDatumList[0]);
421 4 : GetInfoDatumID_GCSRS(datum)!=-1;
422 3 : iDatum++, datum= &(gk_asDatumList[iDatum]) )
423 : {
424 4 : if( !bRelax )
425 : {
426 4 : if( fabs(GetInfoDatumShiftX_GCSRS(datum) - dx) > 1e-4 ) continue;
427 2 : if( fabs(GetInfoDatumShiftY_GCSRS(datum) - dy) > 1e-4 ) continue;
428 1 : if( fabs(GetInfoDatumShiftZ_GCSRS(datum) - dz) > 1e-4 ) continue;
429 : }
430 1 : if( fabs(GetInfoDatumDiffA_GCSRS(datum) - (6378137.0000-a)) > 1e-4 ) continue;
431 1 : if( fabs(GetInfoDatumDiffFlattening_GCSRS(datum) - (0.003352779565406696648-f)) > 1e-7 ) continue;
432 1 : break;
433 : }
434 1 : if( GetInfoDatumID_GCSRS(datum)==-1 && !bRelax )
435 : {
436 : /*
437 : * FIXME : when both nadgrids and towgs84 are defined, bursa-wolf parameters are lost !
438 : * if the projection and the ellipsoid are known, one can retrieve the datum
439 : * Try relaxed search ...
440 : */
441 0 : bRelax= TRUE;
442 0 : goto datum_relax;
443 : }
444 :
445 1 : return datum;
446 : }/* _findDatum_GCSRS */
447 :
448 : /* -------------------------------------------------------------------- */
449 1 : static GCProjectionInfo GCSRSAPI_CALL1(*) _findProjection_GCSRS ( const char* p, double lat_ts )
450 : {
451 : int iProj;
452 : GCProjectionInfo* proj;
453 :
454 2 : for( iProj= 0, proj= &(gk_asProjList[0]);
455 1 : GetInfoProjID_GCSRS(proj)!=-1;
456 0 : iProj++, proj= &(gk_asProjList[iProj]) )
457 : {
458 1 : if( iProj==0 && p==NULL)
459 1 : break;
460 0 : if( iProj==1 &&
461 0 : ( EQUAL(p,SRS_PT_TRANSVERSE_MERCATOR) ||
462 0 : EQUAL(p,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) ) )
463 : break;
464 0 : if( iProj==2 &&
465 0 : EQUAL(p,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
466 0 : break;
467 0 : if( iProj==3 &&
468 0 : EQUAL(p,SRS_PT_BONNE) )
469 0 : break;
470 0 : if( iProj==4 &&
471 0 : EQUAL(p,SRS_PT_EQUIRECTANGULAR) &&
472 : lat_ts==0.0 )
473 0 : break;
474 : /* FIXME : iProj==6 ? */
475 0 : if( iProj==7 &&
476 0 : ( EQUAL(p,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) ||
477 0 : EQUAL(p,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) ) )
478 : break;
479 0 : if( iProj==8 &&
480 0 : EQUAL(p,SRS_PT_GAUSSSCHREIBERTMERCATOR) )
481 0 : break;
482 0 : if( iProj==9 &&
483 0 : EQUAL(p,SRS_PT_POLYCONIC) )
484 0 : break;
485 : /* FIXME
486 : if( iProj==10 &&
487 : ( EQUAL(p,SRS_PT_MERCATOR_1SP) ||
488 : EQUAL(p,SRS_PT_MERCATOR_2SP) ) )
489 : break;
490 : */
491 0 : if( iProj==11 &&
492 0 : ( EQUAL(p,SRS_PT_OBLIQUE_STEREOGRAPHIC) ||
493 0 : EQUAL(p,SRS_PT_POLAR_STEREOGRAPHIC) ) )
494 : break;
495 0 : if( iProj==12 &&
496 0 : EQUAL(p,SRS_PT_MILLER_CYLINDRICAL) )
497 0 : break;
498 : /* FIXME
499 : if( iProj==13 &&
500 : ( EQUAL(p,SRS_PT_HOTINE_OBLIQUE_MERCATOR) ||
501 : EQUAL(p,SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) ||
502 : EQUAL(p,SRS_PT_LABORDE_OBLIQUE_MERCATOR) ) )
503 : break;
504 : */
505 0 : if( iProj==14 &&
506 0 : EQUAL(p,SRS_PT_EQUIRECTANGULAR) &&
507 : lat_ts!=0.0 )
508 0 : break;
509 : }
510 :
511 1 : return proj;
512 : }/* _findProjection_GCSRS */
513 :
514 : #define _CPLDebugSysCoord_GCSRS(m,s) \
515 : CPLDebug( "GEOCONCEPT", "[%s]ID=%d;Zone=%d;DatumID=%d;ProjID=%d;PrimeMeridian=%.10f;CentralMeridian=%.10f;LatitudeOfOrigin=%.10f;StandardParallel1=%.10f;StandardParallel2=%.10f;ScaleFactor=%.10f;FalseEasting=%.10f;FalseNorthing=%.10f;",\
516 : (m)? (m):"",\
517 : GetSysCoordSystemID_GCSRS((s)),\
518 : GetSysCoordTimeZone_GCSRS((s)),\
519 : GetSysCoordDatumID_GCSRS((s)),\
520 : GetSysCoordProjID_GCSRS((s)),\
521 : GetSysCoordPrimeMeridian_GCSRS((s)),\
522 : GetSysCoordCentralMeridian_GCSRS((s)),\
523 : GetSysCoordLatitudeOfOrigin_GCSRS((s)),\
524 : GetSysCoordStandardParallel1_GCSRS((s)),\
525 : GetSysCoordStandardParallel2_GCSRS((s)),\
526 : GetSysCoordScaleFactor_GCSRS((s)),\
527 : GetSysCoordFalseEasting_GCSRS((s)),\
528 : GetSysCoordFalseNorthing_GCSRS((s))\
529 : );
530 :
531 : /* -------------------------------------------------------------------- */
532 1 : static GCSysCoord GCSRSAPI_CALL1(*) _findSysCoord_GCSRS ( GCSysCoord* theSysCoord )
533 : {
534 1 : int iSysCoord, bestSysCoord= -1;
535 : GCSysCoord* gcsc;
536 :
537 1 : if( !theSysCoord) return NULL;
538 :
539 1 : SetSysCoordSystemID_GCSRS(theSysCoord, -1);
540 1 : SetSysCoordTimeZone_GCSRS(theSysCoord, -1);
541 1 : _CPLDebugSysCoord_GCSRS(NULL,theSysCoord);
542 90 : for( iSysCoord= 0, gcsc= &(gk_asSysCoordList[0]);
543 89 : GetSysCoordSystemID_GCSRS(gcsc)!=-1;
544 88 : iSysCoord++, gcsc= &(gk_asSysCoordList[iSysCoord]) )
545 : {
546 88 : if( !_areCompatibleDatums_GCSRS(GetSysCoordDatumID_GCSRS(gcsc), GetSysCoordDatumID_GCSRS(theSysCoord)) ) continue;
547 :
548 53 : if( GetSysCoordProjID_GCSRS(gcsc) != GetSysCoordProjID_GCSRS(theSysCoord) ) continue;
549 :
550 11 : if( fabs(GetSysCoordPrimeMeridian_GCSRS(gcsc) - GetSysCoordPrimeMeridian_GCSRS(theSysCoord) ) > 1e-8 ) continue;
551 :
552 11 : if( fabs(GetSysCoordCentralMeridian_GCSRS(gcsc) - GetSysCoordCentralMeridian_GCSRS(theSysCoord) ) > 1e-8 )
553 : {
554 0 : switch( GetSysCoordProjID_GCSRS(gcsc) )
555 : {
556 : case 1 :/* UTM familly : central meridian is the 6* zone - 183 (in degrees) */
557 0 : if( GetSysCoordCentralMeridian_GCSRS(gcsc)==0.0 ) /* generic UTM definition */
558 : {
559 0 : break;
560 : }
561 : default :
562 0 : continue;
563 : }
564 : }
565 11 : if( fabs(GetSysCoordLatitudeOfOrigin_GCSRS(gcsc) - GetSysCoordLatitudeOfOrigin_GCSRS(theSysCoord) ) > 1e-8 ) continue;
566 :
567 11 : if( fabs(GetSysCoordStandardParallel1_GCSRS(gcsc) - GetSysCoordStandardParallel1_GCSRS(theSysCoord) ) > 1e-8 ) continue;
568 11 : if( fabs(GetSysCoordStandardParallel2_GCSRS(gcsc) - GetSysCoordStandardParallel2_GCSRS(theSysCoord) ) > 1e-8 ) continue;
569 :
570 11 : if( fabs(GetSysCoordScaleFactor_GCSRS(gcsc) - GetSysCoordScaleFactor_GCSRS(theSysCoord) ) > 1e-8 ) continue;
571 :
572 11 : if( fabs(GetSysCoordFalseEasting_GCSRS(gcsc) - GetSysCoordFalseEasting_GCSRS(theSysCoord) ) > 1e-4 ) continue;
573 11 : if( fabs(GetSysCoordFalseNorthing_GCSRS(gcsc) - GetSysCoordFalseNorthing_GCSRS(theSysCoord) ) > 1e-4 ) continue;
574 :
575 : /* Found a candidate : */
576 11 : if( bestSysCoord==-1)
577 : {
578 1 : bestSysCoord= iSysCoord;
579 : }
580 : else
581 : {
582 10 : switch( GetSysCoordProjID_GCSRS(gcsc) )
583 : {
584 : case 0:/* long/lat */
585 12 : if( GetSysCoordDatumID_GCSRS(gcsc)==GetSysCoordDatumID_GCSRS(theSysCoord) &&
586 2 : GetSysCoordDatumID_GCSRS(&(gk_asSysCoordList[bestSysCoord]))!=GetSysCoordDatumID_GCSRS(theSysCoord)) /* exact match */
587 : {
588 0 : bestSysCoord= iSysCoord;
589 : }
590 10 : break;
591 : case 1:/* UTM familly : central meridian is the 6* zone - 183 (in degrees) */
592 0 : if( GetSysCoordCentralMeridian_GCSRS(gcsc)!=0.0 &&
593 0 : GetSysCoordDatumID_GCSRS(gcsc)==GetSysCoordDatumID_GCSRS(theSysCoord) &&
594 0 : GetSysCoordDatumID_GCSRS(&(gk_asSysCoordList[bestSysCoord]))!=GetSysCoordDatumID_GCSRS(theSysCoord)) /* exact match */
595 : {
596 0 : bestSysCoord= iSysCoord;
597 : }
598 : break;
599 : default :
600 : break;
601 : }
602 : }
603 : }
604 : /* Seems to be the right Geoconcept system: */
605 1 : if( bestSysCoord>=0 )
606 : {
607 1 : gcsc= &(gk_asSysCoordList[bestSysCoord]);
608 1 : switch( GetSysCoordSystemID_GCSRS(gcsc) )
609 : {
610 : case 99912 : /* hack */
611 0 : SetSysCoordSystemID_GCSRS(theSysCoord, 12);
612 0 : break;
613 : default :
614 1 : SetSysCoordSystemID_GCSRS(theSysCoord, GetSysCoordSystemID_GCSRS(gcsc));
615 : break;
616 : }
617 1 : SetSysCoordTimeZone_GCSRS(theSysCoord, GetSysCoordTimeZone_GCSRS(gcsc));
618 1 : if( GetSysCoordName_GCSRS(gcsc) )
619 1 : SetSysCoordName_GCSRS(theSysCoord, CPLStrdup(GetSysCoordName_GCSRS(gcsc)));
620 1 : if( GetSysCoordUnit_GCSRS(gcsc) )
621 1 : SetSysCoordUnit_GCSRS(theSysCoord, CPLStrdup(GetSysCoordUnit_GCSRS(gcsc)));
622 : }
623 :
624 1 : return theSysCoord;
625 : }/* _findSysCoord_GCSRS */
626 :
627 : /* -------------------------------------------------------------------- */
628 10 : static void GCSRSAPI_CALL _InitSysCoord_GCSRS (
629 : GCSysCoord* theSysCoord
630 : )
631 : {
632 10 : SetSysCoordSystemID_GCSRS(theSysCoord, -1);
633 10 : SetSysCoordTimeZone_GCSRS(theSysCoord, -1);
634 10 : SetSysCoordName_GCSRS(theSysCoord, NULL);
635 10 : SetSysCoordUnit_GCSRS(theSysCoord, NULL);
636 10 : SetSysCoordCentralMeridian_GCSRS(theSysCoord, 0.0);
637 10 : SetSysCoordLatitudeOfOrigin_GCSRS(theSysCoord, 0.0);
638 10 : SetSysCoordStandardParallel1_GCSRS(theSysCoord, 0.0);
639 10 : SetSysCoordStandardParallel2_GCSRS(theSysCoord, 0.0);
640 10 : SetSysCoordScaleFactor_GCSRS(theSysCoord, 0.0);
641 10 : SetSysCoordFalseEasting_GCSRS(theSysCoord, 0.0);
642 10 : SetSysCoordFalseNorthing_GCSRS(theSysCoord, 0.0);
643 10 : SetSysCoordDatumID_GCSRS(theSysCoord, -1);
644 10 : SetSysCoordProjID_GCSRS(theSysCoord, -1);
645 10 : SetSysCoordPrimeMeridian_GCSRS(theSysCoord, 0);
646 10 : }/* _InitSysCoord_GCSRS */
647 :
648 : /* -------------------------------------------------------------------- */
649 5 : GCSysCoord GCSRSAPI_CALL1(*) CreateSysCoord_GCSRS (
650 : int srsid,
651 : int timezone
652 : )
653 : {
654 : int iSysCoord;
655 : GCSysCoord* theSysCoord, *gcsc;
656 :
657 5 : if( !(theSysCoord= CPLMalloc(sizeof(GCSysCoord))) )
658 : {
659 0 : CPLError( CE_Failure, CPLE_OutOfMemory,
660 : "failed to create a Geoconcept coordinate system.\n"
661 : );
662 0 : return NULL;
663 : }
664 5 : _InitSysCoord_GCSRS(theSysCoord);
665 5 : if( srsid>=0)
666 : {
667 140 : for( iSysCoord= 0, gcsc= &(gk_asSysCoordList[0]);
668 136 : GetSysCoordSystemID_GCSRS(gcsc)!=-1;
669 132 : iSysCoord++, gcsc= &(gk_asSysCoordList[iSysCoord]) )
670 : {
671 136 : if( srsid==GetSysCoordSystemID_GCSRS(gcsc) )
672 : {
673 4 : SetSysCoordSystemID_GCSRS(theSysCoord, srsid);
674 4 : SetSysCoordTimeZone_GCSRS(theSysCoord, timezone);
675 4 : if( GetSysCoordName_GCSRS(gcsc) )
676 4 : SetSysCoordName_GCSRS(theSysCoord, CPLStrdup(GetSysCoordName_GCSRS(gcsc)));
677 4 : if( GetSysCoordUnit_GCSRS(gcsc) )
678 2 : SetSysCoordUnit_GCSRS(theSysCoord, CPLStrdup(GetSysCoordUnit_GCSRS(gcsc)));
679 4 : SetSysCoordCentralMeridian_GCSRS(theSysCoord, GetSysCoordCentralMeridian_GCSRS(gcsc));
680 4 : SetSysCoordLatitudeOfOrigin_GCSRS(theSysCoord, GetSysCoordLatitudeOfOrigin_GCSRS(gcsc));
681 4 : SetSysCoordStandardParallel1_GCSRS(theSysCoord, GetSysCoordStandardParallel1_GCSRS(gcsc));
682 4 : SetSysCoordStandardParallel2_GCSRS(theSysCoord, GetSysCoordStandardParallel2_GCSRS(gcsc));
683 4 : SetSysCoordScaleFactor_GCSRS(theSysCoord, GetSysCoordScaleFactor_GCSRS(gcsc));
684 4 : SetSysCoordFalseEasting_GCSRS(theSysCoord, GetSysCoordFalseEasting_GCSRS(gcsc));
685 4 : SetSysCoordFalseNorthing_GCSRS(theSysCoord, GetSysCoordFalseNorthing_GCSRS(gcsc));
686 4 : SetSysCoordDatumID_GCSRS(theSysCoord, GetSysCoordDatumID_GCSRS(gcsc));
687 4 : SetSysCoordProjID_GCSRS(theSysCoord, GetSysCoordProjID_GCSRS(gcsc));
688 4 : break;
689 : }
690 : }
691 : }
692 :
693 5 : return theSysCoord;
694 : }/* CreateSysCoord_GCSRS */
695 :
696 : /* -------------------------------------------------------------------- */
697 5 : static void GCSRSAPI_CALL _ReInitSysCoord_GCSRS (
698 : GCSysCoord* theSysCoord
699 : )
700 : {
701 5 : if( GetSysCoordName_GCSRS(theSysCoord) )
702 : {
703 5 : CPLFree(GetSysCoordName_GCSRS(theSysCoord));
704 : }
705 5 : if( GetSysCoordUnit_GCSRS(theSysCoord) )
706 : {
707 3 : CPLFree(GetSysCoordUnit_GCSRS(theSysCoord));
708 : }
709 5 : _InitSysCoord_GCSRS(theSysCoord);
710 5 : }/* _ReInitSysCoord_GCSRS */
711 :
712 : /* -------------------------------------------------------------------- */
713 5 : void GCSRSAPI_CALL DestroySysCoord_GCSRS (
714 : GCSysCoord** theSysCoord
715 : )
716 : {
717 5 : _ReInitSysCoord_GCSRS(*theSysCoord);
718 5 : CPLFree(*theSysCoord);
719 5 : *theSysCoord= NULL;
720 5 : }/* DestroySysCoord_GCSRS */
721 :
722 : /* -------------------------------------------------------------------- */
723 1 : GCSysCoord GCSRSAPI_CALL1(*) OGRSpatialReference2SysCoord_GCSRS ( OGRSpatialReferenceH poSR )
724 : {
725 1 : char* pszProj4= NULL;
726 1 : GCSpheroidInfo* ell= NULL;
727 1 : GCDatumInfo* datum= NULL;
728 1 : GCProjectionInfo* gcproj= NULL;
729 : double a, rf, f, p[7];
730 1 : GCSysCoord* syscoord= NULL;
731 :
732 1 : if( !poSR ) return NULL;
733 :
734 1 : pszProj4= NULL;
735 1 : OSRExportToProj4(poSR, &pszProj4);
736 1 : if( !pszProj4 ) pszProj4= CPLStrdup("");
737 :
738 1 : CPLDebug("GEOCONCEPT", "SRS : %s", pszProj4);
739 :
740 1 : if( !(syscoord= CreateSysCoord_GCSRS(-1,-1)) )
741 : {
742 0 : goto onError;
743 : }
744 1 : SetSysCoordPrimeMeridian_GCSRS(syscoord, OSRGetPrimeMeridian(poSR,NULL));
745 :
746 1 : a= OSRGetSemiMajor(poSR,NULL);
747 1 : rf= OSRGetInvFlattening(poSR,NULL);
748 1 : ell= _findSpheroid_GCSRS(a, rf);
749 1 : if( GetInfoSpheroidID_GCSRS(ell)==-1 )
750 : {
751 0 : CPLDebug("GEOCONCEPT", "Unsupported ellipsoid : %.4f %.10f", a, rf);
752 0 : goto onError;
753 : }
754 1 : CPLDebug("GEOCONCEPT", "ellipsoid found : %s",
755 : GetInfoSpheroidName_GCSRS(ell));
756 :
757 1 : OSRGetTOWGS84(poSR,p,7);
758 1 : f= 1.0 - sqrt(1.0 - GetInfoSpheroidExcentricity_GCSRS(ell)*GetInfoSpheroidExcentricity_GCSRS(ell));
759 1 : datum= _findDatum_GCSRS(p[0], p[1], p[2], GetInfoSpheroidSemiMajor_GCSRS(ell), f);
760 1 : if( GetInfoDatumID_GCSRS(datum)==-1 )
761 : {
762 0 : CPLDebug("GEOCONCEPT", "Unsupported datum : %.4f %.4f; %.4f %.4f %.10f",
763 : p[0], p[1], p[2], a, 1.0/rf);
764 0 : goto onError;
765 : }
766 : /* FIXME : WGS 84 and GRS 80 assimilation by Geoconcept : */
767 1 : if( GetInfoSpheroidID_GCSRS(ell)==4 ) /* GRS 80 */
768 : {
769 0 : datum= &(gk_asDatumList[31]);
770 : }
771 1 : else if( GetInfoSpheroidID_GCSRS(ell)==9999 ) /* WGS 84 */
772 : {
773 1 : datum= &(gk_asDatumList[3]);
774 : }
775 1 : CPLDebug("GEOCONCEPT", "datum found : %s", GetInfoDatumName_GCSRS(datum));
776 1 : SetSysCoordDatumID_GCSRS(syscoord, GetInfoDatumID_GCSRS(datum));
777 :
778 1 : gcproj= _findProjection_GCSRS(OSRIsGeographic(poSR)?
779 : NULL
780 : :
781 0 : OSRGetAttrValue(poSR, "PROJECTION", 0),
782 : OSRGetProjParm(poSR,SRS_PP_PSEUDO_STD_PARALLEL_1,0.0,NULL));
783 1 : if( GetInfoProjID_GCSRS(gcproj)==-1 )
784 : {
785 0 : CPLDebug("GEOCONCEPT", "Unsupported projection : %s",
786 0 : OSRIsGeographic(poSR)? "GEOCS":OSRGetAttrValue(poSR, "PROJECTION", 0));
787 0 : goto onError;
788 : }
789 1 : CPLDebug("GEOCONCEPT", "projection : %s", GetInfoProjName_GCSRS(gcproj));
790 1 : SetSysCoordProjID_GCSRS(syscoord, GetInfoProjID_GCSRS(gcproj));
791 :
792 : /* then overwrite them with projection specific parameters ... */
793 1 : if( OSRIsProjected(poSR) )
794 : {
795 : double v;
796 :
797 0 : SetSysCoordPrimeMeridian_GCSRS(syscoord, OSRGetPrimeMeridian(poSR,NULL));
798 0 : SetSysCoordCentralMeridian_GCSRS(syscoord, OSRGetProjParm(poSR,SRS_PP_CENTRAL_MERIDIAN,0.0,NULL));
799 0 : SetSysCoordLatitudeOfOrigin_GCSRS(syscoord, OSRGetProjParm(poSR,SRS_PP_LATITUDE_OF_ORIGIN,0.0,NULL));
800 0 : SetSysCoordStandardParallel1_GCSRS(syscoord, OSRGetProjParm(poSR,SRS_PP_STANDARD_PARALLEL_1,0.0,NULL));
801 0 : SetSysCoordStandardParallel2_GCSRS(syscoord, OSRGetProjParm(poSR,SRS_PP_STANDARD_PARALLEL_2,0.0,NULL));
802 0 : SetSysCoordFalseEasting_GCSRS(syscoord, OSRGetProjParm(poSR,SRS_PP_FALSE_EASTING,0.0,NULL));
803 0 : SetSysCoordFalseNorthing_GCSRS(syscoord, OSRGetProjParm(poSR,SRS_PP_FALSE_NORTHING,0.0,NULL));
804 0 : if( (v= OSRGetProjParm(poSR,SRS_PP_SCALE_FACTOR,0.0,NULL))!= 0.0 )
805 : {
806 0 : SetSysCoordScaleFactor_GCSRS(syscoord, v);
807 : }
808 0 : if( (v= OSRGetProjParm(poSR,SRS_PP_PSEUDO_STD_PARALLEL_1,0.0,NULL))!= 0.0 )
809 : {
810 : /* should be SRS_PT_EQUIRECTANGULAR : */
811 0 : SetSysCoordScaleFactor_GCSRS(syscoord, cos(v*PI/180.0));
812 0 : SetSysCoordStandardParallel1_GCSRS(syscoord, v);/* allow keeping lat_ts sign */
813 : }
814 : }
815 :
816 : /* Retrieve the syscoord : */
817 1 : if( !_findSysCoord_GCSRS(syscoord) )
818 : {
819 0 : CPLDebug("GEOCONCEPT", "invalid syscoord ?!");
820 0 : goto onError;
821 : }
822 1 : if( GetSysCoordSystemID_GCSRS(syscoord)==-1 )
823 : {
824 0 : CPLDebug("GEOCONCEPT", "Cannot find syscoord");
825 0 : goto onError;
826 : }
827 : /* when SRS_PT_TRANSVERSE_MERCATOR, get zone : */
828 1 : if( GetSysCoordTimeZone_GCSRS(syscoord)==0 )
829 : {
830 0 : int pbNorth= 1;
831 0 : SetSysCoordTimeZone_GCSRS(syscoord, OSRGetUTMZone(poSR,&pbNorth));
832 : }
833 :
834 1 : if( pszProj4 )
835 : {
836 1 : CPLFree(pszProj4);
837 : }
838 2 : CPLDebug( "GEOCONCEPT", "SysCoord value: %d:%d",
839 1 : GetSysCoordSystemID_GCSRS(syscoord),
840 1 : GetSysCoordTimeZone_GCSRS(syscoord) );
841 :
842 1 : return syscoord;
843 :
844 : onError:
845 0 : if( pszProj4 )
846 : {
847 0 : CPLDebug( "GEOCONCEPT",
848 : "Unhandled spatial reference system '%s'.",
849 : pszProj4);
850 0 : CPLFree(pszProj4);
851 : }
852 0 : if( syscoord )
853 : {
854 0 : DestroySysCoord_GCSRS(&syscoord);
855 : }
856 0 : return NULL;
857 : }/* OGRSpatialReference2SysCoord_GCSRS */
858 :
859 : /* -------------------------------------------------------------------- */
860 4 : OGRSpatialReferenceH GCSRSAPI_CALL SysCoord2OGRSpatialReference_GCSRS ( GCSysCoord* syscoord )
861 : {
862 : OGRSpatialReferenceH poSR;
863 4 : GCDatumInfo* datum= NULL;
864 4 : GCSpheroidInfo* ell= NULL;
865 : int i;
866 : double f;
867 :
868 4 : poSR= OSRNewSpatialReference(NULL);
869 :
870 4 : if( syscoord && GetSysCoordSystemID_GCSRS(syscoord)!=-1 )
871 : {
872 4 : switch( GetSysCoordProjID_GCSRS(syscoord) )
873 : {
874 : case 0 : /* long/lat */
875 2 : break;
876 : case 1: /* UTM */
877 : case 11: /* MGRS */
878 : case 12: /* TM */
879 0 : OSRSetTM(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
880 : GetSysCoordCentralMeridian_GCSRS(syscoord),
881 : GetSysCoordScaleFactor_GCSRS(syscoord),
882 : GetSysCoordFalseEasting_GCSRS(syscoord),
883 : GetSysCoordFalseNorthing_GCSRS(syscoord));
884 0 : break;
885 : case 2: /* LCC 1SP */
886 0 : OSRSetLCC1SP(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
887 : GetSysCoordCentralMeridian_GCSRS(syscoord),
888 : GetSysCoordScaleFactor_GCSRS(syscoord),
889 : GetSysCoordFalseEasting_GCSRS(syscoord),
890 : GetSysCoordFalseNorthing_GCSRS(syscoord));
891 0 : break;
892 : case 3: /* Bonne */
893 0 : OSRSetBonne(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
894 : GetSysCoordCentralMeridian_GCSRS(syscoord),
895 : GetSysCoordFalseEasting_GCSRS(syscoord),
896 : GetSysCoordFalseNorthing_GCSRS(syscoord));
897 0 : break;
898 : case 4: /* Plate Caree */
899 0 : OSRSetEquirectangular(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
900 : GetSysCoordCentralMeridian_GCSRS(syscoord),
901 : GetSysCoordFalseEasting_GCSRS(syscoord),
902 : GetSysCoordFalseNorthing_GCSRS(syscoord));
903 0 : break;
904 : case 18: /* LCC 2SP */
905 2 : OSRSetLCC(poSR, GetSysCoordStandardParallel1_GCSRS(syscoord),
906 : GetSysCoordStandardParallel2_GCSRS(syscoord),
907 : GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
908 : GetSysCoordCentralMeridian_GCSRS(syscoord),
909 : GetSysCoordFalseEasting_GCSRS(syscoord),
910 : GetSysCoordFalseNorthing_GCSRS(syscoord));
911 2 : break;
912 : case 19: /* Gauss Schreiber : Reunion */
913 0 : OSRSetGaussSchreiberTMercator(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
914 : GetSysCoordCentralMeridian_GCSRS(syscoord),
915 : GetSysCoordScaleFactor_GCSRS(syscoord),
916 : GetSysCoordFalseEasting_GCSRS(syscoord),
917 : GetSysCoordFalseNorthing_GCSRS(syscoord));
918 0 : break;
919 : case 20: /* Polyconic */
920 0 : OSRSetPolyconic(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
921 : GetSysCoordCentralMeridian_GCSRS(syscoord),
922 : GetSysCoordFalseEasting_GCSRS(syscoord),
923 : GetSysCoordFalseNorthing_GCSRS(syscoord));
924 0 : break;
925 : case 21: /* Direct Mercator */
926 0 : OSRSetMercator(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
927 : GetSysCoordCentralMeridian_GCSRS(syscoord),
928 : GetSysCoordScaleFactor_GCSRS(syscoord),
929 : GetSysCoordFalseEasting_GCSRS(syscoord),
930 : GetSysCoordFalseNorthing_GCSRS(syscoord));
931 0 : break;
932 : case 22: /* Stereographic oblic */
933 0 : OSRSetOS(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
934 : GetSysCoordCentralMeridian_GCSRS(syscoord),
935 : GetSysCoordScaleFactor_GCSRS(syscoord),
936 : GetSysCoordFalseEasting_GCSRS(syscoord),
937 : GetSysCoordFalseNorthing_GCSRS(syscoord));
938 0 : break;
939 : case 24: /* Miller */
940 0 : OSRSetMC(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
941 : GetSysCoordCentralMeridian_GCSRS(syscoord),
942 : GetSysCoordFalseEasting_GCSRS(syscoord),
943 : GetSysCoordFalseNorthing_GCSRS(syscoord));
944 0 : break;
945 : case 26: /* Equi rectangular */
946 0 : OSRSetEquirectangular2(poSR, GetSysCoordLatitudeOfOrigin_GCSRS(syscoord),
947 : GetSysCoordCentralMeridian_GCSRS(syscoord),
948 : GetSysCoordStandardParallel1_GCSRS(syscoord),
949 : GetSysCoordFalseEasting_GCSRS(syscoord),
950 : GetSysCoordFalseNorthing_GCSRS(syscoord));
951 : break;
952 : default :
953 : break;
954 : }
955 4 : if( GetSysCoordProjID_GCSRS(syscoord)>0 )
956 2 : OSRSetProjCS(poSR, GetSysCoordName_GCSRS(syscoord));
957 :
958 76 : for( i= 0, datum= &(gk_asDatumList[0]);
959 72 : GetInfoDatumID_GCSRS(datum)!=-1;
960 68 : i++, datum= &(gk_asDatumList[i]) )
961 : {
962 72 : if( GetInfoDatumID_GCSRS(datum)==GetSysCoordDatumID_GCSRS(syscoord) ) break;
963 : }
964 20 : for( i= 0, ell= &(gk_asSpheroidList[0]);
965 16 : GetInfoSpheroidID_GCSRS(ell)!=-1;
966 12 : i++, ell= &(gk_asSpheroidList[i]) )
967 : {
968 16 : if( _areCompatibleSpheroids_GCSRS(GetInfoSpheroidID_GCSRS(ell),
969 4 : GetInfoDatumSpheroidID_GCSRS(datum)) ) break;
970 : }
971 : /* FIXME : WGS 84 and GRS 80 assimilation by Geoconcept : */
972 4 : if( GetInfoDatumID_GCSRS(datum)==4 ) /* WGS 84 */
973 : {
974 2 : ell= &(gk_asSpheroidList[8]);
975 : }
976 2 : else if( GetInfoDatumID_GCSRS(datum)==9984 ) /* GRS 80 */
977 : {
978 2 : ell= &(gk_asSpheroidList[3]);
979 : }
980 4 : f= 1.0 - sqrt(1.0 - GetInfoSpheroidExcentricity_GCSRS(ell)*GetInfoSpheroidExcentricity_GCSRS(ell));
981 24 : OSRSetGeogCS(poSR, GetSysCoordProjID_GCSRS(syscoord)!=0 || !GetSysCoordName_GCSRS(syscoord)?
982 : "unnamed":GetSysCoordName_GCSRS(syscoord),
983 4 : GetInfoDatumID_GCSRS(datum)>=0? GetInfoDatumName_GCSRS(datum):"unknown",
984 4 : GetInfoSpheroidID_GCSRS(ell)>=0? GetInfoSpheroidName_GCSRS(ell):"unknown",
985 4 : GetInfoSpheroidID_GCSRS(ell)>=0? GetInfoSpheroidSemiMajor_GCSRS(ell):6378137.0,
986 8 : GetInfoSpheroidID_GCSRS(ell)>=0? (f==0? 0:1/f):298.257223563,
987 : "Greenwich",
988 : GetSysCoordPrimeMeridian_GCSRS(syscoord),
989 : SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV));
990 : /* As Geoconcept uses Molodensky, we've got only 3 out of 7 params for Bursa-Wolf : */
991 : /* the 4 missing Bursa-Wolf parameters have been added to the gk_asDatumList ! */
992 4 : if( GetInfoProjID_GCSRS(syscoord)>0 && GetInfoDatumID_GCSRS(datum)!=-1 )
993 : {
994 2 : OSRSetTOWGS84(poSR, GetInfoDatumShiftX_GCSRS(datum),
995 : GetInfoDatumShiftY_GCSRS(datum),
996 : GetInfoDatumShiftZ_GCSRS(datum),
997 : GetInfoDatumRotationX_GCSRS(datum),
998 : GetInfoDatumRotationY_GCSRS(datum),
999 : GetInfoDatumRotationZ_GCSRS(datum),
1000 : 1e6*GetInfoDatumScaleFactor_GCSRS(datum));
1001 : }
1002 : }
1003 :
1004 : /* -------------------------------------------------------------------- */
1005 : /* Report on translation. */
1006 : /* -------------------------------------------------------------------- */
1007 : {
1008 : char* pszWKT;
1009 :
1010 4 : OSRExportToWkt(poSR,&pszWKT);
1011 4 : if( pszWKT!=NULL )
1012 : {
1013 4 : CPLDebug( "GEOCONCEPT",
1014 : "This SysCoord value: %d:%d was translated to : %s",
1015 : GetSysCoordSystemID_GCSRS(syscoord),
1016 : GetSysCoordTimeZone_GCSRS(syscoord),
1017 : pszWKT );
1018 4 : CPLFree( pszWKT );
1019 : }
1020 : }
1021 :
1022 4 : return poSR;
1023 : }/* SysCoord2OGRSpatialReference_GCSRS */
|