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