1 : /******************************************************************************
2 : * $Id: ogr_srs_pci.cpp 18735 2010-02-05 16:07:10Z 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 18735 2010-02-05 16:07:10Z 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 : OGRErr OSRImportFromPCI( OGRSpatialReferenceH hSRS, const char *pszProj,
143 4 : const char *pszUnits, double *padfPrjParams )
144 :
145 : {
146 4 : VALIDATE_POINTER1( hSRS, "OSRImportFromPCI", CE_Failure );
147 :
148 : return ((OGRSpatialReference *) hSRS)->importFromPCI( pszProj,
149 : pszUnits,
150 4 : 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 : OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
201 : const char *pszUnits,
202 6 : double *padfPrjParams )
203 :
204 : {
205 6 : Clear();
206 :
207 6 : if( pszProj == NULL || CPLStrnlen(pszProj, 16) < 16 )
208 0 : return OGRERR_CORRUPT_DATA;
209 :
210 : #ifdef DEBUG
211 6 : 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 6 : int bProjAllocated = FALSE;
218 :
219 6 : 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 6 : int bIsNAD27 = FALSE;
238 :
239 6 : strcpy( szEarthModel, "" );
240 6 : pszEM = pszProj + strlen(pszProj) - 1;
241 30 : while( pszEM != pszProj )
242 : {
243 24 : if( *pszEM == 'e' || *pszEM == 'E' || *pszEM == 'd' || *pszEM == 'D' )
244 : {
245 6 : int nCode = atoi(pszEM+1);
246 :
247 6 : if( nCode >= -99 && nCode <= 999 )
248 6 : sprintf( szEarthModel, "%c%03d", toupper(*pszEM), nCode );
249 :
250 6 : break;
251 : }
252 :
253 18 : pszEM--;
254 : }
255 :
256 6 : 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 6 : if( EQUALN( pszProj, "LONG/LAT", 8 ) )
270 : {
271 : }
272 :
273 6 : 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 6 : 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 6 : 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 6 : else if( EQUALN( pszProj, "AE", 2 ) )
295 : {
296 : SetAE( padfPrjParams[3], padfPrjParams[2],
297 0 : padfPrjParams[6], padfPrjParams[7] );
298 : }
299 :
300 6 : 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 5 : 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 5 : 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 5 : else if( EQUALN( pszProj, "LAEA", 4 ) )
324 : {
325 : SetLAEA( padfPrjParams[3], padfPrjParams[2],
326 0 : padfPrjParams[6], padfPrjParams[7] );
327 : }
328 :
329 5 : 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 5 : else if( EQUALN( pszProj, "MC", 2 ) )
337 : {
338 : SetMC( padfPrjParams[3], padfPrjParams[2],
339 0 : padfPrjParams[6], padfPrjParams[7] );
340 : }
341 :
342 5 : else if( EQUALN( pszProj, "MER", 3 ) )
343 : {
344 : SetMercator( padfPrjParams[3], padfPrjParams[2],
345 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
346 0 : padfPrjParams[6], padfPrjParams[7] );
347 : }
348 :
349 5 : 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 5 : else if( EQUALN( pszProj, "PC", 2 ) )
358 : {
359 : SetPolyconic( padfPrjParams[3], padfPrjParams[2],
360 0 : padfPrjParams[6], padfPrjParams[7] );
361 : }
362 :
363 5 : else if( EQUALN( pszProj, "PS", 2 ) )
364 : {
365 : SetPS( padfPrjParams[3], padfPrjParams[2],
366 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
367 0 : padfPrjParams[6], padfPrjParams[7] );
368 : }
369 :
370 5 : else if( EQUALN( pszProj, "ROB", 3 ) )
371 : {
372 : SetRobinson( padfPrjParams[2],
373 0 : padfPrjParams[6], padfPrjParams[7] );
374 : }
375 :
376 5 : else if( EQUALN( pszProj, "SG", 2 ) )
377 : {
378 : SetStereographic( padfPrjParams[3], padfPrjParams[2],
379 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
380 0 : padfPrjParams[6], padfPrjParams[7] );
381 : }
382 :
383 5 : 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 5 : 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 5 : 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 5 : 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 5 : else if( EQUALN( pszProj, "TM", 2 ) )
423 : {
424 : SetTM( padfPrjParams[3], padfPrjParams[2],
425 : (padfPrjParams[8] != 0.0) ? padfPrjParams[9] : 1.0,
426 0 : padfPrjParams[6], padfPrjParams[7] );
427 : }
428 :
429 5 : else if( EQUALN( pszProj, "UTM", 3 ) )
430 : {
431 5 : int iZone, bNorth = TRUE;
432 :
433 5 : iZone = CPLScanLong( (char *)pszProj + 4, 5 );;
434 5 : 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 5 : char byZoneID = 0;
443 :
444 5 : if( strlen(pszProj) > 10 && pszProj[10] != ' ' )
445 2 : byZoneID = pszProj[10];
446 :
447 : // Determine if the MGRS zone falls above or below the equator
448 5 : if (byZoneID != 0 )
449 : {
450 : CPLDebug("OSR_PCI", "Found MGRS zone in UTM projection string: %c",
451 2 : byZoneID);
452 :
453 3 : if (byZoneID >= 'N' && byZoneID <= 'X')
454 : {
455 1 : bNorth = TRUE;
456 : }
457 1 : else if (byZoneID >= 'C' && byZoneID <= 'M')
458 : {
459 1 : bNorth = FALSE;
460 : }
461 : else
462 : {
463 : // yikes, most likely we got something that was not really
464 : // an MGRS zone code so we ignore it.
465 : }
466 : }
467 :
468 5 : SetUTM( iZone, bNorth );
469 : }
470 :
471 0 : else if( EQUALN( pszProj, "VDG", 3 ) )
472 : {
473 : SetVDG( padfPrjParams[2],
474 0 : padfPrjParams[6], padfPrjParams[7] );
475 : }
476 :
477 : else
478 : {
479 0 : CPLDebug( "OSR_PCI", "Unsupported projection: %s", pszProj );
480 0 : SetLocalCS( pszProj );
481 : }
482 :
483 : /* ==================================================================== */
484 : /* Translate the datum/spheroid. */
485 : /* ==================================================================== */
486 :
487 : /* -------------------------------------------------------------------- */
488 : /* We have an earthmodel string, look it up in the datum list. */
489 : /* -------------------------------------------------------------------- */
490 6 : if( strlen(szEarthModel) > 0
491 : && (poRoot == NULL || IsProjected() || IsGeographic()) )
492 : {
493 6 : const PCIDatums *paoDatum = aoDatums;
494 :
495 : // Search for matching datum
496 159 : while ( paoDatum->pszPCIDatum )
497 : {
498 150 : if( EQUALN( szEarthModel, paoDatum->pszPCIDatum, 4 ) )
499 : {
500 3 : OGRSpatialReference oGCS;
501 3 : oGCS.importFromEPSG( paoDatum->nEPSGCode );
502 3 : CopyGeogCSFrom( &oGCS );
503 3 : break;
504 : }
505 147 : paoDatum++;
506 : }
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* If not, look in the ellipsoid list. */
510 : /* -------------------------------------------------------------------- */
511 6 : if ( !paoDatum->pszPCIDatum ) // No matching; search for ellipsoids
512 : {
513 3 : paoDatum = aoEllips;
514 :
515 : #ifdef DEBUG
516 : CPLDebug( "OSR_PCI",
517 : "Cannot found matching datum definition, "
518 3 : "search for ellipsoids." );
519 : #endif
520 :
521 21 : while ( paoDatum->pszPCIDatum )
522 : {
523 18 : if( EQUALN( szEarthModel, paoDatum->pszPCIDatum, 4 )
524 : && paoDatum->nEPSGCode != 0 )
525 : {
526 3 : char *pszName = NULL;
527 : double dfSemiMajor;
528 : double dfInvFlattening;
529 :
530 3 : if ( OSRGetEllipsoidInfo( paoDatum->nEPSGCode, &pszName,
531 : &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE )
532 : {
533 : SetGeogCS( CPLString().Printf(
534 : "Unknown datum based upon the %s ellipsoid",
535 : pszName ),
536 : CPLString().Printf(
537 : "Not specified (based on %s spheroid)",
538 : pszName ),
539 : pszName, dfSemiMajor, dfInvFlattening,
540 3 : NULL, 0.0, NULL, 0.0 );
541 3 : SetAuthority( "SPHEROID", "EPSG", paoDatum->nEPSGCode );
542 :
543 3 : if ( pszName )
544 3 : CPLFree( pszName );
545 : }
546 :
547 3 : break;
548 : }
549 15 : else if( EQUALN( szEarthModel, paoDatum->pszPCIDatum, 4 ) )
550 : {
551 : double dfInvFlattening;
552 :
553 0 : if ( CPLIsEqual(paoDatum->dfSemiMajor, paoDatum->dfSemiMinor) )
554 0 : dfInvFlattening = 0.0;
555 : else
556 : dfInvFlattening = paoDatum->dfSemiMajor
557 0 : / (paoDatum->dfSemiMajor-paoDatum->dfSemiMinor);
558 :
559 : SetGeogCS( "Unknown datum based upon the custom spheroid",
560 : "Not specified (based on custom spheroid)",
561 : CPLString().Printf( "PCI Ellipse %s",
562 : szEarthModel),
563 : paoDatum->dfSemiMajor, dfInvFlattening,
564 0 : NULL, 0, NULL, 0 );
565 0 : break;
566 : }
567 15 : paoDatum++;
568 : }
569 : }
570 :
571 : /* -------------------------------------------------------------------- */
572 : /* Custom spheroid. */
573 : /* -------------------------------------------------------------------- */
574 6 : if ( !paoDatum->pszPCIDatum ) // Didn't found matches
575 : {
576 : #ifdef DEBUG
577 : CPLDebug( "OSR_PCI",
578 0 : "Cannot found matching ellipsoid definition." );
579 : #endif
580 :
581 0 : if( EQUALN( pszProj + 12, "E999", 4 )
582 : || padfPrjParams[0] != 0.0 )
583 : {
584 : double dfInvFlattening;
585 :
586 0 : if( ABS(padfPrjParams[0] - padfPrjParams[1]) < 0.01 )
587 : {
588 0 : dfInvFlattening = 0.0;
589 : }
590 : else
591 : {
592 : dfInvFlattening =
593 0 : padfPrjParams[0]/(padfPrjParams[0]-padfPrjParams[1]);
594 : }
595 :
596 : SetGeogCS( "Unknown datum based upon the custom spheroid",
597 : "Not specified (based on custom spheroid)",
598 : "Custom spheroid",
599 : padfPrjParams[0], dfInvFlattening,
600 0 : NULL, 0, NULL, 0 );
601 : }
602 : else
603 : {
604 : // If we don't know, default to WGS84
605 : // so there is something there.
606 0 : SetWellKnownGeogCS( "WGS84" );
607 : #ifdef DEBUG
608 0 : CPLDebug( "OSR_PCI", "Setting WGS84 as a fallback." );
609 : #endif
610 :
611 : }
612 : }
613 : }
614 :
615 : /* -------------------------------------------------------------------- */
616 : /* Grid units translation */
617 : /* -------------------------------------------------------------------- */
618 6 : if( (IsLocal() || IsProjected()) && pszUnits )
619 : {
620 4 : if( EQUAL( pszUnits, "METRE" ) )
621 4 : SetLinearUnits( SRS_UL_METER, 1.0 );
622 0 : else if( EQUAL( pszUnits, "DEGREE" ) )
623 0 : SetAngularUnits( SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV) );
624 : else
625 0 : SetLinearUnits( SRS_UL_METER, 1.0 );
626 : }
627 :
628 6 : FixupOrdering();
629 :
630 6 : if ( bProjAllocated && padfPrjParams )
631 0 : CPLFree( padfPrjParams );
632 :
633 6 : return OGRERR_NONE;
634 : }
635 :
636 : /************************************************************************/
637 : /* OSRExportToPCI() */
638 : /************************************************************************/
639 : /**
640 : * \brief Export coordinate system in PCI projection definition.
641 : *
642 : * This function is the same as OGRSpatialReference::exportToPCI().
643 : */
644 : OGRErr OSRExportToPCI( OGRSpatialReferenceH hSRS,
645 : char **ppszProj, char **ppszUnits,
646 1 : double **ppadfPrjParams )
647 :
648 : {
649 1 : VALIDATE_POINTER1( hSRS, "OSRExportToPCI", CE_Failure );
650 :
651 1 : *ppszProj = NULL;
652 1 : *ppszUnits = NULL;
653 1 : *ppadfPrjParams = NULL;
654 :
655 : return ((OGRSpatialReference *) hSRS)->exportToPCI( ppszProj, ppszUnits,
656 1 : ppadfPrjParams );
657 : }
658 :
659 : /************************************************************************/
660 : /* exportToPCI() */
661 : /************************************************************************/
662 :
663 : /**
664 : * \brief Export coordinate system in PCI projection definition.
665 : *
666 : * Converts the loaded coordinate reference system into PCI projection
667 : * definition to the extent possible. The strings returned in ppszProj,
668 : * ppszUnits and ppadfPrjParams array should be deallocated by the caller
669 : * with CPLFree() when no longer needed.
670 : *
671 : * LOCAL_CS coordinate systems are not translatable. An empty string
672 : * will be returned along with OGRERR_NONE.
673 : *
674 : * This method is the equivelent of the C function OSRExportToPCI().
675 : *
676 : * @param ppszProj pointer to which dynamically allocated PCI projection
677 : * definition will be assigned.
678 : *
679 : * @param ppszUnits pointer to which dynamically allocated units definition
680 : * will be assigned.
681 : *
682 : * @param ppadfPrjParams pointer to which dynamically allocated array of
683 : * 17 projection parameters will be assigned. See importFromPCI() for the list
684 : * of parameters.
685 : *
686 : * @return OGRERR_NONE on success or an error code on failure.
687 : */
688 :
689 : OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
690 43 : double **ppadfPrjParams ) const
691 :
692 : {
693 43 : const char *pszProjection = GetAttrValue("PROJECTION");
694 :
695 : /* -------------------------------------------------------------------- */
696 : /* Fill all projection parameters with zero. */
697 : /* -------------------------------------------------------------------- */
698 : int i;
699 :
700 43 : *ppadfPrjParams = (double *)CPLMalloc( 17 * sizeof(double) );
701 774 : for ( i = 0; i < 17; i++ )
702 731 : (*ppadfPrjParams)[i] = 0.0;
703 :
704 : /* -------------------------------------------------------------------- */
705 : /* Get the prime meridian info. */
706 : /* -------------------------------------------------------------------- */
707 43 : const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
708 43 : double dfFromGreenwich = 0.0;
709 :
710 43 : if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2
711 : && atof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
712 : {
713 0 : dfFromGreenwich = atof(poPRIMEM->GetChild(1)->GetValue());
714 : }
715 :
716 : /* ==================================================================== */
717 : /* Handle the projection definition. */
718 : /* ==================================================================== */
719 : char szProj[17];
720 :
721 43 : if( IsLocal() )
722 : {
723 0 : if( GetLinearUnits() > 0.30479999 && GetLinearUnits() < 0.3048010 )
724 0 : CPLPrintStringFill( szProj, "FEET", 17 );
725 : else
726 0 : CPLPrintStringFill( szProj, "METER", 17 );
727 : }
728 :
729 43 : else if( pszProjection == NULL )
730 : {
731 : #ifdef DEBUG
732 : CPLDebug( "OSR_PCI",
733 41 : "Empty projection definition, considered as LONG/LAT" );
734 : #endif
735 41 : CPLPrintStringFill( szProj, "LONG/LAT", 17 );
736 : }
737 :
738 2 : else if( EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
739 : {
740 0 : CPLPrintStringFill( szProj, "ACEA", 16 );
741 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
742 : (*ppadfPrjParams)[3] =
743 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
744 : (*ppadfPrjParams)[4] =
745 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
746 : (*ppadfPrjParams)[5] =
747 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
748 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
749 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
750 : }
751 :
752 2 : else if( EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT) )
753 : {
754 0 : CPLPrintStringFill( szProj, "AE", 16 );
755 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
756 : (*ppadfPrjParams)[3] =
757 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
758 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
759 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
760 : }
761 :
762 2 : else if( EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC) )
763 : {
764 0 : CPLPrintStringFill( szProj, "EC", 16 );
765 : (*ppadfPrjParams)[2] =
766 0 : GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 );
767 : (*ppadfPrjParams)[3] =
768 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 );
769 : (*ppadfPrjParams)[4] =
770 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
771 : (*ppadfPrjParams)[5] =
772 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
773 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
774 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
775 : }
776 :
777 2 : else if( EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR) )
778 : {
779 0 : CPLPrintStringFill( szProj, "ER", 16 );
780 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
781 : (*ppadfPrjParams)[3] =
782 0 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
783 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
784 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
785 : }
786 :
787 2 : else if( EQUAL(pszProjection, SRS_PT_GNOMONIC) )
788 : {
789 0 : CPLPrintStringFill( szProj, "GNO", 16 );
790 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
791 : (*ppadfPrjParams)[3] =
792 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
793 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
794 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
795 : }
796 :
797 2 : else if( EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
798 : {
799 0 : CPLPrintStringFill( szProj, "LAEA", 16 );
800 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
801 : (*ppadfPrjParams)[3] =
802 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
803 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
804 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
805 : }
806 :
807 2 : else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
808 : {
809 1 : CPLPrintStringFill( szProj, "LCC", 16 );
810 1 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
811 : (*ppadfPrjParams)[3] =
812 1 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
813 : (*ppadfPrjParams)[4] =
814 1 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
815 : (*ppadfPrjParams)[5] =
816 1 : GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
817 1 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
818 1 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
819 : }
820 :
821 1 : else if( EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL) )
822 : {
823 0 : CPLPrintStringFill( szProj, "MC", 16 );
824 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
825 : (*ppadfPrjParams)[3] =
826 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
827 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
828 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
829 : }
830 :
831 1 : else if( EQUAL(pszProjection, SRS_PT_MERCATOR_1SP) )
832 : {
833 0 : CPLPrintStringFill( szProj, "MER", 16 );
834 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
835 : (*ppadfPrjParams)[3] =
836 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
837 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
838 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
839 0 : (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
840 : }
841 :
842 1 : else if( EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC) )
843 : {
844 0 : CPLPrintStringFill( szProj, "OG", 16 );
845 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
846 : (*ppadfPrjParams)[3] =
847 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
848 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
849 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
850 : }
851 :
852 1 : else if( EQUAL(pszProjection, SRS_PT_POLYCONIC) )
853 : {
854 0 : CPLPrintStringFill( szProj, "PC", 16 );
855 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
856 : (*ppadfPrjParams)[3] =
857 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
858 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
859 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
860 : }
861 :
862 1 : else if( EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
863 : {
864 0 : CPLPrintStringFill( szProj, "PS", 16 );
865 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
866 : (*ppadfPrjParams)[3] =
867 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
868 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
869 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
870 0 : (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
871 : }
872 :
873 1 : else if( EQUAL(pszProjection, SRS_PT_ROBINSON) )
874 : {
875 0 : CPLPrintStringFill( szProj, "ROB", 16 );
876 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
877 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
878 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
879 : }
880 :
881 1 : else if( EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC) )
882 : {
883 0 : CPLPrintStringFill( szProj, "SG", 16 );
884 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
885 : (*ppadfPrjParams)[3] =
886 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
887 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
888 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
889 0 : (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
890 : }
891 :
892 1 : else if( EQUAL(pszProjection, SRS_PT_SINUSOIDAL) )
893 : {
894 0 : CPLPrintStringFill( szProj, "SIN", 16 );
895 : (*ppadfPrjParams)[2] =
896 0 : GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 );
897 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
898 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
899 : }
900 :
901 1 : else if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) )
902 : {
903 : int bNorth;
904 1 : int nZone = GetUTMZone( &bNorth );
905 :
906 1 : if( nZone != 0 )
907 : {
908 1 : CPLPrintStringFill( szProj, "UTM", 16 );
909 1 : if( bNorth )
910 1 : CPLPrintInt32( szProj + 5, nZone, 4 );
911 : else
912 0 : CPLPrintInt32( szProj + 5, -nZone, 4 );
913 : }
914 : else
915 : {
916 0 : CPLPrintStringFill( szProj, "TM", 16 );
917 : (*ppadfPrjParams)[2] =
918 0 : GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
919 : (*ppadfPrjParams)[3] =
920 0 : GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
921 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
922 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
923 0 : (*ppadfPrjParams)[8] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
924 : }
925 : }
926 :
927 0 : else if( EQUAL(pszProjection, SRS_PT_VANDERGRINTEN) )
928 : {
929 0 : CPLPrintStringFill( szProj, "VDG", 16 );
930 0 : (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
931 0 : (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
932 0 : (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
933 : }
934 :
935 : // Projection unsupported by PCI
936 : else
937 : {
938 : CPLDebug( "OSR_PCI",
939 : "Projection \"%s\" unsupported by PCI. "
940 0 : "PIXEL value will be used.", pszProjection );
941 0 : CPLPrintStringFill( szProj, "PIXEL", 16 );
942 : }
943 :
944 : /* -------------------------------------------------------------------- */
945 : /* Translate the datum. */
946 : /* -------------------------------------------------------------------- */
947 43 : const char *pszDatum = GetAttrValue( "DATUM" );
948 :
949 43 : if( pszDatum == NULL || strlen(pszDatum) == 0 )
950 : /* do nothing */;
951 43 : else if( EQUAL( pszDatum, SRS_DN_NAD27 ) )
952 1 : CPLPrintStringFill( szProj + 12, "D-01", 4 );
953 :
954 42 : else if( EQUAL( pszDatum, SRS_DN_NAD83 ) )
955 0 : CPLPrintStringFill( szProj + 12, "D-02", 4 );
956 :
957 42 : else if( EQUAL( pszDatum, SRS_DN_WGS84 ) )
958 41 : CPLPrintStringFill( szProj + 12, "D000", 4 );
959 :
960 : // If not found well known datum, translate ellipsoid
961 : else
962 : {
963 1 : double dfSemiMajor = GetSemiMajor();
964 1 : double dfInvFlattening = GetInvFlattening();
965 :
966 1 : const PCIDatums *paoDatum = aoEllips;
967 :
968 : #ifdef DEBUG
969 : CPLDebug( "OSR_PCI",
970 : "Datum \"%s\" unsupported by PCI. "
971 1 : "Try to translate ellipsoid definition.", pszDatum );
972 : #endif
973 :
974 2 : while ( paoDatum->pszPCIDatum )
975 : {
976 : double dfSM;
977 : double dfIF;
978 :
979 1 : if ( OSRGetEllipsoidInfo( paoDatum->nEPSGCode, NULL,
980 : &dfSM, &dfIF ) == OGRERR_NONE
981 : && CPLIsEqual( dfSemiMajor, dfSM )
982 : && CPLIsEqual( dfInvFlattening, dfIF ) )
983 : {
984 1 : CPLPrintStringFill( szProj + 12, paoDatum->pszPCIDatum, 4 );
985 1 : break;
986 : }
987 :
988 0 : paoDatum++;
989 : }
990 :
991 1 : if ( !paoDatum->pszPCIDatum ) // Didn't found matches; set
992 : { // custom ellipsoid parameters
993 : #ifdef DEBUG
994 : CPLDebug( "OSR_PCI",
995 : "Ellipsoid \"%s\" unsupported by PCI. "
996 0 : "Custom PCI ellipsoid will be used.", pszDatum );
997 : #endif
998 0 : CPLPrintStringFill( szProj + 12, "E999", 4 );
999 0 : (*ppadfPrjParams)[0] = dfSemiMajor;
1000 0 : if ( ABS( dfInvFlattening ) < 0.000000000001 )
1001 : {
1002 0 : (*ppadfPrjParams)[1] = dfSemiMajor;
1003 : }
1004 : else
1005 : {
1006 : (*ppadfPrjParams)[1] =
1007 0 : dfSemiMajor * (1.0 - 1.0/dfInvFlattening);
1008 : }
1009 : }
1010 : }
1011 :
1012 : /* -------------------------------------------------------------------- */
1013 : /* Translate the linear units. */
1014 : /* -------------------------------------------------------------------- */
1015 : const char *pszUnits;
1016 :
1017 43 : if( EQUALN( szProj, "LONG/LAT", 8 ) )
1018 41 : pszUnits = "DEGREE";
1019 : else
1020 2 : pszUnits = "METRE";
1021 :
1022 : /* -------------------------------------------------------------------- */
1023 : /* Report results. */
1024 : /* -------------------------------------------------------------------- */
1025 43 : szProj[16] = '\0';
1026 43 : *ppszProj = CPLStrdup( szProj );
1027 :
1028 43 : *ppszUnits = CPLStrdup( pszUnits );
1029 :
1030 43 : return OGRERR_NONE;
1031 : }
1032 :
|