LCOV - code coverage report
Current view: top level - frmts/gxf - gxf_ogcwkt.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 81 126 64.3 %
Date: 2025-01-18 12:42:00 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GXF Reader
       4             :  * Purpose:  Handle GXF to OGC WKT projection transformation.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "gxfopen.h"
      15             : #include "ogr_srs_api.h"
      16             : 
      17             : /* -------------------------------------------------------------------- */
      18             : /* the following #defines come from ogr_spatialref.h in the GDAL/OGR  */
      19             : /* distribution (see http://gdal.velocet.ca/projects/opengis) and */
      20             : /* should be kept in sync with that file.         */
      21             : /* -------------------------------------------------------------------- */
      22             : 
      23             : #define SRS_PT_ALBERS_CONIC_EQUAL_AREA "Albers_Conic_Equal_Area"
      24             : #define SRS_PT_AZIMUTHAL_EQUIDISTANT "Azimuthal_Equidistant"
      25             : #define SRS_PT_CASSINI_SOLDNER "Cassini_Soldner"
      26             : #define SRS_PT_CYLINDRICAL_EQUAL_AREA "Cylindrical_Equal_Area"
      27             : #define SRS_PT_ECKERT_IV "Eckert_IV"
      28             : #define SRS_PT_ECKERT_VI "Eckert_VI"
      29             : #define SRS_PT_EQUIDISTANT_CONIC "Equidistant_Conic"
      30             : #define SRS_PT_EQUIRECTANGULAR "Equirectangular"
      31             : #define SRS_PT_GALL_STEREOGRAPHIC "Gall_Stereographic"
      32             : #define SRS_PT_GNOMONIC "Gnomonic"
      33             : #define SRS_PT_HOTINE_OBLIQUE_MERCATOR "Hotine_Oblique_Mercator"
      34             : #define SRS_PT_LABORDE_OBLIQUE_MERCATOR "Laborde_Oblique_Mercator"
      35             : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP "Lambert_Conformal_Conic_1SP"
      36             : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP "Lambert_Conformal_Conic_2SP"
      37             : #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM                             \
      38             :     "Lambert_Conformal_Conic_2SP_Belgium"
      39             : #define SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA "Lambert_Azimuthal_Equal_Area"
      40             : #define SRS_PT_MERCATOR_1SP "Mercator_1SP"
      41             : #define SRS_PT_MERCATOR_2SP "Mercator_2SP"
      42             : #define SRS_PT_MILLER_CYLINDRICAL "Miller_Cylindrical"
      43             : #define SRS_PT_MOLLWEIDE "Mollweide"
      44             : #define SRS_PT_NEW_ZEALAND_MAP_GRID "New_Zealand_Map_Grid"
      45             : #define SRS_PT_OBLIQUE_STEREOGRAPHIC "Oblique_Stereographic"
      46             : #define SRS_PT_ORTHOGRAPHIC "Orthographic"
      47             : #define SRS_PT_POLAR_STEREOGRAPHIC "Polar_Stereographic"
      48             : #define SRS_PT_POLYCONIC "Polyconic"
      49             : #define SRS_PT_ROBINSON "Robinson"
      50             : #define SRS_PT_SINUSOIDAL "Sinusoidal"
      51             : #define SRS_PT_STEREOGRAPHIC "Stereographic"
      52             : #define SRS_PT_SWISS_OBLIQUE_CYLINDRICAL "Swiss_Oblique_Cylindrical"
      53             : #define SRS_PT_TRANSVERSE_MERCATOR "Transverse_Mercator"
      54             : #define SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED                              \
      55             :     "Transverse_Mercator_South_Orientated"
      56             : #define SRS_PT_TUNISIA_MINING_GRID "Tunisia_Mining_Grid"
      57             : #define SRS_PT_VANDERGRINTEN "VanDerGrinten"
      58             : 
      59             : #define SRS_PP_CENTRAL_MERIDIAN "central_meridian"
      60             : #define SRS_PP_SCALE_FACTOR "scale_factor"
      61             : #define SRS_PP_STANDARD_PARALLEL_1 "standard_parallel_1"
      62             : #define SRS_PP_STANDARD_PARALLEL_2 "standard_parallel_2"
      63             : #define SRS_PP_LONGITUDE_OF_CENTER "longitude_of_center"
      64             : #define SRS_PP_LATITUDE_OF_CENTER "latitude_of_center"
      65             : #define SRS_PP_LONGITUDE_OF_ORIGIN "longitude_of_origin"
      66             : #define SRS_PP_LATITUDE_OF_ORIGIN "latitude_of_origin"
      67             : #define SRS_PP_FALSE_EASTING "false_easting"
      68             : #define SRS_PP_FALSE_NORTHING "false_northing"
      69             : #define SRS_PP_AZIMUTH "azimuth"
      70             : #define SRS_PP_LONGITUDE_OF_POINT_1 "longitude_of_point_1"
      71             : #define SRS_PP_LATITUDE_OF_POINT_1 "latitude_of_point_1"
      72             : #define SRS_PP_LONGITUDE_OF_POINT_2 "longitude_of_point_2"
      73             : #define SRS_PP_LATITUDE_OF_POINT_2 "latitude_of_point_2"
      74             : #define SRS_PP_LONGITUDE_OF_POINT_3 "longitude_of_point_3"
      75             : #define SRS_PP_LATITUDE_OF_POINT_3 "latitude_of_point_3"
      76             : #define SRS_PP_RECTIFIED_GRID_ANGLE "rectified_grid_angle"
      77             : 
      78             : /* -------------------------------------------------------------------- */
      79             : /*      This table was copied from gt_wkt_srs.cpp in the libgeotiff     */
      80             : /*      distribution.  Please keep changes in sync.                     */
      81             : /* -------------------------------------------------------------------- */
      82             : static const char *const papszDatumEquiv[] = {
      83             :     "Militar_Geographische_Institut",
      84             :     "Militar_Geographische_Institute",
      85             :     "World_Geodetic_System_1984",
      86             :     "WGS_1984",
      87             :     "WGS_72_Transit_Broadcast_Ephemeris",
      88             :     "WGS_1972_Transit_Broadcast_Ephemeris",
      89             :     "World_Geodetic_System_1972",
      90             :     "WGS_1972",
      91             :     "European_Terrestrial_Reference_System_89",
      92             :     "European_Reference_System_1989",
      93             :     NULL};
      94             : 
      95             : /************************************************************************/
      96             : /*                          WKTMassageDatum()                           */
      97             : /*                                                                      */
      98             : /*      Massage an EPSG datum name into WMT format.  Also transform     */
      99             : /*      specific exception cases into WKT versions.                     */
     100             : /*                                                                      */
     101             : /*      This function was copied from the gt_wkt_srs.cpp file in the    */
     102             : /*      libgeotiff distribution.  Please keep changes in sync.          */
     103             : /************************************************************************/
     104             : 
     105           2 : static void WKTMassageDatum(char **ppszDatum)
     106             : 
     107             : {
     108             :     int i, j;
     109             :     char *pszDatum;
     110             : 
     111           2 :     pszDatum = *ppszDatum;
     112           2 :     if (pszDatum[0] == '\0')
     113           0 :         return;
     114             : 
     115             :     /* -------------------------------------------------------------------- */
     116             :     /*      Translate non-alphanumeric values to underscores.               */
     117             :     /* -------------------------------------------------------------------- */
     118          12 :     for (i = 0; pszDatum[i] != '\0'; i++)
     119             :     {
     120          10 :         if (pszDatum[i] != '+' && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z') &&
     121           4 :             !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z') &&
     122           4 :             !(pszDatum[i] >= '0' && pszDatum[i] <= '9'))
     123             :         {
     124           0 :             pszDatum[i] = '_';
     125             :         }
     126             :     }
     127             : 
     128             :     /* -------------------------------------------------------------------- */
     129             :     /*      Remove repeated and trailing underscores.                       */
     130             :     /* -------------------------------------------------------------------- */
     131          10 :     for (i = 1, j = 0; pszDatum[i] != '\0'; i++)
     132             :     {
     133           8 :         if (pszDatum[j] == '_' && pszDatum[i] == '_')
     134           0 :             continue;
     135             : 
     136           8 :         pszDatum[++j] = pszDatum[i];
     137             :     }
     138           2 :     if (pszDatum[j] == '_')
     139           0 :         pszDatum[j] = '\0';
     140             :     else
     141           2 :         pszDatum[j + 1] = '\0';
     142             : 
     143             :     /* -------------------------------------------------------------------- */
     144             :     /*      Search for datum equivalences.  Specific massaged names get     */
     145             :     /*      mapped to OpenGIS specified names.                              */
     146             :     /* -------------------------------------------------------------------- */
     147          12 :     for (i = 0; papszDatumEquiv[i] != NULL; i += 2)
     148             :     {
     149          10 :         if (EQUAL(*ppszDatum, papszDatumEquiv[i]))
     150             :         {
     151           0 :             CPLFree(*ppszDatum);
     152           0 :             *ppszDatum = CPLStrdup(papszDatumEquiv[i + 1]);
     153           0 :             return;
     154             :         }
     155             :     }
     156             : }
     157             : 
     158             : /************************************************************************/
     159             : /*                           OGCWKTSetProj()                            */
     160             : /************************************************************************/
     161             : 
     162           2 : static void OGCWKTSetProj(char *pszProjection, size_t nProjectionSize,
     163             :                           char **papszMethods, const char *pszTransformName,
     164             :                           const char *pszParm1, const char *pszParm2,
     165             :                           const char *pszParm3, const char *pszParm4,
     166             :                           const char *pszParm5, const char *pszParm6,
     167             :                           const char *pszParm7)
     168             : 
     169             : {
     170           2 :     int iParam, nCount = CSLCount(papszMethods);
     171           2 :     const char *apszParamNames[8] = {NULL};
     172             : 
     173           2 :     apszParamNames[0] = pszParm1;
     174           2 :     apszParamNames[1] = pszParm2;
     175           2 :     apszParamNames[2] = pszParm3;
     176           2 :     apszParamNames[3] = pszParm4;
     177           2 :     apszParamNames[4] = pszParm5;
     178           2 :     apszParamNames[5] = pszParm6;
     179           2 :     apszParamNames[6] = pszParm7;
     180           2 :     apszParamNames[7] = NULL;
     181             : 
     182           2 :     snprintf(pszProjection, nProjectionSize, "PROJECTION[\"%s\"]",
     183             :              pszTransformName);
     184             : 
     185          12 :     for (iParam = 0; iParam < nCount - 1 && apszParamNames[iParam] != NULL;
     186          10 :          iParam++)
     187             :     {
     188          10 :         snprintf(pszProjection + strlen(pszProjection),
     189          10 :                  nProjectionSize - strlen(pszProjection),
     190             :                  ",PARAMETER[\"%s\",%s]", apszParamNames[iParam],
     191          10 :                  papszMethods[iParam + 1]);
     192             :     }
     193           2 : }
     194             : 
     195             : /************************************************************************/
     196             : /*                    GXFGetMapProjectionAsOGCWKT()                     */
     197             : /************************************************************************/
     198             : 
     199             : /**
     200             :  * Return the GXF Projection in OpenGIS Well Known Text format.
     201             :  *
     202             :  * The returned string becomes owned by the caller, and should be freed
     203             :  * with CPLFree() or VSIFree().  The return value will be "" if
     204             :  * no projection information is passed.
     205             :  *
     206             :  * The mapping of GXF projections to OGC WKT format is not complete.  Please
     207             :  * see the gxf_ogcwkt.c code to better understand limitations of this
     208             :  * translation.  More information about OGC WKT format can be found in
     209             :  * the OpenGIS Simple Features specification for OLEDB/COM found on the
     210             :  * OpenGIS web site at <a href="http://www.opengis.org/">www.opengis.org</a>.
     211             :  * The translation uses some code cribbed from the OGR library, about which
     212             :  * more can be learned from <a href="http://gdal.velocet.ca/projects/opengis/">
     213             :  * http://gdal.velocet.ca/projects/opengis/</a>.
     214             :  *
     215             :  * For example, the following GXF definitions:
     216             :  * <pre>
     217             :  * #UNIT_LENGTH
     218             :  * m,1
     219             :  * #MAP_PROJECTION
     220             :  * "NAD83 / UTM zone 19N"
     221             :  * "GRS 1980",6378137,0.081819191,0
     222             :  * "Transverse Mercator",0,-69,0.9996,500000,0
     223             :  * </pre>
     224             :  *
     225             :  * Would translate to (without the nice formatting):
     226             :  * <pre>
     227             :    PROJCS["NAD83 / UTM zone 19N",
     228             :           GEOGCS["GRS 1980",
     229             :                  DATUM["GRS_1980",
     230             :                      SPHEROID["GRS 1980",6378137,298.257222413684]],
     231             :                  PRIMEM["unnamed",0],
     232             :                  UNIT["degree",0.0174532925199433]],
     233             :           PROJECTION["Transverse_Mercator"],
     234             :           PARAMETER["latitude_of_origin",0],
     235             :           PARAMETER["central_meridian",-69],
     236             :           PARAMETER["scale_factor",0.9996],
     237             :           PARAMETER["false_easting",500000],
     238             :           PARAMETER["false_northing",0],
     239             :           UNIT["m",1]]
     240             :  * </pre>
     241             :  *
     242             :  * @param hGXF handle to GXF file, as returned by GXFOpen().
     243             :  *
     244             :  * @return string containing OGC WKT projection.
     245             :  */
     246             : 
     247           4 : char *GXFGetMapProjectionAsOGCWKT(GXFHandle hGXF)
     248             : 
     249             : {
     250           4 :     GXFInfo_t *psGXF = hGXF;
     251           4 :     char **papszMethods = NULL;
     252             :     char szWKT[1024 + 32];
     253             :     char szGCS[512];
     254             :     char szProjection[512];
     255             : 
     256             :     /* -------------------------------------------------------------------- */
     257             :     /*      If there was nothing in the file return "unknown".              */
     258             :     /* -------------------------------------------------------------------- */
     259           4 :     if (CSLCount(psGXF->papszMapProjection) < 2)
     260           2 :         return (CPLStrdup(""));
     261             : 
     262           2 :     strcpy(szWKT, "");
     263           2 :     strcpy(szGCS, "");
     264           2 :     strcpy(szProjection, "");
     265             : 
     266             :     /* -------------------------------------------------------------------- */
     267             :     /*      Parse the third line, looking for known projection methods.     */
     268             :     /* -------------------------------------------------------------------- */
     269           2 :     if (psGXF->papszMapProjection[2] != NULL)
     270             :     {
     271             :         /* We allow more than 80 characters if the projection parameters */
     272             :         /* are on 2 lines as allowed by GXF 3 */
     273           2 :         if (strlen(psGXF->papszMapProjection[2]) > 120)
     274           0 :             return (CPLStrdup(""));
     275           2 :         papszMethods = CSLTokenizeStringComplex(psGXF->papszMapProjection[2],
     276             :                                                 ",", TRUE, TRUE);
     277             :     }
     278             : 
     279             :     /* -------------------------------------------------------------------- */
     280             :     /*      Create the PROJCS.                                              */
     281             :     /* -------------------------------------------------------------------- */
     282           2 :     if (papszMethods == NULL || papszMethods[0] == NULL ||
     283           2 :         EQUAL(papszMethods[0], "Geographic"))
     284             :     {
     285             :         /* do nothing */
     286             :     }
     287             : 
     288           2 :     else if (EQUAL(papszMethods[0], "Lambert Conic Conformal (1SP)"))
     289             :     {
     290           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     291             :                       SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
     292             :                       SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
     293             :                       SRS_PP_SCALE_FACTOR, SRS_PP_FALSE_EASTING,
     294             :                       SRS_PP_FALSE_NORTHING, NULL, NULL);
     295             :     }
     296             : 
     297           2 :     else if (EQUAL(papszMethods[0], "Lambert Conic Conformal (2SP)"))
     298             :     {
     299           2 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     300             :                       SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
     301             :                       SRS_PP_STANDARD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_2,
     302             :                       SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
     303             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL);
     304             :     }
     305             : 
     306           0 :     else if (EQUAL(papszMethods[0], "Lambert Conformal (2SP Belgium)"))
     307             :     {
     308           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     309             :                       SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
     310             :                       SRS_PP_STANDARD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_2,
     311             :                       SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
     312             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL);
     313             :     }
     314             : 
     315           0 :     else if (EQUAL(papszMethods[0], "Mercator (1SP)"))
     316             :     {
     317           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     318             :                       SRS_PT_MERCATOR_1SP, SRS_PP_LATITUDE_OF_ORIGIN,
     319             :                       SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
     320             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
     321             :     }
     322             : 
     323           0 :     else if (EQUAL(papszMethods[0], "Mercator (2SP)"))
     324             :     {
     325           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     326             :                       SRS_PT_MERCATOR_2SP,
     327             :                       SRS_PP_LATITUDE_OF_ORIGIN, /* should it be StdParalle1?*/
     328             :                       SRS_PP_CENTRAL_MERIDIAN, SRS_PP_FALSE_EASTING,
     329             :                       SRS_PP_FALSE_NORTHING, NULL, NULL, NULL);
     330             :     }
     331             : 
     332           0 :     else if (EQUAL(papszMethods[0], "Laborde Oblique Mercator"))
     333             :     {
     334           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     335             :                       SRS_PT_LABORDE_OBLIQUE_MERCATOR,
     336             :                       SRS_PP_LATITUDE_OF_CENTER, SRS_PP_LONGITUDE_OF_CENTER,
     337             :                       SRS_PP_AZIMUTH, SRS_PP_SCALE_FACTOR, SRS_PP_FALSE_EASTING,
     338             :                       SRS_PP_FALSE_NORTHING, NULL);
     339             :     }
     340             : 
     341           0 :     else if (EQUAL(papszMethods[0], "Hotine Oblique Mercator"))
     342             :     {
     343           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     344             :                       SRS_PT_HOTINE_OBLIQUE_MERCATOR, SRS_PP_LATITUDE_OF_CENTER,
     345             :                       SRS_PP_LONGITUDE_OF_CENTER, SRS_PP_AZIMUTH,
     346             :                       SRS_PP_RECTIFIED_GRID_ANGLE,
     347             :                       SRS_PP_SCALE_FACTOR, /* not in normal formulation */
     348             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING);
     349             :     }
     350             : 
     351           0 :     else if (EQUAL(papszMethods[0], "New Zealand Map Grid"))
     352             : 
     353             :     {
     354           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     355             :                       SRS_PT_NEW_ZEALAND_MAP_GRID, SRS_PP_LATITUDE_OF_ORIGIN,
     356             :                       SRS_PP_CENTRAL_MERIDIAN, SRS_PP_FALSE_EASTING,
     357             :                       SRS_PP_FALSE_NORTHING, NULL, NULL, NULL);
     358             :     }
     359             : 
     360           0 :     else if (EQUAL(papszMethods[0], "Oblique Stereographic"))
     361             :     {
     362           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     363             :                       SRS_PT_OBLIQUE_STEREOGRAPHIC, SRS_PP_LATITUDE_OF_ORIGIN,
     364             :                       SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
     365             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
     366             :     }
     367             : 
     368           0 :     else if (EQUAL(papszMethods[0], "Polar Stereographic"))
     369             :     {
     370           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     371             :                       SRS_PT_POLAR_STEREOGRAPHIC, SRS_PP_LATITUDE_OF_ORIGIN,
     372             :                       SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
     373             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
     374             :     }
     375             : 
     376           0 :     else if (EQUAL(papszMethods[0], "Swiss Oblique Cylindrical"))
     377             :     {
     378           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     379             :                       SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
     380             :                       SRS_PP_LATITUDE_OF_CENTER, SRS_PP_LONGITUDE_OF_CENTER,
     381             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL,
     382             :                       NULL);
     383             :     }
     384             : 
     385           0 :     else if (EQUAL(papszMethods[0], "Transverse Mercator"))
     386             :     {
     387           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     388             :                       SRS_PT_TRANSVERSE_MERCATOR, SRS_PP_LATITUDE_OF_ORIGIN,
     389             :                       SRS_PP_CENTRAL_MERIDIAN, SRS_PP_SCALE_FACTOR,
     390             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
     391             :     }
     392             : 
     393           0 :     else if (EQUAL(papszMethods[0], "Transverse Mercator (South Oriented)") ||
     394           0 :              EQUAL(papszMethods[0], "Transverse Mercator (South Orientated)"))
     395             :     {
     396           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     397             :                       SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
     398             :                       SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_CENTRAL_MERIDIAN,
     399             :                       SRS_PP_SCALE_FACTOR, SRS_PP_FALSE_EASTING,
     400             :                       SRS_PP_FALSE_NORTHING, NULL, NULL);
     401             :     }
     402             : 
     403           0 :     else if (EQUAL(papszMethods[0], "*Albers Conic"))
     404             :     {
     405           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     406             :                       SRS_PT_ALBERS_CONIC_EQUAL_AREA,
     407             :                       SRS_PP_STANDARD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_2,
     408             :                       SRS_PP_LATITUDE_OF_CENTER, SRS_PP_LONGITUDE_OF_CENTER,
     409             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL);
     410             :     }
     411             : 
     412           0 :     else if (EQUAL(papszMethods[0], "*Equidistant Conic"))
     413             :     {
     414           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     415             :                       SRS_PT_EQUIDISTANT_CONIC, SRS_PP_STANDARD_PARALLEL_1,
     416             :                       SRS_PP_STANDARD_PARALLEL_2, SRS_PP_LATITUDE_OF_CENTER,
     417             :                       SRS_PP_LONGITUDE_OF_CENTER, SRS_PP_FALSE_EASTING,
     418             :                       SRS_PP_FALSE_NORTHING, NULL);
     419             :     }
     420             : 
     421           0 :     else if (EQUAL(papszMethods[0], "*Polyconic"))
     422             :     {
     423           0 :         OGCWKTSetProj(szProjection, sizeof(szProjection), papszMethods,
     424             :                       SRS_PT_POLYCONIC, SRS_PP_LATITUDE_OF_ORIGIN,
     425             :                       SRS_PP_CENTRAL_MERIDIAN,
     426             :                       SRS_PP_SCALE_FACTOR, /* not normally expected */
     427             :                       SRS_PP_FALSE_EASTING, SRS_PP_FALSE_NORTHING, NULL, NULL);
     428             :     }
     429             : 
     430           2 :     CSLDestroy(papszMethods);
     431             : 
     432             :     /* -------------------------------------------------------------------- */
     433             :     /*      Extract the linear Units specification.                         */
     434             :     /* -------------------------------------------------------------------- */
     435           2 :     if (psGXF->pszUnitName != NULL && strlen(szProjection) > 0)
     436             :     {
     437           2 :         if (strlen(psGXF->pszUnitName) > 80)
     438           0 :             return CPLStrdup("");
     439             : 
     440           2 :         CPLsnprintf(szProjection + strlen(szProjection),
     441           2 :                     sizeof(szProjection) - strlen(szProjection),
     442             :                     ",UNIT[\"%s\",%.15g]", psGXF->pszUnitName,
     443             :                     psGXF->dfUnitToMeter);
     444             :     }
     445             : 
     446             :     /* -------------------------------------------------------------------- */
     447             :     /*      Build GEOGCS.  There are still "issues" with the generation     */
     448             :     /*      of the GEOGCS/Datum and Spheroid names.  Of these, only the     */
     449             :     /*      datum name is really significant.                               */
     450             :     /* -------------------------------------------------------------------- */
     451           2 :     if (CSLCount(psGXF->papszMapProjection) > 1)
     452             :     {
     453             :         char **papszTokens;
     454             : 
     455           2 :         if (strlen(psGXF->papszMapProjection[1]) > 80)
     456           0 :             return CPLStrdup("");
     457             : 
     458           2 :         papszTokens = CSLTokenizeStringComplex(psGXF->papszMapProjection[1],
     459             :                                                ",", TRUE, TRUE);
     460             : 
     461           2 :         if (CSLCount(papszTokens) > 2)
     462             :         {
     463           2 :             double dfMajor = CPLAtof(papszTokens[1]);
     464           2 :             double dfEccentricity = CPLAtof(papszTokens[2]);
     465             :             double dfInvFlattening, dfMinor;
     466             :             char *pszOGCDatum;
     467             : 
     468             :             /* translate eccentricity to inv flattening. */
     469           2 :             if (dfEccentricity == 0.0)
     470           0 :                 dfInvFlattening = 0.0;
     471             :             else
     472             :             {
     473           2 :                 dfMinor =
     474           2 :                     dfMajor * pow(1.0 - dfEccentricity * dfEccentricity, 0.5);
     475           2 :                 dfInvFlattening = OSRCalcInvFlattening(dfMajor, dfMinor);
     476             :             }
     477             : 
     478           2 :             pszOGCDatum = CPLStrdup(papszTokens[0]);
     479           2 :             WKTMassageDatum(&pszOGCDatum);
     480             : 
     481           2 :             CPLsnprintf(
     482             :                 szGCS, sizeof(szGCS),
     483             :                 "GEOGCS[\"%s\","
     484             :                 "DATUM[\"%s\","
     485             :                 "SPHEROID[\"%s\",%s,%.15g]],",
     486             :                 papszTokens[0], pszOGCDatum,
     487             :                 papszTokens[0], /* this is datum, but should be ellipse*/
     488           2 :                 papszTokens[1], dfInvFlattening);
     489           2 :             CPLFree(pszOGCDatum);
     490             :         }
     491             : 
     492           2 :         if (CSLCount(papszTokens) > 3)
     493           2 :             CPLsnprintf(szGCS + strlen(szGCS), sizeof(szGCS) - strlen(szGCS),
     494           2 :                         "PRIMEM[\"unnamed\",%s],", papszTokens[3]);
     495             : 
     496           2 :         CPLsnprintf(szGCS + strlen(szGCS), sizeof(szGCS) - strlen(szGCS), "%s",
     497             :                     "UNIT[\"degree\",0.0174532925199433]]");
     498             : 
     499           2 :         CSLDestroy(papszTokens);
     500             :     }
     501             : 
     502           2 :     CPLAssert(strlen(szProjection) < sizeof(szProjection));
     503           2 :     CPLAssert(strlen(szGCS) < sizeof(szGCS));
     504             : 
     505             :     /* -------------------------------------------------------------------- */
     506             :     /*      Put this all together into a full projection.                   */
     507             :     /* -------------------------------------------------------------------- */
     508           2 :     if (strlen(szProjection) > 0)
     509             :     {
     510           2 :         if (strlen(psGXF->papszMapProjection[0]) > 80)
     511           0 :             return CPLStrdup("");
     512             : 
     513           2 :         if (psGXF->papszMapProjection[0][0] == '"')
     514           2 :             snprintf(szWKT, sizeof(szWKT), "PROJCS[%s,%s,%s]",
     515           2 :                      psGXF->papszMapProjection[0], szGCS, szProjection);
     516             :         else
     517           0 :             snprintf(szWKT, sizeof(szWKT), "PROJCS[\"%s\",%s,%s]",
     518           0 :                      psGXF->papszMapProjection[0], szGCS, szProjection);
     519             :     }
     520             :     else
     521             :     {
     522           0 :         strcpy(szWKT, szGCS);
     523             :     }
     524             : 
     525           2 :     return (CPLStrdup(szWKT));
     526             : }

Generated by: LCOV version 1.14