📄 ogr_fromepsg.cpp
字号:
/******************************************************************************
* $Id: ogr_fromepsg.cpp 10646 2007-01-18 02:38:10Z warmerdam $
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: Generate an OGRSpatialReference object based on an EPSG
* PROJCS, or GEOGCS code.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2000, Frank Warmerdam
*
* 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 "ogr_spatialref.h"
#include "cpl_csv.h"
CPL_CVSID("$Id: ogr_fromepsg.cpp 10646 2007-01-18 02:38:10Z warmerdam $");
#ifndef PI
# define PI 3.14159265358979323846
#endif
static const char *papszDatumEquiv[] =
{
"Militar_Geographische_Institut",
"Militar_Geographische_Institute",
"World_Geodetic_System_1984",
"WGS_1984",
"WGS_72_Transit_Broadcast_Ephemeris",
"WGS_1972_Transit_Broadcast_Ephemeris",
"World_Geodetic_System_1972",
"WGS_1972",
"European_Terrestrial_Reference_System_89",
"European_Reference_System_1989",
NULL
};
/************************************************************************/
/* OGREPSGDatumNameMassage() */
/* */
/* Massage an EPSG datum name into WMT format. Also transform */
/* specific exception cases into WKT versions. */
/************************************************************************/
void OGREPSGDatumNameMassage( char ** ppszDatum )
{
int i, j;
char *pszDatum = *ppszDatum;
/* -------------------------------------------------------------------- */
/* Translate non-alphanumeric values to underscores. */
/* -------------------------------------------------------------------- */
for( i = 0; pszDatum[i] != '\0'; i++ )
{
if( !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
&& !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
&& !(pszDatum[i] >= '0' && pszDatum[i] <= '9') )
{
pszDatum[i] = '_';
}
}
/* -------------------------------------------------------------------- */
/* Remove repeated and trailing underscores. */
/* -------------------------------------------------------------------- */
for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
{
if( pszDatum[j] == '_' && pszDatum[i] == '_' )
continue;
pszDatum[++j] = pszDatum[i];
}
if( pszDatum[j] == '_' )
pszDatum[j] = '\0';
else
pszDatum[j+1] = '\0';
/* -------------------------------------------------------------------- */
/* Search for datum equivelences. Specific massaged names get */
/* mapped to OpenGIS specified names. */
/* -------------------------------------------------------------------- */
for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
{
if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
{
CPLFree( *ppszDatum );
*ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
break;
}
}
}
/************************************************************************/
/* EPSGAngleStringToDD() */
/* */
/* Convert an angle in the specified units to decimal degrees. */
/************************************************************************/
static double
EPSGAngleStringToDD( const char * pszAngle, int nUOMAngle )
{
double dfAngle;
if( nUOMAngle == 9110 ) /* DDD.MMSSsss */
{
char *pszDecimal;
dfAngle = ABS(atoi(pszAngle));
pszDecimal = (char *) strchr(pszAngle,'.');
if( pszDecimal != NULL && strlen(pszDecimal) > 1 )
{
char szMinutes[3];
char szSeconds[64];
szMinutes[0] = pszDecimal[1];
if( pszDecimal[2] >= '0' && pszDecimal[2] <= '9' )
szMinutes[1] = pszDecimal[2];
else
szMinutes[1] = '0';
szMinutes[2] = '\0';
dfAngle += atoi(szMinutes) / 60.0;
if( strlen(pszDecimal) > 3 )
{
szSeconds[0] = pszDecimal[3];
if( pszDecimal[4] >= '0' && pszDecimal[4] <= '9' )
{
szSeconds[1] = pszDecimal[4];
szSeconds[2] = '.';
strcpy( szSeconds+3, pszDecimal + 5 );
}
else
{
szSeconds[1] = '0';
szSeconds[2] = '\0';
}
dfAngle += atof(szSeconds) / 3600.0;
}
}
if( pszAngle[0] == '-' )
dfAngle *= -1;
}
else if( nUOMAngle == 9105 || nUOMAngle == 9106 ) /* grad */
{
dfAngle = 180 * (atof(pszAngle ) / 200);
}
else if( nUOMAngle == 9101 ) /* radians */
{
dfAngle = 180 * (atof(pszAngle ) / PI);
}
else if( nUOMAngle == 9103 ) /* arc-minute */
{
dfAngle = atof(pszAngle) / 60;
}
else if( nUOMAngle == 9104 ) /* arc-second */
{
dfAngle = atof(pszAngle) / 3600;
}
else /* decimal degrees ... some cases missing but seeminly never used */
{
CPLAssert( nUOMAngle == 9102 || nUOMAngle == 0 );
dfAngle = atof(pszAngle );
}
return( dfAngle );
}
/************************************************************************/
/* EPSGGetUOMAngleInfo() */
/************************************************************************/
int EPSGGetUOMAngleInfo( int nUOMAngleCode,
char **ppszUOMName,
double * pdfInDegrees )
{
const char *pszUOMName = NULL;
double dfInDegrees = 1.0;
const char *pszFilename = CSVFilename( "unit_of_measure.csv" );
char szSearchKey[24];
sprintf( szSearchKey, "%d", nUOMAngleCode );
pszUOMName = CSVGetField( pszFilename,
"UOM_CODE", szSearchKey, CC_Integer,
"UNIT_OF_MEAS_NAME" );
/* -------------------------------------------------------------------- */
/* If the file is found, read from there. Note that FactorC is */
/* an empty field for any of the DMS style formats, and in this */
/* case we really want to return the default InDegrees value */
/* (1.0) from above. */
/* -------------------------------------------------------------------- */
if( pszUOMName != NULL )
{
double dfFactorB, dfFactorC;
dfFactorB =
atof(CSVGetField( pszFilename,
"UOM_CODE", szSearchKey, CC_Integer,
"FACTOR_B" ));
dfFactorC =
atof(CSVGetField( pszFilename,
"UOM_CODE", szSearchKey, CC_Integer,
"FACTOR_C" ));
if( dfFactorC != 0.0 )
dfInDegrees = (dfFactorB / dfFactorC) * (180.0 / PI);
/* We do a special override of some of the DMS formats name */
if( nUOMAngleCode == 9102 || nUOMAngleCode == 9107
|| nUOMAngleCode == 9108 || nUOMAngleCode == 9110
|| nUOMAngleCode == 9122 )
pszUOMName = "degree";
// For some reason, (FactorB) is not very precise in EPSG, use
// a more exact form for grads.
if( nUOMAngleCode == 9105 )
dfInDegrees = 180.0 / 200.0;
}
/* -------------------------------------------------------------------- */
/* Otherwise handle a few well known units directly. */
/* -------------------------------------------------------------------- */
else
{
switch( nUOMAngleCode )
{
case 9101:
pszUOMName = "radian";
dfInDegrees = 180.0 / PI;
break;
case 9102:
case 9107:
case 9108:
case 9110:
case 9122:
pszUOMName = "degree";
dfInDegrees = 1.0;
break;
case 9103:
pszUOMName = "arc-minute";
dfInDegrees = 1 / 60.0;
break;
case 9104:
pszUOMName = "arc-second";
dfInDegrees = 1 / 3600.0;
break;
case 9105:
pszUOMName = "grad";
dfInDegrees = 180.0 / 200.0;
break;
case 9106:
pszUOMName = "gon";
dfInDegrees = 180.0 / 200.0;
break;
case 9109:
pszUOMName = "microradian";
dfInDegrees = 180.0 / (3.14159265358979 * 1000000.0);
break;
default:
return FALSE;
}
}
/* -------------------------------------------------------------------- */
/* Return to caller. */
/* -------------------------------------------------------------------- */
if( ppszUOMName != NULL )
{
if( pszUOMName != NULL )
*ppszUOMName = CPLStrdup( pszUOMName );
else
*ppszUOMName = NULL;
}
if( pdfInDegrees != NULL )
*pdfInDegrees = dfInDegrees;
return( TRUE );
}
/************************************************************************/
/* EPSGGetUOMLengthInfo() */
/* */
/* Note: This function should eventually also know how to */
/* lookup length aliases in the UOM_LE_ALIAS table. */
/************************************************************************/
static int
EPSGGetUOMLengthInfo( int nUOMLengthCode,
char **ppszUOMName,
double * pdfInMeters )
{
char **papszUnitsRecord;
char szSearchKey[24];
int iNameField;
#define UOM_FILENAME CSVFilename( "unit_of_measure.csv" )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -