1 : /******************************************************************************
2 : * $Id: ogr_srs_pci.cpp 18388 2009-12-26 21:41:14Z warmerdam $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: OGRSpatialReference translation to/from PCI georeferencing
6 : * information.
7 : * Author: Andrey Kiselev, dron@ak4719.spb.edu
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2003, Andrey Kiselev <dron@ak4719.spb.edu>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogr_spatialref.h"
32 : #include "ogr_p.h"
33 : #include "cpl_conv.h"
34 : #include "cpl_csv.h"
35 :
36 : CPL_CVSID("$Id: ogr_srs_pci.cpp 18388 2009-12-26 21:41:14Z warmerdam $");
37 :
38 : typedef struct
39 : {
40 : const char *pszPCIDatum;
41 : int nEPSGCode;
42 : double dfSemiMajor;
43 : double dfSemiMinor;
44 : } PCIDatums;
45 :
46 : static const PCIDatums aoDatums[] =
47 : {
48 : { "D-01", 4267, 0, 0 }, // NAD27 (USA, NADCON)
49 : { "D-03", 4267, 0, 0 }, // NAD27 (Canada, NTv1)
50 : { "D-02", 4269, 0, 0 }, // NAD83 (USA, NADCON)
51 : { "D-04", 4269, 0, 0 }, // NAD83 (Canada, NTv1)
52 : { "D000", 4326, 0, 0 }, // WGS 1984
53 : { "D001", 4322, 0, 0 }, // WGS 1972
54 : { "D008", 4296, 0, 0 }, // Sudan
55 : { "D013", 4601, 0, 0 }, // Antigua Island Astro 1943
56 : { "D029", 4202, 0, 0 }, // Australian Geodetic 1966
57 : { "D030", 4203, 0, 0 }, // Australian Geodetic 1984
58 : { "D033", 4216, 0, 0 }, // Bermuda 1957
59 : { "D034", 4165, 0, 0 }, // Bissau
60 : { "D036", 4219, 0, 0 }, // Bukit Rimpah
61 : { "D038", 4221, 0, 0 }, // Campo Inchauspe
62 : { "D040", 4222, 0, 0 }, // Cape
63 : { "D042", 4223, 0, 0 }, // Carthage
64 : { "D044", 4224, 0, 0 }, // Chua Astro
65 : { "D045", 4225, 0, 0 }, // Corrego Alegre
66 : { "D046", 4155, 0, 0 }, // Dabola (Guinea)
67 : { "D066", 4272, 0, 0 }, // Geodetic Datum 1949 (New Zealand)
68 : { "D071", 4255, 0, 0 }, // Herat North (Afghanistan)
69 : { "D077", 4239, 0, 0 }, // Indian 1954 (Thailand, Vietnam)
70 : { "D078", 4240, 0, 0 }, // Indian 1975 (Thailand)
71 : { "D083", 4244, 0, 0 }, // Kandawala (Sri Lanka)
72 : { "D085", 4245, 0, 0 }, // Kertau 1948 (West Malaysia & Singapore)
73 : { "D088", 4250, 0, 0 }, // Leigon (Ghana)
74 : { "D089", 4251, 0, 0 }, // Liberia 1964 (Liberia)
75 : { "D092", 4256, 0, 0 }, // Mahe 1971 (Mahe Island)
76 : { "D093", 4262, 0, 0 }, // Massawa (Ethiopia (Eritrea))
77 : { "D094", 4261, 0, 0 }, // Merchich (Morocco)
78 : { "D098", 4604, 0, 0 }, // Montserrat Island Astro 1958 (Montserrat (Leeward Islands))
79 : { "D110", 4267, 0, 0 }, // NAD27 / Alaska
80 : { "D139", 4282, 0, 0 }, // Pointe Noire 1948 (Congo)
81 : { "D140", 4615, 0, 0 }, // Porto Santo 1936 (Porto Santo, Madeira Islands)
82 : { "D151", 4139, 0, 0 }, // Puerto Rico (Puerto Rico, Virgin Islands)
83 : { "D153", 4287, 0, 0 }, // Qornoq (Greenland (South))
84 : { "D158", 4292, 0, 0 }, // Sapper Hill 1943 (East Falkland Island)
85 : { "D159", 4293, 0, 0 }, // Schwarzeck (Namibia)
86 : { "D160", 4616, 0, 0 }, // Selvagem Grande 1938 (Salvage Islands)
87 : { "D176", 4297, 0, 0 }, // Tananarive Observatory 1925 (Madagascar)
88 : { "D177", 4298, 0, 0 }, // Timbalai 1948 (Brunei, East Malaysia (Sabah, Sarawak))
89 : { "D187", 4309, 0, 0 }, // Yacare (Uruguay)
90 : { "D188", 4311, 0, 0 }, // Zanderij (Suriname)
91 : { "D401", 4124, 0, 0 }, // RT90 (Sweden)
92 : { "D501", 4312, 0, 0 }, // MGI (Hermannskogel, Austria)
93 : { NULL, 0 }
94 : };
95 :
96 : static const PCIDatums aoEllips[] =
97 : {
98 : { "E000", 7008, 0, 0 }, // Clarke, 1866 (NAD1927)
99 : { "E001", 7034, 0, 0 }, // Clarke, 1880
100 : { "E002", 7004, 0, 0 }, // Bessel, 1841
101 : { "E003", 0, 6378157.5,6356772.2 }, // New International, 1967
102 : { "E004", 7022, 0, 0 }, // International, 1924 (Hayford, 1909)
103 : { "E005", 7043, 0, 0 }, // WGS, 1972
104 : { "E006", 7042, 0, 0 }, // Everest, 1830
105 : { "E007", 0, 6378145.,6356759.769356 }, // WGS, 1966
106 : { "E008", 7019, 0, 0 }, // GRS, 1980 (NAD1983)
107 : { "E009", 7001, 0, 0 }, // Airy, 1830
108 : { "E010", 7018, 0, 0 }, // Modified Everest
109 : { "E011", 7002, 0, 0 }, // Modified Airy
110 : { "E012", 7030, 0, 0 }, // WGS, 1984 (GPS)
111 : { "E013", 0, 6378155.,6356773.3205 }, // Southeast Asia
112 : { "E014", 7003, 0, 0 }, // Australian National, 1965
113 : { "E015", 7024, 0, 0 }, // Krassovsky, 1940
114 : { "E016", 7053, 0, 0 }, // Hough
115 : { "E017", 0, 6378166.,6356784.283666 }, // Mercury, 1960
116 : { "E018", 0, 6378150.,6356768.337303 }, // Modified Mercury, 1968
117 : { "E019", 7052, 0, 0}, // normal sphere
118 : { "E333", 7046, 0, 0 }, // Bessel 1841 (Japan By Law)
119 : { "E600", 0, 6378144.0,6356759.0 }, // D-PAF (Orbits)
120 : { "E900", 7006, 0, 0 }, // Bessel, 1841 (Namibia)
121 : { "E901", 7044, 0, 0 }, // Everest, 1956
122 : { "E902", 7056, 0, 0 }, // Everest, 1969
123 : { "E903", 7016, 0, 0 }, // Everest (Sabah & Sarawak)
124 : { "E904", 7020, 0, 0 }, // Helmert, 1906
125 : { "E905", 0, 6378136.,6356751.301569 }, // SGS 85
126 : { "E906", 0, 6378165.,6356783.286959 }, // WGS 60
127 : { "E907", 7036, 0, 0 }, // South American, 1969
128 : { "E910", 7041, 0, 0 }, // ATS77
129 : { NULL, 0 }
130 : };
131 :
132 : /************************************************************************/
133 : /* OSRImportFromPCI() */
134 : /************************************************************************/
135 :
136 : /**
137 : * \brief Import coordinate system from PCI projection definition.
138 : *
139 : * This function is the same as OGRSpatialReference::importFromPCI().
140 : */
141 :
142 1 : OGRErr OSRImportFromPCI( OGRSpatialReferenceH hSRS, const char *pszProj,
143 : const char *pszUnits, double *padfPrjParams )
144 :
145 : {
146 1 : VALIDATE_POINTER1( hSRS, "OSRImportFromPCI", CE_Failure );
147 :
148 : return ((OGRSpatialReference *) hSRS)->importFromPCI( pszProj,
149 : pszUnits,
150 1 : padfPrjParams );
151 : }
152 :
153 : /************************************************************************/
154 : /* importFromPCI() */
155 : /************************************************************************/
156 :
157 : /**
158 : * \brief Import coordinate system from PCI projection definition.
159 : *
160 : * PCI software uses 16-character string to specify coordinate system
161 : * and datum/ellipsoid. You should supply at least this string to the
162 : * importFromPCI() function.
163 : *
164 : * This function is the equivalent of the C function OSRImportFromPCI().
165 : *
166 : * @param pszProj NULL terminated string containing the definition. Looks
167 : * like "pppppppppppp Ennn" or "pppppppppppp Dnnn", where "pppppppppppp" is
168 : * a projection code, "Ennn" is an ellipsoid code, "Dnnn" --- a datum code.
169 : *
170 : * @param pszUnits Grid units code ("DEGREE" or "METRE"). If NULL "METRE" will
171 : * be used.
172 : *
173 : * @param padfPrjParams Array of 17 coordinate system parameters:
174 : *
175 : * [0] Spheroid semi major axis
176 : * [1] Spheroid semi minor axis
177 : * [2] Reference Longitude
178 : * [3] Reference Latitude
179 : * [4] First Standard Parallel
180 : * [5] Second Standard Parallel
181 : * [6] False Easting
182 : * [7] False Northing
183 : * [8] Scale Factor
184 : * [9] Height above sphere surface
185 : * [10] Longitude of 1st point on center line
186 : * [11] Latitude of 1st point on center line
187 : * [12] Longitude of 2nd point on center line
188 : * [13] Latitude of 2nd point on center line
189 : * [14] Azimuth east of north for center line
190 : * [15] Landsat satellite number
191 : * [16] Landsat path number
192 : *
193 : * Particular projection uses different parameters, unused ones may be set to
194 : * zero. If NULL suppliet instead of array pointer default values will be
195 : * used (i.e., zeroes).
196 : *
197 : * @return OGRERR_NONE on success or an error code in case of failure.
198 : */
199 :
200 3 : OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
201 : const char *pszUnits,
202 : double *padfPrjParams )
203 :
204 : {
205 3 : Clear();
206 :
207 3 : if( pszProj == NULL || CPLStrnlen(pszProj, 16) < 16 )
208 0 : return OGRERR_CORRUPT_DATA;
209 :
210 : #ifdef DEBUG
211 : CPLDebug( "OSR_PCI", "Trying to import projection \"%s\"", pszProj );
212 : #endif
213 :
214 : /* -------------------------------------------------------------------- */
215 : /* Use safe defaults if projection parameters are not supplied. */
216 : /* -------------------------------------------------------------------- */
217 3 : int bProjAllocated = FALSE;
218 :
219 3 : if( padfPrjParams == NULL )
220 : {
221 : int i;
222 :
223 0 : padfPrjParams = (double *)CPLMalloc( 17 * sizeof(double) );
224 0 : if ( !padfPrjParams )
225 0 : return OGRERR_NOT_ENOUGH_MEMORY;
226 0 : for ( i = 0; i < 17; i++ )
227 0 : padfPrjParams[i] = 0.0;
228 0 : bProjAllocated = TRUE;
229 : }
230 :
231 : /* -------------------------------------------------------------------- */
232 : /* Extract and "normalize" the earthmodel to look like E001, */
233 : /* D-02 or D109. */
234 : /* -------------------------------------------------------------------- */
235 : char szEarthModel[5];
236 : const char *pszEM;
237 3 : int bIsNAD27 = FALSE;
238 :
239 3 : strcpy( szEarthModel, "" );
240 3 : pszEM = pszProj + strlen(pszProj) - 1;
241 15 : while( pszEM != pszProj )
242 : {
243 12 : if( *pszEM == 'e' || *pszEM == 'E' || *pszEM == 'd' || *pszEM == 'D' )
244 : {
245 3 : int nCode = atoi(pszEM+1);
246 :
247 3 : if( nCode >= -99 && nCode <= 999 )
248 3 : sprintf( szEarthModel, "%c%03d", toupper(*pszEM), nCode );
249 :
250 3 : break;
251 : }
252 :
253 9 : pszEM--;
254 : }
255 :
256 3 : if( EQUAL(pszEM,"E000")
257 : || EQUAL(pszEM,"D-01")
258 : || EQUAL(pszEM,"D-03")
259 : || EQUAL(pszEM,"D-07")
260 : || EQUAL(pszEM,"D-09")
261 : || EQUAL(pszEM,"D-11")
262 : || EQUAL(pszEM,"D-13")
263 : || EQUAL(pszEM,"D-17") )
264 2 : bIsNAD27 = TRUE;
265 :
266 : /* -------------------------------------------------------------------- */
267 : /* Operate on the basis of the projection name. */
268 : /* -------------------------------------------------------------------- */
269 3 : if( EQUALN( pszProj, "LONG/LAT", 8 ) )
270 : {
271 : }
272 :
273 3 : else if( EQUALN( pszProj, "METER", 5 )
274 : || EQUALN( pszProj, "METRE", 5 ) )
275 : {
276 0 : SetLocalCS( "METER" );
277 0 : SetLinearUnits( "METER", 1.0 );
278 : }
279 :
280 3 : else if( EQUALN( pszProj, "FEET", 4 )
281 : || EQUALN( pszProj, "FOOT", 4 ) )
282 : {
283 0 : SetLocalCS( "FEET" );
284 0 : SetLinearUnits( "FEET", atof(SRS_UL_FOOT_CONV) );
285 : }
286 :
287 3 : else if( EQUALN( pszProj, "ACEA", 4 ) )
288 : {
289 : SetACEA( padfPrjParams[4], padfPrjParams[5],
290 : padfPrjParams[3], padfPrjParams[2],
291 0 : padfPrjParams[6], padfPrjParams[7] );
292 : }
293 :
294 3 : else if( EQUALN( pszProj, "AE", 2 ) )
295 : {
296 : SetAE( padfPrjParams[3], padfPrjParams[2],
297 0 : padfPrjParams[6], padfPrjParams[7] );
298 : }
299 :
300 3 : else if( EQUALN( pszProj, "EC", 2 ) )
301 : {
302 : SetEC( padfPrjParams[4], padfPrjParams[5],
303 : padfPrjParams[3], padfPrjParams[2],
304 1 : padfPrjParams[6], padfPrjParams[7] );
305 : }
306 :
307 2 : else if( EQUALN( pszProj, "ER", 2 ) )
308 : {
309 : // PCI and GCTP don't support natural origin lat.
310 : SetEquirectangular2( 0.0, padfPrjParams[2],
311 : padfPrjParams[3],
312 0 : padfPrjParams[6], padfPrjParams[7] );
313 : }
314 :
315 2 : else if( EQUALN( pszProj, "GNO", 3 ) )
316 : {
317 : SetGnomonic( padfPrjParams[3], padfPrjParams[2],
318 0 : padfPrjParams[6], padfPrjParams[7] );
319 : }
320 :
321 : // FIXME: GVNP --- General Vertical Near- Side Perspective skipped
322 :
323 2 : else if( EQUALN( pszProj, "LAEA", 4 ) )
324 : {
325 : SetLAEA( padfPrjParams[3], padfPrjParams[2],
326 0 : padfPrjParams[6], padfPrjParams[7] );
327 : }
328 :
329 2 : else if( EQUALN( pszProj, "LCC", 3 ) )
330 : {
331 : SetLCC( padfPrjParams[4], padfPrjParams[5],
332 : padfPrjParams[3], padfPrjParams[2],
333 0 : padfPrjParams[6], padfPrjParams[7] );
334 : }
335 :
336 2 : else if( EQUALN( pszProj, "MC", 2 ) )
337 : {
338 : SetMC( padfPrjParams[3], padfPrjParams[2],
339 0 : padfPrjParams[6], padfPrjParams[7] );
340 : }
341 :
342 2 : else if( EQUALN( pszProj, "MER", 3 ) )
343 : {
344 : SetMercator( padfPrjParams[3], padfPrjParams[2],
345 0 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
346 0 : padfPrjParams[6], padfPrjParams[7] );
347 : }
348 :
349 2 : else if( EQUALN( pszProj, "OG", 2 ) )
350 : {
351 : SetOrthographic( padfPrjParams[3], padfPrjParams[2],
352 0 : padfPrjParams[6], padfPrjParams[7] );
353 : }
354 :
355 : // FIXME: OM --- Oblique Mercator skipped
356 :
357 2 : else if( EQUALN( pszProj, "PC", 2 ) )
358 : {
359 : SetPolyconic( padfPrjParams[3], padfPrjParams[2],
360 0 : padfPrjParams[6], padfPrjParams[7] );
361 : }
362 :
363 2 : else if( EQUALN( pszProj, "PS", 2 ) )
364 : {
365 : SetPS( padfPrjParams[3], padfPrjParams[2],
366 0 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
367 0 : padfPrjParams[6], padfPrjParams[7] );
368 : }
369 :
370 2 : else if( EQUALN( pszProj, "ROB", 3 ) )
371 : {
372 : SetRobinson( padfPrjParams[2],
373 0 : padfPrjParams[6], padfPrjParams[7] );
374 : }
375 :
376 2 : else if( EQUALN( pszProj, "SG", 2 ) )
377 : {
378 : SetStereographic( padfPrjParams[3], padfPrjParams[2],
379 0 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
380 0 : padfPrjParams[6], padfPrjParams[7] );
381 : }
382 :
383 2 : else if( EQUALN( pszProj, "SIN", 3 ) )
384 : {
385 : SetSinusoidal( padfPrjParams[2],
386 0 : padfPrjParams[6], padfPrjParams[7] );
387 : }
388 :
389 : // FIXME: SOM --- Space Oblique Mercator skipped
390 :
391 2 : else if( EQUALN( pszProj, "SPCS", 4 ) )
392 : {
393 : int iZone;
394 :
395 0 : iZone = CPLScanLong( (char *)pszProj + 5, 4 );
396 :
397 0 : SetStatePlane( iZone, !bIsNAD27 );
398 : }
399 :
400 2 : else if( EQUALN( pszProj, "SPIF", 4 ) )
401 : {
402 : int iZone;
403 :
404 0 : iZone = CPLScanLong( (char *)pszProj + 5, 4 );
405 :
406 0 : SetStatePlane( iZone, !bIsNAD27 );
407 : SetLinearUnitsAndUpdateParameters( SRS_UL_FOOT,
408 0 : atof(SRS_UL_FOOT_CONV) );
409 : }
410 :
411 2 : else if( EQUALN( pszProj, "SPAF", 4 ) )
412 : {
413 : int iZone;
414 :
415 0 : iZone = CPLScanLong( (char *)pszProj + 5, 4 );
416 :
417 0 : SetStatePlane( iZone, !bIsNAD27 );
418 : SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT,
419 0 : atof(SRS_UL_US_FOOT_CONV) );
420 : }
421 :
422 2 : else if( EQUALN( pszProj, "TM", 2 ) )
423 : {
424 : SetTM( padfPrjParams[3], padfPrjParams[2],
425 0 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
426 0 : padfPrjParams[6], padfPrjParams[7] );
427 : }
428 :
429 2 : else if( EQUALN( pszProj, "UTM", 3 ) )
430 : {
431 2 : int iZone, bNorth = TRUE;
432 :
433 2 : iZone = CPLScanLong( (char *)pszProj + 4, 5 );;
434 2 : if ( iZone < 0 )
435 : {
436 0 : iZone = -iZone;
437 0 : bNorth = FALSE;
438 : }
439 :
440 : // Check for a zone letter. PCI uses, accidentally, MGRS
441 : // type row lettering in its UTM projection
442 2 : char byZoneID = 0;
443 2 : int nZoneOffset = 0;
444 :
445 : // Iterate through the remaining characters in the projection
446 : // string. We should see something like "UTM 55 G D000"
447 6 : for (int i = 9; i < 16; i++)
448 : {
449 8 : if (pszProj[i] == ' ' && nZoneOffset == 0)
450 : {
451 2 : nZoneOffset = i + 1;
452 : }
453 4 : else if (pszProj[i] == ' ' && i - nZoneOffset == 1)
454 : {
455 2 : byZoneID = pszProj[nZoneOffset];
456 2 : break;
457 : }
458 2 : else if (i - nZoneOffset > 1)
459 : {
460 0 : break;
461 : }
462 : }
463 :
464 : // Determine if the MGRS zone falls above or below the equator
465 2 : if (byZoneID != 0)
466 : {
467 : #ifdef DEBUG
468 : CPLDebug("OSR_PCI", "Found MGRS zone in UTM projection string: %c",
469 : byZoneID);
470 : #endif
471 2 : if (byZoneID >= 'N' && byZoneID <= 'X')
472 : {
473 0 : bNorth = TRUE;
474 : }
475 : else
476 : {
477 2 : bNorth = FALSE;
478 : }
479 : }
480 :
481 2 : SetUTM( iZone, bNorth );
482 : }
483 :
484 0 : else if( EQUALN( pszProj, "VDG", 3 ) )
485 : {
486 : SetVDG( padfPrjParams[2],
487 0 : padfPrjParams[6], padfPrjParams[7] );
488 : }
489 :
490 : else
491 : {
492 0 : CPLDebug( "OSR_PCI", "Unsupported projection: %s", pszProj );
493 0 : SetLocalCS( pszProj );
494 : }
495 :
496 : /* ==================================================================== */
497 : /* Translate the datum/spheroid. */
498 : /* ==================================================================== */
499 :
500 : /* -------------------------------------------------------------------- */
501 : /* We have an earthmodel string, look it up in the datum list. */
502 : /* -------------------------------------------------------------------- */
503 3 : if( strlen(szEarthModel) > 0
504 : && (poRoot == NULL || IsProjected() || IsGeographic()) )
505 : {
506 3 : const PCIDatums *paoDatum = aoDatums;
507 :
508 : // Search for matching datum
509 141 : while ( paoDatum->pszPCIDatum )
510 : {
511 135 : if( EQUALN( szEarthModel, paoDatum->pszPCIDatum, 4 ) )
512 : {
513 0 : OGRSpatialReference oGCS;
514 0 : oGCS.importFromEPSG( paoDatum->nEPSGCode );
515 0 : CopyGeogCSFrom( &oGCS );
516 0 : break;
517 : }
518 135 : paoDatum++;
519 : }
520 :
521 : /* -------------------------------------------------------------------- */
522 : /* If not, look in the ellipsoid list. */
523 : /* -------------------------------------------------------------------- */
524 3 : if ( !paoDatum->pszPCIDatum ) // No matching; search for ellipsoids
525 : {
526 3 : paoDatum = aoEllips;
527 :
528 : #ifdef DEBUG
529 : CPLDebug( "OSR_PCI",
530 : "Cannot found matching datum definition, "
531 : "search for ellipsoids." );
532 : #endif
533 :
534 21 : while ( paoDatum->pszPCIDatum )
535 : {
536 18 : if( EQUALN( szEarthModel, paoDatum->pszPCIDatum, 4 )
537 : && paoDatum->nEPSGCode != 0 )
538 : {
539 3 : char *pszName = NULL;
540 : double dfSemiMajor;
541 : double dfInvFlattening;
542 :
543 3 : if ( OSRGetEllipsoidInfo( paoDatum->nEPSGCode, &pszName,
544 : &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE )
545 : {
546 : SetGeogCS( CPLString().Printf(
547 : "Unknown datum based upon the %s ellipsoid",
548 : pszName ),
549 : CPLString().Printf(
550 : "Not specified (based on %s spheroid)",
551 : pszName ),
552 : pszName, dfSemiMajor, dfInvFlattening,
553 3 : NULL, 0.0, NULL, 0.0 );
554 3 : SetAuthority( "SPHEROID", "EPSG", paoDatum->nEPSGCode );
555 :
556 3 : if ( pszName )
557 3 : CPLFree( pszName );
558 : }
559 :
560 3 : break;
561 : }
562 15 : else if( EQUALN( szEarthModel, paoDatum->pszPCIDatum, 4 ) )
563 : {
564 : double dfInvFlattening;
565 :
566 0 : if ( CPLIsEqual(paoDatum->dfSemiMajor, paoDatum->dfSemiMinor) )
567 0 : dfInvFlattening = 0.0;
568 : else
569 : dfInvFlattening = paoDatum->dfSemiMajor
570 0 : / (paoDatum->dfSemiMajor-paoDatum->dfSemiMinor);
571 :
572 : SetGeogCS( "Unknown datum based upon the custom spheroid",
573 : "Not specified (based on custom spheroid)",
574 : CPLString().Printf( "PCI Ellipse %s",
575 : szEarthModel),
576 : paoDatum->dfSemiMajor, dfInvFlattening,
577 0 : NULL, 0, NULL, 0 );
578 0 : break;
579 : }
580 15 : paoDatum++;
581 : }
582 : }
583 :
584 : /* -------------------------------------------------------------------- */
585 : /* Custom spheroid. */
586 : /* -------------------------------------------------------------------- */
587 3 : if ( !paoDatum->pszPCIDatum ) // Didn't found matches
588 : {
589 : #ifdef DEBUG
590 : CPLDebug( "OSR_PCI",
591 : "Cannot found matching ellipsoid definition." );
592 : #endif
593 :
594 0 : if( EQUALN( pszProj + 12, "E999", 4 )
595 0 : || padfPrjParams[0] != 0.0 )
596 : {
597 : double dfInvFlattening;
598 :
599 0 : if( ABS(padfPrjParams[0] - padfPrjParams[1]) < 0.01 )
600 : {
601 0 : dfInvFlattening = 0.0;
602 : }
603 : else
604 : {
605 : dfInvFlattening =
606 0 : padfPrjParams[0]/(padfPrjParams[0]-padfPrjParams[1]);
607 : }
608 :
609 : SetGeogCS( "Unknown datum based upon the custom spheroid",
610 : "Not specified (based on custom spheroid)",
611 : "Custom spheroid",
612 : padfPrjParams[0], dfInvFlattening,
613 0 : NULL, 0, NULL, 0 );
614 : }
615 : else
616 : {
617 : // If we don't know, default to WGS84
618 : // so there is something there.
619 0 : SetWellKnownGeogCS( "WGS84" );
620 : #ifdef DEBUG
621 : CPLDebug( "OSR_PCI", "Setting WGS84 as a fallback." );
622 : #endif
623 :
624 : }
625 : }
626 : }
627 :
628 : /* -------------------------------------------------------------------- */
629 : /* Grid units translation */
630 : /* -------------------------------------------------------------------- */
631 3 : if( (IsLocal() || IsProjected()) && pszUnits )
632 : {
633 1 : if( EQUAL( pszUnits, "METRE" ) )
634 1 : SetLinearUnits( SRS_UL_METER, 1.0 );
635 0 : else if( EQUAL( pszUnits, "DEGREE" ) )
636 0 : SetAngularUnits( SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV) );
637 : else
638 0 : SetLinearUnits( SRS_UL_METER, 1.0 );
639 : }
640 :
641 3 : FixupOrdering();
642 :
643 3 : if ( bProjAllocated && padfPrjParams )
644 0 : CPLFree( padfPrjParams );
645 :
646 3 : return OGRERR_NONE;
647 : }
648 :
649 : /************************************************************************/
650 : /* OSRExportToPCI() */
651 : /************************************************************************/
652 : /**
653 : * \brief Export coordinate system in PCI projection definition.
654 : *
655 : * This function is the same as OGRSpatialReference::exportToPCI().
656 : */
657 1 : OGRErr OSRExportToPCI( OGRSpatialReferenceH hSRS,
658 : char **ppszProj, char **ppszUnits,
659 : double **ppadfPrjParams )
660 :
661 : {
662 1 : VALIDATE_POINTER1( hSRS, "OSRExportToPCI", CE_Failure );
663 :
664 1 : *ppszProj = NULL;
665 1 : *ppszUnits = NULL;
666 1 : *ppadfPrjParams = NULL;
667 :
668 : return ((OGRSpatialReference *) hSRS)->exportToPCI( ppszProj, ppszUnits,
669 1 : ppadfPrjParams );
670 : }
671 :
672 : /************************************************************************/
673 : /* exportToPCI() */
674 : /************************************************************************/
675 :
676 : /**
677 : * \brief Export coordinate system in PCI projection definition.
678 : *
679 : * Converts the loaded coordinate reference system into PCI projection
680 : * definition to the extent possible. The strings returned in ppszProj,
681 : * ppszUnits and ppadfPrjParams array should be deallocated by the caller
682 : * with CPLFree() when no longer needed.
683 : *
684 : * LOCAL_CS coordinate systems are not translatable. An empty string
685 : * will be returned along with OGRERR_NONE.
686 : *
687 : * This method is the equivelent of the C function OSRExportToPCI().
688 : *
689 : * @param ppszProj pointer to which dynamically allocated PCI projection
690 : * definition will be assigned.
691 : *
692 : * @param ppszUnits pointer to which dynamically allocated units definition
693 : * will be assigned.
694 : *
695 : * @param ppadfPrjParams pointer to which dynamically allocated array of
696 : * 17 projection parameters will be assigned. See importFromPCI() for the list
697 : * of parameters.
698 : *
699 : * @return OGRERR_NONE on success or an error code on failure.
700 : */
701 :
702 17 : OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
703 : double **ppadfPrjParams ) const
704 :
705 : {
706 17 : const char *pszProjection = GetAttrValue("PROJECTION");
707 :
708 : /* -------------------------------------------------------------------- */
709 : /* Fill all projection parameters with zero. */
710 : /* -------------------------------------------------------------------- */
711 : int i;
712 :
713 17 : *ppadfPrjParams = (double *)CPLMalloc( 17 * sizeof(double) );
714 306 : for ( i = 0; i < 17; i++ )
715 289 : (*ppadfPrjParams)[i] = 0.0;
716 :
717 : /* -------------------------------------------------------------------- */
718 : /* Get the prime meridian info. */
719 : /* -------------------------------------------------------------------- */
720 17 : const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
721 17 : double dfFromGreenwich = 0.0;
722 :
723 17 : if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2
724 : && atof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
725 : {
726 0 : dfFromGreenwich = atof(poPRIMEM->GetChild(1)->GetValue());
727 : }
728 :
729 : /* ==================================================================== */
730 : /* Handle the projection definition. */
731 : /* ==================================================================== */
732 : char szProj[17];
733 :
734 17 : if( IsLocal() )
735 : {
736 0 : if( GetLinearUnits() > 0.30479999 && GetLinearUnits() < 0.3048010 )
737 0 : CPLPrintStringFill( szProj, "FEET", 17 );
738 : else
739 0 : CPLPrintStringFill( szProj, "METER", 17 );
740 : }
741 :
742 17 : else if( pszProjection == NULL )
743 : {
744 : #ifdef DEBUG
745 : CPLDebug( "OSR_PCI",
746 : "Empty projection definition, considered as LONG/LAT" );
747 : #endif
748 15 : CPLPrintStringFill( szProj, "LONG/LAT", 17 );
749 : }
750 :
751 2 : else if( EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
752 : {
753 0 : CPLPrintStringFill( szProj, "ACEA", 16 );
754 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
755 0 : (*ppadfPrjParams)[3] =
756 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
757 0 : (*ppadfPrjParams)[4] =
758 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
759 0 : (*ppadfPrjParams)[5] =
760 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
761 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
762 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
763 : }
764 :
765 2 : else if( EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT) )
766 : {
767 0 : CPLPrintStringFill( szProj, "AE", 16 );
768 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
769 0 : (*ppadfPrjParams)[3] =
770 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
771 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
772 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
773 : }
774 :
775 2 : else if( EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC) )
776 : {
777 0 : CPLPrintStringFill( szProj, "EC", 16 );
778 0 : (*ppadfPrjParams)[2] =
779 0 : GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 );
780 0 : (*ppadfPrjParams)[3] =
781 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 );
782 0 : (*ppadfPrjParams)[4] =
783 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
784 0 : (*ppadfPrjParams)[5] =
785 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
786 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
787 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
788 : }
789 :
790 2 : else if( EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR) )
791 : {
792 0 : CPLPrintStringFill( szProj, "ER", 16 );
793 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
794 0 : (*ppadfPrjParams)[3] =
795 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
796 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
797 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
798 : }
799 :
800 2 : else if( EQUAL(pszProjection, SRS_PT_GNOMONIC) )
801 : {
802 0 : CPLPrintStringFill( szProj, "GNO", 16 );
803 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
804 0 : (*ppadfPrjParams)[3] =
805 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
806 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
807 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
808 : }
809 :
810 2 : else if( EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
811 : {
812 0 : CPLPrintStringFill( szProj, "LAEA", 16 );
813 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
814 0 : (*ppadfPrjParams)[3] =
815 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
816 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
817 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
818 : }
819 :
820 2 : else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
821 : {
822 1 : CPLPrintStringFill( szProj, "LCC", 16 );
823 1 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
824 1 : (*ppadfPrjParams)[3] =
825 1 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
826 1 : (*ppadfPrjParams)[4] =
827 1 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
828 1 : (*ppadfPrjParams)[5] =
829 1 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
830 1 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
831 1 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
832 : }
833 :
834 1 : else if( EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL) )
835 : {
836 0 : CPLPrintStringFill( szProj, "MC", 16 );
837 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
838 0 : (*ppadfPrjParams)[3] =
839 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
840 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
841 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
842 : }
843 :
844 1 : else if( EQUAL(pszProjection, SRS_PT_MERCATOR_1SP) )
845 : {
846 0 : CPLPrintStringFill( szProj, "MER", 16 );
847 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
848 0 : (*ppadfPrjParams)[3] =
849 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
850 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
851 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
852 0 : (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
853 : }
854 :
855 1 : else if( EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC) )
856 : {
857 0 : CPLPrintStringFill( szProj, "OG", 16 );
858 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
859 0 : (*ppadfPrjParams)[3] =
860 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
861 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
862 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
863 : }
864 :
865 1 : else if( EQUAL(pszProjection, SRS_PT_POLYCONIC) )
866 : {
867 0 : CPLPrintStringFill( szProj, "PC", 16 );
868 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
869 0 : (*ppadfPrjParams)[3] =
870 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
871 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
872 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
873 : }
874 :
875 1 : else if( EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
876 : {
877 0 : CPLPrintStringFill( szProj, "PS", 16 );
878 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
879 0 : (*ppadfPrjParams)[3] =
880 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
881 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
882 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
883 0 : (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
884 : }
885 :
886 1 : else if( EQUAL(pszProjection, SRS_PT_ROBINSON) )
887 : {
888 0 : CPLPrintStringFill( szProj, "ROB", 16 );
889 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
890 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
891 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
892 : }
893 :
894 1 : else if( EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC) )
895 : {
896 0 : CPLPrintStringFill( szProj, "SG", 16 );
897 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
898 0 : (*ppadfPrjParams)[3] =
899 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
900 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
901 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
902 0 : (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
903 : }
904 :
905 1 : else if( EQUAL(pszProjection, SRS_PT_SINUSOIDAL) )
906 : {
907 0 : CPLPrintStringFill( szProj, "SIN", 16 );
908 0 : (*ppadfPrjParams)[2] =
909 0 : GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 );
910 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
911 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
912 : }
913 :
914 1 : else if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) )
915 : {
916 : int bNorth;
917 1 : int nZone = GetUTMZone( &bNorth );
918 :
919 1 : if( nZone != 0 )
920 : {
921 1 : CPLPrintStringFill( szProj, "UTM", 16 );
922 1 : if( bNorth )
923 0 : CPLPrintInt32( szProj + 5, nZone, 4 );
924 : else
925 1 : CPLPrintInt32( szProj + 5, -nZone, 4 );
926 : }
927 : else
928 : {
929 0 : CPLPrintStringFill( szProj, "TM", 16 );
930 0 : (*ppadfPrjParams)[2] =
931 0 : GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
932 0 : (*ppadfPrjParams)[3] =
933 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
934 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
935 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
936 0 : (*ppadfPrjParams)[8] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
937 : }
938 : }
939 :
940 0 : else if( EQUAL(pszProjection, SRS_PT_VANDERGRINTEN) )
941 : {
942 0 : CPLPrintStringFill( szProj, "VDG", 16 );
943 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
944 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
945 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
946 : }
947 :
948 : // Projection unsupported by PCI
949 : else
950 : {
951 : CPLDebug( "OSR_PCI",
952 : "Projection \"%s\" unsupported by PCI. "
953 0 : "PIXEL value will be used.", pszProjection );
954 0 : CPLPrintStringFill( szProj, "PIXEL", 16 );
955 : }
956 :
957 : /* -------------------------------------------------------------------- */
958 : /* Translate the datum. */
959 : /* -------------------------------------------------------------------- */
960 17 : const char *pszDatum = GetAttrValue( "DATUM" );
961 :
962 17 : if( pszDatum == NULL || strlen(pszDatum) == 0 )
963 : /* do nothing */;
964 17 : else if( EQUAL( pszDatum, SRS_DN_NAD27 ) )
965 1 : CPLPrintStringFill( szProj + 12, "D-01", 4 );
966 :
967 16 : else if( EQUAL( pszDatum, SRS_DN_NAD83 ) )
968 0 : CPLPrintStringFill( szProj + 12, "D-02", 4 );
969 :
970 16 : else if( EQUAL( pszDatum, SRS_DN_WGS84 ) )
971 15 : CPLPrintStringFill( szProj + 12, "D000", 4 );
972 :
973 : // If not found well known datum, translate ellipsoid
974 : else
975 : {
976 1 : double dfSemiMajor = GetSemiMajor();
977 1 : double dfInvFlattening = GetInvFlattening();
978 :
979 1 : const PCIDatums *paoDatum = aoEllips;
980 :
981 : #ifdef DEBUG
982 : CPLDebug( "OSR_PCI",
983 : "Datum \"%s\" unsupported by PCI. "
984 : "Try to translate ellipsoid definition.", pszDatum );
985 : #endif
986 :
987 2 : while ( paoDatum->pszPCIDatum )
988 : {
989 : double dfSM;
990 : double dfIF;
991 :
992 1 : if ( OSRGetEllipsoidInfo( paoDatum->nEPSGCode, NULL,
993 : &dfSM, &dfIF ) == OGRERR_NONE
994 : && CPLIsEqual( dfSemiMajor, dfSM )
995 : && CPLIsEqual( dfInvFlattening, dfIF ) )
996 : {
997 1 : CPLPrintStringFill( szProj + 12, paoDatum->pszPCIDatum, 4 );
998 1 : break;
999 : }
1000 :
1001 0 : paoDatum++;
1002 : }
1003 :
1004 1 : if ( !paoDatum->pszPCIDatum ) // Didn't found matches; set
1005 : { // custom ellipsoid parameters
1006 : #ifdef DEBUG
1007 : CPLDebug( "OSR_PCI",
1008 : "Ellipsoid \"%s\" unsupported by PCI. "
1009 : "Custom PCI ellipsoid will be used.", pszDatum );
1010 : #endif
1011 0 : CPLPrintStringFill( szProj + 12, "E999", 4 );
1012 0 : (*ppadfPrjParams)[0] = dfSemiMajor;
1013 0 : if ( ABS( dfInvFlattening ) < 0.000000000001 )
1014 : {
1015 0 : (*ppadfPrjParams)[1] = dfSemiMajor;
1016 : }
1017 : else
1018 : {
1019 0 : (*ppadfPrjParams)[1] =
1020 0 : dfSemiMajor * (1.0 - 1.0/dfInvFlattening);
1021 : }
1022 : }
1023 : }
1024 :
1025 : /* -------------------------------------------------------------------- */
1026 : /* Translate the linear units. */
1027 : /* -------------------------------------------------------------------- */
1028 : const char *pszUnits;
1029 :
1030 17 : if( EQUALN( szProj, "LONG/LAT", 8 ) )
1031 15 : pszUnits = "DEGREE";
1032 : else
1033 2 : pszUnits = "METRE";
1034 :
1035 : /* -------------------------------------------------------------------- */
1036 : /* Report results. */
1037 : /* -------------------------------------------------------------------- */
1038 17 : szProj[16] = '\0';
1039 17 : *ppszProj = CPLStrdup( szProj );
1040 :
1041 17 : *ppszUnits = CPLStrdup( pszUnits );
1042 :
1043 17 : return OGRERR_NONE;
1044 : }
1045 :
|