mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-25 06:12:47 -06:00
770 lines
26 KiB
C++
770 lines
26 KiB
C++
/******************************************************************************
|
|
* $Id: gt_citation.cpp 28263 2014-12-29 22:00:08Z rouault $
|
|
*
|
|
* Project: GeoTIFF Driver
|
|
* Purpose: Implements special parsing of Imagine citation strings, and
|
|
* to encode PE String info in citation fields as needed.
|
|
* Author: Xiuguang Zhou (ESRI)
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2008, Xiuguang Zhou (ESRI)
|
|
* Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "cpl_port.h"
|
|
#include "cpl_string.h"
|
|
|
|
#include "geovalues.h"
|
|
#include "gt_citation.h"
|
|
#include "gt_wkt_srs_priv.h"
|
|
|
|
CPL_CVSID("$Id: gt_citation.cpp 28263 2014-12-29 22:00:08Z rouault $");
|
|
|
|
static const char *apszUnitMap[] = {
|
|
"meters", "1.0",
|
|
"meter", "1.0",
|
|
"m", "1.0",
|
|
"centimeters", "0.01",
|
|
"centimeter", "0.01",
|
|
"cm", "0.01",
|
|
"millimeters", "0.001",
|
|
"millimeter", "0.001",
|
|
"mm", "0.001",
|
|
"kilometers", "1000.0",
|
|
"kilometer", "1000.0",
|
|
"km", "1000.0",
|
|
"us_survey_feet", "0.3048006096012192",
|
|
"us_survey_foot", "0.3048006096012192",
|
|
"feet", "0.3048006096012192",
|
|
"foot", "0.3048006096012192",
|
|
"ft", "0.3048006096012192",
|
|
"international_feet", "0.3048",
|
|
"international_foot", "0.3048",
|
|
"inches", "0.0254000508001",
|
|
"inch", "0.0254000508001",
|
|
"in", "0.0254000508001",
|
|
"yards", "0.9144",
|
|
"yard", "0.9144",
|
|
"yd", "0.9144",
|
|
"miles", "1304.544",
|
|
"mile", "1304.544",
|
|
"mi", "1304.544",
|
|
"modified_american_feet", "0.3048122530",
|
|
"modified_american_foot", "0.3048122530",
|
|
"clarke_feet", "0.3047972651",
|
|
"clarke_foot", "0.3047972651",
|
|
"indian_feet", "0.3047995142",
|
|
"indian_foot", "0.3047995142",
|
|
"Yard_Indian", "0.9143985307444408",
|
|
"Foot_Clarke", "0.30479726540",
|
|
"Foot_Gold_Coast", "0.3047997101815088",
|
|
"Link_Clarke", "0.2011661951640",
|
|
"Yard_Sears", "0.9143984146160287",
|
|
"50_Kilometers", "50000.0",
|
|
"150_Kilometers", "150000.0",
|
|
NULL, NULL
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* ImagineCitationTranslation() */
|
|
/* */
|
|
/* Translate ERDAS Imagine GeoTif citation */
|
|
/************************************************************************/
|
|
char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
|
|
{
|
|
static const char *keyNames[] = {
|
|
"NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL
|
|
};
|
|
|
|
char* ret = NULL;
|
|
int i;
|
|
if(!psCitation)
|
|
return ret;
|
|
if(EQUALN(psCitation, "IMAGINE GeoTIFF Support", strlen("IMAGINE GeoTIFF Support")))
|
|
{
|
|
// this is a handle IMAGING style citation
|
|
char name[256];
|
|
name[0] = '\0';
|
|
char* p = NULL;
|
|
char* p1 = NULL;
|
|
|
|
p = strchr(psCitation, '$');
|
|
if( p && strchr(p, '\n') )
|
|
p = strchr(p, '\n') + 1;
|
|
if(p)
|
|
{
|
|
p1 = p + strlen(p);
|
|
char *p2 = strchr(p, '\n');
|
|
if(p2)
|
|
p1 = MIN(p1, p2);
|
|
p2 = strchr(p, '\0');
|
|
if(p2)
|
|
p1 = MIN(p1, p2);
|
|
for(i=0; keyNames[i]!=NULL; i++)
|
|
{
|
|
p2 = strstr(p, keyNames[i]);
|
|
if(p2)
|
|
p1 = MIN(p1, p2);
|
|
}
|
|
}
|
|
|
|
// PCS name, GCS name and PRJ name
|
|
if(p && p1)
|
|
{
|
|
switch (keyID)
|
|
{
|
|
case PCSCitationGeoKey:
|
|
if(strstr(psCitation, "Projection = "))
|
|
strcpy(name, "PRJ Name = ");
|
|
else
|
|
strcpy(name, "PCS Name = ");
|
|
break;
|
|
case GTCitationGeoKey:
|
|
strcpy(name, "PCS Name = ");
|
|
break;
|
|
case GeogCitationGeoKey:
|
|
if(!strstr(p, "Unable to"))
|
|
strcpy(name, "GCS Name = ");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if(strlen(name)>0)
|
|
{
|
|
char* p2;
|
|
if((p2 = strstr(psCitation, "Projection Name = ")) != 0)
|
|
p = p2 + strlen("Projection Name = ");
|
|
if((p2 = strstr(psCitation, "Projection = ")) != 0)
|
|
p = p2 + strlen("Projection = ");
|
|
if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
|
|
p1 --;
|
|
p2 = p1 - 1;
|
|
while( p2 != 0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
|
|
p2--;
|
|
if(p2 != p1 - 1)
|
|
p1 = p2;
|
|
if(p1 >= p)
|
|
{
|
|
strncat(name, p, p1-p+1);
|
|
strcat(name, "|");
|
|
name[strlen(name)] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
// All other parameters
|
|
for(i=0; keyNames[i]!=NULL; i++)
|
|
{
|
|
p = strstr(psCitation, keyNames[i]);
|
|
if(p)
|
|
{
|
|
p += strlen(keyNames[i]);
|
|
p1 = p + strlen(p);
|
|
char *p2 = strchr(p, '\n');
|
|
if(p2)
|
|
p1 = MIN(p1, p2);
|
|
p2 = strchr(p, '\0');
|
|
if(p2)
|
|
p1 = MIN(p1, p2);
|
|
for(int j=0; keyNames[j]!=NULL; j++)
|
|
{
|
|
p2 = strstr(p, keyNames[j]);
|
|
if(p2)
|
|
p1 = MIN(p1, p2);
|
|
}
|
|
}
|
|
if(p && p1 && p1>p)
|
|
{
|
|
if(EQUAL(keyNames[i], "Units = "))
|
|
strcat(name, "LUnits = ");
|
|
else
|
|
strcat(name, keyNames[i]);
|
|
if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
|
|
p1 --;
|
|
char* p2 = p1 - 1;
|
|
while( p2 != 0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
|
|
p2--;
|
|
if(p2 != p1 - 1)
|
|
p1 = p2;
|
|
if(p1 >= p)
|
|
{
|
|
strncat(name, p, p1-p+1);
|
|
strcat(name, "|");
|
|
name[strlen(name)] = '\0';
|
|
}
|
|
}
|
|
}
|
|
if(strlen(name) > 0)
|
|
ret = CPLStrdup(name);
|
|
}
|
|
return ret;
|
|
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CitationStringParse() */
|
|
/* */
|
|
/* Parse a Citation string */
|
|
/************************************************************************/
|
|
|
|
char** CitationStringParse(char* psCitation, geokey_t keyID)
|
|
{
|
|
char ** ret = NULL;
|
|
if(!psCitation)
|
|
return ret;
|
|
|
|
ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes);
|
|
char* pDelimit = NULL;
|
|
char* pStr = psCitation;
|
|
char name[512];
|
|
int nameSet = FALSE;
|
|
int nameLen = strlen(psCitation);
|
|
OGRBoolean nameFound = FALSE;
|
|
while((pStr-psCitation+1)< nameLen)
|
|
{
|
|
if( (pDelimit = strstr(pStr, "|")) != NULL )
|
|
{
|
|
strncpy( name, pStr, pDelimit-pStr );
|
|
name[pDelimit-pStr] = '\0';
|
|
pStr = pDelimit+1;
|
|
nameSet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
strcpy (name, pStr);
|
|
pStr += strlen(pStr);
|
|
nameSet = TRUE;
|
|
}
|
|
if( strstr(name, "PCS Name = ") )
|
|
{
|
|
ret[CitPcsName] = CPLStrdup(name+strlen("PCS Name = "));
|
|
nameFound = TRUE;
|
|
}
|
|
if(strstr(name, "PRJ Name = "))
|
|
{
|
|
ret[CitProjectionName] = CPLStrdup(name+strlen("PRJ Name = "));
|
|
nameFound = TRUE;
|
|
}
|
|
if(strstr(name, "LUnits = "))
|
|
{
|
|
ret[CitLUnitsName] = CPLStrdup(name+strlen("LUnits = "));
|
|
nameFound = TRUE;
|
|
}
|
|
if(strstr(name, "GCS Name = "))
|
|
{
|
|
ret[CitGcsName] = CPLStrdup(name+strlen("GCS Name = "));
|
|
nameFound = TRUE;
|
|
}
|
|
if(strstr(name, "Datum = "))
|
|
{
|
|
ret[CitDatumName] = CPLStrdup(name+strlen("Datum = "));
|
|
nameFound = TRUE;
|
|
}
|
|
if(strstr(name, "Ellipsoid = "))
|
|
{
|
|
ret[CitEllipsoidName] = CPLStrdup(name+strlen("Ellipsoid = "));
|
|
nameFound = TRUE;
|
|
}
|
|
if(strstr(name, "Primem = "))
|
|
{
|
|
ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));
|
|
nameFound = TRUE;
|
|
}
|
|
if(strstr(name, "AUnits = "))
|
|
{
|
|
ret[CitAUnitsName] = CPLStrdup(name+strlen("AUnits = "));
|
|
nameFound = TRUE;
|
|
}
|
|
}
|
|
if( !nameFound && keyID == GeogCitationGeoKey && nameSet )
|
|
{
|
|
ret[CitGcsName] = CPLStrdup(name);
|
|
nameFound = TRUE;
|
|
}
|
|
if(!nameFound)
|
|
{
|
|
CPLFree( ret );
|
|
ret = (char**)NULL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* SetLinearUnitCitation() */
|
|
/* */
|
|
/* Set linear unit Citation string */
|
|
/************************************************************************/
|
|
void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName)
|
|
{
|
|
char szName[512];
|
|
CPLString osCitation;
|
|
int n = 0;
|
|
if( GDALGTIFKeyGetASCII( psGTIF, PCSCitationGeoKey, szName, 0, sizeof(szName) ) )
|
|
n = strlen(szName);
|
|
if(n>0)
|
|
{
|
|
osCitation = szName;
|
|
if(osCitation[n-1] != '|')
|
|
osCitation += "|";
|
|
osCitation += "LUnits = ";
|
|
osCitation += pszLinearUOMName;
|
|
osCitation += "|";
|
|
}
|
|
else
|
|
{
|
|
osCitation = "LUnits = ";
|
|
osCitation += pszLinearUOMName;
|
|
}
|
|
GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
|
|
return;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetGeogCSCitation() */
|
|
/* */
|
|
/* Set geogcs Citation string */
|
|
/************************************************************************/
|
|
void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid)
|
|
{
|
|
int bRewriteGeogCitation = FALSE;
|
|
char szName[256];
|
|
CPLString osCitation;
|
|
size_t n = 0;
|
|
if( GDALGTIFKeyGetASCII( psGTIF, GeogCitationGeoKey, szName, 0, sizeof(szName) ) )
|
|
n = strlen(szName);
|
|
if (n == 0)
|
|
return;
|
|
|
|
if(!EQUALN(szName, "GCS Name = ", strlen("GCS Name = ")))
|
|
{
|
|
osCitation = "GCS Name = ";
|
|
osCitation += szName;
|
|
}
|
|
else
|
|
{
|
|
osCitation = szName;
|
|
}
|
|
|
|
if(nDatum == KvUserDefined )
|
|
{
|
|
const char* datumName = poSRS->GetAttrValue( "DATUM" );
|
|
if(datumName && strlen(datumName) > 0)
|
|
{
|
|
osCitation += "|Datum = ";
|
|
osCitation += datumName;
|
|
bRewriteGeogCitation = TRUE;
|
|
}
|
|
}
|
|
if(nSpheroid == KvUserDefined )
|
|
{
|
|
const char* spheroidName = poSRS->GetAttrValue( "SPHEROID" );
|
|
if(spheroidName && strlen(spheroidName) > 0)
|
|
{
|
|
osCitation += "|Ellipsoid = ";
|
|
osCitation += spheroidName;
|
|
bRewriteGeogCitation = TRUE;
|
|
}
|
|
}
|
|
|
|
const char* primemName = poSRS->GetAttrValue( "PRIMEM" );
|
|
if(primemName && strlen(primemName) > 0)
|
|
{
|
|
osCitation += "|Primem = ";
|
|
osCitation += primemName;
|
|
bRewriteGeogCitation = TRUE;
|
|
|
|
double primemValue = poSRS->GetPrimeMeridian(NULL);
|
|
if(angUnitName && !EQUAL(angUnitName, "Degree"))
|
|
{
|
|
double aUnit = poSRS->GetAngularUnits(NULL);
|
|
primemValue *= aUnit;
|
|
}
|
|
GTIFKeySet( psGTIF, GeogPrimeMeridianLongGeoKey, TYPE_DOUBLE, 1,
|
|
primemValue );
|
|
}
|
|
if(angUnitName && strlen(angUnitName) > 0 && !EQUAL(angUnitName, "Degree"))
|
|
{
|
|
osCitation += "|AUnits = ";
|
|
osCitation += angUnitName;
|
|
bRewriteGeogCitation = TRUE;
|
|
}
|
|
|
|
if (osCitation[strlen(osCitation) - 1] != '|')
|
|
osCitation += "|";
|
|
|
|
if (bRewriteGeogCitation)
|
|
GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
|
|
|
|
return;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetCitationToSRS() */
|
|
/* */
|
|
/* Parse and set Citation string to SRS */
|
|
/************************************************************************/
|
|
OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
|
|
geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet)
|
|
{
|
|
OGRBoolean ret = FALSE;
|
|
char* lUnitName = NULL;
|
|
|
|
poSRS->GetLinearUnits( &lUnitName );
|
|
if(!lUnitName || strlen(lUnitName) == 0 || EQUAL(lUnitName, "unknown"))
|
|
*linearUnitIsSet = FALSE;
|
|
else
|
|
*linearUnitIsSet = TRUE;
|
|
|
|
char* imgCTName = ImagineCitationTranslation(szCTString, geoKey);
|
|
if(imgCTName)
|
|
{
|
|
strncpy(szCTString, imgCTName, nCTStringLen);
|
|
szCTString[nCTStringLen-1] = '\0';
|
|
CPLFree( imgCTName );
|
|
}
|
|
char** ctNames = CitationStringParse(szCTString, geoKey);
|
|
if(ctNames)
|
|
{
|
|
if( poSRS->GetRoot() == NULL)
|
|
poSRS->SetNode( "PROJCS", "unnamed" );
|
|
if(ctNames[CitPcsName])
|
|
{
|
|
poSRS->SetNode( "PROJCS", ctNames[CitPcsName] );
|
|
ret = TRUE;
|
|
}
|
|
if(ctNames[CitProjectionName])
|
|
poSRS->SetProjection( ctNames[CitProjectionName] );
|
|
|
|
if(ctNames[CitLUnitsName])
|
|
{
|
|
double unitSize = 0.0;
|
|
int size = strlen(ctNames[CitLUnitsName]);
|
|
if(strchr(ctNames[CitLUnitsName], '\0'))
|
|
size -= 1;
|
|
for( int i = 0; apszUnitMap[i] != NULL; i += 2 )
|
|
{
|
|
if( EQUALN(apszUnitMap[i], ctNames[CitLUnitsName], size) )
|
|
{
|
|
unitSize = CPLAtof(apszUnitMap[i+1]);
|
|
break;
|
|
}
|
|
}
|
|
if( unitSize == 0.0 )
|
|
GDALGTIFKeyGetDOUBLE(hGTIF, ProjLinearUnitSizeGeoKey, &unitSize, 0, 1 );
|
|
poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
|
|
*linearUnitIsSet = TRUE;
|
|
}
|
|
for(int i= 0; i<nCitationNameTypes; i++)
|
|
CPLFree( ctNames[i] );
|
|
CPLFree( ctNames );
|
|
}
|
|
|
|
/* if no "PCS Name = " (from Erdas) in GTCitationGeoKey */
|
|
if(geoKey == GTCitationGeoKey)
|
|
{
|
|
if(strlen(szCTString) > 0 && !strstr(szCTString, "PCS Name = "))
|
|
{
|
|
const char* pszProjCS = poSRS->GetAttrValue( "PROJCS" );
|
|
if((!(pszProjCS && strlen(pszProjCS) > 0) && !strstr(szCTString, "Projected Coordinates"))
|
|
||(pszProjCS && strstr(pszProjCS, "unnamed")))
|
|
poSRS->SetNode( "PROJCS", szCTString );
|
|
ret = TRUE;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGeogCSFromCitation() */
|
|
/* */
|
|
/* Parse and get geogcs names from a Citation string */
|
|
/************************************************************************/
|
|
void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
|
|
geokey_t geoKey,
|
|
char **ppszGeogName,
|
|
char **ppszDatumName,
|
|
char **ppszPMName,
|
|
char **ppszSpheroidName,
|
|
char **ppszAngularUnits)
|
|
{
|
|
*ppszGeogName = *ppszDatumName = *ppszPMName =
|
|
*ppszSpheroidName = *ppszAngularUnits = NULL;
|
|
|
|
char* imgCTName = ImagineCitationTranslation(szGCSName, geoKey);
|
|
if(imgCTName)
|
|
{
|
|
strncpy(szGCSName, imgCTName, nGCSName);
|
|
szGCSName[nGCSName-1] = '\0';
|
|
CPLFree( imgCTName );
|
|
}
|
|
char** ctNames = CitationStringParse(szGCSName, geoKey);
|
|
if(ctNames)
|
|
{
|
|
if(ctNames[CitGcsName])
|
|
*ppszGeogName = CPLStrdup( ctNames[CitGcsName] );
|
|
|
|
if(ctNames[CitDatumName])
|
|
*ppszDatumName = CPLStrdup( ctNames[CitDatumName] );
|
|
|
|
if(ctNames[CitEllipsoidName])
|
|
*ppszSpheroidName = CPLStrdup( ctNames[CitEllipsoidName] );
|
|
|
|
if(ctNames[CitPrimemName])
|
|
*ppszPMName = CPLStrdup( ctNames[CitPrimemName] );
|
|
|
|
if(ctNames[CitAUnitsName])
|
|
*ppszAngularUnits = CPLStrdup( ctNames[CitAUnitsName] );
|
|
|
|
for(int i= 0; i<nCitationNameTypes; i++)
|
|
CPLFree( ctNames[i] );
|
|
CPLFree( ctNames );
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* CheckCitationKeyForStatePlaneUTM() */
|
|
/* */
|
|
/* Handle state plane and UTM in citation key */
|
|
/************************************************************************/
|
|
OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet)
|
|
{
|
|
if( !hGTIF || !psDefn || !poSRS )
|
|
return FALSE;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* For ESRI builds we are interested in maximizing PE */
|
|
/* compatability, but generally we prefer to use EPSG */
|
|
/* definitions of the coordinate system if PCS is defined. */
|
|
/* -------------------------------------------------------------------- */
|
|
#if !defined(ESRI_BUILD)
|
|
if( psDefn->PCS != KvUserDefined )
|
|
return FALSE;
|
|
#endif
|
|
|
|
char szCTString[512];
|
|
szCTString[0] = '\0';
|
|
|
|
/* Check units */
|
|
char units[32];
|
|
units[0] = '\0';
|
|
|
|
OGRBoolean hasUnits = FALSE;
|
|
if( GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
|
|
{
|
|
CPLString osLCCT = szCTString;
|
|
|
|
osLCCT.tolower();
|
|
|
|
if( strstr(osLCCT,"us") && strstr(osLCCT,"survey")
|
|
&& (strstr(osLCCT,"feet") || strstr(osLCCT,"foot")) )
|
|
strcpy(units, "us_survey_feet");
|
|
else if(strstr(osLCCT, "linear_feet")
|
|
|| strstr(osLCCT, "linear_foot")
|
|
|| strstr(osLCCT, "international"))
|
|
strcpy(units, "international_feet");
|
|
else if( strstr(osLCCT,"meter") )
|
|
strcpy(units, "meters");
|
|
|
|
if (strlen(units) > 0)
|
|
hasUnits = TRUE;
|
|
|
|
if( strstr( szCTString, "Projection Name = ") && strstr( szCTString, "_StatePlane_"))
|
|
{
|
|
const char *pStr = strstr( szCTString, "Projection Name = ") + strlen("Projection Name = ");
|
|
const char* pReturn = strchr( pStr, '\n');
|
|
char CSName[128];
|
|
strncpy(CSName, pStr, pReturn-pStr);
|
|
CSName[pReturn-pStr] = '\0';
|
|
if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName) == OGRERR_NONE )
|
|
{
|
|
// for some erdas citation keys, the state plane CS name is incomplete, the unit check is necessary.
|
|
OGRBoolean done = FALSE;
|
|
if (hasUnits)
|
|
{
|
|
OGR_SRSNode *poUnit = poSRS->GetAttrNode( "PROJCS|UNIT" );
|
|
|
|
if( poUnit != NULL && poUnit->GetChildCount() >= 2 )
|
|
{
|
|
CPLString unitName = poUnit->GetChild(0)->GetValue();
|
|
unitName.tolower();
|
|
|
|
if (strstr(units, "us_survey_feet"))
|
|
{
|
|
if (strstr(unitName, "us_survey_feet") || strstr(unitName, "foot_us") )
|
|
done = TRUE;
|
|
}
|
|
else if (strstr(units, "international_feet"))
|
|
{
|
|
if (strstr(unitName, "feet") || strstr(unitName, "foot"))
|
|
done = TRUE;
|
|
}
|
|
else if (strstr(units, "meters"))
|
|
{
|
|
if (strstr(unitName, "meter") )
|
|
done = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (done)
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
if( !hasUnits )
|
|
{
|
|
char *pszUnitsName = NULL;
|
|
GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
|
|
if( pszUnitsName && strlen(pszUnitsName) > 0 )
|
|
{
|
|
CPLString osLCCT = pszUnitsName;
|
|
GTIFFreeMemory( pszUnitsName );
|
|
osLCCT.tolower();
|
|
|
|
if( strstr(osLCCT, "us") && strstr(osLCCT, "survey")
|
|
&& (strstr(osLCCT, "feet") || strstr(osLCCT, "foot")))
|
|
strcpy(units, "us_survey_feet");
|
|
else if(strstr(osLCCT, "feet") || strstr(osLCCT, "foot"))
|
|
strcpy(units, "international_feet");
|
|
else if(strstr(osLCCT, "meter"))
|
|
strcpy(units, "meters");
|
|
hasUnits = TRUE;
|
|
}
|
|
}
|
|
|
|
if (strlen(units) == 0)
|
|
strcpy(units, "meters");
|
|
|
|
/* check PCSCitationGeoKey if it exists */
|
|
szCTString[0] = '\0';
|
|
if( hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )
|
|
{
|
|
/* For tif created by LEICA(ERDAS), ESRI state plane pe string was used and */
|
|
/* the state plane zone is given in PCSCitation. Therefore try Esri pe string first. */
|
|
SetCitationToSRS(hGTIF, szCTString, strlen(szCTString), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
|
|
const char *pcsName = poSRS->GetAttrValue("PROJCS");
|
|
const char *pStr = NULL;
|
|
if( (pcsName && (pStr = strstr(pcsName, "State Plane Zone ")) != NULL)
|
|
|| (pStr = strstr(szCTString, "State Plane Zone ")) != NULL )
|
|
{
|
|
pStr += strlen("State Plane Zone ");
|
|
int statePlaneZone = abs(atoi(pStr));
|
|
char nad[32];
|
|
strcpy(nad, "HARN");
|
|
if( strstr(szCTString, "NAD83") || strstr(szCTString, "NAD = 83") )
|
|
strcpy(nad, "NAD83");
|
|
else if( strstr(szCTString, "NAD27") || strstr(szCTString, "NAD = 27") )
|
|
strcpy(nad, "NAD27");
|
|
if( poSRS->ImportFromESRIStatePlaneWKT(statePlaneZone, (const char*)nad, (const char*)units, psDefn->PCS) == OGRERR_NONE )
|
|
return TRUE;
|
|
}
|
|
else if( pcsName && (pStr = strstr(pcsName, "UTM Zone ")) != NULL )
|
|
CheckUTM( psDefn, szCTString );
|
|
}
|
|
|
|
/* check state plane again to see if a pe string is available */
|
|
if( psDefn->PCS != KvUserDefined )
|
|
{
|
|
if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, (const char*)units, psDefn->PCS) == OGRERR_NONE )
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CheckUTM() */
|
|
/* */
|
|
/* Check utm proj code by its name. */
|
|
/************************************************************************/
|
|
void CheckUTM( GTIFDefn * psDefn, const char * pszCtString )
|
|
{
|
|
if(!psDefn || !pszCtString)
|
|
return;
|
|
|
|
static const char *apszUtmProjCode[] = {
|
|
"PSAD56", "17N", "16017",
|
|
"PSAD56", "18N", "16018",
|
|
"PSAD56", "19N", "16019",
|
|
"PSAD56", "20N", "16020",
|
|
"PSAD56", "21N", "16021",
|
|
"PSAD56", "17S", "16117",
|
|
"PSAD56", "18S", "16118",
|
|
"PSAD56", "19S", "16119",
|
|
"PSAD56", "20S", "16120",
|
|
"PSAD56", "21S", "16121",
|
|
"PSAD56", "22S", "16122",
|
|
NULL, NULL, NULL};
|
|
|
|
const char* p = strstr(pszCtString, "Datum = ");
|
|
char datumName[128];
|
|
if(p)
|
|
{
|
|
p += strlen("Datum = ");
|
|
const char* p1 = strchr(p, '|');
|
|
if(p1 && p1-p < (int)sizeof(datumName))
|
|
{
|
|
strncpy(datumName, p, (p1-p));
|
|
datumName[p1-p] = '\0';
|
|
}
|
|
else
|
|
CPLStrlcpy(datumName, p, sizeof(datumName));
|
|
}
|
|
else
|
|
{
|
|
datumName[0] = '\0';
|
|
}
|
|
|
|
char utmName[64];
|
|
p = strstr(pszCtString, "UTM Zone ");
|
|
if(p)
|
|
{
|
|
p += strlen("UTM Zone ");
|
|
const char* p1 = strchr(p, '|');
|
|
if(p1 && p1-p < (int)sizeof(utmName))
|
|
{
|
|
strncpy(utmName, p, (p1-p));
|
|
utmName[p1-p] = '\0';
|
|
}
|
|
else
|
|
CPLStrlcpy(utmName, p, sizeof(utmName));
|
|
|
|
for(int i=0; apszUtmProjCode[i]!=NULL; i += 3)
|
|
{
|
|
if(EQUALN(utmName, apszUtmProjCode[i+1], strlen(apszUtmProjCode[i+1])) &&
|
|
EQUAL(datumName, apszUtmProjCode[i]) )
|
|
{
|
|
if(psDefn->ProjCode != atoi(apszUtmProjCode[i+2]))
|
|
{
|
|
psDefn->ProjCode = (short) atoi(apszUtmProjCode[i+2]);
|
|
GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
|
|
psDefn->ProjParm );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|