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