1 : /******************************************************************************
2 : * $Id$
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 "geo_normalize.h"
35 : #include "geovalues.h"
36 : #include "ogr_spatialref.h"
37 :
38 : CPL_CVSID("$Id$");
39 :
40 : #define nCitationNameTypes 9
41 : typedef enum
42 : {
43 : CitCsName = 0,
44 : CitPcsName = 1,
45 : CitProjectionName = 2,
46 : CitLUnitsName = 3,
47 : CitGcsName = 4,
48 : CitDatumName = 5,
49 : CitEllipsoidName = 6,
50 : CitPrimemName = 7,
51 : CitAUnitsName = 8
52 : } CitationNameType;
53 :
54 : char* ImagineCitationTranslation(const char* psCitation, geokey_t keyID);
55 : char** CitationStringParse(const char* psCitation);
56 : void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName);
57 : void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid);
58 : OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
59 : geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet);
60 : void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
61 : geokey_t geoKey,
62 : char **ppszGeogName,
63 : char **ppszDatumName,
64 : char **ppszPMName,
65 : char **ppszSpheroidName,
66 : char **ppszAngularUnits);
67 :
68 : /************************************************************************/
69 : /* ImagineCitationTranslation() */
70 : /* */
71 : /* Translate ERDAS Imagine GeoTif citation */
72 : /************************************************************************/
73 13 : char* ImagineCitationTranslation(const char* psCitation, geokey_t keyID)
74 : {
75 13 : char* ret = NULL;
76 13 : if(!psCitation)
77 0 : return ret;
78 13 : if(EQUALN(psCitation, "IMAGINE GeoTIFF Support", strlen("IMAGINE GeoTIFF Support")))
79 : {
80 0 : CPLString osName;
81 :
82 : // this is a handle IMAGING style citation
83 0 : const char* p = NULL;
84 0 : p = strchr(psCitation, '$');
85 0 : if(p)
86 0 : p = strchr(p, '\n');
87 0 : if(p)
88 0 : p++;
89 0 : const char* p1 = NULL;
90 0 : if(p)
91 0 : p1 = strchr(p, '\n');
92 0 : if(p && p1)
93 : {
94 0 : switch (keyID)
95 : {
96 : case PCSCitationGeoKey:
97 0 : osName = "PCS Name = ";
98 0 : break;
99 : case GTCitationGeoKey:
100 0 : osName = "CS Name = ";
101 0 : break;
102 : case GeogCitationGeoKey:
103 0 : if(!strstr(p, "Unable to"))
104 0 : osName = "GCS Name = ";
105 : break;
106 : default:
107 : break;
108 : }
109 0 : if(strlen(osName)>0)
110 : {
111 0 : osName.append(p, p1-p);
112 0 : osName += "|";
113 : }
114 : }
115 0 : p = strstr(psCitation, "Projection Name = ");
116 0 : if(p)
117 : {
118 0 : p += strlen("Projection Name = ");
119 0 : p1 = strchr(p, '\n');
120 0 : if(!p1)
121 0 : p1 = strchr(p, '\0');
122 : }
123 0 : if(p && p1)
124 : {
125 0 : osName.append(p, p1-p);
126 0 : osName += "|";
127 : }
128 0 : p = strstr(psCitation, "Datum = ");
129 0 : if(p)
130 : {
131 0 : p += strlen("Datum = ");
132 0 : p1 = strchr(p, '\n');
133 0 : if(!p1)
134 0 : p1 = strchr(p, '\0');
135 : }
136 0 : if(p && p1)
137 : {
138 0 : osName += "Datum = ";
139 0 : osName.append(p, p1-p);
140 0 : osName += "|";
141 : }
142 0 : p = strstr(psCitation, "Ellipsoid = ");
143 0 : if(p)
144 : {
145 0 : p += strlen("Ellipsoid = ");
146 0 : p1 = strchr(p, '\n');
147 0 : if(!p1)
148 0 : p1 = strchr(p, '\0');
149 : }
150 0 : if(p && p1)
151 : {
152 0 : osName += "Ellipsoid = ";
153 0 : osName.append(p, p1-p);
154 0 : osName += "|";
155 : }
156 0 : p = strstr(psCitation, "Units = ");
157 0 : if(p)
158 : {
159 0 : p += strlen("Units = ");
160 0 : p1 = strchr(p, '\n');
161 0 : if(!p1)
162 0 : p1 = strchr(p, '\0');
163 : }
164 0 : if(p && p1)
165 : {
166 0 : osName += "LUnits = ";
167 0 : osName.append(p, p1-p);
168 0 : osName += "|";
169 : }
170 0 : if(strlen(osName) > 0)
171 : {
172 0 : ret = CPLStrdup(osName);
173 0 : }
174 : }
175 13 : return ret;
176 : }
177 :
178 : /************************************************************************/
179 : /* CitationStringParse() */
180 : /* */
181 : /* Parse a Citation string */
182 : /************************************************************************/
183 13 : char** CitationStringParse(const char* psCitation)
184 : {
185 13 : char ** ret = NULL;
186 13 : if(!psCitation)
187 0 : return ret;
188 :
189 13 : ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes);
190 13 : const char* pDelimit = NULL;
191 13 : const char* pStr = psCitation;
192 13 : CPLString osName;
193 13 : int nCitationLen = strlen(psCitation);
194 13 : OGRBoolean nameFound = FALSE;
195 48 : while((pStr-psCitation+1)< nCitationLen)
196 : {
197 22 : if( (pDelimit = strstr(pStr, "|")) )
198 : {
199 18 : osName = "";
200 18 : osName.append(pStr, pDelimit-pStr);
201 18 : pStr = pDelimit+1;
202 : }
203 : else
204 : {
205 4 : osName = pStr;
206 4 : pStr += strlen(pStr);
207 : }
208 22 : const char* name = osName.c_str();
209 22 : if( strstr(name, "PCS Name = ") )
210 : {
211 0 : if (!ret[CitPcsName])
212 0 : ret[CitPcsName] = CPLStrdup(name+strlen("PCS Name = "));
213 0 : nameFound = TRUE;
214 : }
215 22 : if(strstr(name, "Projection Name = "))
216 : {
217 0 : if (!ret[CitProjectionName])
218 0 : ret[CitProjectionName] = CPLStrdup(name+strlen("Projection Name = "));
219 0 : nameFound = TRUE;
220 : }
221 22 : if(strstr(name, "LUnits = "))
222 : {
223 0 : if (!ret[CitLUnitsName])
224 0 : ret[CitLUnitsName] = CPLStrdup(name+strlen("LUnits = "));
225 0 : nameFound = TRUE;
226 : }
227 22 : if(strstr(name, "GCS Name = "))
228 : {
229 3 : if (!ret[CitGcsName])
230 3 : ret[CitGcsName] = CPLStrdup(name+strlen("GCS Name = "));
231 3 : nameFound = TRUE;
232 : }
233 22 : if(strstr(name, "Datum = "))
234 : {
235 3 : if (!ret[CitDatumName])
236 3 : ret[CitDatumName] = CPLStrdup(name+strlen("Datum = "));
237 3 : nameFound = TRUE;
238 : }
239 22 : if(strstr(name, "Ellipsoid = "))
240 : {
241 3 : if (!ret[CitEllipsoidName])
242 3 : ret[CitEllipsoidName] = CPLStrdup(name+strlen("Ellipsoid = "));
243 3 : nameFound = TRUE;
244 : }
245 22 : if(strstr(name, "Primem = "))
246 : {
247 3 : if (!ret[CitPrimemName])
248 3 : ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));
249 3 : nameFound = TRUE;
250 : }
251 22 : if(strstr(name, "AUnits = "))
252 : {
253 0 : if (!ret[CitAUnitsName])
254 0 : ret[CitAUnitsName] = CPLStrdup(name+strlen("AUnits = "));
255 0 : nameFound = TRUE;
256 : }
257 : }
258 13 : if(!nameFound)
259 : {
260 10 : CPLFree( ret );
261 10 : ret = (char**)NULL;
262 : }
263 13 : return ret;
264 : }
265 :
266 : /************************************************************************/
267 : /* SetLinearUnitCitation() */
268 : /* */
269 : /* Set linear unit Citation string */
270 : /************************************************************************/
271 0 : void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName)
272 : {
273 : char szName[512];
274 0 : CPLString osCitation;
275 0 : int n = 0;
276 0 : if( GTIFKeyGet( psGTIF, PCSCitationGeoKey, szName, 0, sizeof(szName) ) )
277 0 : n = strlen(szName);
278 0 : if(n>0)
279 : {
280 0 : osCitation = szName;
281 0 : if(osCitation[n-1] != '|')
282 0 : osCitation += "|";
283 0 : osCitation += "LUnits = ";
284 0 : osCitation += pszLinearUOMName;
285 0 : osCitation += "|";
286 : }
287 : else
288 : {
289 0 : osCitation = "LUnits = ";
290 0 : osCitation += pszLinearUOMName;
291 : }
292 0 : GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
293 0 : return;
294 : }
295 :
296 : /************************************************************************/
297 : /* SetGeogCSCitation() */
298 : /* */
299 : /* Set geogcs Citation string */
300 : /************************************************************************/
301 8 : void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid)
302 : {
303 8 : int bRewriteGeogCitation = FALSE;
304 : char szName[256];
305 8 : CPLString osCitation;
306 8 : size_t n = 0;
307 8 : if( GTIFKeyGet( psGTIF, GeogCitationGeoKey, szName, 0, sizeof(szName) ) )
308 8 : n = strlen(szName);
309 8 : if (n == 0)
310 : return;
311 :
312 8 : if(!EQUALN(szName, "GCS Name = ", strlen("GCS Name = ")))
313 : {
314 8 : osCitation = "GCS Name = ";
315 8 : osCitation += szName;
316 : }
317 : else
318 : {
319 0 : osCitation = szName;
320 : }
321 :
322 8 : if(nDatum == KvUserDefined )
323 : {
324 6 : const char* datumName = poSRS->GetAttrValue( "DATUM" );
325 6 : if(datumName && strlen(datumName) > 0)
326 : {
327 6 : osCitation += "|Datum = ";
328 6 : osCitation += datumName;
329 6 : bRewriteGeogCitation = TRUE;
330 : }
331 : }
332 8 : if(nSpheroid == KvUserDefined )
333 : {
334 8 : const char* spheroidName = poSRS->GetAttrValue( "SPHEROID" );
335 8 : if(spheroidName && strlen(spheroidName) > 0)
336 : {
337 6 : osCitation += "|Ellipsoid = ";
338 6 : osCitation += spheroidName;
339 6 : bRewriteGeogCitation = TRUE;
340 : }
341 : }
342 :
343 8 : const char* primemName = poSRS->GetAttrValue( "PRIMEM" );
344 8 : if(primemName && strlen(primemName) > 0)
345 : {
346 6 : osCitation += "|Primem = ";
347 6 : osCitation += primemName;
348 6 : bRewriteGeogCitation = TRUE;
349 :
350 6 : double primemValue = poSRS->GetPrimeMeridian(NULL);
351 6 : if(angUnitName && !EQUAL(angUnitName, "Degree"))
352 : {
353 0 : double aUnit = poSRS->GetAngularUnits(NULL);
354 0 : primemValue *= aUnit;
355 : }
356 : GTIFKeySet( psGTIF, GeogPrimeMeridianLongGeoKey, TYPE_DOUBLE, 1,
357 6 : primemValue );
358 : }
359 8 : if(angUnitName && strlen(angUnitName) > 0 && !EQUAL(angUnitName, "Degree"))
360 : {
361 0 : osCitation += "|AUnits = ";
362 0 : osCitation += angUnitName;
363 0 : bRewriteGeogCitation = TRUE;
364 : }
365 :
366 8 : if (osCitation[strlen(osCitation) - 1] != '|')
367 8 : osCitation += "|";
368 :
369 8 : if (bRewriteGeogCitation)
370 6 : GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
371 :
372 0 : return;
373 : }
374 :
375 : /************************************************************************/
376 : /* SetCitationToSRS() */
377 : /* */
378 : /* Parse and set Citation string to SRS */
379 : /************************************************************************/
380 8 : OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
381 : geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet)
382 : {
383 8 : OGRBoolean ret = FALSE;
384 8 : *linearUnitIsSet = FALSE;
385 8 : char* imgCTName = ImagineCitationTranslation(szCTString, geoKey);
386 8 : if(imgCTName)
387 : {
388 0 : strncpy(szCTString, imgCTName, nCTStringLen);
389 0 : szCTString[nCTStringLen-1] = '\0';
390 0 : CPLFree( imgCTName );
391 : }
392 8 : char** ctNames = CitationStringParse(szCTString);
393 8 : if(ctNames)
394 : {
395 0 : if( poSRS->GetRoot() == NULL)
396 0 : poSRS->SetNode( "PROJCS", "unnamed" );
397 0 : if(ctNames[CitPcsName])
398 : {
399 0 : poSRS->SetNode( "PROJCS", ctNames[CitPcsName] );
400 0 : ret = TRUE;
401 : }
402 0 : else if(geoKey != GTCitationGeoKey)
403 : {
404 : char szPCSName[128];
405 0 : if( GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 0, sizeof(szPCSName) ) )
406 : {
407 0 : poSRS->SetNode( "PROJCS", szPCSName );
408 0 : ret = TRUE;
409 : }
410 : }
411 :
412 0 : if(ctNames[CitProjectionName])
413 0 : poSRS->SetProjection( ctNames[CitProjectionName] );
414 :
415 0 : if(ctNames[CitLUnitsName])
416 : {
417 : double unitSize;
418 0 : if (GTIFKeyGet(hGTIF, ProjLinearUnitSizeGeoKey, &unitSize, 0,
419 : sizeof(unitSize) ))
420 : {
421 0 : poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
422 0 : *linearUnitIsSet = TRUE;
423 : }
424 : }
425 0 : for(int i= 0; i<nCitationNameTypes; i++)
426 0 : CPLFree( ctNames[i] );
427 0 : CPLFree( ctNames );
428 : }
429 8 : return ret;
430 : }
431 :
432 : /************************************************************************/
433 : /* GetGeogCSFromCitation() */
434 : /* */
435 : /* Parse and get geogcs names from a Citation string */
436 : /************************************************************************/
437 5 : void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
438 : geokey_t geoKey,
439 : char **ppszGeogName,
440 : char **ppszDatumName,
441 : char **ppszPMName,
442 : char **ppszSpheroidName,
443 : char **ppszAngularUnits)
444 : {
445 : *ppszGeogName = *ppszDatumName = *ppszPMName =
446 5 : *ppszSpheroidName = *ppszAngularUnits = NULL;
447 :
448 5 : char* imgCTName = ImagineCitationTranslation(szGCSName, geoKey);
449 5 : if(imgCTName)
450 : {
451 0 : strncpy(szGCSName, imgCTName, nGCSName);
452 0 : szGCSName[nGCSName-1] = '\0';
453 0 : CPLFree( imgCTName );
454 : }
455 5 : char** ctNames = CitationStringParse(szGCSName);
456 5 : if(ctNames)
457 : {
458 3 : if(ctNames[CitGcsName])
459 3 : *ppszGeogName = CPLStrdup( ctNames[CitGcsName] );
460 :
461 3 : if(ctNames[CitDatumName])
462 3 : *ppszDatumName = CPLStrdup( ctNames[CitDatumName] );
463 :
464 3 : if(ctNames[CitEllipsoidName])
465 3 : *ppszSpheroidName = CPLStrdup( ctNames[CitEllipsoidName] );
466 :
467 3 : if(ctNames[CitPrimemName])
468 3 : *ppszPMName = CPLStrdup( ctNames[CitPrimemName] );
469 :
470 3 : if(ctNames[CitAUnitsName])
471 0 : *ppszAngularUnits = CPLStrdup( ctNames[CitAUnitsName] );
472 :
473 30 : for(int i= 0; i<nCitationNameTypes; i++)
474 27 : CPLFree( ctNames[i] );
475 3 : CPLFree( ctNames );
476 : }
477 : return;
478 : }
479 :
480 :
|