1 : /**********************************************************************
2 : * $Id: mitab_spatialref.cpp,v 1.55 2011-06-11 00:35:00 fwarmerdam Exp $
3 : *
4 : * Name: mitab_spatialref.cpp
5 : * Project: MapInfo TAB Read/Write library
6 : * Language: C++
7 : * Purpose: Implementation of the SpatialRef stuff in the TABFile class.
8 : * Author: Frank Warmerdam, warmerdam@pobox.com
9 : *
10 : **********************************************************************
11 : * Copyright (c) 1999-2001, Frank Warmerdam
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 : * $Log: mitab_spatialref.cpp,v $
33 : * Revision 1.55 2011-06-11 00:35:00 fwarmerdam
34 : * add support for reading google mercator (#4115)
35 : *
36 : * Revision 1.54 2010-10-07 18:46:26 aboudreault
37 : * Fixed bad use of atof when locale setting doesn't use . for float (GDAL bug #3775)
38 : *
39 : * Revision 1.53 2010-09-07 16:48:08 aboudreault
40 : * Removed incomplete patch for affine params support in mitab. (bug 1155)
41 : *
42 : * Revision 1.52 2010-07-08 17:21:12 aboudreault
43 : * Put back New_Zealand Datum in asDatumInfoList
44 : *
45 : * Revision 1.51 2010-07-07 19:00:15 aboudreault
46 : * Cleanup Win32 Compile Warnings (GDAL bug #2930)
47 : *
48 : * Revision 1.50 2010-07-05 17:20:14 aboudreault
49 : * Added Krovak projection suppoprt (bug 2230)
50 : *
51 : * Revision 1.49 2009-10-15 16:16:37 fwarmerdam
52 : * add the default EPSG/OGR name for new zealand datums (gdal #3187)
53 : *
54 : * Revision 1.48 2007/11/21 21:15:45 dmorissette
55 : * Fix asDatumInfoList[] and asSpheroidInfoList[] defns/refs (bug 1826)
56 : *
57 : * Revision 1.47 2006/07/10 17:58:48 fwarmerdam
58 : * North_American_Datum_1927 support
59 : *
60 : * Revision 1.46 2006/07/07 19:41:32 dmorissette
61 : * Fixed problem with uninitialized sTABProj.nAffineFlag (bug 1254,1319)
62 : *
63 : * Revision 1.45 2006/05/09 20:21:29 fwarmerdam
64 : * Coordsys false easting and northing are in the units of the coordsys, not
65 : * necessarily meters. Adjusted mitab_spatialref.cpp to reflect this.
66 : * http://bugzilla.remotesensing.org/show_bug.cgi?id=1113
67 : *
68 : * Revision 1.44 2005/09/29 20:15:36 dmorissette
69 : * More improvements to handling of modified TM projections 21-24.
70 : * Added correct name stings to all datum definitions (Anthony D, bug 1155)
71 : *
72 : * Revision 1.43 2005/05/12 22:07:52 dmorissette
73 : * Improved handling of Danish modified TM proj#21-24 (hss, bugs 976,1010)
74 : *
75 : * Revision 1.42 2005/03/22 23:24:54 dmorissette
76 : * Added support for datum id in .MAP header (bug 910)
77 : *
78 : * Revision 1.41 2004/10/11 20:50:04 dmorissette
79 : * 7 new datum defns, 1 fixed and list of ellipsoids updated (Bug 608,Uffe K.)
80 : *
81 : * Revision 1.40 2003/03/21 14:20:42 warmerda
82 : * fixed up regional mercator handling, was screwing up transverse mercator
83 : *
84 : * Revision 1.39 2002/12/19 20:46:01 warmerda
85 : * fixed spelling of Provisional_South_American_Datum_1956
86 : *
87 : * Revision 1.38 2002/12/12 20:12:18 warmerda
88 : * fixed signs of rotational parameters for TOWGS84 in WKT
89 : *
90 : * Revision 1.37 2002/10/15 14:33:30 warmerda
91 : * Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for
92 : * projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant -
93 : * All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect
94 : * (29).
95 : *
96 : * Revision 1.36 2002/09/05 15:38:16 warmerda
97 : * one more ogc datum name
98 : *
99 : * Revision 1.35 2002/09/05 15:23:22 warmerda
100 : * added some EPSG datum names provided by Siro Martello @ Cadcorp
101 : *
102 : * Revision 1.34 2002/04/01 19:49:24 warmerda
103 : * added support for cassini/soldner - proj 30
104 : *
105 : * Revision 1.33 2002/03/01 19:00:15 warmerda
106 : * False Easting/Northing should be in the linear units of measure in MapInfo,
107 : * but in OGRSpatialReference/WKT they are always in meters. Convert accordingly.
108 : *
109 : * Revision 1.32 2001/10/25 16:13:41 warmerda
110 : * Added OGC string for datum 12
111 : *
112 : * Revision 1.31 2001/08/10 21:25:59 warmerda
113 : * SetSpatialRef() now makes a clone of the srs instead of taking a ref to it
114 : *
115 : * Revision 1.30 2001/04/23 17:38:06 warmerda
116 : * fixed use of freed points bug for datum 999/9999
117 : *
118 : * Revision 1.29 2001/04/04 21:43:19 warmerda
119 : * added code to set WGS84 values
120 : *
121 : * Revision 1.28 2001/01/23 21:23:42 daniel
122 : * Added projection bounds lookup table, called from TABFile::SetProjInfo()
123 : *
124 : * Revision 1.27 2001/01/22 16:00:53 warmerda
125 : * reworked swiss projection support
126 : *
127 : * Revision 1.26 2001/01/19 21:56:18 warmerda
128 : * added untested support for Swiss Oblique Mercator
129 : *
130 : * Revision 1.25 2000/12/05 14:56:55 daniel
131 : * Added some missing unit names (aliases) in TABFile::SetSpatialRef()
132 : *
133 : * Revision 1.24 2000/10/16 21:44:50 warmerda
134 : * added nonearth support
135 : *
136 : * Revision 1.23 2000/10/16 18:01:20 warmerda
137 : * added check for NULL on passed in spatial ref
138 : *
139 : * Revision 1.22 2000/10/02 14:46:36 daniel
140 : * Added 7 parameter datums with id 1000+
141 : *
142 : * Revision 1.21 2000/09/29 22:09:18 daniel
143 : * Added new datums/ellipsoid from MapInfo V6.0
144 : *
145 : * Revision 1.20 2000/09/28 16:39:44 warmerda
146 : * avoid warnings for unused, and unitialized variables
147 : *
148 : * Revision 1.19 2000/02/07 17:43:17 daniel
149 : * Fixed offset in parsing of custom datum string in SetSpatialRef()
150 : *
151 : * Revision 1.18 2000/02/04 05:30:50 daniel
152 : * Fixed problem in GetSpatialRef() with szDatumName[] buffer size and added
153 : * use of an epsilon in comparing of datum parameters.
154 : *
155 : * Revision 1.17 2000/01/15 22:30:45 daniel
156 : * Switch to MIT/X-Consortium OpenSource license
157 : *
158 : * Revision 1.16 1999/12/21 20:01:47 warmerda
159 : * added support for DATUM 0
160 : *
161 : * Revision 1.15 1999/11/11 02:56:17 warmerda
162 : * fixed problems with stereographic
163 : *
164 : * Revision 1.14 1999/11/10 20:13:12 warmerda
165 : * implement spheroid table
166 : *
167 : * Revision 1.13 1999/11/09 22:31:38 warmerda
168 : * initial implementation of MIF CoordSys support
169 : *
170 : * Revision 1.12 1999/10/19 16:31:32 warmerda
171 : * Improved mile support.
172 : *
173 : * Revision 1.11 1999/10/19 16:27:50 warmerda
174 : * Added support for Mile (units=0). Also added support for nonearth
175 : * projections.
176 : *
177 : * Revision 1.10 1999/10/05 18:56:08 warmerda
178 : * fixed lots of bugs with projection parameters
179 : *
180 : * Revision 1.9 1999/10/04 21:17:47 warmerda
181 : * Make sure that asDatumInfoList comparisons include the ellipsoid code.
182 : * Don't include OGC name for local NAD27 values. Put NAD83 ahead of GRS80
183 : * so it will be used in preference even though they are identical parms.
184 : *
185 : * Revision 1.8 1999/10/04 19:46:42 warmerda
186 : * assorted changes, including rework of units
187 : *
188 : * Revision 1.7 1999/09/28 04:52:17 daniel
189 : * Added missing param in sprintf() format for szDatumName[]
190 : *
191 : * Revision 1.6 1999/09/28 02:51:46 warmerda
192 : * Added ellipsoid codes, and bulk of write implementation.
193 : *
194 : * Revision 1.5 1999/09/27 21:23:41 warmerda
195 : * added more projections
196 : *
197 : * Revision 1.4 1999/09/24 04:01:28 warmerda
198 : * remember nMIDatumId changes
199 : *
200 : * Revision 1.3 1999/09/23 19:51:38 warmerda
201 : * added datum mapping table support
202 : *
203 : * Revision 1.2 1999/09/22 23:04:59 daniel
204 : * Handle reference count on OGRSpatialReference properly
205 : *
206 : * Revision 1.1 1999/09/21 19:39:22 daniel
207 : * Moved Get/SetSpatialRef() to a separate file
208 : *
209 : **********************************************************************/
210 :
211 : #include "mitab.h"
212 :
213 : /* -------------------------------------------------------------------- */
214 : /* This table was automatically generated by doing translations */
215 : /* between mif and tab for each datum, and extracting the */
216 : /* parameters from the tab file. The EPSG codes and OGC names */
217 : /* were added afterwards and may be incomplete or inaccurate. */
218 : /* -------------------------------------------------------------------- */
219 :
220 : MapInfoDatumInfo asDatumInfoList[] =
221 : {
222 :
223 : { 0, 104, "WGS_1984", 28,0, 0, 0, 0, 0, 0, 0, 0},
224 : { 6269, 74, "North_American_Datum_1983", 0, 0, 0, 0, 0, 0, 0, 0, 0},
225 :
226 : { 0, 0, "", 29, 0, 0, 0, 0, 0, 0, 0, 0}, // Datum ignore
227 :
228 : { 6201, 1, "Adindan", 6, -162, -12, 206, 0, 0, 0, 0, 0},
229 : { 6205, 2, "Afgooye", 3, -43, -163, 45, 0, 0, 0, 0, 0},
230 : { 6204, 3, "Ain_el_Abd_1970", 4, -150, -251, -2, 0, 0, 0, 0, 0},
231 : { 0, 4, "Anna_1_Astro_1965", 2, -491, -22, 435, 0, 0, 0, 0, 0},
232 : { 6209, 5, "Arc_1950", 15,-143, -90, -294,0, 0, 0, 0, 0},
233 : { 6210, 6, "Arc_1960", 6, -160, -8, -300,0, 0, 0, 0, 0},
234 : { 0, 7, "Ascension_Islands", 4, -207, 107, 52, 0, 0, 0, 0, 0},
235 : { 0, 8, "Astro_Beacon_E", 4, 145, 75, -272,0, 0, 0, 0, 0},
236 : { 0, 9, "Astro_B4_Sorol_Atoll", 4, 114, -116, -333,0, 0, 0, 0, 0},
237 : { 0, 10, "Astro_Dos_71_4", 4, -320, 550, -494,0, 0, 0, 0, 0},
238 : { 0, 11, "Astronomic_Station_1952", 4, 124, -234, -25, 0, 0, 0, 0, 0},
239 : { 6202, 12, "Australian_Geodetic_Datum_66",2, -133, -48, 148, 0, 0, 0, 0, 0},
240 : { 6203, 13, "Australian_Geodetic_Datum_84",2, -134, -48, 149, 0, 0, 0, 0, 0},
241 : { 0, 14, "Bellevue_Ign", 4, -127, -769, 472, 0, 0, 0, 0, 0},
242 : { 6216, 15, "Bermuda_1957", 7, -73, 213, 296, 0, 0, 0, 0, 0},
243 : { 6218, 16, "Bogota", 4, 307, 304, -318,0, 0, 0, 0, 0},
244 : { 6221, 17, "Campo_Inchauspe", 4, -148, 136, 90, 0, 0, 0, 0, 0},
245 : { 0, 18, "Canton_Astro_1966", 4, 298, -304, -375,0, 0, 0, 0, 0},
246 : { 6222, 19, "Cape", 6, -136, -108, -292,0, 0, 0, 0, 0},
247 : { 6717, 20, "Cape_Canaveral", 7, -2, 150, 181, 0, 0, 0, 0, 0},
248 : { 6223, 21, "Carthage", 6, -263, 6, 431, 0, 0, 0, 0, 0},
249 : { 6672, 22, "Chatham_1971", 4, 175, -38, 113, 0, 0, 0, 0, 0},
250 : { 6224, 23, "Chua", 4, -134, 229, -29, 0, 0, 0, 0, 0},
251 : { 6225, 24, "Corrego_Alegre", 4, -206, 172, -6, 0, 0, 0, 0, 0},
252 : { 6211, 25, "Batavia", 10,-377,681, -50, 0, 0, 0, 0, 0},
253 : { 0, 26, "Dos_1968", 4, 230, -199, -752,0, 0, 0, 0, 0},
254 : { 6719, 27, "Easter_Island_1967", 4, 211, 147, 111, 0, 0, 0, 0, 0},
255 : { 6230, 28, "European_Datum_1950", 4, -87, -98, -121,0, 0, 0, 0, 0},
256 : { 6668, 29, "European_Datum_1979", 4, -86, -98, -119,0, 0, 0, 0, 0},
257 : { 6233, 30, "Gandajika_1970", 4, -133, -321, 50, 0, 0, 0, 0, 0},
258 : { 6272, 31, "New_Zealand_GD49", 4, 84, -22, 209, 0, 0, 0, 0, 0},
259 : { 6272, 31, "New_Zealand_Geodetic_Datum_1949",4,84, -22, 209, 0, 0, 0, 0, 0},
260 : { 0, 32, "GRS_67", 21,0, 0, 0, 0, 0, 0, 0, 0},
261 : { 0, 33, "GRS_80", 0, 0, 0, 0, 0, 0, 0, 0, 0},
262 : { 6675, 34, "Guam_1963", 7, -100, -248, 259, 0, 0, 0, 0, 0},
263 : { 0, 35, "Gux_1_Astro", 4, 252, -209, -751,0, 0, 0, 0, 0},
264 : { 6254, 36, "Hito_XVIII_1963", 4, 16, 196, 93, 0, 0, 0, 0, 0},
265 : { 6658, 37, "Hjorsey_1955", 4, -73, 46, -86, 0, 0, 0, 0, 0},
266 : { 6738, 38, "Hong_Kong_1963", 4, -156, -271, -189,0, 0, 0, 0, 0},
267 : { 6236, 39, "Hu_Tzu_Shan", 4, -634, -549, -201,0, 0, 0, 0, 0},
268 : { 0, 40, "Indian_Thailand_Vietnam", 11,214, 836, 303, 0, 0, 0, 0, 0},
269 : { 0, 41, "Indian_Bangladesh", 11,289, 734, 257, 0, 0, 0, 0, 0},
270 : { 0, 42, "Ireland_1965", 13,506, -122, 611, 0, 0, 0, 0, 0},
271 : { 0, 43, "ISTS_073_Astro_1969", 4, 208, -435, -229,0, 0, 0, 0, 0},
272 : { 6725, 44, "Johnston_Island_1961", 4, 191, -77, -204,0, 0, 0, 0, 0},
273 : { 6244, 45, "Kandawala", 11,-97, 787, 86, 0, 0, 0, 0, 0},
274 : { 0, 46, "Kerguyelen_Island", 4, 145, -187, 103, 0, 0, 0, 0, 0},
275 : { 6245, 47, "Kertau", 17,-11, 851, 5, 0, 0, 0, 0, 0},
276 : { 0, 48, "L_C_5_Astro", 7, 42, 124, 147, 0, 0, 0, 0, 0},
277 : { 6251, 49, "Liberia_1964", 6, -90, 40, 88, 0, 0, 0, 0, 0},
278 : { 0, 50, "Luzon_Phillippines", 7, -133, -77, -51, 0, 0, 0, 0, 0},
279 : { 0, 51, "Luzon_Mindanao_Island", 7, -133, -79, -72, 0, 0, 0, 0, 0},
280 : { 6256, 52, "Mahe_1971", 6, 41, -220, -134,0, 0, 0, 0, 0},
281 : { 0, 53, "Marco_Astro", 4, -289, -124, 60, 0, 0, 0, 0, 0},
282 : { 6262, 54, "Massawa", 10,639, 405, 60, 0, 0, 0, 0, 0},
283 : { 6261, 55, "Merchich", 16,31, 146, 47, 0, 0, 0, 0, 0},
284 : { 0, 56, "Midway_Astro_1961", 4, 912, -58, 1227,0, 0, 0, 0, 0},
285 : { 6263, 57, "Minna", 6, -92, -93, 122, 0, 0, 0, 0, 0},
286 : { 0, 58, "Nahrwan_Masirah_Island", 6, -247, -148, 369, 0, 0, 0, 0, 0},
287 : { 0, 59, "Nahrwan_Un_Arab_Emirates", 6, -249, -156, 381, 0, 0, 0, 0, 0},
288 : { 0, 60, "Nahrwan_Saudi_Arabia", 6, -231, -196, 482, 0, 0, 0, 0, 0},
289 : { 6271, 61, "Naparima_1972", 4, -2, 374, 172, 0, 0, 0, 0, 0},
290 : { 6267, 62, "NAD_1927", 7, -8, 160, 176, 0, 0, 0, 0, 0},
291 : { 6267, 62, "North_American_Datum_1927", 7, -8, 160, 176, 0, 0, 0, 0, 0},
292 : { 0, 63, "NAD_27_Alaska", 7, -5, 135, 172, 0, 0, 0, 0, 0},
293 : { 0, 64, "NAD_27_Bahamas", 7, -4, 154, 178, 0, 0, 0, 0, 0},
294 : { 0, 65, "NAD_27_San_Salvador", 7, 1, 140, 165, 0, 0, 0, 0, 0},
295 : { 0, 66, "NAD_27_Canada", 7, -10, 158, 187, 0, 0, 0, 0, 0},
296 : { 0, 67, "NAD_27_Canal_Zone", 7, 0, 125, 201, 0, 0, 0, 0, 0},
297 : { 0, 68, "NAD_27_Caribbean", 7, -7, 152, 178, 0, 0, 0, 0, 0},
298 : { 0, 69, "NAD_27_Central_America", 7, 0, 125, 194, 0, 0, 0, 0, 0},
299 : { 0, 70, "NAD_27_Cuba", 7, -9, 152, 178, 0, 0, 0, 0, 0},
300 : { 0, 71, "NAD_27_Greenland", 7, 11, 114, 195, 0, 0, 0, 0, 0},
301 : { 0, 72, "NAD_27_Mexico", 7, -12, 130, 190, 0, 0, 0, 0, 0},
302 : { 0, 73, "NAD_27_Michigan", 8, -8, 160, 176, 0, 0, 0, 0, 0},
303 : { 0, 75, "Observatorio_1966", 4, -425, -169, 81, 0, 0, 0, 0, 0},
304 : { 0, 76, "Old_Egyptian", 22,-130, 110, -13, 0, 0, 0, 0, 0},
305 : { 6135, 77, "Old_Hawaiian", 7, 61, -285, -181,0, 0, 0, 0, 0},
306 : { 0, 78, "Oman", 6, -346, -1, 224, 0, 0, 0, 0, 0},
307 : { 6277, 79, "OSGB_1936", 9, 375, -111, 431, 0, 0, 0, 0, 0},
308 : { 0, 80, "Pico_De_Las_Nieves", 4, -307, -92, 127, 0, 0, 0, 0, 0},
309 : { 6729, 81, "Pitcairn_Astro_1967", 4, 185, 165, 42, 0, 0, 0, 0, 0},
310 : { 6248, 82, "Provisional_South_American", 4, -288, 175, -376,0, 0, 0, 0, 0},
311 : { 6139, 83, "Puerto_Rico", 7, 11, 72, -101,0, 0, 0, 0, 0},
312 : { 6614, 84, "Qatar_National", 4, -128, -283, 22, 0, 0, 0, 0, 0},
313 : { 6287, 85, "Qornoq", 4, 164, 138, -189, 0, 0, 0, 0, 0},
314 : { 6627, 86, "Reunion", 4, 94, -948,-1262,0, 0, 0, 0, 0},
315 : { 6265, 87, "Monte_Mario", 4, -225, -65, 9, 0, 0, 0, 0, 0},
316 : { 0, 88, "Santo_Dos", 4, 170, 42, 84, 0, 0, 0, 0, 0},
317 : { 0, 89, "Sao_Braz", 4, -203, 141, 53, 0, 0, 0, 0, 0},
318 : { 6292, 90, "Sapper_Hill_1943", 4, -355, 16, 74, 0, 0, 0, 0, 0},
319 : { 6293, 91, "Schwarzeck", 14,616, 97, -251, 0, 0, 0, 0, 0},
320 : { 6618, 92, "South_American_Datum_1969", 24,-57, 1, -41, 0, 0, 0, 0, 0},
321 : { 0, 93, "South_Asia", 19,7, -10, -26, 0, 0, 0, 0, 0},
322 : { 0, 94, "Southeast_Base", 4, -499, -249,314, 0, 0, 0, 0, 0},
323 : { 0, 95, "Southwest_Base", 4, -104, 167, -38, 0, 0, 0, 0, 0},
324 : { 6298, 96, "Timbalai_1948", 11,-689, 691, -46, 0, 0, 0, 0, 0},
325 : { 6301, 97, "Tokyo", 10,-128, 481, 664, 0, 0, 0, 0, 0},
326 : { 0, 98, "Tristan_Astro_1968", 4, -632, 438, -609, 0, 0, 0, 0, 0},
327 : { 6731, 99, "Viti_Levu_1916", 6, 51, 391, -36, 0, 0, 0, 0, 0},
328 : { 0, 100, "Wake_Entiwetok_1960", 23,101, 52, -39, 0, 0, 0, 0, 0},
329 : { 0, 101, "WGS_60", 26,0, 0, 0, 0, 0, 0, 0, 0},
330 : { 6760, 102, "WGS_66", 27,0, 0, 0, 0, 0, 0, 0, 0},
331 : { 6322, 103, "WGS_1972", 1, 0, 8, 10, 0, 0, 0, 0, 0},
332 : { 6326, 104, "WGS_1984", 28,0, 0, 0, 0, 0, 0, 0, 0},
333 : { 6309, 105, "Yacare", 4, -155, 171, 37, 0, 0, 0, 0, 0},
334 : { 6311, 106, "Zanderij", 4, -265, 120, -358, 0, 0, 0, 0, 0},
335 : { 0, 107, "NTF", 30,-168, -60, 320, 0, 0, 0, 0, 0},
336 : { 6231, 108, "European_Datum_1987", 4, -83, -96, -113, 0, 0, 0, 0, 0},
337 : { 0, 109, "Netherlands_Bessel", 10,593, 26, 478, 0, 0, 0, 0, 0},
338 : { 0, 110, "Belgium_Hayford", 4, 81, 120, 129, 0, 0, 0, 0, 0},
339 : { 0, 111, "NWGL_10", 1, -1, 15, 1, 0, 0, 0, 0, 0},
340 : { 6124, 112, "Rikets_koordinatsystem_1990",10,498, -36, 568, 0, 0, 0, 0, 0},
341 : { 0, 113, "Lisboa_DLX", 4, -303, -62, 105, 0, 0, 0, 0, 0},
342 : { 0, 114, "Melrica_1973_D73", 4, -223, 110, 37, 0, 0, 0, 0, 0},
343 : { 0, 115, "Euref_98", 0, 0, 0, 0, 0, 0, 0, 0, 0},
344 : { 0, 116, "GDA94", 0, 0, 0, 0, 0, 0, 0, 0, 0},
345 : { 6167, 117, "NZGD2000", 0, 0, 0, 0, 0, 0, 0, 0, 0},
346 : { 6167, 117, "New_Zealand_Geodetic_Datum_2000",0,0, 0, 0, 0, 0, 0, 0, 0},
347 : { 6169, 118, "America_Samoa", 7, -115, 118, 426, 0, 0, 0, 0, 0},
348 : { 0, 119, "Antigua_Astro_1965", 6, -270, 13, 62, 0, 0, 0, 0, 0},
349 : { 6713, 120, "Ayabelle_Lighthouse", 6, -79, -129, 145, 0, 0, 0, 0, 0},
350 : { 6219, 121, "Bukit_Rimpah", 10,-384, 664, -48, 0, 0, 0, 0, 0},
351 : { 0, 122, "Estonia_1937", 10,374, 150, 588, 0, 0, 0, 0, 0},
352 : { 6155, 123, "Dabola", 6, -83, 37, 124, 0, 0, 0, 0, 0},
353 : { 6736, 124, "Deception_Island", 6, 260, 12, -147, 0, 0, 0, 0, 0},
354 : { 0, 125, "Fort_Thomas_1955", 6, -7, 215, 225, 0, 0, 0, 0, 0},
355 : { 0, 126, "Graciosa_base_1948", 4, -104, 167, -38, 0, 0, 0, 0, 0},
356 : { 6255, 127, "Herat_North", 4, -333, -222,114, 0, 0, 0, 0, 0},
357 : { 0, 128, "Hermanns_Kogel", 10,682, -203, 480, 0, 0, 0, 0, 0},
358 : { 6240, 129, "Indian", 50,283, 682, 231, 0, 0, 0, 0, 0},
359 : { 6239, 130, "Indian_1954", 11,217, 823, 299, 0, 0, 0, 0, 0},
360 : { 6131, 131, "Indian_1960", 11,198, 881, 317, 0, 0, 0, 0, 0},
361 : { 6240, 132, "Indian_1975", 11,210, 814, 289, 0, 0, 0, 0, 0},
362 : { 6238, 133, "Indonesian_Datum_1974", 4, -24, -15, 5, 0, 0, 0, 0, 0},
363 : { 0, 134, "ISTS061_Astro_1968", 4, -794, 119, -298, 0, 0, 0, 0, 0},
364 : { 0, 135, "Kusaie_Astro_1951", 4, 647, 1777, -1124,0, 0, 0, 0, 0},
365 : { 6250, 136, "Leigon", 6, -130, 29, 364, 0, 0, 0, 0, 0},
366 : { 0, 137, "Montserrat_Astro_1958", 6, 174, 359, 365, 0, 0, 0, 0, 0},
367 : { 6266, 138, "Mporaloko", 6, -74, -130, 42, 0, 0, 0, 0, 0},
368 : { 0, 139, "North_Sahara_1959", 6, -186, -93, 310, 0, 0, 0, 0, 0},
369 : { 0, 140, "Observatorio_Met_1939", 4, -425, -169,81, 0, 0, 0, 0, 0},
370 : { 6620, 141, "Point_58", 6, -106, -129,165, 0, 0, 0, 0, 0},
371 : { 6282, 142, "Pointe_Noire", 6, -148, 51, -291, 0, 0, 0, 0, 0},
372 : { 6615, 143, "Porto_Santo_1936", 4, -499, -249,314, 0, 0, 0, 0, 0},
373 : { 6616, 144, "Selvagem_Grande_1938", 4, -289, -124,60, 0, 0, 0, 0, 0},
374 : { 0, 145, "Sierra_Leone_1960", 6, -88, 4, 101, 0, 0, 0, 0, 0},
375 : { 6156, 146, "S_JTSK_Ferro", 10, 589, 76, 480, 0, 0, 0, 0, 0},
376 : { 6297, 147, "Tananarive_1925", 4, -189, -242,-91, 0, 0, 0, 0, 0},
377 : { 0, 148, "Voirol_1874", 6, -73, -247,227, 0, 0, 0, 0, 0},
378 : { 0, 149, "Virol_1960", 6, -123, -206,219, 0, 0, 0, 0, 0},
379 : { 6148, 150, "Hartebeesthoek94", 0, 0, 0, 0, 0, 0, 0, 0, 0},
380 : { 6122, 151, "ATS77", 51, 0, 0, 0, 0, 0, 0, 0, 0},
381 : { 6612, 152, "JGD2000", 0, 0, 0, 0, 0, 0, 0, 0, 0},
382 : { 0, 157, "WGS_1984", 54, 0, 0, 0, 0, 0, 0, 0, 0}, // Google merc
383 : { 0, 1000,"DHDN_Potsdam_Rauenberg", 10,582, 105, 414, -1.04, -0.35, 3.08, 8.3, 0},
384 : { 6284, 1001,"Pulkovo_1942", 3, 24, -123, -94, -0.02, 0.25, 0.13, 1.1, 0},
385 : { 6275, 1002,"NTF_Paris_Meridian", 30,-168, -60, 320, 0, 0, 0, 0, 2.337229166667},
386 : { 0, 1003,"Switzerland_CH_1903", 10,660.077,13.551, 369.344, 0.804816, 0.577692, 0.952236, 5.66,0},
387 : { 6237, 1004,"Hungarian_Datum_1972", 21,-56, 75.77, 15.31, -0.37, -0.2, -0.21, -1.01, 0},
388 : { 0, 1005,"Cape_7_Parameter", 28,-134.73,-110.92, -292.66, 0, 0, 0, 1, 0},
389 : { 6203, 1006,"AGD84_7_Param_Aust", 2, -117.763,-51.51, 139.061, -0.292, -0.443, -0.277, -0.191, 0},
390 : { 0, 1007,"AGD66_7_Param_ACT", 2, -129.193,-41.212, 130.73, -0.246, -0.374, -0.329, -2.955, 0},
391 : { 0, 1008,"AGD66_7_Param_TAS", 2, -120.271,-64.543, 161.632, -0.2175, 0.0672, 0.1291, 2.4985, 0},
392 : { 0, 1009,"AGD66_7_Param_VIC_NSW", 2, -119.353,-48.301, 139.484, -0.415, -0.26, -0.437, -0.613, 0},
393 : { 6272, 1010,"NZGD_7_Param_49", 4, 59.47, -5.04, 187.44, -0.47, 0.1, -1.024, -4.5993, 0},
394 : { 0, 1011,"Rikets_Tri_7_Param_1990", 10,419.3836, 99.3335, 591.3451, -0.850389, -1.817277, 7.862238, -0.99496, 0},
395 : { 0, 1012,"Russia_PZ90", 52, -1.08,-0.27,-0.9,0, 0, -0.16,-0.12, 0},
396 : { 0, 1013,"Russia_SK42", 52, 23.92,-141.27,-80.9, 0, -0.35,-0.82, -0.12, 0},
397 : { 0, 1014,"Russia_SK95", 52, 24.82,-131.21,-82.66,0,0,-0.16,-0.12, 0},
398 : { 6301, 1015,"Tokyo", 10, -146.414, 507.337, 680.507,0,0,0,0,0},
399 : { 0, 1016,"Finnish_KKJ", 4, -96.062, -82.428, -121.754, -4.801, -0.345, 1.376, 1.496, 0},
400 : { 6610, 1017,"Xian 1980", 53, 24, -123, -94, -0.02, -0.25, 0.13, 1.1, 0},
401 : { 0, 1018,"Lithuanian Pulkovo 1942", 4, -40.59527, -18.54979, -69.33956, -2.508, -1.8319, 2.6114, -4.2991, 0},
402 : { 0, 1019,"Belgian 1972 7 Parameter", 4, -99.059, 53.322, -112.486, -0.419, 0.83, -1.885, 0.999999, 0},
403 : { 6818, 1020,"S-JTSK with Ferro prime meridian", 10, 589, 76, 480, 0, 0, 0, 0, -17.666666666667},
404 :
405 : { -1, -1, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
406 : };
407 :
408 : /* -------------------------------------------------------------------- */
409 : /* This table was hand entered from Appendix I of the mapinfo 6 */
410 : /* manuals. */
411 : /* -------------------------------------------------------------------- */
412 :
413 : MapInfoSpheroidInfo asSpheroidInfoList[] =
414 : {
415 : { 9,"Airy 1930", 6377563.396, 299.3249646},
416 : {13,"Airy 1930 (modified for Ireland 1965", 6377340.189, 299.3249646},
417 : {51,"ATS77 (Average Terrestrial System 1977)", 6378135, 298.257},
418 : { 2,"Australian", 6378160.0, 298.25},
419 : {10,"Bessel 1841", 6377397.155, 299.1528128},
420 : {35,"Bessel 1841 (modified for NGO 1948)", 6377492.0176, 299.15281},
421 : {14,"Bessel 1841 (modified for Schwarzeck)", 6377483.865, 299.1528128},
422 : {36,"Clarke 1858", 6378293.639, 294.26068},
423 : { 7,"Clarke 1866", 6378206.4, 294.9786982},
424 : { 8,"Clarke 1866 (modified for Michigan)", 6378450.047484481,294.9786982},
425 : { 6,"Clarke 1880", 6378249.145, 293.465},
426 : {15,"Clarke 1880 (modified for Arc 1950)", 6378249.145326, 293.4663076},
427 : {30,"Clarke 1880 (modified for IGN)", 6378249.2, 293.4660213},
428 : {37,"Clarke 1880 (modified for Jamaica)", 6378249.136, 293.46631},
429 : {16,"Clarke 1880 (modified for Merchich)", 6378249.2, 293.46598},
430 : {38,"Clarke 1880 (modified for Palestine)", 6378300.79, 293.46623},
431 : {39,"Everest (Brunei and East Malaysia)", 6377298.556, 300.8017},
432 : {11,"Everest (India 1830)", 6377276.345, 300.8017},
433 : {40,"Everest (India 1956)", 6377301.243, 300.80174},
434 : {50,"Everest (Pakistan)", 6377309.613, 300.8017},
435 : {17,"Everest (W. Malaysia and Singapore 1948)", 6377304.063, 300.8017},
436 : {48,"Everest (West Malaysia 1969)", 6377304.063, 300.8017},
437 : {18,"Fischer 1960", 6378166.0, 298.3},
438 : {19,"Fischer 1960 (modified for South Asia)", 6378155.0, 298.3},
439 : {20,"Fischer 1968", 6378150.0, 298.3},
440 : {21,"GRS 67", 6378160.0, 298.247167427},
441 : { 0,"GRS 80", 6378137.0, 298.257222101},
442 : { 5,"Hayford", 6378388.0, 297.0},
443 : {22,"Helmert 1906", 6378200.0, 298.3},
444 : {23,"Hough", 6378270.0, 297.0},
445 : {31,"IAG 75", 6378140.0, 298.257222},
446 : {41,"Indonesian", 6378160.0, 298.247},
447 : { 4,"International 1924", 6378388.0, 297.0},
448 : {49,"Irish (WOFO)", 6377542.178, 299.325},
449 : { 3,"Krassovsky", 6378245.0, 298.3},
450 : {32,"MERIT 83", 6378137.0, 298.257},
451 : {33,"New International 1967", 6378157.5, 298.25},
452 : {42,"NWL 9D", 6378145.0, 298.25},
453 : {43,"NWL 10D", 6378135.0, 298.26},
454 : {44,"OSU86F", 6378136.2, 298.25722},
455 : {45,"OSU91A", 6378136.3, 298.25722},
456 : {46,"Plessis 1817", 6376523.0, 308.64},
457 : {52,"PZ90", 6378136.0, 298.257839303},
458 : {24,"South American", 6378160.0, 298.25},
459 : {12,"Sphere", 6370997.0, 0.0},
460 : {47,"Struve 1860", 6378297.0, 294.73},
461 : {34,"Walbeck", 6376896.0, 302.78},
462 : {25,"War Office", 6378300.583, 296.0},
463 : {26,"WGS 60", 6378165.0, 298.3},
464 : {27,"WGS 66", 6378145.0, 298.25},
465 : { 1,"WGS 72", 6378135.0, 298.26},
466 : {28,"WGS 84", 6378137.0, 298.257223563},
467 : {29,"WGS 84 (MAPINFO Datum 0)", 6378137.01, 298.257223563},
468 : {54,"WGS 84 (MAPINFO Datum 157)", 6378137.01, 298.257223563},
469 : {-1,NULL, 0.0, 0.0}
470 : };
471 :
472 : /**********************************************************************
473 : * TABFile::GetSpatialRef()
474 : *
475 : * Returns a reference to an OGRSpatialReference for this dataset.
476 : * If the projection parameters have not been parsed yet, then we will
477 : * parse them before returning.
478 : *
479 : * The returned object is owned and maintained by this TABFile and
480 : * should not be modified or freed by the caller.
481 : *
482 : * Returns NULL if the SpatialRef cannot be accessed.
483 : **********************************************************************/
484 2 : OGRSpatialReference *TABFile::GetSpatialRef()
485 : {
486 2 : if (m_eAccessMode != TABRead)
487 : {
488 : CPLError(CE_Failure, CPLE_NotSupported,
489 0 : "GetSpatialRef() can be used only with Read access.");
490 0 : return NULL;
491 : }
492 :
493 2 : if (m_poMAPFile == NULL )
494 : {
495 : CPLError(CE_Failure, CPLE_AssertionFailed,
496 0 : "GetSpatialRef() failed: file has not been opened yet.");
497 0 : return NULL;
498 : }
499 :
500 : /*-----------------------------------------------------------------
501 : * If projection params have already been processed, just use them.
502 : *----------------------------------------------------------------*/
503 2 : if (m_poSpatialRef != NULL)
504 0 : return m_poSpatialRef;
505 :
506 :
507 : /*-----------------------------------------------------------------
508 : * Fetch the parameters from the header.
509 : *----------------------------------------------------------------*/
510 : TABMAPHeaderBlock *poHeader;
511 : TABProjInfo sTABProj;
512 :
513 2 : if ((poHeader = m_poMAPFile->GetHeaderBlock()) == NULL ||
514 : poHeader->GetProjInfo( &sTABProj ) != 0)
515 : {
516 : CPLError(CE_Failure, CPLE_FileIO,
517 0 : "GetSpatialRef() failed reading projection parameters.");
518 0 : return NULL;
519 : }
520 :
521 : /*-----------------------------------------------------------------
522 : * Get the units name, and translation factor.
523 : *----------------------------------------------------------------*/
524 : const char *pszUnitsName;
525 : const char *pszUnitsConv;
526 2 : double dfConv = 1.0;
527 :
528 2 : switch( sTABProj.nUnitsId )
529 : {
530 : case 0:
531 0 : pszUnitsName = "Mile";
532 0 : pszUnitsConv = "1609.344";
533 0 : break;
534 :
535 : case 1:
536 0 : pszUnitsName = "Kilometer";
537 0 : pszUnitsConv = "1000.0";
538 0 : break;
539 :
540 : case 2:
541 0 : pszUnitsName = "IINCH";
542 0 : pszUnitsConv = "0.0254";
543 0 : break;
544 :
545 : case 3:
546 0 : pszUnitsName = SRS_UL_FOOT;
547 0 : pszUnitsConv = SRS_UL_FOOT_CONV;
548 0 : break;
549 :
550 : case 4:
551 0 : pszUnitsName = "IYARD";
552 0 : pszUnitsConv = "0.9144";
553 0 : break;
554 :
555 : case 5:
556 0 : pszUnitsName = "Millimeter";
557 0 : pszUnitsConv = "0.001";
558 0 : break;
559 :
560 : case 6:
561 0 : pszUnitsName = "Centimeter";
562 0 : pszUnitsConv = "0.01";
563 0 : break;
564 :
565 : case 7:
566 2 : pszUnitsName = SRS_UL_METER;
567 2 : pszUnitsConv = "1.0";
568 2 : break;
569 :
570 : case 8:
571 0 : pszUnitsName = SRS_UL_US_FOOT;
572 0 : pszUnitsConv = SRS_UL_US_FOOT_CONV;
573 0 : break;
574 :
575 : case 9:
576 0 : pszUnitsName = SRS_UL_NAUTICAL_MILE;
577 0 : pszUnitsConv = SRS_UL_NAUTICAL_MILE_CONV;
578 0 : break;
579 :
580 : case 30:
581 0 : pszUnitsName = SRS_UL_LINK;
582 0 : pszUnitsConv = SRS_UL_LINK_CONV;
583 0 : break;
584 :
585 : case 31:
586 0 : pszUnitsName = SRS_UL_CHAIN;
587 0 : pszUnitsConv = SRS_UL_CHAIN_CONV;
588 0 : break;
589 :
590 : case 32:
591 0 : pszUnitsName = SRS_UL_ROD;
592 0 : pszUnitsConv = SRS_UL_ROD_CONV;
593 0 : break;
594 :
595 : default:
596 0 : pszUnitsName = SRS_UL_METER;
597 0 : pszUnitsConv = "1.0";
598 : break;
599 : }
600 :
601 2 : dfConv = CPLAtof(pszUnitsConv);
602 :
603 : /*-----------------------------------------------------------------
604 : * Transform them into an OGRSpatialReference.
605 : *----------------------------------------------------------------*/
606 2 : m_poSpatialRef = new OGRSpatialReference;
607 :
608 : /*-----------------------------------------------------------------
609 : * Handle the PROJCS style projections, but add the datum later.
610 : *----------------------------------------------------------------*/
611 2 : switch( sTABProj.nProjId )
612 : {
613 : /*--------------------------------------------------------------
614 : * NonEarth ... we return with an empty SpatialRef. Eventually
615 : * we might want to include the units, but not for now.
616 : *-------------------------------------------------------------*/
617 : case 0:
618 0 : m_poSpatialRef->SetLocalCS( "Nonearth" );
619 0 : break;
620 :
621 : /*--------------------------------------------------------------
622 : * lat/long .. just add the GEOGCS later.
623 : *-------------------------------------------------------------*/
624 : case 1:
625 0 : break;
626 :
627 : /*--------------------------------------------------------------
628 : * Cylindrical Equal Area
629 : *-------------------------------------------------------------*/
630 : case 2:
631 : m_poSpatialRef->SetCEA( sTABProj.adProjParams[1],
632 : sTABProj.adProjParams[0],
633 : sTABProj.adProjParams[2],
634 0 : sTABProj.adProjParams[3] );
635 0 : break;
636 :
637 : /*--------------------------------------------------------------
638 : * Lambert Conic Conformal
639 : *-------------------------------------------------------------*/
640 : case 3:
641 : m_poSpatialRef->SetLCC( sTABProj.adProjParams[2],
642 : sTABProj.adProjParams[3],
643 : sTABProj.adProjParams[1],
644 : sTABProj.adProjParams[0],
645 : sTABProj.adProjParams[4],
646 0 : sTABProj.adProjParams[5] );
647 0 : break;
648 :
649 : /*--------------------------------------------------------------
650 : * Lambert Azimuthal Equal Area
651 : *-------------------------------------------------------------*/
652 : case 4:
653 : case 29:
654 : m_poSpatialRef->SetLAEA( sTABProj.adProjParams[1],
655 : sTABProj.adProjParams[0],
656 0 : 0.0, 0.0 );
657 0 : break;
658 :
659 : /*--------------------------------------------------------------
660 : * Azimuthal Equidistant (Polar aspect only)
661 : *-------------------------------------------------------------*/
662 : case 5:
663 : case 28:
664 : m_poSpatialRef->SetAE( sTABProj.adProjParams[1],
665 : sTABProj.adProjParams[0],
666 0 : 0.0, 0.0 );
667 0 : break;
668 :
669 : /*--------------------------------------------------------------
670 : * Equidistant Conic
671 : *-------------------------------------------------------------*/
672 : case 6:
673 : m_poSpatialRef->SetEC( sTABProj.adProjParams[2],
674 : sTABProj.adProjParams[3],
675 : sTABProj.adProjParams[1],
676 : sTABProj.adProjParams[0],
677 : sTABProj.adProjParams[4],
678 0 : sTABProj.adProjParams[5] );
679 0 : break;
680 :
681 : /*--------------------------------------------------------------
682 : * Hotine Oblique Mercator
683 : *-------------------------------------------------------------*/
684 : case 7:
685 : m_poSpatialRef->SetHOM( sTABProj.adProjParams[1],
686 : sTABProj.adProjParams[0],
687 : sTABProj.adProjParams[2],
688 : 90.0,
689 : sTABProj.adProjParams[3],
690 : sTABProj.adProjParams[4],
691 0 : sTABProj.adProjParams[5] );
692 0 : break;
693 :
694 : /*--------------------------------------------------------------
695 : * Transverse Mercator
696 : *-------------------------------------------------------------*/
697 : case 8:
698 : m_poSpatialRef->SetTM( sTABProj.adProjParams[1],
699 : sTABProj.adProjParams[0],
700 : sTABProj.adProjParams[2],
701 : sTABProj.adProjParams[3],
702 2 : sTABProj.adProjParams[4] );
703 2 : break;
704 :
705 : /*----------------------------------------------------------------
706 : * Transverse Mercator,(modified for Danish System 34 Jylland-Fyn)
707 : *---------------------------------------------------------------*/
708 : case 21:
709 : m_poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_21,
710 : sTABProj.adProjParams[1],
711 : sTABProj.adProjParams[0],
712 : sTABProj.adProjParams[2],
713 : sTABProj.adProjParams[3],
714 0 : sTABProj.adProjParams[4] );
715 0 : break;
716 :
717 : /*--------------------------------------------------------------
718 : * Transverse Mercator,(modified for Danish System 34 Sjaelland)
719 : *-------------------------------------------------------------*/
720 : case 22:
721 : m_poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_22,
722 : sTABProj.adProjParams[1],
723 : sTABProj.adProjParams[0],
724 : sTABProj.adProjParams[2],
725 : sTABProj.adProjParams[3],
726 0 : sTABProj.adProjParams[4] );
727 0 : break;
728 :
729 : /*----------------------------------------------------------------
730 : * Transverse Mercator,(modified for Danish System 34/45 Bornholm)
731 : *---------------------------------------------------------------*/
732 : case 23:
733 : m_poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_23,
734 : sTABProj.adProjParams[1],
735 : sTABProj.adProjParams[0],
736 : sTABProj.adProjParams[2],
737 : sTABProj.adProjParams[3],
738 0 : sTABProj.adProjParams[4] );
739 0 : break;
740 :
741 : /*--------------------------------------------------------------
742 : * Transverse Mercator,(modified for Finnish KKJ)
743 : *-------------------------------------------------------------*/
744 : case 24:
745 : m_poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_24,
746 : sTABProj.adProjParams[1],
747 : sTABProj.adProjParams[0],
748 : sTABProj.adProjParams[2],
749 : sTABProj.adProjParams[3],
750 0 : sTABProj.adProjParams[4] );
751 0 : break;
752 :
753 : /*--------------------------------------------------------------
754 : * Albers Conic Equal Area
755 : *-------------------------------------------------------------*/
756 : case 9:
757 : m_poSpatialRef->SetACEA( sTABProj.adProjParams[2],
758 : sTABProj.adProjParams[3],
759 : sTABProj.adProjParams[1],
760 : sTABProj.adProjParams[0],
761 : sTABProj.adProjParams[4],
762 0 : sTABProj.adProjParams[5] );
763 0 : break;
764 :
765 : /*--------------------------------------------------------------
766 : * Mercator
767 : *-------------------------------------------------------------*/
768 : case 10:
769 : m_poSpatialRef->SetMercator( 0.0, sTABProj.adProjParams[0],
770 0 : 1.0, 0.0, 0.0 );
771 0 : break;
772 :
773 : /*--------------------------------------------------------------
774 : * Miller Cylindrical
775 : *-------------------------------------------------------------*/
776 : case 11:
777 : m_poSpatialRef->SetMC( 0.0, sTABProj.adProjParams[0],
778 0 : 0.0, 0.0 );
779 0 : break;
780 :
781 : /*--------------------------------------------------------------
782 : * Robinson
783 : *-------------------------------------------------------------*/
784 : case 12:
785 : m_poSpatialRef->SetRobinson( sTABProj.adProjParams[0],
786 0 : 0.0, 0.0 );
787 0 : break;
788 :
789 : /*--------------------------------------------------------------
790 : * Mollweide
791 : *-------------------------------------------------------------*/
792 : case 13:
793 : m_poSpatialRef->SetMollweide( sTABProj.adProjParams[0],
794 0 : 0.0, 0.0 );
795 0 : break;
796 :
797 : /*--------------------------------------------------------------
798 : * Eckert IV
799 : *-------------------------------------------------------------*/
800 : case 14:
801 0 : m_poSpatialRef->SetEckertIV( sTABProj.adProjParams[0], 0.0, 0.0 );
802 0 : break;
803 :
804 : /*--------------------------------------------------------------
805 : * Eckert VI
806 : *-------------------------------------------------------------*/
807 : case 15:
808 0 : m_poSpatialRef->SetEckertVI( sTABProj.adProjParams[0], 0.0, 0.0 );
809 0 : break;
810 :
811 : /*--------------------------------------------------------------
812 : * Sinusoidal
813 : *-------------------------------------------------------------*/
814 : case 16:
815 : m_poSpatialRef->SetSinusoidal( sTABProj.adProjParams[0],
816 0 : 0.0, 0.0 );
817 0 : break;
818 :
819 : /*--------------------------------------------------------------
820 : * Gall Stereographic
821 : *-------------------------------------------------------------*/
822 : case 17:
823 0 : m_poSpatialRef->SetGS( sTABProj.adProjParams[0], 0.0, 0.0 );
824 0 : break;
825 :
826 : /*--------------------------------------------------------------
827 : * New Zealand Map Grid
828 : *-------------------------------------------------------------*/
829 : case 18:
830 : m_poSpatialRef->SetNZMG( sTABProj.adProjParams[1],
831 : sTABProj.adProjParams[0],
832 : sTABProj.adProjParams[2],
833 0 : sTABProj.adProjParams[3] );
834 0 : break;
835 :
836 : /*--------------------------------------------------------------
837 : * Lambert Conic Conformal (Belgium)
838 : *-------------------------------------------------------------*/
839 : case 19:
840 : m_poSpatialRef->SetLCCB( sTABProj.adProjParams[2],
841 : sTABProj.adProjParams[3],
842 : sTABProj.adProjParams[1],
843 : sTABProj.adProjParams[0],
844 : sTABProj.adProjParams[4],
845 0 : sTABProj.adProjParams[5] );
846 0 : break;
847 :
848 : /*--------------------------------------------------------------
849 : * Stereographic
850 : *-------------------------------------------------------------*/
851 : case 20:
852 : case 31: /* this is called Double Stereographic, whats the diff? */
853 : m_poSpatialRef->SetStereographic( sTABProj.adProjParams[1],
854 : sTABProj.adProjParams[0],
855 : sTABProj.adProjParams[2],
856 : sTABProj.adProjParams[3],
857 0 : sTABProj.adProjParams[4] );
858 0 : break;
859 :
860 : /*--------------------------------------------------------------
861 : * Swiss Oblique Mercator / Cylindrical
862 : *-------------------------------------------------------------*/
863 : case 25:
864 : m_poSpatialRef->SetSOC( sTABProj.adProjParams[1],
865 : sTABProj.adProjParams[0],
866 : sTABProj.adProjParams[2],
867 0 : sTABProj.adProjParams[3] );
868 0 : break;
869 :
870 : /*--------------------------------------------------------------
871 : * Regional Mercator (regular mercator with a latitude).
872 : *-------------------------------------------------------------*/
873 : case 26:
874 : m_poSpatialRef->SetMercator( sTABProj.adProjParams[1],
875 : sTABProj.adProjParams[0],
876 0 : 1.0, 0.0, 0.0 );
877 0 : break;
878 :
879 : /*--------------------------------------------------------------
880 : * Polyconic
881 : *-------------------------------------------------------------*/
882 : case 27:
883 : m_poSpatialRef->SetPolyconic( sTABProj.adProjParams[1],
884 : sTABProj.adProjParams[0],
885 : sTABProj.adProjParams[2],
886 0 : sTABProj.adProjParams[3] );
887 0 : break;
888 :
889 : /*--------------------------------------------------------------
890 : * Cassini/Soldner
891 : *-------------------------------------------------------------*/
892 : case 30:
893 : m_poSpatialRef->SetCS( sTABProj.adProjParams[1],
894 : sTABProj.adProjParams[0],
895 : sTABProj.adProjParams[2],
896 0 : sTABProj.adProjParams[3] );
897 0 : break;
898 :
899 : /*--------------------------------------------------------------
900 : * Krovak
901 : *-------------------------------------------------------------*/
902 : case 32:
903 : m_poSpatialRef->SetKrovak( sTABProj.adProjParams[1], // dfCenterLat
904 : sTABProj.adProjParams[0], // dfCenterLong
905 : sTABProj.adProjParams[3], // dfAzimuth
906 : sTABProj.adProjParams[2], // dfPseudoStdParallelLat
907 : 1.0, // dfScale
908 : sTABProj.adProjParams[4], // dfFalseEasting
909 0 : sTABProj.adProjParams[5] ); // dfFalseNorthing
910 : break;
911 :
912 : default:
913 : break;
914 : }
915 :
916 : /*-----------------------------------------------------------------
917 : * Collect units definition.
918 : *----------------------------------------------------------------*/
919 2 : if( sTABProj.nProjId != 1 && m_poSpatialRef->GetRoot() != NULL )
920 : {
921 2 : OGR_SRSNode *poUnits = new OGR_SRSNode("UNIT");
922 :
923 2 : m_poSpatialRef->GetRoot()->AddChild(poUnits);
924 :
925 4 : poUnits->AddChild( new OGR_SRSNode( pszUnitsName ) );
926 4 : poUnits->AddChild( new OGR_SRSNode( pszUnitsConv ) );
927 : }
928 :
929 : /*-----------------------------------------------------------------
930 : * Local (nonearth) coordinate systems have no Geographic relationship
931 : * so we just return from here.
932 : *----------------------------------------------------------------*/
933 2 : if( sTABProj.nProjId == 0 )
934 0 : return m_poSpatialRef;
935 :
936 : /*-----------------------------------------------------------------
937 : * Set the datum. We are only given the X, Y and Z shift for
938 : * the datum, so for now we just synthesize a name from this.
939 : * It would be better if we could lookup a name based on the shift.
940 : *
941 : * Since we have already encountered files in which adDatumParams[] values
942 : * were in the order of 1e-150 when they should have actually been zeros,
943 : * we will use an epsilon in our scan instead of looking for equality.
944 : *----------------------------------------------------------------*/
945 : #define TAB_EQUAL(a, b) (((a)<(b) ? ((b)-(a)) : ((a)-(b))) < 1e-10)
946 : char szDatumName[160];
947 : int iDatumInfo;
948 2 : MapInfoDatumInfo *psDatumInfo = NULL;
949 :
950 35 : for( iDatumInfo = 0;
951 : asDatumInfoList[iDatumInfo].nMapInfoDatumID != -1;
952 : iDatumInfo++ )
953 : {
954 35 : psDatumInfo = asDatumInfoList + iDatumInfo;
955 :
956 35 : if( TAB_EQUAL(psDatumInfo->nEllipsoid, sTABProj.nEllipsoidId) &&
957 : ((sTABProj.nDatumId > 0 &&
958 : sTABProj.nDatumId == psDatumInfo->nMapInfoDatumID) ||
959 : (sTABProj.nDatumId <= 0
960 : && TAB_EQUAL(psDatumInfo->dfShiftX, sTABProj.dDatumShiftX)
961 : && TAB_EQUAL(psDatumInfo->dfShiftY, sTABProj.dDatumShiftY)
962 : && TAB_EQUAL(psDatumInfo->dfShiftZ, sTABProj.dDatumShiftZ)
963 0 : && TAB_EQUAL(psDatumInfo->dfDatumParm0,sTABProj.adDatumParams[0])
964 0 : && TAB_EQUAL(psDatumInfo->dfDatumParm1,sTABProj.adDatumParams[1])
965 0 : && TAB_EQUAL(psDatumInfo->dfDatumParm2,sTABProj.adDatumParams[2])
966 0 : && TAB_EQUAL(psDatumInfo->dfDatumParm3,sTABProj.adDatumParams[3])
967 0 : && TAB_EQUAL(psDatumInfo->dfDatumParm4,sTABProj.adDatumParams[4]))))
968 2 : break;
969 :
970 33 : psDatumInfo = NULL;
971 : }
972 :
973 2 : if( psDatumInfo == NULL )
974 : {
975 0 : if( sTABProj.adDatumParams[0] == 0.0
976 0 : && sTABProj.adDatumParams[1] == 0.0
977 0 : && sTABProj.adDatumParams[2] == 0.0
978 0 : && sTABProj.adDatumParams[3] == 0.0
979 0 : && sTABProj.adDatumParams[4] == 0.0 )
980 : {
981 : sprintf( szDatumName,
982 : "MIF 999,%d,%.15g,%.15g,%.15g",
983 : sTABProj.nEllipsoidId,
984 : sTABProj.dDatumShiftX,
985 : sTABProj.dDatumShiftY,
986 0 : sTABProj.dDatumShiftZ );
987 : }
988 : else
989 : {
990 : sprintf( szDatumName,
991 : "MIF 9999,%d,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",
992 : sTABProj.nEllipsoidId,
993 : sTABProj.dDatumShiftX,
994 : sTABProj.dDatumShiftY,
995 : sTABProj.dDatumShiftZ,
996 : sTABProj.adDatumParams[0],
997 : sTABProj.adDatumParams[1],
998 : sTABProj.adDatumParams[2],
999 : sTABProj.adDatumParams[3],
1000 0 : sTABProj.adDatumParams[4] );
1001 : }
1002 : }
1003 2 : else if( strlen(psDatumInfo->pszOGCDatumName) > 0 )
1004 : {
1005 : strncpy( szDatumName, psDatumInfo->pszOGCDatumName,
1006 2 : sizeof(szDatumName) );
1007 : }
1008 : else
1009 : {
1010 0 : sprintf( szDatumName, "MIF %d", psDatumInfo->nMapInfoDatumID );
1011 : }
1012 :
1013 : /*-----------------------------------------------------------------
1014 : * Set the spheroid.
1015 : *----------------------------------------------------------------*/
1016 2 : double dfSemiMajor=0.0, dfInvFlattening=0.0;
1017 2 : const char *pszSpheroidName = NULL;
1018 :
1019 85 : for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ )
1020 : {
1021 85 : if( asSpheroidInfoList[i].nMapInfoId == sTABProj.nEllipsoidId )
1022 : {
1023 2 : dfSemiMajor = asSpheroidInfoList[i].dfA;
1024 2 : dfInvFlattening = asSpheroidInfoList[i].dfInvFlattening;
1025 2 : pszSpheroidName = asSpheroidInfoList[i].pszMapinfoName;
1026 2 : break;
1027 : }
1028 : }
1029 :
1030 : // use WGS 84 if nothing is known.
1031 2 : if( pszSpheroidName == NULL )
1032 : {
1033 0 : pszSpheroidName = "unknown";
1034 0 : dfSemiMajor = 6378137.0;
1035 0 : dfInvFlattening = 298.257223563;
1036 : }
1037 :
1038 : /*-----------------------------------------------------------------
1039 : * Set the prime meridian.
1040 : *----------------------------------------------------------------*/
1041 2 : double dfPMOffset = 0.0;
1042 2 : const char *pszPMName = "Greenwich";
1043 :
1044 2 : if( sTABProj.adDatumParams[4] != 0.0 )
1045 : {
1046 0 : dfPMOffset = sTABProj.adDatumParams[4];
1047 :
1048 0 : pszPMName = "non-Greenwich";
1049 : }
1050 :
1051 : /*-----------------------------------------------------------------
1052 : * Create a GEOGCS definition.
1053 : *----------------------------------------------------------------*/
1054 :
1055 : m_poSpatialRef->SetGeogCS( "unnamed",
1056 : szDatumName,
1057 : pszSpheroidName,
1058 : dfSemiMajor, dfInvFlattening,
1059 : pszPMName, dfPMOffset,
1060 2 : SRS_UA_DEGREE, CPLAtof(SRS_UA_DEGREE_CONV));
1061 :
1062 2 : if( psDatumInfo != NULL )
1063 : {
1064 : m_poSpatialRef->SetTOWGS84( psDatumInfo->dfShiftX,
1065 : psDatumInfo->dfShiftY,
1066 : psDatumInfo->dfShiftZ,
1067 : psDatumInfo->dfDatumParm0 == 0 ? 0 : -psDatumInfo->dfDatumParm0, /* avoids 0 to be transformed into -0 */
1068 : psDatumInfo->dfDatumParm1 == 0 ? 0 : -psDatumInfo->dfDatumParm1,
1069 : psDatumInfo->dfDatumParm2 == 0 ? 0 : -psDatumInfo->dfDatumParm2,
1070 2 : psDatumInfo->dfDatumParm3 );
1071 : }
1072 :
1073 : /*-----------------------------------------------------------------
1074 : * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115)
1075 : *----------------------------------------------------------------*/
1076 2 : if( sTABProj.nProjId == 10
1077 : && sTABProj.nDatumId == 157
1078 : && sTABProj.nEllipsoidId == 54 )
1079 : {
1080 0 : m_poSpatialRef->SetNode( "PROJCS", "WGS 84 / Pseudo-Mercator" );
1081 0 : m_poSpatialRef->SetExtension( "PROJCS", "PROJ4", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs" );
1082 : }
1083 :
1084 2 : return m_poSpatialRef;
1085 : }
1086 :
1087 : /**********************************************************************
1088 : * TABFile::SetSpatialRef()
1089 : *
1090 : * Set the OGRSpatialReference for this dataset.
1091 : * A reference to the OGRSpatialReference will be kept, and it will also
1092 : * be converted into a TABProjInfo to be stored in the .MAP header.
1093 : *
1094 : * Returns 0 on success, and -1 on error.
1095 : **********************************************************************/
1096 2 : int TABFile::SetSpatialRef(OGRSpatialReference *poSpatialRef)
1097 : {
1098 2 : if (m_eAccessMode != TABWrite)
1099 : {
1100 : CPLError(CE_Failure, CPLE_NotSupported,
1101 0 : "SetSpatialRef() can be used only with Write access.");
1102 0 : return -1;
1103 : }
1104 :
1105 2 : if (m_poMAPFile == NULL )
1106 : {
1107 : CPLError(CE_Failure, CPLE_AssertionFailed,
1108 0 : "SetSpatialRef() failed: file has not been opened yet.");
1109 0 : return -1;
1110 : }
1111 :
1112 2 : if( poSpatialRef == NULL )
1113 : {
1114 : CPLError(CE_Failure, CPLE_AssertionFailed,
1115 0 : "SetSpatialRef() failed: Called with NULL poSpatialRef.");
1116 0 : return -1;
1117 : }
1118 :
1119 : /*-----------------------------------------------------------------
1120 : * Keep a copy of the OGRSpatialReference...
1121 : * Note: we have to take the reference count into account...
1122 : *----------------------------------------------------------------*/
1123 2 : if (m_poSpatialRef && m_poSpatialRef->Dereference() == 0)
1124 0 : delete m_poSpatialRef;
1125 :
1126 2 : m_poSpatialRef = poSpatialRef->Clone();
1127 :
1128 : /*-----------------------------------------------------------------
1129 : * Initialize TABProjInfo
1130 : *----------------------------------------------------------------*/
1131 : TABProjInfo sTABProj;
1132 :
1133 2 : sTABProj.nProjId = 0;
1134 2 : sTABProj.nEllipsoidId = 0; /* how will we set this? */
1135 2 : sTABProj.nUnitsId = 7;
1136 2 : sTABProj.adProjParams[0] = sTABProj.adProjParams[1] = 0.0;
1137 2 : sTABProj.adProjParams[2] = sTABProj.adProjParams[3] = 0.0;
1138 2 : sTABProj.adProjParams[4] = sTABProj.adProjParams[5] = 0.0;
1139 :
1140 2 : sTABProj.nDatumId = 0;
1141 2 : sTABProj.dDatumShiftX = 0.0;
1142 2 : sTABProj.dDatumShiftY = 0.0;
1143 2 : sTABProj.dDatumShiftZ = 0.0;
1144 2 : sTABProj.adDatumParams[0] = 0.0;
1145 2 : sTABProj.adDatumParams[1] = 0.0;
1146 2 : sTABProj.adDatumParams[2] = 0.0;
1147 2 : sTABProj.adDatumParams[3] = 0.0;
1148 2 : sTABProj.adDatumParams[4] = 0.0;
1149 :
1150 2 : sTABProj.nAffineFlag = 0;
1151 2 : sTABProj.nAffineUnits = 7;
1152 2 : sTABProj.dAffineParamA = 0.0;
1153 2 : sTABProj.dAffineParamB = 0.0;
1154 2 : sTABProj.dAffineParamC = 0.0;
1155 2 : sTABProj.dAffineParamD = 0.0;
1156 2 : sTABProj.dAffineParamE = 0.0;
1157 2 : sTABProj.dAffineParamF = 0.0;
1158 :
1159 : /*-----------------------------------------------------------------
1160 : * Get the linear units and conversion.
1161 : *----------------------------------------------------------------*/
1162 : char *pszLinearUnits;
1163 : double dfLinearConv;
1164 :
1165 2 : dfLinearConv = poSpatialRef->GetLinearUnits( &pszLinearUnits );
1166 2 : if( dfLinearConv == 0.0 )
1167 0 : dfLinearConv = 1.0;
1168 :
1169 : /*-----------------------------------------------------------------
1170 : * Transform the projection and projection parameters.
1171 : *----------------------------------------------------------------*/
1172 2 : const char *pszProjection = poSpatialRef->GetAttrValue("PROJECTION");
1173 2 : double *parms = sTABProj.adProjParams;
1174 :
1175 2 : if( pszProjection == NULL && poSpatialRef->GetAttrNode("LOCAL_CS") != NULL)
1176 : {
1177 : /* nonearth */
1178 0 : sTABProj.nProjId = 0;
1179 : }
1180 :
1181 2 : else if( pszProjection == NULL )
1182 : {
1183 0 : sTABProj.nProjId = 1;
1184 : }
1185 :
1186 2 : else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
1187 : {
1188 0 : sTABProj.nProjId = 9;
1189 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
1190 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
1191 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
1192 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
1193 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1194 0 : parms[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1195 : }
1196 :
1197 2 : else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
1198 : {
1199 0 : sTABProj.nProjId = 5;
1200 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
1201 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
1202 0 : parms[2] = 90.0;
1203 :
1204 0 : if( ABS((ABS(parms[1]) - 90)) > 0.001 )
1205 0 : sTABProj.nProjId = 28;
1206 : }
1207 :
1208 2 : else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
1209 : {
1210 0 : sTABProj.nProjId = 2;
1211 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1212 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
1213 : }
1214 :
1215 2 : else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
1216 : {
1217 0 : sTABProj.nProjId = 14;
1218 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1219 : }
1220 :
1221 2 : else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
1222 : {
1223 0 : sTABProj.nProjId = 15;
1224 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1225 : }
1226 :
1227 2 : else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
1228 : {
1229 0 : sTABProj.nProjId = 6;
1230 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
1231 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
1232 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
1233 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
1234 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1235 0 : parms[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1236 : }
1237 :
1238 2 : else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
1239 : {
1240 0 : sTABProj.nProjId = 17;
1241 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1242 : }
1243 :
1244 2 : else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
1245 : {
1246 0 : sTABProj.nProjId = 7;
1247 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
1248 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
1249 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_AZIMUTH,0.0);
1250 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1251 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1252 0 : parms[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1253 : }
1254 :
1255 2 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
1256 : {
1257 0 : sTABProj.nProjId = 4;
1258 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
1259 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
1260 0 : parms[2] = 90.0;
1261 :
1262 0 : if( ABS((ABS(parms[1]) - 90)) > 0.001 )
1263 0 : sTABProj.nProjId = 28;
1264 : }
1265 :
1266 2 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
1267 : {
1268 0 : sTABProj.nProjId = 3;
1269 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1270 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1271 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
1272 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
1273 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1274 0 : parms[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1275 : }
1276 :
1277 2 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
1278 : {
1279 0 : sTABProj.nProjId = 19;
1280 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1281 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1282 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
1283 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
1284 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1285 0 : parms[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1286 : }
1287 :
1288 2 : else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
1289 : {
1290 0 : sTABProj.nProjId = 10;
1291 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1292 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1293 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1294 :
1295 0 : if( parms[1] != 0.0 )
1296 0 : sTABProj.nProjId = 26;
1297 : }
1298 :
1299 2 : else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
1300 : {
1301 0 : sTABProj.nProjId = 11;
1302 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
1303 : }
1304 :
1305 2 : else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
1306 : {
1307 0 : sTABProj.nProjId = 13;
1308 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1309 : }
1310 :
1311 2 : else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
1312 : {
1313 0 : sTABProj.nProjId = 18;
1314 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1315 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1316 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1317 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1318 : }
1319 :
1320 2 : else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
1321 : {
1322 0 : sTABProj.nProjId = 25;
1323 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1324 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1325 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1326 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1327 : }
1328 :
1329 2 : else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
1330 : {
1331 0 : sTABProj.nProjId = 12;
1332 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1333 : }
1334 :
1335 2 : else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
1336 : {
1337 0 : sTABProj.nProjId = 16;
1338 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1339 : }
1340 :
1341 2 : else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
1342 : {
1343 0 : sTABProj.nProjId = 20;
1344 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1345 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1346 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1347 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1348 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1349 : }
1350 :
1351 2 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
1352 : {
1353 2 : sTABProj.nProjId = 8;
1354 2 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1355 2 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1356 2 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1357 2 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1358 2 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1359 : }
1360 :
1361 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) ) // Encom 2003
1362 : {
1363 0 : sTABProj.nProjId = 21;
1364 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1365 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1366 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1367 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1368 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1369 : }
1370 :
1371 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) ) // Encom 2003
1372 : {
1373 0 : sTABProj.nProjId = 22;
1374 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1375 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1376 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1377 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1378 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1379 : }
1380 :
1381 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) ) // Encom 2003
1382 : {
1383 0 : sTABProj.nProjId = 23;
1384 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1385 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1386 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1387 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1388 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1389 : }
1390 :
1391 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) ) // Encom 2003
1392 : {
1393 0 : sTABProj.nProjId = 24;
1394 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1395 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1396 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1397 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1398 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1399 : }
1400 :
1401 0 : else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
1402 : {
1403 0 : sTABProj.nProjId = 30;
1404 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1405 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1406 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1407 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1408 : }
1409 :
1410 0 : else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
1411 : {
1412 0 : sTABProj.nProjId = 18;
1413 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1414 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1415 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1416 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1417 : }
1418 :
1419 0 : else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
1420 : {
1421 0 : sTABProj.nProjId = 27;
1422 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1423 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1424 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1425 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1426 : }
1427 :
1428 0 : else if( EQUAL(pszProjection,SRS_PT_KROVAK) )
1429 : {
1430 0 : sTABProj.nProjId = 32;
1431 0 : parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1432 0 : parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1433 0 : parms[2] = poSpatialRef->GetProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1,0.0);
1434 0 : parms[3] = poSpatialRef->GetProjParm(SRS_PP_AZIMUTH,0.0);
1435 0 : parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1436 0 : parms[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1437 : }
1438 :
1439 : /* ==============================================================
1440 : * Translate Datum and Ellipsoid
1441 : * ============================================================== */
1442 2 : const char *pszWKTDatum = poSpatialRef->GetAttrValue("DATUM");
1443 2 : MapInfoDatumInfo *psDatumInfo = NULL;
1444 :
1445 2 : int nDatumEPSGCode = -1;
1446 2 : const char *pszDatumAuthority = poSpatialRef->GetAuthorityName("DATUM");
1447 2 : const char *pszDatumCode = poSpatialRef->GetAuthorityCode("DATUM");
1448 :
1449 2 : if (pszDatumCode && pszDatumAuthority && EQUAL(pszDatumAuthority, "EPSG"))
1450 : {
1451 2 : nDatumEPSGCode = atoi(pszDatumCode);
1452 : }
1453 :
1454 : /*-----------------------------------------------------------------
1455 : * Default to WGS84 if we have no datum at all.
1456 : *----------------------------------------------------------------*/
1457 2 : if( pszWKTDatum == NULL )
1458 : {
1459 0 : psDatumInfo = asDatumInfoList+0; /* WGS 84 */
1460 : }
1461 :
1462 : /*-----------------------------------------------------------------
1463 : * We know the MIF datum number, and need to look it up to
1464 : * translate into datum parameters.
1465 : *----------------------------------------------------------------*/
1466 2 : else if( EQUALN(pszWKTDatum,"MIF ",4)
1467 : && atoi(pszWKTDatum+4) != 999
1468 : && atoi(pszWKTDatum+4) != 9999 )
1469 : {
1470 : int i;
1471 :
1472 0 : for( i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
1473 : {
1474 0 : if( atoi(pszWKTDatum+4) == asDatumInfoList[i].nMapInfoDatumID )
1475 : {
1476 0 : psDatumInfo = asDatumInfoList + i;
1477 0 : break;
1478 : }
1479 : }
1480 :
1481 0 : if( psDatumInfo == NULL )
1482 0 : psDatumInfo = asDatumInfoList+0; /* WGS 84 */
1483 : }
1484 :
1485 : /*-----------------------------------------------------------------
1486 : * We have the MIF datum parameters, and apply those directly.
1487 : *----------------------------------------------------------------*/
1488 2 : else if( EQUALN(pszWKTDatum,"MIF ",4)
1489 : && (atoi(pszWKTDatum+4) == 999 || atoi(pszWKTDatum+4) == 9999) )
1490 : {
1491 : char **papszFields;
1492 :
1493 : papszFields =
1494 0 : CSLTokenizeStringComplex( pszWKTDatum+4, ",", FALSE, TRUE);
1495 :
1496 0 : if( CSLCount(papszFields) >= 5 )
1497 : {
1498 0 : sTABProj.nEllipsoidId = (GByte)atoi(papszFields[1]);
1499 0 : sTABProj.dDatumShiftX = atof(papszFields[2]);
1500 0 : sTABProj.dDatumShiftY = atof(papszFields[3]);
1501 0 : sTABProj.dDatumShiftZ = atof(papszFields[4]);
1502 : }
1503 :
1504 0 : if( CSLCount(papszFields) >= 10 )
1505 : {
1506 0 : sTABProj.adDatumParams[0] = atof(papszFields[5]);
1507 0 : sTABProj.adDatumParams[1] = atof(papszFields[6]);
1508 0 : sTABProj.adDatumParams[2] = atof(papszFields[7]);
1509 0 : sTABProj.adDatumParams[3] = atof(papszFields[8]);
1510 0 : sTABProj.adDatumParams[4] = atof(papszFields[9]);
1511 : }
1512 :
1513 0 : if( CSLCount(papszFields) < 5 )
1514 0 : psDatumInfo = asDatumInfoList+0; /* WKS84 */
1515 :
1516 0 : CSLDestroy( papszFields );
1517 : }
1518 :
1519 : /*-----------------------------------------------------------------
1520 : * We have a "real" datum name, and possibly an EPSG code for the
1521 : * datum. Try to look it up (using EPSG code first) and get the
1522 : * parameters. If we don't find it with either just use WGS84.
1523 : *----------------------------------------------------------------*/
1524 : else
1525 : {
1526 : int i;
1527 :
1528 35 : for( i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
1529 : {
1530 35 : if ( (nDatumEPSGCode > 0 && asDatumInfoList[i].nDatumEPSGCode == nDatumEPSGCode) ||
1531 : EQUAL(pszWKTDatum,asDatumInfoList[i].pszOGCDatumName) )
1532 : {
1533 2 : psDatumInfo = asDatumInfoList + i;
1534 2 : break;
1535 : }
1536 : }
1537 :
1538 2 : if( psDatumInfo == NULL )
1539 0 : psDatumInfo = asDatumInfoList+0; /* WGS 84 */
1540 : }
1541 :
1542 2 : if( psDatumInfo != NULL )
1543 : {
1544 2 : sTABProj.nEllipsoidId = (GByte)psDatumInfo->nEllipsoid;
1545 2 : sTABProj.nDatumId = (GInt16)psDatumInfo->nMapInfoDatumID;
1546 2 : sTABProj.dDatumShiftX = psDatumInfo->dfShiftX;
1547 2 : sTABProj.dDatumShiftY = psDatumInfo->dfShiftY;
1548 2 : sTABProj.dDatumShiftZ = psDatumInfo->dfShiftZ;
1549 2 : sTABProj.adDatumParams[0] = psDatumInfo->dfDatumParm0;
1550 2 : sTABProj.adDatumParams[1] = psDatumInfo->dfDatumParm1;
1551 2 : sTABProj.adDatumParams[2] = psDatumInfo->dfDatumParm2;
1552 2 : sTABProj.adDatumParams[3] = psDatumInfo->dfDatumParm3;
1553 2 : sTABProj.adDatumParams[4] = psDatumInfo->dfDatumParm4;
1554 : }
1555 :
1556 : /*-----------------------------------------------------------------
1557 : * Translate the units
1558 : *----------------------------------------------------------------*/
1559 2 : if( sTABProj.nProjId == 1 || pszLinearUnits == NULL )
1560 0 : sTABProj.nUnitsId = 13;
1561 2 : else if( dfLinearConv == 1000.0 )
1562 0 : sTABProj.nUnitsId = 1;
1563 2 : else if( dfLinearConv == 0.0254 || EQUAL(pszLinearUnits,"Inch")
1564 : || EQUAL(pszLinearUnits,"IINCH") )
1565 0 : sTABProj.nUnitsId = 2;
1566 2 : else if( dfLinearConv == CPLAtof(SRS_UL_FOOT_CONV)
1567 : || EQUAL(pszLinearUnits,SRS_UL_FOOT) )
1568 0 : sTABProj.nUnitsId = 3;
1569 2 : else if( EQUAL(pszLinearUnits,"YARD") || EQUAL(pszLinearUnits,"IYARD")
1570 : || dfLinearConv == 0.9144 )
1571 0 : sTABProj.nUnitsId = 4;
1572 2 : else if( dfLinearConv == 0.001 )
1573 0 : sTABProj.nUnitsId = 5;
1574 2 : else if( dfLinearConv == 0.01 )
1575 0 : sTABProj.nUnitsId = 6;
1576 2 : else if( dfLinearConv == 1.0 )
1577 2 : sTABProj.nUnitsId = 7;
1578 0 : else if( dfLinearConv == CPLAtof(SRS_UL_US_FOOT_CONV)
1579 : || EQUAL(pszLinearUnits,SRS_UL_US_FOOT) )
1580 0 : sTABProj.nUnitsId = 8;
1581 0 : else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
1582 0 : sTABProj.nUnitsId = 9;
1583 0 : else if( EQUAL(pszLinearUnits,SRS_UL_LINK)
1584 : || EQUAL(pszLinearUnits,"GUNTERLINK") )
1585 0 : sTABProj.nUnitsId = 30;
1586 0 : else if( EQUAL(pszLinearUnits,SRS_UL_CHAIN)
1587 : || EQUAL(pszLinearUnits,"GUNTERCHAIN") )
1588 0 : sTABProj.nUnitsId = 31;
1589 0 : else if( EQUAL(pszLinearUnits,SRS_UL_ROD) )
1590 0 : sTABProj.nUnitsId = 32;
1591 0 : else if( EQUAL(pszLinearUnits,"Mile")
1592 : || EQUAL(pszLinearUnits,"IMILE") )
1593 0 : sTABProj.nUnitsId = 0;
1594 : else
1595 0 : sTABProj.nUnitsId = 7;
1596 :
1597 : /*-----------------------------------------------------------------
1598 : * Set the new parameters in the .MAP header.
1599 : * This will also trigger lookup of default bounds for the projection.
1600 : *----------------------------------------------------------------*/
1601 2 : if ( SetProjInfo( &sTABProj ) != 0 )
1602 : {
1603 : CPLError(CE_Failure, CPLE_FileIO,
1604 0 : "SetSpatialRef() failed setting projection parameters.");
1605 0 : return -1;
1606 : }
1607 :
1608 2 : return 0;
1609 : }
1610 :
|