最近项目中需要用到空间参考中两个函数,分别是IsSame和AutoIdentifyEPSG两个函数。其中,前者是用于比较两个空间参考是否相同,而AutoIdentifyEPSG则是说明这个空间参考是否是EPSG编号。因为之前也提到过如果使用ArcGIS Desktop进行投影转为wkt是3857的参考后返回的字符串和GDAL自己申明wkt为3857的参考返回的字符串是不相同的,所有在自己编写的代码中运用到了AutoIdentifyEPSG来验证一下,现在我们来看这个函数的源代码实现。函数定义在OGR下面的ogr_fromepsg.cpp
首先该函数对参考参数进行判断,直接获取地理坐标代码,而如果是投影坐标则需要获取相应的代号信息。
OGRErr OGRSpatialReference::AutoIdentifyEPSG()
{
/* -------------------------------------------------------------------- */
/* Do we have a GEOGCS node, but no authority? If so, try */
/* guessing it. */
/* -------------------------------------------------------------------- */
if( (IsProjected() || IsGeographic())
&& GetAuthorityCode( "GEOGCS" ) == NULL )
{
int nGCS = GetEPSGGeogCS();
if( nGCS != -1 )
SetAuthority( "GEOGCS", "EPSG", nGCS );
}
/* -------------------------------------------------------------------- */
/* Is this a UTM coordinate system with a common GEOGCS? */
/* -------------------------------------------------------------------- */
int nZone, bNorth;
if( (nZone = GetUTMZone( &bNorth )) != 0
&& GetAuthorityCode( "PROJCS") == NULL )
{
const char *pszAuthName, *pszAuthCode;
pszAuthName = GetAuthorityName( "PROJCS|GEOGCS" );
pszAuthCode = GetAuthorityCode( "PROJCS|GEOGCS" );
if( pszAuthName == NULL || pszAuthCode == NULL )
{
/* don't exactly recognise datum */
}
else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4326 )
{ // WGS84
if( bNorth )
SetAuthority( "PROJCS", "EPSG", 32600 + nZone );
else
SetAuthority( "PROJCS", "EPSG", 32700 + nZone );
}
else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4267
&& nZone >= 3 && nZone <= 22 && bNorth )
SetAuthority( "PROJCS", "EPSG", 26700 + nZone ); // NAD27
else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4269
&& nZone >= 3 && nZone <= 23 && bNorth )
SetAuthority( "PROJCS", "EPSG", 26900 + nZone ); // NAD83
else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4322 )
{ // WGS72
if( bNorth )
SetAuthority( "PROJCS", "EPSG", 32200 + nZone );
else
SetAuthority( "PROJCS", "EPSG", 32300 + nZone );
}
}
/* -------------------------------------------------------------------- */
/* Return. */
/* -------------------------------------------------------------------- */
if( IsProjected() && GetAuthorityCode("PROJCS") != NULL )
return OGRERR_NONE;
else if( IsGeographic() && GetAuthorityCode("GEOGCS") != NULL )
return OGRERR_NONE;
else
return OGRERR_UNSUPPORTED_SRS;
}
而IsSame函数则是在ogrspatialreference.cpp中。
int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
{
if( GetRoot() == NULL && poOtherSRS->GetRoot() == NULL )
return TRUE;
else if( GetRoot() == NULL || poOtherSRS->GetRoot() == NULL )
return FALSE;
/* -------------------------------------------------------------------- */
/* Compare geographic coordinate system. */
/* -------------------------------------------------------------------- */
if( !IsSameGeogCS( poOtherSRS ) )
return FALSE;
/* -------------------------------------------------------------------- */
/* Do the have the same root types? Ie. is one PROJCS and one */
/* GEOGCS or perhaps LOCALCS? */
/* -------------------------------------------------------------------- */
if( !EQUAL(GetRoot()->GetValue(),poOtherSRS->GetRoot()->GetValue()) )
return FALSE;
/* -------------------------------------------------------------------- */
/* Compare projected coordinate system. */
/* -------------------------------------------------------------------- */
if( IsProjected() )
{
const char *pszValue1, *pszValue2;
const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
pszValue1 = this->GetAttrValue( "PROJECTION" );
pszValue2 = poOtherSRS->GetAttrValue( "PROJECTION" );
if( pszValue1 == NULL || pszValue2 == NULL
|| !EQUAL(pszValue1,pszValue2) )
return FALSE;
for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
{
const OGR_SRSNode *poNode;
poNode = poPROJCS->GetChild( iChild );
if( !EQUAL(poNode->GetValue(),"PARAMETER")
|| poNode->GetChildCount() != 2 )
continue;
/* this this eventually test within some epsilon? */
if( this->GetProjParm( poNode->GetChild(0)->GetValue() )
!= poOtherSRS->GetProjParm( poNode->GetChild(0)->GetValue() ) )
return FALSE;
}
}
/* -------------------------------------------------------------------- */
/* If they are LOCALCS/PROJCS, do they have the same units? */
/* -------------------------------------------------------------------- */
if( IsLocal() || IsProjected() )
{
if( GetLinearUnits() != 0.0 )
{
double dfRatio;
dfRatio = poOtherSRS->GetLinearUnits() / GetLinearUnits();
if( dfRatio < 0.9999999999 || dfRatio > 1.000000001 )
return FALSE;
}
}
/* -------------------------------------------------------------------- */
/* Compare vertical coordinate system. */
/* -------------------------------------------------------------------- */
if( IsVertical() && !IsSameVertCS( poOtherSRS ) )
return FALSE;
return TRUE;
}