ultimatepp/bazaar/plugin/gdal/ogr/ogr_srs_ozi.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

509 lines
19 KiB
C++

/******************************************************************************
* $Id: ogr_srs_ozi.cpp 28972 2015-04-22 10:39:11Z rouault $
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: OGRSpatialReference translation from OziExplorer
* georeferencing information.
* Author: Andrey Kiselev, dron@ak4719.spb.edu
*
******************************************************************************
* Copyright (c) 2009, Andrey Kiselev <dron@ak4719.spb.edu>
* Copyright (c) 2009-2012, 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 "ogr_spatialref.h"
#include "cpl_conv.h"
#include "cpl_csv.h"
CPL_CVSID("$Id: ogr_srs_ozi.cpp 28972 2015-04-22 10:39:11Z rouault $");
/************************************************************************/
/* OSRImportFromOzi() */
/************************************************************************/
/**
* Import coordinate system from OziExplorer projection definition.
*
* This function will import projection definition in style, used by
* OziExplorer software.
*
* Note: another version of this function with a different signature existed
* in GDAL 1.X.
*
* @param hSRS spatial reference object.
* @param papszLines Map file lines. This is an array of strings containing
* the whole OziExplorer .MAP file. The array is terminated by a NULL pointer.
*
* @return OGRERR_NONE on success or an error code in case of failure.
*
* @since OGR 2.0
*/
OGRErr OSRImportFromOzi( OGRSpatialReferenceH hSRS,
const char * const* papszLines )
{
VALIDATE_POINTER1( hSRS, "OSRImportFromOzi", CE_Failure );
return ((OGRSpatialReference *) hSRS)->importFromOzi( papszLines );
}
/************************************************************************/
/* importFromOzi() */
/************************************************************************/
/**
* Import coordinate system from OziExplorer projection definition.
*
* This method will import projection definition in style, used by
* OziExplorer software.
*
* @param papszLines Map file lines. This is an array of strings containing
* the whole OziExplorer .MAP file. The array is terminated by a NULL pointer.
*
* @return OGRERR_NONE on success or an error code in case of failure.
*
* @since OGR 1.10
*/
OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
{
int iLine;
const char *pszDatum, *pszProj = NULL, *pszProjParms = NULL;
Clear();
int nLines = CSLCount((char**)papszLines);
if( nLines < 5 )
return OGRERR_NOT_ENOUGH_DATA;
pszDatum = papszLines[4];
for ( iLine = 5; iLine < nLines; iLine++ )
{
if ( EQUALN(papszLines[iLine], "Map Projection", 14) )
{
pszProj = papszLines[iLine];
}
else if ( EQUALN(papszLines[iLine], "Projection Setup", 16) )
{
pszProjParms = papszLines[iLine];
}
}
if ( ! ( pszDatum && pszProj && pszProjParms ) )
return OGRERR_NOT_ENOUGH_DATA;
/* -------------------------------------------------------------------- */
/* Operate on the basis of the projection name. */
/* -------------------------------------------------------------------- */
char **papszProj = CSLTokenizeStringComplex( pszProj, ",", TRUE, TRUE );
char **papszProjParms = CSLTokenizeStringComplex( pszProjParms, ",",
TRUE, TRUE );
char **papszDatum = NULL;
if (CSLCount(papszProj) < 2)
{
goto not_enough_data;
}
if ( EQUALN(papszProj[1], "Latitude/Longitude", 18) )
{
}
else if ( EQUALN(papszProj[1], "Mercator", 8) )
{
if (CSLCount(papszProjParms) < 6) goto not_enough_data;
double dfScale = CPLAtof(papszProjParms[3]);
if (papszProjParms[3][0] == 0) dfScale = 1; /* if unset, default to scale = 1 */
SetMercator( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
dfScale,
CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
}
else if ( EQUALN(papszProj[1], "Transverse Mercator", 19) )
{
if (CSLCount(papszProjParms) < 6) goto not_enough_data;
SetTM( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
CPLAtof(papszProjParms[3]),
CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
}
else if ( EQUALN(papszProj[1], "Lambert Conformal Conic", 23) )
{
if (CSLCount(papszProjParms) < 8) goto not_enough_data;
SetLCC( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
}
else if ( EQUALN(papszProj[1], "Sinusoidal", 10) )
{
if (CSLCount(papszProjParms) < 6) goto not_enough_data;
SetSinusoidal( CPLAtof(papszProjParms[2]),
CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
}
else if ( EQUALN(papszProj[1], "Albers Equal Area", 17) )
{
if (CSLCount(papszProjParms) < 8) goto not_enough_data;
SetACEA( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
}
else if ( EQUALN(papszProj[1], "(UTM) Universal Transverse Mercator", 35) && nLines > 5 )
{
/* Look for the UTM zone in the calibration point data */
for ( iLine = 5; iLine < nLines; iLine++ )
{
if ( EQUALN(papszLines[iLine], "Point", 5) )
{
char **papszTok = NULL;
papszTok = CSLTokenizeString2( papszLines[iLine], ",",
CSLT_ALLOWEMPTYTOKENS
| CSLT_STRIPLEADSPACES
| CSLT_STRIPENDSPACES );
if ( CSLCount(papszTok) < 17
|| EQUAL(papszTok[2], "")
|| EQUAL(papszTok[13], "")
|| EQUAL(papszTok[14], "")
|| EQUAL(papszTok[15], "")
|| EQUAL(papszTok[16], "") )
{
CSLDestroy(papszTok);
continue;
}
SetUTM( CPLAtofM(papszTok[13]), EQUAL(papszTok[16], "N") );
CSLDestroy(papszTok);
break;
}
}
if ( iLine == nLines ) /* Try to guess the UTM zone */
{
float fMinLongitude = INT_MAX;
float fMaxLongitude = INT_MIN;
float fMinLatitude = INT_MAX;
float fMaxLatitude = INT_MIN;
int bFoundMMPLL = FALSE;
for ( iLine = 5; iLine < nLines; iLine++ )
{
if ( EQUALN(papszLines[iLine], "MMPLL", 5) )
{
char **papszTok = NULL;
papszTok = CSLTokenizeString2( papszLines[iLine], ",",
CSLT_ALLOWEMPTYTOKENS
| CSLT_STRIPLEADSPACES
| CSLT_STRIPENDSPACES );
if ( CSLCount(papszTok) < 4 )
{
CSLDestroy(papszTok);
continue;
}
float fLongitude = CPLAtofM(papszTok[2]);
float fLatitude = CPLAtofM(papszTok[3]);
CSLDestroy(papszTok);
bFoundMMPLL = TRUE;
if ( fMinLongitude > fLongitude )
fMinLongitude = fLongitude;
if ( fMaxLongitude < fLongitude )
fMaxLongitude = fLongitude;
if ( fMinLatitude > fLatitude )
fMinLatitude = fLatitude;
if ( fMaxLatitude < fLatitude )
fMaxLatitude = fLatitude;
}
}
float fMedianLatitude = ( fMinLatitude + fMaxLatitude ) / 2;
float fMedianLongitude = ( fMinLongitude + fMaxLongitude ) / 2;
if ( bFoundMMPLL && fMaxLatitude <= 90 )
{
int nUtmZone;
if ( fMedianLatitude >= 56 && fMedianLatitude <= 64 &&
fMedianLongitude >= 3 && fMedianLongitude <= 12 )
nUtmZone = 32; /* Norway exception */
else if ( fMedianLatitude >= 72 && fMedianLatitude <= 84 &&
fMedianLongitude >= 0 && fMedianLongitude <= 42 )
nUtmZone = (int) ((fMedianLongitude + 3 ) / 12) * 2 + 31; /* Svalbard exception */
else
nUtmZone = (int) ((fMedianLongitude + 180 ) / 6) + 1;
SetUTM( nUtmZone, fMedianLatitude >= 0 );
}
else
CPLDebug( "OSR_Ozi", "UTM Zone not found");
}
}
else if ( EQUALN(papszProj[1], "(I) France Zone I", 17) )
{
SetLCC1SP( 49.5, 2.337229167, 0.99987734, 600000, 1200000 );
}
else if ( EQUALN(papszProj[1], "(II) France Zone II", 19) )
{
SetLCC1SP( 46.8, 2.337229167, 0.99987742, 600000, 2200000 );
}
else if ( EQUALN(papszProj[1], "(III) France Zone III", 21) )
{
SetLCC1SP( 44.1, 2.337229167, 0.99987750, 600000, 3200000 );
}
else if ( EQUALN(papszProj[1], "(IV) France Zone IV", 19) )
{
SetLCC1SP( 42.165, 2.337229167, 0.99994471, 234.358, 4185861.369 );
}
/*
* Note : The following projections have not been implemented yet
*
*/
/*
else if ( EQUALN(papszProj[1], "(BNG) British National Grid", 27) )
{
}
else if ( EQUALN(papszProj[1], "(IG) Irish Grid", 15) )
{
}
else if ( EQUALN(papszProj[1], "(NZG) New Zealand Grid", 22) )
{
}
else if ( EQUALN(papszProj[1], "(NZTM2) New Zealand TM 2000", 27) )
{
}
else if ( EQUALN(papszProj[1], "(SG) Swedish Grid", 27) )
{
}
else if ( EQUALN(papszProj[1], "(SUI) Swiss Grid", 26) )
{
}
else if ( EQUALN(papszProj[1], "(A)Lambert Azimuthual Equal Area", 32) )
{
}
else if ( EQUALN(papszProj[1], "(EQC) Equidistant Conic", 23) )
{
}
else if ( EQUALN(papszProj[1], "Polyconic (American)", 20) )
{
}
else if ( EQUALN(papszProj[1], "Van Der Grinten", 15) )
{
}
else if ( EQUALN(papszProj[1], "Vertical Near-Sided Perspective", 31) )
{
}
else if ( EQUALN(papszProj[1], "(WIV) Wagner IV", 15) )
{
}
else if ( EQUALN(papszProj[1], "Bonne", 5) )
{
}
else if ( EQUALN(papszProj[1], "(MT0) Montana State Plane Zone 2500", 35) )
{
}
else if ( EQUALN(papszProj[1], "ITA1) Italy Grid Zone 1", 23) )
{
}
else if ( EQUALN(papszProj[1], "ITA2) Italy Grid Zone 2", 23) )
{
}
else if ( EQUALN(papszProj[1], "(VICMAP-TM) Victoria Aust.(pseudo AMG)", 38) )
{
}
else if ( EQUALN(papszProj[1], "VICGRID) Victoria Australia", 27) )
{
}
else if ( EQUALN(papszProj[1], "(VG94) VICGRID94 Victoria Australia", 35) )
{
}
else if ( EQUALN(papszProj[1], "Gnomonic", 8) )
{
}
*/
else
{
CPLDebug( "OSR_Ozi", "Unsupported projection: \"%s\"", papszProj[1] );
SetLocalCS( CPLString().Printf("\"Ozi\" projection \"%s\"",
papszProj[1]) );
}
/* -------------------------------------------------------------------- */
/* Try to translate the datum/spheroid. */
/* -------------------------------------------------------------------- */
papszDatum = CSLTokenizeString2( pszDatum, ",",
CSLT_ALLOWEMPTYTOKENS
| CSLT_STRIPLEADSPACES
| CSLT_STRIPENDSPACES );
if ( papszDatum == NULL)
goto not_enough_data;
if ( !IsLocal() )
{
/* -------------------------------------------------------------------- */
/* Verify that we can find the CSV file containing the datums */
/* -------------------------------------------------------------------- */
if( CSVScanFileByName( CSVFilename( "ozi_datum.csv" ),
"EPSG_DATUM_CODE",
"4326", CC_Integer ) == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Unable to open OZI support file %s.\n"
"Try setting the GDAL_DATA environment variable to point\n"
"to the directory containing OZI csv files.",
CSVFilename( "ozi_datum.csv" ) );
goto other_error;
}
/* -------------------------------------------------------------------- */
/* Search for matching datum */
/* -------------------------------------------------------------------- */
const char *pszOziDatum = CSVFilename( "ozi_datum.csv" );
CPLString osDName = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
CC_ApproxString, "NAME" );
if( strlen(osDName) == 0 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Failed to find datum %s in ozi_datum.csv.",
papszDatum[0] );
goto other_error;
}
int nDatumCode = atoi( CSVGetField( pszOziDatum, "NAME", papszDatum[0],
CC_ApproxString, "EPSG_DATUM_CODE" ) );
if ( nDatumCode > 0 ) // There is a matching EPSG code
{
OGRSpatialReference oGCS;
oGCS.importFromEPSG( nDatumCode );
CopyGeogCSFrom( &oGCS );
}
else // We use the parameters from the CSV files
{
CPLString osEllipseCode = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
CC_ApproxString, "ELLIPSOID_CODE" );
double dfDeltaX = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
CC_ApproxString, "DELTAX" ) );
double dfDeltaY = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
CC_ApproxString, "DELTAY" ) );
double dfDeltaZ = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
CC_ApproxString, "DELTAZ" ) );
/* -------------------------------------------------------------------- */
/* Verify that we can find the CSV file containing the ellipsoids */
/* -------------------------------------------------------------------- */
if( CSVScanFileByName( CSVFilename( "ozi_ellips.csv" ),
"ELLIPSOID_CODE",
"20", CC_Integer ) == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Unable to open OZI support file %s.\n"
"Try setting the GDAL_DATA environment variable to point\n"
"to the directory containing OZI csv files.",
CSVFilename( "ozi_ellips.csv" ) );
goto other_error;
}
/* -------------------------------------------------------------------- */
/* Lookup the ellipse code. */
/* -------------------------------------------------------------------- */
const char *pszOziEllipse = CSVFilename( "ozi_ellips.csv" );
CPLString osEName = CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
CC_ApproxString, "NAME" );
if( strlen(osEName) == 0 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Failed to find ellipsoid %s in ozi_ellips.csv.",
osEllipseCode.c_str() );
goto other_error;
}
double dfA = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
CC_ApproxString, "A" ));
double dfInvF = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
CC_ApproxString, "INVF" ));
/* -------------------------------------------------------------------- */
/* Create geographic coordinate system. */
/* -------------------------------------------------------------------- */
SetGeogCS( osDName, osDName, osEName, dfA, dfInvF );
SetTOWGS84( dfDeltaX, dfDeltaY, dfDeltaZ );
}
}
/* -------------------------------------------------------------------- */
/* Grid units translation */
/* -------------------------------------------------------------------- */
if( IsLocal() || IsProjected() )
SetLinearUnits( SRS_UL_METER, 1.0 );
FixupOrdering();
CSLDestroy(papszProj);
CSLDestroy(papszProjParms);
CSLDestroy(papszDatum);
return OGRERR_NONE;
not_enough_data:
CSLDestroy(papszProj);
CSLDestroy(papszProjParms);
CSLDestroy(papszDatum);
return OGRERR_NOT_ENOUGH_DATA;
other_error:
CSLDestroy(papszProj);
CSLDestroy(papszProjParms);
CSLDestroy(papszDatum);
return OGRERR_FAILURE;
}