Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: OGRSpatialReference translation to/from USGS georeferencing
5 : * information (used in GCTP package).
6 : * Author: Andrey Kiselev, dron@ak4719.spb.edu
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
10 : * Copyright (c) 2008-2009, Even Rouault <even dot rouault at spatialys.com>
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 "cpl_port.h"
32 : #include "ogr_srs_api.h"
33 :
34 : #include <cmath>
35 : #include <cstddef>
36 :
37 : #include "cpl_conv.h"
38 : #include "cpl_csv.h"
39 : #include "cpl_error.h"
40 : #include "cpl_string.h"
41 : #include "ogr_core.h"
42 : #include "ogr_p.h"
43 : #include "ogr_spatialref.h"
44 :
45 : /************************************************************************/
46 : /* GCTP projection codes. */
47 : /************************************************************************/
48 :
49 : constexpr long GEO = 0L; // Geographic
50 : constexpr long UTM = 1L; // Universal Transverse Mercator (UTM)
51 : constexpr long SPCS = 2L; // State Plane Coordinates
52 : constexpr long ALBERS = 3L; // Albers Conical Equal Area
53 : constexpr long LAMCC = 4L; // Lambert Conformal Conic
54 : constexpr long MERCAT = 5L; // Mercator
55 : constexpr long PS = 6L; // Polar Stereographic
56 : constexpr long POLYC = 7L; // Polyconic
57 : constexpr long EQUIDC = 8L; // Equidistant Conic
58 : constexpr long TM = 9L; // Transverse Mercator
59 : constexpr long STEREO = 10L; // Stereographic
60 : constexpr long LAMAZ = 11L; // Lambert Azimuthal Equal Area
61 : constexpr long AZMEQD = 12L; // Azimuthal Equidistant
62 : constexpr long GNOMON = 13L; // Gnomonic
63 : constexpr long ORTHO = 14L; // Orthographic
64 : // constexpr long GVNSP = 15L; // General Vertical Near-Side Perspective
65 : constexpr long SNSOID = 16L; // Sinusiodal
66 : constexpr long EQRECT = 17L; // Equirectangular
67 : constexpr long MILLER = 18L; // Miller Cylindrical
68 : constexpr long VGRINT = 19L; // Van der Grinten
69 : constexpr long HOM = 20L; // (Hotine) Oblique Mercator
70 : constexpr long ROBIN = 21L; // Robinson
71 : // constexpr long SOM = 22L; // Space Oblique Mercator (SOM)
72 : // constexpr long ALASKA = 23L; // Alaska Conformal
73 : // constexpr long GOODE = 24L; // Interrupted Goode Homolosine
74 : constexpr long MOLL = 25L; // Mollweide
75 : // constexpr long IMOLL = 26L; // Interrupted Mollweide
76 : // constexpr long HAMMER = 27L; // Hammer
77 : constexpr long WAGIV = 28L; // Wagner IV
78 : constexpr long WAGVII = 29L; // Wagner VII
79 : // constexpr long OBEQA = 30L; // Oblated Equal Area
80 : // constexpr long ISINUS1 = 31L; // Integerized Sinusoidal Grid (the same as 99)
81 : // constexpr long CEA = 97L; // Cylindrical Equal Area (Grid corners set
82 : // in meters for EASE grid)
83 : // constexpr long BCEA = 98L; // Cylindrical Equal Area (Grid corners set
84 : // in DMS degs for EASE grid)
85 : // constexpr long ISINUS = 99L; // Integerized Sinusoidal Grid
86 : // (added by Raj Gejjagaraguppe ARC for MODIS)
87 :
88 : /************************************************************************/
89 : /* GCTP ellipsoid codes. */
90 : /************************************************************************/
91 :
92 : constexpr long CLARKE1866 = 0L;
93 : // constexpr long CLARKE1880 = 1L;
94 : // constexpr long BESSEL = 2L;
95 : // constexpr long INTERNATIONAL1967 = 3L;
96 : // constexpr long INTERNATIONAL1909 = 4L;
97 : // constexpr long WGS72 = 5L;
98 : // constexpr long EVEREST = 6L;
99 : // constexpr long WGS66 = 7L;
100 : constexpr long GRS1980 = 8L;
101 : // constexpr long AIRY = 9L;
102 : // constexpr long MODIFIED_EVEREST = 10L;
103 : // constexpr long MODIFIED_AIRY = 11L;
104 : constexpr long WGS84 = 12L;
105 : // constexpr long SOUTHEAST_ASIA = 13L;
106 : // constexpr long AUSTRALIAN_NATIONAL= 14L;
107 : // constexpr long KRASSOVSKY = 15L;
108 : // constexpr long HOUGH = 16L;
109 : // constexpr long MERCURY1960 = 17L;
110 : // constexpr long MODIFIED_MERCURY = 18L;
111 : // constexpr long SPHERE = 19L;
112 :
113 : /************************************************************************/
114 : /* Correspondence between GCTP and EPSG ellipsoid codes. */
115 : /************************************************************************/
116 :
117 : constexpr int aoEllipsUSGS[] = {
118 : 7008, // Clarke, 1866 (NAD1927)
119 : 7034, // Clarke, 1880
120 : 7004, // Bessel, 1841
121 : 0, // FIXME: New International, 1967 --- skipped
122 : 7022, // International, 1924 (Hayford, 1909) XXX?
123 : 7043, // WGS, 1972
124 : 7042, // Everest, 1830
125 : 7025, // FIXME: WGS, 1966
126 : 7019, // GRS, 1980 (NAD1983)
127 : 7001, // Airy, 1830
128 : 7018, // Modified Everest
129 : 7002, // Modified Airy
130 : 7030, // WGS, 1984 (GPS)
131 : 0, // FIXME: Southeast Asia --- skipped
132 : 7003, // Australian National, 1965
133 : 7024, // Krassovsky, 1940
134 : 7053, // Hough
135 : 0, // FIXME: Mercury, 1960 --- skipped
136 : 0, // FIXME: Modified Mercury, 1968 --- skipped
137 : 7047, // Sphere, rad 6370997 m (normal sphere)
138 : 7006, // Bessel, 1841 (Namibia)
139 : 7016, // Everest (Sabah & Sarawak)
140 : 7044, // Everest, 1956
141 : 7056, // Everest, Malaysia 1969
142 : 7018, // Everest, Malay & Singapr 1948
143 : 0, // FIXME: Everest, Pakistan --- skipped
144 : 7022, // Hayford (International 1924) XXX?
145 : 7020, // Helmert 1906
146 : 7021, // Indonesian, 1974
147 : 7036, // South American, 1969
148 : 0 // FIXME: WGS 60 --- skipped
149 : };
150 :
151 : #define NUMBER_OF_USGS_ELLIPSOIDS static_cast<int>(CPL_ARRAYSIZE(aoEllipsUSGS))
152 :
153 : /************************************************************************/
154 : /* OSRImportFromUSGS() */
155 : /************************************************************************/
156 :
157 : /**
158 : * \brief Import coordinate system from USGS projection definition.
159 : *
160 : * This function is the same as OGRSpatialReference::importFromUSGS().
161 : */
162 1 : OGRErr OSRImportFromUSGS(OGRSpatialReferenceH hSRS, long iProjsys, long iZone,
163 : double *padfPrjParams, long iDatum)
164 :
165 : {
166 1 : VALIDATE_POINTER1(hSRS, "OSRImportFromUSGS", OGRERR_FAILURE);
167 :
168 1 : return OGRSpatialReference::FromHandle(hSRS)->importFromUSGS(
169 1 : iProjsys, iZone, padfPrjParams, iDatum);
170 : }
171 :
172 8 : static double OGRSpatialReferenceUSGSUnpackNoOp(double dfVal)
173 : {
174 8 : return dfVal;
175 : }
176 :
177 0 : static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
178 : {
179 0 : return dfVal * 180.0 / M_PI;
180 : }
181 :
182 : /************************************************************************/
183 : /* importFromUSGS() */
184 : /************************************************************************/
185 :
186 : /**
187 : \brief Import coordinate system from USGS projection definition.
188 :
189 : This method will import projection definition in style, used by USGS GCTP
190 : software. GCTP operates on angles in packed DMS format (see
191 : CPLDecToPackedDMS() function for details), so all angle values (latitudes,
192 : longitudes, azimuths, etc.) specified in the padfPrjParams array should
193 : be in the packed DMS format, unless bAnglesInPackedDMSFormat is set to FALSE.
194 : *
195 : This function is the equivalent of the C function OSRImportFromUSGS().
196 : Note that the bAnglesInPackedDMSFormat parameter is only present in the C++
197 : method. The C function assumes bAnglesInPackedFormat = TRUE.
198 :
199 : @param iProjSys Input projection system code, used in GCTP.
200 :
201 : @param iZone Input zone for UTM and State Plane projection systems. For
202 : Southern Hemisphere UTM use a negative zone code. iZone ignored for all
203 : other projections.
204 :
205 : @param padfPrjParams Array of 15 coordinate system parameters. These
206 : parameters differs for different projections.
207 :
208 : \verbatim
209 : Projection Transformation Package Projection Parameters:
210 :
211 : ----------------------------------------------------------------------------
212 : | Array Element
213 : Code & Projection Id |---------------------------------------------------
214 : | 0 | 1 | 2 | 3 | 4 | 5 |6 | 7
215 : ----------------------------------------------------------------------------
216 : 0 Geographic | | | | | | | |
217 : 1 U T M |Lon/Z |Lat/Z | | | | | |
218 : 2 State Plane | | | | | | | |
219 : 3 Albers Equal Area |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
220 : 4 Lambert Conformal C |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
221 : 5 Mercator |SMajor|SMinor| | |CentMer|TrueScale|FE|FN
222 : 6 Polar Stereographic |SMajor|SMinor| | |LongPol|TrueScale|FE|FN
223 : 7 Polyconic |SMajor|SMinor| | |CentMer|OriginLat|FE|FN
224 : 8 Equid. Conic A |SMajor|SMinor|STDPAR| |CentMer|OriginLat|FE|FN
225 : Equid. Conic B |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
226 : 9 Transverse Mercator |SMajor|SMinor|Factor| |CentMer|OriginLat|FE|FN
227 : 10 Stereographic |Sphere| | | |CentLon|CenterLat|FE|FN
228 : 11 Lambert Azimuthal |Sphere| | | |CentLon|CenterLat|FE|FN
229 : 12 Azimuthal |Sphere| | | |CentLon|CenterLat|FE|FN
230 : 13 Gnomonic |Sphere| | | |CentLon|CenterLat|FE|FN
231 : 14 Orthographic |Sphere| | | |CentLon|CenterLat|FE|FN
232 : 15 Gen. Vert. Near Per |Sphere| |Height| |CentLon|CenterLat|FE|FN
233 : 16 Sinusoidal |Sphere| | | |CentMer| |FE|FN
234 : 17 Equirectangular |Sphere| | | |CentMer|TrueScale|FE|FN
235 : 18 Miller Cylindrical |Sphere| | | |CentMer| |FE|FN
236 : 19 Van der Grinten |Sphere| | | |CentMer|OriginLat|FE|FN
237 : 20 Hotin Oblique Merc A |SMajor|SMinor|Factor| | |OriginLat|FE|FN
238 : Hotin Oblique Merc B |SMajor|SMinor|Factor|AziAng|AzmthPt|OriginLat|FE|FN
239 : 21 Robinson |Sphere| | | |CentMer| |FE|FN
240 : 22 Space Oblique Merc A |SMajor|SMinor| |IncAng|AscLong| |FE|FN
241 : Space Oblique Merc B |SMajor|SMinor|Satnum|Path | | |FE|FN
242 : 23 Alaska Conformal |SMajor|SMinor| | | | |FE|FN
243 : 24 Interrupted Goode |Sphere| | | | | | |
244 : 25 Mollweide |Sphere| | | |CentMer| |FE|FN
245 : 26 Interrupt Mollweide |Sphere| | | | | | |
246 : 27 Hammer |Sphere| | | |CentMer| |FE|FN
247 : 28 Wagner IV |Sphere| | | |CentMer| |FE|FN
248 : 29 Wagner VII |Sphere| | | |CentMer| |FE|FN
249 : 30 Oblated Equal Area |Sphere| |Shapem|Shapen|CentLon|CenterLat|FE|FN
250 : ----------------------------------------------------------------------------
251 :
252 : ----------------------------------------------------
253 : | Array Element |
254 : Code & Projection Id |---------------------------
255 : | 8 | 9 | 10 | 11 | 12 |
256 : ----------------------------------------------------
257 : 0 Geographic | | | | | |
258 : 1 U T M | | | | | |
259 : 2 State Plane | | | | | |
260 : 3 Albers Equal Area | | | | | |
261 : 4 Lambert Conformal C | | | | | |
262 : 5 Mercator | | | | | |
263 : 6 Polar Stereographic | | | | | |
264 : 7 Polyconic | | | | | |
265 : 8 Equid. Conic A |zero | | | | |
266 : Equid. Conic B |one | | | | |
267 : 9 Transverse Mercator | | | | | |
268 : 10 Stereographic | | | | | |
269 : 11 Lambert Azimuthal | | | | | |
270 : 12 Azimuthal | | | | | |
271 : 13 Gnomonic | | | | | |
272 : 14 Orthographic | | | | | |
273 : 15 Gen. Vert. Near Per | | | | | |
274 : 16 Sinusoidal | | | | | |
275 : 17 Equirectangular | | | | | |
276 : 18 Miller Cylindrical | | | | | |
277 : 19 Van der Grinten | | | | | |
278 : 20 Hotin Oblique Merc A |Long1|Lat1|Long2|Lat2|zero|
279 : Hotin Oblique Merc B | | | | |one |
280 : 21 Robinson | | | | | |
281 : 22 Space Oblique Merc A |PSRev|LRat|PFlag| |zero|
282 : Space Oblique Merc B | | | | |one |
283 : 23 Alaska Conformal | | | | | |
284 : 24 Interrupted Goode | | | | | |
285 : 25 Mollweide | | | | | |
286 : 26 Interrupt Mollweide | | | | | |
287 : 27 Hammer | | | | | |
288 : 28 Wagner IV | | | | | |
289 : 29 Wagner VII | | | | | |
290 : 30 Oblated Equal Area |Angle| | | | |
291 : ----------------------------------------------------
292 :
293 : where
294 :
295 : Lon/Z Longitude of any point in the UTM zone or zero. If zero,
296 : a zone code must be specified.
297 : Lat/Z Latitude of any point in the UTM zone or zero. If zero, a
298 : zone code must be specified.
299 : SMajor Semi-major axis of ellipsoid. If zero, Clarke 1866 in meters
300 : is assumed.
301 : SMinor Eccentricity squared of the ellipsoid if less than zero,
302 : if zero, a spherical form is assumed, or if greater than
303 : zero, the semi-minor axis of ellipsoid.
304 : Sphere Radius of reference sphere. If zero, 6370997 meters is used.
305 : STDPAR Latitude of the standard parallel
306 : STDPR1 Latitude of the first standard parallel
307 : STDPR2 Latitude of the second standard parallel
308 : CentMer Longitude of the central meridian
309 : OriginLat Latitude of the projection origin
310 : FE False easting in the same units as the semi-major axis
311 : FN False northing in the same units as the semi-major axis
312 : TrueScale Latitude of true scale
313 : LongPol Longitude down below pole of map
314 : Factor Scale factor at central meridian (Transverse Mercator) or
315 : center of projection (Hotine Oblique Mercator)
316 : CentLon Longitude of center of projection
317 : CenterLat Latitude of center of projection
318 : Height Height of perspective point
319 : Long1 Longitude of first point on center line (Hotine Oblique
320 : Mercator, format A)
321 : Long2 Longitude of second point on center line (Hotine Oblique
322 : Mercator, format A)
323 : Lat1 Latitude of first point on center line (Hotine Oblique
324 : Mercator, format A)
325 : Lat2 Latitude of second point on center line (Hotine Oblique
326 : Mercator, format A)
327 : AziAng Azimuth angle east of north of center line (Hotine Oblique
328 : Mercator, format B)
329 : AzmthPt Longitude of point on central meridian where azimuth occurs
330 : (Hotine Oblique Mercator, format B)
331 : IncAng Inclination of orbit at ascending node, counter-clockwise
332 : from equator (SOM, format A)
333 : AscLong Longitude of ascending orbit at equator (SOM, format A)
334 : PSRev Period of satellite revolution in minutes (SOM, format A)
335 : LRat Landsat ratio to compensate for confusion at northern end
336 : of orbit (SOM, format A -- use 0.5201613)
337 : PFlag End of path flag for Landsat: 0 = start of path,
338 : 1 = end of path (SOM, format A)
339 : Satnum Landsat Satellite Number (SOM, format B)
340 : Path Landsat Path Number (Use WRS-1 for Landsat 1, 2 and 3 and
341 : WRS-2 for Landsat 4, 5 and 6.) (SOM, format B)
342 : Shapem Oblated Equal Area oval shape parameter m
343 : Shapen Oblated Equal Area oval shape parameter n
344 : Angle Oblated Equal Area oval rotation angle
345 :
346 : Array elements 13 and 14 are set to zero. All array elements with blank
347 : fields are set to zero too.
348 : \endverbatim
349 :
350 : @param iDatum Input spheroid.<p>
351 :
352 : If the datum code is negative, the first two values in the parameter array
353 : (param) are used to define the values as follows:
354 :
355 : <ul>
356 :
357 : <li> If padfPrjParams[0] is a non-zero value and padfPrjParams[1] is
358 : greater than one, the semimajor axis is set to padfPrjParams[0] and
359 : the semiminor axis is set to padfPrjParams[1].
360 :
361 : <li> If padfPrjParams[0] is nonzero and padfPrjParams[1] is greater than
362 : zero but less than or equal to one, the semimajor axis is set to
363 : padfPrjParams[0] and the semiminor axis is computed from the eccentricity
364 : squared value padfPrjParams[1]:<p>
365 :
366 : semiminor = sqrt(1.0 - ES)semimajor<p>
367 :
368 : where<p>
369 :
370 : ES = eccentricity squared
371 :
372 : <li> If padfPrjParams[0] is nonzero and padfPrjParams[1] is equal to zero,
373 : the semimajor axis and semiminor axis are set to padfPrjParams[0].
374 :
375 : <li> If padfPrjParams[0] equals zero and padfPrjParams[1] is greater than
376 : zero, the default Clarke 1866 is used to assign values to the semimajor
377 : axis and semiminor axis.
378 :
379 : <li> If padfPrjParams[0] and padfPrjParams[1] equals zero, the semimajor
380 : axis is set to 6370997.0 and the semiminor axis is set to zero.
381 :
382 : </ul>
383 :
384 : If a datum code is zero or greater, the semimajor and semiminor axis are
385 : defined by the datum code as found in the following table:
386 :
387 : Supported Datums are:
388 : <ul>
389 : <li>0: Clarke 1866 (default)
390 : <li>1: Clarke 1880
391 : <li>2: Bessel
392 : <li>3: International 1967
393 : <li>4: International 1909
394 : <li>5: WGS 72
395 : <li>6: Everest
396 : <li>7: WGS 66
397 : <li>8: GRS 1980/WGS 84
398 : <li>9: Airy
399 : <li>10: Modified Everest
400 : <li>11: Modified Airy
401 : <li>12: WGS 84
402 : <li>13: Southeast Asia
403 : <li>14: Australian National
404 : <li>15: Krassovsky
405 : <li>16: Hough
406 : <li>17: Mercury 1960
407 : <li>18: Modified Mercury 1968
408 : <li>19: Sphere of Radius 6370997 meters
409 : </ul>
410 :
411 : @param nUSGSAngleFormat one of USGS_ANGLE_DECIMALDEGREES,
412 : USGS_ANGLE_PACKEDDMS, or USGS_ANGLE_RADIANS (default is
413 : USGS_ANGLE_PACKEDDMS).
414 :
415 : @return OGRERR_NONE on success or an error code in case of failure.
416 : */
417 :
418 23 : OGRErr OGRSpatialReference::importFromUSGS(long iProjSys, long iZone,
419 : double *padfPrjParams, long iDatum,
420 : int nUSGSAngleFormat)
421 :
422 : {
423 23 : if (!padfPrjParams)
424 0 : return OGRERR_CORRUPT_DATA;
425 :
426 23 : double (*pfnUnpackAnglesFn)(double) = nullptr;
427 :
428 23 : if (nUSGSAngleFormat == USGS_ANGLE_DECIMALDEGREES)
429 6 : pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackNoOp;
430 17 : else if (nUSGSAngleFormat == USGS_ANGLE_RADIANS)
431 0 : pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackRadian;
432 : else
433 17 : pfnUnpackAnglesFn = CPLPackedDMSToDec;
434 :
435 : /* -------------------------------------------------------------------- */
436 : /* Operate on the basis of the projection code. */
437 : /* -------------------------------------------------------------------- */
438 23 : switch (iProjSys)
439 : {
440 2 : case GEO:
441 2 : break;
442 :
443 8 : case UTM:
444 : {
445 8 : int bNorth = TRUE;
446 :
447 8 : if (!iZone)
448 : {
449 2 : if (padfPrjParams[2] != 0.0)
450 : {
451 2 : iZone = static_cast<long>(padfPrjParams[2]);
452 : }
453 0 : else if (padfPrjParams[0] != 0.0 && padfPrjParams[1] != 0.0)
454 : {
455 : const double dfUnpackedAngle =
456 0 : pfnUnpackAnglesFn(padfPrjParams[0]);
457 0 : iZone = static_cast<long>(
458 0 : ((dfUnpackedAngle + 180.0) / 6.0) + 1.0);
459 0 : if (dfUnpackedAngle < 0)
460 0 : bNorth = FALSE;
461 : }
462 : }
463 :
464 8 : if (iZone < -60 || iZone > 60)
465 0 : return OGRERR_CORRUPT_DATA;
466 :
467 8 : if (iZone < 0)
468 : {
469 0 : iZone = -iZone;
470 0 : bNorth = FALSE;
471 : }
472 8 : SetUTM(static_cast<int>(iZone), bNorth);
473 : }
474 8 : break;
475 :
476 0 : case SPCS:
477 : {
478 0 : int bNAD83 = TRUE;
479 :
480 0 : if (iDatum == 0)
481 0 : bNAD83 = FALSE;
482 0 : else if (iDatum != 8)
483 0 : CPLError(CE_Warning, CPLE_AppDefined,
484 : "Wrong datum for State Plane projection %d. "
485 : "Should be 0 or 8.",
486 : static_cast<int>(iDatum));
487 :
488 0 : SetStatePlane(static_cast<int>(iZone), bNAD83);
489 : }
490 0 : break;
491 :
492 0 : case ALBERS:
493 0 : SetACEA(pfnUnpackAnglesFn(padfPrjParams[2]),
494 0 : pfnUnpackAnglesFn(padfPrjParams[3]),
495 0 : pfnUnpackAnglesFn(padfPrjParams[5]),
496 0 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
497 0 : padfPrjParams[7]);
498 0 : break;
499 :
500 2 : case LAMCC:
501 2 : SetLCC(pfnUnpackAnglesFn(padfPrjParams[2]),
502 2 : pfnUnpackAnglesFn(padfPrjParams[3]),
503 2 : pfnUnpackAnglesFn(padfPrjParams[5]),
504 2 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
505 2 : padfPrjParams[7]);
506 2 : break;
507 :
508 0 : case MERCAT:
509 0 : SetMercator(pfnUnpackAnglesFn(padfPrjParams[5]),
510 0 : pfnUnpackAnglesFn(padfPrjParams[4]), 1.0,
511 0 : padfPrjParams[6], padfPrjParams[7]);
512 0 : break;
513 :
514 0 : case PS:
515 0 : SetPS(pfnUnpackAnglesFn(padfPrjParams[5]),
516 0 : pfnUnpackAnglesFn(padfPrjParams[4]), 1.0, padfPrjParams[6],
517 0 : padfPrjParams[7]);
518 :
519 0 : break;
520 :
521 0 : case POLYC:
522 0 : SetPolyconic(pfnUnpackAnglesFn(padfPrjParams[5]),
523 0 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
524 0 : padfPrjParams[7]);
525 0 : break;
526 :
527 1 : case EQUIDC:
528 1 : if (padfPrjParams[8] != 0.0)
529 : {
530 1 : SetEC(pfnUnpackAnglesFn(padfPrjParams[2]),
531 1 : pfnUnpackAnglesFn(padfPrjParams[3]),
532 1 : pfnUnpackAnglesFn(padfPrjParams[5]),
533 1 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
534 1 : padfPrjParams[7]);
535 : }
536 : else
537 : {
538 0 : SetEC(pfnUnpackAnglesFn(padfPrjParams[2]),
539 0 : pfnUnpackAnglesFn(padfPrjParams[2]),
540 0 : pfnUnpackAnglesFn(padfPrjParams[5]),
541 0 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
542 0 : padfPrjParams[7]);
543 : }
544 1 : break;
545 :
546 6 : case TM:
547 6 : SetTM(pfnUnpackAnglesFn(padfPrjParams[5]),
548 6 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[2],
549 6 : padfPrjParams[6], padfPrjParams[7]);
550 6 : break;
551 :
552 0 : case STEREO:
553 0 : SetStereographic(pfnUnpackAnglesFn(padfPrjParams[5]),
554 0 : pfnUnpackAnglesFn(padfPrjParams[4]), 1.0,
555 0 : padfPrjParams[6], padfPrjParams[7]);
556 0 : break;
557 :
558 0 : case LAMAZ:
559 0 : SetLAEA(pfnUnpackAnglesFn(padfPrjParams[5]),
560 0 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
561 0 : padfPrjParams[7]);
562 0 : break;
563 :
564 0 : case AZMEQD:
565 0 : SetAE(pfnUnpackAnglesFn(padfPrjParams[5]),
566 0 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
567 0 : padfPrjParams[7]);
568 0 : break;
569 :
570 0 : case GNOMON:
571 0 : SetGnomonic(pfnUnpackAnglesFn(padfPrjParams[5]),
572 0 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
573 0 : padfPrjParams[7]);
574 0 : break;
575 :
576 0 : case ORTHO:
577 0 : SetOrthographic(pfnUnpackAnglesFn(padfPrjParams[5]),
578 0 : pfnUnpackAnglesFn(padfPrjParams[4]),
579 0 : padfPrjParams[6], padfPrjParams[7]);
580 0 : break;
581 :
582 : // FIXME: GVNSP --- General Vertical Near-Side Perspective skipped.
583 :
584 2 : case SNSOID:
585 2 : SetSinusoidal(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
586 2 : padfPrjParams[7]);
587 2 : break;
588 :
589 0 : case EQRECT:
590 0 : SetEquirectangular2(0.0, pfnUnpackAnglesFn(padfPrjParams[4]),
591 0 : pfnUnpackAnglesFn(padfPrjParams[5]),
592 0 : padfPrjParams[6], padfPrjParams[7]);
593 0 : break;
594 :
595 0 : case MILLER:
596 0 : SetMC(pfnUnpackAnglesFn(padfPrjParams[5]),
597 0 : pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
598 0 : padfPrjParams[7]);
599 0 : break;
600 :
601 0 : case VGRINT:
602 0 : SetVDG(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
603 0 : padfPrjParams[7]);
604 0 : break;
605 :
606 0 : case HOM:
607 0 : if (padfPrjParams[12] != 0.0)
608 : {
609 0 : SetHOM(pfnUnpackAnglesFn(padfPrjParams[5]),
610 0 : pfnUnpackAnglesFn(padfPrjParams[4]),
611 0 : pfnUnpackAnglesFn(padfPrjParams[3]), 0.0,
612 0 : padfPrjParams[2], padfPrjParams[6], padfPrjParams[7]);
613 : }
614 : else
615 : {
616 0 : SetHOM2PNO(pfnUnpackAnglesFn(padfPrjParams[5]),
617 0 : pfnUnpackAnglesFn(padfPrjParams[9]),
618 0 : pfnUnpackAnglesFn(padfPrjParams[8]),
619 0 : pfnUnpackAnglesFn(padfPrjParams[11]),
620 0 : pfnUnpackAnglesFn(padfPrjParams[10]),
621 0 : padfPrjParams[2], padfPrjParams[6],
622 0 : padfPrjParams[7]);
623 : }
624 0 : break;
625 :
626 0 : case ROBIN:
627 0 : SetRobinson(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
628 0 : padfPrjParams[7]);
629 0 : break;
630 :
631 : // FIXME: SOM --- Space Oblique Mercator skipped.
632 : // FIXME: ALASKA --- Alaska Conformal skipped.
633 : // FIXME: GOODE --- Interrupted Goode skipped.
634 :
635 0 : case MOLL:
636 0 : SetMollweide(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
637 0 : padfPrjParams[7]);
638 0 : break;
639 :
640 : // FIXME: IMOLL --- Interrupted Mollweide skipped.
641 : // FIXME: HAMMER --- Hammer skipped.
642 :
643 0 : case WAGIV:
644 0 : SetWagner(4, 0.0, padfPrjParams[6], padfPrjParams[7]);
645 0 : break;
646 :
647 0 : case WAGVII:
648 0 : SetWagner(7, 0.0, padfPrjParams[6], padfPrjParams[7]);
649 0 : break;
650 :
651 : // FIXME: OBEQA --- Oblated Equal Area skipped.
652 : // FIXME: ISINUS1 --- Integerized Sinusoidal Grid (the same as 99).
653 : // FIXME: CEA --- Cylindrical Equal Area skipped (Grid corners set
654 : // in meters for EASE grid).
655 : // FIXME: BCEA --- Cylindrical Equal Area skipped (Grid corners set
656 : // in DMS degs for EASE grid).
657 : // FIXME: ISINUS --- Integrized Sinusoidal skipped.
658 :
659 2 : default:
660 2 : CPLDebug("OSR_USGS", "Unsupported projection: %ld", iProjSys);
661 2 : SetLocalCS(
662 4 : CPLString().Printf("GCTP projection number %ld", iProjSys));
663 2 : break;
664 : }
665 :
666 : /* -------------------------------------------------------------------- */
667 : /* Try to translate the datum/spheroid. */
668 : /* -------------------------------------------------------------------- */
669 :
670 23 : if (!IsLocal())
671 : {
672 21 : char *pszName = nullptr;
673 21 : double dfSemiMajor = 0.0;
674 21 : double dfInvFlattening = 0.0;
675 :
676 21 : if (iDatum < 0) // Use specified ellipsoid parameters.
677 : {
678 2 : if (padfPrjParams[0] > 0.0)
679 : {
680 2 : if (padfPrjParams[1] > 1.0)
681 : {
682 0 : dfInvFlattening = OSRCalcInvFlattening(padfPrjParams[0],
683 0 : padfPrjParams[1]);
684 : }
685 2 : else if (padfPrjParams[1] > 0.0)
686 : {
687 0 : dfInvFlattening =
688 0 : 1.0 / (1.0 - sqrt(1.0 - padfPrjParams[1]));
689 : }
690 : else
691 : {
692 2 : dfInvFlattening = 0.0;
693 : }
694 :
695 2 : SetGeogCS("Unknown datum based upon the custom spheroid",
696 : "Not specified (based on custom spheroid)",
697 : "Custom spheroid", padfPrjParams[0], dfInvFlattening,
698 : nullptr, 0, nullptr, 0);
699 : }
700 0 : else if (padfPrjParams[1] > 0.0) // Clarke 1866.
701 : {
702 0 : if (OSRGetEllipsoidInfo(7008, &pszName, &dfSemiMajor,
703 0 : &dfInvFlattening) == OGRERR_NONE)
704 : {
705 0 : SetGeogCS(
706 0 : CPLString().Printf(
707 : "Unknown datum based upon the %s ellipsoid",
708 0 : pszName),
709 0 : CPLString().Printf(
710 0 : "Not specified (based on %s spheroid)", pszName),
711 : pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
712 : nullptr, 0.0);
713 0 : SetAuthority("SPHEROID", "EPSG", 7008);
714 : }
715 : }
716 : else // Sphere, rad 6370997 m
717 : {
718 0 : if (OSRGetEllipsoidInfo(7047, &pszName, &dfSemiMajor,
719 0 : &dfInvFlattening) == OGRERR_NONE)
720 : {
721 0 : SetGeogCS(
722 0 : CPLString().Printf(
723 : "Unknown datum based upon the %s ellipsoid",
724 0 : pszName),
725 0 : CPLString().Printf(
726 0 : "Not specified (based on %s spheroid)", pszName),
727 : pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
728 : nullptr, 0.0);
729 0 : SetAuthority("SPHEROID", "EPSG", 7047);
730 : }
731 : }
732 : }
733 19 : else if (iDatum < NUMBER_OF_USGS_ELLIPSOIDS && aoEllipsUSGS[iDatum])
734 : {
735 19 : if (OSRGetEllipsoidInfo(aoEllipsUSGS[iDatum], &pszName,
736 : &dfSemiMajor,
737 19 : &dfInvFlattening) == OGRERR_NONE)
738 : {
739 19 : SetGeogCS(
740 38 : CPLString().Printf(
741 19 : "Unknown datum based upon the %s ellipsoid", pszName),
742 38 : CPLString().Printf("Not specified (based on %s spheroid)",
743 19 : pszName),
744 : pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
745 : nullptr, 0.0);
746 19 : SetAuthority("SPHEROID", "EPSG", aoEllipsUSGS[iDatum]);
747 : }
748 : else
749 : {
750 0 : CPLError(CE_Warning, CPLE_AppDefined,
751 : "Failed to lookup datum code %d. "
752 : "Falling back to use WGS84.",
753 : static_cast<int>(iDatum));
754 0 : SetWellKnownGeogCS("WGS84");
755 : }
756 : }
757 : else
758 : {
759 0 : CPLError(CE_Warning, CPLE_AppDefined,
760 : "Wrong datum code %d. Supported datums 0--%d only. "
761 : "Setting WGS84 as a fallback.",
762 : static_cast<int>(iDatum), NUMBER_OF_USGS_ELLIPSOIDS);
763 0 : SetWellKnownGeogCS("WGS84");
764 : }
765 :
766 21 : CPLFree(pszName);
767 : }
768 :
769 : /* -------------------------------------------------------------------- */
770 : /* Grid units translation */
771 : /* -------------------------------------------------------------------- */
772 23 : if (IsLocal() || IsProjected())
773 21 : SetLinearUnits(SRS_UL_METER, 1.0);
774 :
775 23 : return OGRERR_NONE;
776 : }
777 :
778 : /************************************************************************/
779 : /* OSRExportToUSGS() */
780 : /************************************************************************/
781 : /**
782 : * \brief Export coordinate system in USGS GCTP projection definition.
783 : *
784 : * This function is the same as OGRSpatialReference::exportToUSGS().
785 : */
786 :
787 1 : OGRErr OSRExportToUSGS(OGRSpatialReferenceH hSRS, long *piProjSys, long *piZone,
788 : double **ppadfPrjParams, long *piDatum)
789 :
790 : {
791 1 : VALIDATE_POINTER1(hSRS, "OSRExportToUSGS", OGRERR_FAILURE);
792 :
793 1 : *ppadfPrjParams = nullptr;
794 :
795 1 : return OGRSpatialReference::FromHandle(hSRS)->exportToUSGS(
796 1 : piProjSys, piZone, ppadfPrjParams, piDatum);
797 : }
798 :
799 : /************************************************************************/
800 : /* exportToUSGS() */
801 : /************************************************************************/
802 :
803 : /**
804 : * \brief Export coordinate system in USGS GCTP projection definition.
805 : *
806 : * This method is the equivalent of the C function OSRExportToUSGS().
807 : *
808 : * @param piProjSys Pointer to variable, where the projection system code will
809 : * be returned.
810 : *
811 : * @param piZone Pointer to variable, where the zone for UTM and State Plane
812 : * projection systems will be returned.
813 : *
814 : * @param ppadfPrjParams Pointer to which dynamically allocated array of
815 : * 15 projection parameters will be assigned. See importFromUSGS() for
816 : * the list of parameters. Caller responsible to free this array.
817 : *
818 : * @param piDatum Pointer to variable, where the datum code will
819 : * be returned.
820 : *
821 : * @return OGRERR_NONE on success or an error code on failure.
822 : */
823 :
824 1 : OGRErr OGRSpatialReference::exportToUSGS(long *piProjSys, long *piZone,
825 : double **ppadfPrjParams,
826 : long *piDatum) const
827 :
828 : {
829 1 : const char *pszProjection = GetAttrValue("PROJECTION");
830 :
831 : /* -------------------------------------------------------------------- */
832 : /* Fill all projection parameters with zero. */
833 : /* -------------------------------------------------------------------- */
834 1 : *ppadfPrjParams = static_cast<double *>(CPLMalloc(15 * sizeof(double)));
835 16 : for (int i = 0; i < 15; i++)
836 15 : (*ppadfPrjParams)[i] = 0.0;
837 :
838 1 : *piZone = 0L;
839 :
840 : /* ==================================================================== */
841 : /* Handle the projection definition. */
842 : /* ==================================================================== */
843 1 : if (IsLocal())
844 0 : *piProjSys = GEO;
845 :
846 1 : else if (pszProjection == nullptr)
847 : {
848 : #ifdef DEBUG
849 0 : CPLDebug("OSR_USGS",
850 : "Empty projection definition, considered as Geographic");
851 : #endif
852 0 : *piProjSys = GEO;
853 : }
854 :
855 1 : else if (EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA))
856 : {
857 0 : *piProjSys = ALBERS;
858 0 : (*ppadfPrjParams)[2] =
859 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
860 0 : (*ppadfPrjParams)[3] =
861 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
862 0 : (*ppadfPrjParams)[4] =
863 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
864 0 : (*ppadfPrjParams)[5] =
865 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
866 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
867 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
868 : }
869 :
870 1 : else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
871 : {
872 1 : *piProjSys = LAMCC;
873 2 : (*ppadfPrjParams)[2] =
874 1 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
875 2 : (*ppadfPrjParams)[3] =
876 1 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
877 2 : (*ppadfPrjParams)[4] =
878 1 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
879 2 : (*ppadfPrjParams)[5] =
880 1 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
881 1 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
882 1 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
883 : }
884 :
885 0 : else if (EQUAL(pszProjection, SRS_PT_MERCATOR_1SP))
886 : {
887 0 : *piProjSys = MERCAT;
888 0 : (*ppadfPrjParams)[4] =
889 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
890 0 : (*ppadfPrjParams)[5] =
891 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
892 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
893 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
894 : }
895 :
896 0 : else if (EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC))
897 : {
898 0 : *piProjSys = PS;
899 0 : (*ppadfPrjParams)[4] =
900 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
901 0 : (*ppadfPrjParams)[5] =
902 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
903 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
904 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
905 : }
906 :
907 0 : else if (EQUAL(pszProjection, SRS_PT_POLYCONIC))
908 : {
909 0 : *piProjSys = POLYC;
910 0 : (*ppadfPrjParams)[4] =
911 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
912 0 : (*ppadfPrjParams)[5] =
913 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
914 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
915 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
916 : }
917 :
918 0 : else if (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC))
919 : {
920 0 : *piProjSys = EQUIDC;
921 0 : (*ppadfPrjParams)[2] =
922 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
923 0 : (*ppadfPrjParams)[3] =
924 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
925 0 : (*ppadfPrjParams)[4] =
926 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
927 0 : (*ppadfPrjParams)[5] =
928 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
929 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
930 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
931 0 : (*ppadfPrjParams)[8] = 1.0;
932 : }
933 :
934 0 : else if (EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR))
935 : {
936 : int bNorth;
937 :
938 0 : *piZone = GetUTMZone(&bNorth);
939 :
940 0 : if (*piZone != 0)
941 : {
942 0 : *piProjSys = UTM;
943 0 : if (!bNorth)
944 0 : *piZone = -*piZone;
945 : }
946 : else
947 : {
948 0 : *piProjSys = TM;
949 0 : (*ppadfPrjParams)[2] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
950 0 : (*ppadfPrjParams)[4] = CPLDecToPackedDMS(
951 : GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
952 0 : (*ppadfPrjParams)[5] = CPLDecToPackedDMS(
953 : GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
954 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
955 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
956 : }
957 : }
958 :
959 0 : else if (EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC))
960 : {
961 0 : *piProjSys = STEREO;
962 0 : (*ppadfPrjParams)[4] =
963 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
964 0 : (*ppadfPrjParams)[5] =
965 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
966 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
967 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
968 : }
969 :
970 0 : else if (EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
971 : {
972 0 : *piProjSys = LAMAZ;
973 0 : (*ppadfPrjParams)[4] =
974 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
975 0 : (*ppadfPrjParams)[5] =
976 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
977 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
978 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
979 : }
980 :
981 0 : else if (EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT))
982 : {
983 0 : *piProjSys = AZMEQD;
984 0 : (*ppadfPrjParams)[4] =
985 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
986 0 : (*ppadfPrjParams)[5] =
987 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
988 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
989 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
990 : }
991 :
992 0 : else if (EQUAL(pszProjection, SRS_PT_GNOMONIC))
993 : {
994 0 : *piProjSys = GNOMON;
995 0 : (*ppadfPrjParams)[4] =
996 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
997 0 : (*ppadfPrjParams)[5] =
998 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
999 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1000 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1001 : }
1002 :
1003 0 : else if (EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC))
1004 : {
1005 0 : *piProjSys = ORTHO;
1006 0 : (*ppadfPrjParams)[4] =
1007 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
1008 0 : (*ppadfPrjParams)[5] =
1009 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
1010 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1011 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1012 : }
1013 :
1014 0 : else if (EQUAL(pszProjection, SRS_PT_SINUSOIDAL))
1015 : {
1016 0 : *piProjSys = SNSOID;
1017 0 : (*ppadfPrjParams)[4] =
1018 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1019 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1020 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1021 : }
1022 :
1023 0 : else if (EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR))
1024 : {
1025 0 : *piProjSys = EQRECT;
1026 0 : (*ppadfPrjParams)[4] =
1027 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
1028 0 : (*ppadfPrjParams)[5] =
1029 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
1030 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1031 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1032 : }
1033 :
1034 0 : else if (EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL))
1035 : {
1036 0 : *piProjSys = MILLER;
1037 0 : (*ppadfPrjParams)[4] =
1038 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1039 0 : (*ppadfPrjParams)[5] =
1040 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
1041 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1042 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1043 : }
1044 :
1045 0 : else if (EQUAL(pszProjection, SRS_PT_VANDERGRINTEN))
1046 : {
1047 0 : *piProjSys = VGRINT;
1048 0 : (*ppadfPrjParams)[4] =
1049 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1050 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1051 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1052 : }
1053 :
1054 0 : else if (EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR))
1055 : {
1056 0 : *piProjSys = HOM;
1057 0 : (*ppadfPrjParams)[2] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
1058 0 : (*ppadfPrjParams)[3] =
1059 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_AZIMUTH, 0.0));
1060 0 : (*ppadfPrjParams)[4] =
1061 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1062 0 : (*ppadfPrjParams)[5] =
1063 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
1064 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1065 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1066 0 : (*ppadfPrjParams)[12] = 1.0;
1067 : }
1068 :
1069 0 : else if (EQUAL(pszProjection,
1070 : SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN))
1071 : {
1072 0 : *piProjSys = HOM;
1073 0 : (*ppadfPrjParams)[2] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
1074 0 : (*ppadfPrjParams)[5] =
1075 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
1076 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1077 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1078 0 : (*ppadfPrjParams)[8] = CPLDecToPackedDMS(
1079 : GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0));
1080 0 : (*ppadfPrjParams)[9] =
1081 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0));
1082 0 : (*ppadfPrjParams)[10] = CPLDecToPackedDMS(
1083 : GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 0.0));
1084 0 : (*ppadfPrjParams)[11] =
1085 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2, 0.0));
1086 0 : (*ppadfPrjParams)[12] = 0.0;
1087 : }
1088 :
1089 0 : else if (EQUAL(pszProjection, SRS_PT_ROBINSON))
1090 : {
1091 0 : *piProjSys = ROBIN;
1092 0 : (*ppadfPrjParams)[4] =
1093 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1094 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1095 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1096 : }
1097 :
1098 0 : else if (EQUAL(pszProjection, SRS_PT_MOLLWEIDE))
1099 : {
1100 0 : *piProjSys = MOLL;
1101 0 : (*ppadfPrjParams)[4] =
1102 0 : CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
1103 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1104 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1105 : }
1106 :
1107 0 : else if (EQUAL(pszProjection, SRS_PT_WAGNER_IV))
1108 : {
1109 0 : *piProjSys = WAGIV;
1110 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1111 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1112 : }
1113 :
1114 0 : else if (EQUAL(pszProjection, SRS_PT_WAGNER_VII))
1115 : {
1116 0 : *piProjSys = WAGVII;
1117 0 : (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1118 0 : (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1119 : }
1120 : // Projection unsupported by GCTP.
1121 : else
1122 : {
1123 0 : CPLDebug("OSR_USGS",
1124 : "Projection \"%s\" unsupported by USGS GCTP. "
1125 : "Geographic system will be used.",
1126 : pszProjection);
1127 0 : *piProjSys = GEO;
1128 : }
1129 :
1130 : /* -------------------------------------------------------------------- */
1131 : /* Translate the datum. */
1132 : /* -------------------------------------------------------------------- */
1133 1 : const char *pszDatum = GetAttrValue("DATUM");
1134 :
1135 1 : if (pszDatum)
1136 : {
1137 1 : if (EQUAL(pszDatum, SRS_DN_NAD27))
1138 : {
1139 1 : *piDatum = CLARKE1866;
1140 : }
1141 0 : else if (EQUAL(pszDatum, SRS_DN_NAD83))
1142 : {
1143 0 : *piDatum = GRS1980;
1144 : }
1145 0 : else if (EQUAL(pszDatum, SRS_DN_WGS84))
1146 : {
1147 0 : *piDatum = WGS84;
1148 : }
1149 : // If not found well known datum, translate ellipsoid.
1150 : else
1151 : {
1152 0 : const double dfSemiMajor = GetSemiMajor();
1153 0 : const double dfInvFlattening = GetInvFlattening();
1154 :
1155 : #ifdef DEBUG
1156 0 : CPLDebug("OSR_USGS",
1157 : "Datum \"%s\" unsupported by USGS GCTP. "
1158 : "Try to translate ellipsoid definition.",
1159 : pszDatum);
1160 : #endif
1161 :
1162 0 : int i = 0; // Used after for.
1163 0 : for (; i < NUMBER_OF_USGS_ELLIPSOIDS; i++)
1164 : {
1165 0 : double dfSM = 0.0;
1166 0 : double dfIF = 0.0;
1167 :
1168 0 : if (OSRGetEllipsoidInfo(aoEllipsUSGS[i], nullptr, &dfSM,
1169 0 : &dfIF) == OGRERR_NONE &&
1170 0 : CPLIsEqual(dfSemiMajor, dfSM) &&
1171 0 : CPLIsEqual(dfInvFlattening, dfIF))
1172 : {
1173 0 : *piDatum = i;
1174 0 : break;
1175 : }
1176 : }
1177 :
1178 0 : if (i == NUMBER_OF_USGS_ELLIPSOIDS) // Didn't found matches; set
1179 : { // custom ellipsoid parameters.
1180 : #ifdef DEBUG
1181 0 : CPLDebug("OSR_USGS",
1182 : "Ellipsoid \"%s\" unsupported by USGS GCTP. "
1183 : "Custom ellipsoid definition will be used.",
1184 : pszDatum);
1185 : #endif
1186 0 : *piDatum = -1;
1187 0 : (*ppadfPrjParams)[0] = dfSemiMajor;
1188 0 : if (std::abs(dfInvFlattening) < 0.000000000001)
1189 : {
1190 0 : (*ppadfPrjParams)[1] = dfSemiMajor;
1191 : }
1192 : else
1193 : {
1194 0 : (*ppadfPrjParams)[1] =
1195 0 : dfSemiMajor * (1.0 - 1.0 / dfInvFlattening);
1196 : }
1197 : }
1198 : }
1199 : }
1200 : else
1201 : {
1202 0 : *piDatum = -1;
1203 : }
1204 :
1205 1 : return OGRERR_NONE;
1206 : }
|