1 : /******************************************************************************
2 : * $Id: ogr_srs_ozi.cpp 23921 2012-02-07 20:35:29Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: OGRSpatialReference translation from OziExplorer
6 : * georeferencing information.
7 : * Author: Andrey Kiselev, dron@ak4719.spb.edu
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2009, Andrey Kiselev <dron@ak4719.spb.edu>
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 "ogr_spatialref.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_csv.h"
34 :
35 : CPL_CVSID("$Id: ogr_srs_ozi.cpp 23921 2012-02-07 20:35:29Z rouault $");
36 :
37 : /************************************************************************/
38 : /* OSRImportFromOzi() */
39 : /************************************************************************/
40 :
41 6 : OGRErr OSRImportFromOzi( OGRSpatialReferenceH hSRS,
42 : const char *pszDatum, const char *pszProj,
43 : const char *pszProjParms )
44 :
45 : {
46 : return ((OGRSpatialReference *) hSRS)->importFromOzi( pszDatum, pszProj,
47 6 : pszProjParms );
48 : }
49 :
50 : /************************************************************************/
51 : /* importFromOzi() */
52 : /************************************************************************/
53 :
54 : /**
55 : * Import coordinate system from OziExplorer projection definition.
56 : *
57 : * This method will import projection definition in style, used by
58 : * OziExplorer software.
59 : *
60 : * This function is the equivalent of the C function OSRImportFromOzi().
61 : *
62 : * @param pszDatum Datum string. This is a fifth string in the
63 : * OziExplorer .MAP file.
64 : *
65 : * @param pszProj Projection string. Search for line starting with
66 : * "Map Projection" name in the OziExplorer .MAP file and supply it as a
67 : * whole in this parameter.
68 : *
69 : * @param pszProjParms String containing projection parameters. Search for
70 : * "Projection Setup" name in the OziExplorer .MAP file and supply it as a
71 : * whole in this parameter.
72 : *
73 : * @return OGRERR_NONE on success or an error code in case of failure.
74 : */
75 :
76 8 : OGRErr OGRSpatialReference::importFromOzi( const char *pszDatum,
77 : const char *pszProj,
78 : const char *pszProjParms )
79 :
80 : {
81 8 : Clear();
82 :
83 : /* -------------------------------------------------------------------- */
84 : /* Operate on the basis of the projection name. */
85 : /* -------------------------------------------------------------------- */
86 8 : char **papszProj = CSLTokenizeStringComplex( pszProj, ",", TRUE, TRUE );
87 : char **papszProjParms = CSLTokenizeStringComplex( pszProjParms, ",",
88 8 : TRUE, TRUE );
89 8 : char **papszDatum = NULL;
90 :
91 8 : if (CSLCount(papszProj) < 2)
92 : {
93 0 : goto not_enough_data;
94 : }
95 :
96 8 : if ( EQUALN(papszProj[1], "Latitude/Longitude", 18) )
97 : {
98 : }
99 :
100 4 : else if ( EQUALN(papszProj[1], "Mercator", 8) )
101 : {
102 0 : if (CSLCount(papszProjParms) < 6) goto not_enough_data;
103 0 : double dfScale = CPLAtof(papszProjParms[3]);
104 0 : if (papszProjParms[3][0] == 0) dfScale = 1; /* if unset, default to scale = 1 */
105 0 : SetMercator( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
106 : dfScale,
107 0 : CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
108 : }
109 :
110 4 : else if ( EQUALN(papszProj[1], "Transverse Mercator", 19) )
111 : {
112 0 : if (CSLCount(papszProjParms) < 6) goto not_enough_data;
113 0 : SetTM( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
114 0 : CPLAtof(papszProjParms[3]),
115 0 : CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
116 : }
117 :
118 4 : else if ( EQUALN(papszProj[1], "Lambert Conformal Conic", 23) )
119 : {
120 4 : if (CSLCount(papszProjParms) < 8) goto not_enough_data;
121 8 : SetLCC( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
122 8 : CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
123 20 : CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
124 : }
125 :
126 0 : else if ( EQUALN(papszProj[1], "Sinusoidal", 10) )
127 : {
128 0 : if (CSLCount(papszProjParms) < 6) goto not_enough_data;
129 0 : SetSinusoidal( CPLAtof(papszProjParms[2]),
130 0 : CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
131 : }
132 :
133 0 : else if ( EQUALN(papszProj[1], "Albers Equal Area", 17) )
134 : {
135 0 : if (CSLCount(papszProjParms) < 8) goto not_enough_data;
136 0 : SetACEA( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
137 0 : CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
138 0 : CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
139 : }
140 :
141 : else
142 : {
143 0 : CPLDebug( "OSR_Ozi", "Unsupported projection: \"%s\"", papszProj[1] );
144 : SetLocalCS( CPLString().Printf("\"Ozi\" projection \"%s\"",
145 0 : papszProj[1]) );
146 : }
147 :
148 : /* -------------------------------------------------------------------- */
149 : /* Try to translate the datum/spheroid. */
150 : /* -------------------------------------------------------------------- */
151 : papszDatum = CSLTokenizeString2( pszDatum, ",",
152 : CSLT_ALLOWEMPTYTOKENS
153 : | CSLT_STRIPLEADSPACES
154 8 : | CSLT_STRIPENDSPACES );
155 8 : if ( papszDatum == NULL)
156 0 : goto not_enough_data;
157 :
158 8 : if ( !IsLocal() )
159 : {
160 :
161 : /* -------------------------------------------------------------------- */
162 : /* Verify that we can find the CSV file containing the datums */
163 : /* -------------------------------------------------------------------- */
164 8 : if( CSVScanFileByName( CSVFilename( "ozi_datum.csv" ),
165 : "EPSG_DATUM_CODE",
166 : "4326", CC_Integer ) == NULL )
167 : {
168 : CPLError( CE_Failure, CPLE_OpenFailed,
169 : "Unable to open OZI support file %s.\n"
170 : "Try setting the GDAL_DATA environment variable to point\n"
171 : "to the directory containing OZI csv files.",
172 0 : CSVFilename( "ozi_datum.csv" ) );
173 0 : goto other_error;
174 : }
175 :
176 : /* -------------------------------------------------------------------- */
177 : /* Search for matching datum */
178 : /* -------------------------------------------------------------------- */
179 8 : const char *pszOziDatum = CSVFilename( "ozi_datum.csv" );
180 8 : CPLString osDName = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
181 8 : CC_ApproxString, "NAME" );
182 8 : if( strlen(osDName) == 0 )
183 : {
184 : CPLError( CE_Failure, CPLE_AppDefined,
185 : "Failed to find datum %s in ozi_datum.csv.",
186 0 : papszDatum[0] );
187 : goto other_error;
188 : }
189 :
190 8 : int nDatumCode = atoi( CSVGetField( pszOziDatum, "NAME", papszDatum[0],
191 8 : CC_ApproxString, "EPSG_DATUM_CODE" ) );
192 :
193 8 : if ( nDatumCode > 0 ) // There is a matching EPSG code
194 : {
195 6 : OGRSpatialReference oGCS;
196 6 : oGCS.importFromEPSG( nDatumCode );
197 6 : CopyGeogCSFrom( &oGCS );
198 : }
199 : else // We use the parameters from the CSV files
200 : {
201 2 : CPLString osEllipseCode = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
202 2 : CC_ApproxString, "ELLIPSOID_CODE" );
203 2 : double dfDeltaX = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
204 2 : CC_ApproxString, "DELTAX" ) );
205 2 : double dfDeltaY = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
206 2 : CC_ApproxString, "DELTAY" ) );
207 2 : double dfDeltaZ = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
208 2 : CC_ApproxString, "DELTAZ" ) );
209 :
210 :
211 : /* -------------------------------------------------------------------- */
212 : /* Verify that we can find the CSV file containing the ellipsoids */
213 : /* -------------------------------------------------------------------- */
214 2 : if( CSVScanFileByName( CSVFilename( "ozi_ellips.csv" ),
215 : "ELLIPSOID_CODE",
216 : "20", CC_Integer ) == NULL )
217 : {
218 : CPLError( CE_Failure, CPLE_OpenFailed,
219 : "Unable to open OZI support file %s.\n"
220 : "Try setting the GDAL_DATA environment variable to point\n"
221 : "to the directory containing OZI csv files.",
222 0 : CSVFilename( "ozi_ellips.csv" ) );
223 : goto other_error;
224 : }
225 :
226 : /* -------------------------------------------------------------------- */
227 : /* Lookup the ellipse code. */
228 : /* -------------------------------------------------------------------- */
229 2 : const char *pszOziEllipse = CSVFilename( "ozi_ellips.csv" );
230 :
231 : CPLString osEName = CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
232 2 : CC_ApproxString, "NAME" );
233 2 : if( strlen(osEName) == 0 )
234 : {
235 : CPLError( CE_Failure, CPLE_AppDefined,
236 : "Failed to find ellipsoid %s in ozi_ellips.csv.",
237 0 : osEllipseCode.c_str() );
238 : goto other_error;
239 : }
240 :
241 : double dfA = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
242 2 : CC_ApproxString, "A" ));
243 : double dfInvF = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
244 2 : CC_ApproxString, "INVF" ));
245 :
246 : /* -------------------------------------------------------------------- */
247 : /* Create geographic coordinate system. */
248 : /* -------------------------------------------------------------------- */
249 :
250 2 : SetGeogCS( osDName, osDName, osEName, dfA, dfInvF );
251 2 : SetTOWGS84( dfDeltaX, dfDeltaY, dfDeltaZ );
252 :
253 0 : }
254 : }
255 :
256 : /* -------------------------------------------------------------------- */
257 : /* Grid units translation */
258 : /* -------------------------------------------------------------------- */
259 8 : if( IsLocal() || IsProjected() )
260 4 : SetLinearUnits( SRS_UL_METER, 1.0 );
261 :
262 8 : FixupOrdering();
263 :
264 8 : CSLDestroy(papszProj);
265 8 : CSLDestroy(papszProjParms);
266 8 : CSLDestroy(papszDatum);
267 :
268 8 : return OGRERR_NONE;
269 :
270 : not_enough_data:
271 :
272 0 : CSLDestroy(papszProj);
273 0 : CSLDestroy(papszProjParms);
274 0 : CSLDestroy(papszDatum);
275 :
276 0 : return OGRERR_NOT_ENOUGH_DATA;
277 :
278 : other_error:
279 :
280 0 : CSLDestroy(papszProj);
281 0 : CSLDestroy(papszProjParms);
282 0 : CSLDestroy(papszDatum);
283 :
284 0 : return OGRERR_FAILURE;
285 : }
|