LCOV - code coverage report
Current view: top level - ogr - ogr_srs_ozi.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 60 173 34.7 %
Date: 2024-05-04 12:52:34 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  OGRSpatialReference translation from OziExplorer
       5             :  *           georeferencing information.
       6             :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2009, Andrey Kiselev <dron@ak4719.spb.edu>
      10             :  * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * Permission is hereby granted, free of charge, to any person obtaining a
      13             :  * copy of this software and associated documentation files (the "Software"),
      14             :  * to deal in the Software without restriction, including without limitation
      15             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16             :  * and/or sell copies of the Software, and to permit persons to whom the
      17             :  * Software is furnished to do so, subject to the following conditions:
      18             :  *
      19             :  * The above copyright notice and this permission notice shall be included
      20             :  * in all copies or substantial portions of the Software.
      21             :  *
      22             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28             :  * DEALINGS IN THE SOFTWARE.
      29             :  ****************************************************************************/
      30             : 
      31             : #include "cpl_port.h"
      32             : #include "ogr_spatialref.h"
      33             : 
      34             : #include <cstdlib>
      35             : #include <cstring>
      36             : 
      37             : #include "cpl_conv.h"
      38             : #include "cpl_csv.h"
      39             : #include "cpl_error.h"
      40             : #include "cpl_string.h"
      41             : #include "ogr_core.h"
      42             : #include "ogr_srs_api.h"
      43             : 
      44             : /************************************************************************/
      45             : /*                          OSRImportFromOzi()                          */
      46             : /************************************************************************/
      47             : 
      48             : /**
      49             :  * Import coordinate system from OziExplorer projection definition.
      50             :  *
      51             :  * This function will import projection definition in style, used by
      52             :  * OziExplorer software.
      53             :  *
      54             :  * Note: another version of this function with a different signature existed
      55             :  * in GDAL 1.X.
      56             :  *
      57             :  * @param hSRS spatial reference object.
      58             :  * @param papszLines Map file lines. This is an array of strings containing
      59             :  * the whole OziExplorer .MAP file. The array is terminated by a NULL pointer.
      60             :  *
      61             :  * @return OGRERR_NONE on success or an error code in case of failure.
      62             :  *
      63             :  * @since OGR 2.0
      64             :  */
      65             : 
      66           3 : OGRErr OSRImportFromOzi(OGRSpatialReferenceH hSRS,
      67             :                         const char *const *papszLines)
      68             : 
      69             : {
      70           3 :     VALIDATE_POINTER1(hSRS, "OSRImportFromOzi", OGRERR_FAILURE);
      71             : 
      72           3 :     return OGRSpatialReference::FromHandle(hSRS)->importFromOzi(papszLines);
      73             : }
      74             : 
      75             : /************************************************************************/
      76             : /*                            importFromOzi()                           */
      77             : /************************************************************************/
      78             : 
      79             : /**
      80             :  * Import coordinate system from OziExplorer projection definition.
      81             :  *
      82             :  * This method will import projection definition in style, used by
      83             :  * OziExplorer software.
      84             :  *
      85             :  * @param papszLines Map file lines. This is an array of strings containing
      86             :  * the whole OziExplorer .MAP file. The array is terminated by a NULL pointer.
      87             :  *
      88             :  * @return OGRERR_NONE on success or an error code in case of failure.
      89             :  *
      90             :  * @since OGR 1.10
      91             :  */
      92             : 
      93           3 : OGRErr OGRSpatialReference::importFromOzi(const char *const *papszLines)
      94             : {
      95             :     const char *pszDatum;
      96           3 :     const char *pszProj = nullptr;
      97           3 :     const char *pszProjParams = nullptr;
      98             : 
      99           3 :     Clear();
     100             : 
     101           3 :     const int nLines = CSLCount(papszLines);
     102           3 :     if (nLines < 5)
     103           0 :         return OGRERR_NOT_ENOUGH_DATA;
     104             : 
     105           3 :     pszDatum = papszLines[4];
     106             : 
     107           9 :     for (int iLine = 5; iLine < nLines; iLine++)
     108             :     {
     109           6 :         if (STARTS_WITH_CI(papszLines[iLine], "Map Projection"))
     110             :         {
     111           3 :             pszProj = papszLines[iLine];
     112             :         }
     113           3 :         else if (STARTS_WITH_CI(papszLines[iLine], "Projection Setup"))
     114             :         {
     115           3 :             pszProjParams = papszLines[iLine];
     116             :         }
     117             :     }
     118             : 
     119           3 :     if (!(pszDatum && pszProj && pszProjParams))
     120           0 :         return OGRERR_NOT_ENOUGH_DATA;
     121             : 
     122             :     /* -------------------------------------------------------------------- */
     123             :     /*      Operate on the basis of the projection name.                    */
     124             :     /* -------------------------------------------------------------------- */
     125           3 :     char **papszProj = CSLTokenizeStringComplex(pszProj, ",", TRUE, TRUE);
     126             :     char **papszProjParams =
     127           3 :         CSLTokenizeStringComplex(pszProjParams, ",", TRUE, TRUE);
     128           3 :     char **papszDatum = nullptr;
     129             : 
     130           3 :     if (CSLCount(papszProj) < 2)
     131             :     {
     132           0 :         goto not_enough_data;
     133             :     }
     134             : 
     135           3 :     if (STARTS_WITH_CI(papszProj[1], "Latitude/Longitude"))
     136             :     {
     137             :         // Do nothing.
     138             :     }
     139           1 :     else if (STARTS_WITH_CI(papszProj[1], "Mercator"))
     140             :     {
     141           0 :         if (CSLCount(papszProjParams) < 6)
     142           0 :             goto not_enough_data;
     143           0 :         double dfScale = CPLAtof(papszProjParams[3]);
     144             :         // If unset, default to scale = 1.
     145           0 :         if (papszProjParams[3][0] == 0)
     146           0 :             dfScale = 1;
     147           0 :         SetMercator(CPLAtof(papszProjParams[1]), CPLAtof(papszProjParams[2]),
     148           0 :                     dfScale, CPLAtof(papszProjParams[4]),
     149           0 :                     CPLAtof(papszProjParams[5]));
     150             :     }
     151           1 :     else if (STARTS_WITH_CI(papszProj[1], "Transverse Mercator"))
     152             :     {
     153           0 :         if (CSLCount(papszProjParams) < 6)
     154           0 :             goto not_enough_data;
     155           0 :         SetTM(CPLAtof(papszProjParams[1]), CPLAtof(papszProjParams[2]),
     156           0 :               CPLAtof(papszProjParams[3]), CPLAtof(papszProjParams[4]),
     157           0 :               CPLAtof(papszProjParams[5]));
     158             :     }
     159           1 :     else if (STARTS_WITH_CI(papszProj[1], "Lambert Conformal Conic"))
     160             :     {
     161           1 :         if (CSLCount(papszProjParams) < 8)
     162           0 :             goto not_enough_data;
     163           1 :         SetLCC(CPLAtof(papszProjParams[6]), CPLAtof(papszProjParams[7]),
     164           1 :                CPLAtof(papszProjParams[1]), CPLAtof(papszProjParams[2]),
     165           1 :                CPLAtof(papszProjParams[4]), CPLAtof(papszProjParams[5]));
     166             :     }
     167           0 :     else if (STARTS_WITH_CI(papszProj[1], "Sinusoidal"))
     168             :     {
     169           0 :         if (CSLCount(papszProjParams) < 6)
     170           0 :             goto not_enough_data;
     171           0 :         SetSinusoidal(CPLAtof(papszProjParams[2]), CPLAtof(papszProjParams[4]),
     172           0 :                       CPLAtof(papszProjParams[5]));
     173             :     }
     174           0 :     else if (STARTS_WITH_CI(papszProj[1], "Albers Equal Area"))
     175             :     {
     176           0 :         if (CSLCount(papszProjParams) < 8)
     177           0 :             goto not_enough_data;
     178           0 :         SetACEA(CPLAtof(papszProjParams[6]), CPLAtof(papszProjParams[7]),
     179           0 :                 CPLAtof(papszProjParams[1]), CPLAtof(papszProjParams[2]),
     180           0 :                 CPLAtof(papszProjParams[4]), CPLAtof(papszProjParams[5]));
     181             :     }
     182           0 :     else if (STARTS_WITH_CI(papszProj[1],
     183           0 :                             "(UTM) Universal Transverse Mercator") &&
     184             :              nLines > 5)
     185             :     {
     186             :         // Look for the UTM zone in the calibration point data.
     187           0 :         int iLine = 5;  // Used after for.
     188           0 :         for (; iLine < nLines; iLine++)
     189             :         {
     190           0 :             if (STARTS_WITH_CI(papszLines[iLine], "Point"))
     191             :             {
     192           0 :                 char **papszTok = CSLTokenizeString2(papszLines[iLine], ",",
     193             :                                                      CSLT_ALLOWEMPTYTOKENS |
     194             :                                                          CSLT_STRIPLEADSPACES |
     195             :                                                          CSLT_STRIPENDSPACES);
     196           0 :                 if (CSLCount(papszTok) < 17 || EQUAL(papszTok[2], "") ||
     197           0 :                     EQUAL(papszTok[13], "") || EQUAL(papszTok[14], "") ||
     198           0 :                     EQUAL(papszTok[15], "") || EQUAL(papszTok[16], ""))
     199             :                 {
     200           0 :                     CSLDestroy(papszTok);
     201           0 :                     continue;
     202             :                 }
     203           0 :                 SetUTM(atoi(papszTok[13]), EQUAL(papszTok[16], "N"));
     204           0 :                 CSLDestroy(papszTok);
     205           0 :                 break;
     206             :             }
     207             :         }
     208           0 :         if (iLine == nLines)  // Try to guess the UTM zone.
     209             :         {
     210           0 :             float fMinLongitude = 1000.0f;
     211           0 :             float fMaxLongitude = -1000.0f;
     212           0 :             float fMinLatitude = 1000.0f;
     213           0 :             float fMaxLatitude = -1000.0f;
     214           0 :             bool bFoundMMPLL = false;
     215           0 :             for (iLine = 5; iLine < nLines; iLine++)
     216             :             {
     217           0 :                 if (STARTS_WITH_CI(papszLines[iLine], "MMPLL"))
     218             :                 {
     219           0 :                     char **papszTok = CSLTokenizeString2(
     220           0 :                         papszLines[iLine], ",",
     221             :                         CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES |
     222             :                             CSLT_STRIPENDSPACES);
     223           0 :                     if (CSLCount(papszTok) < 4)
     224             :                     {
     225           0 :                         CSLDestroy(papszTok);
     226           0 :                         continue;
     227             :                     }
     228             :                     const float fLongitude =
     229           0 :                         static_cast<float>(CPLAtofM(papszTok[2]));
     230             :                     const float fLatitude =
     231           0 :                         static_cast<float>(CPLAtofM(papszTok[3]));
     232           0 :                     CSLDestroy(papszTok);
     233             : 
     234           0 :                     bFoundMMPLL = true;
     235             : 
     236           0 :                     if (fMinLongitude > fLongitude)
     237           0 :                         fMinLongitude = fLongitude;
     238           0 :                     if (fMaxLongitude < fLongitude)
     239           0 :                         fMaxLongitude = fLongitude;
     240           0 :                     if (fMinLatitude > fLatitude)
     241           0 :                         fMinLatitude = fLatitude;
     242           0 :                     if (fMaxLatitude < fLatitude)
     243           0 :                         fMaxLatitude = fLatitude;
     244             :                 }
     245             :             }
     246           0 :             const float fMedianLatitude = (fMinLatitude + fMaxLatitude) / 2;
     247           0 :             const float fMedianLongitude = (fMinLongitude + fMaxLongitude) / 2;
     248           0 :             if (bFoundMMPLL && fMaxLatitude <= 90)
     249             :             {
     250           0 :                 int nUtmZone = 0;
     251           0 :                 if (fMedianLatitude >= 56 && fMedianLatitude <= 64 &&
     252           0 :                     fMedianLongitude >= 3 && fMedianLongitude <= 12)
     253           0 :                     nUtmZone = 32;  // Norway exception.
     254           0 :                 else if (fMedianLatitude >= 72 && fMedianLatitude <= 84 &&
     255           0 :                          fMedianLongitude >= 0 && fMedianLongitude <= 42)
     256             :                     // Svalbard exception.
     257           0 :                     nUtmZone =
     258           0 :                         static_cast<int>((fMedianLongitude + 3) / 12) * 2 + 31;
     259             :                 else
     260           0 :                     nUtmZone =
     261           0 :                         static_cast<int>((fMedianLongitude + 180) / 6) + 1;
     262           0 :                 SetUTM(nUtmZone, fMedianLatitude >= 0);
     263             :             }
     264             :             else
     265             :             {
     266           0 :                 CPLDebug("OSR_Ozi", "UTM Zone not found");
     267             :             }
     268           0 :         }
     269             :     }
     270           0 :     else if (STARTS_WITH_CI(papszProj[1], "(I) France Zone I"))
     271             :     {
     272           0 :         SetLCC1SP(49.5, 2.337229167, 0.99987734, 600000, 1200000);
     273             :     }
     274           0 :     else if (STARTS_WITH_CI(papszProj[1], "(II) France Zone II"))
     275             :     {
     276           0 :         SetLCC1SP(46.8, 2.337229167, 0.99987742, 600000, 2200000);
     277             :     }
     278           0 :     else if (STARTS_WITH_CI(papszProj[1], "(III) France Zone III"))
     279             :     {
     280           0 :         SetLCC1SP(44.1, 2.337229167, 0.99987750, 600000, 3200000);
     281             :     }
     282           0 :     else if (STARTS_WITH_CI(papszProj[1], "(IV) France Zone IV"))
     283             :     {
     284           0 :         SetLCC1SP(42.165, 2.337229167, 0.99994471, 234.358, 4185861.369);
     285             :     }
     286             : 
     287             :     /*
     288             :      *  Note: The following projections have not been implemented yet
     289             :      *
     290             :      */
     291             : 
     292             :     /*
     293             :         else if( STARTS_WITH_CI(papszProj[1], "(BNG) British National Grid") )
     294             :         {
     295             :         }
     296             :         else if( STARTS_WITH_CI(papszProj[1], "(IG) Irish Grid") )
     297             :         {
     298             :         }
     299             : 
     300             :         else if( STARTS_WITH_CI(papszProj[1], "(NZG) New Zealand Grid") )
     301             :         {
     302             :         }
     303             :         else if( STARTS_WITH_CI(papszProj[1], "(NZTM2) New Zealand TM 2000") )
     304             :         {
     305             :         }
     306             :         else if( STARTS_WITH_CI(papszProj[1], "(SG) Swedish Grid") )
     307             :         {
     308             :         }
     309             :         else if( STARTS_WITH_CI(papszProj[1], "(SUI) Swiss Grid") )
     310             :         {
     311             :         }
     312             :         else if( STARTS_WITH_CI(papszProj[1], "(A)Lambert Azimuthual Equal
     313             :        Area") )
     314             :         {
     315             :         }
     316             :         else if( STARTS_WITH_CI(papszProj[1], "(EQC) Equidistant Conic") )
     317             :         {
     318             :         }
     319             :         else if( STARTS_WITH_CI(papszProj[1], "Polyconic (American)") )
     320             :         {
     321             :         }
     322             :         else if( STARTS_WITH_CI(papszProj[1], "Van Der Grinten") )
     323             :         {
     324             :         }
     325             :         else if( STARTS_WITH_CI(papszProj[1], "Vertical Near-Sided Perspective")
     326             :        )
     327             :         {
     328             :         }
     329             :         else if( STARTS_WITH_CI(papszProj[1], "(WIV) Wagner IV") )
     330             :         {
     331             :         }
     332             :         else if( STARTS_WITH_CI(papszProj[1], "Bonne") )
     333             :         {
     334             :         }
     335             :         else if( STARTS_WITH_CI(papszProj[1],
     336             :                                 "(MT0) Montana State Plane Zone 2500") )
     337             :         {
     338             :         }
     339             :         else if( STARTS_WITH_CI(papszProj[1], "ITA1) Italy Grid Zone 1") )
     340             :         {
     341             :         }
     342             :         else if( STARTS_WITH_CI(papszProj[1], "ITA2) Italy Grid Zone 2") )
     343             :         {
     344             :         }
     345             :         else if( STARTS_WITH_CI(papszProj[1],
     346             :                                 "(VICMAP-TM) Victoria Aust.(pseudo AMG)") )
     347             :         {
     348             :         }
     349             :         else if( STARTS_WITH_CI(papszProj[1], "VICGRID) Victoria Australia") )
     350             :         {
     351             :         }
     352             :         else if( STARTS_WITH_CI(papszProj[1],
     353             :                                 "(VG94) VICGRID94 Victoria Australia") )
     354             :         {
     355             :         }
     356             :         else if( STARTS_WITH_CI(papszProj[1], "Gnomonic") )
     357             :         {
     358             :         }
     359             :     */
     360             :     else
     361             :     {
     362           0 :         CPLDebug("OSR_Ozi", "Unsupported projection: \"%s\"", papszProj[1]);
     363           0 :         SetLocalCS(
     364           0 :             CPLString().Printf(R"("Ozi" projection "%s")", papszProj[1]));
     365             :     }
     366             : 
     367             :     /* -------------------------------------------------------------------- */
     368             :     /*      Try to translate the datum/spheroid.                            */
     369             :     /* -------------------------------------------------------------------- */
     370           3 :     papszDatum = CSLTokenizeString2(
     371             :         pszDatum, ",",
     372             :         CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
     373           3 :     if (papszDatum == nullptr)
     374           0 :         goto not_enough_data;
     375             : 
     376           3 :     if (!IsLocal())
     377             :     {
     378             :         /* --------------------------------------------------------------------
     379             :          */
     380             :         /*      Verify that we can find the CSV file containing the datums */
     381             :         /* --------------------------------------------------------------------
     382             :          */
     383           3 :         if (CSVScanFileByName(CSVFilename("ozi_datum.csv"), "EPSG_DATUM_CODE",
     384           3 :                               "4326", CC_Integer) == nullptr)
     385             :         {
     386           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
     387             :                      "Unable to open OZI support file %s.  "
     388             :                      "Try setting the GDAL_DATA environment variable to point "
     389             :                      "to the directory containing OZI csv files.",
     390             :                      CSVFilename("ozi_datum.csv"));
     391           0 :             goto other_error;
     392             :         }
     393             : 
     394             :         /* --------------------------------------------------------------------
     395             :          */
     396             :         /*      Search for matching datum */
     397             :         /* --------------------------------------------------------------------
     398             :          */
     399           3 :         const char *pszOziDatum = CSVFilename("ozi_datum.csv");
     400             :         CPLString osDName = CSVGetField(pszOziDatum, "NAME", papszDatum[0],
     401           3 :                                         CC_ApproxString, "NAME");
     402           3 :         if (osDName.empty())
     403             :         {
     404           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     405             :                      "Failed to find datum %s in ozi_datum.csv.",
     406             :                      papszDatum[0]);
     407           0 :             goto other_error;
     408             :         }
     409             : 
     410             :         const int nDatumCode =
     411           3 :             atoi(CSVGetField(pszOziDatum, "NAME", papszDatum[0],
     412             :                              CC_ApproxString, "EPSG_DATUM_CODE"));
     413             : 
     414           3 :         if (nDatumCode > 0)  // There is a matching EPSG code
     415             :         {
     416           4 :             OGRSpatialReference oGCS;
     417           2 :             oGCS.importFromEPSG(nDatumCode);
     418           2 :             CopyGeogCSFrom(&oGCS);
     419             :         }
     420             :         else  // We use the parameters from the CSV files
     421             :         {
     422             :             CPLString osEllipseCode =
     423             :                 CSVGetField(pszOziDatum, "NAME", papszDatum[0], CC_ApproxString,
     424           1 :                             "ELLIPSOID_CODE");
     425           1 :             const double dfDeltaX = CPLAtof(CSVGetField(
     426             :                 pszOziDatum, "NAME", papszDatum[0], CC_ApproxString, "DELTAX"));
     427           1 :             const double dfDeltaY = CPLAtof(CSVGetField(
     428             :                 pszOziDatum, "NAME", papszDatum[0], CC_ApproxString, "DELTAY"));
     429           1 :             const double dfDeltaZ = CPLAtof(CSVGetField(
     430             :                 pszOziDatum, "NAME", papszDatum[0], CC_ApproxString, "DELTAZ"));
     431             : 
     432             :             /* --------------------------------------------------------------------
     433             :              */
     434             :             /*     Verify that we can find the CSV file containing the
     435             :              * ellipsoids.  */
     436             :             /* --------------------------------------------------------------------
     437             :              */
     438           1 :             if (CSVScanFileByName(CSVFilename("ozi_ellips.csv"),
     439             :                                   "ELLIPSOID_CODE", "20",
     440           1 :                                   CC_Integer) == nullptr)
     441             :             {
     442           0 :                 CPLError(
     443             :                     CE_Failure, CPLE_OpenFailed,
     444             :                     "Unable to open OZI support file %s.  "
     445             :                     "Try setting the GDAL_DATA environment variable to point "
     446             :                     "to the directory containing OZI csv files.",
     447             :                     CSVFilename("ozi_ellips.csv"));
     448           0 :                 goto other_error;
     449             :             }
     450             : 
     451             :             /* --------------------------------------------------------------------
     452             :              */
     453             :             /*      Lookup the ellipse code. */
     454             :             /* --------------------------------------------------------------------
     455             :              */
     456           1 :             const char *pszOziEllipse = CSVFilename("ozi_ellips.csv");
     457             : 
     458             :             CPLString osEName =
     459             :                 CSVGetField(pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
     460           1 :                             CC_ApproxString, "NAME");
     461           1 :             if (osEName.empty())
     462             :             {
     463           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     464             :                          "Failed to find ellipsoid %s in ozi_ellips.csv.",
     465             :                          osEllipseCode.c_str());
     466           0 :                 goto other_error;
     467             :             }
     468             : 
     469             :             const double dfA =
     470           1 :                 CPLAtof(CSVGetField(pszOziEllipse, "ELLIPSOID_CODE",
     471             :                                     osEllipseCode, CC_ApproxString, "A"));
     472             :             const double dfInvF =
     473           1 :                 CPLAtof(CSVGetField(pszOziEllipse, "ELLIPSOID_CODE",
     474             :                                     osEllipseCode, CC_ApproxString, "INVF"));
     475             : 
     476             :             /* --------------------------------------------------------------------
     477             :              */
     478             :             /*      Create geographic coordinate system. */
     479             :             /* --------------------------------------------------------------------
     480             :              */
     481           1 :             SetGeogCS(osDName, osDName, osEName, dfA, dfInvF);
     482           1 :             SetTOWGS84(dfDeltaX, dfDeltaY, dfDeltaZ);
     483             :         }
     484             :     }
     485             : 
     486             :     /* -------------------------------------------------------------------- */
     487             :     /*      Grid units translation                                          */
     488             :     /* -------------------------------------------------------------------- */
     489           3 :     if (IsLocal() || IsProjected())
     490           1 :         SetLinearUnits(SRS_UL_METER, 1.0);
     491             : 
     492           3 :     CSLDestroy(papszProj);
     493           3 :     CSLDestroy(papszProjParams);
     494           3 :     CSLDestroy(papszDatum);
     495             : 
     496           3 :     return OGRERR_NONE;
     497             : 
     498           0 : not_enough_data:
     499             : 
     500           0 :     CSLDestroy(papszProj);
     501           0 :     CSLDestroy(papszProjParams);
     502           0 :     CSLDestroy(papszDatum);
     503             : 
     504           0 :     return OGRERR_NOT_ENOUGH_DATA;
     505             : 
     506           0 : other_error:
     507             : 
     508           0 :     CSLDestroy(papszProj);
     509           0 :     CSLDestroy(papszProjParams);
     510           0 :     CSLDestroy(papszDatum);
     511             : 
     512           0 :     return OGRERR_FAILURE;
     513             : }

Generated by: LCOV version 1.14