LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mitab - mitab_coordsys.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 591 189 32.0 %
Date: 2012-12-26 Functions: 5 3 60.0 %

       1                 : /**********************************************************************
       2                 :  * $Id: mitab_coordsys.cpp,v 1.42 2011-06-11 00:35:00 fwarmerdam Exp $
       3                 :  *
       4                 :  * Name:     mitab_coordsys.cpp
       5                 :  * Project:  MapInfo TAB Read/Write library
       6                 :  * Language: C++
       7                 :  * Purpose:  Implementation translation between MIF CoordSys format, and
       8                 :  *           and OGRSpatialRef format.
       9                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
      10                 :  *
      11                 :  **********************************************************************
      12                 :  * Copyright (c) 1999-2001, Frank Warmerdam
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  * 
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  * 
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  **********************************************************************
      32                 :  *
      33                 :  * $Log: mitab_coordsys.cpp,v $
      34                 :  * Revision 1.42  2011-06-11 00:35:00  fwarmerdam
      35                 :  * add support for reading google mercator (#4115)
      36                 :  *
      37                 :  * Revision 1.41  2010-10-07 18:46:26  aboudreault
      38                 :  * Fixed bad use of atof when locale setting doesn't use . for float (GDAL bug #3775)
      39                 :  *
      40                 :  * Revision 1.40  2010-09-07 16:48:08  aboudreault
      41                 :  * Removed incomplete patch for affine params support in mitab. (bug 1155)
      42                 :  *
      43                 :  * Revision 1.39  2010-07-07 19:00:15  aboudreault
      44                 :  * Cleanup Win32 Compile Warnings (GDAL bug #2930)
      45                 :  *
      46                 :  * Revision 1.38  2010-07-05 18:32:48  aboudreault
      47                 :  * Fixed memory leaks in mitab_capi.cpp and mitab_coordsys.cpp
      48                 :  *
      49                 :  * Revision 1.37  2010-07-05 17:20:14  aboudreault
      50                 :  * Added Krovak projection suppoprt (bug 2230)
      51                 :  *
      52                 :  * Revision 1.36  2007-11-21 21:15:45  dmorissette
      53                 :  * Fix asDatumInfoList[] and asSpheroidInfoList[] defns/refs (bug 1826)
      54                 :  *
      55                 :  * Revision 1.35  2007/06/21 13:23:43  fwarmerdam
      56                 :  * Fixed support for predefined datums with non-greenwich prime meridians
      57                 :  *
      58                 :  * Revision 1.34  2006/03/10 19:50:45  fwarmerdam
      59                 :  * Coordsys false easting and northing are in the units of the coordsys, not
      60                 :  * necessarily meters.  Adjusted mitab_coordsys.cpp to reflect this.
      61                 :  * http://bugzilla.remotesensing.org/show_bug.cgi?id=1113
      62                 :  *
      63                 :  * Revision 1.33  2005/09/29 20:13:57  dmorissette
      64                 :  * MITABCoordSys2SpatialRef() patches from Anthony D (bug 1155):
      65                 :  * Improved support for modified TM projections 21-24.
      66                 :  * Added support for affine parameters (inside #ifdef MITAB_AFFINE_PARAMS since
      67                 :  * affine params cannot be stored directly in OGRSpatialReference)
      68                 :  *
      69                 :  * Revision 1.32  2005/08/07 21:00:38  fwarmerdam
      70                 :  * Initialize adfDatumParm[] to avoid warnings with gcc 4.
      71                 :  *
      72                 :  * Revision 1.31  2005/05/12 22:07:52  dmorissette
      73                 :  * Improved handling of Danish modified TM proj#21-24 (hss, bugs 976,1010)
      74                 :  *
      75                 :  * Revision 1.30  2005/03/22 23:24:54  dmorissette
      76                 :  * Added support for datum id in .MAP header (bug 910)
      77                 :  *
      78                 :  * Revision 1.29  2004/06/03 19:36:53  fwarmerdam
      79                 :  * fixed memory leak processing non-earth coordsys
      80                 :  *
      81                 :  * Revision 1.28  2003/03/21 14:20:42  warmerda
      82                 :  * fixed up regional mercator handling, was screwing up transverse mercator
      83                 :  *
      84                 :  * Revision 1.27  2003/01/09 17:33:26  warmerda
      85                 :  * fixed ellipsoid extraction for datum 999/9999
      86                 :  *
      87                 :  * Revision 1.26  2002/12/12 20:12:18  warmerda
      88                 :  * fixed signs of rotational parameters for TOWGS84 in WKT
      89                 :  *
      90                 :  * Revision 1.25  2002/10/15 14:33:30  warmerda
      91                 :  * Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for
      92                 :  * projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant -
      93                 :  * All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect (29).
      94                 :  *
      95                 :  * Revision 1.24  2002/09/23 13:16:04  warmerda
      96                 :  * fixed leak in MITABExtractCoordSysBounds()
      97                 :  *
      98                 :  * Revision 1.23  2002/04/01 19:49:24  warmerda
      99                 :  * added support for cassini/soldner - proj 30
     100                 :  *
     101                 :  * Revision 1.22  2002/03/01 19:00:15  warmerda
     102                 :  * False Easting/Northing should be in the linear units of measure in MapInfo,
     103                 :  * but in OGRSpatialReference/WKT they are always in meters.  Convert accordingly.
     104                 :  *
     105                 :  * Revision 1.21  2001/04/04 21:43:19  warmerda
     106                 :  * added code to set WGS84 values
     107                 :  *
     108                 :  * Revision 1.20  2001/01/23 21:23:42  daniel
     109                 :  * Added projection bounds lookup table, called from TABFile::SetProjInfo()
     110                 :  *
     111                 :  * Revision 1.19  2001/01/22 16:00:53  warmerda
     112                 :  * reworked swiss projection support
     113                 :  *
     114                 :  * Revision 1.18  2001/01/19 21:56:18  warmerda
     115                 :  * added untested support for Swiss Oblique Mercator
     116                 :  **********************************************************************/
     117                 : 
     118                 : #include "mitab.h"
     119                 : #include "mitab_utils.h"
     120                 : 
     121                 : extern MapInfoDatumInfo asDatumInfoList[];
     122                 : extern MapInfoSpheroidInfo asSpheroidInfoList[];
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                             GetMIFParm()                             */
     126                 : /************************************************************************/
     127                 : 
     128              22 : static double GetMIFParm( char ** papszFields, int iField, double dfDefault )
     129                 : 
     130                 : {
     131              22 :     if( iField >= CSLCount(papszFields) )
     132               0 :         return dfDefault;
     133                 :     else
     134              22 :         return atof(papszFields[iField]);
     135                 : }
     136                 : 
     137                 : /************************************************************************/
     138                 : /*                      MITABCoordSys2SpatialRef()                      */
     139                 : /*                                                                      */
     140                 : /*      Convert a MIF COORDSYS string into a new OGRSpatialReference    */
     141                 : /*      object.                                                         */
     142                 : /************************************************************************/
     143                 : 
     144               4 : OGRSpatialReference *MITABCoordSys2SpatialRef( const char * pszCoordSys )
     145                 : 
     146                 : {
     147                 :     char        **papszFields;
     148                 :     OGRSpatialReference *poSR;
     149                 : 
     150               4 :     if( pszCoordSys == NULL )
     151               0 :         return NULL;
     152                 :     
     153                 : /* -------------------------------------------------------------------- */
     154                 : /*      Parse the passed string into words.                             */
     155                 : /* -------------------------------------------------------------------- */
     156               4 :     while(*pszCoordSys == ' ') pszCoordSys++;  // Eat leading spaces
     157               4 :     if( EQUALN(pszCoordSys,"CoordSys",8) )
     158               2 :         pszCoordSys += 9;
     159                 :     
     160               4 :     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
     161                 : 
     162                 : /* -------------------------------------------------------------------- */
     163                 : /*      Clip off Bounds information.                                    */
     164                 : /* -------------------------------------------------------------------- */
     165               4 :     int         iBounds = CSLFindString( papszFields, "Bounds" );
     166                 : 
     167              14 :     while( iBounds != -1 && papszFields[iBounds] != NULL )
     168                 :     {
     169               6 :         CPLFree( papszFields[iBounds] );
     170               6 :         papszFields[iBounds] = NULL;
     171               6 :         iBounds++;
     172                 :     }
     173                 : 
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      Create a spatialreference object to operate on.                 */
     176                 : /* -------------------------------------------------------------------- */
     177               4 :     poSR = new OGRSpatialReference;
     178                 : 
     179                 : /* -------------------------------------------------------------------- */
     180                 : /*      Fetch the projection.                                           */
     181                 : /* -------------------------------------------------------------------- */
     182                 :     char        **papszNextField;
     183               4 :     int nProjection = 0;
     184                 : 
     185              12 :     if( CSLCount( papszFields ) >= 3
     186               4 :         && EQUAL(papszFields[0],"Earth")
     187               4 :         && EQUAL(papszFields[1],"Projection") )
     188                 :     {
     189               4 :         nProjection = atoi(papszFields[2]);
     190               4 :         papszNextField = papszFields + 3;
     191                 :     }
     192               0 :     else if (CSLCount( papszFields ) >= 2
     193               0 :              && EQUAL(papszFields[0],"NonEarth") )
     194                 :     {
     195                 :         // NonEarth Units "..." Bounds (x, y) (x, y)
     196               0 :         nProjection = 0;
     197               0 :         papszNextField = papszFields + 2;
     198                 : 
     199               0 :         if( papszNextField[0] != NULL && EQUAL(papszNextField[0],"Units") )
     200               0 :             papszNextField++;
     201                 :     }
     202                 :     else
     203                 :     {
     204                 :         // Invalid projection string ???
     205               0 :         if (CSLCount(papszFields) > 0)
     206                 :             CPLError(CE_Warning, CPLE_IllegalArg,
     207               0 :                      "Failed parsing CoordSys: '%s'", pszCoordSys);
     208               0 :         CSLDestroy(papszFields);
     209               0 :         delete poSR;
     210               0 :         return NULL;
     211                 :     }
     212                 : 
     213                 : /* -------------------------------------------------------------------- */
     214                 : /*      Fetch the datum information.                                    */
     215                 : /* -------------------------------------------------------------------- */
     216               4 :     int         nDatum = 0;
     217               4 :     double      adfDatumParm[8] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
     218               4 :     int         nEllipsoid=0;
     219                 : 
     220               4 :     if( nProjection != 0 && CSLCount(papszNextField) > 0 )
     221                 :     {
     222               4 :         nDatum = atoi(papszNextField[0]);
     223               4 :         papszNextField++;
     224                 :     }
     225                 : 
     226               4 :     if( (nDatum == 999 || nDatum == 9999)
     227                 :         && CSLCount(papszNextField) >= 4 )
     228                 :     {
     229               0 :         nEllipsoid = atoi(papszNextField[0]);
     230               0 :         adfDatumParm[0] = atof(papszNextField[1]);
     231               0 :         adfDatumParm[1] = atof(papszNextField[2]);
     232               0 :         adfDatumParm[2] = atof(papszNextField[3]);
     233               0 :         papszNextField += 4;
     234                 :     }
     235                 : 
     236               4 :     if( nDatum == 9999
     237                 :         && CSLCount(papszNextField) >= 5 )
     238                 :     {
     239               0 :         adfDatumParm[3] = atof(papszNextField[0]);
     240               0 :         adfDatumParm[4] = atof(papszNextField[1]);
     241               0 :         adfDatumParm[5] = atof(papszNextField[2]);
     242               0 :         adfDatumParm[6] = atof(papszNextField[3]);
     243               0 :         adfDatumParm[7] = atof(papszNextField[4]);
     244               0 :         papszNextField += 5;
     245                 :     }
     246                 : 
     247                 : /* -------------------------------------------------------------------- */
     248                 : /*      Fetch the units string.                                         */
     249                 : /* -------------------------------------------------------------------- */
     250               4 :     const char  *pszMIFUnits = NULL;
     251               4 :     const char  *pszUnitsName = NULL;
     252               4 :     double dfUnitsConv = 1.0;
     253                 :     
     254               4 :     if( CSLCount(papszNextField) > 0 )
     255                 :     {
     256               4 :         pszMIFUnits = papszNextField[0];
     257               4 :         papszNextField++;
     258                 :     }
     259                 : 
     260               4 :     if( nProjection == 1 || pszMIFUnits == NULL )
     261                 :         /* do nothing */;
     262               4 :     else if( EQUAL(pszMIFUnits,"km") )
     263                 :     {
     264               0 :         pszUnitsName = "Kilometer"; 
     265               0 :         dfUnitsConv = 1000.0;
     266                 :     }
     267               4 :     else if( EQUAL(pszMIFUnits, "in" ) )
     268                 :     {
     269               0 :         pszUnitsName = "IINCH"; 
     270               0 :         dfUnitsConv = 0.0254; 
     271                 :     }
     272               4 :     else if( EQUAL(pszMIFUnits, "ft" ) )
     273                 :     {
     274               0 :         pszUnitsName = SRS_UL_FOOT;
     275               0 :         dfUnitsConv = CPLAtof(SRS_UL_FOOT_CONV);
     276                 :     }
     277               4 :     else if( EQUAL(pszMIFUnits, "yd" ) )
     278                 :     {
     279               0 :         pszUnitsName = "IYARD";
     280               0 :         dfUnitsConv = 0.9144;
     281                 :     }
     282               4 :     else if( EQUAL(pszMIFUnits, "mm" ) )
     283                 :     {
     284               0 :         pszUnitsName = "Millimeter";
     285               0 :         dfUnitsConv = 0.001;
     286                 :     }
     287               4 :     else if( EQUAL(pszMIFUnits, "cm" ) )
     288                 :     {
     289               0 :         pszUnitsName = "Centimeter";
     290               0 :         dfUnitsConv = 0.01;
     291                 :     }
     292               4 :     else if( EQUAL(pszMIFUnits, "m" ) )
     293                 :     {
     294               4 :         pszUnitsName = SRS_UL_METER;
     295               4 :         dfUnitsConv = 1.0;
     296                 :     }   
     297               0 :     else if( EQUAL(pszMIFUnits, "survey foot" )
     298                 :              || EQUAL(pszMIFUnits, "survey ft" ) )
     299                 :     {
     300               0 :         pszUnitsName = SRS_UL_US_FOOT;
     301               0 :         dfUnitsConv = CPLAtof(SRS_UL_US_FOOT_CONV);
     302                 :     }   
     303               0 :     else if( EQUAL(pszMIFUnits, "nmi" ) )
     304                 :     {
     305               0 :         pszUnitsName = SRS_UL_NAUTICAL_MILE;
     306               0 :         dfUnitsConv = CPLAtof(SRS_UL_NAUTICAL_MILE_CONV);
     307                 :     }   
     308               0 :     else if( EQUAL(pszMIFUnits, "li" ) )
     309                 :     {
     310               0 :         pszUnitsName = SRS_UL_LINK;
     311               0 :         dfUnitsConv = CPLAtof(SRS_UL_LINK_CONV);
     312                 :     }
     313               0 :     else if( EQUAL(pszMIFUnits, "ch" ) )
     314                 :     {
     315               0 :         pszUnitsName = SRS_UL_CHAIN;
     316               0 :         dfUnitsConv = CPLAtof(SRS_UL_CHAIN_CONV);
     317                 :     }   
     318               0 :     else if( EQUAL(pszMIFUnits, "rd" ) )
     319                 :     {
     320               0 :         pszUnitsName = SRS_UL_ROD;
     321               0 :         dfUnitsConv = CPLAtof(SRS_UL_ROD);
     322                 :     }   
     323               0 :     else if( EQUAL(pszMIFUnits, "mi" ) )
     324                 :     {
     325               0 :         pszUnitsName = "Mile";
     326               0 :         dfUnitsConv = 1609.344;
     327                 :     }
     328                 : 
     329                 : /* -------------------------------------------------------------------- */
     330                 : /*      Handle the PROJCS style projections, but add the datum          */
     331                 : /*      later.                                                          */
     332                 : /*                                                                      */
     333                 : /*      Note that per GDAL bug 1113 the false easting and north are     */
     334                 : /*      in local units, not necessarily meters.                         */
     335                 : /* -------------------------------------------------------------------- */
     336               4 :     int nBaseProjection = nProjection;
     337               4 :     if (nBaseProjection>=3000) nBaseProjection -=3000;
     338               4 :     else if (nBaseProjection>=2000) nBaseProjection -=2000;
     339               4 :     else if (nBaseProjection>=1000) nBaseProjection -=1000;
     340               4 :     switch( nBaseProjection )
     341                 :     {
     342                 :         /*--------------------------------------------------------------
     343                 :          * NonEarth ... we return with an empty SpatialRef.  Eventually
     344                 :          * we might want to include the units, but not for now.
     345                 :          *
     346                 :          * __TODO__ Changed to return NULL because returning an empty
     347                 :          * SpatialRef caused confusion between Latlon and NonEarth since
     348                 :          * empty SpatialRefs do have a GEOGCS set and makes them look like
     349                 :          * Lat/Lon SpatialRefs.
     350                 :          *
     351                 :          * Ideally we would like to return a SpatialRef whith no GEGOCS
     352                 :          *-------------------------------------------------------------*/
     353                 :       case 0:
     354               0 :         poSR->SetLocalCS( "Nonearth" );
     355               0 :         break;
     356                 : 
     357                 :         /*--------------------------------------------------------------
     358                 :          * lat/long .. just add the GEOGCS later.
     359                 :          *-------------------------------------------------------------*/
     360                 :       case 1:
     361               0 :         break;
     362                 : 
     363                 :         /*--------------------------------------------------------------
     364                 :          * Cylindrical Equal Area
     365                 :          *-------------------------------------------------------------*/
     366                 :       case 2:
     367                 :         poSR->SetCEA( GetMIFParm( papszNextField, 1, 0.0 ),
     368                 :                       GetMIFParm( papszNextField, 0, 0.0 ),
     369                 :                       GetMIFParm( papszNextField, 2, 0.0 ),
     370               0 :                       GetMIFParm( papszNextField, 3, 0.0 ) );
     371               0 :         break;
     372                 : 
     373                 :         /*--------------------------------------------------------------
     374                 :          * Lambert Conic Conformal
     375                 :          *-------------------------------------------------------------*/
     376                 :       case 3:
     377                 :         poSR->SetLCC( GetMIFParm( papszNextField, 2, 0.0 ),
     378                 :                       GetMIFParm( papszNextField, 3, 0.0 ),
     379                 :                       GetMIFParm( papszNextField, 1, 0.0 ),
     380                 :                       GetMIFParm( papszNextField, 0, 0.0 ),
     381                 :                       GetMIFParm( papszNextField, 4, 0.0 ),
     382               2 :                       GetMIFParm( papszNextField, 5, 0.0 ) );
     383               2 :         break;
     384                 : 
     385                 :         /*--------------------------------------------------------------
     386                 :          * Lambert Azimuthal Equal Area
     387                 :          *-------------------------------------------------------------*/
     388                 :       case 4: 
     389                 :       case 29:
     390                 :         poSR->SetLAEA( GetMIFParm( papszNextField, 1, 0.0 ),
     391                 :                        GetMIFParm( papszNextField, 0, 0.0 ),
     392               0 :                        0.0, 0.0 );
     393               0 :         break;
     394                 : 
     395                 :         /*--------------------------------------------------------------
     396                 :          * Azimuthal Equidistant 
     397                 :          *-------------------------------------------------------------*/
     398                 :       case 5:  /* polar aspect only */
     399                 :       case 28: /* all aspects */
     400                 :         poSR->SetAE( GetMIFParm( papszNextField, 1, 0.0 ),
     401                 :                      GetMIFParm( papszNextField, 0, 0.0 ),
     402               0 :                      0.0, 0.0 );
     403               0 :         break;
     404                 : 
     405                 :         /*--------------------------------------------------------------
     406                 :          * Equidistant Conic
     407                 :          *-------------------------------------------------------------*/
     408                 :       case 6:
     409                 :         poSR->SetEC( GetMIFParm( papszNextField, 2, 0.0 ),
     410                 :                      GetMIFParm( papszNextField, 3, 0.0 ),
     411                 :                      GetMIFParm( papszNextField, 1, 0.0 ),
     412                 :                      GetMIFParm( papszNextField, 0, 0.0 ),
     413                 :                      GetMIFParm( papszNextField, 4, 0.0 ),
     414               0 :                      GetMIFParm( papszNextField, 5, 0.0 ) );
     415               0 :         break;
     416                 : 
     417                 :         /*--------------------------------------------------------------
     418                 :          * Hotine Oblique Mercator
     419                 :          *-------------------------------------------------------------*/
     420                 :       case 7:
     421                 :         poSR->SetHOM( GetMIFParm( papszNextField, 1, 0.0 ),
     422                 :                       GetMIFParm( papszNextField, 0, 0.0 ),
     423                 :                       GetMIFParm( papszNextField, 2, 0.0 ),
     424                 :                       90.0,
     425                 :                       GetMIFParm( papszNextField, 3, 1.0 ),
     426                 :                       GetMIFParm( papszNextField, 4, 0.0 ),
     427               0 :                       GetMIFParm( papszNextField, 5, 0.0 ) );
     428               0 :         break;
     429                 : 
     430                 :         /*--------------------------------------------------------------
     431                 :          * Transverse Mercator
     432                 :          *-------------------------------------------------------------*/
     433                 :       case 8:
     434                 :         poSR->SetTM( GetMIFParm( papszNextField, 1, 0.0 ),
     435                 :                      GetMIFParm( papszNextField, 0, 0.0 ),
     436                 :                      GetMIFParm( papszNextField, 2, 1.0 ),
     437                 :                      GetMIFParm( papszNextField, 3, 0.0 ),
     438               2 :                      GetMIFParm( papszNextField, 4, 0.0 ) );
     439               2 :         break;
     440                 : 
     441                 :         /*----------------------------------------------------------------
     442                 :          * Transverse Mercator,(modified for Danish System 34 Jylland-Fyn)
     443                 :          *---------------------------------------------------------------*/
     444                 :       case 21:
     445                 :         poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_21,
     446                 :                             GetMIFParm( papszNextField, 1, 0.0 ),
     447                 :                             GetMIFParm( papszNextField, 0, 0.0 ),
     448                 :                             GetMIFParm( papszNextField, 2, 1.0 ),
     449                 :                             GetMIFParm( papszNextField, 3, 0.0 ),
     450               0 :                             GetMIFParm( papszNextField, 4, 0.0 ));
     451               0 :         break;
     452                 : 
     453                 :         /*--------------------------------------------------------------
     454                 :          * Transverse Mercator,(modified for Danish System 34 Sjaelland)
     455                 :          *-------------------------------------------------------------*/
     456                 :       case 22:
     457                 :         poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_22,
     458                 :                             GetMIFParm( papszNextField, 1, 0.0 ),
     459                 :                             GetMIFParm( papszNextField, 0, 0.0 ),
     460                 :                             GetMIFParm( papszNextField, 2, 1.0 ),
     461                 :                             GetMIFParm( papszNextField, 3, 0.0 ),
     462               0 :                             GetMIFParm( papszNextField, 4, 0.0 ));
     463               0 :         break;
     464                 : 
     465                 :         /*----------------------------------------------------------------
     466                 :          * Transverse Mercator,(modified for Danish System 34/45 Bornholm)
     467                 :          *---------------------------------------------------------------*/
     468                 :       case 23:
     469                 :         poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_23,
     470                 :                             GetMIFParm( papszNextField, 1, 0.0 ),
     471                 :                             GetMIFParm( papszNextField, 0, 0.0 ),
     472                 :                             GetMIFParm( papszNextField, 2, 1.0 ),
     473                 :                             GetMIFParm( papszNextField, 3, 0.0 ),
     474               0 :                             GetMIFParm( papszNextField, 4, 0.0 ));
     475               0 :         break;
     476                 : 
     477                 :         /*--------------------------------------------------------------
     478                 :          * Transverse Mercator,(modified for Finnish KKJ)
     479                 :          *-------------------------------------------------------------*/
     480                 :       case 24:
     481                 :         poSR->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_24,
     482                 :                             GetMIFParm( papszNextField, 1, 0.0 ),
     483                 :                             GetMIFParm( papszNextField, 0, 0.0 ),
     484                 :                             GetMIFParm( papszNextField, 2, 1.0 ),
     485                 :                             GetMIFParm( papszNextField, 3, 0.0 ),
     486               0 :                             GetMIFParm( papszNextField, 4, 0.0 ));
     487               0 :         break;
     488                 : 
     489                 :         /*--------------------------------------------------------------
     490                 :          * Albers Conic Equal Area
     491                 :          *-------------------------------------------------------------*/
     492                 :       case 9:
     493                 :         poSR->SetACEA( GetMIFParm( papszNextField, 2, 0.0 ),
     494                 :                        GetMIFParm( papszNextField, 3, 0.0 ),
     495                 :                        GetMIFParm( papszNextField, 1, 0.0 ),
     496                 :                        GetMIFParm( papszNextField, 0, 0.0 ),
     497                 :                        GetMIFParm( papszNextField, 4, 0.0 ),
     498               0 :                        GetMIFParm( papszNextField, 5, 0.0 ) );
     499               0 :         break;
     500                 : 
     501                 :         /*--------------------------------------------------------------
     502                 :          * Mercator
     503                 :          *-------------------------------------------------------------*/
     504                 :       case 10:
     505                 :         poSR->SetMercator( 0.0, GetMIFParm( papszNextField, 0, 0.0 ),
     506               0 :                            1.0, 0.0, 0.0 );
     507               0 :         break;
     508                 : 
     509                 :         /*--------------------------------------------------------------
     510                 :          * Miller Cylindrical
     511                 :          *-------------------------------------------------------------*/
     512                 :       case 11:
     513                 :         poSR->SetMC( 0.0, GetMIFParm( papszNextField, 0, 0.0 ),
     514               0 :                      0.0, 0.0 );
     515               0 :         break;
     516                 : 
     517                 :         /*--------------------------------------------------------------
     518                 :          * Robinson
     519                 :          *-------------------------------------------------------------*/
     520                 :       case 12:
     521                 :         poSR->SetRobinson( GetMIFParm( papszNextField, 0, 0.0 ),
     522               0 :                            0.0, 0.0 );
     523               0 :         break;
     524                 : 
     525                 :         /*--------------------------------------------------------------
     526                 :          * Mollweide
     527                 :          *-------------------------------------------------------------*/
     528                 :       case 13:
     529                 :         poSR->SetMollweide( GetMIFParm( papszNextField, 0, 0.0 ),
     530               0 :                             0.0, 0.0 );
     531               0 :         break;
     532                 : 
     533                 :         /*--------------------------------------------------------------
     534                 :          * Eckert IV
     535                 :          *-------------------------------------------------------------*/
     536                 :       case 14:
     537                 :         poSR->SetEckertIV( GetMIFParm( papszNextField, 0, 0.0 ),
     538               0 :                            0.0, 0.0 );
     539               0 :         break;
     540                 : 
     541                 :         /*--------------------------------------------------------------
     542                 :          * Eckert VI
     543                 :          *-------------------------------------------------------------*/
     544                 :       case 15:
     545                 :         poSR->SetEckertVI( GetMIFParm( papszNextField, 0, 0.0 ),
     546               0 :                            0.0, 0.0 );
     547               0 :         break;
     548                 : 
     549                 :         /*--------------------------------------------------------------
     550                 :          * Sinusoidal
     551                 :          *-------------------------------------------------------------*/
     552                 :       case 16:
     553                 :         poSR->SetSinusoidal( GetMIFParm( papszNextField, 0, 0.0 ),
     554               0 :                              0.0, 0.0 );
     555               0 :         break;
     556                 : 
     557                 :         /*--------------------------------------------------------------
     558                 :          * Gall
     559                 :          *-------------------------------------------------------------*/
     560                 :       case 17:
     561                 :         poSR->SetGS( GetMIFParm( papszNextField, 0, 0.0 ),
     562               0 :                      0.0, 0.0 );
     563               0 :         break;
     564                 :         
     565                 :         /*--------------------------------------------------------------
     566                 :          * New Zealand Map Grid
     567                 :          *-------------------------------------------------------------*/
     568                 :       case 18:
     569                 :         poSR->SetNZMG( GetMIFParm( papszNextField, 1, 0.0 ),
     570                 :                        GetMIFParm( papszNextField, 0, 0.0 ),
     571                 :                        GetMIFParm( papszNextField, 2, 0.0 ),
     572               0 :                        GetMIFParm( papszNextField, 3, 0.0 ) );
     573               0 :         break;
     574                 : 
     575                 :         /*--------------------------------------------------------------
     576                 :          * Lambert Conic Conformal (Belgium)
     577                 :          *-------------------------------------------------------------*/
     578                 :       case 19:
     579                 :         poSR->SetLCCB( GetMIFParm( papszNextField, 2, 0.0 ),
     580                 :                        GetMIFParm( papszNextField, 3, 0.0 ),
     581                 :                        GetMIFParm( papszNextField, 1, 0.0 ),
     582                 :                        GetMIFParm( papszNextField, 0, 0.0 ),
     583                 :                        GetMIFParm( papszNextField, 4, 0.0 ),
     584               0 :                        GetMIFParm( papszNextField, 5, 0.0 ) );
     585               0 :         break;
     586                 : 
     587                 :         /*--------------------------------------------------------------
     588                 :          * Stereographic
     589                 :          *-------------------------------------------------------------*/
     590                 :       case 20:
     591                 :       case 31: /* double stereographic */
     592                 :         poSR->SetStereographic( 
     593                 :             GetMIFParm( papszNextField, 1, 0.0 ),
     594                 :             GetMIFParm( papszNextField, 0, 0.0 ),
     595                 :             GetMIFParm( papszNextField, 2, 1.0 ),
     596                 :             GetMIFParm( papszNextField, 3, 0.0 ),
     597               0 :             GetMIFParm( papszNextField, 4, 0.0 ) );
     598               0 :         break;
     599                 : 
     600                 :         /*--------------------------------------------------------------
     601                 :          * Swiss Oblique Mercator / Cylindrical
     602                 :          *-------------------------------------------------------------*/
     603                 :       case 25:
     604                 :         poSR->SetSOC( GetMIFParm( papszNextField, 1, 0.0 ),
     605                 :                       GetMIFParm( papszNextField, 0, 0.0 ),
     606                 :                       GetMIFParm( papszNextField, 2, 0.0 ),
     607               0 :                       GetMIFParm( papszNextField, 3, 0.0 ) );
     608               0 :         break;
     609                 : 
     610                 :         /*--------------------------------------------------------------
     611                 :          * Regional Mercator
     612                 :          *-------------------------------------------------------------*/
     613                 :       case 26:
     614                 :         poSR->SetMercator( GetMIFParm( papszNextField, 1, 0.0 ), 
     615                 :                            GetMIFParm( papszNextField, 0, 0.0 ),
     616               0 :                            1.0, 0.0, 0.0 );
     617               0 :         break;
     618                 : 
     619                 :         /*--------------------------------------------------------------
     620                 :          * Polygonic
     621                 :          *-------------------------------------------------------------*/
     622                 :       case 27:
     623                 :         poSR->SetPolyconic( GetMIFParm( papszNextField, 1, 0.0 ), 
     624                 :                             GetMIFParm( papszNextField, 0, 0.0 ),
     625                 :                           GetMIFParm( papszNextField, 2, 0.0 ),
     626               0 :                           GetMIFParm( papszNextField, 3, 0.0 ) );
     627               0 :         break;
     628                 : 
     629                 :         /*--------------------------------------------------------------
     630                 :          * CassiniSoldner
     631                 :          *-------------------------------------------------------------*/
     632                 :       case 30:
     633                 :         poSR->SetCS( 
     634                 :             GetMIFParm( papszNextField, 1, 0.0 ),
     635                 :             GetMIFParm( papszNextField, 0, 0.0 ),
     636                 :             GetMIFParm( papszNextField, 2, 0.0 ),
     637               0 :             GetMIFParm( papszNextField, 3, 0.0 ) );
     638               0 :         break;
     639                 : 
     640                 :         /*--------------------------------------------------------------
     641                 :          * Krovak
     642                 :          *-------------------------------------------------------------*/
     643                 :        case 32:
     644                 :          poSR->SetKrovak( GetMIFParm( papszNextField, 1, 0.0 ),  // dfCenterLat
     645                 :                           GetMIFParm( papszNextField, 0, 0.0 ),  // dfCenterLong
     646                 :                           GetMIFParm( papszNextField, 3, 1.0 ),  // dfAzimuth
     647                 :                           GetMIFParm( papszNextField, 2, 0.0 ),  // dfPseudoStdParallelLat
     648                 :                           1.0,                    // dfScale
     649                 :                           GetMIFParm( papszNextField, 4, 0.0 ),  // dfFalseEasting
     650               0 :                           GetMIFParm( papszNextField, 5, 0.0 )); // dfFalseNorthing
     651                 :          break;
     652                 : 
     653                 :       default:
     654                 :         break;
     655                 :     }
     656                 : 
     657                 : /* -------------------------------------------------------------------- */
     658                 : /*      Set linear units.                                               */
     659                 : /* -------------------------------------------------------------------- */
     660               4 :     if( pszUnitsName != NULL )
     661               4 :         poSR->SetLinearUnits( pszUnitsName, dfUnitsConv );
     662                 : 
     663                 : /* -------------------------------------------------------------------- */
     664                 : /*      For Non-Earth projection, we're done at this point.             */
     665                 : /* -------------------------------------------------------------------- */
     666               4 :     if (nProjection == 0)
     667                 :     {
     668               0 :         CSLDestroy(papszFields);
     669               0 :         return poSR;
     670                 :     }
     671                 : 
     672                 : /* ==================================================================== */
     673                 : /*      Establish the GeogCS                                            */
     674                 : /* ==================================================================== */
     675               4 :     const char *pszGeogName = "unnamed";
     676               4 :     const char *pszSpheroidName = "GRS_1980";
     677               4 :     double      dfSemiMajor = 6378137.0;
     678               4 :     double      dfInvFlattening = 298.257222101;
     679               4 :     const char *pszPrimeM = "Greenwich";
     680               4 :     double      dfPMLongToGreenwich = 0.0;
     681                 : 
     682                 : /* -------------------------------------------------------------------- */
     683                 : /*      Find the datum, and collect it's parameters if possible.        */
     684                 : /* -------------------------------------------------------------------- */
     685                 :     int         iDatum;
     686               4 :     MapInfoDatumInfo *psDatumInfo = NULL;
     687                 :     
     688             393 :     for( iDatum = 0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++ )
     689                 :     {
     690             393 :         if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
     691                 :         {
     692               4 :             psDatumInfo = asDatumInfoList + iDatum;
     693               4 :             break;
     694                 :         }
     695                 :     }
     696                 : 
     697               4 :     if( asDatumInfoList[iDatum].nMapInfoDatumID == -1
     698                 :         && nDatum != 999 && nDatum != 9999 )
     699                 :     {
     700                 :         /* use WGS84 */
     701               0 :         psDatumInfo = asDatumInfoList + 0;
     702                 :     }
     703                 : 
     704               4 :     if( psDatumInfo != NULL )
     705                 :     {
     706               4 :         nEllipsoid = psDatumInfo->nEllipsoid;
     707               4 :         adfDatumParm[0] =  psDatumInfo->dfShiftX;
     708               4 :         adfDatumParm[1] = psDatumInfo->dfShiftY;
     709               4 :         adfDatumParm[2] = psDatumInfo->dfShiftZ;
     710               4 :         adfDatumParm[3] = psDatumInfo->dfDatumParm0;
     711               4 :         adfDatumParm[4] = psDatumInfo->dfDatumParm1;
     712               4 :         adfDatumParm[5] = psDatumInfo->dfDatumParm2;
     713               4 :         adfDatumParm[6] = psDatumInfo->dfDatumParm3;
     714               4 :         adfDatumParm[7] = psDatumInfo->dfDatumParm4;
     715                 :     }
     716                 :     
     717                 : /* -------------------------------------------------------------------- */
     718                 : /*      Set the spheroid if it is known from the table.                 */
     719                 : /* -------------------------------------------------------------------- */
     720              24 :     for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ )
     721                 :     {
     722              24 :         if( asSpheroidInfoList[i].nMapInfoId == nEllipsoid )
     723                 :         {
     724               4 :             dfSemiMajor = asSpheroidInfoList[i].dfA;
     725               4 :             dfInvFlattening = asSpheroidInfoList[i].dfInvFlattening;
     726               4 :             pszSpheroidName = asSpheroidInfoList[i].pszMapinfoName;
     727               4 :             break;
     728                 :         }
     729                 :     }
     730                 : 
     731                 : /* -------------------------------------------------------------------- */
     732                 : /*      apply datum parameters.                                         */
     733                 : /* -------------------------------------------------------------------- */
     734                 :     char        szDatumName[128];
     735                 : 
     736               4 :     if( nDatum == 999 )
     737                 :     {
     738                 :         sprintf( szDatumName,
     739                 :                  "MIF 9999,%d,%.15g,%.15g,%.15g",
     740                 :                  nEllipsoid,
     741                 :                  adfDatumParm[0],
     742                 :                  adfDatumParm[1],
     743               0 :                  adfDatumParm[2] );
     744                 :     }
     745               4 :     else if( nDatum == 9999 )
     746                 :     {
     747                 :         sprintf( szDatumName,
     748                 :                  "MIF 9999,%d,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",
     749                 :                  nEllipsoid,
     750                 :                  adfDatumParm[0],
     751                 :                  adfDatumParm[1],
     752                 :                  adfDatumParm[2],
     753                 :                  adfDatumParm[3],
     754                 :                  adfDatumParm[4],
     755                 :                  adfDatumParm[5],
     756                 :                  adfDatumParm[6],
     757               0 :                  adfDatumParm[7] );
     758                 :     }
     759               8 :     else if( psDatumInfo->pszOGCDatumName != NULL
     760                 :              && strlen(psDatumInfo->pszOGCDatumName) > 0 )
     761                 :     {
     762                 :         strncpy( szDatumName, psDatumInfo->pszOGCDatumName,
     763               4 :                  sizeof(szDatumName) );
     764                 :     }
     765                 :     else
     766                 :     {
     767               0 :         sprintf( szDatumName, "MIF %d", nDatum );
     768                 :     }
     769                 : 
     770                 : /* -------------------------------------------------------------------- */
     771                 : /*      Set prime meridian for 9999 datums.                             */
     772                 : /* -------------------------------------------------------------------- */
     773               4 :     if( nDatum == 9999 || adfDatumParm[7] != 0.0 )
     774                 :     {
     775               1 :         pszPrimeM = "non-Greenwich";
     776               1 :         dfPMLongToGreenwich = adfDatumParm[7];
     777                 :     }
     778                 : 
     779                 : /* -------------------------------------------------------------------- */
     780                 : /*      Set the GeogCS.                                                 */
     781                 : /* -------------------------------------------------------------------- */
     782                 :     poSR->SetGeogCS( pszGeogName, szDatumName, pszSpheroidName,
     783                 :                      dfSemiMajor, dfInvFlattening,
     784                 :                      pszPrimeM, dfPMLongToGreenwich,
     785                 :                      SRS_UA_DEGREE,
     786               4 :                      CPLAtof(SRS_UA_DEGREE_CONV) );
     787                 : 
     788                 :     poSR->SetTOWGS84( adfDatumParm[0], adfDatumParm[1], adfDatumParm[2],
     789              12 :                       -adfDatumParm[3], -adfDatumParm[4], -adfDatumParm[5], 
     790              16 :                       adfDatumParm[6] );
     791                 : 
     792                 :     /*-----------------------------------------------------------------
     793                 :      * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115)
     794                 :      *----------------------------------------------------------------*/
     795                 : 
     796               4 :     if( nBaseProjection == 10 && nDatum == 157 )
     797                 :     {
     798               0 :         poSR->SetNode( "PROJCS", "WGS 84 / Pseudo-Mercator" );
     799               0 :         poSR->SetExtension( "PROJCS", "PROJ4", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
     800                 :     }
     801                 : /* -------------------------------------------------------------------- */
     802                 : /*      Report on translation.                                          */
     803                 : /* -------------------------------------------------------------------- */
     804                 :     char        *pszWKT;
     805                 : 
     806               4 :     poSR->exportToWkt( &pszWKT );
     807               4 :     if( pszWKT != NULL )
     808                 :     {
     809                 :         CPLDebug( "MITAB",
     810                 :                   "This CoordSys value:\n%s\nwas translated to:\n%s\n",
     811               4 :                   pszCoordSys, pszWKT );
     812               4 :         CPLFree( pszWKT );
     813                 :     }
     814                 : 
     815               4 :     CSLDestroy(papszFields);
     816                 : 
     817               4 :     return poSR;
     818                 : }
     819                 : 
     820                 : /************************************************************************/
     821                 : /*                      MITABSpatialRef2CoordSys()                      */
     822                 : /*                                                                      */
     823                 : /*      Converts a OGRSpatialReference object into a MIF COORDSYS       */
     824                 : /*      string.                                                         */
     825                 : /*                                                                      */
     826                 : /*      The function returns a newly allocated string that should be    */
     827                 : /*      CPLFree()'d by the caller.                                      */
     828                 : /************************************************************************/
     829                 : 
     830               2 : char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
     831                 : 
     832                 : {
     833               2 :     if( poSR == NULL )
     834               0 :         return NULL;
     835                 :     
     836                 :     /*-----------------------------------------------------------------
     837                 :      * Get the linear units.
     838                 :      *----------------------------------------------------------------*/
     839                 :     double      dfLinearConv;
     840                 :     char        *pszLinearUnits;
     841                 : 
     842               2 :     dfLinearConv = poSR->GetLinearUnits( &pszLinearUnits );
     843                 : 
     844                 :     /*-----------------------------------------------------------------
     845                 :      * Transform the projection and projection parameters.
     846                 :      *----------------------------------------------------------------*/
     847               2 :     const char *pszProjection = poSR->GetAttrValue("PROJECTION");
     848                 :     double      parms[10];
     849               2 :     int         nProjection = 0;
     850               2 :     int         nParmCount = 0;
     851                 : 
     852               2 :     if( pszProjection == NULL )
     853                 :     {
     854                 :         /*--------------------------------------------------------------
     855                 :          * NULL projection.  
     856                 :          * We have 2 possibilities: CoordSys NonEarth or Lat/Lon 
     857                 :          * NonEarth ... is an empty SpatialRef.  
     858                 :          * Lat/Lon has no "PROJECTION" but GEOGCS is set
     859                 :          *-------------------------------------------------------------*/
     860               0 :          if ( poSR->GetAttrValue("GEOGCS") == NULL)
     861               0 :             nProjection = 0; // Non-Earth
     862                 :         else
     863               0 :             nProjection = 1; // Lat/Lon
     864                 :     }
     865               2 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     866                 :     {
     867               0 :         nProjection = 9;
     868               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     869               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     870               0 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     871               0 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     872               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     873               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     874               0 :         nParmCount = 6;
     875                 :     }
     876                 : 
     877               2 :     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     878                 :     {
     879               0 :         nProjection = 5;
     880               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     881               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     882               0 :         parms[2] = 90.0;
     883               0 :         nParmCount = 3;
     884                 : 
     885               0 :         if( ABS((ABS(parms[1]) - 90)) > 0.001 )
     886               0 :             nProjection = 28;
     887                 :     }
     888                 : 
     889               2 :     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
     890                 :     {
     891               0 :         nProjection = 2;
     892               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     893               0 :         parms[1] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     894               0 :         nParmCount = 2;
     895                 :     }
     896                 : 
     897               2 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
     898                 :     {
     899               0 :         nProjection = 14;
     900               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     901               0 :         nParmCount = 1;
     902                 :     }
     903                 : 
     904               2 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
     905                 :     {
     906               0 :         nProjection = 15;
     907               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     908               0 :         nParmCount = 1;
     909                 :     }
     910                 : 
     911               2 :     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
     912                 :     {
     913               0 :         nProjection = 6;
     914               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     915               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     916               0 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     917               0 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     918               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     919               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     920               0 :         nParmCount = 6;
     921                 :     }
     922                 : 
     923               2 :     else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
     924                 :     {
     925               0 :         nProjection = 17;
     926               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     927               0 :         nParmCount = 1;
     928                 :     }
     929                 : 
     930               2 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     931                 :     {
     932               0 :         nProjection = 7;
     933               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     934               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     935               0 :         parms[2] = poSR->GetProjParm(SRS_PP_AZIMUTH,0.0);
     936               0 :         parms[3] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
     937               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     938               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     939               0 :         nParmCount = 6;
     940                 :     }
     941                 : 
     942               2 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     943                 :     {
     944               0 :         nProjection = 4;
     945               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     946               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     947               0 :         parms[2] = 90.0;
     948               0 :         nParmCount = 3;
     949                 : 
     950               0 :         if( ABS((ABS(parms[1]) - 90)) > 0.001 )
     951               0 :             nProjection = 28;
     952                 :     }
     953                 : 
     954               2 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     955                 :     {
     956               1 :         nProjection = 3;
     957               1 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     958               1 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
     959               1 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     960               1 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     961               1 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     962               1 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     963               1 :         nParmCount = 6;
     964                 :     }
     965                 : 
     966               1 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
     967                 :     {
     968               0 :         nProjection = 19;
     969               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     970               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
     971               0 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     972               0 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     973               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     974               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     975               0 :         nParmCount = 6;
     976                 :     }
     977                 : 
     978               1 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
     979                 :     {
     980               0 :         nProjection = 10;
     981               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     982               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
     983               0 :         nParmCount = 1;
     984                 : 
     985               0 :         if( parms[1] != 0.0 )
     986                 :         {
     987               0 :             nProjection = 26;
     988               0 :             nParmCount = 2;
     989                 :         }
     990                 :     }
     991                 : 
     992               1 :     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
     993                 :     {
     994               0 :         nProjection = 11;
     995               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     996               0 :         nParmCount = 1;
     997                 :     }
     998                 : 
     999               1 :     else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
    1000                 :     {
    1001               0 :         nProjection = 13;
    1002               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1003               0 :         nParmCount = 1;
    1004                 :     }
    1005                 : 
    1006               1 :     else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
    1007                 :     {
    1008               0 :         nProjection = 25;
    1009               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1010               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1011               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1012               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1013               0 :         nParmCount = 4;
    1014                 :     }
    1015                 : 
    1016               1 :     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
    1017                 :     {
    1018               0 :         nProjection = 12;
    1019               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1020               0 :         nParmCount = 1;
    1021                 :     }
    1022                 : 
    1023               1 :     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
    1024                 :     {
    1025               0 :         nProjection = 16;
    1026               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1027               0 :         nParmCount = 1;
    1028                 :     }
    1029                 : 
    1030               1 :     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
    1031                 :     {
    1032               0 :         nProjection = 20;
    1033               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1034               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1035               0 :         parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1036               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1037               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1038               0 :         nParmCount = 5;
    1039                 :     }
    1040                 : 
    1041               1 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
    1042                 :     {
    1043               1 :         nProjection = 8;
    1044               1 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1045               1 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1046               1 :         parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1047               1 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1048               1 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1049               1 :         nParmCount = 5;
    1050                 :     }
    1051                 : 
    1052                 :     // Transverse Mercator,(modified for Danish System 34 Jylland-Fyn)
    1053               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) )
    1054                 :     {
    1055               0 :        nProjection = 21;
    1056               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1057               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1058               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1059               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1060               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1061               0 :        nParmCount = 5;
    1062                 :     }
    1063                 : 
    1064                 :     // Transverse Mercator,(modified for Danish System 34 Sjaelland)
    1065               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) )
    1066                 :     {
    1067               0 :        nProjection = 22;
    1068               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1069               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1070               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1071               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1072               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1073               0 :        nParmCount = 5;
    1074                 :     }
    1075                 : 
    1076                 :     // Transverse Mercator,(modified for Danish System 34/45 Bornholm)
    1077               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) )
    1078                 :     {
    1079               0 :        nProjection = 23;
    1080               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1081               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1082               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1083               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1084               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1085               0 :        nParmCount = 5;
    1086                 :     }
    1087                 : 
    1088                 :     // Transverse Mercator,(modified for Finnish KKJ)
    1089               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) )
    1090                 :     {
    1091               0 :        nProjection = 24;
    1092               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1093               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1094               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1095               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1096               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1097               0 :        nParmCount = 5;
    1098                 :     }
    1099                 : 
    1100               0 :     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
    1101                 :     {
    1102               0 :         nProjection = 30;
    1103               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1104               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1105               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1106               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1107               0 :         nParmCount = 4;
    1108                 :     }
    1109                 : 
    1110               0 :     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
    1111                 :     {
    1112               0 :         nProjection = 18;
    1113               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1114               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1115               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1116               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1117               0 :         nParmCount = 4;
    1118                 :     }
    1119                 : 
    1120               0 :     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
    1121                 :     {
    1122               0 :         nProjection = 27;
    1123               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1124               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1125               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1126               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1127               0 :         nParmCount = 4;
    1128                 :     }
    1129                 : 
    1130               0 :     else if( EQUAL(pszProjection,SRS_PT_KROVAK) )
    1131                 :     {
    1132               0 :         nProjection = 32;
    1133               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
    1134               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
    1135               0 :         parms[2] = poSR->GetProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1,0.0);
    1136               0 :         parms[3] = poSR->GetProjParm(SRS_PP_AZIMUTH,0.0);
    1137               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1138               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1139               0 :         nParmCount = 6;
    1140                 :     }
    1141                 : 
    1142                 :     /* ==============================================================
    1143                 :      * Translate Datum and Ellipsoid
    1144                 :      * ============================================================== */
    1145               2 :     int         nDatum = 0;
    1146               2 :     double      adfDatumParm[8] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
    1147               2 :     int         nEllipsoid=0;
    1148                 :     
    1149               2 :     int nDatumEPSGCode = -1;
    1150               2 :     const char *pszDatumAuthority = poSR->GetAuthorityName("DATUM");
    1151               2 :     const char *pszDatumCode = poSR->GetAuthorityCode("DATUM");
    1152                 :     
    1153               2 :     if (pszDatumCode && pszDatumAuthority && EQUAL(pszDatumAuthority, "EPSG"))
    1154                 :     {
    1155               2 :       nDatumEPSGCode = atoi(pszDatumCode);
    1156                 :     }
    1157                 :     
    1158               2 :     const char *pszWKTDatum = poSR->GetAttrValue("DATUM");
    1159                 : 
    1160               2 :     if( pszWKTDatum == NULL )
    1161                 :     {
    1162               0 :         nDatum = 0;
    1163               0 :         if( nProjection == 1 )
    1164               0 :             nProjection = 0;
    1165                 :     }
    1166                 :     
    1167                 :     /*-----------------------------------------------------------------
    1168                 :      * We know the MIF datum number, and need to look it up to
    1169                 :      * translate into datum parameters.
    1170                 :      *----------------------------------------------------------------*/
    1171               2 :     else if( EQUALN(pszWKTDatum,"MIF ",4)
    1172                 :              && atoi(pszWKTDatum+4) != 999
    1173                 :              && atoi(pszWKTDatum+4) != 9999 )
    1174                 :     {
    1175               0 :         nDatum = atoi(pszWKTDatum+4);
    1176                 :     }
    1177                 : 
    1178                 :     /*-----------------------------------------------------------------
    1179                 :      * We have the MIF datum parameters, and apply those directly.
    1180                 :      *----------------------------------------------------------------*/
    1181               2 :     else if( EQUALN(pszWKTDatum,"MIF ",4)
    1182                 :              && (atoi(pszWKTDatum+4) == 999 || atoi(pszWKTDatum+4) == 9999) )
    1183                 :     {
    1184                 :         char    **papszFields;
    1185                 :         
    1186               0 :         nDatum = atoi(pszWKTDatum+4);
    1187                 : 
    1188                 :         papszFields =
    1189               0 :             CSLTokenizeStringComplex( pszWKTDatum+4, ",", FALSE, TRUE);
    1190                 : 
    1191               0 :         if( CSLCount(papszFields) >= 5 )
    1192                 :         {
    1193               0 :             nEllipsoid = atoi(papszFields[1]);
    1194               0 :             adfDatumParm[0] = atof(papszFields[2]);
    1195               0 :             adfDatumParm[1] = atof(papszFields[3]);
    1196               0 :             adfDatumParm[2] = atof(papszFields[4]);
    1197                 :         }
    1198                 : 
    1199               0 :         if( CSLCount(papszFields) >= 10 )
    1200                 :         {
    1201               0 :             adfDatumParm[3] = atof(papszFields[5]);
    1202               0 :             adfDatumParm[4] = atof(papszFields[6]);
    1203               0 :             adfDatumParm[5] = atof(papszFields[7]);
    1204               0 :             adfDatumParm[6] = atof(papszFields[8]);
    1205               0 :             adfDatumParm[7] = atof(papszFields[9]);
    1206                 :         }
    1207                 : 
    1208               0 :         if( CSLCount(papszFields) < 5 )
    1209               0 :             nDatum = 104; /* WGS84 */
    1210                 : 
    1211               0 :         CSLDestroy( papszFields );
    1212                 :     }
    1213                 :     
    1214                 :     /*-----------------------------------------------------------------
    1215                 :      * We have a "real" datum name, and possibly an EPSG code for the
    1216                 :      * datum.  Try to look it up (using EPSG code first) and get the
    1217                 :      * parameters.  If we don't find it with either just use WGS84.
    1218                 :      *----------------------------------------------------------------*/
    1219                 :     else 
    1220                 :     {
    1221                 :         int     i;
    1222                 : 
    1223             132 :         for( i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
    1224                 :         {
    1225             132 :           if ( (nDatumEPSGCode > 0 && asDatumInfoList[i].nDatumEPSGCode == nDatumEPSGCode) ||
    1226                 :                EQUAL(pszWKTDatum,asDatumInfoList[i].pszOGCDatumName) )
    1227                 :             {
    1228               2 :                 nDatum = asDatumInfoList[i].nMapInfoDatumID;
    1229               2 :                 break;
    1230                 :             }
    1231                 :         }
    1232                 : 
    1233               2 :         if( nDatum == 0 )
    1234               0 :             nDatum = 104; /* WGS84 */
    1235                 :     }
    1236                 :     
    1237                 :     /*-----------------------------------------------------------------
    1238                 :      * Translate the units
    1239                 :      *----------------------------------------------------------------*/
    1240               2 :     const char  *pszMIFUnits = "m";
    1241                 : 
    1242               2 :     if( nProjection == 1 )
    1243               0 :         pszMIFUnits = NULL;
    1244               2 :     else if( pszLinearUnits == NULL )
    1245               0 :         pszMIFUnits = "m";
    1246               2 :     else if( dfLinearConv == 1000.0 )
    1247               0 :         pszMIFUnits = "km";
    1248               2 :     else if( dfLinearConv == 0.0254 || EQUAL(pszLinearUnits,"Inch")
    1249                 :              || EQUAL(pszLinearUnits,"IINCH"))
    1250               0 :         pszMIFUnits = "in";
    1251               2 :     else if( dfLinearConv == CPLAtof(SRS_UL_FOOT_CONV)
    1252                 :              || EQUAL(pszLinearUnits,SRS_UL_FOOT) )
    1253               0 :         pszMIFUnits = "ft";
    1254               2 :     else if( EQUAL(pszLinearUnits,"YARD") || EQUAL(pszLinearUnits,"IYARD") 
    1255                 :              || dfLinearConv == 0.9144 )
    1256               0 :         pszMIFUnits = "yd";
    1257               2 :     else if( dfLinearConv == 0.001 )
    1258               0 :         pszMIFUnits = "mm";
    1259               2 :     else if( dfLinearConv == 0.01 )
    1260               0 :         pszMIFUnits = "cm";
    1261               2 :     else if( dfLinearConv == 1.0 )
    1262               2 :         pszMIFUnits = "m";
    1263               0 :     else if( dfLinearConv == CPLAtof(SRS_UL_US_FOOT_CONV)
    1264                 :              || EQUAL(pszLinearUnits,SRS_UL_US_FOOT) )
    1265               0 :         pszMIFUnits = "survey ft";
    1266               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
    1267               0 :         pszMIFUnits = "nmi";
    1268               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_LINK) 
    1269                 :              || EQUAL(pszLinearUnits,"GUNTERLINK") )
    1270               0 :         pszMIFUnits = "li";
    1271               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_CHAIN) 
    1272                 :              || EQUAL(pszLinearUnits,"GUNTERCHAIN") )
    1273               0 :         pszMIFUnits = "ch";
    1274               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_ROD) )
    1275               0 :         pszMIFUnits = "rd";
    1276               0 :     else if( EQUAL(pszLinearUnits,"Mile") 
    1277                 :              || EQUAL(pszLinearUnits,"IMILE") )
    1278               0 :         pszMIFUnits = "mi";
    1279                 :     
    1280                 : /* -------------------------------------------------------------------- */
    1281                 : /*      Build coordinate system definition.                             */
    1282                 : /* -------------------------------------------------------------------- */
    1283                 :     char        szCoordSys[256];
    1284                 : 
    1285               2 :     if( nProjection != 0 )
    1286                 :     {
    1287                 :         sprintf( szCoordSys,
    1288                 :                  "Earth Projection %d",
    1289               2 :                  nProjection );
    1290                 : 
    1291                 :     }
    1292                 :     else
    1293                 :         sprintf( szCoordSys,
    1294               0 :                  "NonEarth Units" );
    1295                 : 
    1296                 : /* -------------------------------------------------------------------- */
    1297                 : /*      Append Datum                                                    */
    1298                 : /* -------------------------------------------------------------------- */
    1299               2 :     if( nProjection != 0 )
    1300                 :     {
    1301                 :         sprintf( szCoordSys + strlen(szCoordSys),
    1302                 :                  ", %d",
    1303               2 :                  nDatum );
    1304                 : 
    1305               2 :         if( nDatum == 999 || nDatum == 9999 )
    1306                 :         {
    1307                 :             sprintf( szCoordSys + strlen(szCoordSys),
    1308                 :                      ", %d, %.15g, %.15g, %.15g",
    1309                 :                      nEllipsoid,
    1310               0 :                      adfDatumParm[0], adfDatumParm[1], adfDatumParm[2] );
    1311                 :         }
    1312                 :         
    1313               2 :         if( nDatum == 9999 )
    1314                 :         {
    1315                 :             sprintf( szCoordSys + strlen(szCoordSys),
    1316                 :                      ", %.15g, %.15g, %.15g, %.15g, %.15g",
    1317                 :                      adfDatumParm[3], adfDatumParm[4], adfDatumParm[5],
    1318               0 :                      adfDatumParm[6], adfDatumParm[7] );
    1319                 :         }
    1320                 :     }
    1321                 : 
    1322                 : /* -------------------------------------------------------------------- */
    1323                 : /*      Append units.                                                   */
    1324                 : /* -------------------------------------------------------------------- */
    1325               2 :     if( nProjection != 1 && pszMIFUnits != NULL )
    1326                 :     {
    1327               2 :         if( nProjection != 0 )
    1328               2 :             strcat( szCoordSys, "," );
    1329                 :         
    1330                 :         sprintf( szCoordSys + strlen(szCoordSys),
    1331                 :                  " \"%s\"",
    1332               2 :                  pszMIFUnits );
    1333                 :     }
    1334                 : 
    1335                 : /* -------------------------------------------------------------------- */
    1336                 : /*      Append Projection Parms.                                        */
    1337                 : /* -------------------------------------------------------------------- */
    1338              13 :     for( int iParm = 0; iParm < nParmCount; iParm++ )
    1339                 :         sprintf( szCoordSys + strlen(szCoordSys),
    1340                 :                  ", %.15g",
    1341              11 :                  parms[iParm] );
    1342                 : 
    1343                 : /* -------------------------------------------------------------------- */
    1344                 : /*      Report on translation                                           */
    1345                 : /* -------------------------------------------------------------------- */
    1346               2 :     char        *pszWKT = NULL;
    1347                 : 
    1348               2 :     poSR->exportToWkt( &pszWKT );
    1349               2 :     if( pszWKT != NULL )
    1350                 :     {
    1351                 :         CPLDebug( "MITAB",
    1352                 :                   "This WKT Projection:\n%s\n\ntranslates to:\n%s\n",
    1353               2 :                   pszWKT, szCoordSys );
    1354               2 :         CPLFree( pszWKT );
    1355                 :     }
    1356                 : 
    1357               2 :     return( CPLStrdup( szCoordSys ) );
    1358                 : }
    1359                 : 
    1360                 : 
    1361                 : /************************************************************************/
    1362                 : /*                      MITABExtractCoordSysBounds                      */
    1363                 : /*                                                                      */
    1364                 : /* Return TRUE if MIF coordsys string contains a BOUNDS parameter and   */
    1365                 : /* Set x/y min/max values.                                              */
    1366                 : /************************************************************************/
    1367                 : 
    1368               0 : GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
    1369                 :                                   double &dXMin, double &dYMin,
    1370                 :                                   double &dXMax, double &dYMax )
    1371                 : 
    1372                 : {
    1373                 :     char        **papszFields;
    1374                 : 
    1375               0 :     if( pszCoordSys == NULL )
    1376               0 :         return FALSE;
    1377                 :     
    1378               0 :     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,()", TRUE, FALSE );
    1379                 : 
    1380               0 :     int iBounds = CSLFindString( papszFields, "Bounds" );
    1381                 : 
    1382               0 :     if (iBounds >= 0 && iBounds + 4 < CSLCount(papszFields))
    1383                 :     {
    1384               0 :         dXMin = atof(papszFields[++iBounds]);
    1385               0 :         dYMin = atof(papszFields[++iBounds]);
    1386               0 :         dXMax = atof(papszFields[++iBounds]);
    1387               0 :         dYMax = atof(papszFields[++iBounds]);
    1388               0 :         CSLDestroy( papszFields );
    1389               0 :         return TRUE;
    1390                 :     }
    1391                 : 
    1392               0 :     CSLDestroy( papszFields );
    1393               0 :     return FALSE;
    1394                 : }
    1395                 : 
    1396                 : 
    1397                 : /**********************************************************************
    1398                 :  *                     MITABCoordSys2TABProjInfo()
    1399                 :  *
    1400                 :  * Convert a MIF COORDSYS string into a TABProjInfo structure.
    1401                 :  *
    1402                 :  * Note that it would have been possible to achieve the same by calling
    1403                 :  * TABFile::SetSpatialRef( MITABCoordSys2SpatialRef() ) but this would 
    1404                 :  * involve lots of manipulations for cases where only a simple conversion
    1405                 :  * is required.
    1406                 :  *
    1407                 :  * Returns 0 on success, -1 on error.
    1408                 :  **********************************************************************/
    1409               0 : int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
    1410                 : 
    1411                 : {
    1412                 :     char        **papszFields;
    1413                 : 
    1414                 :     // Set all fields to zero, equivalent of NonEarth Units "mi"
    1415               0 :     memset(psProj, 0, sizeof(TABProjInfo));
    1416                 : 
    1417               0 :     if( pszCoordSys == NULL )
    1418               0 :         return -1;
    1419                 :     
    1420                 :     /*-----------------------------------------------------------------
    1421                 :      * Parse the passed string into words.
    1422                 :      *----------------------------------------------------------------*/
    1423               0 :     while(*pszCoordSys == ' ') pszCoordSys++;  // Eat leading spaces
    1424               0 :     if( EQUALN(pszCoordSys,"CoordSys",8) )
    1425               0 :         pszCoordSys += 9;
    1426                 :     
    1427               0 :     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
    1428                 : 
    1429                 :     /*-----------------------------------------------------------------
    1430                 :      * Clip off Bounds information.
    1431                 :      *----------------------------------------------------------------*/
    1432               0 :     int         iBounds = CSLFindString( papszFields, "Bounds" );
    1433                 : 
    1434               0 :     while( iBounds != -1 && papszFields[iBounds] != NULL )
    1435                 :     {
    1436               0 :         CPLFree( papszFields[iBounds] );
    1437               0 :         papszFields[iBounds] = NULL;
    1438               0 :         iBounds++;
    1439                 :     }
    1440                 : 
    1441                 :     /*-----------------------------------------------------------------
    1442                 :      * Fetch the projection.
    1443                 :      *----------------------------------------------------------------*/
    1444                 :     char        **papszNextField;
    1445                 : 
    1446               0 :     if( CSLCount( papszFields ) >= 3
    1447               0 :         && EQUAL(papszFields[0],"Earth")
    1448               0 :         && EQUAL(papszFields[1],"Projection") )
    1449                 :     {
    1450               0 :         psProj->nProjId = (GByte)atoi(papszFields[2]);
    1451               0 :         papszNextField = papszFields + 3;
    1452                 :     }
    1453               0 :     else if (CSLCount( papszFields ) >= 2
    1454               0 :              && EQUAL(papszFields[0],"NonEarth") )
    1455                 :     {
    1456                 :         // NonEarth Units "..." Bounds (x, y) (x, y)
    1457               0 :         psProj->nProjId = 0;
    1458               0 :         papszNextField = papszFields + 2;
    1459                 : 
    1460               0 :         if( papszNextField[0] != NULL && EQUAL(papszNextField[0],"Units") )
    1461               0 :             papszNextField++;
    1462                 :     }
    1463                 :     else
    1464                 :     {
    1465                 :         // Invalid projection string ???
    1466               0 :         if (CSLCount(papszFields) > 0)
    1467                 :             CPLError(CE_Warning, CPLE_IllegalArg,
    1468               0 :                      "Failed parsing CoordSys: '%s'", pszCoordSys);
    1469               0 :         CSLDestroy(papszFields);
    1470               0 :         return -1;
    1471                 :     }
    1472                 : 
    1473                 :     /*-----------------------------------------------------------------
    1474                 :      * Fetch the datum information.
    1475                 :      *----------------------------------------------------------------*/
    1476               0 :     int         nDatum = 0;
    1477                 : 
    1478               0 :     if( psProj->nProjId != 0 && CSLCount(papszNextField) > 0 )
    1479                 :     {
    1480               0 :         nDatum = atoi(papszNextField[0]);
    1481               0 :         papszNextField++;
    1482                 :     }
    1483                 : 
    1484               0 :     if( (nDatum == 999 || nDatum == 9999)
    1485                 :         && CSLCount(papszNextField) >= 4 )
    1486                 :     {
    1487               0 :         psProj->nEllipsoidId = (GByte)atoi(papszFields[0]);
    1488               0 :         psProj->dDatumShiftX = atof(papszNextField[1]);
    1489               0 :         psProj->dDatumShiftY = atof(papszNextField[2]);
    1490               0 :         psProj->dDatumShiftZ = atof(papszNextField[3]);
    1491               0 :         papszNextField += 4;
    1492                 : 
    1493               0 :         if( nDatum == 9999
    1494                 :             && CSLCount(papszNextField) >= 5 )
    1495                 :         {
    1496               0 :             psProj->adDatumParams[0] = atof(papszNextField[0]);
    1497               0 :             psProj->adDatumParams[1] = atof(papszNextField[1]);
    1498               0 :             psProj->adDatumParams[2] = atof(papszNextField[2]);
    1499               0 :             psProj->adDatumParams[3] = atof(papszNextField[3]);
    1500               0 :             psProj->adDatumParams[4] = atof(papszNextField[4]);
    1501               0 :             papszNextField += 5;
    1502                 :         }
    1503                 :     }
    1504               0 :     else if (nDatum != 999 && nDatum != 9999)
    1505                 :     {
    1506                 :     /*-----------------------------------------------------------------
    1507                 :      * Find the datum, and collect it's parameters if possible.
    1508                 :      *----------------------------------------------------------------*/
    1509                 :         int         iDatum;
    1510               0 :         MapInfoDatumInfo *psDatumInfo = NULL;
    1511                 :         
    1512               0 :         for(iDatum=0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++)
    1513                 :         {
    1514               0 :             if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
    1515                 :             {
    1516               0 :                 psDatumInfo = asDatumInfoList + iDatum;
    1517               0 :                 break;
    1518                 :             }
    1519                 :         }
    1520                 : 
    1521               0 :         if( asDatumInfoList[iDatum].nMapInfoDatumID == -1
    1522                 :             && nDatum != 999 && nDatum != 9999 )
    1523                 :         {
    1524                 :             /* use WGS84 */
    1525               0 :             psDatumInfo = asDatumInfoList + 0;
    1526                 :         }
    1527                 : 
    1528               0 :         if( psDatumInfo != NULL )
    1529                 :         {
    1530               0 :             psProj->nEllipsoidId = (GByte)psDatumInfo->nEllipsoid;
    1531               0 :             psProj->nDatumId = (GInt16)psDatumInfo->nMapInfoDatumID;
    1532               0 :             psProj->dDatumShiftX = psDatumInfo->dfShiftX;
    1533               0 :             psProj->dDatumShiftY = psDatumInfo->dfShiftY;
    1534               0 :             psProj->dDatumShiftZ = psDatumInfo->dfShiftZ;
    1535               0 :             psProj->adDatumParams[0] = psDatumInfo->dfDatumParm0;
    1536               0 :             psProj->adDatumParams[1] = psDatumInfo->dfDatumParm1;
    1537               0 :             psProj->adDatumParams[2] = psDatumInfo->dfDatumParm2;
    1538               0 :             psProj->adDatumParams[3] = psDatumInfo->dfDatumParm3;
    1539               0 :             psProj->adDatumParams[4] = psDatumInfo->dfDatumParm4;
    1540                 :         }
    1541                 :     }    
    1542                 : 
    1543                 :     /*-----------------------------------------------------------------
    1544                 :      * Fetch the units string.
    1545                 :      *----------------------------------------------------------------*/
    1546               0 :     if( CSLCount(papszNextField) > 0 )
    1547                 :     {
    1548               0 :         psProj->nUnitsId = (GByte)TABUnitIdFromString(papszNextField[0]);
    1549               0 :         papszNextField++;
    1550                 :     }
    1551                 : 
    1552                 :     /*-----------------------------------------------------------------
    1553                 :      * Finally the projection parameters.
    1554                 :      *----------------------------------------------------------------*/
    1555               0 :     for(int iParam=0; iParam < 6 && CSLCount(papszNextField) > 0; iParam++)
    1556                 :     {
    1557               0 :         psProj->adProjParams[iParam] = atof(papszNextField[0]);
    1558               0 :         papszNextField++;         
    1559                 :     }
    1560                 : 
    1561               0 :     return 0;
    1562                 : }
    1563                 : 

Generated by: LCOV version 1.7