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