1 : /******************************************************************************
2 : * $Id: gxf_ogcwkt.c 25164 2012-10-20 13:42:32Z rouault $
3 : *
4 : * Project: GXF Reader
5 : * Purpose: Handle GXF to OGC WKT projection transformation.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gxfopen.h"
31 :
32 : CPL_CVSID("$Id: gxf_ogcwkt.c 25164 2012-10-20 13:42:32Z rouault $");
33 :
34 : /* -------------------------------------------------------------------- */
35 : /* the following #defines come from ogr_spatialref.h in the GDAL/OGR */
36 : /* distribution (see http://gdal.velocet.ca/projects/opengis) and */
37 : /* should be kept in sync with that file. */
38 : /* -------------------------------------------------------------------- */
39 :
40 : #define SRS_PT_ALBERS_CONIC_EQUAL_AREA \
41 : "Albers_Conic_Equal_Area"
42 : #define SRS_PT_AZIMUTHAL_EQUIDISTANT "Azimuthal_Equidistant"
43 : #define SRS_PT_CASSINI_SOLDNER "Cassini_Soldner"
44 : #define SRS_PT_CYLINDRICAL_EQUAL_AREA "Cylindrical_Equal_Area"
45 : #define SRS_PT_ECKERT_IV "Eckert_IV"
46 : #define SRS_PT_ECKERT_VI "Eckert_VI"
47 : #define SRS_PT_EQUIDISTANT_CONIC "Equidistant_Conic"
48 : #define SRS_PT_EQUIRECTANGULAR "Equirectangular"
49 : #define SRS_PT_GALL_STEREOGRAPHIC "Gall_Stereographic"
50 : #define SRS_PT_GNOMONIC "Gnomonic"
51 : #define SRS_PT_HOTINE_OBLIQUE_MERCATOR \
52 : "Hotine_Oblique_Mercator"
53 : #define SRS_PT_LABORDE_OBLIQUE_MERCATOR \
54 : "Laborde_Oblique_Mercator"
55 : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP \
56 : "Lambert_Conformal_Conic_1SP"
57 : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP \
58 : "Lambert_Conformal_Conic_2SP"
59 : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM \
60 : "Lambert_Conformal_Conic_2SP_Belgium"
61 : #define SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA \
62 : "Lambert_Azimuthal_Equal_Area"
63 : #define SRS_PT_MERCATOR_1SP "Mercator_1SP"
64 : #define SRS_PT_MERCATOR_2SP "Mercator_2SP"
65 : #define SRS_PT_MILLER_CYLINDRICAL "Miller_Cylindrical"
66 : #define SRS_PT_MOLLWEIDE "Mollweide"
67 : #define SRS_PT_NEW_ZEALAND_MAP_GRID \
68 : "New_Zealand_Map_Grid"
69 : #define SRS_PT_OBLIQUE_STEREOGRAPHIC \
70 : "Oblique_Stereographic"
71 : #define SRS_PT_ORTHOGRAPHIC "Orthographic"
72 : #define SRS_PT_POLAR_STEREOGRAPHIC \
73 : "Polar_Stereographic"
74 : #define SRS_PT_POLYCONIC "Polyconic"
75 : #define SRS_PT_ROBINSON "Robinson"
76 : #define SRS_PT_SINUSOIDAL "Sinusoidal"
77 : #define SRS_PT_STEREOGRAPHIC "Stereographic"
78 : #define SRS_PT_SWISS_OBLIQUE_CYLINDRICAL \
79 : "Swiss_Oblique_Cylindrical"
80 : #define SRS_PT_TRANSVERSE_MERCATOR \
81 : "Transverse_Mercator"
82 : #define SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED \
83 : "Transverse_Mercator_South_Orientated"
84 : #define SRS_PT_TUNISIA_MINING_GRID \
85 : "Tunisia_Mining_Grid"
86 : #define SRS_PT_VANDERGRINTEN "VanDerGrinten"
87 :
88 : #define SRS_PP_CENTRAL_MERIDIAN "central_meridian"
89 : #define SRS_PP_SCALE_FACTOR "scale_factor"
90 : #define SRS_PP_STANDARD_PARALLEL_1 "standard_parallel_1"
91 : #define SRS_PP_STANDARD_PARALLEL_2 "standard_parallel_2"
92 : #define SRS_PP_LONGITUDE_OF_CENTER "longitude_of_center"
93 : #define SRS_PP_LATITUDE_OF_CENTER "latitude_of_center"
94 : #define SRS_PP_LONGITUDE_OF_ORIGIN "longitude_of_origin"
95 : #define SRS_PP_LATITUDE_OF_ORIGIN "latitude_of_origin"
96 : #define SRS_PP_FALSE_EASTING "false_easting"
97 : #define SRS_PP_FALSE_NORTHING "false_northing"
98 : #define SRS_PP_AZIMUTH "azimuth"
99 : #define SRS_PP_LONGITUDE_OF_POINT_1 "longitude_of_point_1"
100 : #define SRS_PP_LATITUDE_OF_POINT_1 "latitude_of_point_1"
101 : #define SRS_PP_LONGITUDE_OF_POINT_2 "longitude_of_point_2"
102 : #define SRS_PP_LATITUDE_OF_POINT_2 "latitude_of_point_2"
103 : #define SRS_PP_LONGITUDE_OF_POINT_3 "longitude_of_point_3"
104 : #define SRS_PP_LATITUDE_OF_POINT_3 "latitude_of_point_3"
105 : #define SRS_PP_RECTIFIED_GRID_ANGLE "rectified_grid_angle"
106 :
107 : /* -------------------------------------------------------------------- */
108 : /* This table was copied from gt_wkt_srs.cpp in the libgeotiff */
109 : /* distribution. Please keep changes in sync. */
110 : /* -------------------------------------------------------------------- */
111 : static char *papszDatumEquiv[] =
112 : {
113 : "Militar_Geographische_Institut",
114 : "Militar_Geographische_Institute",
115 : "World_Geodetic_System_1984",
116 : "WGS_1984",
117 : "WGS_72_Transit_Broadcast_Ephemeris",
118 : "WGS_1972_Transit_Broadcast_Ephemeris",
119 : "World_Geodetic_System_1972",
120 : "WGS_1972",
121 : "European_Terrestrial_Reference_System_89",
122 : "European_Reference_System_1989",
123 : NULL
124 : };
125 :
126 : /************************************************************************/
127 : /* WKTMassageDatum() */
128 : /* */
129 : /* Massage an EPSG datum name into WMT format. Also transform */
130 : /* specific exception cases into WKT versions. */
131 : /* */
132 : /* This function was copied from the gt_wkt_srs.cpp file in the */
133 : /* libgeotiff distribution. Please keep changes in sync. */
134 : /************************************************************************/
135 :
136 6 : static void WKTMassageDatum( char ** ppszDatum )
137 :
138 : {
139 : int i, j;
140 : char *pszDatum;
141 :
142 6 : pszDatum = *ppszDatum;
143 6 : if (pszDatum[0] == '\0')
144 0 : return;
145 :
146 : /* -------------------------------------------------------------------- */
147 : /* Translate non-alphanumeric values to underscores. */
148 : /* -------------------------------------------------------------------- */
149 51 : for( i = 0; pszDatum[i] != '\0'; i++ )
150 : {
151 184 : if( pszDatum[i] != '+'
152 63 : && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
153 27 : && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
154 49 : && !(pszDatum[i] >= '0' && pszDatum[i] <= '9') )
155 : {
156 5 : pszDatum[i] = '_';
157 : }
158 : }
159 :
160 : /* -------------------------------------------------------------------- */
161 : /* Remove repeated and trailing underscores. */
162 : /* -------------------------------------------------------------------- */
163 45 : for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
164 : {
165 39 : if( pszDatum[j] == '_' && pszDatum[i] == '_' )
166 0 : continue;
167 :
168 39 : pszDatum[++j] = pszDatum[i];
169 : }
170 6 : if( pszDatum[j] == '_' )
171 0 : pszDatum[j] = '\0';
172 : else
173 6 : pszDatum[j+1] = '\0';
174 :
175 : /* -------------------------------------------------------------------- */
176 : /* Search for datum equivelences. Specific massaged names get */
177 : /* mapped to OpenGIS specified names. */
178 : /* -------------------------------------------------------------------- */
179 36 : for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
180 : {
181 30 : if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
182 : {
183 0 : CPLFree( *ppszDatum );
184 0 : *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
185 0 : return;
186 : }
187 : }
188 : }
189 :
190 : /************************************************************************/
191 : /* OGCWKTSetProj() */
192 : /************************************************************************/
193 :
194 5 : static void OGCWKTSetProj( char * pszProjection, char ** papszMethods,
195 : const char * pszTransformName,
196 : const char * pszParm1,
197 : const char * pszParm2,
198 : const char * pszParm3,
199 : const char * pszParm4,
200 : const char * pszParm5,
201 : const char * pszParm6,
202 : const char * pszParm7 )
203 :
204 : {
205 5 : int iParm, nCount = CSLCount(papszMethods);
206 : const char *apszParmNames[8];
207 :
208 5 : apszParmNames[0] = pszParm1;
209 5 : apszParmNames[1] = pszParm2;
210 5 : apszParmNames[2] = pszParm3;
211 5 : apszParmNames[3] = pszParm4;
212 5 : apszParmNames[4] = pszParm5;
213 5 : apszParmNames[5] = pszParm6;
214 5 : apszParmNames[6] = pszParm7;
215 5 : apszParmNames[7] = NULL;
216 :
217 5 : sprintf( pszProjection,
218 : "PROJECTION[\"%s\"]",
219 : pszTransformName );
220 :
221 30 : for( iParm = 0; iParm < nCount-1 && apszParmNames[iParm] != NULL; iParm++ )
222 : {
223 25 : sprintf( pszProjection + strlen(pszProjection),
224 : ",PARAMETER[\"%s\",%s]",
225 : apszParmNames[iParm],
226 25 : papszMethods[iParm+1] );
227 : }
228 5 : }
229 :
230 :
231 : /************************************************************************/
232 : /* GXFGetMapProjectionAsOGCWKT() */
233 : /************************************************************************/
234 :
235 : /**
236 : * Return the GXF Projection in OpenGIS Well Known Text format.
237 : *
238 : * The returned string becomes owned by the caller, and should be freed
239 : * with CPLFree() or VSIFree(). The return value will be "" if
240 : * no projection information is passed.
241 : *
242 : * The mapping of GXF projections to OGC WKT format is not complete. Please
243 : * see the gxf_ogcwkt.c code to better understand limitations of this
244 : * translation. More information about OGC WKT format can be found in
245 : * the OpenGIS Simple Features specification for OLEDB/COM found on the
246 : * OpenGIS web site at <a href="http://www.opengis.org/">www.opengis.org</a>.
247 : * The translation uses some code cribbed from the OGR library, about which
248 : * more can be learned from <a href="http://gdal.velocet.ca/projects/opengis/">
249 : * http://gdal.velocet.ca/projects/opengis/</a>.
250 : *
251 : * For example, the following GXF definitions:
252 : * <pre>
253 : * #UNIT_LENGTH
254 : * m,1
255 : * #MAP_PROJECTION
256 : * "NAD83 / UTM zone 19N"
257 : * "GRS 1980",6378137,0.081819191,0
258 : * "Transverse Mercator",0,-69,0.9996,500000,0
259 : * </pre>
260 : *
261 : * Would translate to (without the nice formatting):
262 : * <pre>
263 : PROJCS["NAD83 / UTM zone 19N",
264 : GEOGCS["GRS 1980",
265 : DATUM["GRS_1980",
266 : SPHEROID["GRS 1980",6378137,298.257222413684]],
267 : PRIMEM["unnamed",0],
268 : UNIT["degree",0.0174532925199433]],
269 : PROJECTION["Transverse_Mercator"],
270 : PARAMETER["latitude_of_origin",0],
271 : PARAMETER["central_meridian",-69],
272 : PARAMETER["scale_factor",0.9996],
273 : PARAMETER["false_easting",500000],
274 : PARAMETER["false_northing",0],
275 : UNIT["m",1]]
276 : * </pre>
277 : *
278 : * @param hGXF handle to GXF file, as returned by GXFOpen().
279 : *
280 : * @return string containing OGC WKT projection.
281 : */
282 :
283 8 : char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
284 :
285 : {
286 8 : GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
287 8 : char **papszMethods = NULL;
288 : char szWKT[1024];
289 : char szGCS[512];
290 : char szProjection[512];
291 :
292 : /* -------------------------------------------------------------------- */
293 : /* If there was nothing in the file return "unknown". */
294 : /* -------------------------------------------------------------------- */
295 8 : if( CSLCount(psGXF->papszMapProjection) < 2 )
296 2 : return( CPLStrdup( "" ) );
297 :
298 6 : strcpy( szWKT, "" );
299 6 : strcpy( szGCS, "" );
300 6 : strcpy( szProjection, "" );
301 :
302 : /* -------------------------------------------------------------------- */
303 : /* Parse the third line, looking for known projection methods. */
304 : /* -------------------------------------------------------------------- */
305 6 : if( psGXF->papszMapProjection[2] != NULL )
306 : {
307 : /* We allow more than 80 characters if the projection parameters */
308 : /* are on 2 lines as allowed by GXF 3 */
309 6 : if( strlen(psGXF->papszMapProjection[2]) > 120 )
310 0 : return( CPLStrdup( "" ) );
311 6 : papszMethods = CSLTokenizeStringComplex(psGXF->papszMapProjection[2],
312 : ",", TRUE, TRUE );
313 : }
314 :
315 : #ifdef DBMALLOC
316 : malloc_chain_check(1);
317 : #endif
318 :
319 : /* -------------------------------------------------------------------- */
320 : /* Create the PROJCS. */
321 : /* -------------------------------------------------------------------- */
322 17 : if( papszMethods == NULL
323 6 : || papszMethods[0] == NULL
324 5 : || EQUAL(papszMethods[0],"Geographic") )
325 : {
326 : /* do nothing */
327 : }
328 :
329 5 : else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (1SP)") )
330 : {
331 0 : OGCWKTSetProj( szProjection, papszMethods,
332 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
333 : SRS_PP_LATITUDE_OF_ORIGIN,
334 : SRS_PP_CENTRAL_MERIDIAN,
335 : SRS_PP_SCALE_FACTOR,
336 : SRS_PP_FALSE_EASTING,
337 : SRS_PP_FALSE_NORTHING,
338 : NULL,
339 : NULL );
340 : }
341 :
342 5 : else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (2SP)") )
343 : {
344 2 : OGCWKTSetProj( szProjection, papszMethods,
345 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
346 : SRS_PP_STANDARD_PARALLEL_1,
347 : SRS_PP_STANDARD_PARALLEL_2,
348 : SRS_PP_LATITUDE_OF_ORIGIN,
349 : SRS_PP_CENTRAL_MERIDIAN,
350 : SRS_PP_FALSE_EASTING,
351 : SRS_PP_FALSE_NORTHING,
352 : NULL );
353 : }
354 :
355 3 : else if( EQUAL(papszMethods[0],"Lambert Conformal (2SP Belgium)") )
356 : {
357 0 : OGCWKTSetProj( szProjection, papszMethods,
358 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
359 : SRS_PP_STANDARD_PARALLEL_1,
360 : SRS_PP_STANDARD_PARALLEL_2,
361 : SRS_PP_LATITUDE_OF_ORIGIN,
362 : SRS_PP_CENTRAL_MERIDIAN,
363 : SRS_PP_FALSE_EASTING,
364 : SRS_PP_FALSE_NORTHING,
365 : NULL );
366 : }
367 :
368 3 : else if( EQUAL(papszMethods[0],"Mercator (1SP)"))
369 : {
370 0 : OGCWKTSetProj( szProjection, papszMethods,
371 : SRS_PT_MERCATOR_1SP,
372 : SRS_PP_LATITUDE_OF_ORIGIN,
373 : SRS_PP_CENTRAL_MERIDIAN,
374 : SRS_PP_SCALE_FACTOR,
375 : SRS_PP_FALSE_EASTING,
376 : SRS_PP_FALSE_NORTHING,
377 : NULL,
378 : NULL );
379 : }
380 :
381 3 : else if( EQUAL(papszMethods[0],"Mercator (2SP)"))
382 : {
383 0 : OGCWKTSetProj( szProjection, papszMethods,
384 : SRS_PT_MERCATOR_2SP,
385 : SRS_PP_LATITUDE_OF_ORIGIN,/* should it be StdParalle1?*/
386 : SRS_PP_CENTRAL_MERIDIAN,
387 : SRS_PP_FALSE_EASTING,
388 : SRS_PP_FALSE_NORTHING,
389 : NULL,
390 : NULL,
391 : NULL );
392 : }
393 :
394 3 : else if( EQUAL(papszMethods[0],"Laborde Oblique Mercator") )
395 : {
396 0 : OGCWKTSetProj( szProjection, papszMethods,
397 : SRS_PT_LABORDE_OBLIQUE_MERCATOR,
398 : SRS_PP_LATITUDE_OF_CENTER,
399 : SRS_PP_LONGITUDE_OF_CENTER,
400 : SRS_PP_AZIMUTH,
401 : SRS_PP_SCALE_FACTOR,
402 : SRS_PP_FALSE_EASTING,
403 : SRS_PP_FALSE_NORTHING,
404 : NULL );
405 :
406 : }
407 :
408 3 : else if( EQUAL(papszMethods[0],"Hotine Oblique Mercator") )
409 : {
410 0 : OGCWKTSetProj( szProjection, papszMethods,
411 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
412 : SRS_PP_LATITUDE_OF_CENTER,
413 : SRS_PP_LONGITUDE_OF_CENTER,
414 : SRS_PP_AZIMUTH,
415 : SRS_PP_RECTIFIED_GRID_ANGLE,
416 : SRS_PP_SCALE_FACTOR, /* not in normal formulation */
417 : SRS_PP_FALSE_EASTING,
418 : SRS_PP_FALSE_NORTHING );
419 : }
420 :
421 3 : else if( EQUAL(papszMethods[0],"New Zealand Map Grid") )
422 :
423 : {
424 0 : OGCWKTSetProj( szProjection, papszMethods,
425 : SRS_PT_NEW_ZEALAND_MAP_GRID,
426 : SRS_PP_LATITUDE_OF_ORIGIN,
427 : SRS_PP_CENTRAL_MERIDIAN,
428 : SRS_PP_FALSE_EASTING,
429 : SRS_PP_FALSE_NORTHING,
430 : NULL,
431 : NULL,
432 : NULL );
433 : }
434 :
435 3 : else if( EQUAL(papszMethods[0],"Oblique Stereographic") )
436 : {
437 0 : OGCWKTSetProj( szProjection, papszMethods,
438 : SRS_PT_OBLIQUE_STEREOGRAPHIC,
439 : SRS_PP_LATITUDE_OF_ORIGIN,
440 : SRS_PP_CENTRAL_MERIDIAN,
441 : SRS_PP_SCALE_FACTOR,
442 : SRS_PP_FALSE_EASTING,
443 : SRS_PP_FALSE_NORTHING,
444 : NULL,
445 : NULL );
446 : }
447 :
448 3 : else if( EQUAL(papszMethods[0],"Polar Stereographic") )
449 : {
450 0 : OGCWKTSetProj( szProjection, papszMethods,
451 : SRS_PT_POLAR_STEREOGRAPHIC,
452 : SRS_PP_LATITUDE_OF_ORIGIN,
453 : SRS_PP_CENTRAL_MERIDIAN,
454 : SRS_PP_SCALE_FACTOR,
455 : SRS_PP_FALSE_EASTING,
456 : SRS_PP_FALSE_NORTHING,
457 : NULL,
458 : NULL );
459 : }
460 :
461 3 : else if( EQUAL(papszMethods[0],"Swiss Oblique Cylindrical") )
462 : {
463 0 : OGCWKTSetProj( szProjection, papszMethods,
464 : SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
465 : SRS_PP_LATITUDE_OF_CENTER,
466 : SRS_PP_LONGITUDE_OF_CENTER,
467 : SRS_PP_FALSE_EASTING,
468 : SRS_PP_FALSE_NORTHING,
469 : NULL,
470 : NULL,
471 : NULL );
472 : }
473 :
474 3 : else if( EQUAL(papszMethods[0],"Transverse Mercator") )
475 : {
476 3 : OGCWKTSetProj( szProjection, papszMethods,
477 : SRS_PT_TRANSVERSE_MERCATOR,
478 : SRS_PP_LATITUDE_OF_ORIGIN,
479 : SRS_PP_CENTRAL_MERIDIAN,
480 : SRS_PP_SCALE_FACTOR,
481 : SRS_PP_FALSE_EASTING,
482 : SRS_PP_FALSE_NORTHING,
483 : NULL,
484 : NULL );
485 : }
486 :
487 0 : else if( EQUAL(papszMethods[0],"Transverse Mercator (South Oriented)")
488 0 : || EQUAL(papszMethods[0],"Transverse Mercator (South Orientated)"))
489 : {
490 0 : OGCWKTSetProj( szProjection, papszMethods,
491 : SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
492 : SRS_PP_LATITUDE_OF_ORIGIN,
493 : SRS_PP_CENTRAL_MERIDIAN,
494 : SRS_PP_SCALE_FACTOR,
495 : SRS_PP_FALSE_EASTING,
496 : SRS_PP_FALSE_NORTHING,
497 : NULL,
498 : NULL );
499 : }
500 :
501 0 : else if( EQUAL(papszMethods[0],"*Albers Conic") )
502 : {
503 0 : OGCWKTSetProj( szProjection, papszMethods,
504 : SRS_PT_ALBERS_CONIC_EQUAL_AREA,
505 : SRS_PP_STANDARD_PARALLEL_1,
506 : SRS_PP_STANDARD_PARALLEL_2,
507 : SRS_PP_LATITUDE_OF_CENTER,
508 : SRS_PP_LONGITUDE_OF_CENTER,
509 : SRS_PP_FALSE_EASTING,
510 : SRS_PP_FALSE_NORTHING,
511 : NULL );
512 : }
513 :
514 0 : else if( EQUAL(papszMethods[0],"*Equidistant Conic") )
515 : {
516 0 : OGCWKTSetProj( szProjection, papszMethods,
517 : SRS_PT_EQUIDISTANT_CONIC,
518 : SRS_PP_STANDARD_PARALLEL_1,
519 : SRS_PP_STANDARD_PARALLEL_2,
520 : SRS_PP_LATITUDE_OF_CENTER,
521 : SRS_PP_LONGITUDE_OF_CENTER,
522 : SRS_PP_FALSE_EASTING,
523 : SRS_PP_FALSE_NORTHING,
524 : NULL );
525 : }
526 :
527 0 : else if( EQUAL(papszMethods[0],"*Polyconic") )
528 : {
529 0 : OGCWKTSetProj( szProjection, papszMethods,
530 : SRS_PT_POLYCONIC,
531 : SRS_PP_LATITUDE_OF_ORIGIN,
532 : SRS_PP_CENTRAL_MERIDIAN,
533 : SRS_PP_SCALE_FACTOR, /* not normally expected */
534 : SRS_PP_FALSE_EASTING,
535 : SRS_PP_FALSE_NORTHING,
536 : NULL,
537 : NULL );
538 : }
539 :
540 6 : CSLDestroy( papszMethods );
541 :
542 :
543 : /* -------------------------------------------------------------------- */
544 : /* Extract the linear Units specification. */
545 : /* -------------------------------------------------------------------- */
546 6 : if( psGXF->pszUnitName != NULL && strlen(szProjection) > 0 )
547 : {
548 5 : if( strlen(psGXF->pszUnitName) > 80 )
549 0 : return CPLStrdup("");
550 :
551 5 : sprintf( szProjection+strlen(szProjection),
552 : ",UNIT[\"%s\",%.15g]",
553 : psGXF->pszUnitName, psGXF->dfUnitToMeter );
554 : }
555 :
556 : /* -------------------------------------------------------------------- */
557 : /* Build GEOGCS. There are still "issues" with the generation */
558 : /* of the GEOGCS/Datum and Spheroid names. Of these, only the */
559 : /* datum name is really significant. */
560 : /* -------------------------------------------------------------------- */
561 6 : if( CSLCount(psGXF->papszMapProjection) > 1 )
562 : {
563 : char **papszTokens;
564 :
565 6 : if( strlen(psGXF->papszMapProjection[1]) > 80 )
566 0 : return CPLStrdup("");
567 :
568 6 : papszTokens = CSLTokenizeStringComplex(psGXF->papszMapProjection[1],
569 : ",", TRUE, TRUE );
570 :
571 :
572 6 : if( CSLCount(papszTokens) > 2 )
573 : {
574 6 : double dfMajor = atof(papszTokens[1]);
575 6 : double dfEccentricity = atof(papszTokens[2]);
576 : double dfInvFlattening, dfMinor;
577 : char *pszOGCDatum;
578 :
579 : /* translate eccentricity to inv flattening. */
580 6 : if( dfEccentricity == 0.0 )
581 0 : dfInvFlattening = 0.0;
582 : else
583 : {
584 6 : dfMinor = dfMajor * pow(1.0-dfEccentricity*dfEccentricity,0.5);
585 6 : dfInvFlattening = 1.0 / (1 - dfMinor/dfMajor);
586 : }
587 :
588 6 : pszOGCDatum = CPLStrdup(papszTokens[0]);
589 6 : WKTMassageDatum( &pszOGCDatum );
590 :
591 6 : sprintf( szGCS,
592 : "GEOGCS[\"%s\","
593 : "DATUM[\"%s\","
594 : "SPHEROID[\"%s\",%s,%.15g]],",
595 : papszTokens[0],
596 : pszOGCDatum,
597 : papszTokens[0], /* this is datum, but should be ellipse*/
598 6 : papszTokens[1],
599 : dfInvFlattening );
600 6 : CPLFree( pszOGCDatum );
601 : }
602 :
603 6 : if( CSLCount(papszTokens) > 3 )
604 6 : sprintf( szGCS + strlen(szGCS),
605 : "PRIMEM[\"unnamed\",%s],",
606 6 : papszTokens[3] );
607 :
608 6 : strcat( szGCS, "UNIT[\"degree\",0.0174532925199433]]" );
609 :
610 6 : CSLDestroy( papszTokens );
611 : }
612 :
613 6 : CPLAssert(strlen(szProjection) < sizeof(szProjection));
614 6 : CPLAssert(strlen(szGCS) < sizeof(szGCS));
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Put this all together into a full projection. */
618 : /* -------------------------------------------------------------------- */
619 6 : if( strlen(szProjection) > 0 )
620 : {
621 5 : if( strlen(psGXF->papszMapProjection[0]) > 80 )
622 0 : return CPLStrdup("");
623 :
624 5 : if( psGXF->papszMapProjection[0][0] == '"' )
625 5 : sprintf( szWKT,
626 : "PROJCS[%s,%s,%s]",
627 : psGXF->papszMapProjection[0],
628 : szGCS,
629 : szProjection );
630 : else
631 0 : sprintf( szWKT,
632 : "PROJCS[\"%s\",%s,%s]",
633 : psGXF->papszMapProjection[0],
634 : szGCS,
635 : szProjection );
636 :
637 : }
638 : else
639 : {
640 1 : strcpy( szWKT, szGCS );
641 : }
642 :
643 6 : return( CPLStrdup( szWKT ) );
644 : }
645 :
|