Line data Source code
1 : /******************************************************************************
2 : * $Id$
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 : * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
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 "gxfopen.h"
32 : #include "ogr_srs_api.h"
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 "Albers_Conic_Equal_Area"
41 : #define SRS_PT_AZIMUTHAL_EQUIDISTANT "Azimuthal_Equidistant"
42 : #define SRS_PT_CASSINI_SOLDNER "Cassini_Soldner"
43 : #define SRS_PT_CYLINDRICAL_EQUAL_AREA "Cylindrical_Equal_Area"
44 : #define SRS_PT_ECKERT_IV "Eckert_IV"
45 : #define SRS_PT_ECKERT_VI "Eckert_VI"
46 : #define SRS_PT_EQUIDISTANT_CONIC "Equidistant_Conic"
47 : #define SRS_PT_EQUIRECTANGULAR "Equirectangular"
48 : #define SRS_PT_GALL_STEREOGRAPHIC "Gall_Stereographic"
49 : #define SRS_PT_GNOMONIC "Gnomonic"
50 : #define SRS_PT_HOTINE_OBLIQUE_MERCATOR "Hotine_Oblique_Mercator"
51 : #define SRS_PT_LABORDE_OBLIQUE_MERCATOR "Laborde_Oblique_Mercator"
52 : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP "Lambert_Conformal_Conic_1SP"
53 : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP "Lambert_Conformal_Conic_2SP"
54 : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM \
55 : "Lambert_Conformal_Conic_2SP_Belgium"
56 : #define SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA "Lambert_Azimuthal_Equal_Area"
57 : #define SRS_PT_MERCATOR_1SP "Mercator_1SP"
58 : #define SRS_PT_MERCATOR_2SP "Mercator_2SP"
59 : #define SRS_PT_MILLER_CYLINDRICAL "Miller_Cylindrical"
60 : #define SRS_PT_MOLLWEIDE "Mollweide"
61 : #define SRS_PT_NEW_ZEALAND_MAP_GRID "New_Zealand_Map_Grid"
62 : #define SRS_PT_OBLIQUE_STEREOGRAPHIC "Oblique_Stereographic"
63 : #define SRS_PT_ORTHOGRAPHIC "Orthographic"
64 : #define SRS_PT_POLAR_STEREOGRAPHIC "Polar_Stereographic"
65 : #define SRS_PT_POLYCONIC "Polyconic"
66 : #define SRS_PT_ROBINSON "Robinson"
67 : #define SRS_PT_SINUSOIDAL "Sinusoidal"
68 : #define SRS_PT_STEREOGRAPHIC "Stereographic"
69 : #define SRS_PT_SWISS_OBLIQUE_CYLINDRICAL "Swiss_Oblique_Cylindrical"
70 : #define SRS_PT_TRANSVERSE_MERCATOR "Transverse_Mercator"
71 : #define SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED \
72 : "Transverse_Mercator_South_Orientated"
73 : #define SRS_PT_TUNISIA_MINING_GRID "Tunisia_Mining_Grid"
74 : #define SRS_PT_VANDERGRINTEN "VanDerGrinten"
75 :
76 : #define SRS_PP_CENTRAL_MERIDIAN "central_meridian"
77 : #define SRS_PP_SCALE_FACTOR "scale_factor"
78 : #define SRS_PP_STANDARD_PARALLEL_1 "standard_parallel_1"
79 : #define SRS_PP_STANDARD_PARALLEL_2 "standard_parallel_2"
80 : #define SRS_PP_LONGITUDE_OF_CENTER "longitude_of_center"
81 : #define SRS_PP_LATITUDE_OF_CENTER "latitude_of_center"
82 : #define SRS_PP_LONGITUDE_OF_ORIGIN "longitude_of_origin"
83 : #define SRS_PP_LATITUDE_OF_ORIGIN "latitude_of_origin"
84 : #define SRS_PP_FALSE_EASTING "false_easting"
85 : #define SRS_PP_FALSE_NORTHING "false_northing"
86 : #define SRS_PP_AZIMUTH "azimuth"
87 : #define SRS_PP_LONGITUDE_OF_POINT_1 "longitude_of_point_1"
88 : #define SRS_PP_LATITUDE_OF_POINT_1 "latitude_of_point_1"
89 : #define SRS_PP_LONGITUDE_OF_POINT_2 "longitude_of_point_2"
90 : #define SRS_PP_LATITUDE_OF_POINT_2 "latitude_of_point_2"
91 : #define SRS_PP_LONGITUDE_OF_POINT_3 "longitude_of_point_3"
92 : #define SRS_PP_LATITUDE_OF_POINT_3 "latitude_of_point_3"
93 : #define SRS_PP_RECTIFIED_GRID_ANGLE "rectified_grid_angle"
94 :
95 : /* -------------------------------------------------------------------- */
96 : /* This table was copied from gt_wkt_srs.cpp in the libgeotiff */
97 : /* distribution. Please keep changes in sync. */
98 : /* -------------------------------------------------------------------- */
99 : static const char *const papszDatumEquiv[] = {
100 : "Militar_Geographische_Institut",
101 : "Militar_Geographische_Institute",
102 : "World_Geodetic_System_1984",
103 : "WGS_1984",
104 : "WGS_72_Transit_Broadcast_Ephemeris",
105 : "WGS_1972_Transit_Broadcast_Ephemeris",
106 : "World_Geodetic_System_1972",
107 : "WGS_1972",
108 : "European_Terrestrial_Reference_System_89",
109 : "European_Reference_System_1989",
110 : NULL};
111 :
112 : /************************************************************************/
113 : /* WKTMassageDatum() */
114 : /* */
115 : /* Massage an EPSG datum name into WMT format. Also transform */
116 : /* specific exception cases into WKT versions. */
117 : /* */
118 : /* This function was copied from the gt_wkt_srs.cpp file in the */
119 : /* libgeotiff distribution. Please keep changes in sync. */
120 : /************************************************************************/
121 :
122 2 : static void WKTMassageDatum(char **ppszDatum)
123 :
124 : {
125 : int i, j;
126 : char *pszDatum;
127 :
128 2 : pszDatum = *ppszDatum;
129 2 : if (pszDatum[0] == '\0')
130 0 : return;
131 :
132 : /* -------------------------------------------------------------------- */
133 : /* Translate non-alphanumeric values to underscores. */
134 : /* -------------------------------------------------------------------- */
135 12 : for (i = 0; pszDatum[i] != '\0'; i++)
136 : {
137 10 : if (pszDatum[i] != '+' && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z') &&
138 4 : !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z') &&
139 4 : !(pszDatum[i] >= '0' && pszDatum[i] <= '9'))
140 : {
141 0 : pszDatum[i] = '_';
142 : }
143 : }
144 :
145 : /* -------------------------------------------------------------------- */
146 : /* Remove repeated and trailing underscores. */
147 : /* -------------------------------------------------------------------- */
148 10 : for (i = 1, j = 0; pszDatum[i] != '\0'; i++)
149 : {
150 8 : if (pszDatum[j] == '_' && pszDatum[i] == '_')
151 0 : continue;
152 :
153 8 : pszDatum[++j] = pszDatum[i];
154 : }
155 2 : if (pszDatum[j] == '_')
156 0 : pszDatum[j] = '\0';
157 : else
158 2 : pszDatum[j + 1] = '\0';
159 :
160 : /* -------------------------------------------------------------------- */
161 : /* Search for datum equivalences. Specific massaged names get */
162 : /* mapped to OpenGIS specified names. */
163 : /* -------------------------------------------------------------------- */
164 12 : for (i = 0; papszDatumEquiv[i] != NULL; i += 2)
165 : {
166 10 : if (EQUAL(*ppszDatum, papszDatumEquiv[i]))
167 : {
168 0 : CPLFree(*ppszDatum);
169 0 : *ppszDatum = CPLStrdup(papszDatumEquiv[i + 1]);
170 0 : return;
171 : }
172 : }
173 : }
174 :
175 : /************************************************************************/
176 : /* OGCWKTSetProj() */
177 : /************************************************************************/
178 :
179 2 : static void OGCWKTSetProj(char *pszProjection, size_t nProjectionSize,
180 : char **papszMethods, const char *pszTransformName,
181 : const char *pszParm1, const char *pszParm2,
182 : const char *pszParm3, const char *pszParm4,
183 : const char *pszParm5, const char *pszParm6,
184 : const char *pszParm7)
185 :
186 : {
187 2 : int iParam, nCount = CSLCount(papszMethods);
188 2 : const char *apszParamNames[8] = {NULL};
189 :
190 2 : apszParamNames[0] = pszParm1;
191 2 : apszParamNames[1] = pszParm2;
192 2 : apszParamNames[2] = pszParm3;
193 2 : apszParamNames[3] = pszParm4;
194 2 : apszParamNames[4] = pszParm5;
195 2 : apszParamNames[5] = pszParm6;
196 2 : apszParamNames[6] = pszParm7;
197 2 : apszParamNames[7] = NULL;
198 :
199 2 : snprintf(pszProjection, nProjectionSize, "PROJECTION[\"%s\"]",
200 : pszTransformName);
201 :
202 12 : for (iParam = 0; iParam < nCount - 1 && apszParamNames[iParam] != NULL;
203 10 : iParam++)
204 : {
205 10 : snprintf(pszProjection + strlen(pszProjection),
206 10 : nProjectionSize - strlen(pszProjection),
207 : ",PARAMETER[\"%s\",%s]", apszParamNames[iParam],
208 10 : papszMethods[iParam + 1]);
209 : }
210 2 : }
211 :
212 : /************************************************************************/
213 : /* GXFGetMapProjectionAsOGCWKT() */
214 : /************************************************************************/
215 :
216 : /**
217 : * Return the GXF Projection in OpenGIS Well Known Text format.
218 : *
219 : * The returned string becomes owned by the caller, and should be freed
220 : * with CPLFree() or VSIFree(). The return value will be "" if
221 : * no projection information is passed.
222 : *
223 : * The mapping of GXF projections to OGC WKT format is not complete. Please
224 : * see the gxf_ogcwkt.c code to better understand limitations of this
225 : * translation. More information about OGC WKT format can be found in
226 : * the OpenGIS Simple Features specification for OLEDB/COM found on the
227 : * OpenGIS web site at <a href="http://www.opengis.org/">www.opengis.org</a>.
228 : * The translation uses some code cribbed from the OGR library, about which
229 : * more can be learned from <a href="http://gdal.velocet.ca/projects/opengis/">
230 : * http://gdal.velocet.ca/projects/opengis/</a>.
231 : *
232 : * For example, the following GXF definitions:
233 : * <pre>
234 : * #UNIT_LENGTH
235 : * m,1
236 : * #MAP_PROJECTION
237 : * "NAD83 / UTM zone 19N"
238 : * "GRS 1980",6378137,0.081819191,0
239 : * "Transverse Mercator",0,-69,0.9996,500000,0
240 : * </pre>
241 : *
242 : * Would translate to (without the nice formatting):
243 : * <pre>
244 : PROJCS["NAD83 / UTM zone 19N",
245 : GEOGCS["GRS 1980",
246 : DATUM["GRS_1980",
247 : SPHEROID["GRS 1980",6378137,298.257222413684]],
248 : PRIMEM["unnamed",0],
249 : UNIT["degree",0.0174532925199433]],
250 : PROJECTION["Transverse_Mercator"],
251 : PARAMETER["latitude_of_origin",0],
252 : PARAMETER["central_meridian",-69],
253 : PARAMETER["scale_factor",0.9996],
254 : PARAMETER["false_easting",500000],
255 : PARAMETER["false_northing",0],
256 : UNIT["m",1]]
257 : * </pre>
258 : *
259 : * @param hGXF handle to GXF file, as returned by GXFOpen().
260 : *
261 : * @return string containing OGC WKT projection.
262 : */
263 :
264 4 : char *GXFGetMapProjectionAsOGCWKT(GXFHandle hGXF)
265 :
266 : {
267 4 : GXFInfo_t *psGXF = (GXFInfo_t *)hGXF;
268 4 : char **papszMethods = NULL;
269 : char szWKT[1024 + 32];
270 : char szGCS[512];
271 : char szProjection[512];
272 :
273 : /* -------------------------------------------------------------------- */
274 : /* If there was nothing in the file return "unknown". */
275 : /* -------------------------------------------------------------------- */
276 4 : if (CSLCount(psGXF->papszMapProjection) < 2)
277 2 : return (CPLStrdup(""));
278 :
279 2 : strcpy(szWKT, "");
280 2 : strcpy(szGCS, "");
281 2 : strcpy(szProjection, "");
282 :
283 : /* -------------------------------------------------------------------- */
284 : /* Parse the third line, looking for known projection methods. */
285 : /* -------------------------------------------------------------------- */
286 2 : if (psGXF->papszMapProjection[2] != NULL)
287 : {
288 : /* We allow more than 80 characters if the projection parameters */
289 : /* are on 2 lines as allowed by GXF 3 */
290 2 : if (strlen(psGXF->papszMapProjection[2]) > 120)
291 0 : return (CPLStrdup(""));
292 2 : papszMethods = CSLTokenizeStringComplex(psGXF->papszMapProjection[2],
293 : ",", TRUE, TRUE);
294 : }
295 :
296 : /* -------------------------------------------------------------------- */
297 : /* Create the PROJCS. */
298 : /* -------------------------------------------------------------------- */
299 2 : if (papszMethods == NULL || papszMethods[0] == NULL ||
300 2 : EQUAL(papszMethods[0], "Geographic"))
301 : {
302 : /* do nothing */
303 : }
304 :
305 2 : else if (EQUAL(papszMethods[0], "Lambert Conic Conformal (1SP)"))
306 : {
307 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
308 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
309 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
310 : SRS_PP_SCALE_FACTOR, SRS_PP_FALSE_EASTING,
311 : SRS_PP_FALSE_NORTHING, NULL, NULL);
312 : }
313 :
314 2 : else if (EQUAL(papszMethods[0], "Lambert Conic Conformal (2SP)"))
315 : {
316 2 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
317 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
318 : SRS_PP_STANDARD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_2,
319 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
320 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL);
321 : }
322 :
323 0 : else if (EQUAL(papszMethods[0], "Lambert Conformal (2SP Belgium)"))
324 : {
325 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
326 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
327 : SRS_PP_STANDARD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_2,
328 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
329 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL);
330 : }
331 :
332 0 : else if (EQUAL(papszMethods[0], "Mercator (1SP)"))
333 : {
334 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
335 : SRS_PT_MERCATOR_1SP, SRS_PP_LATITUDE_OF_ORIGIN,
336 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
337 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
338 : }
339 :
340 0 : else if (EQUAL(papszMethods[0], "Mercator (2SP)"))
341 : {
342 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
343 : SRS_PT_MERCATOR_2SP,
344 : SRS_PP_LATITUDE_OF_ORIGIN, /* should it be StdParalle1?*/
345 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_FALSE_EASTING,
346 : SRS_PP_FALSE_NORTHING, NULL, NULL, NULL);
347 : }
348 :
349 0 : else if (EQUAL(papszMethods[0], "Laborde Oblique Mercator"))
350 : {
351 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
352 : SRS_PT_LABORDE_OBLIQUE_MERCATOR,
353 : SRS_PP_LATITUDE_OF_CENTER, SRS_PP_LONGITUDE_OF_CENTER,
354 : SRS_PP_AZIMUTH, SRS_PP_SCALE_FACTOR, SRS_PP_FALSE_EASTING,
355 : SRS_PP_FALSE_NORTHING, NULL);
356 : }
357 :
358 0 : else if (EQUAL(papszMethods[0], "Hotine Oblique Mercator"))
359 : {
360 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
361 : SRS_PT_HOTINE_OBLIQUE_MERCATOR, SRS_PP_LATITUDE_OF_CENTER,
362 : SRS_PP_LONGITUDE_OF_CENTER, SRS_PP_AZIMUTH,
363 : SRS_PP_RECTIFIED_GRID_ANGLE,
364 : SRS_PP_SCALE_FACTOR, /* not in normal formulation */
365 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING);
366 : }
367 :
368 0 : else if (EQUAL(papszMethods[0], "New Zealand Map Grid"))
369 :
370 : {
371 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
372 : SRS_PT_NEW_ZEALAND_MAP_GRID, SRS_PP_LATITUDE_OF_ORIGIN,
373 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_FALSE_EASTING,
374 : SRS_PP_FALSE_NORTHING, NULL, NULL, NULL);
375 : }
376 :
377 0 : else if (EQUAL(papszMethods[0], "Oblique Stereographic"))
378 : {
379 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
380 : SRS_PT_OBLIQUE_STEREOGRAPHIC, SRS_PP_LATITUDE_OF_ORIGIN,
381 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
382 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
383 : }
384 :
385 0 : else if (EQUAL(papszMethods[0], "Polar Stereographic"))
386 : {
387 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
388 : SRS_PT_POLAR_STEREOGRAPHIC, SRS_PP_LATITUDE_OF_ORIGIN,
389 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
390 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
391 : }
392 :
393 0 : else if (EQUAL(papszMethods[0], "Swiss Oblique Cylindrical"))
394 : {
395 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
396 : SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
397 : SRS_PP_LATITUDE_OF_CENTER, SRS_PP_LONGITUDE_OF_CENTER,
398 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL,
399 : NULL);
400 : }
401 :
402 0 : else if (EQUAL(papszMethods[0], "Transverse Mercator"))
403 : {
404 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
405 : SRS_PT_TRANSVERSE_MERCATOR, SRS_PP_LATITUDE_OF_ORIGIN,
406 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
407 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
408 : }
409 :
410 0 : else if (EQUAL(papszMethods[0], "Transverse Mercator (South Oriented)") ||
411 0 : EQUAL(papszMethods[0], "Transverse Mercator (South Orientated)"))
412 : {
413 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
414 : SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
415 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
416 : SRS_PP_SCALE_FACTOR, SRS_PP_FALSE_EASTING,
417 : SRS_PP_FALSE_NORTHING, NULL, NULL);
418 : }
419 :
420 0 : else if (EQUAL(papszMethods[0], "*Albers Conic"))
421 : {
422 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
423 : SRS_PT_ALBERS_CONIC_EQUAL_AREA,
424 : SRS_PP_STANDARD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_2,
425 : SRS_PP_LATITUDE_OF_CENTER, SRS_PP_LONGITUDE_OF_CENTER,
426 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL);
427 : }
428 :
429 0 : else if (EQUAL(papszMethods[0], "*Equidistant Conic"))
430 : {
431 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
432 : SRS_PT_EQUIDISTANT_CONIC, SRS_PP_STANDARD_PARALLEL_1,
433 : SRS_PP_STANDARD_PARALLEL_2, SRS_PP_LATITUDE_OF_CENTER,
434 : SRS_PP_LONGITUDE_OF_CENTER, SRS_PP_FALSE_EASTING,
435 : SRS_PP_FALSE_NORTHING, NULL);
436 : }
437 :
438 0 : else if (EQUAL(papszMethods[0], "*Polyconic"))
439 : {
440 0 : OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
441 : SRS_PT_POLYCONIC, SRS_PP_LATITUDE_OF_ORIGIN,
442 : SRS_PP_CENTRAL_MERIDIAN,
443 : SRS_PP_SCALE_FACTOR, /* not normally expected */
444 : SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
445 : }
446 :
447 2 : CSLDestroy(papszMethods);
448 :
449 : /* -------------------------------------------------------------------- */
450 : /* Extract the linear Units specification. */
451 : /* -------------------------------------------------------------------- */
452 2 : if (psGXF->pszUnitName != NULL && strlen(szProjection) > 0)
453 : {
454 2 : if (strlen(psGXF->pszUnitName) > 80)
455 0 : return CPLStrdup("");
456 :
457 2 : CPLsnprintf(szProjection + strlen(szProjection),
458 2 : sizeof(szProjection) - strlen(szProjection),
459 : ",UNIT[\"%s\",%.15g]", psGXF->pszUnitName,
460 : psGXF->dfUnitToMeter);
461 : }
462 :
463 : /* -------------------------------------------------------------------- */
464 : /* Build GEOGCS. There are still "issues" with the generation */
465 : /* of the GEOGCS/Datum and Spheroid names. Of these, only the */
466 : /* datum name is really significant. */
467 : /* -------------------------------------------------------------------- */
468 2 : if (CSLCount(psGXF->papszMapProjection) > 1)
469 : {
470 : char **papszTokens;
471 :
472 2 : if (strlen(psGXF->papszMapProjection[1]) > 80)
473 0 : return CPLStrdup("");
474 :
475 2 : papszTokens = CSLTokenizeStringComplex(psGXF->papszMapProjection[1],
476 : ",", TRUE, TRUE);
477 :
478 2 : if (CSLCount(papszTokens) > 2)
479 : {
480 2 : double dfMajor = CPLAtof(papszTokens[1]);
481 2 : double dfEccentricity = CPLAtof(papszTokens[2]);
482 : double dfInvFlattening, dfMinor;
483 : char *pszOGCDatum;
484 :
485 : /* translate eccentricity to inv flattening. */
486 2 : if (dfEccentricity == 0.0)
487 0 : dfInvFlattening = 0.0;
488 : else
489 : {
490 2 : dfMinor =
491 2 : dfMajor * pow(1.0 - dfEccentricity * dfEccentricity, 0.5);
492 2 : dfInvFlattening = OSRCalcInvFlattening(dfMajor, dfMinor);
493 : }
494 :
495 2 : pszOGCDatum = CPLStrdup(papszTokens[0]);
496 2 : WKTMassageDatum(&pszOGCDatum);
497 :
498 2 : CPLsnprintf(
499 : szGCS, sizeof(szGCS),
500 : "GEOGCS[\"%s\","
501 : "DATUM[\"%s\","
502 : "SPHEROID[\"%s\",%s,%.15g]],",
503 : papszTokens[0], pszOGCDatum,
504 : papszTokens[0], /* this is datum, but should be ellipse*/
505 2 : papszTokens[1], dfInvFlattening);
506 2 : CPLFree(pszOGCDatum);
507 : }
508 :
509 2 : if (CSLCount(papszTokens) > 3)
510 2 : CPLsnprintf(szGCS + strlen(szGCS), sizeof(szGCS) - strlen(szGCS),
511 2 : "PRIMEM[\"unnamed\",%s],", papszTokens[3]);
512 :
513 2 : CPLsnprintf(szGCS + strlen(szGCS), sizeof(szGCS) - strlen(szGCS), "%s",
514 : "UNIT[\"degree\",0.0174532925199433]]");
515 :
516 2 : CSLDestroy(papszTokens);
517 : }
518 :
519 2 : CPLAssert(strlen(szProjection) < sizeof(szProjection));
520 2 : CPLAssert(strlen(szGCS) < sizeof(szGCS));
521 :
522 : /* -------------------------------------------------------------------- */
523 : /* Put this all together into a full projection. */
524 : /* -------------------------------------------------------------------- */
525 2 : if (strlen(szProjection) > 0)
526 : {
527 2 : if (strlen(psGXF->papszMapProjection[0]) > 80)
528 0 : return CPLStrdup("");
529 :
530 2 : if (psGXF->papszMapProjection[0][0] == '"')
531 2 : snprintf(szWKT, sizeof(szWKT), "PROJCS[%s,%s,%s]",
532 2 : psGXF->papszMapProjection[0], szGCS, szProjection);
533 : else
534 0 : snprintf(szWKT, sizeof(szWKT), "PROJCS[\"%s\",%s,%s]",
535 0 : psGXF->papszMapProjection[0], szGCS, szProjection);
536 : }
537 : else
538 : {
539 0 : strcpy(szWKT, szGCS);
540 : }
541 :
542 2 : return (CPLStrdup(szWKT));
543 : }
|