1 : /******************************************************************************
2 : * $Id: gt_citation.cpp 23433 2011-11-27 19:49:54Z rouault $
3 : *
4 : * Project: GeoTIFF Driver
5 : * Purpose: Implements special parsing of Imagine citation strings, and
6 : * to encode PE String info in citation fields as needed.
7 : * Author: Xiuguang Zhou (ESRI)
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2008, Xiuguang Zhou (ESRI)
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_port.h"
32 : #include "cpl_string.h"
33 :
34 : #include "geovalues.h"
35 : #include "gt_citation.h"
36 :
37 : CPL_CVSID("$Id: gt_citation.cpp 23433 2011-11-27 19:49:54Z rouault $");
38 :
39 : static const char *apszUnitMap[] = {
40 : "meters", "1.0",
41 : "meter", "1.0",
42 : "m", "1.0",
43 : "centimeters", "0.01",
44 : "centimeter", "0.01",
45 : "cm", "0.01",
46 : "millimeters", "0.001",
47 : "millimeter", "0.001",
48 : "mm", "0.001",
49 : "kilometers", "1000.0",
50 : "kilometer", "1000.0",
51 : "km", "1000.0",
52 : "us_survey_feet", "0.3048006096012192",
53 : "us_survey_foot", "0.3048006096012192",
54 : "feet", "0.3048006096012192",
55 : "foot", "0.3048006096012192",
56 : "ft", "0.3048006096012192",
57 : "international_feet", "0.3048",
58 : "international_foot", "0.3048",
59 : "inches", "0.0254000508001",
60 : "inch", "0.0254000508001",
61 : "in", "0.0254000508001",
62 : "yards", "0.9144",
63 : "yard", "0.9144",
64 : "yd", "0.9144",
65 : "miles", "1304.544",
66 : "mile", "1304.544",
67 : "mi", "1304.544",
68 : "modified_american_feet", "0.3048122530",
69 : "modified_american_foot", "0.3048122530",
70 : "clarke_feet", "0.3047972651",
71 : "clarke_foot", "0.3047972651",
72 : "indian_feet", "0.3047995142",
73 : "indian_foot", "0.3047995142",
74 : "Yard_Indian", "0.9143985307444408",
75 : "Foot_Clarke", "0.304797265",
76 : "Foot_Gold_Coast", "0.3047997101815088",
77 : "Link_Clarke", "0.2011661949",
78 : "Yard_Sears", "0.9143984146160287",
79 : "50_Kilometers", "50000.0",
80 : "150_Kilometers", "150000.0",
81 : NULL, NULL
82 : };
83 :
84 : /************************************************************************/
85 : /* ImagineCitationTranslation() */
86 : /* */
87 : /* Translate ERDAS Imagine GeoTif citation */
88 : /************************************************************************/
89 1300 : char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
90 : {
91 : static const char *keyNames[] = {
92 : "NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL
93 : };
94 :
95 1300 : char* ret = NULL;
96 : int i;
97 1300 : if(!psCitation)
98 0 : return ret;
99 1300 : if(EQUALN(psCitation, "IMAGINE GeoTIFF Support", strlen("IMAGINE GeoTIFF Support")))
100 : {
101 : // this is a handle IMAGING style citation
102 : char name[256];
103 2 : name[0] = '\0';
104 2 : char* p = NULL;
105 2 : char* p1 = NULL;
106 :
107 2 : p = strchr(psCitation, '$');
108 2 : if( p && strchr(p, '\n') )
109 2 : p = strchr(p, '\n') + 1;
110 2 : if(p)
111 : {
112 2 : p1 = p + strlen(p);
113 2 : char *p2 = strchr(p, '\n');
114 2 : if(p2)
115 2 : p1 = MIN(p1, p2);
116 2 : p2 = strchr(p, '\0');
117 2 : if(p2)
118 2 : p1 = MIN(p1, p2);
119 10 : for(i=0; keyNames[i]!=NULL; i++)
120 : {
121 8 : p2 = strstr(p, keyNames[i]);
122 8 : if(p2)
123 2 : p1 = MIN(p1, p2);
124 : }
125 : }
126 :
127 : // PCS name, GCS name and PRJ name
128 2 : if(p && p1)
129 : {
130 2 : switch (keyID)
131 : {
132 : case PCSCitationGeoKey:
133 2 : if(strstr(psCitation, "Projection = "))
134 0 : strcpy(name, "PRJ Name = ");
135 : else
136 2 : strcpy(name, "PCS Name = ");
137 2 : break;
138 : case GTCitationGeoKey:
139 0 : strcpy(name, "PCS Name = ");
140 0 : break;
141 : case GeogCitationGeoKey:
142 0 : if(!strstr(p, "Unable to"))
143 0 : strcpy(name, "GCS Name = ");
144 : break;
145 : default:
146 : break;
147 : }
148 2 : if(strlen(name)>0)
149 : {
150 : char* p2;
151 2 : if((p2 = strstr(psCitation, "Projection Name = ")) != 0)
152 0 : p = p2 + strlen("Projection Name = ");
153 2 : if((p2 = strstr(psCitation, "Projection = ")) != 0)
154 0 : p = p2 + strlen("Projection = ");
155 2 : if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
156 2 : p1 --;
157 2 : p2 = p1 - 1;
158 4 : while( p2>0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
159 0 : p2--;
160 2 : if(p2 != p1 - 1)
161 0 : p1 = p2;
162 2 : if(p1 >= p)
163 : {
164 2 : strncat(name, p, p1-p+1);
165 2 : strcat(name, "|");
166 2 : name[strlen(name)] = '\0';
167 : }
168 : }
169 : }
170 :
171 : // All other parameters
172 10 : for(i=0; keyNames[i]!=NULL; i++)
173 : {
174 8 : p = strstr(psCitation, keyNames[i]);
175 8 : if(p)
176 : {
177 2 : p += strlen(keyNames[i]);
178 2 : p1 = p + strlen(p);
179 2 : char *p2 = strchr(p, '\n');
180 2 : if(p2)
181 0 : p1 = MIN(p1, p2);
182 2 : p2 = strchr(p, '\0');
183 2 : if(p2)
184 2 : p1 = MIN(p1, p2);
185 10 : for(int j=0; keyNames[j]!=NULL; j++)
186 : {
187 8 : p2 = strstr(p, keyNames[j]);
188 8 : if(p2)
189 0 : p1 = MIN(p1, p2);
190 : }
191 : }
192 8 : if(p && p1 && p1>p)
193 : {
194 2 : if(EQUAL(keyNames[i], "Units = "))
195 0 : strcat(name, "LUnits = ");
196 : else
197 2 : strcat(name, keyNames[i]);
198 2 : if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
199 2 : p1 --;
200 2 : char* p2 = p1 - 1;
201 4 : while( p2>0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
202 0 : p2--;
203 2 : if(p2 != p1 - 1)
204 0 : p1 = p2;
205 2 : if(p1 >= p)
206 : {
207 2 : strncat(name, p, p1-p+1);
208 2 : strcat(name, "|");
209 2 : name[strlen(name)] = '\0';
210 : }
211 : }
212 : }
213 2 : if(strlen(name) > 0)
214 2 : ret = CPLStrdup(name);
215 : }
216 1300 : return ret;
217 :
218 : }
219 :
220 : /************************************************************************/
221 : /* CitationStringParse() */
222 : /* */
223 : /* Parse a Citation string */
224 : /************************************************************************/
225 :
226 1300 : char** CitationStringParse(char* psCitation, geokey_t keyID)
227 : {
228 1300 : char ** ret = NULL;
229 1300 : if(!psCitation)
230 0 : return ret;
231 :
232 1300 : ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes);
233 1300 : char* pDelimit = NULL;
234 1300 : char* pStr = psCitation;
235 : char name[512];
236 1300 : int nameSet = FALSE;
237 1300 : int nameLen = strlen(psCitation);
238 1300 : OGRBoolean nameFound = FALSE;
239 4052 : while((pStr-psCitation+1)< nameLen)
240 : {
241 1452 : if( (pDelimit = strstr(pStr, "|")) != NULL )
242 : {
243 204 : strncpy( name, pStr, pDelimit-pStr );
244 204 : name[pDelimit-pStr] = '\0';
245 204 : pStr = pDelimit+1;
246 204 : nameSet = TRUE;
247 : }
248 : else
249 : {
250 1248 : strcpy (name, pStr);
251 1248 : pStr += strlen(pStr);
252 1248 : nameSet = TRUE;
253 : }
254 1452 : if( strstr(name, "PCS Name = ") )
255 : {
256 2 : ret[CitPcsName] = CPLStrdup(name+strlen("PCS Name = "));
257 2 : nameFound = TRUE;
258 : }
259 1452 : if(strstr(name, "PRJ Name = "))
260 : {
261 0 : ret[CitProjectionName] = CPLStrdup(name+strlen("PRJ Name = "));
262 0 : nameFound = TRUE;
263 : }
264 1452 : if(strstr(name, "LUnits = "))
265 : {
266 6 : ret[CitLUnitsName] = CPLStrdup(name+strlen("LUnits = "));
267 6 : nameFound = TRUE;
268 : }
269 1452 : if(strstr(name, "GCS Name = "))
270 : {
271 50 : ret[CitGcsName] = CPLStrdup(name+strlen("GCS Name = "));
272 50 : nameFound = TRUE;
273 : }
274 1452 : if(strstr(name, "Datum = "))
275 : {
276 50 : ret[CitDatumName] = CPLStrdup(name+strlen("Datum = "));
277 50 : nameFound = TRUE;
278 : }
279 1452 : if(strstr(name, "Ellipsoid = "))
280 : {
281 50 : ret[CitEllipsoidName] = CPLStrdup(name+strlen("Ellipsoid = "));
282 50 : nameFound = TRUE;
283 : }
284 1452 : if(strstr(name, "Primem = "))
285 : {
286 50 : ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));
287 50 : nameFound = TRUE;
288 : }
289 1452 : if(strstr(name, "AUnits = "))
290 : {
291 0 : ret[CitAUnitsName] = CPLStrdup(name+strlen("AUnits = "));
292 0 : nameFound = TRUE;
293 : }
294 : }
295 1300 : if( !nameFound && keyID == GeogCitationGeoKey && nameSet )
296 : {
297 4 : ret[CitGcsName] = CPLStrdup(name);
298 4 : nameFound = TRUE;
299 : }
300 1300 : if(!nameFound)
301 : {
302 1238 : CPLFree( ret );
303 1238 : ret = (char**)NULL;
304 : }
305 1300 : return ret;
306 : }
307 :
308 :
309 : /************************************************************************/
310 : /* SetLinearUnitCitation() */
311 : /* */
312 : /* Set linear unit Citation string */
313 : /************************************************************************/
314 4 : void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName)
315 : {
316 : char szName[512];
317 4 : CPLString osCitation;
318 4 : int n = 0;
319 4 : if( GTIFKeyGet( psGTIF, PCSCitationGeoKey, szName, 0, sizeof(szName) ) )
320 0 : n = strlen(szName);
321 4 : if(n>0)
322 : {
323 0 : osCitation = szName;
324 0 : if(osCitation[n-1] != '|')
325 0 : osCitation += "|";
326 0 : osCitation += "LUnits = ";
327 0 : osCitation += pszLinearUOMName;
328 0 : osCitation += "|";
329 : }
330 : else
331 : {
332 4 : osCitation = "LUnits = ";
333 4 : osCitation += pszLinearUOMName;
334 : }
335 4 : GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
336 4 : return;
337 : }
338 :
339 : /************************************************************************/
340 : /* SetGeogCSCitation() */
341 : /* */
342 : /* Set geogcs Citation string */
343 : /************************************************************************/
344 54 : void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid)
345 : {
346 54 : int bRewriteGeogCitation = FALSE;
347 : char szName[256];
348 54 : CPLString osCitation;
349 54 : size_t n = 0;
350 54 : if( GTIFKeyGet( psGTIF, GeogCitationGeoKey, szName, 0, sizeof(szName) ) )
351 54 : n = strlen(szName);
352 54 : if (n == 0)
353 : return;
354 :
355 54 : if(!EQUALN(szName, "GCS Name = ", strlen("GCS Name = ")))
356 : {
357 54 : osCitation = "GCS Name = ";
358 54 : osCitation += szName;
359 : }
360 : else
361 : {
362 0 : osCitation = szName;
363 : }
364 :
365 54 : if(nDatum == KvUserDefined )
366 : {
367 50 : const char* datumName = poSRS->GetAttrValue( "DATUM" );
368 50 : if(datumName && strlen(datumName) > 0)
369 : {
370 50 : osCitation += "|Datum = ";
371 50 : osCitation += datumName;
372 50 : bRewriteGeogCitation = TRUE;
373 : }
374 : }
375 54 : if(nSpheroid == KvUserDefined )
376 : {
377 54 : const char* spheroidName = poSRS->GetAttrValue( "SPHEROID" );
378 54 : if(spheroidName && strlen(spheroidName) > 0)
379 : {
380 50 : osCitation += "|Ellipsoid = ";
381 50 : osCitation += spheroidName;
382 50 : bRewriteGeogCitation = TRUE;
383 : }
384 : }
385 :
386 54 : const char* primemName = poSRS->GetAttrValue( "PRIMEM" );
387 54 : if(primemName && strlen(primemName) > 0)
388 : {
389 50 : osCitation += "|Primem = ";
390 50 : osCitation += primemName;
391 50 : bRewriteGeogCitation = TRUE;
392 :
393 50 : double primemValue = poSRS->GetPrimeMeridian(NULL);
394 50 : if(angUnitName && !EQUAL(angUnitName, "Degree"))
395 : {
396 0 : double aUnit = poSRS->GetAngularUnits(NULL);
397 0 : primemValue *= aUnit;
398 : }
399 : GTIFKeySet( psGTIF, GeogPrimeMeridianLongGeoKey, TYPE_DOUBLE, 1,
400 50 : primemValue );
401 : }
402 54 : if(angUnitName && strlen(angUnitName) > 0 && !EQUAL(angUnitName, "Degree"))
403 : {
404 0 : osCitation += "|AUnits = ";
405 0 : osCitation += angUnitName;
406 0 : bRewriteGeogCitation = TRUE;
407 : }
408 :
409 54 : if (osCitation[strlen(osCitation) - 1] != '|')
410 54 : osCitation += "|";
411 :
412 54 : if (bRewriteGeogCitation)
413 50 : GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
414 :
415 0 : return;
416 : }
417 :
418 : /************************************************************************/
419 : /* SetCitationToSRS() */
420 : /* */
421 : /* Parse and set Citation string to SRS */
422 : /************************************************************************/
423 1246 : OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
424 : geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet)
425 : {
426 1246 : OGRBoolean ret = FALSE;
427 1246 : char* lUnitName = NULL;
428 :
429 1246 : poSRS->GetLinearUnits( &lUnitName );
430 2488 : if(!lUnitName || strlen(lUnitName) == 0 || EQUAL(lUnitName, "unknown"))
431 1242 : *linearUnitIsSet = FALSE;
432 : else
433 4 : *linearUnitIsSet = TRUE;
434 :
435 1246 : char* imgCTName = ImagineCitationTranslation(szCTString, geoKey);
436 1246 : if(imgCTName)
437 : {
438 2 : strncpy(szCTString, imgCTName, nCTStringLen);
439 2 : szCTString[nCTStringLen-1] = '\0';
440 2 : CPLFree( imgCTName );
441 : }
442 1246 : char** ctNames = CitationStringParse(szCTString, geoKey);
443 1246 : if(ctNames)
444 : {
445 8 : if( poSRS->GetRoot() == NULL)
446 2 : poSRS->SetNode( "PROJCS", "unnamed" );
447 8 : if(ctNames[CitPcsName])
448 : {
449 2 : poSRS->SetNode( "PROJCS", ctNames[CitPcsName] );
450 2 : ret = TRUE;
451 : }
452 8 : if(ctNames[CitProjectionName])
453 0 : poSRS->SetProjection( ctNames[CitProjectionName] );
454 :
455 8 : if(ctNames[CitLUnitsName])
456 : {
457 6 : double unitSize = 0.0;
458 6 : int size = strlen(ctNames[CitLUnitsName]);
459 6 : if(strchr(ctNames[CitLUnitsName], '\0'))
460 6 : size -= 1;
461 252 : for( int i = 0; apszUnitMap[i] != NULL; i += 2 )
462 : {
463 246 : if( EQUALN(apszUnitMap[i], ctNames[CitLUnitsName], size) )
464 : {
465 0 : unitSize = atof(apszUnitMap[i+1]);
466 0 : break;
467 : }
468 : }
469 6 : if( unitSize == 0.0 )
470 : GTIFKeyGet(hGTIF, ProjLinearUnitSizeGeoKey, &unitSize, 0,
471 6 : sizeof(unitSize) );
472 6 : poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
473 6 : *linearUnitIsSet = TRUE;
474 : }
475 80 : for(int i= 0; i<nCitationNameTypes; i++)
476 72 : CPLFree( ctNames[i] );
477 8 : CPLFree( ctNames );
478 : }
479 :
480 : /* if no "PCS Name = " (from Erdas) in GTCitationGeoKey */
481 1246 : if(geoKey == GTCitationGeoKey)
482 : {
483 1236 : if(strlen(szCTString) > 0 && !strstr(szCTString, "PCS Name = "))
484 : {
485 1236 : const char* pszProjCS = poSRS->GetAttrValue( "PROJCS" );
486 1236 : if((!(pszProjCS && strlen(pszProjCS) > 0) && !strstr(szCTString, "Projected Coordinates"))
487 : ||(pszProjCS && strstr(pszProjCS, "unnamed")))
488 172 : poSRS->SetNode( "PROJCS", szCTString );
489 1236 : ret = TRUE;
490 : }
491 : }
492 :
493 1246 : return ret;
494 : }
495 :
496 : /************************************************************************/
497 : /* GetGeogCSFromCitation() */
498 : /* */
499 : /* Parse and get geogcs names from a Citation string */
500 : /************************************************************************/
501 54 : void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
502 : geokey_t geoKey,
503 : char **ppszGeogName,
504 : char **ppszDatumName,
505 : char **ppszPMName,
506 : char **ppszSpheroidName,
507 : char **ppszAngularUnits)
508 : {
509 : *ppszGeogName = *ppszDatumName = *ppszPMName =
510 54 : *ppszSpheroidName = *ppszAngularUnits = NULL;
511 :
512 54 : char* imgCTName = ImagineCitationTranslation(szGCSName, geoKey);
513 54 : if(imgCTName)
514 : {
515 0 : strncpy(szGCSName, imgCTName, nGCSName);
516 0 : szGCSName[nGCSName-1] = '\0';
517 0 : CPLFree( imgCTName );
518 : }
519 54 : char** ctNames = CitationStringParse(szGCSName, geoKey);
520 54 : if(ctNames)
521 : {
522 54 : if(ctNames[CitGcsName])
523 54 : *ppszGeogName = CPLStrdup( ctNames[CitGcsName] );
524 :
525 54 : if(ctNames[CitDatumName])
526 50 : *ppszDatumName = CPLStrdup( ctNames[CitDatumName] );
527 :
528 54 : if(ctNames[CitEllipsoidName])
529 50 : *ppszSpheroidName = CPLStrdup( ctNames[CitEllipsoidName] );
530 :
531 54 : if(ctNames[CitPrimemName])
532 50 : *ppszPMName = CPLStrdup( ctNames[CitPrimemName] );
533 :
534 54 : if(ctNames[CitAUnitsName])
535 0 : *ppszAngularUnits = CPLStrdup( ctNames[CitAUnitsName] );
536 :
537 540 : for(int i= 0; i<nCitationNameTypes; i++)
538 486 : CPLFree( ctNames[i] );
539 54 : CPLFree( ctNames );
540 : }
541 : return;
542 : }
543 :
544 :
545 : /************************************************************************/
546 : /* CheckCitationKeyForStatePlaneUTM() */
547 : /* */
548 : /* Handle state plane and UTM in citation key */
549 : /************************************************************************/
550 1148 : OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet)
551 : {
552 1148 : if( !hGTIF || !psDefn || !poSRS )
553 0 : return FALSE;
554 : char szCTString[512];
555 1148 : szCTString[0] = '\0';
556 :
557 : /* Check units */
558 : char units[32];
559 1148 : units[0] = '\0';
560 :
561 1148 : OGRBoolean hasUnits = FALSE;
562 1148 : if( GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
563 : {
564 1142 : CPLString osLCCT = szCTString;
565 :
566 1142 : osLCCT.tolower();
567 :
568 1142 : if( strstr(osLCCT,"us") && strstr(osLCCT,"survey")
569 : && (strstr(osLCCT,"feet") || strstr(osLCCT,"foot")) )
570 0 : strcpy(units, "us_survey_feet");
571 1142 : else if(strstr(osLCCT, "linear_feet")
572 : || strstr(osLCCT, "linear_foot")
573 : || strstr(osLCCT, "international"))
574 2 : strcpy(units, "international_feet");
575 1140 : else if( strstr(osLCCT,"meter") )
576 0 : strcpy(units, "meters");
577 :
578 1142 : if (strlen(units) > 0)
579 2 : hasUnits = TRUE;
580 :
581 1142 : if( strstr( szCTString, "Projection Name = ") && strstr( szCTString, "_StatePlane_"))
582 : {
583 2 : const char *pStr = strstr( szCTString, "Projection Name = ") + strlen("Projection Name = ");
584 2 : const char* pReturn = strchr( pStr, '\n');
585 : char CSName[128];
586 2 : strncpy(CSName, pStr, pReturn-pStr);
587 2 : CSName[pReturn-pStr] = '\0';
588 2 : if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName) == OGRERR_NONE )
589 : {
590 : // for some erdas citation keys, the state plane CS name is incomplete, the unit check is necessary.
591 2 : OGRBoolean done = FALSE;
592 2 : if (hasUnits)
593 : {
594 2 : OGR_SRSNode *poUnit = poSRS->GetAttrNode( "PROJCS|UNIT" );
595 :
596 2 : if( poUnit != NULL && poUnit->GetChildCount() >= 2 )
597 : {
598 2 : CPLString unitName = poUnit->GetChild(0)->GetValue();
599 2 : unitName.tolower();
600 :
601 2 : if (strstr(units, "us_survey_feet"))
602 : {
603 0 : if (strstr(unitName, "us_survey_feet") || strstr(unitName, "foot_us") )
604 0 : done = TRUE;
605 : }
606 2 : else if (strstr(units, "international_feet"))
607 : {
608 2 : if (strstr(unitName, "feet") || strstr(unitName, "foot"))
609 0 : done = TRUE;
610 : }
611 0 : else if (strstr(units, "meters"))
612 : {
613 0 : if (strstr(unitName, "meter") )
614 0 : done = TRUE;
615 2 : }
616 : }
617 : }
618 2 : if (done)
619 0 : return TRUE;
620 : }
621 0 : }
622 : }
623 1148 : if( !hasUnits )
624 : {
625 1146 : char *pszUnitsName = NULL;
626 1146 : GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
627 1146 : if( pszUnitsName && strlen(pszUnitsName) > 0 )
628 : {
629 1142 : CPLString osLCCT = pszUnitsName;
630 1142 : GTIFFreeMemory( pszUnitsName );
631 1142 : osLCCT.tolower();
632 :
633 1142 : if( strstr(osLCCT, "us") && strstr(osLCCT, "survey")
634 : && (strstr(osLCCT, "feet") || strstr(osLCCT, "foot")))
635 24 : strcpy(units, "us_survey_feet");
636 1118 : else if(strstr(osLCCT, "feet") || strstr(osLCCT, "foot"))
637 0 : strcpy(units, "international_feet");
638 1118 : else if(strstr(osLCCT, "meter"))
639 0 : strcpy(units, "meters");
640 1142 : hasUnits = TRUE;
641 : }
642 : }
643 :
644 1148 : if (strlen(units) == 0)
645 1122 : strcpy(units, "meters");
646 :
647 : /* check PCSCitationGeoKey if it exists */
648 1148 : szCTString[0] = '\0';
649 1148 : if( hGTIF && GTIFKeyGet( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )
650 : {
651 : /* For tif created by LEICA(ERDAS), ESRI state plane pe string was used and */
652 : /* the state plane zone is given in PCSCitation. Therefore try Esri pe string first. */
653 8 : SetCitationToSRS(hGTIF, szCTString, strlen(szCTString), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
654 8 : const char *pcsName = poSRS->GetAttrValue("PROJCS");
655 8 : const char *pStr = NULL;
656 8 : if( (pcsName && (pStr = strstr(pcsName, "State Plane Zone ")) != NULL)
657 : || (pStr = strstr(szCTString, "State Plane Zone ")) != NULL )
658 : {
659 2 : pStr += strlen("State Plane Zone ");
660 2 : int statePlaneZone = abs(atoi(pStr));
661 : char nad[32];
662 2 : strcpy(nad, "HARN");
663 2 : if( strstr(szCTString, "NAD83") || strstr(szCTString, "NAD = 83") )
664 0 : strcpy(nad, "NAD83");
665 2 : else if( strstr(szCTString, "NAD27") || strstr(szCTString, "NAD = 27") )
666 0 : strcpy(nad, "NAD27");
667 2 : if( poSRS->ImportFromESRIStatePlaneWKT(statePlaneZone, (const char*)nad, (const char*)units, psDefn->PCS) == OGRERR_NONE )
668 2 : return TRUE;
669 : }
670 6 : else if( pcsName && (pStr = strstr(pcsName, "UTM Zone ")) != NULL )
671 0 : CheckUTM( psDefn, szCTString );
672 : }
673 :
674 : /* check state plane again to see if a pe string is available */
675 1146 : if( psDefn->PCS != KvUserDefined )
676 : {
677 1046 : if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, (const char*)units, psDefn->PCS) == OGRERR_NONE )
678 2 : return TRUE;
679 : }
680 1144 : return FALSE;
681 : }
682 :
683 : /************************************************************************/
684 : /* CheckUTM() */
685 : /* */
686 : /* Check utm proj code by its name. */
687 : /************************************************************************/
688 0 : void CheckUTM( GTIFDefn * psDefn, char * pszCtString )
689 : {
690 0 : if(!psDefn || !pszCtString)
691 0 : return;
692 :
693 : static const char *apszUtmProjCode[] = {
694 : "PSAD56", "17N", "16017",
695 : "PSAD56", "18N", "16018",
696 : "PSAD56", "19N", "16019",
697 : "PSAD56", "20N", "16020",
698 : "PSAD56", "21N", "16021",
699 : "PSAD56", "17S", "16117",
700 : "PSAD56", "18S", "16118",
701 : "PSAD56", "19S", "16119",
702 : "PSAD56", "20S", "16120",
703 : "PSAD56", "21S", "16121",
704 : "PSAD56", "22S", "16122",
705 : NULL, NULL, NULL};
706 :
707 0 : char* p = strstr(pszCtString, "Datum = ");
708 : char datumName[128];
709 0 : if(p)
710 : {
711 0 : p += strlen("Datum = ");
712 0 : char* p1 = strchr(p, '|');
713 0 : if(p1)
714 : {
715 0 : strncpy(datumName, p, (p1-p));
716 0 : datumName[p1-p] = '\0';
717 : }
718 : else
719 0 : strcpy(datumName, p);
720 : }
721 :
722 : char utmName[64];
723 0 : p = strstr(pszCtString, "UTM Zone ");
724 0 : if(p)
725 : {
726 0 : p += strlen("UTM Zone ");
727 0 : char* p1 = strchr(p, '|');
728 0 : if(p1)
729 : {
730 0 : strncpy(utmName, p, (p1-p));
731 0 : utmName[p1-p] = '\0';
732 : }
733 : else
734 0 : strcpy(utmName, p);
735 : }
736 :
737 0 : for(int i=0; apszUtmProjCode[i]!=NULL; i += 3)
738 : {
739 0 : if(EQUALN(utmName, apszUtmProjCode[i+1], strlen(apszUtmProjCode[i+1])) &&
740 : EQUAL(datumName, apszUtmProjCode[i]) )
741 : {
742 0 : if(psDefn->ProjCode != atoi(apszUtmProjCode[i+2]))
743 : {
744 0 : psDefn->ProjCode = (short) atoi(apszUtmProjCode[i+2]);
745 : GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
746 0 : psDefn->ProjParm );
747 0 : break;
748 : }
749 : }
750 : }
751 0 : return;
752 : }
|