1 : /**********************************************************************
2 : * $Id: mitab_coordsys.cpp,v 1.36 2007/11/21 21:15:45 dmorissette Exp $
3 : *
4 : * Name: mitab_coordsys.cpp
5 : * Project: MapInfo TAB Read/Write library
6 : * Language: C++
7 : * Purpose: Implementation translation between MIF CoordSys format, and
8 : * and OGRSpatialRef format.
9 : * Author: Frank Warmerdam, warmerdam@pobox.com
10 : *
11 : **********************************************************************
12 : * Copyright (c) 1999-2001, Frank Warmerdam
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : **********************************************************************
32 : *
33 : * $Log: mitab_coordsys.cpp,v $
34 : * Revision 1.36 2007/11/21 21:15:45 dmorissette
35 : * Fix asDatumInfoList[] and asSpheroidInfoList[] defns/refs (bug 1826)
36 : *
37 : * Revision 1.35 2007/06/21 13:23:43 fwarmerdam
38 : * Fixed support for predefined datums with non-greenwich prime meridians
39 : *
40 : * Revision 1.34 2006/03/10 19:50:45 fwarmerdam
41 : * Coordsys false easting and northing are in the units of the coordsys, not
42 : * necessarily meters. Adjusted mitab_coordsys.cpp to reflect this.
43 : * http://bugzilla.remotesensing.org/show_bug.cgi?id=1113
44 : *
45 : * Revision 1.33 2005/09/29 20:13:57 dmorissette
46 : * MITABCoordSys2SpatialRef() patches from Anthony D (bug 1155):
47 : * Improved support for modified TM projections 21-24.
48 : * Added support for affine parameters (inside #ifdef MITAB_AFFINE_PARAMS since
49 : * affine params cannot be stored directly in OGRSpatialReference)
50 : *
51 : * Revision 1.32 2005/08/07 21:00:38 fwarmerdam
52 : * Initialize adfDatumParm[] to avoid warnings with gcc 4.
53 : *
54 : * Revision 1.31 2005/05/12 22:07:52 dmorissette
55 : * Improved handling of Danish modified TM proj#21-24 (hss, bugs 976,1010)
56 : *
57 : * Revision 1.30 2005/03/22 23:24:54 dmorissette
58 : * Added support for datum id in .MAP header (bug 910)
59 : *
60 : * Revision 1.29 2004/06/03 19:36:53 fwarmerdam
61 : * fixed memory leak processing non-earth coordsys
62 : *
63 : * Revision 1.28 2003/03/21 14:20:42 warmerda
64 : * fixed up regional mercator handling, was screwing up transverse mercator
65 : *
66 : * Revision 1.27 2003/01/09 17:33:26 warmerda
67 : * fixed ellipsoid extraction for datum 999/9999
68 : *
69 : * Revision 1.26 2002/12/12 20:12:18 warmerda
70 : * fixed signs of rotational parameters for TOWGS84 in WKT
71 : *
72 : * Revision 1.25 2002/10/15 14:33:30 warmerda
73 : * Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for
74 : * projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant -
75 : * All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect (29).
76 : *
77 : * Revision 1.24 2002/09/23 13:16:04 warmerda
78 : * fixed leak in MITABExtractCoordSysBounds()
79 : *
80 : * Revision 1.23 2002/04/01 19:49:24 warmerda
81 : * added support for cassini/soldner - proj 30
82 : *
83 : * Revision 1.22 2002/03/01 19:00:15 warmerda
84 : * False Easting/Northing should be in the linear units of measure in MapInfo,
85 : * but in OGRSpatialReference/WKT they are always in meters. Convert accordingly.
86 : *
87 : * Revision 1.21 2001/04/04 21:43:19 warmerda
88 : * added code to set WGS84 values
89 : *
90 : * Revision 1.20 2001/01/23 21:23:42 daniel
91 : * Added projection bounds lookup table, called from TABFile::SetProjInfo()
92 : *
93 : * Revision 1.19 2001/01/22 16:00:53 warmerda
94 : * reworked swiss projection support
95 : *
96 : * Revision 1.18 2001/01/19 21:56:18 warmerda
97 : * added untested support for Swiss Oblique Mercator
98 : **********************************************************************/
99 :
100 : #include "mitab.h"
101 : #include "mitab_utils.h"
102 :
103 : extern MapInfoDatumInfo asDatumInfoList[];
104 : extern MapInfoSpheroidInfo asSpheroidInfoList[];
105 :
106 : /************************************************************************/
107 : /* GetMIFParm() */
108 : /************************************************************************/
109 :
110 22 : static double GetMIFParm( char ** papszFields, int iField, double dfDefault )
111 :
112 : {
113 22 : if( iField >= CSLCount(papszFields) )
114 0 : return dfDefault;
115 : else
116 22 : return atof(papszFields[iField]);
117 : }
118 :
119 : /************************************************************************/
120 : /* MITABCoordSys2SpatialRef() */
121 : /* */
122 : /* Convert a MIF COORDSYS string into a new OGRSpatialReference */
123 : /* object. */
124 : /************************************************************************/
125 :
126 4 : OGRSpatialReference *MITABCoordSys2SpatialRef( const char * pszCoordSys )
127 :
128 : {
129 : char **papszFields;
130 : OGRSpatialReference *poSR;
131 :
132 : #ifdef MITAB_AFFINE_PARAMS // See MITAB bug 1155
133 : // Encom 2003
134 : int nAffineUnits = 7;
135 : double dAffineParams[6];
136 : #endif
137 :
138 4 : if( pszCoordSys == NULL )
139 0 : return NULL;
140 :
141 : /* -------------------------------------------------------------------- */
142 : /* Parse the passed string into words. */
143 : /* -------------------------------------------------------------------- */
144 4 : while(*pszCoordSys == ' ') pszCoordSys++; // Eat leading spaces
145 4 : if( EQUALN(pszCoordSys,"CoordSys",8) )
146 2 : pszCoordSys += 9;
147 :
148 4 : papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
149 :
150 : #ifdef MITAB_AFFINE_PARAMS // See MITAB bug 1155
151 : /* -------------------------------------------------------------------- */
152 : /* Store and then clip off Affine information. - Encom 2003 */
153 : /* -------------------------------------------------------------------- */
154 : int iAffine = CSLFindString( papszFields, "Affine" );
155 : int nAffineIndex = 0;
156 : int nAffineFlag = 0;
157 :
158 : while( iAffine != -1 && papszFields[iAffine] != NULL )
159 : {
160 : nAffineFlag = 1;
161 : if (nAffineIndex<2)
162 : {
163 : // Ignore "Affine Units"
164 : }
165 : else if (nAffineIndex==2)
166 : {
167 : // Convert units to integer (TBD)
168 : nAffineUnits = TABUnitIdFromString(papszFields[iAffine]);
169 : if (nAffineUnits==-1) nAffineUnits = 7; // metres is default
170 : }
171 : else if (nAffineIndex<=8)
172 : {
173 : // Store affine params
174 : dAffineParams[nAffineIndex-3] = atof(papszFields[iAffine]);
175 : }
176 : nAffineIndex++;
177 :
178 : CPLFree( papszFields[iAffine] );
179 : papszFields[iAffine] = NULL;
180 : iAffine++;
181 : }
182 : #endif // MITAB_AFFINE_PARAMS
183 :
184 : /* -------------------------------------------------------------------- */
185 : /* Clip off Bounds information. */
186 : /* -------------------------------------------------------------------- */
187 4 : int iBounds = CSLFindString( papszFields, "Bounds" );
188 :
189 14 : while( iBounds != -1 && papszFields[iBounds] != NULL )
190 : {
191 6 : CPLFree( papszFields[iBounds] );
192 6 : papszFields[iBounds] = NULL;
193 6 : iBounds++;
194 : }
195 :
196 : /* -------------------------------------------------------------------- */
197 : /* Create a spatialreference object to operate on. */
198 : /* -------------------------------------------------------------------- */
199 4 : poSR = new OGRSpatialReference;
200 :
201 : #ifdef MITAB_AFFINE_PARAMS // See MITAB bug 1155
202 : // Encom 2003
203 : if (nAffineFlag)
204 : {
205 : poSR->nAffineFlag = 1;
206 : poSR->nAffineUnit = nAffineUnits;
207 : poSR->dAffineParamA = dAffineParams[0];
208 : poSR->dAffineParamB = dAffineParams[1];
209 : poSR->dAffineParamC = dAffineParams[2];
210 : poSR->dAffineParamD = dAffineParams[3];
211 : poSR->dAffineParamE = dAffineParams[4];
212 : poSR->dAffineParamF = dAffineParams[5];
213 : }
214 : else
215 : {
216 : poSR->nAffineFlag = 0; // Encom 2005
217 : }
218 : #endif
219 :
220 : /* -------------------------------------------------------------------- */
221 : /* Fetch the projection. */
222 : /* -------------------------------------------------------------------- */
223 : char **papszNextField;
224 4 : int nProjection = 0;
225 :
226 8 : if( CSLCount( papszFields ) >= 3
227 : && EQUAL(papszFields[0],"Earth")
228 : && EQUAL(papszFields[1],"Projection") )
229 : {
230 4 : nProjection = atoi(papszFields[2]);
231 4 : papszNextField = papszFields + 3;
232 : }
233 0 : else if (CSLCount( papszFields ) >= 2
234 : && EQUAL(papszFields[0],"NonEarth") )
235 : {
236 : // NonEarth Units "..." Bounds (x, y) (x, y)
237 0 : nProjection = 0;
238 0 : papszNextField = papszFields + 2;
239 :
240 0 : if( papszNextField[0] != NULL && EQUAL(papszNextField[0],"Units") )
241 0 : papszNextField++;
242 : }
243 : else
244 : {
245 : // Invalid projection string ???
246 0 : if (CSLCount(papszFields) > 0)
247 : CPLError(CE_Warning, CPLE_IllegalArg,
248 0 : "Failed parsing CoordSys: '%s'", pszCoordSys);
249 0 : CSLDestroy(papszFields);
250 0 : return NULL;
251 : }
252 :
253 : /* -------------------------------------------------------------------- */
254 : /* Fetch the datum information. */
255 : /* -------------------------------------------------------------------- */
256 4 : int nDatum = 0;
257 4 : double adfDatumParm[8] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
258 4 : int nEllipsoid=0;
259 :
260 4 : if( nProjection != 0 && CSLCount(papszNextField) > 0 )
261 : {
262 4 : nDatum = atoi(papszNextField[0]);
263 4 : papszNextField++;
264 : }
265 :
266 4 : if( (nDatum == 999 || nDatum == 9999)
267 : && CSLCount(papszNextField) >= 4 )
268 : {
269 0 : nEllipsoid = atoi(papszNextField[0]);
270 0 : adfDatumParm[0] = atof(papszNextField[1]);
271 0 : adfDatumParm[1] = atof(papszNextField[2]);
272 0 : adfDatumParm[2] = atof(papszNextField[3]);
273 0 : papszNextField += 4;
274 : }
275 :
276 4 : if( nDatum == 9999
277 : && CSLCount(papszNextField) >= 5 )
278 : {
279 0 : adfDatumParm[3] = atof(papszNextField[0]);
280 0 : adfDatumParm[4] = atof(papszNextField[1]);
281 0 : adfDatumParm[5] = atof(papszNextField[2]);
282 0 : adfDatumParm[6] = atof(papszNextField[3]);
283 0 : adfDatumParm[7] = atof(papszNextField[4]);
284 0 : papszNextField += 5;
285 : }
286 :
287 : /* -------------------------------------------------------------------- */
288 : /* Fetch the units string. */
289 : /* -------------------------------------------------------------------- */
290 4 : const char *pszMIFUnits = NULL;
291 4 : const char *pszUnitsName = NULL;
292 4 : double dfUnitsConv = 1.0;
293 :
294 4 : if( CSLCount(papszNextField) > 0 )
295 : {
296 4 : pszMIFUnits = papszNextField[0];
297 4 : papszNextField++;
298 : }
299 :
300 4 : if( nProjection == 1 || pszMIFUnits == NULL )
301 : /* do nothing */;
302 4 : else if( EQUAL(pszMIFUnits,"km") )
303 : {
304 0 : pszUnitsName = "Kilometer";
305 0 : dfUnitsConv = 1000.0;
306 : }
307 4 : else if( EQUAL(pszMIFUnits, "in" ) )
308 : {
309 0 : pszUnitsName = "IINCH";
310 0 : dfUnitsConv = 0.0254;
311 : }
312 4 : else if( EQUAL(pszMIFUnits, "ft" ) )
313 : {
314 0 : pszUnitsName = SRS_UL_FOOT;
315 0 : dfUnitsConv = atof(SRS_UL_FOOT_CONV);
316 : }
317 4 : else if( EQUAL(pszMIFUnits, "yd" ) )
318 : {
319 0 : pszUnitsName = "IYARD";
320 0 : dfUnitsConv = 0.9144;
321 : }
322 4 : else if( EQUAL(pszMIFUnits, "mm" ) )
323 : {
324 0 : pszUnitsName = "Millimeter";
325 0 : dfUnitsConv = 0.001;
326 : }
327 4 : else if( EQUAL(pszMIFUnits, "cm" ) )
328 : {
329 0 : pszUnitsName = "Centimeter";
330 0 : dfUnitsConv = 0.01;
331 : }
332 4 : else if( EQUAL(pszMIFUnits, "m" ) )
333 : {
334 4 : pszUnitsName = SRS_UL_METER;
335 4 : dfUnitsConv = 1.0;
336 : }
337 0 : else if( EQUAL(pszMIFUnits, "survey foot" )
338 : || EQUAL(pszMIFUnits, "survey ft" ) )
339 : {
340 0 : pszUnitsName = SRS_UL_US_FOOT;
341 0 : dfUnitsConv = atof(SRS_UL_US_FOOT_CONV);
342 : }
343 0 : else if( EQUAL(pszMIFUnits, "nmi" ) )
344 : {
345 0 : pszUnitsName = SRS_UL_NAUTICAL_MILE;
346 0 : dfUnitsConv = atof(SRS_UL_NAUTICAL_MILE_CONV);
347 : }
348 0 : else if( EQUAL(pszMIFUnits, "li" ) )
349 : {
350 0 : pszUnitsName = SRS_UL_LINK;
351 0 : dfUnitsConv = atof(SRS_UL_LINK_CONV);
352 : }
353 0 : else if( EQUAL(pszMIFUnits, "ch" ) )
354 : {
355 0 : pszUnitsName = SRS_UL_CHAIN;
356 0 : dfUnitsConv = atof(SRS_UL_CHAIN_CONV);
357 : }
358 0 : else if( EQUAL(pszMIFUnits, "rd" ) )
359 : {
360 0 : pszUnitsName = SRS_UL_ROD;
361 0 : dfUnitsConv = atof(SRS_UL_ROD);
362 : }
363 0 : else if( EQUAL(pszMIFUnits, "mi" ) )
364 : {
365 0 : pszUnitsName = "Mile";
366 0 : dfUnitsConv = 1609.344;
367 : }
368 :
369 : /* -------------------------------------------------------------------- */
370 : /* Handle the PROJCS style projections, but add the datum */
371 : /* later. */
372 : /* */
373 : /* Note that per GDAL bug 1113 the false easting and north are */
374 : /* in local units, not necessarily meters. */
375 : /* -------------------------------------------------------------------- */
376 4 : switch( nProjection )
377 : {
378 : /*--------------------------------------------------------------
379 : * NonEarth ... we return with an empty SpatialRef. Eventually
380 : * we might want to include the units, but not for now.
381 : *
382 : * __TODO__ Changed to return NULL because returning an empty
383 : * SpatialRef caused confusion between Latlon and NonEarth since
384 : * empty SpatialRefs do have a GEOGCS set and makes them look like
385 : * Lat/Lon SpatialRefs.
386 : *
387 : * Ideally we would like to return a SpatialRef whith no GEGOCS
388 : *-------------------------------------------------------------*/
389 : case 0:
390 0 : poSR->SetLocalCS( "Nonearth" );
391 0 : break;
392 :
393 : /*--------------------------------------------------------------
394 : * lat/long .. just add the GEOGCS later.
395 : *-------------------------------------------------------------*/
396 : case 1:
397 0 : break;
398 :
399 : /*--------------------------------------------------------------
400 : * Cylindrical Equal Area
401 : *-------------------------------------------------------------*/
402 : case 2:
403 : poSR->SetCEA( GetMIFParm( papszNextField, 1, 0.0 ),
404 : GetMIFParm( papszNextField, 0, 0.0 ),
405 : GetMIFParm( papszNextField, 2, 0.0 ),
406 0 : GetMIFParm( papszNextField, 3, 0.0 ) );
407 0 : break;
408 :
409 : /*--------------------------------------------------------------
410 : * Lambert Conic Conformal
411 : *-------------------------------------------------------------*/
412 : case 3:
413 : poSR->SetLCC( GetMIFParm( papszNextField, 2, 0.0 ),
414 : GetMIFParm( papszNextField, 3, 0.0 ),
415 : GetMIFParm( papszNextField, 1, 0.0 ),
416 : GetMIFParm( papszNextField, 0, 0.0 ),
417 : GetMIFParm( papszNextField, 4, 0.0 ),
418 2 : GetMIFParm( papszNextField, 5, 0.0 ) );
419 2 : break;
420 :
421 : /*--------------------------------------------------------------
422 : * Lambert Azimuthal Equal Area
423 : *-------------------------------------------------------------*/
424 : case 4:
425 : case 29:
426 : poSR->SetLAEA( GetMIFParm( papszNextField, 1, 0.0 ),
427 : GetMIFParm( papszNextField, 0, 0.0 ),
428 0 : 0.0, 0.0 );
429 0 : break;
430 :
431 : /*--------------------------------------------------------------
432 : * Azimuthal Equidistant
433 : *-------------------------------------------------------------*/
434 : case 5: /* polar aspect only */
435 : case 28: /* all aspects */
436 : poSR->SetAE( GetMIFParm( papszNextField, 1, 0.0 ),
437 : GetMIFParm( papszNextField, 0, 0.0 ),
438 0 : 0.0, 0.0 );
439 0 : break;
440 :
441 : /*--------------------------------------------------------------
442 : * Equidistant Conic
443 : *-------------------------------------------------------------*/
444 : case 6:
445 : poSR->SetEC( GetMIFParm( papszNextField, 2, 0.0 ),
446 : GetMIFParm( papszNextField, 3, 0.0 ),
447 : GetMIFParm( papszNextField, 1, 0.0 ),
448 : GetMIFParm( papszNextField, 0, 0.0 ),
449 : GetMIFParm( papszNextField, 4, 0.0 ),
450 0 : GetMIFParm( papszNextField, 5, 0.0 ) );
451 0 : break;
452 :
453 : /*--------------------------------------------------------------
454 : * Hotine Oblique Mercator
455 : *-------------------------------------------------------------*/
456 : case 7:
457 : poSR->SetHOM( GetMIFParm( papszNextField, 1, 0.0 ),
458 : GetMIFParm( papszNextField, 0, 0.0 ),
459 : GetMIFParm( papszNextField, 2, 0.0 ),
460 : 90.0,
461 : GetMIFParm( papszNextField, 3, 1.0 ),
462 : GetMIFParm( papszNextField, 4, 0.0 ),
463 0 : GetMIFParm( papszNextField, 5, 0.0 ) );
464 0 : break;
465 :
466 : /*--------------------------------------------------------------
467 : * Transverse Mercator
468 : *-------------------------------------------------------------*/
469 : case 8:
470 : poSR->SetTM( GetMIFParm( papszNextField, 1, 0.0 ),
471 : GetMIFParm( papszNextField, 0, 0.0 ),
472 : GetMIFParm( papszNextField, 2, 1.0 ),
473 : GetMIFParm( papszNextField, 3, 0.0 ),
474 2 : GetMIFParm( papszNextField, 4, 0.0 ) );
475 2 : break;
476 :
477 : /*----------------------------------------------------------------
478 : * Transverse Mercator,(modified for Danish System 34 Jylland-Fyn)
479 : *---------------------------------------------------------------*/
480 : case 21:
481 : poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_21,
482 : GetMIFParm( papszNextField, 1, 0.0 ),
483 : GetMIFParm( papszNextField, 0, 0.0 ),
484 : GetMIFParm( papszNextField, 2, 1.0 ),
485 : GetMIFParm( papszNextField, 3, 0.0 ),
486 0 : GetMIFParm( papszNextField, 4, 0.0 ));
487 0 : break;
488 :
489 : /*--------------------------------------------------------------
490 : * Transverse Mercator,(modified for Danish System 34 Sjaelland)
491 : *-------------------------------------------------------------*/
492 : case 22:
493 : poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_22,
494 : GetMIFParm( papszNextField, 1, 0.0 ),
495 : GetMIFParm( papszNextField, 0, 0.0 ),
496 : GetMIFParm( papszNextField, 2, 1.0 ),
497 : GetMIFParm( papszNextField, 3, 0.0 ),
498 0 : GetMIFParm( papszNextField, 4, 0.0 ));
499 0 : break;
500 :
501 : /*----------------------------------------------------------------
502 : * Transverse Mercator,(modified for Danish System 34/45 Bornholm)
503 : *---------------------------------------------------------------*/
504 : case 23:
505 : poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_23,
506 : GetMIFParm( papszNextField, 1, 0.0 ),
507 : GetMIFParm( papszNextField, 0, 0.0 ),
508 : GetMIFParm( papszNextField, 2, 1.0 ),
509 : GetMIFParm( papszNextField, 3, 0.0 ),
510 0 : GetMIFParm( papszNextField, 4, 0.0 ));
511 0 : break;
512 :
513 : /*--------------------------------------------------------------
514 : * Transverse Mercator,(modified for Finnish KKJ)
515 : *-------------------------------------------------------------*/
516 : case 24:
517 : poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_24,
518 : GetMIFParm( papszNextField, 1, 0.0 ),
519 : GetMIFParm( papszNextField, 0, 0.0 ),
520 : GetMIFParm( papszNextField, 2, 1.0 ),
521 : GetMIFParm( papszNextField, 3, 0.0 ),
522 0 : GetMIFParm( papszNextField, 4, 0.0 ));
523 0 : break;
524 :
525 : /*--------------------------------------------------------------
526 : * Albers Conic Equal Area
527 : *-------------------------------------------------------------*/
528 : case 9:
529 : poSR->SetACEA( GetMIFParm( papszNextField, 2, 0.0 ),
530 : GetMIFParm( papszNextField, 3, 0.0 ),
531 : GetMIFParm( papszNextField, 1, 0.0 ),
532 : GetMIFParm( papszNextField, 0, 0.0 ),
533 : GetMIFParm( papszNextField, 4, 0.0 ),
534 0 : GetMIFParm( papszNextField, 5, 0.0 ) );
535 0 : break;
536 :
537 : /*--------------------------------------------------------------
538 : * Mercator
539 : *-------------------------------------------------------------*/
540 : case 10:
541 : poSR->SetMercator( 0.0, GetMIFParm( papszNextField, 0, 0.0 ),
542 0 : 1.0, 0.0, 0.0 );
543 0 : break;
544 :
545 : /*--------------------------------------------------------------
546 : * Miller Cylindrical
547 : *-------------------------------------------------------------*/
548 : case 11:
549 : poSR->SetMC( 0.0, GetMIFParm( papszNextField, 0, 0.0 ),
550 0 : 0.0, 0.0 );
551 0 : break;
552 :
553 : /*--------------------------------------------------------------
554 : * Robinson
555 : *-------------------------------------------------------------*/
556 : case 12:
557 : poSR->SetRobinson( GetMIFParm( papszNextField, 0, 0.0 ),
558 0 : 0.0, 0.0 );
559 0 : break;
560 :
561 : /*--------------------------------------------------------------
562 : * Mollweide
563 : *-------------------------------------------------------------*/
564 : case 13:
565 : poSR->SetMollweide( GetMIFParm( papszNextField, 0, 0.0 ),
566 0 : 0.0, 0.0 );
567 :
568 : /*--------------------------------------------------------------
569 : * Eckert IV
570 : *-------------------------------------------------------------*/
571 : case 14:
572 : poSR->SetEckertIV( GetMIFParm( papszNextField, 0, 0.0 ),
573 0 : 0.0, 0.0 );
574 0 : break;
575 :
576 : /*--------------------------------------------------------------
577 : * Eckert VI
578 : *-------------------------------------------------------------*/
579 : case 15:
580 : poSR->SetEckertVI( GetMIFParm( papszNextField, 0, 0.0 ),
581 0 : 0.0, 0.0 );
582 0 : break;
583 :
584 : /*--------------------------------------------------------------
585 : * Sinusoidal
586 : *-------------------------------------------------------------*/
587 : case 16:
588 : poSR->SetSinusoidal( GetMIFParm( papszNextField, 0, 0.0 ),
589 0 : 0.0, 0.0 );
590 0 : break;
591 :
592 : /*--------------------------------------------------------------
593 : * Gall
594 : *-------------------------------------------------------------*/
595 : case 17:
596 : poSR->SetGS( GetMIFParm( papszNextField, 0, 0.0 ),
597 0 : 0.0, 0.0 );
598 0 : break;
599 :
600 : /*--------------------------------------------------------------
601 : * New Zealand Map Grid
602 : *-------------------------------------------------------------*/
603 : case 18:
604 : poSR->SetNZMG( GetMIFParm( papszNextField, 1, 0.0 ),
605 : GetMIFParm( papszNextField, 0, 0.0 ),
606 : GetMIFParm( papszNextField, 2, 0.0 ),
607 0 : GetMIFParm( papszNextField, 3, 0.0 ) );
608 0 : break;
609 :
610 : /*--------------------------------------------------------------
611 : * Lambert Conic Conformal (Belgium)
612 : *-------------------------------------------------------------*/
613 : case 19:
614 : poSR->SetLCCB( GetMIFParm( papszNextField, 2, 0.0 ),
615 : GetMIFParm( papszNextField, 3, 0.0 ),
616 : GetMIFParm( papszNextField, 1, 0.0 ),
617 : GetMIFParm( papszNextField, 0, 0.0 ),
618 : GetMIFParm( papszNextField, 4, 0.0 ),
619 0 : GetMIFParm( papszNextField, 5, 0.0 ) );
620 0 : break;
621 :
622 : /*--------------------------------------------------------------
623 : * Stereographic
624 : *-------------------------------------------------------------*/
625 : case 20:
626 : case 31: /* double stereographic */
627 : poSR->SetStereographic(
628 : GetMIFParm( papszNextField, 1, 0.0 ),
629 : GetMIFParm( papszNextField, 0, 0.0 ),
630 : GetMIFParm( papszNextField, 2, 1.0 ),
631 : GetMIFParm( papszNextField, 3, 0.0 ),
632 0 : GetMIFParm( papszNextField, 4, 0.0 ) );
633 0 : break;
634 :
635 : /*--------------------------------------------------------------
636 : * Swiss Oblique Mercator / Cylindrical
637 : *-------------------------------------------------------------*/
638 : case 25:
639 : poSR->SetSOC( GetMIFParm( papszNextField, 1, 0.0 ),
640 : GetMIFParm( papszNextField, 0, 0.0 ),
641 : GetMIFParm( papszNextField, 2, 0.0 ),
642 0 : GetMIFParm( papszNextField, 3, 0.0 ) );
643 0 : break;
644 :
645 : /*--------------------------------------------------------------
646 : * Regional Mercator
647 : *-------------------------------------------------------------*/
648 : case 26:
649 : poSR->SetMercator( GetMIFParm( papszNextField, 1, 0.0 ),
650 : GetMIFParm( papszNextField, 0, 0.0 ),
651 0 : 1.0, 0.0, 0.0 );
652 0 : break;
653 :
654 : /*--------------------------------------------------------------
655 : * Polygonic
656 : *-------------------------------------------------------------*/
657 : case 27:
658 : poSR->SetPolyconic( GetMIFParm( papszNextField, 1, 0.0 ),
659 : GetMIFParm( papszNextField, 0, 0.0 ),
660 : GetMIFParm( papszNextField, 2, 0.0 ),
661 0 : GetMIFParm( papszNextField, 3, 0.0 ) );
662 0 : break;
663 :
664 : /*--------------------------------------------------------------
665 : * CassiniSoldner
666 : *-------------------------------------------------------------*/
667 : case 30:
668 : poSR->SetCS(
669 : GetMIFParm( papszNextField, 1, 0.0 ),
670 : GetMIFParm( papszNextField, 0, 0.0 ),
671 : GetMIFParm( papszNextField, 2, 0.0 ),
672 0 : GetMIFParm( papszNextField, 3, 0.0 ) );
673 : break;
674 :
675 : default:
676 : break;
677 : }
678 :
679 : /* -------------------------------------------------------------------- */
680 : /* Set linear units. */
681 : /* -------------------------------------------------------------------- */
682 4 : if( pszUnitsName != NULL )
683 4 : poSR->SetLinearUnits( pszUnitsName, dfUnitsConv );
684 :
685 : /* -------------------------------------------------------------------- */
686 : /* For Non-Earth projection, we're done at this point. */
687 : /* -------------------------------------------------------------------- */
688 4 : if (nProjection == 0)
689 : {
690 0 : CSLDestroy(papszFields);
691 0 : return poSR;
692 : }
693 :
694 : /* ==================================================================== */
695 : /* Establish the GeogCS */
696 : /* ==================================================================== */
697 4 : const char *pszGeogName = "unnamed";
698 4 : const char *pszSpheroidName = "GRS_1980";
699 4 : double dfSemiMajor = 6378137.0;
700 4 : double dfInvFlattening = 298.257222101;
701 4 : const char *pszPrimeM = "Greenwich";
702 4 : double dfPMLongToGreenwich = 0.0;
703 :
704 : /* -------------------------------------------------------------------- */
705 : /* Find the datum, and collect it's parameters if possible. */
706 : /* -------------------------------------------------------------------- */
707 : int iDatum;
708 4 : MapInfoDatumInfo *psDatumInfo = NULL;
709 :
710 392 : for( iDatum = 0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++ )
711 : {
712 392 : if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
713 : {
714 4 : psDatumInfo = asDatumInfoList + iDatum;
715 4 : break;
716 : }
717 : }
718 :
719 4 : if( asDatumInfoList[iDatum].nMapInfoDatumID == -1
720 : && nDatum != 999 && nDatum != 9999 )
721 : {
722 : /* use WGS84 */
723 0 : psDatumInfo = asDatumInfoList + 0;
724 : }
725 :
726 4 : if( psDatumInfo != NULL )
727 : {
728 4 : nEllipsoid = psDatumInfo->nEllipsoid;
729 4 : adfDatumParm[0] = psDatumInfo->dfShiftX;
730 4 : adfDatumParm[1] = psDatumInfo->dfShiftY;
731 4 : adfDatumParm[2] = psDatumInfo->dfShiftZ;
732 4 : adfDatumParm[3] = psDatumInfo->dfDatumParm0;
733 4 : adfDatumParm[4] = psDatumInfo->dfDatumParm1;
734 4 : adfDatumParm[5] = psDatumInfo->dfDatumParm2;
735 4 : adfDatumParm[6] = psDatumInfo->dfDatumParm3;
736 4 : adfDatumParm[7] = psDatumInfo->dfDatumParm4;
737 : }
738 :
739 : /* -------------------------------------------------------------------- */
740 : /* Set the spheroid if it is known from the table. */
741 : /* -------------------------------------------------------------------- */
742 24 : for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ )
743 : {
744 24 : if( asSpheroidInfoList[i].nMapInfoId == nEllipsoid )
745 : {
746 4 : dfSemiMajor = asSpheroidInfoList[i].dfA;
747 4 : dfInvFlattening = asSpheroidInfoList[i].dfInvFlattening;
748 4 : pszSpheroidName = asSpheroidInfoList[i].pszMapinfoName;
749 4 : break;
750 : }
751 : }
752 :
753 : /* -------------------------------------------------------------------- */
754 : /* apply datum parameters. */
755 : /* -------------------------------------------------------------------- */
756 : char szDatumName[128];
757 :
758 4 : if( nDatum == 999 )
759 : {
760 : sprintf( szDatumName,
761 : "MIF 9999,%d,%.15g,%.15g,%.15g",
762 : nEllipsoid,
763 : adfDatumParm[0],
764 : adfDatumParm[1],
765 0 : adfDatumParm[2] );
766 : }
767 4 : else if( nDatum == 9999 )
768 : {
769 : sprintf( szDatumName,
770 : "MIF 9999,%d,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",
771 : nEllipsoid,
772 : adfDatumParm[0],
773 : adfDatumParm[1],
774 : adfDatumParm[2],
775 : adfDatumParm[3],
776 : adfDatumParm[4],
777 : adfDatumParm[5],
778 : adfDatumParm[6],
779 0 : adfDatumParm[7] );
780 : }
781 8 : else if( psDatumInfo->pszOGCDatumName != NULL
782 : && strlen(psDatumInfo->pszOGCDatumName) > 0 )
783 : {
784 : strncpy( szDatumName, psDatumInfo->pszOGCDatumName,
785 4 : sizeof(szDatumName) );
786 : }
787 : else
788 : {
789 0 : sprintf( szDatumName, "MIF %d", nDatum );
790 : }
791 :
792 : /* -------------------------------------------------------------------- */
793 : /* Set prime meridian for 9999 datums. */
794 : /* -------------------------------------------------------------------- */
795 4 : if( nDatum == 9999 || adfDatumParm[7] != 0.0 )
796 : {
797 1 : pszPrimeM = "non-Greenwich";
798 1 : dfPMLongToGreenwich = adfDatumParm[7];
799 : }
800 :
801 : /* -------------------------------------------------------------------- */
802 : /* Set the GeogCS. */
803 : /* -------------------------------------------------------------------- */
804 : poSR->SetGeogCS( pszGeogName, szDatumName, pszSpheroidName,
805 : dfSemiMajor, dfInvFlattening,
806 : pszPrimeM, dfPMLongToGreenwich,
807 : SRS_UA_DEGREE,
808 4 : atof(SRS_UA_DEGREE_CONV) );
809 :
810 : poSR->SetTOWGS84( adfDatumParm[0], adfDatumParm[1], adfDatumParm[2],
811 : -adfDatumParm[3], -adfDatumParm[4], -adfDatumParm[5],
812 4 : adfDatumParm[6] );
813 :
814 : /* -------------------------------------------------------------------- */
815 : /* Report on translation. */
816 : /* -------------------------------------------------------------------- */
817 : char *pszWKT;
818 :
819 4 : poSR->exportToWkt( &pszWKT );
820 4 : if( pszWKT != NULL )
821 : {
822 : CPLDebug( "MITAB",
823 : "This CoordSys value:\n%s\nwas translated to:\n%s\n",
824 4 : pszCoordSys, pszWKT );
825 4 : CPLFree( pszWKT );
826 : }
827 :
828 4 : CSLDestroy(papszFields);
829 :
830 4 : return poSR;
831 : }
832 :
833 : /************************************************************************/
834 : /* MITABSpatialRef2CoordSys() */
835 : /* */
836 : /* Converts a OGRSpatialReference object into a MIF COORDSYS */
837 : /* string. */
838 : /* */
839 : /* The function returns a newly allocated string that should be */
840 : /* CPLFree()'d by the caller. */
841 : /************************************************************************/
842 :
843 1 : char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
844 :
845 : {
846 1 : if( poSR == NULL )
847 0 : return NULL;
848 :
849 : /*-----------------------------------------------------------------
850 : * Get the linear units.
851 : *----------------------------------------------------------------*/
852 : double dfLinearConv;
853 : char *pszLinearUnits;
854 :
855 1 : dfLinearConv = poSR->GetLinearUnits( &pszLinearUnits );
856 :
857 : /*-----------------------------------------------------------------
858 : * Transform the projection and projection parameters.
859 : *----------------------------------------------------------------*/
860 1 : const char *pszProjection = poSR->GetAttrValue("PROJECTION");
861 : double parms[10];
862 1 : int nProjection = 0;
863 1 : int nParmCount = 0;
864 :
865 1 : if( pszProjection == NULL )
866 : {
867 : /*--------------------------------------------------------------
868 : * NULL projection.
869 : * We have 2 possibilities: CoordSys NonEarth or Lat/Lon
870 : * NonEarth ... is an empty SpatialRef.
871 : * Lat/Lon has no "PROJECTION" but GEOGCS is set
872 : *-------------------------------------------------------------*/
873 0 : if ( poSR->GetAttrValue("GEOGCS") == NULL)
874 0 : nProjection = 0; // Non-Earth
875 : else
876 0 : nProjection = 1; // Lat/Lon
877 : }
878 1 : else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
879 : {
880 0 : nProjection = 9;
881 0 : parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
882 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
883 0 : parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
884 0 : parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
885 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
886 0 : parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
887 0 : nParmCount = 6;
888 : }
889 :
890 1 : else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
891 : {
892 0 : nProjection = 5;
893 0 : parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
894 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
895 0 : parms[2] = 90.0;
896 0 : nParmCount = 3;
897 :
898 0 : if( ABS((ABS(parms[1]) - 90)) > 0.001 )
899 0 : nProjection = 28;
900 : }
901 :
902 1 : else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
903 : {
904 0 : nProjection = 2;
905 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
906 0 : parms[1] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
907 0 : nParmCount = 2;
908 : }
909 :
910 1 : else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
911 : {
912 0 : nProjection = 14;
913 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
914 0 : nParmCount = 1;
915 : }
916 :
917 1 : else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
918 : {
919 0 : nProjection = 15;
920 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
921 0 : nParmCount = 1;
922 : }
923 :
924 1 : else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
925 : {
926 0 : nProjection = 6;
927 0 : parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
928 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
929 0 : parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
930 0 : parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
931 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
932 0 : parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
933 0 : nParmCount = 6;
934 : }
935 :
936 1 : else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
937 : {
938 0 : nProjection = 17;
939 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
940 0 : nParmCount = 1;
941 : }
942 :
943 1 : else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
944 : {
945 0 : nProjection = 7;
946 0 : parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
947 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
948 0 : parms[2] = poSR->GetProjParm(SRS_PP_AZIMUTH,0.0);
949 0 : parms[3] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
950 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
951 0 : parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
952 0 : nParmCount = 6;
953 : }
954 :
955 1 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
956 : {
957 0 : nProjection = 4;
958 0 : parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
959 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
960 0 : parms[2] = 90.0;
961 0 : nParmCount = 3;
962 :
963 0 : if( ABS((ABS(parms[1]) - 90)) > 0.001 )
964 0 : nProjection = 28;
965 : }
966 :
967 1 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
968 : {
969 1 : nProjection = 3;
970 1 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
971 1 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
972 1 : parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
973 1 : parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
974 1 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
975 1 : parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
976 1 : nParmCount = 6;
977 : }
978 :
979 0 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
980 : {
981 0 : nProjection = 19;
982 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
983 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
984 0 : parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
985 0 : parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
986 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
987 0 : parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
988 0 : nParmCount = 6;
989 : }
990 :
991 0 : else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
992 : {
993 0 : nProjection = 10;
994 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
995 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
996 0 : nParmCount = 1;
997 :
998 0 : if( parms[1] != 0.0 )
999 : {
1000 0 : nProjection = 26;
1001 0 : nParmCount = 2;
1002 : }
1003 : }
1004 :
1005 0 : else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
1006 : {
1007 0 : nProjection = 11;
1008 0 : parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
1009 0 : nParmCount = 1;
1010 : }
1011 :
1012 0 : else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
1013 : {
1014 0 : nProjection = 13;
1015 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1016 0 : nParmCount = 1;
1017 : }
1018 :
1019 0 : else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
1020 : {
1021 0 : nProjection = 25;
1022 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1023 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1024 0 : parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1025 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1026 0 : nParmCount = 4;
1027 : }
1028 :
1029 0 : else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
1030 : {
1031 0 : nProjection = 12;
1032 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1033 0 : nParmCount = 1;
1034 : }
1035 :
1036 0 : else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
1037 : {
1038 0 : nProjection = 16;
1039 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1040 0 : nParmCount = 1;
1041 : }
1042 :
1043 0 : else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
1044 : {
1045 0 : nProjection = 20;
1046 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1047 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1048 0 : parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1049 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1050 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1051 0 : nParmCount = 5;
1052 : }
1053 :
1054 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
1055 : {
1056 0 : nProjection = 8;
1057 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1058 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1059 0 : parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1060 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1061 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1062 0 : nParmCount = 5;
1063 : }
1064 :
1065 : // Transverse Mercator,(modified for Danish System 34 Jylland-Fyn)
1066 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) )
1067 : {
1068 0 : nProjection = 21;
1069 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1070 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1071 0 : parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1072 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1073 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1074 0 : nParmCount = 5;
1075 : }
1076 :
1077 : // Transverse Mercator,(modified for Danish System 34 Sjaelland)
1078 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) )
1079 : {
1080 0 : nProjection = 22;
1081 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1082 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1083 0 : parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1084 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1085 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1086 0 : nParmCount = 5;
1087 : }
1088 :
1089 : // Transverse Mercator,(modified for Danish System 34/45 Bornholm)
1090 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) )
1091 : {
1092 0 : nProjection = 23;
1093 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1094 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1095 0 : parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1096 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1097 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1098 0 : nParmCount = 5;
1099 : }
1100 :
1101 : // Transverse Mercator,(modified for Finnish KKJ)
1102 0 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) )
1103 : {
1104 0 : nProjection = 24;
1105 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1106 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1107 0 : parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
1108 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1109 0 : parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1110 0 : nParmCount = 5;
1111 : }
1112 :
1113 0 : else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
1114 : {
1115 0 : nProjection = 30;
1116 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1117 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1118 0 : parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1119 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1120 0 : nParmCount = 4;
1121 : }
1122 :
1123 0 : else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
1124 : {
1125 0 : nProjection = 18;
1126 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1127 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1128 0 : parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1129 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1130 0 : nParmCount = 4;
1131 : }
1132 :
1133 0 : else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
1134 : {
1135 0 : nProjection = 27;
1136 0 : parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
1137 0 : parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
1138 0 : parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
1139 0 : parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
1140 0 : nParmCount = 4;
1141 : }
1142 :
1143 : /* ==============================================================
1144 : * Translate Datum and Ellipsoid
1145 : * ============================================================== */
1146 1 : int nDatum = 0;
1147 1 : double adfDatumParm[8] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
1148 1 : int nEllipsoid=0;
1149 :
1150 1 : const char *pszWKTDatum = poSR->GetAttrValue("DATUM");
1151 :
1152 1 : if( pszWKTDatum == NULL )
1153 : {
1154 0 : nDatum = 0;
1155 0 : if( nProjection == 1 )
1156 0 : nProjection = 0;
1157 : }
1158 :
1159 : /*-----------------------------------------------------------------
1160 : * We know the MIF datum number, and need to look it up to
1161 : * translate into datum parameters.
1162 : *----------------------------------------------------------------*/
1163 1 : else if( EQUALN(pszWKTDatum,"MIF ",4)
1164 : && atoi(pszWKTDatum+4) != 999
1165 : && atoi(pszWKTDatum+4) != 9999 )
1166 : {
1167 0 : nDatum = atoi(pszWKTDatum+4);
1168 : }
1169 :
1170 : /*-----------------------------------------------------------------
1171 : * We have the MIF datum parameters, and apply those directly.
1172 : *----------------------------------------------------------------*/
1173 1 : else if( EQUALN(pszWKTDatum,"MIF ",4)
1174 : && (atoi(pszWKTDatum+4) == 999 || atoi(pszWKTDatum+4) == 9999) )
1175 : {
1176 : char **papszFields;
1177 :
1178 0 : nDatum = atoi(pszWKTDatum+4);
1179 :
1180 : papszFields =
1181 0 : CSLTokenizeStringComplex( pszWKTDatum+4, ",", FALSE, TRUE);
1182 :
1183 0 : if( CSLCount(papszFields) >= 5 )
1184 : {
1185 0 : nEllipsoid = atoi(papszFields[1]);
1186 0 : adfDatumParm[0] = atof(papszFields[2]);
1187 0 : adfDatumParm[1] = atof(papszFields[3]);
1188 0 : adfDatumParm[2] = atof(papszFields[4]);
1189 : }
1190 :
1191 0 : if( CSLCount(papszFields) >= 10 )
1192 : {
1193 0 : adfDatumParm[3] = atof(papszFields[5]);
1194 0 : adfDatumParm[4] = atof(papszFields[6]);
1195 0 : adfDatumParm[5] = atof(papszFields[7]);
1196 0 : adfDatumParm[6] = atof(papszFields[8]);
1197 0 : adfDatumParm[7] = atof(papszFields[9]);
1198 : }
1199 :
1200 0 : if( CSLCount(papszFields) < 5 )
1201 0 : nDatum = 104; /* WGS84 */
1202 :
1203 0 : CSLDestroy( papszFields );
1204 : }
1205 :
1206 : /*-----------------------------------------------------------------
1207 : * We have a "real" datum name. Try to look it up and get the
1208 : * parameters. If we don't find it just use WGS84.
1209 : *----------------------------------------------------------------*/
1210 : else
1211 : {
1212 : int i;
1213 :
1214 67 : for( i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
1215 : {
1216 67 : if( EQUAL(pszWKTDatum,asDatumInfoList[i].pszOGCDatumName) )
1217 : {
1218 1 : nDatum = asDatumInfoList[i].nMapInfoDatumID;
1219 1 : break;
1220 : }
1221 : }
1222 :
1223 1 : if( nDatum == 0 )
1224 0 : nDatum = 104; /* WGS84 */
1225 : }
1226 :
1227 : /*-----------------------------------------------------------------
1228 : * Translate the units
1229 : *----------------------------------------------------------------*/
1230 1 : const char *pszMIFUnits = "m";
1231 :
1232 1 : if( nProjection == 1 )
1233 0 : pszMIFUnits = NULL;
1234 1 : else if( pszLinearUnits == NULL )
1235 0 : pszMIFUnits = "m";
1236 1 : else if( dfLinearConv == 1000.0 )
1237 0 : pszMIFUnits = "km";
1238 1 : else if( dfLinearConv == 0.0254 || EQUAL(pszLinearUnits,"Inch")
1239 : || EQUAL(pszLinearUnits,"IINCH"))
1240 0 : pszMIFUnits = "in";
1241 1 : else if( dfLinearConv == atof(SRS_UL_FOOT_CONV)
1242 : || EQUAL(pszLinearUnits,SRS_UL_FOOT) )
1243 0 : pszMIFUnits = "ft";
1244 1 : else if( EQUAL(pszLinearUnits,"YARD") || EQUAL(pszLinearUnits,"IYARD")
1245 : || dfLinearConv == 0.9144 )
1246 0 : pszMIFUnits = "yd";
1247 1 : else if( dfLinearConv == 0.001 )
1248 0 : pszMIFUnits = "mm";
1249 1 : else if( dfLinearConv == 0.01 )
1250 0 : pszMIFUnits = "cm";
1251 1 : else if( dfLinearConv == 1.0 )
1252 1 : pszMIFUnits = "m";
1253 0 : else if( dfLinearConv == atof(SRS_UL_US_FOOT_CONV)
1254 : || EQUAL(pszLinearUnits,SRS_UL_US_FOOT) )
1255 0 : pszMIFUnits = "survey ft";
1256 0 : else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
1257 0 : pszMIFUnits = "nmi";
1258 0 : else if( EQUAL(pszLinearUnits,SRS_UL_LINK)
1259 : || EQUAL(pszLinearUnits,"GUNTERLINK") )
1260 0 : pszMIFUnits = "li";
1261 0 : else if( EQUAL(pszLinearUnits,SRS_UL_CHAIN)
1262 : || EQUAL(pszLinearUnits,"GUNTERCHAIN") )
1263 0 : pszMIFUnits = "ch";
1264 0 : else if( EQUAL(pszLinearUnits,SRS_UL_ROD) )
1265 0 : pszMIFUnits = "rd";
1266 0 : else if( EQUAL(pszLinearUnits,"Mile")
1267 : || EQUAL(pszLinearUnits,"IMILE") )
1268 0 : pszMIFUnits = "mi";
1269 :
1270 : /* -------------------------------------------------------------------- */
1271 : /* Build coordinate system definition. */
1272 : /* -------------------------------------------------------------------- */
1273 : char szCoordSys[256];
1274 :
1275 1 : if( nProjection != 0 )
1276 : {
1277 : sprintf( szCoordSys,
1278 : "Earth Projection %d",
1279 1 : nProjection );
1280 :
1281 : }
1282 : else
1283 : sprintf( szCoordSys,
1284 0 : "NonEarth Units" );
1285 :
1286 : /* -------------------------------------------------------------------- */
1287 : /* Append Datum */
1288 : /* -------------------------------------------------------------------- */
1289 1 : if( nProjection != 0 )
1290 : {
1291 : sprintf( szCoordSys + strlen(szCoordSys),
1292 : ", %d",
1293 1 : nDatum );
1294 :
1295 1 : if( nDatum == 999 || nDatum == 9999 )
1296 : {
1297 : sprintf( szCoordSys + strlen(szCoordSys),
1298 : ", %d, %.15g, %.15g, %.15g",
1299 : nEllipsoid,
1300 0 : adfDatumParm[0], adfDatumParm[1], adfDatumParm[2] );
1301 : }
1302 :
1303 1 : if( nDatum == 9999 )
1304 : {
1305 : sprintf( szCoordSys + strlen(szCoordSys),
1306 : ", %.15g, %.15g, %.15g, %.15g, %.15g",
1307 : adfDatumParm[3], adfDatumParm[4], adfDatumParm[5],
1308 0 : adfDatumParm[6], adfDatumParm[7] );
1309 : }
1310 : }
1311 :
1312 : /* -------------------------------------------------------------------- */
1313 : /* Append units. */
1314 : /* -------------------------------------------------------------------- */
1315 1 : if( nProjection != 1 && pszMIFUnits != NULL )
1316 : {
1317 1 : if( nProjection != 0 )
1318 1 : strcat( szCoordSys, "," );
1319 :
1320 : sprintf( szCoordSys + strlen(szCoordSys),
1321 : " \"%s\"",
1322 1 : pszMIFUnits );
1323 : }
1324 :
1325 : /* -------------------------------------------------------------------- */
1326 : /* Append Projection Parms. */
1327 : /* -------------------------------------------------------------------- */
1328 7 : for( int iParm = 0; iParm < nParmCount; iParm++ )
1329 : sprintf( szCoordSys + strlen(szCoordSys),
1330 : ", %.15g",
1331 6 : parms[iParm] );
1332 :
1333 : /* -------------------------------------------------------------------- */
1334 : /* Report on translation */
1335 : /* -------------------------------------------------------------------- */
1336 1 : char *pszWKT = NULL;
1337 :
1338 1 : poSR->exportToWkt( &pszWKT );
1339 1 : if( pszWKT != NULL )
1340 : {
1341 : CPLDebug( "MITAB",
1342 : "This WKT Projection:\n%s\n\ntranslates to:\n%s\n",
1343 1 : pszWKT, szCoordSys );
1344 1 : CPLFree( pszWKT );
1345 : }
1346 :
1347 1 : return( CPLStrdup( szCoordSys ) );
1348 : }
1349 :
1350 :
1351 : /************************************************************************/
1352 : /* MITABExtractCoordSysBounds */
1353 : /* */
1354 : /* Return TRUE if MIF coordsys string contains a BOUNDS parameter and */
1355 : /* Set x/y min/max values. */
1356 : /************************************************************************/
1357 :
1358 : GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
1359 : double &dXMin, double &dYMin,
1360 0 : double &dXMax, double &dYMax )
1361 :
1362 : {
1363 : char **papszFields;
1364 :
1365 0 : if( pszCoordSys == NULL )
1366 0 : return FALSE;
1367 :
1368 0 : papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,()", TRUE, FALSE );
1369 :
1370 0 : int iBounds = CSLFindString( papszFields, "Bounds" );
1371 :
1372 0 : if (iBounds >= 0 && iBounds + 4 < CSLCount(papszFields))
1373 : {
1374 0 : dXMin = atof(papszFields[++iBounds]);
1375 0 : dYMin = atof(papszFields[++iBounds]);
1376 0 : dXMax = atof(papszFields[++iBounds]);
1377 0 : dYMax = atof(papszFields[++iBounds]);
1378 0 : CSLDestroy( papszFields );
1379 0 : return TRUE;
1380 : }
1381 :
1382 0 : CSLDestroy( papszFields );
1383 0 : return FALSE;
1384 : }
1385 :
1386 :
1387 : /**********************************************************************
1388 : * MITABCoordSys2TABProjInfo()
1389 : *
1390 : * Convert a MIF COORDSYS string into a TABProjInfo structure.
1391 : *
1392 : * Note that it would have been possible to achieve the same by calling
1393 : * TABFile::SetSpatialRef( MITABCoordSys2SpatialRef() ) but this would
1394 : * involve lots of manipulations for cases where only a simple conversion
1395 : * is required.
1396 : *
1397 : * Returns 0 on success, -1 on error.
1398 : **********************************************************************/
1399 0 : int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
1400 :
1401 : {
1402 : char **papszFields;
1403 :
1404 : // Set all fields to zero, equivalent of NonEarth Units "mi"
1405 0 : memset(psProj, 0, sizeof(TABProjInfo));
1406 :
1407 0 : if( pszCoordSys == NULL )
1408 0 : return -1;
1409 :
1410 : /*-----------------------------------------------------------------
1411 : * Parse the passed string into words.
1412 : *----------------------------------------------------------------*/
1413 0 : while(*pszCoordSys == ' ') pszCoordSys++; // Eat leading spaces
1414 0 : if( EQUALN(pszCoordSys,"CoordSys",8) )
1415 0 : pszCoordSys += 9;
1416 :
1417 0 : papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
1418 :
1419 : /*-----------------------------------------------------------------
1420 : * Clip off Bounds information.
1421 : *----------------------------------------------------------------*/
1422 0 : int iBounds = CSLFindString( papszFields, "Bounds" );
1423 :
1424 0 : while( iBounds != -1 && papszFields[iBounds] != NULL )
1425 : {
1426 0 : CPLFree( papszFields[iBounds] );
1427 0 : papszFields[iBounds] = NULL;
1428 0 : iBounds++;
1429 : }
1430 :
1431 : /*-----------------------------------------------------------------
1432 : * Fetch the projection.
1433 : *----------------------------------------------------------------*/
1434 : char **papszNextField;
1435 :
1436 0 : if( CSLCount( papszFields ) >= 3
1437 : && EQUAL(papszFields[0],"Earth")
1438 : && EQUAL(papszFields[1],"Projection") )
1439 : {
1440 0 : psProj->nProjId = atoi(papszFields[2]);
1441 0 : papszNextField = papszFields + 3;
1442 : }
1443 0 : else if (CSLCount( papszFields ) >= 2
1444 : && EQUAL(papszFields[0],"NonEarth") )
1445 : {
1446 : // NonEarth Units "..." Bounds (x, y) (x, y)
1447 0 : psProj->nProjId = 0;
1448 0 : papszNextField = papszFields + 2;
1449 :
1450 0 : if( papszNextField[0] != NULL && EQUAL(papszNextField[0],"Units") )
1451 0 : papszNextField++;
1452 : }
1453 : else
1454 : {
1455 : // Invalid projection string ???
1456 0 : if (CSLCount(papszFields) > 0)
1457 : CPLError(CE_Warning, CPLE_IllegalArg,
1458 0 : "Failed parsing CoordSys: '%s'", pszCoordSys);
1459 0 : CSLDestroy(papszFields);
1460 0 : return -1;
1461 : }
1462 :
1463 : /*-----------------------------------------------------------------
1464 : * Fetch the datum information.
1465 : *----------------------------------------------------------------*/
1466 0 : int nDatum = 0;
1467 :
1468 0 : if( psProj->nProjId != 0 && CSLCount(papszNextField) > 0 )
1469 : {
1470 0 : nDatum = atoi(papszNextField[0]);
1471 0 : papszNextField++;
1472 : }
1473 :
1474 0 : if( (nDatum == 999 || nDatum == 9999)
1475 : && CSLCount(papszNextField) >= 4 )
1476 : {
1477 0 : psProj->nEllipsoidId = atoi(papszFields[0]);
1478 0 : psProj->dDatumShiftX = atof(papszNextField[1]);
1479 0 : psProj->dDatumShiftY = atof(papszNextField[2]);
1480 0 : psProj->dDatumShiftZ = atof(papszNextField[3]);
1481 0 : papszNextField += 4;
1482 :
1483 0 : if( nDatum == 9999
1484 : && CSLCount(papszNextField) >= 5 )
1485 : {
1486 0 : psProj->adDatumParams[0] = atof(papszNextField[0]);
1487 0 : psProj->adDatumParams[1] = atof(papszNextField[1]);
1488 0 : psProj->adDatumParams[2] = atof(papszNextField[2]);
1489 0 : psProj->adDatumParams[3] = atof(papszNextField[3]);
1490 0 : psProj->adDatumParams[4] = atof(papszNextField[4]);
1491 0 : papszNextField += 5;
1492 : }
1493 : }
1494 0 : else if (nDatum != 999 && nDatum != 9999)
1495 : {
1496 : /*-----------------------------------------------------------------
1497 : * Find the datum, and collect it's parameters if possible.
1498 : *----------------------------------------------------------------*/
1499 : int iDatum;
1500 0 : MapInfoDatumInfo *psDatumInfo = NULL;
1501 :
1502 0 : for(iDatum=0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++)
1503 : {
1504 0 : if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
1505 : {
1506 0 : psDatumInfo = asDatumInfoList + iDatum;
1507 0 : break;
1508 : }
1509 : }
1510 :
1511 0 : if( asDatumInfoList[iDatum].nMapInfoDatumID == -1
1512 : && nDatum != 999 && nDatum != 9999 )
1513 : {
1514 : /* use WGS84 */
1515 0 : psDatumInfo = asDatumInfoList + 0;
1516 : }
1517 :
1518 0 : if( psDatumInfo != NULL )
1519 : {
1520 0 : psProj->nEllipsoidId = psDatumInfo->nEllipsoid;
1521 0 : psProj->nDatumId = psDatumInfo->nMapInfoDatumID;
1522 0 : psProj->dDatumShiftX = psDatumInfo->dfShiftX;
1523 0 : psProj->dDatumShiftY = psDatumInfo->dfShiftY;
1524 0 : psProj->dDatumShiftZ = psDatumInfo->dfShiftZ;
1525 0 : psProj->adDatumParams[0] = psDatumInfo->dfDatumParm0;
1526 0 : psProj->adDatumParams[1] = psDatumInfo->dfDatumParm1;
1527 0 : psProj->adDatumParams[2] = psDatumInfo->dfDatumParm2;
1528 0 : psProj->adDatumParams[3] = psDatumInfo->dfDatumParm3;
1529 0 : psProj->adDatumParams[4] = psDatumInfo->dfDatumParm4;
1530 : }
1531 : }
1532 :
1533 : /*-----------------------------------------------------------------
1534 : * Fetch the units string.
1535 : *----------------------------------------------------------------*/
1536 0 : if( CSLCount(papszNextField) > 0 )
1537 : {
1538 0 : psProj->nUnitsId = TABUnitIdFromString(papszNextField[0]);
1539 0 : papszNextField++;
1540 : }
1541 :
1542 : /*-----------------------------------------------------------------
1543 : * Finally the projection parameters.
1544 : *----------------------------------------------------------------*/
1545 0 : for(int iParam=0; iParam < 6 && CSLCount(papszNextField) > 0; iParam++)
1546 : {
1547 0 : psProj->adProjParams[iParam] = atof(papszNextField[0]);
1548 0 : papszNextField++;
1549 : }
1550 :
1551 0 : return 0;
1552 : }
1553 :
|