LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mitab - mitab_coordsys.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 585 184 31.5 %
Date: 2012-04-28 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              44 : static double GetMIFParm( char ** papszFields, int iField, double dfDefault )
     129                 : 
     130                 : {
     131              44 :     if( iField >= CSLCount(papszFields) )
     132               0 :         return dfDefault;
     133                 :     else
     134              44 :         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               8 : OGRSpatialReference *MITABCoordSys2SpatialRef( const char * pszCoordSys )
     145                 : 
     146                 : {
     147                 :     char        **papszFields;
     148                 :     OGRSpatialReference *poSR;
     149                 : 
     150               8 :     if( pszCoordSys == NULL )
     151               0 :         return NULL;
     152                 :     
     153                 : /* -------------------------------------------------------------------- */
     154                 : /*      Parse the passed string into words.                             */
     155                 : /* -------------------------------------------------------------------- */
     156               8 :     while(*pszCoordSys == ' ') pszCoordSys++;  // Eat leading spaces
     157               8 :     if( EQUALN(pszCoordSys,"CoordSys",8) )
     158               4 :         pszCoordSys += 9;
     159                 :     
     160               8 :     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
     161                 : 
     162                 : /* -------------------------------------------------------------------- */
     163                 : /*      Clip off Bounds information.                                    */
     164                 : /* -------------------------------------------------------------------- */
     165               8 :     int         iBounds = CSLFindString( papszFields, "Bounds" );
     166                 : 
     167              28 :     while( iBounds != -1 && papszFields[iBounds] != NULL )
     168                 :     {
     169              12 :         CPLFree( papszFields[iBounds] );
     170              12 :         papszFields[iBounds] = NULL;
     171              12 :         iBounds++;
     172                 :     }
     173                 : 
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      Create a spatialreference object to operate on.                 */
     176                 : /* -------------------------------------------------------------------- */
     177               8 :     poSR = new OGRSpatialReference;
     178                 : 
     179                 : /* -------------------------------------------------------------------- */
     180                 : /*      Fetch the projection.                                           */
     181                 : /* -------------------------------------------------------------------- */
     182                 :     char        **papszNextField;
     183               8 :     int nProjection = 0;
     184                 : 
     185              24 :     if( CSLCount( papszFields ) >= 3
     186               8 :         && EQUAL(papszFields[0],"Earth")
     187               8 :         && EQUAL(papszFields[1],"Projection") )
     188                 :     {
     189               8 :         nProjection = atoi(papszFields[2]);
     190               8 :         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               8 :     int         nDatum = 0;
     217               8 :     double      adfDatumParm[8] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
     218               8 :     int         nEllipsoid=0;
     219                 : 
     220               8 :     if( nProjection != 0 && CSLCount(papszNextField) > 0 )
     221                 :     {
     222               8 :         nDatum = atoi(papszNextField[0]);
     223               8 :         papszNextField++;
     224                 :     }
     225                 : 
     226               8 :     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               8 :     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               8 :     const char  *pszMIFUnits = NULL;
     251               8 :     const char  *pszUnitsName = NULL;
     252               8 :     double dfUnitsConv = 1.0;
     253                 :     
     254               8 :     if( CSLCount(papszNextField) > 0 )
     255                 :     {
     256               8 :         pszMIFUnits = papszNextField[0];
     257               8 :         papszNextField++;
     258                 :     }
     259                 : 
     260               8 :     if( nProjection == 1 || pszMIFUnits == NULL )
     261                 :         /* do nothing */;
     262               8 :     else if( EQUAL(pszMIFUnits,"km") )
     263                 :     {
     264               0 :         pszUnitsName = "Kilometer"; 
     265               0 :         dfUnitsConv = 1000.0;
     266                 :     }
     267               8 :     else if( EQUAL(pszMIFUnits, "in" ) )
     268                 :     {
     269               0 :         pszUnitsName = "IINCH"; 
     270               0 :         dfUnitsConv = 0.0254; 
     271                 :     }
     272               8 :     else if( EQUAL(pszMIFUnits, "ft" ) )
     273                 :     {
     274               0 :         pszUnitsName = SRS_UL_FOOT;
     275               0 :         dfUnitsConv = CPLAtof(SRS_UL_FOOT_CONV);
     276                 :     }
     277               8 :     else if( EQUAL(pszMIFUnits, "yd" ) )
     278                 :     {
     279               0 :         pszUnitsName = "IYARD";
     280               0 :         dfUnitsConv = 0.9144;
     281                 :     }
     282               8 :     else if( EQUAL(pszMIFUnits, "mm" ) )
     283                 :     {
     284               0 :         pszUnitsName = "Millimeter";
     285               0 :         dfUnitsConv = 0.001;
     286                 :     }
     287               8 :     else if( EQUAL(pszMIFUnits, "cm" ) )
     288                 :     {
     289               0 :         pszUnitsName = "Centimeter";
     290               0 :         dfUnitsConv = 0.01;
     291                 :     }
     292               8 :     else if( EQUAL(pszMIFUnits, "m" ) )
     293                 :     {
     294               8 :         pszUnitsName = SRS_UL_METER;
     295               8 :         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               8 :     int nBaseProjection = nProjection;
     337               8 :     if (nBaseProjection>=3000) nBaseProjection -=3000;
     338               8 :     else if (nBaseProjection>=2000) nBaseProjection -=2000;
     339               8 :     else if (nBaseProjection>=1000) nBaseProjection -=1000;
     340               8 :     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               4 :                       GetMIFParm( papszNextField, 5, 0.0 ) );
     383               4 :         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               4 :                      GetMIFParm( papszNextField, 4, 0.0 ) );
     439               4 :         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                 : 
     532                 :         /*--------------------------------------------------------------
     533                 :          * Eckert IV
     534                 :          *-------------------------------------------------------------*/
     535                 :       case 14:
     536                 :         poSR->SetEckertIV( GetMIFParm( papszNextField, 0, 0.0 ),
     537               0 :                            0.0, 0.0 );
     538               0 :         break;
     539                 : 
     540                 :         /*--------------------------------------------------------------
     541                 :          * Eckert VI
     542                 :          *-------------------------------------------------------------*/
     543                 :       case 15:
     544                 :         poSR->SetEckertVI( GetMIFParm( papszNextField, 0, 0.0 ),
     545               0 :                            0.0, 0.0 );
     546               0 :         break;
     547                 : 
     548                 :         /*--------------------------------------------------------------
     549                 :          * Sinusoidal
     550                 :          *-------------------------------------------------------------*/
     551                 :       case 16:
     552                 :         poSR->SetSinusoidal( GetMIFParm( papszNextField, 0, 0.0 ),
     553               0 :                              0.0, 0.0 );
     554               0 :         break;
     555                 : 
     556                 :         /*--------------------------------------------------------------
     557                 :          * Gall
     558                 :          *-------------------------------------------------------------*/
     559                 :       case 17:
     560                 :         poSR->SetGS( GetMIFParm( papszNextField, 0, 0.0 ),
     561               0 :                      0.0, 0.0 );
     562               0 :         break;
     563                 :         
     564                 :         /*--------------------------------------------------------------
     565                 :          * New Zealand Map Grid
     566                 :          *-------------------------------------------------------------*/
     567                 :       case 18:
     568                 :         poSR->SetNZMG( GetMIFParm( papszNextField, 1, 0.0 ),
     569                 :                        GetMIFParm( papszNextField, 0, 0.0 ),
     570                 :                        GetMIFParm( papszNextField, 2, 0.0 ),
     571               0 :                        GetMIFParm( papszNextField, 3, 0.0 ) );
     572               0 :         break;
     573                 : 
     574                 :         /*--------------------------------------------------------------
     575                 :          * Lambert Conic Conformal (Belgium)
     576                 :          *-------------------------------------------------------------*/
     577                 :       case 19:
     578                 :         poSR->SetLCCB( GetMIFParm( papszNextField, 2, 0.0 ),
     579                 :                        GetMIFParm( papszNextField, 3, 0.0 ),
     580                 :                        GetMIFParm( papszNextField, 1, 0.0 ),
     581                 :                        GetMIFParm( papszNextField, 0, 0.0 ),
     582                 :                        GetMIFParm( papszNextField, 4, 0.0 ),
     583               0 :                        GetMIFParm( papszNextField, 5, 0.0 ) );
     584               0 :         break;
     585                 : 
     586                 :         /*--------------------------------------------------------------
     587                 :          * Stereographic
     588                 :          *-------------------------------------------------------------*/
     589                 :       case 20:
     590                 :       case 31: /* double stereographic */
     591                 :         poSR->SetStereographic( 
     592                 :             GetMIFParm( papszNextField, 1, 0.0 ),
     593                 :             GetMIFParm( papszNextField, 0, 0.0 ),
     594                 :             GetMIFParm( papszNextField, 2, 1.0 ),
     595                 :             GetMIFParm( papszNextField, 3, 0.0 ),
     596               0 :             GetMIFParm( papszNextField, 4, 0.0 ) );
     597               0 :         break;
     598                 : 
     599                 :         /*--------------------------------------------------------------
     600                 :          * Swiss Oblique Mercator / Cylindrical
     601                 :          *-------------------------------------------------------------*/
     602                 :       case 25:
     603                 :         poSR->SetSOC( GetMIFParm( papszNextField, 1, 0.0 ),
     604                 :                       GetMIFParm( papszNextField, 0, 0.0 ),
     605                 :                       GetMIFParm( papszNextField, 2, 0.0 ),
     606               0 :                       GetMIFParm( papszNextField, 3, 0.0 ) );
     607               0 :         break;
     608                 : 
     609                 :         /*--------------------------------------------------------------
     610                 :          * Regional Mercator
     611                 :          *-------------------------------------------------------------*/
     612                 :       case 26:
     613                 :         poSR->SetMercator( GetMIFParm( papszNextField, 1, 0.0 ), 
     614                 :                            GetMIFParm( papszNextField, 0, 0.0 ),
     615               0 :                            1.0, 0.0, 0.0 );
     616               0 :         break;
     617                 : 
     618                 :         /*--------------------------------------------------------------
     619                 :          * Polygonic
     620                 :          *-------------------------------------------------------------*/
     621                 :       case 27:
     622                 :         poSR->SetPolyconic( GetMIFParm( papszNextField, 1, 0.0 ), 
     623                 :                             GetMIFParm( papszNextField, 0, 0.0 ),
     624                 :                           GetMIFParm( papszNextField, 2, 0.0 ),
     625               0 :                           GetMIFParm( papszNextField, 3, 0.0 ) );
     626               0 :         break;
     627                 : 
     628                 :         /*--------------------------------------------------------------
     629                 :          * CassiniSoldner
     630                 :          *-------------------------------------------------------------*/
     631                 :       case 30:
     632                 :         poSR->SetCS( 
     633                 :             GetMIFParm( papszNextField, 1, 0.0 ),
     634                 :             GetMIFParm( papszNextField, 0, 0.0 ),
     635                 :             GetMIFParm( papszNextField, 2, 0.0 ),
     636               0 :             GetMIFParm( papszNextField, 3, 0.0 ) );
     637               0 :         break;
     638                 : 
     639                 :         /*--------------------------------------------------------------
     640                 :          * Krovak
     641                 :          *-------------------------------------------------------------*/
     642                 :        case 32:
     643                 :          poSR->SetKrovak( GetMIFParm( papszNextField, 1, 0.0 ),  // dfCenterLat
     644                 :                           GetMIFParm( papszNextField, 0, 0.0 ),  // dfCenterLong
     645                 :                           GetMIFParm( papszNextField, 3, 1.0 ),  // dfAzimuth
     646                 :                           GetMIFParm( papszNextField, 2, 0.0 ),  // dfPseudoStdParallelLat
     647                 :                           1.0,                    // dfScale
     648                 :                           GetMIFParm( papszNextField, 4, 0.0 ),  // dfFalseEasting
     649               0 :                           GetMIFParm( papszNextField, 5, 0.0 )); // dfFalseNorthing
     650                 :          break;
     651                 : 
     652                 :       default:
     653                 :         break;
     654                 :     }
     655                 : 
     656                 : /* -------------------------------------------------------------------- */
     657                 : /*      Set linear units.                                               */
     658                 : /* -------------------------------------------------------------------- */
     659               8 :     if( pszUnitsName != NULL )
     660               8 :         poSR->SetLinearUnits( pszUnitsName, dfUnitsConv );
     661                 : 
     662                 : /* -------------------------------------------------------------------- */
     663                 : /*      For Non-Earth projection, we're done at this point.             */
     664                 : /* -------------------------------------------------------------------- */
     665               8 :     if (nProjection == 0)
     666                 :     {
     667               0 :         CSLDestroy(papszFields);
     668               0 :         return poSR;
     669                 :     }
     670                 : 
     671                 : /* ==================================================================== */
     672                 : /*      Establish the GeogCS                                            */
     673                 : /* ==================================================================== */
     674               8 :     const char *pszGeogName = "unnamed";
     675               8 :     const char *pszSpheroidName = "GRS_1980";
     676               8 :     double      dfSemiMajor = 6378137.0;
     677               8 :     double      dfInvFlattening = 298.257222101;
     678               8 :     const char *pszPrimeM = "Greenwich";
     679               8 :     double      dfPMLongToGreenwich = 0.0;
     680                 : 
     681                 : /* -------------------------------------------------------------------- */
     682                 : /*      Find the datum, and collect it's parameters if possible.        */
     683                 : /* -------------------------------------------------------------------- */
     684                 :     int         iDatum;
     685               8 :     MapInfoDatumInfo *psDatumInfo = NULL;
     686                 :     
     687             786 :     for( iDatum = 0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++ )
     688                 :     {
     689             786 :         if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
     690                 :         {
     691               8 :             psDatumInfo = asDatumInfoList + iDatum;
     692               8 :             break;
     693                 :         }
     694                 :     }
     695                 : 
     696               8 :     if( asDatumInfoList[iDatum].nMapInfoDatumID == -1
     697                 :         && nDatum != 999 && nDatum != 9999 )
     698                 :     {
     699                 :         /* use WGS84 */
     700               0 :         psDatumInfo = asDatumInfoList + 0;
     701                 :     }
     702                 : 
     703               8 :     if( psDatumInfo != NULL )
     704                 :     {
     705               8 :         nEllipsoid = psDatumInfo->nEllipsoid;
     706               8 :         adfDatumParm[0] =  psDatumInfo->dfShiftX;
     707               8 :         adfDatumParm[1] = psDatumInfo->dfShiftY;
     708               8 :         adfDatumParm[2] = psDatumInfo->dfShiftZ;
     709               8 :         adfDatumParm[3] = psDatumInfo->dfDatumParm0;
     710               8 :         adfDatumParm[4] = psDatumInfo->dfDatumParm1;
     711               8 :         adfDatumParm[5] = psDatumInfo->dfDatumParm2;
     712               8 :         adfDatumParm[6] = psDatumInfo->dfDatumParm3;
     713               8 :         adfDatumParm[7] = psDatumInfo->dfDatumParm4;
     714                 :     }
     715                 :     
     716                 : /* -------------------------------------------------------------------- */
     717                 : /*      Set the spheroid if it is known from the table.                 */
     718                 : /* -------------------------------------------------------------------- */
     719              48 :     for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ )
     720                 :     {
     721              48 :         if( asSpheroidInfoList[i].nMapInfoId == nEllipsoid )
     722                 :         {
     723               8 :             dfSemiMajor = asSpheroidInfoList[i].dfA;
     724               8 :             dfInvFlattening = asSpheroidInfoList[i].dfInvFlattening;
     725               8 :             pszSpheroidName = asSpheroidInfoList[i].pszMapinfoName;
     726               8 :             break;
     727                 :         }
     728                 :     }
     729                 : 
     730                 : /* -------------------------------------------------------------------- */
     731                 : /*      apply datum parameters.                                         */
     732                 : /* -------------------------------------------------------------------- */
     733                 :     char        szDatumName[128];
     734                 : 
     735               8 :     if( nDatum == 999 )
     736                 :     {
     737                 :         sprintf( szDatumName,
     738                 :                  "MIF 9999,%d,%.15g,%.15g,%.15g",
     739                 :                  nEllipsoid,
     740                 :                  adfDatumParm[0],
     741                 :                  adfDatumParm[1],
     742               0 :                  adfDatumParm[2] );
     743                 :     }
     744               8 :     else if( nDatum == 9999 )
     745                 :     {
     746                 :         sprintf( szDatumName,
     747                 :                  "MIF 9999,%d,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",
     748                 :                  nEllipsoid,
     749                 :                  adfDatumParm[0],
     750                 :                  adfDatumParm[1],
     751                 :                  adfDatumParm[2],
     752                 :                  adfDatumParm[3],
     753                 :                  adfDatumParm[4],
     754                 :                  adfDatumParm[5],
     755                 :                  adfDatumParm[6],
     756               0 :                  adfDatumParm[7] );
     757                 :     }
     758              16 :     else if( psDatumInfo->pszOGCDatumName != NULL
     759                 :              && strlen(psDatumInfo->pszOGCDatumName) > 0 )
     760                 :     {
     761                 :         strncpy( szDatumName, psDatumInfo->pszOGCDatumName,
     762               8 :                  sizeof(szDatumName) );
     763                 :     }
     764                 :     else
     765                 :     {
     766               0 :         sprintf( szDatumName, "MIF %d", nDatum );
     767                 :     }
     768                 : 
     769                 : /* -------------------------------------------------------------------- */
     770                 : /*      Set prime meridian for 9999 datums.                             */
     771                 : /* -------------------------------------------------------------------- */
     772               8 :     if( nDatum == 9999 || adfDatumParm[7] != 0.0 )
     773                 :     {
     774               2 :         pszPrimeM = "non-Greenwich";
     775               2 :         dfPMLongToGreenwich = adfDatumParm[7];
     776                 :     }
     777                 : 
     778                 : /* -------------------------------------------------------------------- */
     779                 : /*      Set the GeogCS.                                                 */
     780                 : /* -------------------------------------------------------------------- */
     781                 :     poSR->SetGeogCS( pszGeogName, szDatumName, pszSpheroidName,
     782                 :                      dfSemiMajor, dfInvFlattening,
     783                 :                      pszPrimeM, dfPMLongToGreenwich,
     784                 :                      SRS_UA_DEGREE,
     785               8 :                      CPLAtof(SRS_UA_DEGREE_CONV) );
     786                 : 
     787                 :     poSR->SetTOWGS84( adfDatumParm[0], adfDatumParm[1], adfDatumParm[2],
     788              24 :                       -adfDatumParm[3], -adfDatumParm[4], -adfDatumParm[5], 
     789              32 :                       adfDatumParm[6] );
     790                 : 
     791                 :     /*-----------------------------------------------------------------
     792                 :      * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115)
     793                 :      *----------------------------------------------------------------*/
     794                 : 
     795               8 :     if( nBaseProjection == 10 && nDatum == 157 )
     796                 :     {
     797               0 :         poSR->SetNode( "PROJCS", "WGS 84 / Pseudo-Mercator" );
     798               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" );
     799                 :     }
     800                 : /* -------------------------------------------------------------------- */
     801                 : /*      Report on translation.                                          */
     802                 : /* -------------------------------------------------------------------- */
     803                 :     char        *pszWKT;
     804                 : 
     805               8 :     poSR->exportToWkt( &pszWKT );
     806               8 :     if( pszWKT != NULL )
     807                 :     {
     808                 :         CPLDebug( "MITAB",
     809                 :                   "This CoordSys value:\n%s\nwas translated to:\n%s\n",
     810               8 :                   pszCoordSys, pszWKT );
     811               8 :         CPLFree( pszWKT );
     812                 :     }
     813                 : 
     814               8 :     CSLDestroy(papszFields);
     815                 : 
     816               8 :     return poSR;
     817                 : }
     818                 : 
     819                 : /************************************************************************/
     820                 : /*                      MITABSpatialRef2CoordSys()                      */
     821                 : /*                                                                      */
     822                 : /*      Converts a OGRSpatialReference object into a MIF COORDSYS       */
     823                 : /*      string.                                                         */
     824                 : /*                                                                      */
     825                 : /*      The function returns a newly allocated string that should be    */
     826                 : /*      CPLFree()'d by the caller.                                      */
     827                 : /************************************************************************/
     828                 : 
     829               4 : char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
     830                 : 
     831                 : {
     832               4 :     if( poSR == NULL )
     833               0 :         return NULL;
     834                 :     
     835                 :     /*-----------------------------------------------------------------
     836                 :      * Get the linear units.
     837                 :      *----------------------------------------------------------------*/
     838                 :     double      dfLinearConv;
     839                 :     char        *pszLinearUnits;
     840                 : 
     841               4 :     dfLinearConv = poSR->GetLinearUnits( &pszLinearUnits );
     842                 : 
     843                 :     /*-----------------------------------------------------------------
     844                 :      * Transform the projection and projection parameters.
     845                 :      *----------------------------------------------------------------*/
     846               4 :     const char *pszProjection = poSR->GetAttrValue("PROJECTION");
     847                 :     double      parms[10];
     848               4 :     int         nProjection = 0;
     849               4 :     int         nParmCount = 0;
     850                 : 
     851               4 :     if( pszProjection == NULL )
     852                 :     {
     853                 :         /*--------------------------------------------------------------
     854                 :          * NULL projection.  
     855                 :          * We have 2 possibilities: CoordSys NonEarth or Lat/Lon 
     856                 :          * NonEarth ... is an empty SpatialRef.  
     857                 :          * Lat/Lon has no "PROJECTION" but GEOGCS is set
     858                 :          *-------------------------------------------------------------*/
     859               0 :          if ( poSR->GetAttrValue("GEOGCS") == NULL)
     860               0 :             nProjection = 0; // Non-Earth
     861                 :         else
     862               0 :             nProjection = 1; // Lat/Lon
     863                 :     }
     864               4 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     865                 :     {
     866               0 :         nProjection = 9;
     867               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     868               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     869               0 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     870               0 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     871               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     872               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     873               0 :         nParmCount = 6;
     874                 :     }
     875                 : 
     876               4 :     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     877                 :     {
     878               0 :         nProjection = 5;
     879               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     880               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     881               0 :         parms[2] = 90.0;
     882               0 :         nParmCount = 3;
     883                 : 
     884               0 :         if( ABS((ABS(parms[1]) - 90)) > 0.001 )
     885               0 :             nProjection = 28;
     886                 :     }
     887                 : 
     888               4 :     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
     889                 :     {
     890               0 :         nProjection = 2;
     891               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     892               0 :         parms[1] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     893               0 :         nParmCount = 2;
     894                 :     }
     895                 : 
     896               4 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
     897                 :     {
     898               0 :         nProjection = 14;
     899               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     900               0 :         nParmCount = 1;
     901                 :     }
     902                 : 
     903               4 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
     904                 :     {
     905               0 :         nProjection = 15;
     906               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     907               0 :         nParmCount = 1;
     908                 :     }
     909                 : 
     910               4 :     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
     911                 :     {
     912               0 :         nProjection = 6;
     913               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     914               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     915               0 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     916               0 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     917               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     918               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     919               0 :         nParmCount = 6;
     920                 :     }
     921                 : 
     922               4 :     else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
     923                 :     {
     924               0 :         nProjection = 17;
     925               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     926               0 :         nParmCount = 1;
     927                 :     }
     928                 : 
     929               4 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     930                 :     {
     931               0 :         nProjection = 7;
     932               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     933               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     934               0 :         parms[2] = poSR->GetProjParm(SRS_PP_AZIMUTH,0.0);
     935               0 :         parms[3] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
     936               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     937               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     938               0 :         nParmCount = 6;
     939                 :     }
     940                 : 
     941               4 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     942                 :     {
     943               0 :         nProjection = 4;
     944               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     945               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
     946               0 :         parms[2] = 90.0;
     947               0 :         nParmCount = 3;
     948                 : 
     949               0 :         if( ABS((ABS(parms[1]) - 90)) > 0.001 )
     950               0 :             nProjection = 28;
     951                 :     }
     952                 : 
     953               4 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     954                 :     {
     955               2 :         nProjection = 3;
     956               2 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     957               2 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
     958               2 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     959               2 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     960               2 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     961               2 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     962               2 :         nParmCount = 6;
     963                 :     }
     964                 : 
     965               2 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
     966                 :     {
     967               0 :         nProjection = 19;
     968               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     969               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
     970               0 :         parms[2] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
     971               0 :         parms[3] = poSR->GetProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0);
     972               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
     973               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
     974               0 :         nParmCount = 6;
     975                 :     }
     976                 : 
     977               2 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
     978                 :     {
     979               0 :         nProjection = 10;
     980               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     981               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
     982               0 :         nParmCount = 1;
     983                 : 
     984               0 :         if( parms[1] != 0.0 )
     985                 :         {
     986               0 :             nProjection = 26;
     987               0 :             nParmCount = 2;
     988                 :         }
     989                 :     }
     990                 : 
     991               2 :     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
     992                 :     {
     993               0 :         nProjection = 11;
     994               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
     995               0 :         nParmCount = 1;
     996                 :     }
     997                 : 
     998               2 :     else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
     999                 :     {
    1000               0 :         nProjection = 13;
    1001               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1002               0 :         nParmCount = 1;
    1003                 :     }
    1004                 : 
    1005               2 :     else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
    1006                 :     {
    1007               0 :         nProjection = 25;
    1008               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1009               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1010               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1011               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1012               0 :         nParmCount = 4;
    1013                 :     }
    1014                 : 
    1015               2 :     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
    1016                 :     {
    1017               0 :         nProjection = 12;
    1018               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1019               0 :         nParmCount = 1;
    1020                 :     }
    1021                 : 
    1022               2 :     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
    1023                 :     {
    1024               0 :         nProjection = 16;
    1025               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1026               0 :         nParmCount = 1;
    1027                 :     }
    1028                 : 
    1029               2 :     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
    1030                 :     {
    1031               0 :         nProjection = 20;
    1032               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1033               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1034               0 :         parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1035               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1036               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1037               0 :         nParmCount = 5;
    1038                 :     }
    1039                 : 
    1040               2 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
    1041                 :     {
    1042               2 :         nProjection = 8;
    1043               2 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1044               2 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1045               2 :         parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1046               2 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1047               2 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1048               2 :         nParmCount = 5;
    1049                 :     }
    1050                 : 
    1051                 :     // Transverse Mercator,(modified for Danish System 34 Jylland-Fyn)
    1052               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) )
    1053                 :     {
    1054               0 :        nProjection = 21;
    1055               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1056               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1057               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1058               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1059               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1060               0 :        nParmCount = 5;
    1061                 :     }
    1062                 : 
    1063                 :     // Transverse Mercator,(modified for Danish System 34 Sjaelland)
    1064               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) )
    1065                 :     {
    1066               0 :        nProjection = 22;
    1067               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1068               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1069               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1070               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1071               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1072               0 :        nParmCount = 5;
    1073                 :     }
    1074                 : 
    1075                 :     // Transverse Mercator,(modified for Danish System 34/45 Bornholm)
    1076               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) )
    1077                 :     {
    1078               0 :        nProjection = 23;
    1079               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1080               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1081               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1082               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1083               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1084               0 :        nParmCount = 5;
    1085                 :     }
    1086                 : 
    1087                 :     // Transverse Mercator,(modified for Finnish KKJ)
    1088               0 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) )
    1089                 :     {
    1090               0 :        nProjection = 24;
    1091               0 :        parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1092               0 :        parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1093               0 :        parms[2] = poSR->GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    1094               0 :        parms[3] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1095               0 :        parms[4] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1096               0 :        nParmCount = 5;
    1097                 :     }
    1098                 : 
    1099               0 :     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
    1100                 :     {
    1101               0 :         nProjection = 30;
    1102               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1103               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1104               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1105               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1106               0 :         nParmCount = 4;
    1107                 :     }
    1108                 : 
    1109               0 :     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
    1110                 :     {
    1111               0 :         nProjection = 18;
    1112               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1113               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1114               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1115               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1116               0 :         nParmCount = 4;
    1117                 :     }
    1118                 : 
    1119               0 :     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
    1120                 :     {
    1121               0 :         nProjection = 27;
    1122               0 :         parms[0] = poSR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
    1123               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
    1124               0 :         parms[2] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1125               0 :         parms[3] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1126               0 :         nParmCount = 4;
    1127                 :     }
    1128                 : 
    1129               0 :     else if( EQUAL(pszProjection,SRS_PT_KROVAK) )
    1130                 :     {
    1131               0 :         nProjection = 32;
    1132               0 :         parms[0] = poSR->GetProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0);
    1133               0 :         parms[1] = poSR->GetProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0);
    1134               0 :         parms[2] = poSR->GetProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1,0.0);
    1135               0 :         parms[3] = poSR->GetProjParm(SRS_PP_AZIMUTH,0.0);
    1136               0 :         parms[4] = poSR->GetProjParm(SRS_PP_FALSE_EASTING,0.0);
    1137               0 :         parms[5] = poSR->GetProjParm(SRS_PP_FALSE_NORTHING,0.0);
    1138               0 :         nParmCount = 6;
    1139                 :     }
    1140                 : 
    1141                 :     /* ==============================================================
    1142                 :      * Translate Datum and Ellipsoid
    1143                 :      * ============================================================== */
    1144               4 :     int         nDatum = 0;
    1145               4 :     double      adfDatumParm[8] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
    1146               4 :     int         nEllipsoid=0;
    1147                 :     
    1148               4 :     const char *pszWKTDatum = poSR->GetAttrValue("DATUM");
    1149                 : 
    1150               4 :     if( pszWKTDatum == NULL )
    1151                 :     {
    1152               0 :         nDatum = 0;
    1153               0 :         if( nProjection == 1 )
    1154               0 :             nProjection = 0;
    1155                 :     }
    1156                 :     
    1157                 :     /*-----------------------------------------------------------------
    1158                 :      * We know the MIF datum number, and need to look it up to
    1159                 :      * translate into datum parameters.
    1160                 :      *----------------------------------------------------------------*/
    1161               4 :     else if( EQUALN(pszWKTDatum,"MIF ",4)
    1162                 :              && atoi(pszWKTDatum+4) != 999
    1163                 :              && atoi(pszWKTDatum+4) != 9999 )
    1164                 :     {
    1165               0 :         nDatum = atoi(pszWKTDatum+4);
    1166                 :     }
    1167                 : 
    1168                 :     /*-----------------------------------------------------------------
    1169                 :      * We have the MIF datum parameters, and apply those directly.
    1170                 :      *----------------------------------------------------------------*/
    1171               4 :     else if( EQUALN(pszWKTDatum,"MIF ",4)
    1172                 :              && (atoi(pszWKTDatum+4) == 999 || atoi(pszWKTDatum+4) == 9999) )
    1173                 :     {
    1174                 :         char    **papszFields;
    1175                 :         
    1176               0 :         nDatum = atoi(pszWKTDatum+4);
    1177                 : 
    1178                 :         papszFields =
    1179               0 :             CSLTokenizeStringComplex( pszWKTDatum+4, ",", FALSE, TRUE);
    1180                 : 
    1181               0 :         if( CSLCount(papszFields) >= 5 )
    1182                 :         {
    1183               0 :             nEllipsoid = atoi(papszFields[1]);
    1184               0 :             adfDatumParm[0] = atof(papszFields[2]);
    1185               0 :             adfDatumParm[1] = atof(papszFields[3]);
    1186               0 :             adfDatumParm[2] = atof(papszFields[4]);
    1187                 :         }
    1188                 : 
    1189               0 :         if( CSLCount(papszFields) >= 10 )
    1190                 :         {
    1191               0 :             adfDatumParm[3] = atof(papszFields[5]);
    1192               0 :             adfDatumParm[4] = atof(papszFields[6]);
    1193               0 :             adfDatumParm[5] = atof(papszFields[7]);
    1194               0 :             adfDatumParm[6] = atof(papszFields[8]);
    1195               0 :             adfDatumParm[7] = atof(papszFields[9]);
    1196                 :         }
    1197                 : 
    1198               0 :         if( CSLCount(papszFields) < 5 )
    1199               0 :             nDatum = 104; /* WGS84 */
    1200                 : 
    1201               0 :         CSLDestroy( papszFields );
    1202                 :     }
    1203                 :     
    1204                 :     /*-----------------------------------------------------------------
    1205                 :      * We have a "real" datum name.  Try to look it up and get the
    1206                 :      * parameters.  If we don't find it just use WGS84.
    1207                 :      *----------------------------------------------------------------*/
    1208                 :     else 
    1209                 :     {
    1210                 :         int     i;
    1211                 : 
    1212             268 :         for( i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
    1213                 :         {
    1214             268 :             if( EQUAL(pszWKTDatum,asDatumInfoList[i].pszOGCDatumName) )
    1215                 :             {
    1216               4 :                 nDatum = asDatumInfoList[i].nMapInfoDatumID;
    1217               4 :                 break;
    1218                 :             }
    1219                 :         }
    1220                 : 
    1221               4 :         if( nDatum == 0 )
    1222               0 :             nDatum = 104; /* WGS84 */
    1223                 :     }
    1224                 : 
    1225                 :     /*-----------------------------------------------------------------
    1226                 :      * Translate the units
    1227                 :      *----------------------------------------------------------------*/
    1228               4 :     const char  *pszMIFUnits = "m";
    1229                 : 
    1230               4 :     if( nProjection == 1 )
    1231               0 :         pszMIFUnits = NULL;
    1232               4 :     else if( pszLinearUnits == NULL )
    1233               0 :         pszMIFUnits = "m";
    1234               4 :     else if( dfLinearConv == 1000.0 )
    1235               0 :         pszMIFUnits = "km";
    1236               4 :     else if( dfLinearConv == 0.0254 || EQUAL(pszLinearUnits,"Inch")
    1237                 :              || EQUAL(pszLinearUnits,"IINCH"))
    1238               0 :         pszMIFUnits = "in";
    1239               4 :     else if( dfLinearConv == CPLAtof(SRS_UL_FOOT_CONV)
    1240                 :              || EQUAL(pszLinearUnits,SRS_UL_FOOT) )
    1241               0 :         pszMIFUnits = "ft";
    1242               4 :     else if( EQUAL(pszLinearUnits,"YARD") || EQUAL(pszLinearUnits,"IYARD") 
    1243                 :              || dfLinearConv == 0.9144 )
    1244               0 :         pszMIFUnits = "yd";
    1245               4 :     else if( dfLinearConv == 0.001 )
    1246               0 :         pszMIFUnits = "mm";
    1247               4 :     else if( dfLinearConv == 0.01 )
    1248               0 :         pszMIFUnits = "cm";
    1249               4 :     else if( dfLinearConv == 1.0 )
    1250               4 :         pszMIFUnits = "m";
    1251               0 :     else if( dfLinearConv == CPLAtof(SRS_UL_US_FOOT_CONV)
    1252                 :              || EQUAL(pszLinearUnits,SRS_UL_US_FOOT) )
    1253               0 :         pszMIFUnits = "survey ft";
    1254               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
    1255               0 :         pszMIFUnits = "nmi";
    1256               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_LINK) 
    1257                 :              || EQUAL(pszLinearUnits,"GUNTERLINK") )
    1258               0 :         pszMIFUnits = "li";
    1259               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_CHAIN) 
    1260                 :              || EQUAL(pszLinearUnits,"GUNTERCHAIN") )
    1261               0 :         pszMIFUnits = "ch";
    1262               0 :     else if( EQUAL(pszLinearUnits,SRS_UL_ROD) )
    1263               0 :         pszMIFUnits = "rd";
    1264               0 :     else if( EQUAL(pszLinearUnits,"Mile") 
    1265                 :              || EQUAL(pszLinearUnits,"IMILE") )
    1266               0 :         pszMIFUnits = "mi";
    1267                 :     
    1268                 : /* -------------------------------------------------------------------- */
    1269                 : /*      Build coordinate system definition.                             */
    1270                 : /* -------------------------------------------------------------------- */
    1271                 :     char        szCoordSys[256];
    1272                 : 
    1273               4 :     if( nProjection != 0 )
    1274                 :     {
    1275                 :         sprintf( szCoordSys,
    1276                 :                  "Earth Projection %d",
    1277               4 :                  nProjection );
    1278                 : 
    1279                 :     }
    1280                 :     else
    1281                 :         sprintf( szCoordSys,
    1282               0 :                  "NonEarth Units" );
    1283                 : 
    1284                 : /* -------------------------------------------------------------------- */
    1285                 : /*      Append Datum                                                    */
    1286                 : /* -------------------------------------------------------------------- */
    1287               4 :     if( nProjection != 0 )
    1288                 :     {
    1289                 :         sprintf( szCoordSys + strlen(szCoordSys),
    1290                 :                  ", %d",
    1291               4 :                  nDatum );
    1292                 : 
    1293               4 :         if( nDatum == 999 || nDatum == 9999 )
    1294                 :         {
    1295                 :             sprintf( szCoordSys + strlen(szCoordSys),
    1296                 :                      ", %d, %.15g, %.15g, %.15g",
    1297                 :                      nEllipsoid,
    1298               0 :                      adfDatumParm[0], adfDatumParm[1], adfDatumParm[2] );
    1299                 :         }
    1300                 :         
    1301               4 :         if( nDatum == 9999 )
    1302                 :         {
    1303                 :             sprintf( szCoordSys + strlen(szCoordSys),
    1304                 :                      ", %.15g, %.15g, %.15g, %.15g, %.15g",
    1305                 :                      adfDatumParm[3], adfDatumParm[4], adfDatumParm[5],
    1306               0 :                      adfDatumParm[6], adfDatumParm[7] );
    1307                 :         }
    1308                 :     }
    1309                 : 
    1310                 : /* -------------------------------------------------------------------- */
    1311                 : /*      Append units.                                                   */
    1312                 : /* -------------------------------------------------------------------- */
    1313               4 :     if( nProjection != 1 && pszMIFUnits != NULL )
    1314                 :     {
    1315               4 :         if( nProjection != 0 )
    1316               4 :             strcat( szCoordSys, "," );
    1317                 :         
    1318                 :         sprintf( szCoordSys + strlen(szCoordSys),
    1319                 :                  " \"%s\"",
    1320               4 :                  pszMIFUnits );
    1321                 :     }
    1322                 : 
    1323                 : /* -------------------------------------------------------------------- */
    1324                 : /*      Append Projection Parms.                                        */
    1325                 : /* -------------------------------------------------------------------- */
    1326              26 :     for( int iParm = 0; iParm < nParmCount; iParm++ )
    1327                 :         sprintf( szCoordSys + strlen(szCoordSys),
    1328                 :                  ", %.15g",
    1329              22 :                  parms[iParm] );
    1330                 : 
    1331                 : /* -------------------------------------------------------------------- */
    1332                 : /*      Report on translation                                           */
    1333                 : /* -------------------------------------------------------------------- */
    1334               4 :     char        *pszWKT = NULL;
    1335                 : 
    1336               4 :     poSR->exportToWkt( &pszWKT );
    1337               4 :     if( pszWKT != NULL )
    1338                 :     {
    1339                 :         CPLDebug( "MITAB",
    1340                 :                   "This WKT Projection:\n%s\n\ntranslates to:\n%s\n",
    1341               4 :                   pszWKT, szCoordSys );
    1342               4 :         CPLFree( pszWKT );
    1343                 :     }
    1344                 : 
    1345               4 :     return( CPLStrdup( szCoordSys ) );
    1346                 : }
    1347                 : 
    1348                 : 
    1349                 : /************************************************************************/
    1350                 : /*                      MITABExtractCoordSysBounds                      */
    1351                 : /*                                                                      */
    1352                 : /* Return TRUE if MIF coordsys string contains a BOUNDS parameter and   */
    1353                 : /* Set x/y min/max values.                                              */
    1354                 : /************************************************************************/
    1355                 : 
    1356               0 : GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
    1357                 :                                   double &dXMin, double &dYMin,
    1358                 :                                   double &dXMax, double &dYMax )
    1359                 : 
    1360                 : {
    1361                 :     char        **papszFields;
    1362                 : 
    1363               0 :     if( pszCoordSys == NULL )
    1364               0 :         return FALSE;
    1365                 :     
    1366               0 :     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,()", TRUE, FALSE );
    1367                 : 
    1368               0 :     int iBounds = CSLFindString( papszFields, "Bounds" );
    1369                 : 
    1370               0 :     if (iBounds >= 0 && iBounds + 4 < CSLCount(papszFields))
    1371                 :     {
    1372               0 :         dXMin = atof(papszFields[++iBounds]);
    1373               0 :         dYMin = atof(papszFields[++iBounds]);
    1374               0 :         dXMax = atof(papszFields[++iBounds]);
    1375               0 :         dYMax = atof(papszFields[++iBounds]);
    1376               0 :         CSLDestroy( papszFields );
    1377               0 :         return TRUE;
    1378                 :     }
    1379                 : 
    1380               0 :     CSLDestroy( papszFields );
    1381               0 :     return FALSE;
    1382                 : }
    1383                 : 
    1384                 : 
    1385                 : /**********************************************************************
    1386                 :  *                     MITABCoordSys2TABProjInfo()
    1387                 :  *
    1388                 :  * Convert a MIF COORDSYS string into a TABProjInfo structure.
    1389                 :  *
    1390                 :  * Note that it would have been possible to achieve the same by calling
    1391                 :  * TABFile::SetSpatialRef( MITABCoordSys2SpatialRef() ) but this would 
    1392                 :  * involve lots of manipulations for cases where only a simple conversion
    1393                 :  * is required.
    1394                 :  *
    1395                 :  * Returns 0 on success, -1 on error.
    1396                 :  **********************************************************************/
    1397               0 : int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
    1398                 : 
    1399                 : {
    1400                 :     char        **papszFields;
    1401                 : 
    1402                 :     // Set all fields to zero, equivalent of NonEarth Units "mi"
    1403               0 :     memset(psProj, 0, sizeof(TABProjInfo));
    1404                 : 
    1405               0 :     if( pszCoordSys == NULL )
    1406               0 :         return -1;
    1407                 :     
    1408                 :     /*-----------------------------------------------------------------
    1409                 :      * Parse the passed string into words.
    1410                 :      *----------------------------------------------------------------*/
    1411               0 :     while(*pszCoordSys == ' ') pszCoordSys++;  // Eat leading spaces
    1412               0 :     if( EQUALN(pszCoordSys,"CoordSys",8) )
    1413               0 :         pszCoordSys += 9;
    1414                 :     
    1415               0 :     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
    1416                 : 
    1417                 :     /*-----------------------------------------------------------------
    1418                 :      * Clip off Bounds information.
    1419                 :      *----------------------------------------------------------------*/
    1420               0 :     int         iBounds = CSLFindString( papszFields, "Bounds" );
    1421                 : 
    1422               0 :     while( iBounds != -1 && papszFields[iBounds] != NULL )
    1423                 :     {
    1424               0 :         CPLFree( papszFields[iBounds] );
    1425               0 :         papszFields[iBounds] = NULL;
    1426               0 :         iBounds++;
    1427                 :     }
    1428                 : 
    1429                 :     /*-----------------------------------------------------------------
    1430                 :      * Fetch the projection.
    1431                 :      *----------------------------------------------------------------*/
    1432                 :     char        **papszNextField;
    1433                 : 
    1434               0 :     if( CSLCount( papszFields ) >= 3
    1435               0 :         && EQUAL(papszFields[0],"Earth")
    1436               0 :         && EQUAL(papszFields[1],"Projection") )
    1437                 :     {
    1438               0 :         psProj->nProjId = (GByte)atoi(papszFields[2]);
    1439               0 :         papszNextField = papszFields + 3;
    1440                 :     }
    1441               0 :     else if (CSLCount( papszFields ) >= 2
    1442               0 :              && EQUAL(papszFields[0],"NonEarth") )
    1443                 :     {
    1444                 :         // NonEarth Units "..." Bounds (x, y) (x, y)
    1445               0 :         psProj->nProjId = 0;
    1446               0 :         papszNextField = papszFields + 2;
    1447                 : 
    1448               0 :         if( papszNextField[0] != NULL && EQUAL(papszNextField[0],"Units") )
    1449               0 :             papszNextField++;
    1450                 :     }
    1451                 :     else
    1452                 :     {
    1453                 :         // Invalid projection string ???
    1454               0 :         if (CSLCount(papszFields) > 0)
    1455                 :             CPLError(CE_Warning, CPLE_IllegalArg,
    1456               0 :                      "Failed parsing CoordSys: '%s'", pszCoordSys);
    1457               0 :         CSLDestroy(papszFields);
    1458               0 :         return -1;
    1459                 :     }
    1460                 : 
    1461                 :     /*-----------------------------------------------------------------
    1462                 :      * Fetch the datum information.
    1463                 :      *----------------------------------------------------------------*/
    1464               0 :     int         nDatum = 0;
    1465                 : 
    1466               0 :     if( psProj->nProjId != 0 && CSLCount(papszNextField) > 0 )
    1467                 :     {
    1468               0 :         nDatum = atoi(papszNextField[0]);
    1469               0 :         papszNextField++;
    1470                 :     }
    1471                 : 
    1472               0 :     if( (nDatum == 999 || nDatum == 9999)
    1473                 :         && CSLCount(papszNextField) >= 4 )
    1474                 :     {
    1475               0 :         psProj->nEllipsoidId = (GByte)atoi(papszFields[0]);
    1476               0 :         psProj->dDatumShiftX = atof(papszNextField[1]);
    1477               0 :         psProj->dDatumShiftY = atof(papszNextField[2]);
    1478               0 :         psProj->dDatumShiftZ = atof(papszNextField[3]);
    1479               0 :         papszNextField += 4;
    1480                 : 
    1481               0 :         if( nDatum == 9999
    1482                 :             && CSLCount(papszNextField) >= 5 )
    1483                 :         {
    1484               0 :             psProj->adDatumParams[0] = atof(papszNextField[0]);
    1485               0 :             psProj->adDatumParams[1] = atof(papszNextField[1]);
    1486               0 :             psProj->adDatumParams[2] = atof(papszNextField[2]);
    1487               0 :             psProj->adDatumParams[3] = atof(papszNextField[3]);
    1488               0 :             psProj->adDatumParams[4] = atof(papszNextField[4]);
    1489               0 :             papszNextField += 5;
    1490                 :         }
    1491                 :     }
    1492               0 :     else if (nDatum != 999 && nDatum != 9999)
    1493                 :     {
    1494                 :     /*-----------------------------------------------------------------
    1495                 :      * Find the datum, and collect it's parameters if possible.
    1496                 :      *----------------------------------------------------------------*/
    1497                 :         int         iDatum;
    1498               0 :         MapInfoDatumInfo *psDatumInfo = NULL;
    1499                 :         
    1500               0 :         for(iDatum=0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++)
    1501                 :         {
    1502               0 :             if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
    1503                 :             {
    1504               0 :                 psDatumInfo = asDatumInfoList + iDatum;
    1505               0 :                 break;
    1506                 :             }
    1507                 :         }
    1508                 : 
    1509               0 :         if( asDatumInfoList[iDatum].nMapInfoDatumID == -1
    1510                 :             && nDatum != 999 && nDatum != 9999 )
    1511                 :         {
    1512                 :             /* use WGS84 */
    1513               0 :             psDatumInfo = asDatumInfoList + 0;
    1514                 :         }
    1515                 : 
    1516               0 :         if( psDatumInfo != NULL )
    1517                 :         {
    1518               0 :             psProj->nEllipsoidId = (GByte)psDatumInfo->nEllipsoid;
    1519               0 :             psProj->nDatumId = (GInt16)psDatumInfo->nMapInfoDatumID;
    1520               0 :             psProj->dDatumShiftX = psDatumInfo->dfShiftX;
    1521               0 :             psProj->dDatumShiftY = psDatumInfo->dfShiftY;
    1522               0 :             psProj->dDatumShiftZ = psDatumInfo->dfShiftZ;
    1523               0 :             psProj->adDatumParams[0] = psDatumInfo->dfDatumParm0;
    1524               0 :             psProj->adDatumParams[1] = psDatumInfo->dfDatumParm1;
    1525               0 :             psProj->adDatumParams[2] = psDatumInfo->dfDatumParm2;
    1526               0 :             psProj->adDatumParams[3] = psDatumInfo->dfDatumParm3;
    1527               0 :             psProj->adDatumParams[4] = psDatumInfo->dfDatumParm4;
    1528                 :         }
    1529                 :     }    
    1530                 : 
    1531                 :     /*-----------------------------------------------------------------
    1532                 :      * Fetch the units string.
    1533                 :      *----------------------------------------------------------------*/
    1534               0 :     if( CSLCount(papszNextField) > 0 )
    1535                 :     {
    1536               0 :         psProj->nUnitsId = (GByte)TABUnitIdFromString(papszNextField[0]);
    1537               0 :         papszNextField++;
    1538                 :     }
    1539                 : 
    1540                 :     /*-----------------------------------------------------------------
    1541                 :      * Finally the projection parameters.
    1542                 :      *----------------------------------------------------------------*/
    1543               0 :     for(int iParam=0; iParam < 6 && CSLCount(papszNextField) > 0; iParam++)
    1544                 :     {
    1545               0 :         psProj->adProjParams[iParam] = atof(papszNextField[0]);
    1546               0 :         papszNextField++;         
    1547                 :     }
    1548                 : 
    1549               0 :     return 0;
    1550                 : }
    1551                 : 

Generated by: LCOV version 1.7