LCOV - code coverage report
Current view: top level - ogr - ogr_srs_panorama.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 177 414 42.8 %
Date: 2024-05-04 12:52:34 Functions: 6 9 66.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  OGRSpatialReference translation to/from "Panorama" GIS
       5             :  *           georeferencing information (also know as GIS "Integration").
       6             :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2005, Andrey Kiselev <dron@ak4719.spb.edu>
      10             :  * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
      11             :  * Copyright (c) 2020-2022, Dmitry Baryshnikov <polimax@mail.ru>
      12             :  *
      13             :  * Permission is hereby granted, free of charge, to any person obtaining a
      14             :  * copy of this software and associated documentation files (the "Software"),
      15             :  * to deal in the Software without restriction, including without limitation
      16             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17             :  * and/or sell copies of the Software, and to permit persons to whom the
      18             :  * Software is furnished to do so, subject to the following conditions:
      19             :  *
      20             :  * The above copyright notice and this permission notice shall be included
      21             :  * in all copies or substantial portions of the Software.
      22             :  *
      23             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29             :  * DEALINGS IN THE SOFTWARE.
      30             :  ****************************************************************************/
      31             : 
      32             : #include "ogr_spatialref.h"
      33             : #include "cpl_conv.h"
      34             : #include "cpl_csv.h"
      35             : #include "ogr_p.h"
      36             : 
      37             : #include <cmath>
      38             : 
      39             : constexpr double TO_DEGREES = 180.0 / M_PI;
      40             : constexpr double TO_RADIANS = M_PI / 180.0;
      41             : constexpr int NONE_VAL = -1L;
      42             : 
      43             : // This function computes zone number from the central meridian parameter.
      44          13 : static int GetZoneNumberGK(double dfCenterLong)
      45             : {
      46          13 :     return static_cast<int>((dfCenterLong + 363.0) / 6.0 + 0.5) % 60;
      47             : }
      48             : 
      49          67 : static int GetZoneNumberUTM(double dfCenterLong)
      50             : {
      51          67 :     return static_cast<int>((dfCenterLong + 186.0) / 6.0);
      52             : }
      53             : 
      54         236 : static bool IsNone(long val)
      55             : {
      56         236 :     return val == -1L || val == 0L || val == 255L;
      57             : }
      58             : 
      59             : /************************************************************************/
      60             : /*  "Panorama" projection codes.                                        */
      61             : /************************************************************************/
      62             : 
      63             : constexpr long PAN_PROJ_TM = 1L;       // Gauss-Kruger (Transverse Mercator)
      64             : constexpr long PAN_PROJ_LCC = 2L;      // Lambert Conformal Conic 2SP
      65             : constexpr long PAN_PROJ_STEREO = 5L;   // Stereographic
      66             : constexpr long PAN_PROJ_AE = 6L;       // Azimuthal Equidistant (Postel)
      67             : constexpr long PAN_PROJ_MERCAT = 8L;   // Mercator
      68             : constexpr long PAN_PROJ_POLYC = 10L;   // Polyconic
      69             : constexpr long PAN_PROJ_PS = 13L;      // Polar Stereographic
      70             : constexpr long PAN_PROJ_GNOMON = 15L;  // Gnomonic
      71             : constexpr long PAN_PROJ_UTM = 17L;     // Universal Transverse Mercator (UTM)
      72             : constexpr long PAN_PROJ_WAG1 = 18L;    // Wagner I (Kavraisky VI)
      73             : constexpr long PAN_PROJ_MOLL = 19L;    // Mollweide
      74             : constexpr long PAN_PROJ_EC = 20L;      // Equidistant Conic
      75             : constexpr long PAN_PROJ_LAEA = 24L;    // Lambert Azimuthal Equal Area
      76             : constexpr long PAN_PROJ_EQC = 27L;     // Equirectangular
      77             : constexpr long PAN_PROJ_CEA = 28L;     // Cylindrical Equal Area (Lambert)
      78             : constexpr long PAN_PROJ_IMWP = 29L;  // International Map of the World Polyconic
      79             : constexpr long PAN_PROJ_SPHERE = 33L;  // Sphere
      80             : constexpr long PAN_PROJ_MILLER = 34L;  // Miller
      81             : constexpr long PAN_PROJ_PSEUDO_MERCATOR =
      82             :     35L;  // Popular Visualisation Pseudo Mercator
      83             : /************************************************************************/
      84             : /*  "Panorama" datum codes.                                             */
      85             : /************************************************************************/
      86             : 
      87             : constexpr long PAN_DATUM_PULKOVO42 = 1L;    // Pulkovo 1942
      88             : constexpr long PAN_DATUM_UTM = 2L;          // Universal Transverse Mercator
      89             : constexpr long PAN_DATUM_RECTANGULAR = 6L;  // WGS84
      90             : // constexpr long PAN_DATUM_WGS84 = 8L;        // WGS84
      91             : constexpr long PAN_DATUM_PULKOVO95 = 9L;  // Pulokovo 1995
      92             : constexpr long PAN_DATUM_GSK2011 = 10L;   // GSK 2011
      93             : 
      94             : /************************************************************************/
      95             : /*  "Panorama" ellipsoid codes.                                         */
      96             : /************************************************************************/
      97             : 
      98             : constexpr long PAN_ELLIPSOID_KRASSOVSKY = 1L;  // Krassovsky, 1940
      99             : // constexpr long PAN_ELLIPSOID_WGS72       = 2L;  // WGS, 1972
     100             : // constexpr long PAN_ELLIPSOID_INT1924     = 3L;  // International, 1924
     101             : // (Hayford, 1909) constexpr long PAN_ELLIPSOID_CLARCKE1880 = 4L;  // Clarke,
     102             : // 1880 constexpr long PAN_ELLIPSOID_CLARCKE1866 = 5L;  // Clarke, 1866
     103             : // (NAD1927) constexpr long PAN_ELLIPSOID_EVEREST1830 = 6L;  // Everest, 1830
     104             : // constexpr long PAN_ELLIPSOID_BESSEL1841  = 7L;  // Bessel, 1841
     105             : // constexpr long PAN_ELLIPSOID_AIRY1830    = 8L;  // Airy, 1830
     106             : constexpr long PAN_ELLIPSOID_WGS84 = 9L;          // WGS, 1984 (GPS)
     107             : constexpr long PAN_ELLIPSOID_WGS84_SPHERE = 45L;  // WGS, 1984 (Sphere)
     108             : constexpr long PAN_ELLIPSOID_GSK2011 = 46L;       // GSK 2011
     109             : constexpr long PAN_ELLIPSOID_PZ90 = 47L;          // PZ-90
     110             : 
     111             : /************************************************************************/
     112             : /*  Correspondence between "Panorama" datum and EPSG GeogCS codes.             */
     113             : /************************************************************************/
     114             : 
     115             : constexpr int aoDatums[] = {
     116             :     0,     // 0.  Undefined (also may be 255 or -1)
     117             :     4284,  // 1.  Pulkovo, 1942
     118             :     4326,  // 2.  WGS, 1984,
     119             :     4277,  // 3.  OSGB 1936 (British National Grid)
     120             :     0,     // 4.  Local spatial reference
     121             :     0,     // 5.  SK 63
     122             :     0,     // 6.  Rectangular conditional spatial reference
     123             :     0,     // 7.  Geodesic coordinates in radians
     124             :     0,     // 8.  Geodesic coordinates in degrees
     125             :     4200,  // 9.  Pulkovo, 1995
     126             :     7683   // 10. GSK 2011
     127             : };
     128             : 
     129             : constexpr int NUMBER_OF_DATUMS = static_cast<int>(CPL_ARRAYSIZE(aoDatums));
     130             : 
     131             : /************************************************************************/
     132             : /*  Correspondence between "Panorama" and EPSG ellipsoid codes.         */
     133             : /************************************************************************/
     134             : 
     135             : constexpr int aoPanoramaEllips[] = {
     136             :     0,     // 0. Undefined
     137             :     7024,  // 1. Krassovsky, 1940
     138             :     7043,  // 2. WGS, 1972
     139             :     7022,  // 3. International, 1924 (Hayford, 1909)
     140             :     7034,  // 4. Clarke, 1880
     141             :     7008,  // 5. Clarke, 1866 (NAD1927)
     142             :     7015,  // 6. Everest, 1830
     143             :     7004,  // 7. Bessel, 1841
     144             :     7001,  // 8. Airy, 1830
     145             :     7030,  // 9. WGS, 1984 (GPS)
     146             :     7054,  // 10. PZ-90.02 // http://epsg.io/7054-ellipsoid
     147             :     7019,  // 11. GRS, 1980 (NAD1983)
     148             :     0,     // 12. IERS 1996 (6378136.49 298.25645)
     149             :     7022,  // 13. International, 1924 (Hayford, 1909) XXX?
     150             :     7036,  // 14. South American, 1969
     151             :     7021,  // 15. Indonesian, 1974
     152             :     7020,  // 16. Helmert 1906
     153             :     0,     // 17. FIXME: Fisher 1960 - https://epsg.io/37002
     154             :     0,     // 18. FIXME: Fisher 1968 - https://epsg.io/37003
     155             :     0,     // 19. FIXME: Haff 1960 - (6378270.0 297.0)
     156             :     7042,  // 20. Everest, 1830
     157             :     7003,  // 21. Australian National, 1965
     158             :     1024,  // 22. CGCS2000 http://epsg.io/1024-ellipsoid
     159             :     7002,  // 23. Airy Modified 1849 http://epsg.io/7002-ellipsoid
     160             :     7005,  // 24. Bessel Modified
     161             :     7046,  // 25. Bessel Namibia
     162             :     7046,  // 26. Bessel Namibia (GLM)
     163             :     7013,  // 27. Clarke 1880 (Arc)
     164             :     7014,  // 28. Clarke 1880 (SGA 1922)
     165             :     7042,  // 29. Everest (1830 Definition)
     166             :     7018,  // 30. Everest 1830 Modified
     167             :     7056,  // 31. Everest 1830 (RSO 1969)
     168             :     7045,  // 32. Everest 1830 (1975 Definition)
     169             :     7025,  // 33. NWL 9D
     170             :     7027,  // 34. Plessis 1817
     171             :     7028,  // 35. Struve 1860
     172             :     7029,  // 36. War Office
     173             :     7031,  // 37. GEM 10C
     174             :     7032,  // 38. OSU86F
     175             :     7033,  // 39. OSU91A
     176             :     7036,  // 40. GRS 1967
     177             :     7041,  // 41. Average Terrestrial System 1977
     178             :     7049,  // 42. IAG 1975
     179             :     7050,  // 43. GRS 1967 Modified
     180             :     7051,  // 44. Danish 1876
     181             :     7048,  // 45. GRS 1980 Authalic Sphere
     182             :     1025,  // 46. GSK 2011
     183             :     7054   // 47. PZ-90
     184             : };
     185             : 
     186             : constexpr int NUMBER_OF_PANORAM_ELLIPSOIDS =
     187             :     static_cast<int>(CPL_ARRAYSIZE(aoPanoramaEllips));
     188             : 
     189             : /************************************************************************/
     190             : /*  Correspondence between "Panorama" and EPSG vertical CS.             */
     191             : /************************************************************************/
     192             : 
     193             : constexpr int aoVCS[] = {
     194             :     0,     //0, 255, -1 - Undefined
     195             :     8357,  //1 Baltic 1957 height
     196             :     5711,  //2 AHD height
     197             :     5195,  //3 Trieste height
     198             :     5710,  //4 Ostend height - zero normal
     199             :     5710,  //5 Ostend height - null point de shosse
     200             :     0,     //6 Channel height (GB)
     201             :     5732,  //7 Belfast height
     202             :     5731,  //8 Malin Head height
     203             :     0,     //9 Dublib bay height
     204             :     5716,  //10 Piraeus height
     205             :     5733,  //11 DNN height
     206             :     8089,  //12 ISH2004 height
     207             :     5782,  //13 Alicante height
     208             :     0,     //14 Canary islands
     209             :     5214,  //15 Genoa height
     210             :     5709,  //16 NAP height
     211             :     5776,  //17 NN54 height
     212             :     0,     //18 North Norway
     213             :     5780,  //19 Cascais height
     214             :     5717,  //20 N60 height
     215             :     5613,  //21 RH2000 height
     216             :     0,     //22 France, Marseilles height
     217             :     5775,  //23 Antalya height
     218             :     5702,  //24 NGVD29 height (ftUS)
     219             :     5705,  //25 Baltic 1977 height
     220             :     0,     //26 Pacific Ocean (Ohotsk sea level)
     221             :     5714   //27 MSL height
     222             : };
     223             : 
     224             : constexpr int NUMBER_OF_VERTICALCS = static_cast<int>(CPL_ARRAYSIZE(aoVCS));
     225             : 
     226             : /************************************************************************/
     227             : /*                        OSRImportFromPanorama()                       */
     228             : /************************************************************************/
     229             : 
     230             : /** Import coordinate system from "Panorama" GIS projection definition.
     231             :  *
     232             :  * See OGRSpatialReference::importFromPanorama()
     233             :  */
     234             : 
     235           0 : OGRErr OSRImportFromPanorama(OGRSpatialReferenceH hSRS, long iProjSys,
     236             :                              long iDatum, long iEllips, double *padfPrjParams)
     237             : 
     238             : {
     239           0 :     VALIDATE_POINTER1(hSRS, "OSRImportFromPanorama", OGRERR_FAILURE);
     240             : 
     241           0 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromPanorama(
     242           0 :         iProjSys, iDatum, iEllips, padfPrjParams);
     243             : }
     244             : 
     245             : /************************************************************************/
     246             : /*                          importFromPanorama()                        */
     247             : /************************************************************************/
     248             : 
     249             : /**
     250             :  * Import coordinate system from "Panorama" GIS projection definition.
     251             :  *
     252             :  * This method will import projection definition in style, used by
     253             :  * "Panorama" GIS.
     254             :  *
     255             :  * This function is the equivalent of the C function OSRImportFromPanorama().
     256             :  *
     257             :  * @param iProjSys Input projection system code, used in GIS "Panorama".
     258             :  *
     259             :  * Supported Projections are:
     260             :  * <ul>
     261             :  * <li>1:  Gauss-Kruger (Transverse Mercator)</li>
     262             :  * <li>2:  Lambert Conformal Conic 2SP</li>
     263             :  * <li>5:  Stereographic</li>
     264             :  * <li>6:  Azimuthal Equidistant (Postel)</li>
     265             :  * <li>8:  Mercator</li>
     266             :  * <li>10: Polyconic</li>
     267             :  * <li>13: Polar Stereographic</li>
     268             :  * <li>15: Gnomonic</li>
     269             :  * <li>17: Universal Transverse Mercator (UTM)</li>
     270             :  * <li>18: Wagner I (Kavraisky VI)</li>
     271             :  * <li>19: Mollweide</li>
     272             :  * <li>20: Equidistant Conic</li>
     273             :  * <li>24: Lambert Azimuthal Equal Area</li>
     274             :  * <li>27: Equirectangular</li>
     275             :  * <li>28: Cylindrical Equal Area (Lambert)</li>
     276             :  * <li>29: International Map of the World Polyconic</li>
     277             :  * </ul>
     278             :  *
     279             :  * @param iDatum Input coordinate system.
     280             :  *
     281             :  * Supported Datums are:
     282             :  * <ul>
     283             :  * <li>1:  Pulkovo, 1942</li>
     284             :  * <li>2:  WGS, 1984</li>
     285             :  * <li>3:  OSGB 1936 (British National Grid)</li>
     286             :  * <li>9:  Pulkovo, 1995</li>
     287             :  * <li>10: GSK 2011</li>
     288             :  * </ul>
     289             :  *
     290             :  * @param iEllips Input spheroid.
     291             :  *
     292             :  * Supported Spheroids are:
     293             :  * <ul>
     294             :  * <li>1:  Krassovsky, 1940</li>
     295             :  * <li>2:  WGS, 1972</li>
     296             :  * <li>3:  International, 1924 (Hayford, 1909)</li>
     297             :  * <li>4:  Clarke, 1880</li>
     298             :  * <li>5:  Clarke, 1866 (NAD1927)</li>
     299             :  * <li>6:  Everest, 1830</li>
     300             :  * <li>7:  Bessel, 1841</li>
     301             :  * <li>8:  Airy, 1830</li>
     302             :  * <li>9:  WGS, 1984 (GPS)</li>
     303             :  * <li>10: PZ-90.02</li>
     304             :  * <li>11: GRS, 1980 (NAD1983)</li>
     305             :  * <li>12: IERS 1996 (6378136.49 298.25645)</li>
     306             :  * <li>13: International, 1924 (Hayford, 1909)</li>
     307             :  * <li>14: South American, 1969</li>
     308             :  * <li>15: Indonesian, 1974</li>
     309             :  * <li>16: Helmert 1906</li>
     310             :  * <li>17: Fisher 1960</li>
     311             :  * <li>18: Fisher 1968</li>
     312             :  * <li>19. Haff 1960 - (6378270.0 297.0)</li>
     313             :  * <li>20: Everest, 1830</li>
     314             :  * <li>21: Australian National, 1965</li>
     315             :  * <li>22: CGCS2000</li>
     316             :  * <li>23: Airy Modified 1849</li>
     317             :  * <li>24: Bessel Modified</li>
     318             :  * <li>25: Bessel Namibia</li>
     319             :  * <li>26: Bessel Namibia (GLM)</li>
     320             :  * <li>27: Clarke 1880 (Arc)</li>
     321             :  * <li>28: Clarke 1880 (SGA 1922)</li>
     322             :  * <li>29: Everest (1830 Definition)</li>
     323             :  * <li>30: Everest 1830 Modified</li>
     324             :  * <li>31: Everest 1830 (RSO 1969)</li>
     325             :  * <li>32: Everest 1830 (1975 Definition)</li>
     326             :  * <li>33: NWL 9D</li>
     327             :  * <li>34: Plessis 1817</li>
     328             :  * <li>35: Struve 1860</li>
     329             :  * <li>36: War Office</li>
     330             :  * <li>37: GEM 10C</li>
     331             :  * <li>38: OSU86F</li>
     332             :  * <li>39: OSU91A</li>
     333             :  * <li>40: GRS 1967</li>
     334             :  * <li>41: Average Terrestrial System 1977</li>
     335             :  * <li>42: IAG 1975</li>
     336             :  * <li>43: GRS 1967 Modified</li>
     337             :  * <li>44: Danish 1876</li>
     338             :  * <li>45: GRS 1980 Authalic Sphere</li>
     339             :  * <li>46: GSK 2011</li>
     340             :  * <li>47: PZ-90</li>
     341             :  * </ul>
     342             :  *
     343             :  * @param padfPrjParams Array of 8 coordinate system parameters:
     344             :  *
     345             :  * <ul>
     346             :  * <li>[0]  Latitude of the first standard parallel (radians)</li>
     347             :  * <li>[1]  Latitude of the second standard parallel (radians)</li>
     348             :  * <li>[2]  Latitude of center of projection (radians)</li>
     349             :  * <li>[3]  Longitude of center of projection (radians)</li>
     350             :  * <li>[4]  Scaling factor</li>
     351             :  * <li>[5]  False Easting</li>
     352             :  * <li>[6]  False Northing</li>
     353             :  * <li>[7]  Zone number</li>
     354             :  * </ul>
     355             :  *
     356             :  * @param bNorth If northern hemisphere true, else false. Defaults to true.
     357             :  *
     358             :  * Particular projection uses different parameters, unused ones may be set to
     359             :  * zero. If NULL supplied instead of array pointer default values will be used
     360             :  * (i.e., zeroes).
     361             :  *
     362             :  * @return OGRERR_NONE on success or an error code in case of failure.
     363             :  */
     364             : 
     365         101 : OGRErr OGRSpatialReference::importFromPanorama(long iProjSys, long iDatum,
     366             :                                                long iEllips,
     367             :                                                double *padfPrjParams,
     368             :                                                bool bNorth)
     369             : 
     370             : {
     371         101 :     Clear();
     372             : 
     373             :     /* -------------------------------------------------------------------- */
     374             :     /*      Use safe defaults if projection parameters are not supplied.    */
     375             :     /* -------------------------------------------------------------------- */
     376         101 :     double adfPrjParams[8] = {0.0};
     377         101 :     if (padfPrjParams != nullptr)
     378             :     {
     379          99 :         std::copy(padfPrjParams, padfPrjParams + 8, adfPrjParams);
     380             :     }
     381             : 
     382         101 :     CPLDebug("OSR_Panorama",
     383             :              "importFromPanorama: proj %ld, datum %ld, ellips %ld, params [%f, "
     384             :              "%f, %f, %f, %f, %f, %f, %f], north %d",
     385             :              iProjSys, iDatum, iEllips, adfPrjParams[0], adfPrjParams[1],
     386             :              adfPrjParams[2], adfPrjParams[3], adfPrjParams[4], adfPrjParams[5],
     387             :              adfPrjParams[6], adfPrjParams[7], bNorth);
     388             : 
     389             :     // Check some zonal projections
     390         230 :     if ((IsNone(iEllips) || iEllips == PAN_ELLIPSOID_KRASSOVSKY) &&
     391         230 :         (IsNone(iDatum) || iDatum == PAN_DATUM_PULKOVO42) &&
     392             :         iProjSys == PAN_PROJ_TM)  // Pulkovo 1942 / Gauss-Kruger
     393             :     {
     394          12 :         int nZone = adfPrjParams[7] == 0.0
     395          12 :                         ? GetZoneNumberGK(TO_DEGREES * adfPrjParams[3])
     396           2 :                         : static_cast<int>(adfPrjParams[7]);
     397             : 
     398          12 :         if (nZone > 1 && nZone < 33)
     399             :         {
     400          12 :             return importFromEPSG(28400 + nZone);
     401             :         }
     402             :     }
     403         178 :     if ((IsNone(iEllips) || iEllips == PAN_ELLIPSOID_KRASSOVSKY) &&
     404         178 :         iDatum == PAN_DATUM_PULKOVO95 &&
     405             :         iProjSys == PAN_PROJ_TM)  // Pulkovo 1995 / Gauss-Kruger
     406             :     {
     407           0 :         int nZone = adfPrjParams[7] == 0.0
     408           0 :                         ? GetZoneNumberGK(TO_DEGREES * adfPrjParams[3])
     409           0 :                         : static_cast<int>(adfPrjParams[7]);
     410             : 
     411           0 :         if (nZone > 3 && nZone < 33)
     412             :         {
     413           0 :             return importFromEPSG(20000 + nZone);
     414             :         }
     415             :     }
     416          89 :     if (iEllips == PAN_ELLIPSOID_WGS84 && iDatum == PAN_DATUM_UTM &&
     417             :         iProjSys == PAN_PROJ_UTM)  // WGS84 / UTM
     418             :     {
     419           4 :         const int nZone = adfPrjParams[7] == 0.0
     420           4 :                               ? GetZoneNumberUTM(TO_DEGREES * adfPrjParams[3])
     421           0 :                               : static_cast<int>(adfPrjParams[7]);
     422             :         int nEPSG;
     423           4 :         if (bNorth)
     424             :         {
     425           2 :             nEPSG = 32600 + nZone;
     426             :         }
     427             :         else
     428             :         {
     429           2 :             nEPSG = 32700 + nZone;
     430             :         }
     431           4 :         return importFromEPSG(nEPSG);
     432             :     }
     433             : 
     434             :     /* -------------------------------------------------------------------- */
     435             :     /*      Operate on the basis of the projection code.                    */
     436             :     /* -------------------------------------------------------------------- */
     437          85 :     switch (iProjSys)
     438             :     {
     439           0 :         case -1L:
     440             :         case 255L:
     441           0 :             break;
     442             : 
     443          13 :         case PAN_PROJ_SPHERE:
     444          13 :             if (iEllips == PAN_ELLIPSOID_WGS84)
     445             :             {
     446          13 :                 return SetWellKnownGeogCS("EPSG:4326");
     447             :             }
     448           0 :             break;
     449             : 
     450          63 :         case PAN_PROJ_UTM:
     451             :         {
     452             :             const int nZone =
     453          63 :                 adfPrjParams[7] == 0.0
     454          63 :                     ? GetZoneNumberUTM(TO_DEGREES * adfPrjParams[3])
     455           0 :                     : static_cast<int>(adfPrjParams[7]);
     456             : 
     457          63 :             SetUTM(nZone, bNorth);
     458             :         }
     459          63 :         break;
     460             : 
     461           0 :         case PAN_PROJ_WAG1:
     462           0 :             SetWagner(1, 0.0, adfPrjParams[5], adfPrjParams[6]);
     463           0 :             break;
     464             : 
     465           0 :         case PAN_PROJ_MERCAT:
     466           0 :             SetMercator(TO_DEGREES * adfPrjParams[0],
     467           0 :                         TO_DEGREES * adfPrjParams[3], adfPrjParams[4],
     468             :                         adfPrjParams[5], adfPrjParams[6]);
     469           0 :             break;
     470             : 
     471           0 :         case PAN_PROJ_PS:
     472           0 :             SetPS(TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
     473             :                   adfPrjParams[4], adfPrjParams[5], adfPrjParams[6]);
     474           0 :             break;
     475             : 
     476           0 :         case PAN_PROJ_POLYC:
     477           0 :             SetPolyconic(TO_DEGREES * adfPrjParams[2],
     478           0 :                          TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     479             :                          adfPrjParams[6]);
     480           0 :             break;
     481             : 
     482           0 :         case PAN_PROJ_EC:
     483           0 :             SetEC(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
     484           0 :                   TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
     485             :                   adfPrjParams[5], adfPrjParams[6]);
     486           0 :             break;
     487             : 
     488           0 :         case PAN_PROJ_LCC:
     489           0 :             SetLCC(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
     490           0 :                    TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
     491             :                    adfPrjParams[5], adfPrjParams[6]);
     492           0 :             break;
     493             : 
     494           6 :         case PAN_PROJ_TM:
     495             :         {
     496             :             // XXX: we need zone number to compute false easting
     497             :             // parameter, because usually it is not contained in the
     498             :             // "Panorama" projection definition.
     499             :             // FIXME: what to do with negative values?
     500           6 :             int nZone = 0;
     501           6 :             double dfCenterLong = 0.0;
     502             : 
     503           6 :             if (adfPrjParams[7] == 0.0)
     504             :             {
     505           0 :                 dfCenterLong = TO_DEGREES * adfPrjParams[3];
     506           0 :                 nZone = GetZoneNumberGK(dfCenterLong);
     507             :             }
     508             :             else
     509             :             {
     510           6 :                 nZone = static_cast<int>(adfPrjParams[7]);
     511           6 :                 dfCenterLong = 6.0 * nZone - 3.0;
     512             :             }
     513             : 
     514           6 :             adfPrjParams[5] = nZone * 1000000.0 + 500000.0;
     515           6 :             adfPrjParams[4] = 1.0;
     516           6 :             SetTM(TO_DEGREES * adfPrjParams[2], dfCenterLong, adfPrjParams[4],
     517             :                   adfPrjParams[5], adfPrjParams[6]);
     518             :         }
     519           6 :         break;
     520             : 
     521           0 :         case PAN_PROJ_STEREO:
     522           0 :             SetStereographic(TO_DEGREES * adfPrjParams[2],
     523           0 :                              TO_DEGREES * adfPrjParams[3], adfPrjParams[4],
     524             :                              adfPrjParams[5], adfPrjParams[6]);
     525           0 :             break;
     526             : 
     527           0 :         case PAN_PROJ_AE:
     528           0 :             SetAE(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
     529             :                   adfPrjParams[5], adfPrjParams[6]);
     530           0 :             break;
     531             : 
     532           0 :         case PAN_PROJ_GNOMON:
     533           0 :             SetGnomonic(TO_DEGREES * adfPrjParams[2],
     534           0 :                         TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     535             :                         adfPrjParams[6]);
     536           0 :             break;
     537             : 
     538           0 :         case PAN_PROJ_MOLL:
     539           0 :             SetMollweide(TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     540             :                          adfPrjParams[6]);
     541           0 :             break;
     542             : 
     543           0 :         case PAN_PROJ_LAEA:
     544           0 :             SetLAEA(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
     545             :                     adfPrjParams[5], adfPrjParams[6]);
     546           0 :             break;
     547             : 
     548           0 :         case PAN_PROJ_EQC:
     549           0 :             SetEquirectangular(TO_DEGREES * adfPrjParams[0],
     550           0 :                                TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     551             :                                adfPrjParams[6]);
     552           0 :             break;
     553             : 
     554           0 :         case PAN_PROJ_CEA:
     555           0 :             SetCEA(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
     556             :                    adfPrjParams[5], adfPrjParams[6]);
     557           0 :             break;
     558             : 
     559           0 :         case PAN_PROJ_IMWP:
     560           0 :             SetIWMPolyconic(
     561           0 :                 TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
     562           0 :                 TO_DEGREES * adfPrjParams[3], adfPrjParams[5], adfPrjParams[6]);
     563           0 :             break;
     564             : 
     565           0 :         case PAN_PROJ_MILLER:
     566           0 :             SetMC(TO_DEGREES * adfPrjParams[5], TO_DEGREES * adfPrjParams[4],
     567             :                   adfPrjParams[6], adfPrjParams[7]);
     568           0 :             break;
     569             : 
     570           2 :         case PAN_PROJ_PSEUDO_MERCATOR:
     571             :         {
     572           2 :             int nEPSG = 0;
     573           2 :             if (iEllips == PAN_ELLIPSOID_WGS84_SPHERE)
     574             :             {
     575           1 :                 nEPSG = 3857;
     576             :             }
     577           1 :             else if (iEllips == PAN_ELLIPSOID_WGS84)
     578             :             {
     579           1 :                 nEPSG = 3395;
     580             :             }
     581           2 :             if (nEPSG > 0)
     582             :             {
     583           2 :                 return importFromEPSG(nEPSG);
     584             :             }
     585             :         }
     586           0 :         break;
     587             : 
     588           1 :         default:
     589           1 :             CPLDebug("OSR_Panorama", "Unsupported projection: %ld", iProjSys);
     590           2 :             SetLocalCS(CPLString().Printf("\"Panorama\" projection number %ld",
     591           1 :                                           iProjSys));
     592           1 :             break;
     593             :     }
     594             : 
     595             :     /* -------------------------------------------------------------------- */
     596             :     /*      Try to translate the datum/spheroid.                            */
     597             :     /* -------------------------------------------------------------------- */
     598             : 
     599          70 :     if (!IsLocal())
     600             :     {
     601          69 :         if (iEllips == PAN_ELLIPSOID_GSK2011 || iDatum == PAN_DATUM_GSK2011)
     602             :         {
     603           0 :             OGRSpatialReference oGCS;
     604           0 :             oGCS.importFromEPSG(7683);
     605           0 :             CopyGeogCSFrom(&oGCS);
     606             :         }
     607          69 :         else if (iEllips == PAN_ELLIPSOID_PZ90)
     608             :         {
     609           0 :             OGRSpatialReference oGCS;
     610           0 :             oGCS.importFromEPSG(7679);
     611           0 :             CopyGeogCSFrom(&oGCS);
     612             :         }
     613          69 :         else if (iDatum == PAN_DATUM_PULKOVO95)
     614             :         {
     615           0 :             OGRSpatialReference oGCS;
     616           0 :             oGCS.importFromEPSG(4200);
     617           0 :             CopyGeogCSFrom(&oGCS);
     618             :         }
     619          69 :         else if (iDatum > 0 && iDatum < NUMBER_OF_DATUMS && aoDatums[iDatum])
     620             :         {
     621          44 :             OGRSpatialReference oGCS;
     622          22 :             oGCS.importFromEPSG(aoDatums[iDatum]);
     623          44 :             CopyGeogCSFrom(&oGCS);
     624             :         }
     625          47 :         else if (iEllips > 0 && iEllips < NUMBER_OF_PANORAM_ELLIPSOIDS &&
     626          30 :                  aoPanoramaEllips[iEllips])
     627             :         {
     628          30 :             char *pszName = nullptr;
     629          30 :             double dfSemiMajor = 0.0;
     630          30 :             double dfInvFlattening = 0.0;
     631             : 
     632          30 :             if (OSRGetEllipsoidInfo(aoPanoramaEllips[iEllips], &pszName,
     633             :                                     &dfSemiMajor,
     634          30 :                                     &dfInvFlattening) == OGRERR_NONE)
     635             :             {
     636          30 :                 SetGeogCS(
     637          60 :                     CPLString().Printf(
     638          30 :                         "Unknown datum based upon the %s ellipsoid", pszName),
     639          60 :                     CPLString().Printf("Not specified (based on %s spheroid)",
     640          30 :                                        pszName),
     641             :                     pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
     642             :                     nullptr, 0.0);
     643          30 :                 SetAuthority("SPHEROID", "EPSG", aoPanoramaEllips[iEllips]);
     644             :             }
     645             :             else
     646             :             {
     647           0 :                 CPLError(CE_Warning, CPLE_AppDefined,
     648             :                          "Failed to lookup ellipsoid code %ld. "
     649             :                          "Falling back to use Pulkovo 42.",
     650             :                          iEllips);
     651           0 :                 SetWellKnownGeogCS("EPSG:4284");
     652             :             }
     653             : 
     654          30 :             CPLFree(pszName);
     655             :         }
     656             :         else
     657             :         {
     658          17 :             CPLError(CE_Warning, CPLE_AppDefined,
     659             :                      "Wrong datum code %ld. Supported datums are 1 - %d "
     660             :                      "only.  Falling back to use Pulkovo 42.",
     661             :                      iDatum, NUMBER_OF_DATUMS - 1);
     662          17 :             SetWellKnownGeogCS("EPSG:4284");
     663             :         }
     664             :     }
     665             : 
     666             :     /* -------------------------------------------------------------------- */
     667             :     /*      Grid units translation                                          */
     668             :     /* -------------------------------------------------------------------- */
     669          70 :     if (IsLocal() || IsProjected())
     670             :     {
     671          70 :         SetLinearUnits(SRS_UL_METER, 1.0);
     672             :     }
     673             : 
     674          70 :     return OGRERR_NONE;
     675             : }
     676             : 
     677             : /**
     678             :  * Import vertical coordinate system from "Panorama" GIS projection definition.
     679             :  *
     680             :  * @param iVCS Input vertical coordinate system ID.
     681             :  *
     682             :  * Supported VCS are:
     683             :  * <ul>
     684             :  * <li>1:  Baltic 1977 height (EPSG:5705)</li>
     685             :  * <li>2:  AHD height (EPSG:5711)</li>
     686             :  * <li>4:  Ostend height (EPSG:5710)</li>
     687             :  * <li>5:  Ostend height (EPSG:5710)</li>
     688             :  * <li>7:  Belfast height (EPSG: 5732)</li>
     689             :  * <li>8:  Malin Head height (EPSG: 5731)</li>
     690             :  * <li>10: Piraeus height (EPSG:5716)</li>
     691             :  * <li>11: DNN height (EPSG:5733)</li>
     692             :  * <li>12: ISH2004 height (EPSG:8089)</li>
     693             :  * <li>13: Alicante height (EPSG:5782)</li>
     694             :  * <li>15: Genoa height (EPSG:5214)</li>
     695             :  * <li>16: NAP height (EPSG:5709)</li>
     696             :  * <li>17: NN54 height (EPSG:5776)</li>
     697             :  * <li>19: Cascais height (EPSG:5780)</li>
     698             :  * <li>20: N60 height (EPSG:5717)</li>
     699             :  * <li>21: RH2000 height (EPSG:5613)</li>
     700             :  * <li>23: Antalya height (EPSG:5775)</li>
     701             :  * <li>24: NGVD29 height (ftUS) (EPSG:5702)</li>
     702             :  * <li>25: Baltic 1977 height (EPSG:5705)</li>
     703             :  * <li>27: MSL height (EPSG:5714)</li>
     704             :  * </ul>
     705             :  */
     706           0 : OGRErr OGRSpatialReference::importVertCSFromPanorama(int iVCS)
     707             : {
     708           0 :     if (iVCS < 0 || iVCS >= NUMBER_OF_VERTICALCS)
     709             :     {
     710           0 :         return OGRERR_CORRUPT_DATA;
     711             :     }
     712             : 
     713           0 :     const int nEPSG = aoVCS[iVCS];
     714             : 
     715           0 :     if (nEPSG == 0)
     716             :     {
     717           0 :         CPLError(CE_Warning, CPLE_NotSupported,
     718             :                  "Vertical coordinate system (Panorama index %d) not supported",
     719             :                  iVCS);
     720           0 :         return OGRERR_UNSUPPORTED_SRS;
     721             :     }
     722             : 
     723           0 :     OGRSpatialReference sr;
     724           0 :     sr.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     725           0 :     OGRErr eImportFromEPSGErr = sr.importFromEPSG(nEPSG);
     726           0 :     if (eImportFromEPSGErr != OGRERR_NONE)
     727             :     {
     728           0 :         CPLError(CE_Warning, CPLE_None,
     729             :                  "Vertical coordinate system (Panorama index %d, EPSG %d) "
     730             :                  "import from EPSG error",
     731             :                  iVCS, nEPSG);
     732           0 :         return OGRERR_UNSUPPORTED_SRS;
     733             :     }
     734             : 
     735           0 :     if (sr.IsVertical() != 1)
     736             :     {
     737           0 :         CPLError(CE_Warning, CPLE_None,
     738             :                  "Coordinate system (Panorama index %d, EPSG %d) "
     739             :                  "is not Vertical",
     740             :                  iVCS, nEPSG);
     741           0 :         return OGRERR_UNSUPPORTED_SRS;
     742             :     }
     743             : 
     744             :     OGRErr eSetVertCSErr =
     745           0 :         SetVertCS(sr.GetAttrValue("VERT_CS"), sr.GetAttrValue("VERT_DATUM"));
     746           0 :     if (eSetVertCSErr != OGRERR_NONE)
     747             :     {
     748           0 :         CPLError(CE_Warning, CPLE_None,
     749             :                  "Vertical coordinate system (Panorama index %d, EPSG %d) "
     750             :                  "set error",
     751             :                  iVCS, nEPSG);
     752           0 :         return eSetVertCSErr;
     753             :     }
     754           0 :     return OGRERR_NONE;
     755             : }
     756             : 
     757             : /**
     758             :  * Export vertical coordinate system to "Panorama" GIS projection definition.
     759             :  */
     760          53 : OGRErr OGRSpatialReference::exportVertCSToPanorama(int *piVert) const
     761             : {
     762          53 :     auto pszVertCSName = GetAttrValue("COMPD_CS|VERT_CS");
     763          53 :     if (pszVertCSName != nullptr)
     764             :     {
     765           1 :         auto pszValue = GetAuthorityCode("COMPD_CS|VERT_CS");
     766           1 :         if (pszValue != nullptr)
     767             :         {
     768           0 :             auto nEPSG = atoi(pszValue);
     769           0 :             if (nEPSG > 0)
     770             :             {
     771           0 :                 for (int i = 0; i < NUMBER_OF_VERTICALCS; i++)
     772             :                 {
     773           0 :                     if (aoVCS[i] == nEPSG)
     774             :                     {
     775           0 :                         *piVert = i;
     776           0 :                         return OGRERR_NONE;
     777             :                     }
     778             :                 }
     779             :             }
     780             :         }
     781             :         else  // Try to get Panorama ID from pszVertCSName
     782             :         {
     783          26 :             for (int i = 0; i < NUMBER_OF_VERTICALCS; i++)
     784             :             {
     785          26 :                 if (aoVCS[i] > 0)
     786             :                 {
     787          20 :                     OGRSpatialReference oTmpSRS;
     788          20 :                     oTmpSRS.importFromEPSG(aoVCS[i]);
     789          20 :                     if (EQUAL(pszVertCSName, oTmpSRS.GetAttrValue("VERT_CS")))
     790             :                     {
     791             : 
     792           1 :                         *piVert = i;
     793           1 :                         return OGRERR_NONE;
     794             :                     }
     795             :                 }
     796             :             }
     797             :         }
     798             :     }
     799          52 :     CPLDebug("OSR_Panorama",
     800             :              "Vertical coordinate system not supported by Panorama");
     801          52 :     return OGRERR_UNSUPPORTED_SRS;
     802             : }
     803             : 
     804             : /************************************************************************/
     805             : /*                      OSRExportToPanorama()                           */
     806             : /************************************************************************/
     807             : 
     808             : /** Export coordinate system in "Panorama" GIS projection definition.
     809             :  *
     810             :  * See OGRSpatialReference::exportToPanorama()
     811             :  */
     812             : 
     813           0 : OGRErr OSRExportToPanorama(OGRSpatialReferenceH hSRS, long *piProjSys,
     814             :                            long *piDatum, long *piEllips, long *piZone,
     815             :                            double *padfPrjParams)
     816             : 
     817             : {
     818           0 :     VALIDATE_POINTER1(hSRS, "OSRExportToPanorama", OGRERR_FAILURE);
     819           0 :     VALIDATE_POINTER1(piProjSys, "OSRExportToPanorama", OGRERR_FAILURE);
     820           0 :     VALIDATE_POINTER1(piDatum, "OSRExportToPanorama", OGRERR_FAILURE);
     821           0 :     VALIDATE_POINTER1(piEllips, "OSRExportToPanorama", OGRERR_FAILURE);
     822           0 :     VALIDATE_POINTER1(padfPrjParams, "OSRExportToPanorama", OGRERR_FAILURE);
     823             : 
     824           0 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToPanorama(
     825           0 :         piProjSys, piDatum, piEllips, piZone, padfPrjParams);
     826             : }
     827             : 
     828             : /************************************************************************/
     829             : /*                           exportToPanorama()                         */
     830             : /************************************************************************/
     831             : 
     832             : /**
     833             :  * Export coordinate system in "Panorama" GIS projection definition.
     834             :  *
     835             :  * This method is the equivalent of the C function OSRExportToPanorama().
     836             :  *
     837             :  * @param piProjSys Pointer to variable, where the projection system code will
     838             :  * be returned.
     839             :  *
     840             :  * @param piDatum Pointer to variable, where the coordinate system code will
     841             :  * be returned.
     842             :  *
     843             :  * @param piEllips Pointer to variable, where the spheroid code will be
     844             :  * returned.
     845             :  *
     846             :  * @param piZone Pointer to variable, where the zone for UTM projection
     847             :  * system will be returned.
     848             :  *
     849             :  * @param padfPrjParams an existing 7 double buffer into which the
     850             :  * projection parameters will be placed. See importFromPanorama()
     851             :  * for the list of parameters.
     852             :  *
     853             :  * @return OGRERR_NONE on success or an error code on failure.
     854             :  */
     855             : 
     856          56 : OGRErr OGRSpatialReference::exportToPanorama(long *piProjSys, long *piDatum,
     857             :                                              long *piEllips, long *piZone,
     858             :                                              double *padfPrjParams) const
     859             : 
     860             : {
     861          56 :     CPLAssert(padfPrjParams);
     862             : 
     863          56 :     const char *pszProjection = GetAttrValue("PROJECTION");
     864          56 :     int nEPSG = 0;
     865          56 :     auto pszEPSG = GetAuthorityCode("PROJCS");
     866          56 :     if (pszEPSG == nullptr)
     867             :     {
     868          50 :         pszEPSG = GetAuthorityCode("GEOGCS");
     869             :     }
     870          56 :     if (pszEPSG != nullptr)
     871             :     {
     872          32 :         nEPSG = atoi(pszEPSG);
     873             :     }
     874             : 
     875             :     /* -------------------------------------------------------------------- */
     876             :     /*      Fill all projection parameters with zero.                       */
     877             :     /* -------------------------------------------------------------------- */
     878          56 :     *piDatum = 0L;
     879          56 :     *piEllips = 0L;
     880          56 :     *piZone = 0L;
     881         448 :     for (int i = 0; i < 7; i++)
     882         392 :         padfPrjParams[i] = 0.0;
     883             : 
     884             :     /* ==================================================================== */
     885             :     /*      Handle the projection definition.                               */
     886             :     /* ==================================================================== */
     887          56 :     if (IsLocal())
     888             :     {
     889           0 :         *piProjSys = NONE_VAL;
     890             :     }
     891          56 :     else if (IsGeographic() || IsGeocentric())
     892             :     {
     893          22 :         *piProjSys = PAN_PROJ_SPHERE;
     894             :     }
     895             :     // Check well known EPSG codes
     896          34 :     else if (nEPSG == 3857)
     897             :     {
     898           0 :         *piProjSys = PAN_PROJ_PSEUDO_MERCATOR;
     899           0 :         *piDatum = PAN_DATUM_RECTANGULAR;
     900           0 :         *piEllips = PAN_ELLIPSOID_WGS84_SPHERE;
     901           0 :         return OGRERR_NONE;
     902             :     }
     903          34 :     else if (pszProjection == nullptr)
     904             :     {
     905             : #ifdef DEBUG
     906           0 :         CPLDebug("OSR_Panorama",
     907             :                  "Empty projection definition, considered as Geographic");
     908             : #endif
     909           0 :         *piProjSys = NONE_VAL;
     910             :     }
     911          34 :     else if (EQUAL(pszProjection, SRS_PT_MERCATOR_1SP))
     912             :     {
     913           0 :         *piProjSys = PAN_PROJ_MERCAT;
     914           0 :         padfPrjParams[3] =
     915           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     916           0 :         padfPrjParams[0] =
     917           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     918           0 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     919           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     920           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     921             :     }
     922          34 :     else if (EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC))
     923             :     {
     924           0 :         *piProjSys = PAN_PROJ_PS;
     925           0 :         padfPrjParams[3] =
     926           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     927           0 :         padfPrjParams[2] =
     928           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     929           0 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     930           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     931           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     932             :     }
     933          34 :     else if (EQUAL(pszProjection, SRS_PT_POLYCONIC))
     934             :     {
     935           0 :         *piProjSys = PAN_PROJ_POLYC;
     936           0 :         padfPrjParams[3] =
     937           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     938           0 :         padfPrjParams[2] =
     939           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     940           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     941           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     942             :     }
     943          34 :     else if (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC))
     944             :     {
     945           0 :         *piProjSys = PAN_PROJ_EC;
     946           0 :         padfPrjParams[0] =
     947           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
     948           0 :         padfPrjParams[1] =
     949           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);
     950           0 :         padfPrjParams[3] =
     951           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     952           0 :         padfPrjParams[2] =
     953           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     954           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     955           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     956             :     }
     957          34 :     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
     958             :     {
     959           0 :         *piProjSys = PAN_PROJ_LCC;
     960           0 :         padfPrjParams[0] =
     961           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
     962           0 :         padfPrjParams[1] =
     963           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);
     964           0 :         padfPrjParams[3] =
     965           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     966           0 :         padfPrjParams[2] =
     967           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     968           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     969           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     970             :     }
     971          34 :     else if (EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR))
     972             :     {
     973          33 :         int bNorth = FALSE;
     974             : 
     975          33 :         *piZone = GetUTMZone(&bNorth);
     976             : 
     977          33 :         auto dfCenterLong = GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     978          33 :         padfPrjParams[3] = TO_RADIANS * dfCenterLong;
     979          33 :         padfPrjParams[2] =
     980          33 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     981          33 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     982          33 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     983          33 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     984             : 
     985          33 :         if (*piZone != 0)
     986             :         {
     987          30 :             *piProjSys = PAN_PROJ_UTM;
     988          30 :             if (!bNorth)
     989           0 :                 *piZone = -*piZone;
     990             :         }
     991             :         else
     992             :         {
     993           3 :             *piProjSys = PAN_PROJ_TM;
     994           3 :             auto nZone = GetZoneNumberGK(dfCenterLong);
     995           3 :             *piZone = nZone;
     996             :         }
     997             :     }
     998           1 :     else if (EQUAL(pszProjection, SRS_PT_WAGNER_I))
     999             :     {
    1000           0 :         *piProjSys = PAN_PROJ_WAG1;
    1001           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1002           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1003             :     }
    1004           1 :     else if (EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC))
    1005             :     {
    1006           0 :         *piProjSys = PAN_PROJ_STEREO;
    1007           0 :         padfPrjParams[3] =
    1008           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1009           0 :         padfPrjParams[2] =
    1010           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
    1011           0 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
    1012           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1013           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1014             :     }
    1015           1 :     else if (EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT))
    1016             :     {
    1017           0 :         *piProjSys = PAN_PROJ_AE;
    1018           0 :         padfPrjParams[3] =
    1019           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);
    1020           0 :         padfPrjParams[0] =
    1021           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);
    1022           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1023           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1024             :     }
    1025           1 :     else if (EQUAL(pszProjection, SRS_PT_GNOMONIC))
    1026             :     {
    1027           0 :         *piProjSys = PAN_PROJ_GNOMON;
    1028           0 :         padfPrjParams[3] =
    1029           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1030           0 :         padfPrjParams[2] =
    1031           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
    1032           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1033           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1034             :     }
    1035           1 :     else if (EQUAL(pszProjection, SRS_PT_MOLLWEIDE))
    1036             :     {
    1037           0 :         *piProjSys = PAN_PROJ_MOLL;
    1038           0 :         padfPrjParams[3] =
    1039           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1040           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1041           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1042             :     }
    1043           1 :     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
    1044             :     {
    1045           0 :         *piProjSys = PAN_PROJ_LAEA;
    1046           0 :         padfPrjParams[3] =
    1047           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1048           0 :         padfPrjParams[0] =
    1049           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
    1050           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1051           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1052             :     }
    1053           1 :     else if (EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR))
    1054             :     {
    1055           0 :         *piProjSys = PAN_PROJ_EQC;
    1056           0 :         padfPrjParams[3] =
    1057           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1058           0 :         padfPrjParams[0] =
    1059           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
    1060           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1061           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1062             :     }
    1063           1 :     else if (EQUAL(pszProjection, SRS_PT_CYLINDRICAL_EQUAL_AREA))
    1064             :     {
    1065           0 :         *piProjSys = PAN_PROJ_CEA;
    1066           0 :         padfPrjParams[3] =
    1067           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1068           0 :         padfPrjParams[2] =
    1069           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
    1070           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1071           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1072             :     }
    1073           1 :     else if (EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC))
    1074             :     {
    1075           0 :         *piProjSys = PAN_PROJ_IMWP;
    1076           0 :         padfPrjParams[3] =
    1077           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1078           0 :         padfPrjParams[0] =
    1079           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0);
    1080           0 :         padfPrjParams[1] =
    1081           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0);
    1082           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1083           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1084             :     }
    1085             :     // Projection unsupported by "Panorama" GIS
    1086             :     else
    1087             :     {
    1088           1 :         CPLDebug("OSR_Panorama",
    1089             :                  "Projection \"%s\" unsupported by \"Panorama\" GIS. "
    1090             :                  "Geographic system will be used.",
    1091             :                  pszProjection);
    1092           1 :         *piProjSys = NONE_VAL;
    1093             :     }
    1094             : 
    1095             :     /* -------------------------------------------------------------------- */
    1096             :     /*      Translate the datum.                                            */
    1097             :     /* -------------------------------------------------------------------- */
    1098          56 :     const char *pszDatum = GetAttrValue("DATUM");
    1099             : 
    1100          56 :     if (pszDatum == nullptr)
    1101             :     {
    1102           0 :         *piDatum = NONE_VAL;
    1103           0 :         *piEllips = NONE_VAL;
    1104             :     }
    1105          56 :     else if (EQUAL(pszDatum, "Pulkovo_1942"))
    1106             :     {
    1107          22 :         *piDatum = PAN_DATUM_PULKOVO42;
    1108          22 :         *piEllips = PAN_ELLIPSOID_KRASSOVSKY;
    1109             :     }
    1110          34 :     else if (EQUAL(pszDatum, "Pulkovo_1995"))
    1111             :     {
    1112           0 :         *piDatum = PAN_DATUM_PULKOVO95;
    1113           0 :         *piEllips = PAN_ELLIPSOID_KRASSOVSKY;
    1114             :     }
    1115          34 :     else if (EQUAL(pszDatum, SRS_DN_WGS84))
    1116             :     {
    1117          24 :         *piDatum = PAN_DATUM_RECTANGULAR;  // PAN_DATUM_WGS84;
    1118          24 :         *piEllips = PAN_ELLIPSOID_WGS84;
    1119             :     }
    1120             : 
    1121             :     // If not found well known datum, translate ellipsoid.
    1122             :     else
    1123             :     {
    1124          10 :         const double dfSemiMajor = GetSemiMajor();
    1125          10 :         const double dfInvFlattening = GetInvFlattening();
    1126             : 
    1127             : #ifdef DEBUG
    1128          10 :         CPLDebug("OSR_Panorama",
    1129             :                  "Datum \"%s\" unsupported by \"Panorama\" GIS. "
    1130             :                  "Trying to translate an ellipsoid definition.",
    1131             :                  pszDatum);
    1132             : #endif
    1133             : 
    1134          10 :         int i = 0;  // Used after for.
    1135          60 :         for (; i < NUMBER_OF_PANORAM_ELLIPSOIDS; i++)
    1136             :         {
    1137          60 :             if (aoPanoramaEllips[i])
    1138             :             {
    1139          50 :                 double dfSM = 0.0;
    1140          50 :                 double dfIF = 1.0;
    1141             : 
    1142          50 :                 if (OSRGetEllipsoidInfo(aoPanoramaEllips[i], nullptr, &dfSM,
    1143          50 :                                         &dfIF) == OGRERR_NONE &&
    1144          60 :                     std::abs(dfSemiMajor - dfSM) < 1e-10 * dfSemiMajor &&
    1145          10 :                     std::abs(dfInvFlattening - dfIF) < 1e-10 * dfInvFlattening)
    1146             :                 {
    1147          10 :                     *piEllips = i;
    1148          10 :                     break;
    1149             :                 }
    1150             :             }
    1151             :         }
    1152             : 
    1153          10 :         if (i == NUMBER_OF_PANORAM_ELLIPSOIDS)  // Didn't found matches.
    1154             :         {
    1155             : #ifdef DEBUG
    1156           0 :             CPLDebug("OSR_Panorama",
    1157             :                      R"(Ellipsoid "%s" unsupported by "Panorama" GIS.)",
    1158             :                      pszDatum);
    1159             : #endif
    1160           0 :             *piDatum = NONE_VAL;
    1161           0 :             *piEllips = NONE_VAL;
    1162             :         }
    1163             :     }
    1164             : 
    1165          56 :     return OGRERR_NONE;
    1166             : }

Generated by: LCOV version 1.14