1 : /******************************************************************************
2 : * $Id: gt_citation.cpp 24344 2012-04-29 21:32:42Z warmerdam $
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 24344 2012-04-29 21:32:42Z warmerdam $");
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 680 : char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
90 : {
91 : static const char *keyNames[] = {
92 : "NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL
93 : };
94 :
95 680 : char* ret = NULL;
96 : int i;
97 680 : if(!psCitation)
98 0 : return ret;
99 680 : if(EQUALN(psCitation, "IMAGINE GeoTIFF Support", strlen("IMAGINE GeoTIFF Support")))
100 : {
101 : // this is a handle IMAGING style citation
102 : char name[256];
103 0 : name[0] = '\0';
104 0 : char* p = NULL;
105 0 : char* p1 = NULL;
106 :
107 0 : p = strchr(psCitation, '$');
108 0 : if( p && strchr(p, '\n') )
109 0 : p = strchr(p, '\n') + 1;
110 0 : if(p)
111 : {
112 0 : p1 = p + strlen(p);
113 0 : char *p2 = strchr(p, '\n');
114 0 : if(p2)
115 0 : p1 = MIN(p1, p2);
116 0 : p2 = strchr(p, '\0');
117 0 : if(p2)
118 0 : p1 = MIN(p1, p2);
119 0 : for(i=0; keyNames[i]!=NULL; i++)
120 : {
121 0 : p2 = strstr(p, keyNames[i]);
122 0 : if(p2)
123 0 : p1 = MIN(p1, p2);
124 : }
125 : }
126 :
127 : // PCS name, GCS name and PRJ name
128 0 : if(p && p1)
129 : {
130 0 : switch (keyID)
131 : {
132 : case PCSCitationGeoKey:
133 0 : if(strstr(psCitation, "Projection = "))
134 0 : strcpy(name, "PRJ Name = ");
135 : else
136 0 : strcpy(name, "PCS Name = ");
137 0 : 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 0 : if(strlen(name)>0)
149 : {
150 : char* p2;
151 0 : if((p2 = strstr(psCitation, "Projection Name = ")) != 0)
152 0 : p = p2 + strlen("Projection Name = ");
153 0 : if((p2 = strstr(psCitation, "Projection = ")) != 0)
154 0 : p = p2 + strlen("Projection = ");
155 0 : if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
156 0 : p1 --;
157 0 : p2 = p1 - 1;
158 0 : while( p2>0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
159 0 : p2--;
160 0 : if(p2 != p1 - 1)
161 0 : p1 = p2;
162 0 : if(p1 >= p)
163 : {
164 0 : strncat(name, p, p1-p+1);
165 0 : strcat(name, "|");
166 0 : name[strlen(name)] = '\0';
167 : }
168 : }
169 : }
170 :
171 : // All other parameters
172 0 : for(i=0; keyNames[i]!=NULL; i++)
173 : {
174 0 : p = strstr(psCitation, keyNames[i]);
175 0 : if(p)
176 : {
177 0 : p += strlen(keyNames[i]);
178 0 : p1 = p + strlen(p);
179 0 : char *p2 = strchr(p, '\n');
180 0 : if(p2)
181 0 : p1 = MIN(p1, p2);
182 0 : p2 = strchr(p, '\0');
183 0 : if(p2)
184 0 : p1 = MIN(p1, p2);
185 0 : for(int j=0; keyNames[j]!=NULL; j++)
186 : {
187 0 : p2 = strstr(p, keyNames[j]);
188 0 : if(p2)
189 0 : p1 = MIN(p1, p2);
190 : }
191 : }
192 0 : if(p && p1 && p1>p)
193 : {
194 0 : if(EQUAL(keyNames[i], "Units = "))
195 0 : strcat(name, "LUnits = ");
196 : else
197 0 : strcat(name, keyNames[i]);
198 0 : if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
199 0 : p1 --;
200 0 : char* p2 = p1 - 1;
201 0 : while( p2>0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
202 0 : p2--;
203 0 : if(p2 != p1 - 1)
204 0 : p1 = p2;
205 0 : if(p1 >= p)
206 : {
207 0 : strncat(name, p, p1-p+1);
208 0 : strcat(name, "|");
209 0 : name[strlen(name)] = '\0';
210 : }
211 : }
212 : }
213 0 : if(strlen(name) > 0)
214 0 : ret = CPLStrdup(name);
215 : }
216 680 : return ret;
217 :
218 : }
219 :
220 : /************************************************************************/
221 : /* CitationStringParse() */
222 : /* */
223 : /* Parse a Citation string */
224 : /************************************************************************/
225 :
226 680 : char** CitationStringParse(char* psCitation, geokey_t keyID)
227 : {
228 680 : char ** ret = NULL;
229 680 : if(!psCitation)
230 0 : return ret;
231 :
232 680 : ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes);
233 680 : char* pDelimit = NULL;
234 680 : char* pStr = psCitation;
235 : char name[512];
236 680 : int nameSet = FALSE;
237 680 : int nameLen = strlen(psCitation);
238 680 : OGRBoolean nameFound = FALSE;
239 2121 : while((pStr-psCitation+1)< nameLen)
240 : {
241 761 : if( (pDelimit = strstr(pStr, "|")) != NULL )
242 : {
243 108 : strncpy( name, pStr, pDelimit-pStr );
244 108 : name[pDelimit-pStr] = '\0';
245 108 : pStr = pDelimit+1;
246 108 : nameSet = TRUE;
247 : }
248 : else
249 : {
250 653 : strcpy (name, pStr);
251 653 : pStr += strlen(pStr);
252 653 : nameSet = TRUE;
253 : }
254 761 : if( strstr(name, "PCS Name = ") )
255 : {
256 0 : ret[CitPcsName] = CPLStrdup(name+strlen("PCS Name = "));
257 0 : nameFound = TRUE;
258 : }
259 761 : if(strstr(name, "PRJ Name = "))
260 : {
261 0 : ret[CitProjectionName] = CPLStrdup(name+strlen("PRJ Name = "));
262 0 : nameFound = TRUE;
263 : }
264 761 : if(strstr(name, "LUnits = "))
265 : {
266 2 : ret[CitLUnitsName] = CPLStrdup(name+strlen("LUnits = "));
267 2 : nameFound = TRUE;
268 : }
269 761 : if(strstr(name, "GCS Name = "))
270 : {
271 27 : ret[CitGcsName] = CPLStrdup(name+strlen("GCS Name = "));
272 27 : nameFound = TRUE;
273 : }
274 761 : if(strstr(name, "Datum = "))
275 : {
276 27 : ret[CitDatumName] = CPLStrdup(name+strlen("Datum = "));
277 27 : nameFound = TRUE;
278 : }
279 761 : if(strstr(name, "Ellipsoid = "))
280 : {
281 27 : ret[CitEllipsoidName] = CPLStrdup(name+strlen("Ellipsoid = "));
282 27 : nameFound = TRUE;
283 : }
284 761 : if(strstr(name, "Primem = "))
285 : {
286 27 : ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));
287 27 : nameFound = TRUE;
288 : }
289 761 : if(strstr(name, "AUnits = "))
290 : {
291 0 : ret[CitAUnitsName] = CPLStrdup(name+strlen("AUnits = "));
292 0 : nameFound = TRUE;
293 : }
294 : }
295 680 : if( !nameFound && keyID == GeogCitationGeoKey && nameSet )
296 : {
297 3 : ret[CitGcsName] = CPLStrdup(name);
298 3 : nameFound = TRUE;
299 : }
300 680 : if(!nameFound)
301 : {
302 648 : CPLFree( ret );
303 648 : ret = (char**)NULL;
304 : }
305 680 : return ret;
306 : }
307 :
308 :
309 : /************************************************************************/
310 : /* SetLinearUnitCitation() */
311 : /* */
312 : /* Set linear unit Citation string */
313 : /************************************************************************/
314 1 : void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName)
315 : {
316 : char szName[512];
317 1 : CPLString osCitation;
318 1 : int n = 0;
319 1 : if( GTIFKeyGet( psGTIF, PCSCitationGeoKey, szName, 0, sizeof(szName) ) )
320 0 : n = strlen(szName);
321 1 : 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 1 : osCitation = "LUnits = ";
333 1 : osCitation += pszLinearUOMName;
334 : }
335 1 : GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
336 1 : return;
337 : }
338 :
339 : /************************************************************************/
340 : /* SetGeogCSCitation() */
341 : /* */
342 : /* Set geogcs Citation string */
343 : /************************************************************************/
344 28 : void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid)
345 : {
346 28 : int bRewriteGeogCitation = FALSE;
347 : char szName[256];
348 28 : CPLString osCitation;
349 28 : size_t n = 0;
350 28 : if( GTIFKeyGet( psGTIF, GeogCitationGeoKey, szName, 0, sizeof(szName) ) )
351 28 : n = strlen(szName);
352 28 : if (n == 0)
353 : return;
354 :
355 28 : if(!EQUALN(szName, "GCS Name = ", strlen("GCS Name = ")))
356 : {
357 28 : osCitation = "GCS Name = ";
358 28 : osCitation += szName;
359 : }
360 : else
361 : {
362 0 : osCitation = szName;
363 : }
364 :
365 28 : if(nDatum == KvUserDefined )
366 : {
367 25 : const char* datumName = poSRS->GetAttrValue( "DATUM" );
368 25 : if(datumName && strlen(datumName) > 0)
369 : {
370 25 : osCitation += "|Datum = ";
371 25 : osCitation += datumName;
372 25 : bRewriteGeogCitation = TRUE;
373 : }
374 : }
375 28 : if(nSpheroid == KvUserDefined )
376 : {
377 28 : const char* spheroidName = poSRS->GetAttrValue( "SPHEROID" );
378 28 : if(spheroidName && strlen(spheroidName) > 0)
379 : {
380 25 : osCitation += "|Ellipsoid = ";
381 25 : osCitation += spheroidName;
382 25 : bRewriteGeogCitation = TRUE;
383 : }
384 : }
385 :
386 28 : const char* primemName = poSRS->GetAttrValue( "PRIMEM" );
387 28 : if(primemName && strlen(primemName) > 0)
388 : {
389 25 : osCitation += "|Primem = ";
390 25 : osCitation += primemName;
391 25 : bRewriteGeogCitation = TRUE;
392 :
393 25 : double primemValue = poSRS->GetPrimeMeridian(NULL);
394 25 : 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 25 : primemValue );
401 : }
402 28 : if(angUnitName && strlen(angUnitName) > 0 && !EQUAL(angUnitName, "Degree"))
403 : {
404 0 : osCitation += "|AUnits = ";
405 0 : osCitation += angUnitName;
406 0 : bRewriteGeogCitation = TRUE;
407 : }
408 :
409 28 : if (osCitation[strlen(osCitation) - 1] != '|')
410 28 : osCitation += "|";
411 :
412 28 : if (bRewriteGeogCitation)
413 25 : 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 650 : OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
424 : geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet)
425 : {
426 650 : OGRBoolean ret = FALSE;
427 650 : char* lUnitName = NULL;
428 :
429 650 : poSRS->GetLinearUnits( &lUnitName );
430 1300 : if(!lUnitName || strlen(lUnitName) == 0 || EQUAL(lUnitName, "unknown"))
431 650 : *linearUnitIsSet = FALSE;
432 : else
433 0 : *linearUnitIsSet = TRUE;
434 :
435 650 : char* imgCTName = ImagineCitationTranslation(szCTString, geoKey);
436 650 : if(imgCTName)
437 : {
438 0 : strncpy(szCTString, imgCTName, nCTStringLen);
439 0 : szCTString[nCTStringLen-1] = '\0';
440 0 : CPLFree( imgCTName );
441 : }
442 650 : char** ctNames = CitationStringParse(szCTString, geoKey);
443 650 : if(ctNames)
444 : {
445 2 : if( poSRS->GetRoot() == NULL)
446 1 : poSRS->SetNode( "PROJCS", "unnamed" );
447 2 : if(ctNames[CitPcsName])
448 : {
449 0 : poSRS->SetNode( "PROJCS", ctNames[CitPcsName] );
450 0 : ret = TRUE;
451 : }
452 2 : if(ctNames[CitProjectionName])
453 0 : poSRS->SetProjection( ctNames[CitProjectionName] );
454 :
455 2 : if(ctNames[CitLUnitsName])
456 : {
457 2 : double unitSize = 0.0;
458 2 : int size = strlen(ctNames[CitLUnitsName]);
459 2 : if(strchr(ctNames[CitLUnitsName], '\0'))
460 2 : size -= 1;
461 84 : for( int i = 0; apszUnitMap[i] != NULL; i += 2 )
462 : {
463 82 : if( EQUALN(apszUnitMap[i], ctNames[CitLUnitsName], size) )
464 : {
465 0 : unitSize = atof(apszUnitMap[i+1]);
466 0 : break;
467 : }
468 : }
469 2 : if( unitSize == 0.0 )
470 : GTIFKeyGet(hGTIF, ProjLinearUnitSizeGeoKey, &unitSize, 0,
471 2 : sizeof(unitSize) );
472 2 : poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
473 2 : *linearUnitIsSet = TRUE;
474 : }
475 20 : for(int i= 0; i<nCitationNameTypes; i++)
476 18 : CPLFree( ctNames[i] );
477 2 : CPLFree( ctNames );
478 : }
479 :
480 : /* if no "PCS Name = " (from Erdas) in GTCitationGeoKey */
481 650 : if(geoKey == GTCitationGeoKey)
482 : {
483 648 : if(strlen(szCTString) > 0 && !strstr(szCTString, "PCS Name = "))
484 : {
485 648 : const char* pszProjCS = poSRS->GetAttrValue( "PROJCS" );
486 648 : if((!(pszProjCS && strlen(pszProjCS) > 0) && !strstr(szCTString, "Projected Coordinates"))
487 : ||(pszProjCS && strstr(pszProjCS, "unnamed")))
488 92 : poSRS->SetNode( "PROJCS", szCTString );
489 648 : ret = TRUE;
490 : }
491 : }
492 :
493 650 : return ret;
494 : }
495 :
496 : /************************************************************************/
497 : /* GetGeogCSFromCitation() */
498 : /* */
499 : /* Parse and get geogcs names from a Citation string */
500 : /************************************************************************/
501 30 : 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 30 : *ppszSpheroidName = *ppszAngularUnits = NULL;
511 :
512 30 : char* imgCTName = ImagineCitationTranslation(szGCSName, geoKey);
513 30 : if(imgCTName)
514 : {
515 0 : strncpy(szGCSName, imgCTName, nGCSName);
516 0 : szGCSName[nGCSName-1] = '\0';
517 0 : CPLFree( imgCTName );
518 : }
519 30 : char** ctNames = CitationStringParse(szGCSName, geoKey);
520 30 : if(ctNames)
521 : {
522 30 : if(ctNames[CitGcsName])
523 30 : *ppszGeogName = CPLStrdup( ctNames[CitGcsName] );
524 :
525 30 : if(ctNames[CitDatumName])
526 27 : *ppszDatumName = CPLStrdup( ctNames[CitDatumName] );
527 :
528 30 : if(ctNames[CitEllipsoidName])
529 27 : *ppszSpheroidName = CPLStrdup( ctNames[CitEllipsoidName] );
530 :
531 30 : if(ctNames[CitPrimemName])
532 27 : *ppszPMName = CPLStrdup( ctNames[CitPrimemName] );
533 :
534 30 : if(ctNames[CitAUnitsName])
535 0 : *ppszAngularUnits = CPLStrdup( ctNames[CitAUnitsName] );
536 :
537 300 : for(int i= 0; i<nCitationNameTypes; i++)
538 270 : CPLFree( ctNames[i] );
539 30 : CPLFree( ctNames );
540 : }
541 : return;
542 : }
543 :
544 :
545 : /************************************************************************/
546 : /* CheckCitationKeyForStatePlaneUTM() */
547 : /* */
548 : /* Handle state plane and UTM in citation key */
549 : /************************************************************************/
550 599 : OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet)
551 : {
552 599 : if( !hGTIF || !psDefn || !poSRS )
553 0 : return FALSE;
554 :
555 : /* -------------------------------------------------------------------- */
556 : /* For ESRI builds we are interested in maximizing PE */
557 : /* compatability, but generally we prefer to use EPSG */
558 : /* definitions of the coordinate system if PCS is defined. */
559 : /* -------------------------------------------------------------------- */
560 : #if !defined(ESRI_BUILD)
561 599 : if( psDefn->PCS != KvUserDefined )
562 546 : return FALSE;
563 : #endif
564 :
565 : char szCTString[512];
566 53 : szCTString[0] = '\0';
567 :
568 : /* Check units */
569 : char units[32];
570 53 : units[0] = '\0';
571 :
572 53 : OGRBoolean hasUnits = FALSE;
573 53 : if( GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
574 : {
575 53 : CPLString osLCCT = szCTString;
576 :
577 53 : osLCCT.tolower();
578 :
579 53 : if( strstr(osLCCT,"us") && strstr(osLCCT,"survey")
580 : && (strstr(osLCCT,"feet") || strstr(osLCCT,"foot")) )
581 0 : strcpy(units, "us_survey_feet");
582 53 : else if(strstr(osLCCT, "linear_feet")
583 : || strstr(osLCCT, "linear_foot")
584 : || strstr(osLCCT, "international"))
585 0 : strcpy(units, "international_feet");
586 53 : else if( strstr(osLCCT,"meter") )
587 0 : strcpy(units, "meters");
588 :
589 53 : if (strlen(units) > 0)
590 0 : hasUnits = TRUE;
591 :
592 53 : if( strstr( szCTString, "Projection Name = ") && strstr( szCTString, "_StatePlane_"))
593 : {
594 0 : const char *pStr = strstr( szCTString, "Projection Name = ") + strlen("Projection Name = ");
595 0 : const char* pReturn = strchr( pStr, '\n');
596 : char CSName[128];
597 0 : strncpy(CSName, pStr, pReturn-pStr);
598 0 : CSName[pReturn-pStr] = '\0';
599 0 : if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName) == OGRERR_NONE )
600 : {
601 : // for some erdas citation keys, the state plane CS name is incomplete, the unit check is necessary.
602 0 : OGRBoolean done = FALSE;
603 0 : if (hasUnits)
604 : {
605 0 : OGR_SRSNode *poUnit = poSRS->GetAttrNode( "PROJCS|UNIT" );
606 :
607 0 : if( poUnit != NULL && poUnit->GetChildCount() >= 2 )
608 : {
609 0 : CPLString unitName = poUnit->GetChild(0)->GetValue();
610 0 : unitName.tolower();
611 :
612 0 : if (strstr(units, "us_survey_feet"))
613 : {
614 0 : if (strstr(unitName, "us_survey_feet") || strstr(unitName, "foot_us") )
615 0 : done = TRUE;
616 : }
617 0 : else if (strstr(units, "international_feet"))
618 : {
619 0 : if (strstr(unitName, "feet") || strstr(unitName, "foot"))
620 0 : done = TRUE;
621 : }
622 0 : else if (strstr(units, "meters"))
623 : {
624 0 : if (strstr(unitName, "meter") )
625 0 : done = TRUE;
626 0 : }
627 : }
628 : }
629 0 : if (done)
630 0 : return TRUE;
631 : }
632 0 : }
633 : }
634 53 : if( !hasUnits )
635 : {
636 53 : char *pszUnitsName = NULL;
637 53 : GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
638 53 : if( pszUnitsName && strlen(pszUnitsName) > 0 )
639 : {
640 52 : CPLString osLCCT = pszUnitsName;
641 52 : GTIFFreeMemory( pszUnitsName );
642 52 : osLCCT.tolower();
643 :
644 52 : if( strstr(osLCCT, "us") && strstr(osLCCT, "survey")
645 : && (strstr(osLCCT, "feet") || strstr(osLCCT, "foot")))
646 10 : strcpy(units, "us_survey_feet");
647 42 : else if(strstr(osLCCT, "feet") || strstr(osLCCT, "foot"))
648 0 : strcpy(units, "international_feet");
649 42 : else if(strstr(osLCCT, "meter"))
650 0 : strcpy(units, "meters");
651 52 : hasUnits = TRUE;
652 : }
653 : }
654 :
655 53 : if (strlen(units) == 0)
656 43 : strcpy(units, "meters");
657 :
658 : /* check PCSCitationGeoKey if it exists */
659 53 : szCTString[0] = '\0';
660 53 : if( hGTIF && GTIFKeyGet( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )
661 : {
662 : /* For tif created by LEICA(ERDAS), ESRI state plane pe string was used and */
663 : /* the state plane zone is given in PCSCitation. Therefore try Esri pe string first. */
664 1 : SetCitationToSRS(hGTIF, szCTString, strlen(szCTString), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
665 1 : const char *pcsName = poSRS->GetAttrValue("PROJCS");
666 1 : const char *pStr = NULL;
667 1 : if( (pcsName && (pStr = strstr(pcsName, "State Plane Zone ")) != NULL)
668 : || (pStr = strstr(szCTString, "State Plane Zone ")) != NULL )
669 : {
670 0 : pStr += strlen("State Plane Zone ");
671 0 : int statePlaneZone = abs(atoi(pStr));
672 : char nad[32];
673 0 : strcpy(nad, "HARN");
674 0 : if( strstr(szCTString, "NAD83") || strstr(szCTString, "NAD = 83") )
675 0 : strcpy(nad, "NAD83");
676 0 : else if( strstr(szCTString, "NAD27") || strstr(szCTString, "NAD = 27") )
677 0 : strcpy(nad, "NAD27");
678 0 : if( poSRS->ImportFromESRIStatePlaneWKT(statePlaneZone, (const char*)nad, (const char*)units, psDefn->PCS) == OGRERR_NONE )
679 0 : return TRUE;
680 : }
681 1 : else if( pcsName && (pStr = strstr(pcsName, "UTM Zone ")) != NULL )
682 0 : CheckUTM( psDefn, szCTString );
683 : }
684 :
685 : /* check state plane again to see if a pe string is available */
686 53 : if( psDefn->PCS != KvUserDefined )
687 : {
688 0 : if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, (const char*)units, psDefn->PCS) == OGRERR_NONE )
689 0 : return TRUE;
690 : }
691 :
692 53 : return FALSE;
693 : }
694 :
695 : /************************************************************************/
696 : /* CheckUTM() */
697 : /* */
698 : /* Check utm proj code by its name. */
699 : /************************************************************************/
700 0 : void CheckUTM( GTIFDefn * psDefn, char * pszCtString )
701 : {
702 0 : if(!psDefn || !pszCtString)
703 0 : return;
704 :
705 : static const char *apszUtmProjCode[] = {
706 : "PSAD56", "17N", "16017",
707 : "PSAD56", "18N", "16018",
708 : "PSAD56", "19N", "16019",
709 : "PSAD56", "20N", "16020",
710 : "PSAD56", "21N", "16021",
711 : "PSAD56", "17S", "16117",
712 : "PSAD56", "18S", "16118",
713 : "PSAD56", "19S", "16119",
714 : "PSAD56", "20S", "16120",
715 : "PSAD56", "21S", "16121",
716 : "PSAD56", "22S", "16122",
717 : NULL, NULL, NULL};
718 :
719 0 : char* p = strstr(pszCtString, "Datum = ");
720 : char datumName[128];
721 0 : if(p)
722 : {
723 0 : p += strlen("Datum = ");
724 0 : char* p1 = strchr(p, '|');
725 0 : if(p1)
726 : {
727 0 : strncpy(datumName, p, (p1-p));
728 0 : datumName[p1-p] = '\0';
729 : }
730 : else
731 0 : strcpy(datumName, p);
732 : }
733 :
734 : char utmName[64];
735 0 : p = strstr(pszCtString, "UTM Zone ");
736 0 : if(p)
737 : {
738 0 : p += strlen("UTM Zone ");
739 0 : char* p1 = strchr(p, '|');
740 0 : if(p1)
741 : {
742 0 : strncpy(utmName, p, (p1-p));
743 0 : utmName[p1-p] = '\0';
744 : }
745 : else
746 0 : strcpy(utmName, p);
747 : }
748 :
749 0 : for(int i=0; apszUtmProjCode[i]!=NULL; i += 3)
750 : {
751 0 : if(EQUALN(utmName, apszUtmProjCode[i+1], strlen(apszUtmProjCode[i+1])) &&
752 : EQUAL(datumName, apszUtmProjCode[i]) )
753 : {
754 0 : if(psDefn->ProjCode != atoi(apszUtmProjCode[i+2]))
755 : {
756 0 : psDefn->ProjCode = (short) atoi(apszUtmProjCode[i+2]);
757 : GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
758 0 : psDefn->ProjParm );
759 0 : break;
760 : }
761 : }
762 : }
763 0 : return;
764 : }
|