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: 2024-11-25 13:07:18 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.14