LCOV - code coverage report
Current view: top level - frmts/ilwis - ilwiscoordinatesystem.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 143 444 32.2 %
Date: 2024-05-04 12:52:34 Functions: 5 30 16.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Purpose: Translation from ILWIS coordinate system information.
       4             :  * Author:   Lichun Wang, lichun@itc.nl
       5             :  *
       6             :  ******************************************************************************
       7             :  * Copyright (c) 2004, ITC
       8             :  * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : #include "cpl_conv.h"
      29             : #include "ilwisdataset.h"
      30             : 
      31             : #include <string>
      32             : 
      33             : namespace GDAL
      34             : {
      35             : 
      36             : typedef struct
      37             : {
      38             :     const char *pszIlwisDatum;
      39             :     const char *pszWKTDatum;
      40             :     int nEPSGCode;
      41             : } IlwisDatums;
      42             : 
      43             : typedef struct
      44             : {
      45             :     const char *pszIlwisEllips;
      46             :     int nEPSGCode;
      47             :     double semiMajor;
      48             :     double invFlattening;
      49             : } IlwisEllips;
      50             : 
      51             : static const IlwisDatums iwDatums[] = {
      52             :     {"Adindan", "Adindan", 4201},
      53             :     {"Afgooye", "Afgooye", 4205},
      54             :     // AGREF --- skipped
      55             :     {"Ain el Abd 1970", "Ain_el_Abd_1970", 4204},
      56             :     {"American Samoa 1962", "American_Samoa_1962", 4169},
      57             :     // Anna 1 Astro 1965 --- skipped
      58             :     {"Antigua Island Astro 1943", "Antigua_1943", 4601},
      59             :     {"Arc 1950", "Arc_1950", 4209},  // Arc 1950
      60             :     {"Arc 1960", "Arc_1960", 4210},  // Arc 1960
      61             :     // Ascension Island 1958
      62             :     // Astro Beacon E 1945
      63             :     // Astro DOS 71/4
      64             :     // Astro Tern Island (FRIG) 1961
      65             :     // Astronomical Station 1952
      66             :     {"Australian Geodetic 1966", "Australian_Geodetic_Datum_1966", 4202},
      67             :     {"Australian Geodetic 1984", "Australian_Geodetic_Datum_1984", 4203},
      68             :     // Ayabelle Lighthouse
      69             :     // Bellevue (IGN)
      70             :     {"Bermuda 1957", "Bermuda_1957", 4216},
      71             :     {"Bissau", "Bissau", 4165},
      72             :     {"Bogota Observatory  (1975)", "Bogota", 4218},
      73             :     {"Bukit Rimpah", "Bukit_Rimpah", 4219},
      74             :     // Camp Area Astro
      75             :     {"Campo Inchauspe", "Campo_Inchauspe", 4221},
      76             :     // Canton Astro 1966
      77             :     {"Cape", "Cape", 4222},
      78             :     // Cape Canaveral
      79             :     {"Carthage", "Carthage", 4223},
      80             :     {"CH1903", "CH1903", 4149},
      81             :     // Chatham Island Astro 1971
      82             :     {"Chua Astro", "Chua", 4224},
      83             :     {"Corrego Alegre", "Corrego_Alegre", 4225},
      84             :     // Croatia
      85             :     // D-PAF (Orbits)
      86             :     {"Dabola", "Dabola_1981", 4155},
      87             :     // Deception Island
      88             :     // Djakarta (Batavia)
      89             :     // DOS 1968
      90             :     // Easter Island 1967
      91             :     // Estonia 1937
      92             :     {"European 1950 (ED 50)", "European_Datum_1950", 4154},
      93             :     // European 1979 (ED 79
      94             :     // Fort Thomas 1955
      95             :     {"Gan 1970", "Gandajika_1970", 4233},
      96             :     // Geodetic Datum 1949
      97             :     // Graciosa Base SW 1948
      98             :     // Guam 1963
      99             :     {"Gunung Segara", "Gunung_Segara", 4613},
     100             :     // GUX 1 Astro
     101             :     {"Herat North", "Herat_North", 4255},
     102             :     // Hermannskogel
     103             :     // Hjorsey 1955
     104             :     // Hong Kong 1963
     105             :     {"Hu-Tzu-Shan", "Hu_Tzu_Shan", 4236},
     106             :     // Indian (Bangladesh)
     107             :     // Indian (India, Nepal)
     108             :     // Indian (Pakistan)
     109             :     {"Indian 1954", "Indian_1954", 4239},
     110             :     {"Indian 1960", "Indian_1960", 4131},
     111             :     {"Indian 1975", "Indian_1975", 4240},
     112             :     {"Indonesian 1974", "Indonesian_Datum_1974", 4238},
     113             :     // Ireland 1965
     114             :     // ISTS 061 Astro 1968
     115             :     // ISTS 073 Astro 1969
     116             :     // Johnston Island 1961
     117             :     {"Kandawala", "Kandawala", 4244},
     118             :     // Kerguelen Island 1949
     119             :     {"Kertau 1948", "Kertau", 4245},
     120             :     // Kusaie Astro 1951
     121             :     // L. C. 5 Astro 1961
     122             :     {"Leigon", "Leigon", 4250},
     123             :     {"Liberia 1964", "Liberia_1964", 4251},
     124             :     {"Luzon", "Luzon_1911", 4253},
     125             :     // M'Poraloko
     126             :     {"Mahe 1971", "Mahe_1971", 4256},
     127             :     {"Massawa", "Massawa", 4262},
     128             :     {"Merchich", "Merchich", 4261},
     129             :     {"MGI (Hermannskogel)", "Militar_Geographische_Institute", 4312},
     130             :     // Midway Astro 1961
     131             :     {"Minna", "Minna", 4263},
     132             :     {"Montserrat Island Astro 1958", "Montserrat_1958", 4604},
     133             :     {"Nahrwan", "Nahrwan_1967", 4270},
     134             :     {"Naparima BWI", "Naparima_1955", 4158},
     135             :     {"North American 1927 (NAD 27)", "North_American_Datum_1927", 4267},
     136             :     {"North American 1983 (NAD 83)", "North_American_Datum_1983", 4269},
     137             :     // North Sahara 1959
     138             :     {"NTF (Nouvelle Triangulation de France)",
     139             :      "Nouvelle_Triangulation_Francaise", 4807},
     140             :     // Observatorio Meteorologico 1939
     141             :     // Old Egyptian 1907
     142             :     {"Old Hawaiian", "Old_Hawaiian", 4135},
     143             :     // Oman
     144             :     // Ordnance Survey Great Britain 1936
     145             :     // Pico de las Nieves
     146             :     // Pitcairn Astro 1967
     147             :     // Point 58
     148             :     {"Pointe Noire 1948", "Pointe_Noire", 4282},
     149             :     {"Porto Santo 1936", "Porto_Santo", 4615},
     150             :     // Potsdam (Rauenburg)
     151             :     {"Potsdam (Rauenburg)", "Deutsches_Hauptdreiecksnetz", 4314},
     152             :     {"Provisional South American 1956", "Provisional_South_American_Datum_1956",
     153             :      4248},
     154             :     // Provisional South Chilean 1963
     155             :     {"Puerto Rico", "Puerto_Rico", 4139},
     156             :     {"Pulkovo 1942", "Pulkovo_1942", 4178},
     157             :     //{ "Qatar National", "Qatar_National_Datum_1995", 4614 },
     158             :     {"Qornoq", "Qornoq", 4287},
     159             :     {"Puerto Rico", "Puerto_Rico", 4139},
     160             :     // Reunion
     161             :     {"Rome 1940", "Monte_Mario", 4806},
     162             :     {"RT90", "Rikets_koordinatsystem_1990", 4124},
     163             :     {"Rijks Driehoeksmeting", "Amersfoort", 4289},
     164             :     {"S-42 (Pulkovo 1942)", "Pulkovo_1942", 4178},
     165             :     //{ "S-JTSK", "Jednotne_Trigonometricke_Site_Katastralni", 4156 },
     166             :     // Santo (DOS) 1965
     167             :     // Sao Braz
     168             :     {"Sapper Hill 1943", "Sapper_Hill_1943", 4292},
     169             :     {"Schwarzeck", "Schwarzeck", 4293},
     170             :     {"Selvagem Grande 1938", "Selvagem_Grande", 4616},
     171             :     // vSGS 1985
     172             :     // Sierra Leone 1960
     173             :     {"South American 1969", "South_American_Datum_1969", 4291},
     174             :     // South Asia
     175             :     {"Tananarive Observatory 1925", "Tananarive_1925", 4297},
     176             :     {"Timbalai 1948", "Timbalai_1948", 4298},
     177             :     {"Tokyo", "Tokyo", 4301},
     178             :     // Tristan Astro 1968
     179             :     // Viti Levu 1916
     180             :     {"Voirol 1874", "Voirol_1875", 4304},
     181             :     // Voirol 1960
     182             :     // Wake Island Astro 1952
     183             :     // Wake-Eniwetok 1960
     184             :     {"WGS 1972", "WGS_1972", 4322},
     185             :     {"WGS 1984", "WGS_1984", 4326},
     186             :     {"Yacare", "Yacare", 4309},
     187             :     {"Zanderij", "Zanderij", 4311},
     188             :     {nullptr, nullptr, 0}};
     189             : 
     190             : static const IlwisEllips iwEllips[] = {
     191             :     {"Sphere", 7035, 6371007, 0.0},  // rad 6370997 m (normal sphere)
     192             :     {"Airy 1830", 7031, 6377563.396, 299.3249646},
     193             :     {"Modified Airy", 7002, 6377340.189, 299.3249646},
     194             :     {"ATS77", 7204, 6378135.0, 298.257000006},
     195             :     {"Australian National", 7003, 6378160, 298.249997276},
     196             :     {"Bessel 1841", 7042, 6377397.155, 299.1528128},
     197             :     {"Bessel 1841 (Japan By Law)", 7046, 6377397.155, 299.152815351},
     198             :     {"Bessel 1841 (Namibia)", 7006, 6377483.865, 299.1528128},
     199             :     {"Clarke 1866", 7008, 6378206.4, 294.9786982},
     200             :     {"Clarke 1880", 7034, 6378249.145, 293.465},
     201             :     {"Clarke 1880 (IGN)", 7011, 6378249.2, 293.466},
     202             :     // FIXME: D-PAF (Orbits) --- skipped
     203             :     // FIXME: Du Plessis Modified --- skipped
     204             :     // FIXME: Du Plessis Reconstituted --- skipped
     205             :     {"Everest (India 1830)", 7015, 6377276.345, 300.8017},
     206             :     // Everest (India 1956) --- skipped
     207             :     // Everest (Malaysia 1969) --- skipped
     208             :     {"Everest (E. Malaysia and Brunei)", 7016, 6377298.556, 300.8017},
     209             :     {"Everest (Malay. and Singapore 1948)", 7018, 6377304.063, 300.8017},
     210             :     {"Everest (Pakistan)", 7044, 6377309.613, 300.8017},
     211             :     // Everest (Sabah Sarawak) --- skipped
     212             :     // Fischer 1960 --- skipped
     213             :     // Fischer 1960 (Modified) --- skipped
     214             :     // Fischer 1968 --- skipped
     215             :     {"GRS 80", 7019, 6378137, 298.257222101},
     216             :     {"Helmert 1906", 7020, 6378200, 298.3},
     217             :     // Hough 1960 --- skipped
     218             :     {"Indonesian 1974", 7021, 6378160, 298.247},
     219             :     {"International 1924", 7022, 6378388, 297},
     220             :     {"Krassovsky 1940", 7024, 6378245, 298.3},
     221             :     // New_International 1967
     222             :     // SGS 85
     223             :     // South American 1969
     224             :     // WGS 60
     225             :     // WGS 66
     226             :     {"WGS 72", 7020, 6378135.0, 298.259998590},
     227             :     {"WGS 84", 7030, 6378137, 298.257223563},
     228             :     {nullptr, 0, 0.0, 0.0}};
     229             : 
     230             : #ifndef R2D
     231             : #define R2D (180 / M_PI)
     232             : #endif
     233             : #ifndef D2R
     234             : #define D2R (M_PI / 180)
     235             : #endif
     236             : 
     237             : /* ==================================================================== */
     238             : /*      Some "standard" std::strings.                                        */
     239             : /* ==================================================================== */
     240             : 
     241             : static const char ILW_False_Easting[] = "False Easting";
     242             : static const char ILW_False_Northing[] = "False Northing";
     243             : static const char ILW_Central_Meridian[] = "Central Meridian";
     244             : static const char ILW_Central_Parallel[] = "Central Parallel";
     245             : static const char ILW_Standard_Parallel_1[] = "Standard Parallel 1";
     246             : static const char ILW_Standard_Parallel_2[] = "Standard Parallel 2";
     247             : static const char ILW_Scale_Factor[] = "Scale Factor";
     248             : static const char ILW_Latitude_True_Scale[] = "Latitude of True Scale";
     249             : static const char ILW_Height_Persp_Center[] = "Height Persp. Center";
     250             : 
     251          58 : static double ReadPrjParams(const std::string &section,
     252             :                             const std::string &entry,
     253             :                             const std::string &filename)
     254             : {
     255         116 :     std::string str = ReadElement(section, entry, filename);
     256             :     // string str="";
     257          58 :     if (!str.empty())
     258          13 :         return CPLAtof(str.c_str());
     259             : 
     260          45 :     return 0.0;
     261             : }
     262             : 
     263           5 : static int fetchParams(const std::string &csyFileName, double *padfPrjParams)
     264             : {
     265             :     // Fill all projection parameters with zero
     266          70 :     for (int i = 0; i < 13; i++)
     267          65 :         padfPrjParams[i] = 0.0;
     268             : 
     269             :     // std::string pszProj = ReadElement("CoordSystem", "Projection",
     270             :     // csyFileName);
     271             :     std::string pszEllips =
     272          10 :         ReadElement("CoordSystem", "Ellipsoid", csyFileName);
     273             : 
     274             :     // fetch info about a custom ellipsoid
     275           5 :     if (STARTS_WITH_CI(pszEllips.c_str(), "User Defined"))
     276             :     {
     277           4 :         padfPrjParams[0] = ReadPrjParams("Ellipsoid", "a", csyFileName);
     278           4 :         padfPrjParams[2] = ReadPrjParams("Ellipsoid", "1/f", csyFileName);
     279             :     }
     280           1 :     else if (STARTS_WITH_CI(pszEllips.c_str(), "Sphere"))
     281             :     {
     282           0 :         padfPrjParams[0] =
     283           0 :             ReadPrjParams("CoordSystem", "Sphere Radius", csyFileName);
     284             :     }
     285             : 
     286          10 :     padfPrjParams[3] =
     287           5 :         ReadPrjParams("Projection", "False Easting", csyFileName);
     288          10 :     padfPrjParams[4] =
     289           5 :         ReadPrjParams("Projection", "False Northing", csyFileName);
     290             : 
     291          10 :     padfPrjParams[5] =
     292           5 :         ReadPrjParams("Projection", "Central Parallel", csyFileName);
     293          10 :     padfPrjParams[6] =
     294           5 :         ReadPrjParams("Projection", "Central Meridian", csyFileName);
     295             : 
     296          10 :     padfPrjParams[7] =
     297           5 :         ReadPrjParams("Projection", "Standard Parallel 1", csyFileName);
     298          10 :     padfPrjParams[8] =
     299           5 :         ReadPrjParams("Projection", "Standard Parallel 2", csyFileName);
     300             : 
     301           5 :     padfPrjParams[9] = ReadPrjParams("Projection", "Scale Factor", csyFileName);
     302          10 :     padfPrjParams[10] =
     303           5 :         ReadPrjParams("Projection", "Latitude of True Scale", csyFileName);
     304           5 :     padfPrjParams[11] = ReadPrjParams("Projection", "Zone", csyFileName);
     305          10 :     padfPrjParams[12] =
     306           5 :         ReadPrjParams("Projection", ILW_Height_Persp_Center, csyFileName);
     307             : 
     308          10 :     return true;
     309             : }
     310             : 
     311             : /************************************************************************/
     312             : /*                          mapTMParams                                  */
     313             : /************************************************************************/
     314             : /**
     315             :  * fetch the parameters from ILWIS projection definition for
     316             :  * --- Gauss-Krueger Germany.
     317             :  * --- Gauss Colombia
     318             :  * --- Gauss-Boaga Italy
     319             :  **/
     320           0 : static int mapTMParams(const std::string &sProj, double dfZone,
     321             :                        double &dfFalseEasting, double &dfCentralMeridian)
     322             : {
     323           0 :     if (STARTS_WITH_CI(sProj.c_str(), "Gauss-Krueger Germany"))
     324             :     {
     325             :         // Zone number must be in the range 1 to 3
     326           0 :         dfCentralMeridian = 6.0 + (dfZone - 1) * 3;
     327           0 :         dfFalseEasting = 2500000 + (dfZone - 1) * 1000000;
     328             :     }
     329           0 :     else if (STARTS_WITH_CI(sProj.c_str(), "Gauss-Boaga Italy"))
     330             :     {
     331           0 :         if (dfZone == 1)
     332             :         {
     333           0 :             dfCentralMeridian = 9;
     334           0 :             dfFalseEasting = 1500000;
     335             :         }
     336           0 :         else if (dfZone == 2)
     337             :         {
     338           0 :             dfCentralMeridian = 15;
     339           0 :             dfFalseEasting = 2520000;
     340             :         }
     341             :         else
     342           0 :             return false;
     343             :     }
     344           0 :     else if (STARTS_WITH_CI(sProj.c_str(), "Gauss Colombia"))
     345             :     {
     346             :         // Zone number must be in the range 1 to 4
     347           0 :         dfCentralMeridian = -77.08097220 + (dfZone - 1) * 3;
     348             :     }
     349           0 :     return true;
     350             : }
     351             : 
     352             : /************************************************************************/
     353             : /*                          scaleFromLATTS()                             */
     354             : /************************************************************************/
     355             : /**
     356             :  * Compute the scale factor from Latitude_Of_True_Scale parameter.
     357             :  *
     358             :  **/
     359           0 : static void scaleFromLATTS(const std::string &sEllips, double phits,
     360             :                            double &scale)
     361             : {
     362           0 :     if (STARTS_WITH_CI(sEllips.c_str(), "Sphere"))
     363             :     {
     364           0 :         scale = cos(phits);
     365             :     }
     366             :     else
     367             :     {
     368           0 :         const IlwisEllips *piwEllips = iwEllips;
     369           0 :         double e2 = 0.0;
     370           0 :         while (piwEllips->pszIlwisEllips)
     371             :         {
     372           0 :             if (EQUALN(sEllips.c_str(), piwEllips->pszIlwisEllips,
     373             :                        strlen(piwEllips->pszIlwisEllips)))
     374             :             {
     375           0 :                 double a = piwEllips->semiMajor;
     376           0 :                 double b = a * (1 - piwEllips->invFlattening);
     377           0 :                 e2 = (a * a - b * b) / (a * a);
     378           0 :                 break;
     379             :             }
     380           0 :             piwEllips++;
     381             :         }
     382           0 :         scale = cos(phits) / sqrt(1. - e2 * sin(phits) * sin(phits));
     383             :     }
     384           0 : }
     385             : 
     386             : /************************************************************************/
     387             : /*                          ReadProjection()                           */
     388             : /************************************************************************/
     389             : 
     390             : /**
     391             :  * Import coordinate system from ILWIS projection definition.
     392             :  *
     393             :  * The method will import projection definition in ILWIS,
     394             :  * It uses 13 parameters to define the coordinate system
     395             :  * and datum/ellipsoid specified in the padfPrjParams array.
     396             :  *
     397             :  * @param csyFileName Name of .csy file
     398             :  **/
     399             : 
     400           5 : CPLErr ILWISDataset::ReadProjection(const std::string &csyFileName)
     401             : {
     402          10 :     std::string pszEllips;
     403          10 :     std::string pszDatum;
     404           5 :     std::string pszProj;
     405             : 
     406             :     // translate ILWIS pre-defined coordinate systems
     407           5 :     if (STARTS_WITH_CI(csyFileName.c_str(), "latlon.csy"))
     408             :     {
     409           0 :         pszProj = "LatLon";
     410           0 :         pszDatum = "";
     411           0 :         pszEllips = "Sphere";
     412             :     }
     413           5 :     else if (STARTS_WITH_CI(csyFileName.c_str(), "LatlonWGS84.csy"))
     414             :     {
     415           0 :         pszProj = "LatLon";
     416           0 :         pszDatum = "WGS 1984";
     417           0 :         pszEllips = "WGS 84";
     418             :     }
     419             :     else
     420             :     {
     421           5 :         pszProj = ReadElement("CoordSystem", "Type", csyFileName);
     422           5 :         if (!STARTS_WITH_CI(pszProj.c_str(), "LatLon"))
     423           5 :             pszProj = ReadElement("CoordSystem", "Projection", csyFileName);
     424           5 :         pszDatum = ReadElement("CoordSystem", "Datum", csyFileName);
     425           5 :         pszEllips = ReadElement("CoordSystem", "Ellipsoid", csyFileName);
     426             :     }
     427             : 
     428             :     /* -------------------------------------------------------------------- */
     429             :     /*      Fetch array containing 13 coordinate system parameters          */
     430             :     /* -------------------------------------------------------------------- */
     431             :     double padfPrjParams[13];
     432           5 :     fetchParams(csyFileName, padfPrjParams);
     433             : 
     434           5 :     m_oSRS.Clear();
     435             :     /* -------------------------------------------------------------------- */
     436             :     /*      Operate on the basis of the projection name.                    */
     437             :     /* -------------------------------------------------------------------- */
     438           5 :     if (STARTS_WITH_CI(pszProj.c_str(), "LatLon"))
     439             :     {
     440             :         // set datum later
     441             :     }
     442           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Albers EqualArea Conic"))
     443             :     {
     444           0 :         m_oSRS.SetProjCS("Albers EqualArea Conic");
     445           0 :         m_oSRS.SetACEA(padfPrjParams[7], padfPrjParams[8], padfPrjParams[5],
     446             :                        padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
     447             :     }
     448           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Azimuthal Equidistant"))
     449             :     {
     450           0 :         m_oSRS.SetProjCS("Azimuthal Equidistant");
     451           0 :         m_oSRS.SetAE(padfPrjParams[5], padfPrjParams[6], padfPrjParams[3],
     452             :                      padfPrjParams[4]);
     453             :     }
     454           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Central Cylindrical"))
     455             :     {
     456             :         // Use Central Parallel for dfStdP1
     457             :         // padfPrjParams[5] is always to zero
     458           0 :         m_oSRS.SetProjCS("Central Cylindrical");
     459           0 :         m_oSRS.SetCEA(padfPrjParams[5], padfPrjParams[6], padfPrjParams[3],
     460             :                       padfPrjParams[4]);
     461             :     }
     462           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Cassini"))
     463             :     {
     464             :         // Use Latitude_Of_True_Scale for dfCenterLat
     465             :         // Scale Factor 1.0 should always be defined
     466           0 :         m_oSRS.SetProjCS("Cassini");
     467           0 :         m_oSRS.SetCS(padfPrjParams[10], padfPrjParams[6], padfPrjParams[3],
     468             :                      padfPrjParams[4]);
     469             :     }
     470           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "DutchRD"))
     471             :     {
     472           0 :         m_oSRS.SetProjCS("DutchRD");
     473           0 :         m_oSRS.SetStereographic(52.156160556, 5.387638889, 0.9999079, 155000,
     474             :                                 463000);
     475             :     }
     476           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Equidistant Conic"))
     477             :     {
     478           0 :         m_oSRS.SetProjCS("Equidistant Conic");
     479           0 :         m_oSRS.SetEC(padfPrjParams[7], padfPrjParams[8], padfPrjParams[5],
     480             :                      padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
     481             :     }
     482           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Gauss-Krueger Germany"))
     483             :     {
     484             :         // FalseNorthing and CenterLat are always set to 0
     485             :         // Scale 1.0 is defined
     486             :         // FalseEasting and CentralMeridian are defined by the selected zone
     487           0 :         mapTMParams("Gauss-Krueger Germany", padfPrjParams[11],
     488             :                     padfPrjParams[3], padfPrjParams[6]);
     489           0 :         m_oSRS.SetProjCS("Gauss-Krueger Germany");
     490           0 :         m_oSRS.SetTM(0, padfPrjParams[6], 1.0, padfPrjParams[3], 0);
     491             :     }
     492           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Gauss-Boaga Italy"))
     493             :     {
     494             :         // FalseNorthing and CenterLat are always set to 0
     495             :         // Scale 0.9996 is defined
     496             :         // FalseEasting and CentralMeridian are defined by the selected zone
     497           0 :         mapTMParams("Gauss-Boaga Italy", padfPrjParams[11], padfPrjParams[3],
     498             :                     padfPrjParams[6]);
     499           0 :         m_oSRS.SetProjCS("Gauss-Boaga Italy");
     500           0 :         m_oSRS.SetTM(0, padfPrjParams[6], 0.9996, padfPrjParams[3], 0);
     501             :     }
     502           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Gauss Colombia"))
     503             :     {
     504             :         // 1000000 used for FalseNorthing and FalseEasting
     505             :         // 1.0 used for scale
     506             :         // CenterLat is defined 45.1609259259259
     507             :         // CentralMeridian is defined by the selected zone
     508           0 :         mapTMParams("Gauss Colombia", padfPrjParams[11], padfPrjParams[3],
     509             :                     padfPrjParams[6]);
     510           0 :         m_oSRS.SetProjCS("Gauss Colombia");
     511           0 :         m_oSRS.SetTM(45.1609259259259, padfPrjParams[6], 1.0, 1000000, 1000000);
     512             :     }
     513           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Gnomonic"))
     514             :     {
     515           0 :         m_oSRS.SetProjCS("Gnomonic");
     516           0 :         m_oSRS.SetGnomonic(padfPrjParams[5], padfPrjParams[6], padfPrjParams[3],
     517             :                            padfPrjParams[4]);
     518             :     }
     519           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Lambert Conformal Conic"))
     520             :     {
     521             :         // should use 1.0 for scale factor in Ilwis definition
     522           0 :         m_oSRS.SetProjCS("Lambert Conformal Conic");
     523           0 :         m_oSRS.SetLCC(padfPrjParams[7], padfPrjParams[8], padfPrjParams[5],
     524             :                       padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
     525             :     }
     526           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Lambert Cylind EqualArea"))
     527             :     {
     528             :         // Latitude_Of_True_Scale used for dfStdP1 ?
     529           0 :         m_oSRS.SetProjCS("Lambert Conformal Conic");
     530           0 :         m_oSRS.SetCEA(padfPrjParams[10], padfPrjParams[6], padfPrjParams[3],
     531             :                       padfPrjParams[4]);
     532             :     }
     533           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Mercator"))
     534             :     {
     535             :         // use 0 for CenterLat, scale is computed from the
     536             :         // Latitude_Of_True_Scale
     537           0 :         scaleFromLATTS(pszEllips, padfPrjParams[10], padfPrjParams[9]);
     538           0 :         m_oSRS.SetProjCS("Mercator");
     539           0 :         m_oSRS.SetMercator(0, padfPrjParams[6], padfPrjParams[9],
     540             :                            padfPrjParams[3], padfPrjParams[4]);
     541             :     }
     542           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Miller"))
     543             :     {
     544             :         // use 0 for CenterLat
     545           0 :         m_oSRS.SetProjCS("Miller");
     546           0 :         m_oSRS.SetMC(0, padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
     547             :     }
     548           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Mollweide"))
     549             :     {
     550           0 :         m_oSRS.SetProjCS("Mollweide");
     551           0 :         m_oSRS.SetMollweide(padfPrjParams[6], padfPrjParams[3],
     552             :                             padfPrjParams[4]);
     553             :     }
     554           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Orthographic"))
     555             :     {
     556           0 :         m_oSRS.SetProjCS("Orthographic");
     557           0 :         m_oSRS.SetOrthographic(padfPrjParams[5], padfPrjParams[6],
     558             :                                padfPrjParams[3], padfPrjParams[4]);
     559             :     }
     560          10 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Plate Carree") ||
     561           5 :              STARTS_WITH_CI(pszProj.c_str(), "Plate Rectangle"))
     562             :     {
     563             :         // set 0.0 for CenterLat for Plate Carree projection
     564             :         // skip Latitude_Of_True_Scale for Plate Rectangle projection definition
     565           0 :         m_oSRS.SetProjCS(pszProj.c_str());
     566           0 :         m_oSRS.SetEquirectangular(padfPrjParams[5], padfPrjParams[6],
     567             :                                   padfPrjParams[3], padfPrjParams[4]);
     568             :     }
     569           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "PolyConic"))
     570             :     {
     571             :         // skip scale factor
     572           0 :         m_oSRS.SetProjCS("PolyConic");
     573           0 :         m_oSRS.SetPolyconic(padfPrjParams[5], padfPrjParams[6],
     574             :                             padfPrjParams[3], padfPrjParams[4]);
     575             :     }
     576           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Robinson"))
     577             :     {
     578           0 :         m_oSRS.SetProjCS("Robinson");
     579           0 :         m_oSRS.SetRobinson(padfPrjParams[6], padfPrjParams[3],
     580             :                            padfPrjParams[4]);
     581             :     }
     582           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Sinusoidal"))
     583             :     {
     584           0 :         m_oSRS.SetProjCS("Sinusoidal");
     585           0 :         m_oSRS.SetSinusoidal(padfPrjParams[6], padfPrjParams[3],
     586             :                              padfPrjParams[4]);
     587             :     }
     588           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Stereographic"))
     589             :     {
     590           0 :         m_oSRS.SetProjCS("Stereographic");
     591           0 :         m_oSRS.SetStereographic(padfPrjParams[5], padfPrjParams[6],
     592             :                                 padfPrjParams[9], padfPrjParams[3],
     593             :                                 padfPrjParams[4]);
     594             :     }
     595           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "Transverse Mercator"))
     596             :     {
     597           0 :         m_oSRS.SetProjCS("Transverse Mercator");
     598           0 :         m_oSRS.SetStereographic(padfPrjParams[5], padfPrjParams[6],
     599             :                                 padfPrjParams[9], padfPrjParams[3],
     600             :                                 padfPrjParams[4]);
     601             :     }
     602           5 :     else if (STARTS_WITH_CI(pszProj.c_str(), "UTM"))
     603             :     {
     604             :         std::string pszNH =
     605          15 :             ReadElement("Projection", "Northern Hemisphere", csyFileName);
     606           5 :         m_oSRS.SetProjCS("UTM");
     607           5 :         if (STARTS_WITH_CI(pszNH.c_str(), "Yes"))
     608           4 :             m_oSRS.SetUTM((int)padfPrjParams[11], 1);
     609             :         else
     610           1 :             m_oSRS.SetUTM((int)padfPrjParams[11], 0);
     611             :     }
     612           0 :     else if (STARTS_WITH_CI(pszProj.c_str(), "VanderGrinten"))
     613             :     {
     614           0 :         m_oSRS.SetVDG(padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
     615             :     }
     616           0 :     else if (STARTS_WITH_CI(pszProj.c_str(), "GeoStationary Satellite"))
     617             :     {
     618           0 :         m_oSRS.SetGEOS(padfPrjParams[6], padfPrjParams[12], padfPrjParams[3],
     619             :                        padfPrjParams[4]);
     620             :     }
     621           0 :     else if (STARTS_WITH_CI(pszProj.c_str(), "MSG Perspective"))
     622             :     {
     623           0 :         m_oSRS.SetGEOS(padfPrjParams[6], padfPrjParams[12], padfPrjParams[3],
     624             :                        padfPrjParams[4]);
     625             :     }
     626             :     else
     627             :     {
     628           0 :         m_oSRS.SetLocalCS(pszProj.c_str());
     629             :     }
     630             :     /* -------------------------------------------------------------------- */
     631             :     /*      Try to translate the datum/spheroid.                            */
     632             :     /* -------------------------------------------------------------------- */
     633             : 
     634           5 :     if (!m_oSRS.IsLocal())
     635             :     {
     636           5 :         const IlwisDatums *piwDatum = iwDatums;
     637             : 
     638             :         // Search for matching datum
     639         222 :         while (piwDatum->pszIlwisDatum)
     640             :         {
     641         222 :             if (EQUALN(pszDatum.c_str(), piwDatum->pszIlwisDatum,
     642             :                        strlen(piwDatum->pszIlwisDatum)))
     643             :             {
     644          10 :                 OGRSpatialReference oOGR;
     645           5 :                 oOGR.importFromEPSG(piwDatum->nEPSGCode);
     646           5 :                 m_oSRS.CopyGeogCSFrom(&oOGR);
     647           5 :                 break;
     648             :             }
     649         217 :             piwDatum++;
     650             :         }  // End of searching for matching datum.
     651             : 
     652             :         /* --------------------------------------------------------------------
     653             :          */
     654             :         /*      If no matching for datum definition, fetch info about an */
     655             :         /*      ellipsoid.  semi major axis is always returned in meters */
     656             :         /* --------------------------------------------------------------------
     657             :          */
     658           5 :         const IlwisEllips *piwEllips = iwEllips;
     659           5 :         if (pszEllips.empty())
     660           1 :             pszEllips = "Sphere";
     661           5 :         if (!piwDatum->pszIlwisDatum)
     662             :         {
     663           0 :             while (piwEllips->pszIlwisEllips)
     664             :             {
     665           0 :                 if (EQUALN(pszEllips.c_str(), piwEllips->pszIlwisEllips,
     666             :                            strlen(piwEllips->pszIlwisEllips)))
     667             :                 {
     668           0 :                     double dfSemiMajor = piwEllips->semiMajor;
     669           0 :                     if (STARTS_WITH_CI(pszEllips.c_str(), "Sphere") &&
     670           0 :                         padfPrjParams[0] != 0)
     671             :                     {
     672           0 :                         dfSemiMajor = padfPrjParams[0];
     673             :                     }
     674           0 :                     m_oSRS.SetGeogCS(
     675             :                         CPLSPrintf("Unknown datum based upon the %s ellipsoid",
     676           0 :                                    piwEllips->pszIlwisEllips),
     677             :                         CPLSPrintf("Not specified (based on %s spheroid)",
     678           0 :                                    piwEllips->pszIlwisEllips),
     679           0 :                         piwEllips->pszIlwisEllips, dfSemiMajor,
     680           0 :                         piwEllips->invFlattening, nullptr, 0.0, nullptr, 0.0);
     681           0 :                     m_oSRS.SetAuthority("SPHEROID", "EPSG",
     682           0 :                                         piwEllips->nEPSGCode);
     683             : 
     684           0 :                     break;
     685             :                 }
     686           0 :                 piwEllips++;
     687             :             }  // end of searching for matching ellipsoid
     688             :         }
     689             : 
     690             :         /* --------------------------------------------------------------------
     691             :          */
     692             :         /*      If no matching for ellipsoid definition, fetch info about an */
     693             :         /*      user defined ellipsoid. If cannot find, default to WGS 84 */
     694             :         /* --------------------------------------------------------------------
     695             :          */
     696           5 :         if (!piwEllips->pszIlwisEllips)
     697             :         {
     698             : 
     699           0 :             if (STARTS_WITH_CI(pszEllips.c_str(), "User Defined"))
     700             :             {
     701           0 :                 m_oSRS.SetGeogCS(
     702             :                     "Unknown datum based upon the custom ellipsoid",
     703             :                     "Not specified (based on custom ellipsoid)",
     704             :                     "Custom ellipsoid", padfPrjParams[0], padfPrjParams[2],
     705             :                     nullptr, 0, nullptr, 0);
     706             :             }
     707             :             else
     708             :             {
     709             :                 // if cannot find the user defined ellips, default to WGS84
     710           0 :                 m_oSRS.SetWellKnownGeogCS("WGS84");
     711             :             }
     712             :         }
     713             :     }  // end of if ( !IsLocal() )
     714             : 
     715             :     /* -------------------------------------------------------------------- */
     716             :     /*      Units translation                                          */
     717             :     /* -------------------------------------------------------------------- */
     718           5 :     if (m_oSRS.IsLocal() || m_oSRS.IsProjected())
     719             :     {
     720           5 :         m_oSRS.SetLinearUnits(SRS_UL_METER, 1.0);
     721             :     }
     722             : 
     723          10 :     return CE_None;
     724             : }
     725             : 
     726           0 : static void WriteFalseEastNorth(const std::string &csFileName,
     727             :                                 const OGRSpatialReference &oSRS)
     728             : {
     729           0 :     WriteElement("Projection", ILW_False_Easting, csFileName,
     730             :                  oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0));
     731           0 :     WriteElement("Projection", ILW_False_Northing, csFileName,
     732             :                  oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
     733           0 : }
     734             : 
     735           0 : static void WriteProjectionName(const std::string &csFileName,
     736             :                                 const std::string &stProjection)
     737             : {
     738           0 :     WriteElement("CoordSystem", "Type", csFileName, "Projection");
     739           0 :     WriteElement("CoordSystem", "Projection", csFileName, stProjection);
     740           0 : }
     741             : 
     742           2 : static void WriteUTM(const std::string &csFileName,
     743             :                      const OGRSpatialReference &oSRS)
     744             : {
     745             :     int bNorth;
     746             : 
     747           2 :     int nZone = oSRS.GetUTMZone(&bNorth);
     748           2 :     WriteElement("CoordSystem", "Type", csFileName, "Projection");
     749           2 :     WriteElement("CoordSystem", "Projection", csFileName, "UTM");
     750           2 :     if (bNorth)
     751           2 :         WriteElement("Projection", "Northern Hemisphere", csFileName, "Yes");
     752             :     else
     753           0 :         WriteElement("Projection", "Northern Hemisphere", csFileName, "No");
     754           2 :     WriteElement("Projection", "Zone", csFileName, nZone);
     755           2 : }
     756             : 
     757           0 : static void WriteAlbersConicEqualArea(const std::string &csFileName,
     758             :                                       const OGRSpatialReference &oSRS)
     759             : {
     760           0 :     WriteProjectionName(csFileName, "Albers EqualArea Conic");
     761           0 :     WriteFalseEastNorth(csFileName, oSRS);
     762           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     763             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     764           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     765             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     766           0 :     WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
     767             :                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
     768           0 :     WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
     769             :                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
     770           0 : }
     771             : 
     772           0 : static void WriteAzimuthalEquidistant(const std::string &csFileName,
     773             :                                       const OGRSpatialReference &oSRS)
     774             : {
     775           0 :     WriteProjectionName(csFileName, "Azimuthal Equidistant");
     776           0 :     WriteFalseEastNorth(csFileName, oSRS);
     777           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     778             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     779           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     780             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     781           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
     782           0 : }
     783             : 
     784           0 : static void WriteCylindricalEqualArea(const std::string &csFileName,
     785             :                                       const OGRSpatialReference &oSRS)
     786             : {
     787           0 :     WriteProjectionName(csFileName, "Central Cylindrical");
     788           0 :     WriteFalseEastNorth(csFileName, oSRS);
     789           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     790             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     791           0 : }
     792             : 
     793           0 : static void WriteCassiniSoldner(const std::string &csFileName,
     794             :                                 const OGRSpatialReference &oSRS)
     795             : {
     796           0 :     WriteProjectionName(csFileName, "Cassini");
     797           0 :     WriteFalseEastNorth(csFileName, oSRS);
     798           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     799             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     800           0 :     WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
     801             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     802           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
     803           0 : }
     804             : 
     805           0 : static void WriteStereographic(const std::string &csFileName,
     806             :                                const OGRSpatialReference &oSRS)
     807             : {
     808           0 :     WriteProjectionName(csFileName, "Stereographic");
     809           0 :     WriteFalseEastNorth(csFileName, oSRS);
     810           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     811             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     812           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     813             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     814           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName,
     815             :                  oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
     816           0 : }
     817             : 
     818           0 : static void WriteEquidistantConic(const std::string &csFileName,
     819             :                                   const OGRSpatialReference &oSRS)
     820             : {
     821           0 :     WriteProjectionName(csFileName, "Equidistant Conic");
     822           0 :     WriteFalseEastNorth(csFileName, oSRS);
     823           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     824             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     825           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     826             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     827           0 :     WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
     828             :                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
     829           0 :     WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
     830             :                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
     831           0 : }
     832             : 
     833           0 : static void WriteTransverseMercator(const std::string &csFileName,
     834             :                                     const OGRSpatialReference &oSRS)
     835             : {
     836           0 :     WriteProjectionName(csFileName, "Transverse Mercator");
     837           0 :     WriteFalseEastNorth(csFileName, oSRS);
     838           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     839             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     840           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     841             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     842           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName,
     843             :                  oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
     844           0 : }
     845             : 
     846           0 : static void WriteGnomonic(const std::string &csFileName,
     847             :                           const OGRSpatialReference &oSRS)
     848             : {
     849           0 :     WriteProjectionName(csFileName, "Gnomonic");
     850           0 :     WriteFalseEastNorth(csFileName, oSRS);
     851           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     852             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     853           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     854             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     855           0 : }
     856             : 
     857           0 : static void WriteLambertConformalConic(const std::string &csFileName,
     858             :                                        const OGRSpatialReference &oSRS)
     859             : {
     860           0 :     WriteProjectionName(csFileName, "Lambert Conformal Conic");
     861           0 :     WriteFalseEastNorth(csFileName, oSRS);
     862           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     863             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     864           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     865             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     866           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
     867           0 : }
     868             : 
     869           0 : static void WriteLambertConformalConic2SP(const std::string &csFileName,
     870             :                                           const OGRSpatialReference &oSRS)
     871             : {
     872           0 :     WriteProjectionName(csFileName, "Lambert Conformal Conic");
     873           0 :     WriteFalseEastNorth(csFileName, oSRS);
     874           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     875             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     876           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     877             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     878           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
     879           0 :     WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
     880             :                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
     881           0 :     WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
     882             :                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
     883           0 : }
     884             : 
     885           0 : static void WriteLambertAzimuthalEqualArea(const std::string &csFileName,
     886             :                                            const OGRSpatialReference &oSRS)
     887             : {
     888           0 :     WriteProjectionName(csFileName, "Lambert Azimuthal EqualArea");
     889           0 :     WriteFalseEastNorth(csFileName, oSRS);
     890           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     891             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     892           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     893             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     894           0 : }
     895             : 
     896           0 : static void WriteMercator_1SP(const std::string &csFileName,
     897             :                               const OGRSpatialReference &oSRS)
     898             : {
     899           0 :     WriteProjectionName(csFileName, "Mercator");
     900           0 :     WriteFalseEastNorth(csFileName, oSRS);
     901           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     902             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     903           0 :     WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
     904             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     905           0 : }
     906             : 
     907           0 : static void WriteMillerCylindrical(const std::string &csFileName,
     908             :                                    const OGRSpatialReference &oSRS)
     909             : {
     910           0 :     WriteProjectionName(csFileName, "Miller");
     911           0 :     WriteFalseEastNorth(csFileName, oSRS);
     912           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     913             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     914           0 : }
     915             : 
     916           0 : static void WriteMolleweide(const std::string &csFileName,
     917             :                             const OGRSpatialReference &oSRS)
     918             : {
     919           0 :     WriteProjectionName(csFileName, "Mollweide");
     920           0 :     WriteFalseEastNorth(csFileName, oSRS);
     921           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     922             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     923           0 : }
     924             : 
     925           0 : static void WriteOrthographic(const std::string &csFileName,
     926             :                               const OGRSpatialReference &oSRS)
     927             : {
     928           0 :     WriteProjectionName(csFileName, "Orthographic");
     929           0 :     WriteFalseEastNorth(csFileName, oSRS);
     930           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     931             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     932           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     933             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     934           0 : }
     935             : 
     936           0 : static void WritePlateRectangle(const std::string &csFileName,
     937             :                                 const OGRSpatialReference &oSRS)
     938             : {
     939           0 :     WriteProjectionName(csFileName, "Plate Rectangle");
     940           0 :     WriteFalseEastNorth(csFileName, oSRS);
     941           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     942             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     943           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     944             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     945           0 :     WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
     946             :                  "0.0000000000");
     947           0 : }
     948             : 
     949           0 : static void WritePolyConic(const std::string &csFileName,
     950             :                            const OGRSpatialReference &oSRS)
     951             : {
     952           0 :     WriteProjectionName(csFileName, "PolyConic");
     953           0 :     WriteFalseEastNorth(csFileName, oSRS);
     954           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     955             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     956           0 :     WriteElement("Projection", ILW_Central_Parallel, csFileName,
     957             :                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     958           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
     959           0 : }
     960             : 
     961           0 : static void WriteRobinson(const std::string &csFileName,
     962             :                           const OGRSpatialReference &oSRS)
     963             : {
     964           0 :     WriteProjectionName(csFileName, "Robinson");
     965           0 :     WriteFalseEastNorth(csFileName, oSRS);
     966           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     967             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     968           0 : }
     969             : 
     970           0 : static void WriteSinusoidal(const std::string &csFileName,
     971             :                             const OGRSpatialReference &oSRS)
     972             : {
     973           0 :     WriteProjectionName(csFileName, "Sinusoidal");
     974           0 :     WriteFalseEastNorth(csFileName, oSRS);
     975           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     976             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     977           0 : }
     978             : 
     979           0 : static void WriteVanderGrinten(const std::string &csFileName,
     980             :                                const OGRSpatialReference &oSRS)
     981             : {
     982           0 :     WriteProjectionName(csFileName, "VanderGrinten");
     983           0 :     WriteFalseEastNorth(csFileName, oSRS);
     984           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     985             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     986           0 : }
     987             : 
     988           0 : static void WriteGeoStatSat(const std::string &csFileName,
     989             :                             const OGRSpatialReference &oSRS)
     990             : {
     991           0 :     WriteProjectionName(csFileName, "GeoStationary Satellite");
     992           0 :     WriteFalseEastNorth(csFileName, oSRS);
     993           0 :     WriteElement("Projection", ILW_Central_Meridian, csFileName,
     994             :                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     995           0 :     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
     996           0 :     WriteElement("Projection", ILW_Height_Persp_Center, csFileName,
     997             :                  oSRS.GetNormProjParm(SRS_PP_SATELLITE_HEIGHT, 35785831.0));
     998           0 : }
     999             : 
    1000             : /************************************************************************/
    1001             : /*                          WriteProjection()                           */
    1002             : /************************************************************************/
    1003             : /**
    1004             :  * Export coordinate system in ILWIS projection definition.
    1005             :  *
    1006             :  * Converts the loaded coordinate reference system into ILWIS projection
    1007             :  * definition to the extent possible.
    1008             :  */
    1009          31 : CPLErr ILWISDataset::WriteProjection()
    1010             : 
    1011             : {
    1012          31 :     OGRSpatialReference *poGeogSRS = nullptr;
    1013             : 
    1014          62 :     std::string csFileName = CPLResetExtension(osFileName, "csy");
    1015          62 :     std::string pszBaseName = std::string(CPLGetBasename(osFileName));
    1016             :     // std::string pszPath = std::string(CPLGetPath( osFileName ));
    1017          31 :     const bool bHaveSRS = !m_oSRS.IsEmpty();
    1018             : 
    1019          31 :     const IlwisDatums *piwDatum = iwDatums;
    1020             :     // std::string pszEllips;
    1021          62 :     std::string osDatum;
    1022             :     // std::string pszProj;
    1023             : 
    1024             :     /* -------------------------------------------------------------------- */
    1025             :     /*      Collect datum/ellips information. */
    1026             :     /* -------------------------------------------------------------------- */
    1027          31 :     if (bHaveSRS)
    1028             :     {
    1029          31 :         poGeogSRS = m_oSRS.CloneGeogCS();
    1030             :     }
    1031             : 
    1032          62 :     std::string grFileName = CPLResetExtension(osFileName, "grf");
    1033          31 :     std::string csy;
    1034          31 :     if (poGeogSRS)
    1035             :     {
    1036          31 :         csy = pszBaseName + ".csy";
    1037             : 
    1038          31 :         WriteElement("Ilwis", "Type", csFileName, "CoordSystem");
    1039          31 :         const char *pszDatum = poGeogSRS->GetAttrValue("GEOGCS|DATUM");
    1040          31 :         if (pszDatum)
    1041          31 :             osDatum = pszDatum;
    1042             : 
    1043             :         /* WKT to ILWIS translation */
    1044        2058 :         while (piwDatum->pszWKTDatum)
    1045             :         {
    1046        2058 :             if (EQUALN(osDatum.c_str(), piwDatum->pszWKTDatum,
    1047             :                        strlen(piwDatum->pszWKTDatum)))
    1048             :             {
    1049          62 :                 WriteElement("CoordSystem", "Datum", csFileName,
    1050          31 :                              piwDatum->pszIlwisDatum);
    1051          31 :                 break;
    1052             :             }
    1053        2027 :             piwDatum++;
    1054             :         }  // End of searching for matching datum.
    1055          31 :         WriteElement("CoordSystem", "Width", csFileName, 28);
    1056             :         // pszEllips = poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
    1057          31 :         double a = poGeogSRS->GetSemiMajor();
    1058          31 :         /* b = */ poGeogSRS->GetSemiMinor();
    1059          31 :         double f = poGeogSRS->GetInvFlattening();
    1060          31 :         WriteElement("CoordSystem", "Ellipsoid", csFileName, "User Defined");
    1061          31 :         WriteElement("Ellipsoid", "a", csFileName, a);
    1062          31 :         WriteElement("Ellipsoid", "1/f", csFileName, f);
    1063             :     }
    1064             :     else
    1065           0 :         csy = "unknown.csy";
    1066             : 
    1067             :     /* -------------------------------------------------------------------- */
    1068             :     /*  Determine to write a geo-referencing file for the dataset to create */
    1069             :     /* -------------------------------------------------------------------- */
    1070          31 :     if (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0 ||
    1071           0 :         adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0 ||
    1072           0 :         adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0)
    1073          31 :         WriteElement("GeoRef", "CoordSystem", grFileName, csy);
    1074             : 
    1075             :     /* -------------------------------------------------------------------- */
    1076             :     /*  Recognise various projections.                                      */
    1077             :     /* -------------------------------------------------------------------- */
    1078          31 :     const char *pszProjName = nullptr;
    1079             : 
    1080          31 :     if (bHaveSRS)
    1081          31 :         pszProjName = m_oSRS.GetAttrValue("PROJCS|PROJECTION");
    1082             : 
    1083          31 :     if (pszProjName == nullptr)
    1084             :     {
    1085          29 :         if (bHaveSRS && m_oSRS.IsGeographic())
    1086             :         {
    1087          29 :             WriteElement("CoordSystem", "Type", csFileName, "LatLon");
    1088             :         }
    1089             :     }
    1090           2 :     else if (m_oSRS.GetUTMZone(nullptr) != 0)
    1091             :     {
    1092           2 :         WriteUTM(csFileName, m_oSRS);
    1093             :     }
    1094           0 :     else if (EQUAL(pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA))
    1095             :     {
    1096           0 :         WriteAlbersConicEqualArea(csFileName, m_oSRS);
    1097             :     }
    1098           0 :     else if (EQUAL(pszProjName, SRS_PT_AZIMUTHAL_EQUIDISTANT))
    1099             :     {
    1100           0 :         WriteAzimuthalEquidistant(csFileName, m_oSRS);
    1101             :     }
    1102           0 :     else if (EQUAL(pszProjName, SRS_PT_CYLINDRICAL_EQUAL_AREA))
    1103             :     {
    1104           0 :         WriteCylindricalEqualArea(csFileName, m_oSRS);
    1105             :     }
    1106           0 :     else if (EQUAL(pszProjName, SRS_PT_CASSINI_SOLDNER))
    1107             :     {
    1108           0 :         WriteCassiniSoldner(csFileName, m_oSRS);
    1109             :     }
    1110           0 :     else if (EQUAL(pszProjName, SRS_PT_STEREOGRAPHIC))
    1111             :     {
    1112           0 :         WriteStereographic(csFileName, m_oSRS);
    1113             :     }
    1114           0 :     else if (EQUAL(pszProjName, SRS_PT_EQUIDISTANT_CONIC))
    1115             :     {
    1116           0 :         WriteEquidistantConic(csFileName, m_oSRS);
    1117             :     }
    1118           0 :     else if (EQUAL(pszProjName, SRS_PT_TRANSVERSE_MERCATOR))
    1119             :     {
    1120           0 :         WriteTransverseMercator(csFileName, m_oSRS);
    1121             :     }
    1122           0 :     else if (EQUAL(pszProjName, SRS_PT_GNOMONIC))
    1123             :     {
    1124           0 :         WriteGnomonic(csFileName, m_oSRS);
    1125             :     }
    1126           0 :     else if (EQUAL(pszProjName, "Lambert_Conformal_Conic"))
    1127             :     {
    1128           0 :         WriteLambertConformalConic(csFileName, m_oSRS);
    1129             :     }
    1130           0 :     else if (EQUAL(pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP))
    1131             :     {
    1132           0 :         WriteLambertConformalConic(csFileName, m_oSRS);
    1133             :     }
    1134           0 :     else if (EQUAL(pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
    1135             :     {
    1136           0 :         WriteLambertConformalConic2SP(csFileName, m_oSRS);
    1137             :     }
    1138           0 :     else if (EQUAL(pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
    1139             :     {
    1140           0 :         WriteLambertAzimuthalEqualArea(csFileName, m_oSRS);
    1141             :     }
    1142           0 :     else if (EQUAL(pszProjName, SRS_PT_MERCATOR_1SP))
    1143             :     {
    1144           0 :         WriteMercator_1SP(csFileName, m_oSRS);
    1145             :     }
    1146           0 :     else if (EQUAL(pszProjName, SRS_PT_MILLER_CYLINDRICAL))
    1147             :     {
    1148           0 :         WriteMillerCylindrical(csFileName, m_oSRS);
    1149             :     }
    1150           0 :     else if (EQUAL(pszProjName, SRS_PT_MOLLWEIDE))
    1151             :     {
    1152           0 :         WriteMolleweide(csFileName, m_oSRS);
    1153             :     }
    1154           0 :     else if (EQUAL(pszProjName, SRS_PT_ORTHOGRAPHIC))
    1155             :     {
    1156           0 :         WriteOrthographic(csFileName, m_oSRS);
    1157             :     }
    1158           0 :     else if (EQUAL(pszProjName, SRS_PT_EQUIRECTANGULAR))
    1159             :     {
    1160           0 :         WritePlateRectangle(csFileName, m_oSRS);
    1161             :     }
    1162           0 :     else if (EQUAL(pszProjName, SRS_PT_POLYCONIC))
    1163             :     {
    1164           0 :         WritePolyConic(csFileName, m_oSRS);
    1165             :     }
    1166           0 :     else if (EQUAL(pszProjName, SRS_PT_ROBINSON))
    1167             :     {
    1168           0 :         WriteRobinson(csFileName, m_oSRS);
    1169             :     }
    1170           0 :     else if (EQUAL(pszProjName, SRS_PT_SINUSOIDAL))
    1171             :     {
    1172           0 :         WriteSinusoidal(csFileName, m_oSRS);
    1173             :     }
    1174           0 :     else if (EQUAL(pszProjName, SRS_PT_VANDERGRINTEN))
    1175             :     {
    1176           0 :         WriteVanderGrinten(csFileName, m_oSRS);
    1177             :     }
    1178           0 :     else if (EQUAL(pszProjName, SRS_PT_GEOSTATIONARY_SATELLITE))
    1179             :     {
    1180           0 :         WriteGeoStatSat(csFileName, m_oSRS);
    1181             :     }
    1182             :     else
    1183             :     {
    1184             :         // Projection unknown by ILWIS
    1185             :     }
    1186             : 
    1187             :     /* -------------------------------------------------------------------- */
    1188             :     /*      Cleanup                                                         */
    1189             :     /* -------------------------------------------------------------------- */
    1190          31 :     if (poGeogSRS != nullptr)
    1191          31 :         delete poGeogSRS;
    1192             : 
    1193          62 :     return CE_None;
    1194             : }
    1195             : 
    1196             : }  // namespace GDAL

Generated by: LCOV version 1.14