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