LCOV - code coverage report
Current view: top level - ogr - ogr_srs_usgs.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 108 453 23.8 %
Date: 2024-05-03 15:49:35 Functions: 5 6 83.3 %

          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             : }

Generated by: LCOV version 1.14