1 : /******************************************************************************
2 : * $Id: gt_wkt_srs.cpp 25659 2013-02-19 22:51:46Z warmerdam $
3 : *
4 : * Project: GeoTIFF Driver
5 : * Purpose: Implements translation between GeoTIFF normalized projection
6 : * definitions and OpenGIS WKT SRS format. This code is
7 : * deliberately GDAL free, and it is intended to be moved into
8 : * libgeotiff someday if possible.
9 : * Author: Frank Warmerdam, warmerdam@pobox.com
10 : *
11 : ******************************************************************************
12 : * Copyright (c) 1999, Frank Warmerdam
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #include "cpl_serv.h"
34 : #include "geo_tiffp.h"
35 : #define CPL_ERROR_H_INCLUDED
36 :
37 : #include "geovalues.h"
38 : #include "ogr_spatialref.h"
39 : #include "gdal.h"
40 : #include "xtiffio.h"
41 : #include "cpl_multiproc.h"
42 : #include "tifvsi.h"
43 : #include "gt_wkt_srs.h"
44 : #include "gt_wkt_srs_for_gdal.h"
45 : #include "gt_citation.h"
46 :
47 : CPL_CVSID("$Id: gt_wkt_srs.cpp 25659 2013-02-19 22:51:46Z warmerdam $")
48 :
49 : #define ProjLinearUnitsInterpCorrectGeoKey 3059
50 :
51 : #ifndef CT_HotineObliqueMercatorAzimuthCenter
52 : # define CT_HotineObliqueMercatorAzimuthCenter 9815
53 : #endif
54 :
55 :
56 : CPL_C_START
57 : void CPL_DLL LibgeotiffOneTimeInit();
58 : void LibgeotiffOneTimeCleanupMutex();
59 :
60 : // replicated from gdal_csv.h.
61 : const char * GDALDefaultCSVFilename( const char *pszBasename );
62 :
63 : #ifndef CPL_SERV_H_INTERNAL
64 : /* Make VSIL_STRICT_ENFORCE active in DEBUG builds */
65 : #ifdef DEBUG
66 : #define VSIL_STRICT_ENFORCE
67 : #endif
68 :
69 : #ifdef VSIL_STRICT_ENFORCE
70 : typedef struct _VSILFILE VSILFILE;
71 : #else
72 : typedef FILE VSILFILE;
73 : #endif
74 :
75 : // ensure compatability with older libgeotiffs.
76 : #if !defined(GTIFAtof)
77 : # define GTIFAtof atof
78 : #endif
79 :
80 : int CPL_DLL VSIFCloseL( VSILFILE * );
81 : int CPL_DLL VSIUnlink( const char * );
82 : VSILFILE CPL_DLL *VSIFileFromMemBuffer( const char *pszFilename,
83 : GByte *pabyData,
84 : GUIntBig nDataLength,
85 : int bTakeOwnership );
86 : GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename,
87 : GUIntBig *pnDataLength,
88 : int bUnlinkAndSeize );
89 :
90 : int CPL_DLL CSLTestBoolean( const char *pszValue );
91 : const char CPL_DLL * CPL_STDCALL CPLGetConfigOption( const char *, const char * );
92 :
93 : /* Those stuff are redefined in external libgeotiff cpl_serv.h */
94 : /* as macros. Let's use GDAL functions instead */
95 : /* E.Rouault : I'm wondering why we just don't #define CPL_SERV_H_INCLUDED */
96 : /* at the beginning of this file to avoid cpl_serv.h to be used at all ??? */
97 :
98 : #undef CSVReadParseLine
99 : char CPL_DLL **CSVReadParseLine( FILE *fp);
100 : #undef CSLDestroy
101 : void CPL_DLL CPL_STDCALL CSLDestroy(char **papszStrList);
102 : #undef VSIFree
103 : void CPL_DLL VSIFree( void * );
104 : #undef CPLFree
105 : #define CPLFree VSIFree
106 : #undef CPLMalloc
107 : void CPL_DLL *CPLMalloc( size_t );
108 : #undef CPLCalloc
109 : void CPL_DLL *CPLCalloc( size_t, size_t );
110 : #undef CPLStrdup
111 : char CPL_DLL *CPLStrdup( const char * );
112 :
113 : #endif /* CPL_SERV_H_INTERNAL */
114 :
115 : const char CPL_DLL * CPL_STDCALL CPLGetConfigOption( const char *, const char * );
116 : void CPL_DLL CPL_STDCALL CPLDebug( const char *, const char *, ... );
117 :
118 : CPL_C_END
119 :
120 : // To remind myself not to use CPLString in this file!
121 : #define CPLString Please_do_not_use_CPLString_in_this_file
122 :
123 : static const char *papszDatumEquiv[] =
124 : {
125 : "Militar_Geographische_Institut",
126 : "Militar_Geographische_Institute",
127 : "World_Geodetic_System_1984",
128 : "WGS_1984",
129 : "WGS_72_Transit_Broadcast_Ephemeris",
130 : "WGS_1972_Transit_Broadcast_Ephemeris",
131 : "World_Geodetic_System_1972",
132 : "WGS_1972",
133 : "European_Terrestrial_Reference_System_89",
134 : "European_Reference_System_1989",
135 : NULL
136 : };
137 :
138 : // older libgeotiff's won't list this.
139 : #ifndef CT_CylindricalEqualArea
140 : # define CT_CylindricalEqualArea 28
141 : #endif
142 :
143 : /************************************************************************/
144 : /* LibgeotiffOneTimeInit() */
145 : /************************************************************************/
146 :
147 : static void* hMutex = NULL;
148 :
149 1651 : void LibgeotiffOneTimeInit()
150 : {
151 : static int bOneTimeInitDone = FALSE;
152 1651 : CPLMutexHolder oHolder( &hMutex);
153 :
154 1651 : if (bOneTimeInitDone)
155 : return;
156 :
157 450 : bOneTimeInitDone = TRUE;
158 :
159 : // If linking with an external libgeotiff we hope this will call the
160 : // SetCSVFilenameHook() in libgeotiff, not the one in gdal/port!
161 450 : SetCSVFilenameHook( GDALDefaultCSVFilename );
162 : }
163 :
164 : /************************************************************************/
165 : /* LibgeotiffOneTimeCleanupMutex() */
166 : /************************************************************************/
167 :
168 550 : void LibgeotiffOneTimeCleanupMutex()
169 : {
170 550 : if( hMutex != NULL )
171 : {
172 444 : CPLDestroyMutex(hMutex);
173 444 : hMutex = NULL;
174 : }
175 550 : }
176 :
177 : /************************************************************************/
178 : /* GTIFToCPLRecyleString() */
179 : /* */
180 : /* This changes a string from the libgeotiff heap to the GDAL */
181 : /* heap. */
182 : /************************************************************************/
183 :
184 5084 : static void GTIFToCPLRecycleString( char **ppszTarget )
185 :
186 : {
187 5084 : if( *ppszTarget == NULL )
188 3 : return;
189 :
190 5081 : char *pszTempString = CPLStrdup(*ppszTarget);
191 5081 : GTIFFreeMemory( *ppszTarget );
192 5081 : *ppszTarget = pszTempString;
193 : }
194 :
195 : /************************************************************************/
196 : /* WKTMassageDatum() */
197 : /* */
198 : /* Massage an EPSG datum name into WMT format. Also transform */
199 : /* specific exception cases into WKT versions. */
200 : /************************************************************************/
201 :
202 17419 : static void WKTMassageDatum( char ** ppszDatum )
203 :
204 : {
205 : int i, j;
206 : char *pszDatum;
207 :
208 17419 : pszDatum = *ppszDatum;
209 17419 : if (pszDatum[0] == '\0')
210 0 : return;
211 :
212 : /* -------------------------------------------------------------------- */
213 : /* Translate non-alphanumeric values to underscores. */
214 : /* -------------------------------------------------------------------- */
215 382579 : for( i = 0; pszDatum[i] != '\0'; i++ )
216 : {
217 1694317 : if( pszDatum[i] != '+'
218 638529 : && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
219 551079 : && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
220 139549 : && !(pszDatum[i] >= '0' && pszDatum[i] <= '9') )
221 : {
222 44009 : pszDatum[i] = '_';
223 : }
224 : }
225 :
226 : /* -------------------------------------------------------------------- */
227 : /* Remove repeated and trailing underscores. */
228 : /* -------------------------------------------------------------------- */
229 365160 : for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
230 : {
231 347741 : if( pszDatum[j] == '_' && pszDatum[i] == '_' )
232 3077 : continue;
233 :
234 344664 : pszDatum[++j] = pszDatum[i];
235 : }
236 17419 : if( pszDatum[j] == '_' )
237 2219 : pszDatum[j] = '\0';
238 : else
239 15200 : pszDatum[j+1] = '\0';
240 :
241 : /* -------------------------------------------------------------------- */
242 : /* Search for datum equivelences. Specific massaged names get */
243 : /* mapped to OpenGIS specified names. */
244 : /* -------------------------------------------------------------------- */
245 102200 : for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
246 : {
247 85374 : if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
248 : {
249 593 : CPLFree( *ppszDatum );
250 593 : *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
251 593 : return;
252 : }
253 : }
254 : }
255 :
256 : /************************************************************************/
257 : /* GTIFCleanupImageineNames() */
258 : /* */
259 : /* Erdas Imagine sometimes emits big copyright messages, and */
260 : /* other stuff into citations. These can be pretty messy when */
261 : /* turned into WKT, so we try to trim and clean the strings */
262 : /* somewhat. */
263 : /************************************************************************/
264 :
265 : /* For example:
266 : GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25659 $ $Date: 2013-02-19 23:51:46 +0100 (mar. 19 févr. 2013) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
267 :
268 : GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25659 $ $Date: 2013-02-19 23:51:46 +0100 (mar. 19 févr. 2013) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
269 :
270 : PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25659 $ $Date: 2013-02-19 23:51:46 +0100 (mar. 19 févr. 2013) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
271 :
272 : */
273 :
274 5 : static void GTIFCleanupImagineNames( char *pszCitation )
275 :
276 : {
277 5 : if( strstr(pszCitation,"IMAGINE GeoTIFF") == NULL )
278 5 : return;
279 :
280 : /* -------------------------------------------------------------------- */
281 : /* First, we skip past all the copyright, and RCS stuff. We */
282 : /* assume that this will have a "$" at the end of it all. */
283 : /* -------------------------------------------------------------------- */
284 : char *pszSkip;
285 :
286 0 : for( pszSkip = pszCitation + strlen(pszCitation) - 1;
287 : pszSkip != pszCitation && *pszSkip != '$';
288 : pszSkip-- ) {}
289 :
290 0 : if( *pszSkip == '$' )
291 0 : pszSkip++;
292 :
293 0 : memmove( pszCitation, pszSkip, strlen(pszSkip)+1 );
294 :
295 : /* -------------------------------------------------------------------- */
296 : /* Convert any newlines into spaces, they really gum up the */
297 : /* WKT. */
298 : /* -------------------------------------------------------------------- */
299 : int i;
300 :
301 0 : for( i = 0; pszCitation[i] != '\0'; i++ )
302 : {
303 0 : if( pszCitation[i] == '\n' )
304 0 : pszCitation[i] = ' ';
305 : }
306 : }
307 :
308 : /************************************************************************/
309 : /* GTIFGetOGISDefn() */
310 : /************************************************************************/
311 :
312 1045 : char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
313 :
314 : {
315 1045 : OGRSpatialReference oSRS;
316 :
317 : /* -------------------------------------------------------------------- */
318 : /* Make sure we have hooked CSVFilename(). */
319 : /* -------------------------------------------------------------------- */
320 1045 : LibgeotiffOneTimeInit();
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* Handle non-standard coordinate systems where GTModelTypeGeoKey */
324 : /* is not defined, but ProjectedCSTypeGeoKey is defined (ticket #3019) */
325 : /* -------------------------------------------------------------------- */
326 1045 : if( psDefn->Model == KvUserDefined && psDefn->PCS != KvUserDefined)
327 : {
328 1 : psDefn->Model = ModelTypeProjected;
329 : }
330 :
331 : /* -------------------------------------------------------------------- */
332 : /* Handle non-standard coordinate systems as LOCAL_CS. */
333 : /* -------------------------------------------------------------------- */
334 1045 : if( psDefn->Model != ModelTypeProjected
335 : && psDefn->Model != ModelTypeGeographic
336 : && psDefn->Model != ModelTypeGeocentric )
337 : {
338 : char *pszWKT;
339 : char szPeStr[2400];
340 :
341 : /** check if there is a pe string citation key **/
342 6 : if( GTIFKeyGet( hGTIF, PCSCitationGeoKey, szPeStr, 0, sizeof(szPeStr) ) &&
343 : strstr(szPeStr, "ESRI PE String = " ) )
344 : {
345 1 : pszWKT = CPLStrdup( szPeStr + strlen("ESRI PE String = ") );
346 1 : return pszWKT;
347 : }
348 : else
349 : {
350 5 : char *pszUnitsName = NULL;
351 : char szPCSName[300];
352 5 : int nKeyCount = 0;
353 : int anVersion[3];
354 :
355 5 : if( hGTIF != NULL )
356 5 : GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount );
357 :
358 5 : if( nKeyCount > 0 ) // Use LOCAL_CS if we have any geokeys at all.
359 : {
360 : // Handle citation.
361 5 : strcpy( szPCSName, "unnamed" );
362 5 : if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName,
363 : 0, sizeof(szPCSName) ) )
364 : GTIFKeyGet( hGTIF, GeogCitationGeoKey, szPCSName,
365 0 : 0, sizeof(szPCSName) );
366 :
367 5 : GTIFCleanupImagineNames( szPCSName );
368 5 : oSRS.SetLocalCS( szPCSName );
369 :
370 : // Handle units
371 5 : GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
372 :
373 5 : if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
374 : {
375 0 : oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
376 0 : oSRS.SetAuthority( "LOCAL_CS|UNIT", "EPSG", psDefn->UOMLength);
377 : }
378 : else
379 5 : oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
380 :
381 5 : GTIFFreeMemory( pszUnitsName );
382 : }
383 5 : oSRS.exportToWkt( &pszWKT );
384 :
385 5 : return pszWKT;
386 : }
387 : }
388 :
389 : /* -------------------------------------------------------------------- */
390 : /* Handle Geocentric coordinate systems. */
391 : /* -------------------------------------------------------------------- */
392 1039 : if( psDefn->Model == ModelTypeGeocentric )
393 : {
394 : char szName[300];
395 :
396 0 : strcpy( szName, "unnamed" );
397 0 : if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szName,
398 : 0, sizeof(szName) ) )
399 : GTIFKeyGet( hGTIF, GeogCitationGeoKey, szName,
400 0 : 0, sizeof(szName) );
401 :
402 0 : oSRS.SetGeocCS( szName );
403 :
404 0 : char *pszUnitsName = NULL;
405 :
406 0 : GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
407 :
408 0 : if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
409 : {
410 0 : oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
411 0 : oSRS.SetAuthority( "GEOCCS|UNIT", "EPSG", psDefn->UOMLength );
412 : }
413 : else
414 0 : oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
415 :
416 0 : GTIFFreeMemory( pszUnitsName );
417 : }
418 :
419 : /* -------------------------------------------------------------------- */
420 : /* #3901: In libgeotiff 1.3.0 and earlier we incorrectly */
421 : /* interpreted linear projection parameter geokeys (false */
422 : /* easting/northing) as being in meters instead of the */
423 : /* coordinate system of the file. The following code attempts */
424 : /* to provide mechanisms for fixing the issue if we are linked */
425 : /* with an older version of libgeotiff. */
426 : /* -------------------------------------------------------------------- */
427 : int iParm;
428 : const char *pszLinearUnits =
429 1039 : CPLGetConfigOption( "GTIFF_LINEAR_UNITS", "DEFAULT" );
430 :
431 : #if LIBGEOTIFF_VERSION <= 1300
432 : if( EQUAL(pszLinearUnits,"DEFAULT") && psDefn->Projection == KvUserDefined )
433 : {
434 : for( iParm = 0; iParm < psDefn->nParms; iParm++ )
435 : {
436 : switch( psDefn->ProjParmId[iParm] )
437 : {
438 : case ProjFalseEastingGeoKey:
439 : case ProjFalseNorthingGeoKey:
440 : case ProjFalseOriginEastingGeoKey:
441 : case ProjFalseOriginNorthingGeoKey:
442 : case ProjCenterEastingGeoKey:
443 : case ProjCenterNorthingGeoKey:
444 : if( psDefn->UOMLengthInMeters != 0
445 : && psDefn->UOMLengthInMeters != 1.0 )
446 : {
447 : psDefn->ProjParm[iParm] *= psDefn->UOMLengthInMeters;
448 : CPLDebug( "GTIFF", "converting geokey to meters to fix bug in old libgeotiff" );
449 : }
450 : break;
451 :
452 : default:
453 : break;
454 : }
455 : }
456 : }
457 : #endif /* LIBGEOTIFF_VERSION <= 1300 */
458 :
459 : /* -------------------------------------------------------------------- */
460 : /* #3901: If folks have broken GeoTIFF files generated with */
461 : /* older versions of GDAL+libgeotiff, then they may need a */
462 : /* hack to allow them to be read properly. This is that */
463 : /* hack. We basically try to undue the conversion applied by */
464 : /* libgeotiff to meters (or above) to simulate the old */
465 : /* behavior. */
466 : /* -------------------------------------------------------------------- */
467 1039 : short bLinearUnitsMarkedCorrect = FALSE;
468 :
469 : GTIFKeyGet(hGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey,
470 1039 : &bLinearUnitsMarkedCorrect, 0, 1);
471 :
472 1039 : if( EQUAL(pszLinearUnits,"BROKEN")
473 : && psDefn->Projection == KvUserDefined
474 : && !bLinearUnitsMarkedCorrect )
475 : {
476 16 : for( iParm = 0; iParm < psDefn->nParms; iParm++ )
477 : {
478 14 : switch( psDefn->ProjParmId[iParm] )
479 : {
480 : case ProjFalseEastingGeoKey:
481 : case ProjFalseNorthingGeoKey:
482 : case ProjFalseOriginEastingGeoKey:
483 : case ProjFalseOriginNorthingGeoKey:
484 : case ProjCenterEastingGeoKey:
485 : case ProjCenterNorthingGeoKey:
486 4 : if( psDefn->UOMLengthInMeters != 0
487 : && psDefn->UOMLengthInMeters != 1.0 )
488 : {
489 4 : psDefn->ProjParm[iParm] /= psDefn->UOMLengthInMeters;
490 4 : CPLDebug( "GTIFF", "converting geokey to accomodate old broken file due to GTIFF_LINEAR_UNITS=BROKEN setting." );
491 : }
492 : break;
493 :
494 : default:
495 : break;
496 : }
497 : }
498 : }
499 :
500 : /* -------------------------------------------------------------------- */
501 : /* If this is a projected SRS we set the PROJCS keyword first */
502 : /* to ensure that the GEOGCS will be a child. */
503 : /* -------------------------------------------------------------------- */
504 1039 : OGRBoolean linearUnitIsSet = FALSE;
505 1039 : if( psDefn->Model == ModelTypeProjected )
506 : {
507 : char szCTString[512];
508 615 : strcpy( szCTString, "unnamed" );
509 615 : if( psDefn->PCS != KvUserDefined )
510 : {
511 562 : char *pszPCSName = NULL;
512 :
513 562 : GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL );
514 :
515 562 : oSRS.SetNode( "PROJCS", pszPCSName ? pszPCSName : "unnamed" );
516 562 : if ( pszPCSName )
517 562 : GTIFFreeMemory( pszPCSName );
518 :
519 562 : oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
520 : }
521 53 : else if(hGTIF && GTIFKeyGet( hGTIF, PCSCitationGeoKey, szCTString, 0,
522 : sizeof(szCTString)) )
523 : {
524 1 : if (!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
525 : PCSCitationGeoKey, &oSRS, &linearUnitIsSet))
526 1 : oSRS.SetNode("PROJCS",szCTString);
527 : }
528 : else
529 : {
530 52 : if( hGTIF )
531 : {
532 52 : GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) );
533 52 : if(!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
534 : GTCitationGeoKey, &oSRS, &linearUnitIsSet))
535 0 : oSRS.SetNode( "PROJCS", szCTString );
536 : }
537 : else
538 0 : oSRS.SetNode( "PROJCS", szCTString );
539 : }
540 :
541 : /* Handle ESRI/Erdas style state plane and UTM in citation key */
542 615 : if( CheckCitationKeyForStatePlaneUTM(hGTIF, psDefn, &oSRS, &linearUnitIsSet) )
543 : {
544 : char *pszWKT;
545 0 : oSRS.morphFromESRI();
546 0 : oSRS.FixupOrdering();
547 0 : if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
548 0 : return pszWKT;
549 : }
550 :
551 : /* Handle ESRI PE string in citation */
552 615 : szCTString[0] = '\0';
553 615 : if( hGTIF && GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
554 612 : SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString), GTCitationGeoKey, &oSRS, &linearUnitIsSet);
555 : }
556 :
557 : /* ==================================================================== */
558 : /* Setup the GeogCS */
559 : /* ==================================================================== */
560 1039 : char *pszGeogName = NULL;
561 1039 : char *pszDatumName = NULL;
562 1039 : char *pszPMName = NULL;
563 1039 : char *pszSpheroidName = NULL;
564 1039 : char *pszAngularUnits = NULL;
565 1039 : double dfInvFlattening=0.0, dfSemiMajor=0.0;
566 : char szGCSName[512];
567 1039 : OGRBoolean aUnitGot = FALSE;
568 :
569 1039 : if( !GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL )
570 : && hGTIF != NULL
571 : && GTIFKeyGet( hGTIF, GeogCitationGeoKey, szGCSName, 0,
572 : sizeof(szGCSName)) )
573 : {
574 : GetGeogCSFromCitation(szGCSName, sizeof(szGCSName),
575 : GeogCitationGeoKey,
576 : &pszGeogName, &pszDatumName,
577 : &pszPMName, &pszSpheroidName,
578 30 : &pszAngularUnits);
579 : }
580 : else
581 1009 : GTIFToCPLRecycleString( &pszGeogName );
582 :
583 1039 : if( !pszDatumName )
584 : {
585 1012 : GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
586 1012 : GTIFToCPLRecycleString( &pszDatumName );
587 : }
588 1039 : if( !pszSpheroidName )
589 : {
590 1012 : GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
591 1012 : GTIFToCPLRecycleString( &pszSpheroidName );
592 : }
593 : else
594 : {
595 27 : GTIFKeyGet(hGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 );
596 27 : GTIFKeyGet(hGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening, 0, 1 );
597 : }
598 1039 : if( !pszPMName )
599 : {
600 1012 : GTIFGetPMInfo( psDefn->PM, &pszPMName, NULL );
601 1012 : GTIFToCPLRecycleString( &pszPMName );
602 : }
603 : else
604 27 : GTIFKeyGet(hGTIF, GeogPrimeMeridianLongGeoKey, &(psDefn->PMLongToGreenwich), 0, 1 );
605 :
606 1039 : if( !pszAngularUnits )
607 : {
608 1039 : GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
609 1039 : if( pszAngularUnits == NULL )
610 0 : pszAngularUnits = CPLStrdup("unknown");
611 : else
612 1039 : GTIFToCPLRecycleString( &pszAngularUnits );
613 : }
614 : else
615 : {
616 0 : GTIFKeyGet(hGTIF, GeogAngularUnitSizeGeoKey, &(psDefn->UOMAngleInDegrees), 0, 1 );
617 0 : aUnitGot = TRUE;
618 : }
619 :
620 1039 : if( pszDatumName != NULL )
621 1039 : WKTMassageDatum( &pszDatumName );
622 :
623 1039 : dfSemiMajor = psDefn->SemiMajor;
624 1039 : if( dfSemiMajor == 0.0 )
625 : {
626 0 : pszSpheroidName = CPLStrdup("unretrievable - using WGS84");
627 0 : dfSemiMajor = SRS_WGS84_SEMIMAJOR;
628 0 : dfInvFlattening = SRS_WGS84_INVFLATTENING;
629 : }
630 1039 : else if( dfInvFlattening == 0.0 && ((psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
631 : || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 ) )
632 : {
633 1010 : dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0);
634 :
635 : /* Take official inverse flattening definition in the WGS84 case */
636 1010 : if (fabs(dfSemiMajor-SRS_WGS84_SEMIMAJOR) < 1e-10 &&
637 : fabs(dfInvFlattening - SRS_WGS84_INVFLATTENING) < 1e-10)
638 487 : dfInvFlattening = SRS_WGS84_INVFLATTENING;
639 : }
640 1039 : if(!pszGeogName || strlen(pszGeogName) == 0)
641 : {
642 0 : CPLFree(pszGeogName);
643 0 : pszGeogName = CPLStrdup( pszDatumName ? pszDatumName : "unknown" );
644 : }
645 :
646 1039 : if(aUnitGot)
647 : oSRS.SetGeogCS( pszGeogName, pszDatumName,
648 : pszSpheroidName, dfSemiMajor, dfInvFlattening,
649 : pszPMName,
650 : psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
651 : pszAngularUnits,
652 0 : psDefn->UOMAngleInDegrees );
653 : else
654 : oSRS.SetGeogCS( pszGeogName, pszDatumName,
655 : pszSpheroidName, dfSemiMajor, dfInvFlattening,
656 : pszPMName,
657 : psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
658 : pszAngularUnits,
659 1039 : psDefn->UOMAngleInDegrees * 0.0174532925199433 );
660 :
661 1039 : if( psDefn->GCS != KvUserDefined && psDefn->GCS > 0 )
662 1009 : oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS );
663 :
664 1039 : if( psDefn->Datum != KvUserDefined )
665 1012 : oSRS.SetAuthority( "DATUM", "EPSG", psDefn->Datum );
666 :
667 1039 : if( psDefn->Ellipsoid != KvUserDefined )
668 1012 : oSRS.SetAuthority( "SPHEROID", "EPSG", psDefn->Ellipsoid );
669 :
670 1039 : CPLFree( pszGeogName );
671 1039 : CPLFree( pszDatumName );
672 1039 : CPLFree( pszSpheroidName );
673 1039 : CPLFree( pszPMName );
674 1039 : CPLFree( pszAngularUnits );
675 :
676 : #if LIBGEOTIFF_VERSION >= 1310 && !defined(GEO_NORMALIZE_DISABLE_TOWGS84)
677 1039 : if( psDefn->TOWGS84Count > 0 )
678 : oSRS.SetTOWGS84( psDefn->TOWGS84[0],
679 : psDefn->TOWGS84[1],
680 : psDefn->TOWGS84[2],
681 : psDefn->TOWGS84[3],
682 : psDefn->TOWGS84[4],
683 : psDefn->TOWGS84[5],
684 27 : psDefn->TOWGS84[6] );
685 : #endif
686 :
687 : /* ==================================================================== */
688 : /* Handle projection parameters. */
689 : /* ==================================================================== */
690 1039 : if( psDefn->Model == ModelTypeProjected )
691 : {
692 : /* -------------------------------------------------------------------- */
693 : /* Make a local copy of parms, and convert back into the */
694 : /* angular units of the GEOGCS and the linear units of the */
695 : /* projection. */
696 : /* -------------------------------------------------------------------- */
697 : double adfParm[10];
698 : int i;
699 :
700 4920 : for( i = 0; i < MIN(10,psDefn->nParms); i++ )
701 4305 : adfParm[i] = psDefn->ProjParm[i];
702 :
703 2460 : for( ; i < 10; i++ )
704 1845 : adfParm[i] = 0.0;
705 :
706 615 : if(!aUnitGot)
707 : {
708 615 : adfParm[0] *= psDefn->UOMAngleInDegrees;
709 615 : adfParm[1] *= psDefn->UOMAngleInDegrees;
710 615 : adfParm[2] *= psDefn->UOMAngleInDegrees;
711 615 : adfParm[3] *= psDefn->UOMAngleInDegrees;
712 : }
713 615 : int unitCode = 0;
714 615 : GTIFKeyGet(hGTIF, ProjLinearUnitsGeoKey, &unitCode, 0, 1 );
715 615 : if(unitCode != KvUserDefined)
716 : {
717 614 : adfParm[5] /= psDefn->UOMLengthInMeters;
718 614 : adfParm[6] /= psDefn->UOMLengthInMeters;
719 : }
720 :
721 : /* -------------------------------------------------------------------- */
722 : /* Translation the fundamental projection. */
723 : /* -------------------------------------------------------------------- */
724 615 : switch( psDefn->CTProjection )
725 : {
726 : case CT_TransverseMercator:
727 : oSRS.SetTM( adfParm[0], adfParm[1],
728 : adfParm[4],
729 532 : adfParm[5], adfParm[6] );
730 532 : break;
731 :
732 : case CT_TransvMercator_SouthOriented:
733 : oSRS.SetTMSO( adfParm[0], adfParm[1],
734 : adfParm[4],
735 2 : adfParm[5], adfParm[6] );
736 2 : break;
737 :
738 : case CT_Mercator:
739 : oSRS.SetMercator( adfParm[0], adfParm[1],
740 : adfParm[4],
741 12 : adfParm[5], adfParm[6] );
742 :
743 12 : if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator.
744 : {
745 : oSRS.SetExtension( "PROJCS", "PROJ4",
746 8 : "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs" );
747 : }
748 12 : break;
749 :
750 : case CT_ObliqueStereographic:
751 : oSRS.SetOS( adfParm[0], adfParm[1],
752 : adfParm[4],
753 2 : adfParm[5], adfParm[6] );
754 2 : break;
755 :
756 : case CT_Stereographic:
757 : oSRS.SetStereographic( adfParm[0], adfParm[1],
758 : adfParm[4],
759 2 : adfParm[5], adfParm[6] );
760 2 : break;
761 :
762 : case CT_ObliqueMercator: /* hotine */
763 : oSRS.SetHOM( adfParm[0], adfParm[1],
764 : adfParm[2], adfParm[3],
765 : adfParm[4],
766 0 : adfParm[5], adfParm[6] );
767 0 : break;
768 :
769 : case CT_HotineObliqueMercatorAzimuthCenter:
770 : oSRS.SetHOMAC( adfParm[0], adfParm[1],
771 : adfParm[2], adfParm[3],
772 : adfParm[4],
773 4 : adfParm[5], adfParm[6] );
774 4 : break;
775 :
776 : case CT_EquidistantConic:
777 : oSRS.SetEC( adfParm[0], adfParm[1],
778 : adfParm[2], adfParm[3],
779 0 : adfParm[5], adfParm[6] );
780 0 : break;
781 :
782 : case CT_CassiniSoldner:
783 : oSRS.SetCS( adfParm[0], adfParm[1],
784 2 : adfParm[5], adfParm[6] );
785 2 : break;
786 :
787 : case CT_Polyconic:
788 : oSRS.SetPolyconic( adfParm[0], adfParm[1],
789 1 : adfParm[5], adfParm[6] );
790 1 : break;
791 :
792 : case CT_AzimuthalEquidistant:
793 : oSRS.SetAE( adfParm[0], adfParm[1],
794 11 : adfParm[5], adfParm[6] );
795 11 : break;
796 :
797 : case CT_MillerCylindrical:
798 : oSRS.SetMC( adfParm[0], adfParm[1],
799 0 : adfParm[5], adfParm[6] );
800 0 : break;
801 :
802 : case CT_Equirectangular:
803 : oSRS.SetEquirectangular2( adfParm[0], adfParm[1],
804 : adfParm[2],
805 2 : adfParm[5], adfParm[6] );
806 2 : break;
807 :
808 : case CT_Gnomonic:
809 : oSRS.SetGnomonic( adfParm[0], adfParm[1],
810 0 : adfParm[5], adfParm[6] );
811 0 : break;
812 :
813 : case CT_LambertAzimEqualArea:
814 : oSRS.SetLAEA( adfParm[0], adfParm[1],
815 4 : adfParm[5], adfParm[6] );
816 4 : break;
817 :
818 : case CT_Orthographic:
819 : oSRS.SetOrthographic( adfParm[0], adfParm[1],
820 2 : adfParm[5], adfParm[6] );
821 2 : break;
822 :
823 : case CT_Robinson:
824 : oSRS.SetRobinson( adfParm[1],
825 0 : adfParm[5], adfParm[6] );
826 0 : break;
827 :
828 : case CT_Sinusoidal:
829 : oSRS.SetSinusoidal( adfParm[1],
830 0 : adfParm[5], adfParm[6] );
831 0 : break;
832 :
833 : case CT_VanDerGrinten:
834 : oSRS.SetVDG( adfParm[1],
835 1 : adfParm[5], adfParm[6] );
836 1 : break;
837 :
838 : case CT_PolarStereographic:
839 : oSRS.SetPS( adfParm[0], adfParm[1],
840 : adfParm[4],
841 6 : adfParm[5], adfParm[6] );
842 6 : break;
843 :
844 : case CT_LambertConfConic_2SP:
845 : oSRS.SetLCC( adfParm[2], adfParm[3],
846 : adfParm[0], adfParm[1],
847 14 : adfParm[5], adfParm[6] );
848 14 : break;
849 :
850 : case CT_LambertConfConic_1SP:
851 : oSRS.SetLCC1SP( adfParm[0], adfParm[1],
852 : adfParm[4],
853 5 : adfParm[5], adfParm[6] );
854 5 : break;
855 :
856 : case CT_AlbersEqualArea:
857 : oSRS.SetACEA( adfParm[0], adfParm[1],
858 : adfParm[2], adfParm[3],
859 4 : adfParm[5], adfParm[6] );
860 4 : break;
861 :
862 : case CT_NewZealandMapGrid:
863 : oSRS.SetNZMG( adfParm[0], adfParm[1],
864 2 : adfParm[5], adfParm[6] );
865 2 : break;
866 :
867 : case CT_CylindricalEqualArea:
868 : oSRS.SetCEA( adfParm[0], adfParm[1],
869 4 : adfParm[5], adfParm[6] );
870 4 : break;
871 : default:
872 3 : if( oSRS.IsProjected() )
873 3 : oSRS.GetRoot()->SetValue( "LOCAL_CS" );
874 : break;
875 : }
876 :
877 : /* -------------------------------------------------------------------- */
878 : /* Set projection units. */
879 : /* -------------------------------------------------------------------- */
880 615 : if(!linearUnitIsSet)
881 : {
882 615 : char *pszUnitsName = NULL;
883 :
884 615 : GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
885 :
886 1229 : if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
887 : {
888 614 : oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
889 614 : oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
890 : }
891 : else
892 1 : oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
893 :
894 615 : GTIFFreeMemory( pszUnitsName );
895 : }
896 : }
897 :
898 : /* ==================================================================== */
899 : /* Handle vertical coordinate system information if we have it. */
900 : /* ==================================================================== */
901 1039 : short verticalCSType = -1;
902 1039 : short verticalDatum = -1;
903 1039 : short verticalUnits = -1;
904 1039 : const char *pszFilename = NULL;
905 : const char *pszValue;
906 : char szSearchKey[128];
907 1039 : bool bNeedManualVertCS = false;
908 : char citation[2048];
909 :
910 : // Don't do anything if there is no apparent vertical information.
911 1039 : GTIFKeyGet( hGTIF, VerticalCSTypeGeoKey, &verticalCSType, 0, 1 );
912 1039 : GTIFKeyGet( hGTIF, VerticalDatumGeoKey, &verticalDatum, 0, 1 );
913 1039 : GTIFKeyGet( hGTIF, VerticalUnitsGeoKey, &verticalUnits, 0, 1 );
914 :
915 1039 : if( (verticalCSType != -1 || verticalDatum != -1 || verticalUnits != -1)
916 : && (oSRS.IsGeographic() || oSRS.IsProjected() || oSRS.IsLocal()) )
917 : {
918 2 : if( !GTIFKeyGet( hGTIF, VerticalCitationGeoKey, &citation,
919 : 0, sizeof(citation) ) )
920 0 : strcpy( citation, "unknown" );
921 :
922 : /* -------------------------------------------------------------------- */
923 : /* The original geotiff specification appears to have */
924 : /* misconstrued the EPSG codes 5101 to 5106 to be vertical */
925 : /* coordinate system codes, when in fact they are vertical */
926 : /* datum codes. So if these are found in the */
927 : /* VerticalCSTypeGeoKey move them to the VerticalDatumGeoKey */
928 : /* and insert the "normal" corresponding VerticalCSTypeGeoKey */
929 : /* value. */
930 : /* -------------------------------------------------------------------- */
931 2 : if( (verticalCSType >= 5101 && verticalCSType <= 5112)
932 : && verticalDatum == -1 )
933 : {
934 0 : verticalDatum = verticalCSType;
935 0 : verticalCSType = verticalDatum + 600;
936 : }
937 :
938 : /* -------------------------------------------------------------------- */
939 : /* This addresses another case where the EGM96 Vertical Datum code */
940 : /* is mis-used as a Vertical CS code (#4922) */
941 : /* -------------------------------------------------------------------- */
942 2 : if( verticalCSType == 5171 )
943 : {
944 0 : verticalDatum = 5171;
945 0 : verticalCSType = 5773;
946 : }
947 :
948 : /* -------------------------------------------------------------------- */
949 : /* Somewhat similarly, codes 5001 to 5033 were treated as */
950 : /* vertical coordinate systems based on ellipsoidal heights. */
951 : /* We use the corresponding 2d geodetic datum as the vertical */
952 : /* datum and clear the vertical coordinate system code since */
953 : /* there isn't one in epsg. */
954 : /* -------------------------------------------------------------------- */
955 2 : if( (verticalCSType >= 5001 && verticalCSType <= 5033)
956 : && verticalDatum == -1 )
957 : {
958 0 : verticalDatum = verticalCSType+1000;
959 0 : verticalCSType = -1;
960 : }
961 :
962 : /* -------------------------------------------------------------------- */
963 : /* Promote to being a compound coordinate system. */
964 : /* -------------------------------------------------------------------- */
965 2 : OGR_SRSNode *poOldRoot = oSRS.GetRoot()->Clone();
966 :
967 2 : oSRS.Clear();
968 2 : oSRS.SetNode( "COMPD_CS", "unknown" );
969 2 : oSRS.GetRoot()->AddChild( poOldRoot );
970 :
971 : /* -------------------------------------------------------------------- */
972 : /* If we have the vertical cs, try to look it up using the */
973 : /* vertcs.csv file, and use the definition provided by that. */
974 : /* -------------------------------------------------------------------- */
975 2 : bNeedManualVertCS = true;
976 :
977 2 : if( verticalCSType != KvUserDefined && verticalCSType > 0 )
978 : {
979 2 : OGRSpatialReference oVertSRS;
980 2 : if( oVertSRS.importFromEPSG( verticalCSType ) == OGRERR_NONE )
981 : {
982 2 : oSRS.GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
983 2 : bNeedManualVertCS = false;
984 2 : }
985 : }
986 : }
987 :
988 : /* -------------------------------------------------------------------- */
989 : /* Collect some information from the VerticalCS if not provided */
990 : /* via geokeys. */
991 : /* -------------------------------------------------------------------- */
992 1039 : if( bNeedManualVertCS )
993 : {
994 0 : if( verticalCSType > 0 && verticalCSType != KvUserDefined )
995 : {
996 0 : pszFilename = CSVFilename( "coordinate_reference_system.csv" );
997 0 : sprintf( szSearchKey, "%d", verticalCSType );
998 :
999 0 : if( verticalDatum < 1 || verticalDatum == KvUserDefined )
1000 : {
1001 : pszValue = CSVGetField( pszFilename,
1002 : "coord_ref_sys_code",
1003 : szSearchKey, CC_Integer,
1004 0 : "datum_code" );
1005 0 : if( pszValue != NULL )
1006 0 : verticalDatum = (short) atoi(pszValue);
1007 : }
1008 :
1009 0 : if( EQUAL(citation,"unknown") )
1010 : {
1011 : pszValue = CSVGetField( pszFilename,
1012 : "coord_ref_sys_code",
1013 : szSearchKey, CC_Integer,
1014 0 : "coord_ref_sys_name" );
1015 0 : if( pszValue != NULL && *pszValue != '\0' )
1016 0 : strncpy( citation, pszValue, sizeof(citation) );
1017 : }
1018 :
1019 0 : if( verticalUnits < 1 || verticalUnits == KvUserDefined )
1020 : {
1021 : pszValue = CSVGetField( pszFilename,
1022 : "coord_ref_sys_code",
1023 : szSearchKey, CC_Integer,
1024 0 : "coord_sys_code" );
1025 0 : if( pszValue != NULL )
1026 : {
1027 0 : pszFilename = CSVFilename( "coordinate_axis.csv" );
1028 : pszValue = CSVGetField( pszFilename,
1029 : "coord_sys_code",
1030 : pszValue, CC_Integer,
1031 0 : "uom_code" );
1032 0 : if( pszValue != NULL )
1033 0 : verticalUnits = (short) atoi(pszValue);
1034 : }
1035 : }
1036 : }
1037 :
1038 : /* -------------------------------------------------------------------- */
1039 : /* Setup VERT_CS with citation if present. */
1040 : /* -------------------------------------------------------------------- */
1041 0 : oSRS.SetNode( "COMPD_CS|VERT_CS", citation );
1042 :
1043 : /* -------------------------------------------------------------------- */
1044 : /* Setup the vertical datum. */
1045 : /* -------------------------------------------------------------------- */
1046 0 : const char *pszVDatumName = "unknown";
1047 0 : const char *pszVDatumType = "2005"; // CS_VD_GeoidModelDerived
1048 :
1049 0 : if( verticalDatum > 0 && verticalDatum != KvUserDefined )
1050 : {
1051 0 : pszFilename = CSVFilename( "datum.csv" );
1052 0 : if( EQUAL(pszFilename,"datum.csv") )
1053 0 : pszFilename = CSVFilename( "gdal_datum.csv" );
1054 :
1055 0 : sprintf( szSearchKey, "%d", verticalDatum );
1056 :
1057 : pszValue = CSVGetField( pszFilename,
1058 : "DATUM_CODE", szSearchKey, CC_Integer,
1059 0 : "DATUM_NAME" );
1060 0 : if( pszValue != NULL && *pszValue != '\0' )
1061 0 : pszVDatumName = pszValue;
1062 :
1063 : pszValue = CSVGetField( pszFilename,
1064 : "DATUM_CODE", szSearchKey, CC_Integer,
1065 0 : "DATUM_TYPE" );
1066 0 : if( pszValue != NULL && EQUALN(pszValue,"geodetic",8) )
1067 0 : pszVDatumType = "2002"; // CS_VD_Ellipsoidal
1068 :
1069 : // We unfortunately don't know how to identify other
1070 : // vertical datum types, particularly orthometric (2001).
1071 : }
1072 :
1073 0 : oSRS.SetNode( "COMPD_CS|VERT_CS|VERT_DATUM", pszVDatumName );
1074 : oSRS.GetAttrNode( "COMPD_CS|VERT_CS|VERT_DATUM" )
1075 0 : ->AddChild( new OGR_SRSNode( pszVDatumType ) );
1076 0 : if( verticalDatum > 0 && verticalDatum != KvUserDefined )
1077 : oSRS.SetAuthority( "COMPD_CS|VERT_CS|VERT_DATUM", "EPSG",
1078 0 : verticalDatum );
1079 :
1080 : /* -------------------------------------------------------------------- */
1081 : /* Set the vertical units. */
1082 : /* -------------------------------------------------------------------- */
1083 0 : if( verticalUnits > 0 && verticalUnits != KvUserDefined
1084 : && verticalUnits != 9001 )
1085 : {
1086 : char szInMeters[128];
1087 :
1088 0 : pszFilename = CSVFilename("unit_of_measure.csv");
1089 :
1090 : // Name
1091 0 : sprintf( szSearchKey, "%d", verticalUnits );
1092 : pszValue = CSVGetField( pszFilename,
1093 : "uom_code", szSearchKey, CC_Integer,
1094 0 : "unit_of_meas_name" );
1095 0 : if( pszValue == NULL )
1096 0 : pszValue = "unknown";
1097 :
1098 0 : oSRS.SetNode( "COMPD_CS|VERT_CS|UNIT", pszValue );
1099 :
1100 : // Value
1101 : double dfFactorB, dfFactorC;
1102 : dfFactorB = GTIFAtof(
1103 : CSVGetField( pszFilename,
1104 : "uom_code", szSearchKey, CC_Integer,
1105 0 : "factor_b" ));
1106 : dfFactorC = GTIFAtof(
1107 : CSVGetField( pszFilename,
1108 : "uom_code", szSearchKey, CC_Integer,
1109 0 : "factor_c" ));
1110 0 : if( dfFactorB != 0.0 && dfFactorC != 0.0 )
1111 0 : sprintf( szInMeters, "%.16g", dfFactorB / dfFactorC );
1112 : else
1113 0 : strcpy( szInMeters, "1" );
1114 :
1115 :
1116 : oSRS.GetAttrNode( "COMPD_CS|VERT_CS|UNIT" )
1117 0 : ->AddChild( new OGR_SRSNode( szInMeters ) );
1118 :
1119 0 : oSRS.SetAuthority( "COMPD_CS|VERT_CS|UNIT", "EPSG", verticalUnits);
1120 : }
1121 : else
1122 : {
1123 0 : oSRS.SetNode( "COMPD_CS|VERT_CS|UNIT", "metre" );
1124 : oSRS.GetAttrNode( "COMPD_CS|VERT_CS|UNIT" )
1125 0 : ->AddChild( new OGR_SRSNode( "1.0" ) );
1126 0 : oSRS.SetAuthority( "COMPD_CS|VERT_CS|UNIT", "EPSG", 9001 );
1127 : }
1128 :
1129 : /* -------------------------------------------------------------------- */
1130 : /* Set the axis and VERT_CS authority. */
1131 : /* -------------------------------------------------------------------- */
1132 0 : oSRS.SetNode( "COMPD_CS|VERT_CS|AXIS", "Up" );
1133 : oSRS.GetAttrNode( "COMPD_CS|VERT_CS|AXIS" )
1134 0 : ->AddChild( new OGR_SRSNode( "UP" ) );
1135 :
1136 0 : if( verticalCSType > 0 && verticalCSType != KvUserDefined )
1137 0 : oSRS.SetAuthority( "COMPD_CS|VERT_CS", "EPSG", verticalCSType );
1138 : }
1139 :
1140 : /* ==================================================================== */
1141 : /* Return the WKT serialization of the object. */
1142 : /* ==================================================================== */
1143 : char *pszWKT;
1144 :
1145 1039 : oSRS.FixupOrdering();
1146 :
1147 1039 : if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
1148 1039 : return pszWKT;
1149 : else
1150 0 : return NULL;
1151 : }
1152 :
1153 : /************************************************************************/
1154 : /* OGCDatumName2EPSGDatumCode() */
1155 : /************************************************************************/
1156 :
1157 375 : static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
1158 :
1159 : {
1160 : FILE *fp;
1161 : char **papszTokens;
1162 375 : int nReturn = KvUserDefined;
1163 :
1164 :
1165 : /* -------------------------------------------------------------------- */
1166 : /* Do we know it as a built in? */
1167 : /* -------------------------------------------------------------------- */
1168 375 : if( EQUAL(pszOGCName,"NAD27")
1169 : || EQUAL(pszOGCName,"North_American_Datum_1927") )
1170 0 : return Datum_North_American_Datum_1927;
1171 375 : else if( EQUAL(pszOGCName,"NAD83")
1172 : || EQUAL(pszOGCName,"North_American_Datum_1983") )
1173 1 : return Datum_North_American_Datum_1983;
1174 374 : else if( EQUAL(pszOGCName,"WGS84") || EQUAL(pszOGCName,"WGS_1984")
1175 : || EQUAL(pszOGCName,"WGS 84"))
1176 345 : return Datum_WGS84;
1177 29 : else if( EQUAL(pszOGCName,"WGS72") || EQUAL(pszOGCName,"WGS_1972") )
1178 3 : return Datum_WGS72;
1179 :
1180 : /* -------------------------------------------------------------------- */
1181 : /* Open the table if possible. */
1182 : /* -------------------------------------------------------------------- */
1183 26 : fp = VSIFOpen( CSVFilename("gdal_datum.csv"), "r" );
1184 26 : if( fp == NULL )
1185 0 : fp = VSIFOpen( CSVFilename("datum.csv"), "r" );
1186 :
1187 26 : if( fp == NULL )
1188 0 : return nReturn;
1189 :
1190 : /* -------------------------------------------------------------------- */
1191 : /* Discard the first line with field names. */
1192 : /* -------------------------------------------------------------------- */
1193 26 : CSLDestroy( CSVReadParseLine( fp ) );
1194 :
1195 : /* -------------------------------------------------------------------- */
1196 : /* Read lines looking for our datum. */
1197 : /* -------------------------------------------------------------------- */
1198 16406 : for( papszTokens = CSVReadParseLine( fp );
1199 : CSLCount(papszTokens) > 2 && nReturn == KvUserDefined;
1200 : papszTokens = CSVReadParseLine( fp ) )
1201 : {
1202 16380 : WKTMassageDatum( papszTokens + 1 );
1203 :
1204 16380 : if( EQUAL(papszTokens[1], pszOGCName) )
1205 0 : nReturn = atoi(papszTokens[0]);
1206 :
1207 16380 : CSLDestroy( papszTokens );
1208 : }
1209 :
1210 26 : CSLDestroy( papszTokens );
1211 26 : VSIFClose( fp );
1212 :
1213 26 : return nReturn;
1214 : }
1215 :
1216 : /************************************************************************/
1217 : /* GTIFSetFromOGISDefn() */
1218 : /* */
1219 : /* Write GeoTIFF projection tags from an OGC WKT definition. */
1220 : /************************************************************************/
1221 :
1222 945 : int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
1223 :
1224 : {
1225 : OGRSpatialReference *poSRS;
1226 945 : int nPCS = KvUserDefined;
1227 : OGRErr eErr;
1228 945 : OGRBoolean peStrStored = FALSE;
1229 :
1230 : GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
1231 945 : RasterPixelIsArea);
1232 :
1233 : /* -------------------------------------------------------------------- */
1234 : /* Create an OGRSpatialReference object corresponding to the */
1235 : /* string. */
1236 : /* -------------------------------------------------------------------- */
1237 945 : poSRS = new OGRSpatialReference();
1238 945 : if( poSRS->importFromWkt((char **) &pszOGCWKT) != OGRERR_NONE )
1239 : {
1240 1 : delete poSRS;
1241 1 : return FALSE;
1242 : }
1243 :
1244 : /* -------------------------------------------------------------------- */
1245 : /* Get the ellipsoid definition. */
1246 : /* -------------------------------------------------------------------- */
1247 944 : short nSpheroid = KvUserDefined;
1248 : double dfSemiMajor, dfInvFlattening;
1249 :
1250 944 : if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID") != NULL
1251 : && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID"),
1252 : "EPSG"))
1253 : {
1254 : nSpheroid = (short)
1255 253 : atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM|SPHEROID"));
1256 : }
1257 691 : else if( poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID") != NULL
1258 : && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID"),"EPSG"))
1259 : {
1260 : nSpheroid = (short)
1261 317 : atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM|SPHEROID"));
1262 : }
1263 :
1264 944 : dfSemiMajor = poSRS->GetSemiMajor( &eErr );
1265 944 : dfInvFlattening = poSRS->GetInvFlattening( &eErr );
1266 944 : if( eErr != OGRERR_NONE )
1267 : {
1268 3 : dfSemiMajor = 0.0;
1269 3 : dfInvFlattening = 0.0;
1270 : }
1271 :
1272 : /* -------------------------------------------------------------------- */
1273 : /* Get the Datum so we can special case a few PCS codes. */
1274 : /* -------------------------------------------------------------------- */
1275 944 : int nDatum = KvUserDefined;
1276 :
1277 944 : if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM") != NULL
1278 : && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM"),"EPSG") )
1279 252 : nDatum = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM"));
1280 692 : else if( poSRS->GetAuthorityName("GEOGCS|DATUM") != NULL
1281 : && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM"),"EPSG") )
1282 317 : nDatum = atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM"));
1283 375 : else if( poSRS->GetAttrValue("DATUM") != NULL )
1284 375 : nDatum = OGCDatumName2EPSGDatumCode( poSRS->GetAttrValue("DATUM") );
1285 :
1286 : /* -------------------------------------------------------------------- */
1287 : /* Get the GCS if possible. */
1288 : /* -------------------------------------------------------------------- */
1289 944 : int nGCS = KvUserDefined;
1290 :
1291 944 : if( poSRS->GetAuthorityName("PROJCS|GEOGCS") != NULL
1292 : && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS"),"EPSG") )
1293 252 : nGCS = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS"));
1294 692 : else if( poSRS->GetAuthorityName("GEOGCS") != NULL
1295 : && EQUAL(poSRS->GetAuthorityName("GEOGCS"),"EPSG") )
1296 328 : nGCS = atoi(poSRS->GetAuthorityCode("GEOGCS"));
1297 :
1298 944 : if( nGCS > 32767 )
1299 0 : nGCS = KvUserDefined;
1300 :
1301 : /* -------------------------------------------------------------------- */
1302 : /* Get the linear units. */
1303 : /* -------------------------------------------------------------------- */
1304 944 : char *pszLinearUOMName = NULL;
1305 944 : double dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName );
1306 944 : int nUOMLengthCode = 9001; /* meters */
1307 :
1308 944 : if( poSRS->GetAuthorityName("PROJCS|UNIT") != NULL
1309 : && EQUAL(poSRS->GetAuthorityName("PROJCS|UNIT"),"EPSG")
1310 : && poSRS->GetAttrNode( "PROJCS|UNIT" ) != poSRS->GetAttrNode("GEOGCS|UNIT") )
1311 244 : nUOMLengthCode = atoi(poSRS->GetAuthorityCode("PROJCS|UNIT"));
1312 700 : else if( (pszLinearUOMName != NULL
1313 : && EQUAL(pszLinearUOMName,SRS_UL_FOOT))
1314 : || fabs(dfLinearUOM-GTIFAtof(SRS_UL_FOOT_CONV)) < 0.0000001 )
1315 0 : nUOMLengthCode = 9002; /* international foot */
1316 700 : else if( (pszLinearUOMName != NULL
1317 : && EQUAL(pszLinearUOMName,SRS_UL_US_FOOT))
1318 : || ABS(dfLinearUOM-GTIFAtof(SRS_UL_US_FOOT_CONV)) < 0.0000001 )
1319 2 : nUOMLengthCode = 9003; /* us survey foot */
1320 698 : else if( fabs(dfLinearUOM-1.0) > 0.00000001 )
1321 1 : nUOMLengthCode = KvUserDefined;
1322 :
1323 : /* -------------------------------------------------------------------- */
1324 : /* Get some authority values. */
1325 : /* -------------------------------------------------------------------- */
1326 944 : if( poSRS->GetAuthorityName("PROJCS") != NULL
1327 : && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG") )
1328 : {
1329 239 : nPCS = atoi(poSRS->GetAuthorityCode("PROJCS"));
1330 239 : if( nPCS > 32767 )
1331 0 : nPCS = KvUserDefined;
1332 : }
1333 :
1334 : /* -------------------------------------------------------------------- */
1335 : /* Handle the projection transformation. */
1336 : /* -------------------------------------------------------------------- */
1337 944 : const char *pszProjection = poSRS->GetAttrValue( "PROJECTION" );
1338 944 : int bWritePEString = FALSE;
1339 :
1340 944 : if( nPCS != KvUserDefined )
1341 : {
1342 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1343 239 : ModelTypeProjected);
1344 239 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
1345 : }
1346 705 : else if( poSRS->IsGeocentric() )
1347 : {
1348 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1349 0 : ModelTypeGeocentric );
1350 : }
1351 705 : else if( pszProjection == NULL )
1352 : {
1353 666 : if( poSRS->IsGeographic() )
1354 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1355 666 : ModelTypeGeographic);
1356 : // otherwise, presumably something like LOCAL_CS.
1357 : }
1358 39 : else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
1359 : {
1360 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1361 1 : ModelTypeProjected);
1362 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1363 1 : KvUserDefined );
1364 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1365 1 : KvUserDefined );
1366 :
1367 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1368 1 : CT_AlbersEqualArea );
1369 :
1370 : GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1,
1371 1 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
1372 :
1373 : GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
1374 1 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
1375 :
1376 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1377 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
1378 :
1379 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1380 1 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1381 :
1382 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1383 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1384 :
1385 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1386 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1387 : }
1388 :
1389 38 : else if( poSRS->GetUTMZone() != 0 )
1390 : {
1391 : int bNorth, nZone, nProjection;
1392 :
1393 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1394 2 : ModelTypeProjected);
1395 :
1396 2 : nZone = poSRS->GetUTMZone( &bNorth );
1397 :
1398 2 : if( nDatum == Datum_North_American_Datum_1983 && nZone >= 3
1399 : && nZone <= 22 && bNorth && nUOMLengthCode == 9001 )
1400 : {
1401 0 : nPCS = 26900 + nZone;
1402 :
1403 0 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
1404 : }
1405 2 : else if( nDatum == Datum_North_American_Datum_1927 && nZone >= 3
1406 : && nZone <= 22 && bNorth && nUOMLengthCode == 9001 )
1407 : {
1408 0 : nPCS = 26700 + nZone;
1409 :
1410 0 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
1411 : }
1412 2 : else if( nDatum == Datum_WGS84 && nUOMLengthCode == 9001 )
1413 : {
1414 0 : if( bNorth )
1415 0 : nPCS = 32600 + nZone;
1416 : else
1417 0 : nPCS = 32700 + nZone;
1418 :
1419 0 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
1420 : }
1421 : else
1422 : {
1423 2 : if( bNorth )
1424 2 : nProjection = 16000 + nZone;
1425 : else
1426 0 : nProjection = 16100 + nZone;
1427 :
1428 :
1429 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1430 2 : KvUserDefined );
1431 :
1432 2 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, nProjection );
1433 : }
1434 : }
1435 :
1436 36 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
1437 : {
1438 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1439 1 : ModelTypeProjected);
1440 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1441 1 : KvUserDefined );
1442 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1443 1 : KvUserDefined );
1444 :
1445 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1446 1 : CT_TransverseMercator );
1447 :
1448 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1449 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1450 :
1451 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1452 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1453 :
1454 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
1455 1 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1456 :
1457 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1458 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1459 :
1460 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1461 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1462 : }
1463 :
1464 35 : else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
1465 : {
1466 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1467 1 : ModelTypeProjected);
1468 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1469 1 : KvUserDefined );
1470 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1471 1 : KvUserDefined );
1472 :
1473 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1474 1 : CT_TransvMercator_SouthOriented );
1475 :
1476 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1477 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1478 :
1479 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1480 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1481 :
1482 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
1483 1 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1484 :
1485 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1486 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1487 :
1488 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1489 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1490 : }
1491 :
1492 36 : else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP)
1493 : || EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
1494 :
1495 : {
1496 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1497 2 : ModelTypeProjected);
1498 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1499 2 : KvUserDefined );
1500 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1501 2 : KvUserDefined );
1502 :
1503 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1504 2 : CT_Mercator );
1505 :
1506 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1507 2 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1508 :
1509 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1510 2 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1511 :
1512 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
1513 2 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1514 :
1515 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1516 2 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1517 :
1518 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1519 2 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1520 : }
1521 :
1522 32 : else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
1523 : {
1524 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1525 1 : ModelTypeProjected);
1526 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1527 1 : KvUserDefined );
1528 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1529 1 : KvUserDefined );
1530 :
1531 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1532 1 : CT_ObliqueStereographic );
1533 :
1534 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1535 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1536 :
1537 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1538 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1539 :
1540 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
1541 1 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1542 :
1543 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1544 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1545 :
1546 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1547 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1548 : }
1549 :
1550 31 : else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
1551 : {
1552 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1553 1 : ModelTypeProjected);
1554 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1555 1 : KvUserDefined );
1556 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1557 1 : KvUserDefined );
1558 :
1559 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1560 1 : CT_Stereographic );
1561 :
1562 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1563 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1564 :
1565 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1566 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1567 :
1568 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
1569 1 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1570 :
1571 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1572 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1573 :
1574 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1575 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1576 : }
1577 :
1578 30 : else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
1579 : {
1580 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1581 3 : ModelTypeProjected);
1582 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1583 3 : KvUserDefined );
1584 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1585 3 : KvUserDefined );
1586 :
1587 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1588 3 : CT_PolarStereographic );
1589 :
1590 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1591 3 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1592 :
1593 : GTIFKeySet(psGTIF, ProjStraightVertPoleLongGeoKey, TYPE_DOUBLE, 1,
1594 3 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1595 :
1596 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
1597 3 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1598 :
1599 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1600 3 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1601 :
1602 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1603 3 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1604 : }
1605 :
1606 27 : else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
1607 : {
1608 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1609 0 : ModelTypeProjected);
1610 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1611 0 : KvUserDefined );
1612 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1613 0 : KvUserDefined );
1614 :
1615 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1616 0 : CT_ObliqueMercator );
1617 :
1618 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1619 0 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
1620 :
1621 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1622 0 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1623 :
1624 : GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1,
1625 0 : poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) );
1626 :
1627 : GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1,
1628 0 : poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) );
1629 :
1630 : GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1,
1631 0 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1632 :
1633 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1634 0 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1635 :
1636 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1637 0 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1638 : }
1639 :
1640 27 : else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
1641 : {
1642 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1643 2 : ModelTypeProjected);
1644 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1645 2 : KvUserDefined );
1646 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1647 2 : KvUserDefined );
1648 :
1649 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1650 2 : CT_HotineObliqueMercatorAzimuthCenter );
1651 :
1652 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1653 2 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
1654 :
1655 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1656 2 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1657 :
1658 : GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1,
1659 2 : poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) );
1660 :
1661 : GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1,
1662 2 : poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) );
1663 :
1664 : GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1,
1665 2 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1666 :
1667 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1668 2 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1669 :
1670 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1671 2 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1672 : }
1673 :
1674 25 : else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
1675 : {
1676 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1677 1 : ModelTypeProjected);
1678 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1679 1 : KvUserDefined );
1680 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1681 1 : KvUserDefined );
1682 :
1683 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1684 1 : CT_CassiniSoldner );
1685 :
1686 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1687 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1688 :
1689 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1690 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1691 :
1692 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1693 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1694 :
1695 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1696 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1697 : }
1698 :
1699 24 : else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
1700 : {
1701 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1702 0 : ModelTypeProjected);
1703 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1704 0 : KvUserDefined );
1705 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1706 0 : KvUserDefined );
1707 :
1708 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1709 0 : CT_EquidistantConic );
1710 :
1711 : GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
1712 0 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
1713 :
1714 : GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
1715 0 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
1716 :
1717 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1718 0 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
1719 :
1720 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1721 0 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1722 :
1723 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1724 0 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1725 :
1726 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1727 0 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1728 : }
1729 :
1730 24 : else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
1731 : {
1732 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1733 1 : ModelTypeProjected);
1734 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1735 1 : KvUserDefined );
1736 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1737 1 : KvUserDefined );
1738 :
1739 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1740 1 : CT_Polyconic );
1741 :
1742 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1743 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1744 :
1745 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1746 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1747 :
1748 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
1749 1 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
1750 :
1751 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1752 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1753 :
1754 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1755 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1756 : }
1757 :
1758 23 : else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
1759 : {
1760 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1761 4 : ModelTypeProjected);
1762 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1763 4 : KvUserDefined );
1764 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1765 4 : KvUserDefined );
1766 :
1767 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1768 4 : CT_AzimuthalEquidistant );
1769 :
1770 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1771 4 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
1772 :
1773 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1774 4 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1775 :
1776 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1777 4 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1778 :
1779 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1780 4 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1781 : }
1782 :
1783 19 : else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
1784 : {
1785 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1786 0 : ModelTypeProjected);
1787 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1788 0 : KvUserDefined );
1789 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1790 0 : KvUserDefined );
1791 :
1792 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1793 0 : CT_MillerCylindrical );
1794 :
1795 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1796 0 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
1797 :
1798 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1799 0 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1800 :
1801 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1802 0 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1803 :
1804 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1805 0 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1806 : }
1807 :
1808 19 : else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
1809 : {
1810 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1811 2 : ModelTypeProjected);
1812 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1813 2 : KvUserDefined );
1814 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1815 2 : KvUserDefined );
1816 :
1817 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1818 2 : CT_Equirectangular );
1819 :
1820 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1821 2 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1822 :
1823 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1824 2 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1825 :
1826 : GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
1827 2 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
1828 :
1829 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1830 2 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1831 :
1832 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1833 2 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1834 : }
1835 :
1836 17 : else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
1837 : {
1838 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1839 0 : ModelTypeProjected);
1840 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1841 0 : KvUserDefined );
1842 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1843 0 : KvUserDefined );
1844 :
1845 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1846 0 : CT_Gnomonic );
1847 :
1848 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1849 0 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1850 :
1851 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1852 0 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1853 :
1854 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1855 0 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1856 :
1857 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1858 0 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1859 : }
1860 :
1861 17 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
1862 : {
1863 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1864 2 : ModelTypeProjected);
1865 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1866 2 : KvUserDefined );
1867 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1868 2 : KvUserDefined );
1869 :
1870 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1871 2 : CT_LambertAzimEqualArea );
1872 :
1873 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1874 2 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
1875 :
1876 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1877 2 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1878 :
1879 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1880 2 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1881 :
1882 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1883 2 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1884 : }
1885 :
1886 15 : else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
1887 : {
1888 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1889 1 : ModelTypeProjected);
1890 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1891 1 : KvUserDefined );
1892 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1893 1 : KvUserDefined );
1894 :
1895 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1896 1 : CT_Orthographic );
1897 :
1898 : GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
1899 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1900 :
1901 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1902 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1903 :
1904 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1905 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1906 :
1907 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1908 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1909 : }
1910 :
1911 14 : else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
1912 : {
1913 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1914 2 : ModelTypeProjected);
1915 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1916 2 : KvUserDefined );
1917 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1918 2 : KvUserDefined );
1919 :
1920 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1921 2 : CT_NewZealandMapGrid );
1922 :
1923 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
1924 2 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
1925 :
1926 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
1927 2 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1928 :
1929 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1930 2 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1931 :
1932 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1933 2 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1934 : }
1935 :
1936 12 : else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
1937 : {
1938 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1939 0 : ModelTypeProjected);
1940 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1941 0 : KvUserDefined );
1942 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1943 0 : KvUserDefined );
1944 :
1945 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1946 0 : CT_Robinson );
1947 :
1948 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1949 0 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1950 :
1951 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1952 0 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1953 :
1954 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1955 0 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1956 : }
1957 :
1958 12 : else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
1959 : {
1960 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1961 1 : ModelTypeProjected);
1962 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1963 1 : KvUserDefined );
1964 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1965 1 : KvUserDefined );
1966 :
1967 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1968 1 : CT_Sinusoidal );
1969 :
1970 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1971 1 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
1972 :
1973 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1974 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1975 :
1976 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1977 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
1978 : }
1979 :
1980 11 : else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
1981 : {
1982 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
1983 2 : ModelTypeProjected);
1984 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
1985 2 : KvUserDefined );
1986 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
1987 2 : KvUserDefined );
1988 :
1989 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
1990 2 : CT_VanDerGrinten );
1991 :
1992 : GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
1993 2 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
1994 :
1995 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
1996 2 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
1997 :
1998 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
1999 2 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
2000 : }
2001 :
2002 9 : else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
2003 : {
2004 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
2005 0 : ModelTypeProjected);
2006 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
2007 0 : KvUserDefined );
2008 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
2009 0 : KvUserDefined );
2010 :
2011 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
2012 0 : CT_AlbersEqualArea );
2013 :
2014 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
2015 0 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
2016 :
2017 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
2018 0 : poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
2019 :
2020 : GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
2021 0 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
2022 :
2023 : GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
2024 0 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
2025 :
2026 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
2027 0 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
2028 :
2029 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
2030 0 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
2031 : }
2032 :
2033 9 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
2034 : {
2035 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
2036 4 : ModelTypeProjected);
2037 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
2038 4 : KvUserDefined );
2039 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
2040 4 : KvUserDefined );
2041 :
2042 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
2043 4 : CT_LambertConfConic_2SP );
2044 :
2045 : GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1,
2046 4 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
2047 :
2048 : GTIFKeySet(psGTIF, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1,
2049 4 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
2050 :
2051 : GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
2052 4 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
2053 :
2054 : GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
2055 4 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
2056 :
2057 : GTIFKeySet(psGTIF, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1,
2058 4 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
2059 :
2060 : GTIFKeySet(psGTIF, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1,
2061 4 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
2062 : }
2063 :
2064 5 : else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
2065 : {
2066 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
2067 1 : ModelTypeProjected);
2068 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
2069 1 : KvUserDefined );
2070 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
2071 1 : KvUserDefined );
2072 :
2073 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
2074 1 : CT_LambertConfConic_1SP );
2075 :
2076 : GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
2077 1 : poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
2078 :
2079 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
2080 1 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
2081 :
2082 : GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
2083 1 : poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
2084 :
2085 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
2086 1 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
2087 :
2088 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
2089 1 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
2090 : }
2091 :
2092 4 : else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
2093 : {
2094 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
2095 2 : ModelTypeProjected);
2096 : GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
2097 2 : KvUserDefined );
2098 : GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
2099 2 : KvUserDefined );
2100 :
2101 : GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
2102 2 : CT_CylindricalEqualArea );
2103 :
2104 : GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
2105 2 : poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
2106 :
2107 : GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
2108 2 : poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
2109 :
2110 : GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
2111 2 : poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
2112 :
2113 : GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
2114 2 : poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
2115 : }
2116 :
2117 : else
2118 : {
2119 2 : bWritePEString = TRUE;
2120 : }
2121 :
2122 : // Note that VERTCS is an ESRI "spelling" of VERT_CS so we assume if
2123 : // we find it that we should try to treat this as a PE string.
2124 944 : bWritePEString |= (poSRS->GetAttrValue("VERTCS") != NULL);
2125 :
2126 944 : if( bWritePEString
2127 : && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
2128 : "YES") ) )
2129 : {
2130 : /* Anyhing we can't map, we store as an ESRI PE string with a citation key */
2131 2 : char *pszPEString = NULL;
2132 2 : poSRS->morphToESRI();
2133 2 : poSRS->exportToWkt( &pszPEString );
2134 2 : int peStrLen = strlen(pszPEString);
2135 2 : if(peStrLen > 0)
2136 : {
2137 2 : char *outPeStr = (char *) CPLMalloc( peStrLen + strlen("ESRI PE String = ")+1 );
2138 2 : strcpy(outPeStr, "ESRI PE String = ");
2139 2 : strcat(outPeStr, pszPEString);
2140 2 : GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, outPeStr );
2141 2 : peStrStored = TRUE;
2142 2 : CPLFree( outPeStr );
2143 : }
2144 2 : if(pszPEString)
2145 2 : CPLFree( pszPEString );
2146 : GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
2147 2 : KvUserDefined );
2148 : }
2149 :
2150 : /* -------------------------------------------------------------------- */
2151 : /* Is there a false easting/northing set? If so, write out a */
2152 : /* special geokey tag to indicate that GDAL has written these */
2153 : /* with the proper interpretation of the linear units. */
2154 : /* -------------------------------------------------------------------- */
2155 944 : double dfFE = 0.0, dfFN = 0.0;
2156 :
2157 944 : if( (GTIFKeyGet(psGTIF, ProjFalseEastingGeoKey, &dfFE, 0, 1)
2158 : || GTIFKeyGet(psGTIF, ProjFalseNorthingGeoKey, &dfFN, 0, 1)
2159 : || GTIFKeyGet(psGTIF, ProjFalseOriginEastingGeoKey, &dfFE, 0, 1)
2160 : || GTIFKeyGet(psGTIF, ProjFalseOriginNorthingGeoKey, &dfFN, 0, 1))
2161 : && (dfFE != 0.0 || dfFN != 0.0)
2162 : && nUOMLengthCode != 9001 )
2163 : {
2164 : GTIFKeySet(psGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey,
2165 3 : TYPE_SHORT, 1, (short) 1 );
2166 : }
2167 :
2168 : /* -------------------------------------------------------------------- */
2169 : /* Write linear units information. */
2170 : /* -------------------------------------------------------------------- */
2171 944 : if( poSRS->IsGeocentric() )
2172 : {
2173 : GTIFKeySet(psGTIF, GeogLinearUnitsGeoKey, TYPE_SHORT, 1,
2174 0 : nUOMLengthCode );
2175 0 : if( nUOMLengthCode == KvUserDefined )
2176 : GTIFKeySet( psGTIF, GeogLinearUnitSizeGeoKey, TYPE_DOUBLE, 1,
2177 0 : dfLinearUOM);
2178 : }
2179 944 : else if( !poSRS->IsGeographic() )
2180 : {
2181 : GTIFKeySet(psGTIF, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
2182 278 : nUOMLengthCode );
2183 278 : if( nUOMLengthCode == KvUserDefined )
2184 : GTIFKeySet( psGTIF, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1,
2185 1 : dfLinearUOM);
2186 :
2187 : /* if linear units name is available and user defined, store it as citation */
2188 278 : if(!peStrStored
2189 : && nUOMLengthCode == KvUserDefined
2190 : && pszLinearUOMName
2191 : && strlen(pszLinearUOMName)>0
2192 : && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
2193 : "YES") ) )
2194 : {
2195 1 : SetLinearUnitCitation(psGTIF, pszLinearUOMName);
2196 : }
2197 : }
2198 :
2199 : /* -------------------------------------------------------------------- */
2200 : /* Write angular units. Always Degrees for now. */
2201 : /* Changed to support different angular units */
2202 : /* -------------------------------------------------------------------- */
2203 :
2204 944 : char* angUnitName = NULL;
2205 944 : double angUnitValue = poSRS->GetAngularUnits(&angUnitName);
2206 944 : if(EQUAL(angUnitName, "Degree"))
2207 : GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1,
2208 943 : Angular_Degree );
2209 1 : else if(angUnitName)
2210 : {
2211 : GTIFKeySet(psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0,
2212 1 : angUnitName ); // it may be rewritten if the gcs is userdefined
2213 : GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1,
2214 1 : angUnitValue );
2215 : }
2216 :
2217 : /* -------------------------------------------------------------------- */
2218 : /* Try to write a citation from the main coordinate system */
2219 : /* name. */
2220 : /* -------------------------------------------------------------------- */
2221 944 : if( poSRS->GetRoot() != NULL
2222 : && poSRS->GetRoot()->GetChild(0) != NULL
2223 : && (poSRS->IsProjected() || poSRS->IsLocal() || poSRS->IsGeocentric()) )
2224 : {
2225 : GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0,
2226 278 : poSRS->GetRoot()->GetChild(0)->GetValue() );
2227 : }
2228 :
2229 : /* -------------------------------------------------------------------- */
2230 : /* Try to write a GCS citation. */
2231 : /* -------------------------------------------------------------------- */
2232 944 : OGR_SRSNode *poGCS = poSRS->GetAttrNode( "GEOGCS" );
2233 :
2234 944 : if( poGCS != NULL && poGCS->GetChild(0) != NULL )
2235 : {
2236 : GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0,
2237 944 : poGCS->GetChild(0)->GetValue() );
2238 : }
2239 :
2240 : /* -------------------------------------------------------------------- */
2241 : /* Try to identify the GCS/datum, scanning the EPSG datum file for */
2242 : /* a match. */
2243 : /* -------------------------------------------------------------------- */
2244 944 : if( nPCS == KvUserDefined )
2245 : {
2246 705 : if( nGCS == KvUserDefined )
2247 : {
2248 364 : if( nDatum == Datum_North_American_Datum_1927 )
2249 0 : nGCS = GCS_NAD27;
2250 364 : else if( nDatum == Datum_North_American_Datum_1983 )
2251 1 : nGCS = GCS_NAD83;
2252 363 : else if( nDatum == Datum_WGS84 || nDatum == DatumE_WGS84 )
2253 334 : nGCS = GCS_WGS_84;
2254 : }
2255 :
2256 705 : if( nGCS != KvUserDefined )
2257 : {
2258 : GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT,
2259 676 : 1, nGCS );
2260 : }
2261 29 : else if( nDatum != KvUserDefined )
2262 : {
2263 : GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1,
2264 3 : KvUserDefined );
2265 : GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
2266 3 : 1, nDatum );
2267 : }
2268 26 : else if( nSpheroid != KvUserDefined )
2269 : {
2270 : GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1,
2271 0 : KvUserDefined );
2272 : GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
2273 0 : 1, KvUserDefined );
2274 : GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
2275 0 : nSpheroid );
2276 : }
2277 26 : else if( dfSemiMajor != 0.0 )
2278 : {
2279 : GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1,
2280 26 : KvUserDefined );
2281 : GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
2282 26 : 1, KvUserDefined );
2283 : GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
2284 26 : KvUserDefined );
2285 : GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
2286 26 : dfSemiMajor );
2287 26 : if( dfInvFlattening == 0.0 )
2288 : GTIFKeySet( psGTIF, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1,
2289 3 : dfSemiMajor );
2290 : else
2291 : GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
2292 23 : dfInvFlattening );
2293 : }
2294 0 : else if( poSRS->GetAttrValue("DATUM") != NULL
2295 : && strstr(poSRS->GetAttrValue("DATUM"),"unknown") == NULL
2296 : && strstr(poSRS->GetAttrValue("DATUM"),"unnamed") == NULL )
2297 :
2298 : {
2299 : CPLError( CE_Warning, CPLE_AppDefined,
2300 : "Couldn't translate `%s' to a GeoTIFF datum.\n",
2301 0 : poSRS->GetAttrValue("DATUM") );
2302 : }
2303 :
2304 : /* Always set InvFlattening if it is avaliable. */
2305 : /* So that it doesn'tneed to calculate from SemiMinor */
2306 705 : if( dfInvFlattening != 0.0 )
2307 : GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
2308 699 : dfInvFlattening );
2309 : /* Always set SemiMajor to keep the precision and in case of editing */
2310 705 : if( dfSemiMajor != 0.0 )
2311 : GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
2312 702 : dfSemiMajor );
2313 :
2314 705 : if( nGCS == KvUserDefined
2315 : && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
2316 : "YES") ) )
2317 29 : SetGeogCSCitation(psGTIF, poSRS, angUnitName, nDatum, nSpheroid);
2318 : }
2319 :
2320 : /* -------------------------------------------------------------------- */
2321 : /* Do we have TOWGS84 parameters? */
2322 : /* -------------------------------------------------------------------- */
2323 :
2324 : #if LIBGEOTIFF_VERSION >= 1310 && !defined(GEO_NORMALIZE_DISABLE_TOWGS84)
2325 : double adfTOWGS84[7];
2326 :
2327 944 : if( poSRS->GetTOWGS84( adfTOWGS84 ) == OGRERR_NONE )
2328 : {
2329 218 : if( adfTOWGS84[3] == 0.0 && adfTOWGS84[4] == 0.0
2330 108 : && adfTOWGS84[5] == 0.0 && adfTOWGS84[6] == 0.0 )
2331 : {
2332 109 : if( nGCS == GCS_WGS_84 && adfTOWGS84[0] == 0.0
2333 56 : && adfTOWGS84[1] == 0.0 && adfTOWGS84[2] == 0.0 )
2334 : {
2335 : ; /* do nothing */
2336 : }
2337 : else
2338 : GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 3,
2339 25 : adfTOWGS84 );
2340 : }
2341 : else
2342 : GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 7,
2343 4 : adfTOWGS84 );
2344 : }
2345 : #endif
2346 :
2347 : /* -------------------------------------------------------------------- */
2348 : /* Do we have vertical datum information to set? */
2349 : /* -------------------------------------------------------------------- */
2350 944 : if( poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) != NULL )
2351 : {
2352 : const char *pszValue;
2353 :
2354 : GTIFKeySet( psGTIF, VerticalCitationGeoKey, TYPE_ASCII, 0,
2355 1 : poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) );
2356 :
2357 1 : pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS" );
2358 1 : if( pszValue && atoi(pszValue) )
2359 : GTIFKeySet( psGTIF, VerticalCSTypeGeoKey, TYPE_SHORT, 1,
2360 1 : atoi(pszValue) );
2361 :
2362 1 : pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|VERT_DATUM" );
2363 1 : if( pszValue && atoi(pszValue) )
2364 : GTIFKeySet( psGTIF, VerticalDatumGeoKey, TYPE_SHORT, 1,
2365 1 : atoi(pszValue) );
2366 :
2367 1 : pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|UNIT" );
2368 1 : if( pszValue && atoi(pszValue) )
2369 : GTIFKeySet( psGTIF, VerticalUnitsGeoKey, TYPE_SHORT, 1,
2370 1 : atoi(pszValue) );
2371 : }
2372 :
2373 : /* -------------------------------------------------------------------- */
2374 : /* Cleanup */
2375 : /* -------------------------------------------------------------------- */
2376 944 : delete poSRS;
2377 944 : return TRUE;
2378 : }
2379 :
2380 : /************************************************************************/
2381 : /* GTIFWktFromMemBuf() */
2382 : /************************************************************************/
2383 :
2384 75 : CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
2385 : char **ppszWKT, double *padfGeoTransform,
2386 : int *pnGCPCount, GDAL_GCP **ppasGCPList )
2387 :
2388 : {
2389 : char szFilename[100];
2390 :
2391 : sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif",
2392 75 : (long) CPLGetPID() );
2393 :
2394 : /* -------------------------------------------------------------------- */
2395 : /* Make sure we have hooked CSVFilename(). */
2396 : /* -------------------------------------------------------------------- */
2397 75 : LibgeotiffOneTimeInit();
2398 :
2399 : /* -------------------------------------------------------------------- */
2400 : /* Create a memory file from the buffer. */
2401 : /* -------------------------------------------------------------------- */
2402 75 : VSILFILE *fp = VSIFileFromMemBuffer( szFilename, pabyBuffer, nSize, FALSE );
2403 75 : if( fp == NULL )
2404 0 : return CE_Failure;
2405 75 : VSIFCloseL( fp );
2406 :
2407 : /* -------------------------------------------------------------------- */
2408 : /* Initialize access to the memory geotiff structure. */
2409 : /* -------------------------------------------------------------------- */
2410 : TIFF *hTIFF;
2411 75 : hTIFF = VSI_TIFFOpen( szFilename, "rc" );
2412 :
2413 75 : if( hTIFF == NULL )
2414 : {
2415 : CPLError( CE_Failure, CPLE_AppDefined,
2416 0 : "TIFF/GeoTIFF structure is corrupt." );
2417 0 : VSIUnlink( szFilename );
2418 0 : return CE_Failure;
2419 : }
2420 :
2421 : /* -------------------------------------------------------------------- */
2422 : /* Get the projection definition. */
2423 : /* -------------------------------------------------------------------- */
2424 : GTIF *hGTIF;
2425 : GTIFDefn *psGTIFDefn;
2426 :
2427 75 : hGTIF = GTIFNew(hTIFF);
2428 :
2429 : #if LIBGEOTIFF_VERSION >= 1410
2430 : psGTIFDefn = GTIFAllocDefn();
2431 : #else
2432 75 : psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
2433 : #endif
2434 :
2435 75 : if( hGTIF != NULL && GTIFGetDefn( hGTIF, psGTIFDefn ) )
2436 75 : *ppszWKT = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
2437 : else
2438 0 : *ppszWKT = NULL;
2439 :
2440 75 : if( hGTIF )
2441 75 : GTIFFree( hGTIF );
2442 :
2443 : #if LIBGEOTIFF_VERSION >= 1410
2444 : GTIFFreeDefn(psGTIFDefn);
2445 : #else
2446 75 : CPLFree(psGTIFDefn);
2447 : #endif
2448 :
2449 : /* -------------------------------------------------------------------- */
2450 : /* Get geotransform or tiepoints. */
2451 : /* -------------------------------------------------------------------- */
2452 : double *padfTiePoints, *padfScale, *padfMatrix;
2453 : int16 nCount;
2454 :
2455 75 : padfGeoTransform[0] = 0.0;
2456 75 : padfGeoTransform[1] = 1.0;
2457 75 : padfGeoTransform[2] = 0.0;
2458 75 : padfGeoTransform[3] = 0.0;
2459 75 : padfGeoTransform[4] = 0.0;
2460 75 : padfGeoTransform[5] = 1.0;
2461 :
2462 75 : *pnGCPCount = 0;
2463 75 : *ppasGCPList = NULL;
2464 :
2465 75 : if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
2466 : && nCount >= 2 )
2467 : {
2468 65 : padfGeoTransform[1] = padfScale[0];
2469 65 : padfGeoTransform[5] = - ABS(padfScale[1]);
2470 :
2471 65 : if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
2472 : && nCount >= 6 )
2473 : {
2474 : padfGeoTransform[0] =
2475 65 : padfTiePoints[3] - padfTiePoints[0] * padfGeoTransform[1];
2476 65 : padfGeoTransform[3] =
2477 65 : padfTiePoints[4] - padfTiePoints[1] * padfGeoTransform[5];
2478 : }
2479 : }
2480 :
2481 10 : else if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
2482 : && nCount >= 6 )
2483 : {
2484 10 : *pnGCPCount = nCount / 6;
2485 10 : *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),*pnGCPCount);
2486 :
2487 138 : for( int iGCP = 0; iGCP < *pnGCPCount; iGCP++ )
2488 : {
2489 : char szID[32];
2490 128 : GDAL_GCP *psGCP = *ppasGCPList + iGCP;
2491 :
2492 128 : sprintf( szID, "%d", iGCP+1 );
2493 128 : psGCP->pszId = CPLStrdup( szID );
2494 128 : psGCP->pszInfo = CPLStrdup("");
2495 128 : psGCP->dfGCPPixel = padfTiePoints[iGCP*6+0];
2496 128 : psGCP->dfGCPLine = padfTiePoints[iGCP*6+1];
2497 128 : psGCP->dfGCPX = padfTiePoints[iGCP*6+3];
2498 128 : psGCP->dfGCPY = padfTiePoints[iGCP*6+4];
2499 128 : psGCP->dfGCPZ = padfTiePoints[iGCP*6+5];
2500 : }
2501 : }
2502 :
2503 0 : else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix )
2504 : && nCount == 16 )
2505 : {
2506 0 : padfGeoTransform[0] = padfMatrix[3];
2507 0 : padfGeoTransform[1] = padfMatrix[0];
2508 0 : padfGeoTransform[2] = padfMatrix[1];
2509 0 : padfGeoTransform[3] = padfMatrix[7];
2510 0 : padfGeoTransform[4] = padfMatrix[4];
2511 0 : padfGeoTransform[5] = padfMatrix[5];
2512 : }
2513 :
2514 : /* -------------------------------------------------------------------- */
2515 : /* Cleanup. */
2516 : /* -------------------------------------------------------------------- */
2517 75 : XTIFFClose( hTIFF );
2518 :
2519 75 : VSIUnlink( szFilename );
2520 :
2521 75 : if( *ppszWKT == NULL )
2522 0 : return CE_Failure;
2523 : else
2524 75 : return CE_None;
2525 : }
2526 :
2527 : /************************************************************************/
2528 : /* GTIFMemBufFromWkt() */
2529 : /************************************************************************/
2530 :
2531 30 : CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
2532 : int nGCPCount, const GDAL_GCP *pasGCPList,
2533 : int *pnSize, unsigned char **ppabyBuffer )
2534 :
2535 : {
2536 : TIFF *hTIFF;
2537 : GTIF *hGTIF;
2538 : char szFilename[100];
2539 :
2540 : sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif",
2541 30 : (long) CPLGetPID() );
2542 :
2543 : /* -------------------------------------------------------------------- */
2544 : /* Make sure we have hooked CSVFilename(). */
2545 : /* -------------------------------------------------------------------- */
2546 30 : LibgeotiffOneTimeInit();
2547 :
2548 : /* -------------------------------------------------------------------- */
2549 : /* Initialize access to the memory geotiff structure. */
2550 : /* -------------------------------------------------------------------- */
2551 30 : hTIFF = VSI_TIFFOpen( szFilename, "w" );
2552 :
2553 30 : if( hTIFF == NULL )
2554 : {
2555 : CPLError( CE_Failure, CPLE_AppDefined,
2556 0 : "TIFF/GeoTIFF structure is corrupt." );
2557 0 : return CE_Failure;
2558 : }
2559 :
2560 : /* -------------------------------------------------------------------- */
2561 : /* Write some minimal set of image parameters. */
2562 : /* -------------------------------------------------------------------- */
2563 30 : TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, 1 );
2564 30 : TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, 1 );
2565 30 : TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, 8 );
2566 30 : TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, 1 );
2567 30 : TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, 1 );
2568 30 : TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
2569 30 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
2570 :
2571 : /* -------------------------------------------------------------------- */
2572 : /* Get the projection definition. */
2573 : /* -------------------------------------------------------------------- */
2574 :
2575 30 : if( pszWKT != NULL )
2576 : {
2577 30 : hGTIF = GTIFNew(hTIFF);
2578 30 : GTIFSetFromOGISDefn( hGTIF, pszWKT );
2579 30 : GTIFWriteKeys( hGTIF );
2580 30 : GTIFFree( hGTIF );
2581 : }
2582 :
2583 : /* -------------------------------------------------------------------- */
2584 : /* Set the geotransform, or GCPs. */
2585 : /* -------------------------------------------------------------------- */
2586 68 : if( padfGeoTransform[0] != 0.0 || padfGeoTransform[1] != 1.0
2587 4 : || padfGeoTransform[2] != 0.0 || padfGeoTransform[3] != 0.0
2588 6 : || padfGeoTransform[4] != 0.0 || ABS(padfGeoTransform[5]) != 1.0 )
2589 : {
2590 :
2591 56 : if( padfGeoTransform[2] == 0.0 && padfGeoTransform[4] == 0.0 )
2592 : {
2593 : double adfPixelScale[3], adfTiePoints[6];
2594 :
2595 28 : adfPixelScale[0] = padfGeoTransform[1];
2596 28 : adfPixelScale[1] = fabs(padfGeoTransform[5]);
2597 28 : adfPixelScale[2] = 0.0;
2598 :
2599 28 : TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
2600 :
2601 28 : adfTiePoints[0] = 0.0;
2602 28 : adfTiePoints[1] = 0.0;
2603 28 : adfTiePoints[2] = 0.0;
2604 28 : adfTiePoints[3] = padfGeoTransform[0];
2605 28 : adfTiePoints[4] = padfGeoTransform[3];
2606 28 : adfTiePoints[5] = 0.0;
2607 :
2608 28 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
2609 : }
2610 : else
2611 : {
2612 : double adfMatrix[16];
2613 :
2614 0 : memset(adfMatrix,0,sizeof(double) * 16);
2615 :
2616 0 : adfMatrix[0] = padfGeoTransform[1];
2617 0 : adfMatrix[1] = padfGeoTransform[2];
2618 0 : adfMatrix[3] = padfGeoTransform[0];
2619 0 : adfMatrix[4] = padfGeoTransform[4];
2620 0 : adfMatrix[5] = padfGeoTransform[5];
2621 0 : adfMatrix[7] = padfGeoTransform[3];
2622 0 : adfMatrix[15] = 1.0;
2623 :
2624 0 : TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
2625 : }
2626 : }
2627 :
2628 : /* -------------------------------------------------------------------- */
2629 : /* Otherwise write tiepoints if they are available. */
2630 : /* -------------------------------------------------------------------- */
2631 2 : else if( nGCPCount > 0 )
2632 : {
2633 : double *padfTiePoints;
2634 :
2635 1 : padfTiePoints = (double *) CPLMalloc(6*sizeof(double)*nGCPCount);
2636 :
2637 5 : for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
2638 : {
2639 :
2640 4 : padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
2641 4 : padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine;
2642 4 : padfTiePoints[iGCP*6+2] = 0;
2643 4 : padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX;
2644 4 : padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY;
2645 4 : padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ;
2646 : }
2647 :
2648 1 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6*nGCPCount, padfTiePoints);
2649 1 : CPLFree( padfTiePoints );
2650 : }
2651 :
2652 : /* -------------------------------------------------------------------- */
2653 : /* Cleanup and return the created memory buffer. */
2654 : /* -------------------------------------------------------------------- */
2655 30 : GByte bySmallImage = 0;
2656 :
2657 30 : TIFFWriteEncodedStrip( hTIFF, 0, (char *) &bySmallImage, 1 );
2658 30 : TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTIFMemBufFromWkt");
2659 30 : TIFFWriteDirectory( hTIFF );
2660 :
2661 30 : XTIFFClose( hTIFF );
2662 :
2663 : /* -------------------------------------------------------------------- */
2664 : /* Read back from the memory buffer. It would be preferrable */
2665 : /* to be able to "steal" the memory buffer, but there isn't */
2666 : /* currently any support for this. */
2667 : /* -------------------------------------------------------------------- */
2668 : GUIntBig nBigLength;
2669 :
2670 30 : *ppabyBuffer = VSIGetMemFileBuffer( szFilename, &nBigLength, TRUE );
2671 30 : *pnSize = (int) nBigLength;
2672 :
2673 30 : return CE_None;
2674 : }
|