LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/ili - ili1reader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 483 372 77.0 %
Date: 2012-12-26 Functions: 29 23 79.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ili1reader.cpp 24610 2012-06-25 15:21:32Z pka $
       3                 :  *
       4                 :  * Project:  Interlis 1 Reader
       5                 :  * Purpose:  Implementation of ILI1Reader class.
       6                 :  * Author:   Pirmin Kalberer, Sourcepole AG
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_ili1.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "ogr_api.h"
      34                 : #include "ogr_geos.h"
      35                 : 
      36                 : #include "ilihelper.h"
      37                 : #include "iomhelper.h"
      38                 : #include "ili1reader.h"
      39                 : #include "ili1readerp.h"
      40                 : 
      41                 : #include <vector>
      42                 : 
      43                 : #ifdef HAVE_GEOS
      44                 : #  define POLYGONIZE_AREAS
      45                 : #endif
      46                 : 
      47                 : #ifndef POLYGONIZE_AREAS
      48                 : #  if defined(__GNUC_PREREQ)
      49                 : #    warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 2.1.0
      50                 : #  endif
      51                 : #endif
      52                 : 
      53                 : CPL_CVSID("$Id: ili1reader.cpp 24610 2012-06-25 15:21:32Z pka $");
      54                 : 
      55                 : //
      56                 : // ILI1Reader
      57                 : //
      58              10 : IILI1Reader::~IILI1Reader() {
      59              10 : }
      60                 : 
      61              10 : ILI1Reader::ILI1Reader() {
      62              10 :   fpItf = NULL;
      63              10 :   nLayers = 0;
      64              10 :   papoLayers = NULL;
      65              10 :   curLayer = NULL;
      66              10 :   metaLayer = NULL;
      67              10 :   codeBlank = '_';
      68              10 :   codeUndefined = '@';
      69              10 :   codeContinue = '\\';
      70              10 :   SetArcDegrees(1);
      71                 : 
      72              10 : }
      73                 : 
      74              10 : ILI1Reader::~ILI1Reader() {
      75                 :  int i;
      76              10 :  if (fpItf) VSIFClose( fpItf );
      77                 : 
      78              40 :  for(i=0;i<nLayers;i++)
      79              30 :      delete papoLayers[i];
      80              10 :  CPLFree(papoLayers);
      81                 : 
      82              10 :  delete metaLayer;
      83              10 : }
      84                 : 
      85              11 : void ILI1Reader::SetArcDegrees(double arcDegrees) {
      86              11 :   arcIncr = arcDegrees*PI/180;
      87              11 : }
      88                 : 
      89                 : /* -------------------------------------------------------------------- */
      90                 : /*      Open the source file.                                           */
      91                 : /* -------------------------------------------------------------------- */
      92              10 : int ILI1Reader::OpenFile( const char *pszFilename ) {
      93              10 :     fpItf = VSIFOpen( pszFilename, "r" );
      94              10 :     if( fpItf == NULL )
      95                 :     {
      96                 :           CPLError( CE_Failure, CPLE_OpenFailed,
      97                 :                     "Failed to open ILI file `%s'.",
      98               0 :                     pszFilename );
      99                 : 
     100               0 :         return FALSE;
     101                 :     }
     102              10 :     return TRUE;
     103                 : }
     104                 : 
     105              50 : int ILI1Reader::HasMultiplePointGeom(const char* layername) {
     106              50 :     if (metaLayer != NULL) {
     107              50 :         OGRFeature *metaFeature = NULL;
     108              50 :         metaLayer->ResetReading();
     109              50 :         int i = -1;
     110             180 :         while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
     111              80 :             if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
     112              20 :               i++;
     113                 :             }
     114              80 :             delete metaFeature;
     115                 :         }
     116              50 :         return i;
     117                 :     } else {
     118               0 :         return -1;
     119                 :     }
     120                 : }
     121                 : 
     122               0 : char* ILI1Reader::GetPointLayerName(const char* layername, char* newlayername) {
     123                 :     static char geomlayername[512];
     124               0 :     geomlayername[0] = '\0';
     125               0 :     strcat(geomlayername, layername);
     126               0 :     strcat(geomlayername, "__");
     127               0 :     strcat(geomlayername, newlayername);
     128               0 :     return geomlayername;
     129                 : }
     130                 : 
     131              50 : const char* ILI1Reader::GetLayerNameString(const char* topicname, const char* tablename) {
     132                 :     static char layername[512];
     133              50 :     layername[0] = '\0';
     134              50 :     strcat(layername, topicname);
     135              50 :     strcat(layername, "__");
     136              50 :     strcat(layername, tablename);
     137              50 :     return layername;
     138                 : }
     139                 : 
     140              20 : const char* ILI1Reader::GetLayerName(IOM_BASKET model, IOM_OBJECT table) {
     141                 :     static char layername[512];
     142              20 :     IOM_OBJECT topic = GetAttrObj(model, table, "container");
     143              20 :     layername[0] = '\0';
     144              20 :     strcat(layername, iom_getattrvalue(topic, "name"));
     145              20 :     strcat(layername, "__");
     146              20 :     strcat(layername, iom_getattrvalue(table, "name"));
     147              20 :     return layername;
     148                 : }
     149                 : 
     150              10 : void ILI1Reader::AddCoord(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT modelele, IOM_OBJECT typeobj) {
     151              10 :   unsigned int dim = ::GetCoordDim(model, typeobj);
     152              30 :   for (unsigned int i=0; i<dim; i++) {
     153              20 :     OGRFieldDefn fieldDef(CPLSPrintf("%s_%d", iom_getattrvalue(modelele, "name"), i), OFTReal);
     154              20 :     layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
     155                 :     //CPLDebug( "AddCoord   OGR_ILI", "Field %s: OFTReal", fieldDef.GetNameRef());
     156                 :   }
     157              10 : }
     158                 : 
     159               5 : OGRILI1Layer* ILI1Reader::AddGeomTable(const char* datalayername, const char* geomname, OGRwkbGeometryType eType) {
     160                 :   static char layername[512];
     161               5 :   layername[0] = '\0';
     162               5 :   strcat(layername, datalayername);
     163               5 :   strcat(layername, "_");
     164               5 :   strcat(layername, geomname);
     165                 : 
     166               5 :   OGRILI1Layer* geomlayer = new OGRILI1Layer(layername, NULL, 0, eType, NULL);
     167               5 :   AddLayer(geomlayer);
     168               5 :   OGRFieldDefn fieldDef("_TID", OFTString);
     169              10 :   geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef);
     170               5 :   if (eType == wkbPolygon)
     171                 :   {
     172               0 :      OGRFieldDefn fieldDefRef("_RefTID", OFTString);
     173               0 :      geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDefRef);
     174                 :   }
     175               5 :   OGRFieldDefn fieldDef2("ILI_Geometry", OFTString); //in write mode only?
     176               5 :   geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
     177               5 :   return geomlayer;
     178                 : }
     179                 : 
     180              50 : void ILI1Reader::AddField(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT obj) {
     181              50 :   const char* typenam = "Reference";
     182              50 :   if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.LocalAttribute")) typenam = GetTypeName(model, obj);
     183                 :   //CPLDebug( "OGR_ILI", "Field %s: %s", iom_getattrvalue(obj, "name"), typenam);
     184              50 :   if (EQUAL(typenam, "iom04.metamodel.SurfaceType")) {
     185               0 :     OGRILI1Layer* polyLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbPolygon);
     186               0 :     layer->SetSurfacePolyLayer(polyLayer);
     187                 :     //TODO: add line attributes to geometry
     188              50 :   } else if (EQUAL(typenam, "iom04.metamodel.AreaType")) {
     189               5 :     IOM_OBJECT controlPointDomain = GetAttrObj(model, GetTypeObj(model, obj), "controlPointDomain");
     190               5 :     if (controlPointDomain) {
     191               5 :       AddCoord(layer, model, obj, GetTypeObj(model, controlPointDomain));
     192               5 :       layer->GetLayerDefn()->SetGeomType(wkbPoint);
     193                 :     }
     194               5 :     OGRILI1Layer* areaLineLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbMultiLineString);
     195                 : #ifdef POLYGONIZE_AREAS
     196               5 :     OGRILI1Layer* areaLayer = new OGRILI1Layer(CPLSPrintf("%s__Areas",layer->GetLayerDefn()->GetName()), NULL, 0, wkbPolygon, NULL);
     197               5 :     AddLayer(areaLayer);
     198               5 :     areaLayer->SetAreaLayers(layer, areaLineLayer);
     199                 : #endif
     200              45 :   } else if (EQUAL(typenam, "iom04.metamodel.PolylineType") ) {
     201               5 :     layer->GetLayerDefn()->SetGeomType(wkbMultiLineString);
     202              40 :   } else if (EQUAL(typenam, "iom04.metamodel.CoordType")) {
     203               5 :     AddCoord(layer, model, obj, GetTypeObj(model, obj));
     204               5 :     if (layer->GetLayerDefn()->GetGeomType() == wkbUnknown) layer->GetLayerDefn()->SetGeomType(wkbPoint);
     205              35 :   } else if (EQUAL(typenam, "iom04.metamodel.NumericType") ) {
     206               5 :      OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTReal);
     207               5 :      layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
     208              30 :   } else if (EQUAL(typenam, "iom04.metamodel.EnumerationType") ) {
     209               5 :      OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTInteger);
     210               5 :      layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
     211                 :   } else {
     212              25 :     OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTString);
     213              25 :     layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
     214                 :   }
     215              50 : }
     216                 : 
     217              10 : int ILI1Reader::ReadModel(const char *pszModelFilename) {
     218                 : 
     219                 :   IOM_BASKET model;
     220                 :   IOM_ITERATOR modelelei;
     221                 :   IOM_OBJECT modelele;
     222                 : 
     223              10 :   iom_init();
     224                 : 
     225                 :   // set error listener to a iom provided one, that just
     226                 :   // dumps all errors to stderr
     227              10 :   iom_seterrlistener(iom_stderrlistener);
     228                 : 
     229                 :   // compile ili model
     230              10 :   char *iomarr[1] = {(char *)pszModelFilename};
     231              10 :   model=iom_compileIli(1, iomarr);
     232              10 :   if(!model){
     233               0 :     CPLError( CE_Failure, CPLE_FileIO, "iom_compileIli failed." );
     234               0 :     iom_end();
     235               0 :     return FALSE;
     236                 :   }
     237                 : 
     238                 :   // create new layer with meta information (ILI table name and geometry column index)
     239                 :   // while reading the features from the ITF we have to know which column is the geometry column
     240              10 :   metaLayer = new OGRILI1Layer("Metatable", NULL, 0, wkbUnknown, NULL);
     241              10 :   OGRFieldDefn fieldDef1("layername", OFTString);
     242              20 :   metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef1);
     243              10 :   OGRFieldDefn fieldDef2("geomIdx", OFTInteger);
     244              10 :   metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
     245              10 :   OGRFieldDefn fieldDef3("geomlayername", OFTString);
     246              10 :   metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef3);
     247                 : 
     248                 : 
     249                 :   // read tables
     250              10 :   int j = 0;
     251              10 :   modelelei=iom_iteratorobject(model);
     252              10 :   modelele=iom_nextobject(modelelei);
     253            2620 :   while(modelele){
     254            2600 :     const char *tag=iom_getobjecttag(modelele);
     255                 : 
     256            2600 :     if (tag) {
     257            2600 :       if (EQUAL(tag,"iom04.metamodel.Table")) {
     258                 : 
     259             220 :         const char* topic = iom_getattrvalue(GetAttrObj(model, modelele, "container"), "name");
     260                 : 
     261             220 :         if (!EQUAL(topic, "INTERLIS")) {
     262                 : 
     263              20 :           const char* layername = GetLayerName(model, modelele);
     264              20 :           OGRSpatialReference *poSRSIn = NULL;
     265              20 :           int bWriterIn = 0;
     266              20 :           OGRwkbGeometryType eReqType = wkbUnknown;
     267              20 :           OGRILI1DataSource *poDSIn = NULL;
     268                 : 
     269              20 :           CPLDebug( "OGR_ILI", "Reading table model '%s'", layername );
     270                 : 
     271                 :           // read fields
     272                 :           IOM_OBJECT fields[255];
     273                 :           IOM_OBJECT roledefs[255];
     274              20 :           memset(fields, 0, 255);
     275              20 :           memset(roledefs, 0, 255);
     276              20 :           int maxIdx = -1;
     277              20 :           IOM_ITERATOR fieldit=iom_iteratorobject(model);
     278              20 :           std::vector<IOM_OBJECT> attributes;
     279                 : 
     280            5390 :           for (IOM_OBJECT fieldele=iom_nextobject(fieldit); fieldele; fieldele=iom_nextobject(fieldit)){
     281            5370 :             const char *etag=iom_getobjecttag(fieldele);
     282                 : 
     283            5370 :             if (etag && (EQUAL(etag,"iom04.metamodel.ViewableAttributesAndRoles"))) {
     284             760 :               IOM_OBJECT table = GetAttrObj(model, fieldele, "viewable");
     285                 : 
     286             760 :               if (table == modelele) {
     287                 : 
     288              50 :                 IOM_OBJECT obj = GetAttrObj(model, fieldele, "attributesAndRoles");
     289              50 :                 int ili1AttrIdx = GetAttrObjPos(fieldele, "attributesAndRoles")-1;
     290                 : 
     291              50 :                 if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.RoleDef")) {
     292               5 :                   int ili1AttrIdxOppend = atoi(iom_getattrvalue(GetAttrObj(model, obj, "oppend"), "ili1AttrIdx"));
     293                 : 
     294               5 :                   if (ili1AttrIdxOppend>=0) {
     295               5 :                     roledefs[ili1AttrIdxOppend] = obj;
     296               5 :                     if (ili1AttrIdxOppend > maxIdx) maxIdx = ili1AttrIdxOppend;
     297                 :                   }
     298                 :                 } else {
     299              45 :                   fields[ili1AttrIdx] = obj;
     300              45 :                   if (ili1AttrIdx > maxIdx) maxIdx = ili1AttrIdx;
     301                 :                 }
     302                 :               }
     303                 :             }
     304            5370 :             iom_releaseobject(fieldele);
     305                 :           }
     306              20 :           iom_releaseiterator(fieldit);
     307                 : 
     308                 :           // if multiple gets positive we have more than one geometry column (only points)
     309              20 :           int multiple = -1;
     310                 : 
     311              70 :           for (int i=0; i<=maxIdx; i++) {
     312              50 :             IOM_OBJECT obj = fields[i];
     313              50 :             if (obj) {
     314              45 :              attributes.push_back(obj);
     315              45 :              if (EQUAL(GetTypeName(model, obj), "iom04.metamodel.CoordType")) multiple++;
     316                 :             }
     317                 :           }
     318                 : 
     319              70 :           for (int i=0; i<=maxIdx; i++) {
     320              50 :             IOM_OBJECT obj = roledefs[i];
     321              50 :             if (obj) attributes.insert(attributes.begin() + i, obj);
     322                 :           }
     323                 : 
     324              20 :           OGRFeature *feature = NULL;
     325              20 :           char* geomlayername = '\0';
     326              20 :           OGRILI1Layer* layer = NULL;
     327                 : 
     328              70 :           for(size_t i=0; i<attributes.size(); i++) {
     329              50 :             IOM_OBJECT obj = attributes.at(i);
     330              50 :             const char* typenam = GetTypeName(model, obj);
     331              50 :             if (EQUAL(typenam, "iom04.metamodel.CoordType")  || EQUAL(typenam, "iom04.metamodel.AreaType")) {
     332              10 :               feature = OGRFeature::CreateFeature(metaLayer->GetLayerDefn());
     333              10 :               feature->SetFID(j+1);
     334              10 :               feature->SetField("layername", layername);
     335              10 :               feature->SetField("geomIdx", (int)i);
     336                 : 
     337              10 :               if(multiple > 0) {
     338               0 :                 geomlayername = GetPointLayerName(layername, iom_getattrvalue(obj, "name"));
     339               0 :                 feature->SetField("geomlayername", geomlayername);
     340               0 :                 layer = new OGRILI1Layer(geomlayername, poSRSIn, bWriterIn, eReqType, poDSIn);
     341               0 :                 AddLayer(layer);
     342                 : 
     343                 :               } else {
     344              10 :                 feature->SetField("geomlayername", layername);
     345              10 :                 layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
     346              10 :                 AddLayer(layer);
     347                 :               }
     348              10 :               metaLayer->AddFeature(feature);
     349                 :             }
     350                 :           }
     351                 : 
     352              20 :           if(layer == NULL) {
     353              10 :             layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
     354              10 :             AddLayer(layer);
     355                 :           }
     356                 : 
     357              20 :           OGRFieldDefn fieldDef("_TID", OFTString);
     358              20 :           layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
     359                 : 
     360              70 :           for(size_t i=0; i<attributes.size(); i++) {
     361              50 :             IOM_OBJECT obj = attributes.at(i);
     362              50 :             AddField(layer, model, obj);
     363                 :           }
     364                 : 
     365                 :           // additional point layer added
     366              20 :           if(multiple > 0) {
     367               0 :             for(int i = 1; i <= multiple; i++) {
     368               0 :                OGRILI1Layer* pointLayer = papoLayers[nLayers-(i+1)];
     369               0 :                for (int j=0; j < layer->GetLayerDefn()->GetFieldCount(); j++) {
     370               0 :                  pointLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(j));
     371                 :                }
     372               0 :             if (pointLayer->GetLayerDefn()->GetGeomType() == wkbUnknown) pointLayer->GetLayerDefn()->SetGeomType(wkbPoint);
     373                 :             }
     374                 :           }
     375                 : 
     376              20 :           if (papoLayers[nLayers-1]->GetLayerDefn()->GetFieldCount() == 0) {
     377                 :               //Area layer added
     378               5 :               OGRILI1Layer* areaLayer = papoLayers[nLayers-1];
     379              25 :               for (int i=0; i < layer->GetLayerDefn()->GetFieldCount(); i++) {
     380              20 :                 areaLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(i));
     381                 :               }
     382              20 :           }
     383                 :         }
     384            2380 :       } else if (EQUAL(tag,"iom04.metamodel.Ili1Format")) {
     385              10 :         codeBlank = atoi(iom_getattrvalue(modelele, "blankCode"));
     386              10 :         CPLDebug( "OGR_ILI", "Reading Ili1Format blankCode '%c'", codeBlank );
     387              10 :         codeUndefined = atoi(iom_getattrvalue(modelele, "undefinedCode"));
     388              10 :         CPLDebug( "OGR_ILI", "Reading Ili1Format undefinedCode '%c'", codeUndefined );
     389              10 :         codeContinue = atoi(iom_getattrvalue(modelele, "continueCode"));
     390              10 :         CPLDebug( "OGR_ILI", "Reading Ili1Format continueCode '%c'", codeContinue );
     391                 :       }
     392            2600 :       iom_releaseobject(modelele);
     393                 : 
     394            2600 :       modelele=iom_nextobject(modelelei);
     395            2600 :       j++;
     396                 :     }
     397                 :   }
     398                 : 
     399              10 :   iom_releaseiterator(modelelei);
     400                 : 
     401              10 :   iom_releasebasket(model);
     402                 : 
     403              10 :   iom_end();
     404                 : 
     405              10 :   return 0;
     406                 : }
     407                 : 
     408              10 : int ILI1Reader::ReadFeatures() {
     409              10 :     char **tokens = NULL;
     410              10 :     const char *firsttok = NULL;
     411                 :     const char *pszLine;
     412              10 :     char *topic = NULL;
     413              10 :     int ret = TRUE;
     414                 : 
     415             105 :     while (ret && (tokens = ReadParseLine()))
     416                 :     {
     417              95 :       firsttok = tokens[0];
     418              95 :       if (EQUAL(firsttok, "SCNT"))
     419                 :       {
     420                 :         //read description
     421              20 :         do
     422                 :         {
     423              20 :           pszLine = CPLReadLine( fpItf );
     424                 :         }
     425                 :         while (pszLine && !EQUALN(pszLine, "////", 4));
     426              10 :         ret = (pszLine != NULL);
     427                 :       }
     428              85 :       else if (EQUAL(firsttok, "MOTR"))
     429                 :       {
     430                 :         //read model
     431               0 :         do
     432                 :         {
     433               0 :           pszLine = CPLReadLine( fpItf );
     434                 :         }
     435                 :         while (pszLine && !EQUALN(pszLine, "////", 4));
     436               0 :         ret = (pszLine != NULL);
     437                 :       }
     438              85 :       else if (EQUAL(firsttok, "MTID"))
     439                 :       {
     440                 :       }
     441              75 :       else if (EQUAL(firsttok, "MODL"))
     442                 :       {
     443                 :       }
     444              65 :       else if (EQUAL(firsttok, "TOPI"))
     445                 :       {
     446              10 :         CPLFree(topic);
     447              10 :         topic = CPLStrdup(CSLGetField(tokens, 1));
     448                 :       }
     449              55 :       else if (EQUAL(firsttok, "TABL"))
     450                 :       {
     451              25 :         CPLDebug( "OGR_ILI", "Reading table '%s'", GetLayerNameString(topic, CSLGetField(tokens, 1)) );
     452              25 :         const char *layername = GetLayerNameString(topic, CSLGetField(tokens, 1));
     453              25 :         curLayer = GetLayerByName(layername);
     454                 : 
     455              25 :         int multiple = HasMultiplePointGeom(layername);
     456                 : 
     457                 :         // create only a new layer if there is no curLayer AND
     458                 :         // if there are more than one point geometry columns
     459              25 :         if (curLayer == NULL && multiple < 1) { //create one
     460               0 :           CPLDebug( "OGR_ILI", "No model found, using default field names." );
     461               0 :           OGRSpatialReference *poSRSIn = NULL;
     462               0 :           int bWriterIn = 0;
     463               0 :           OGRwkbGeometryType eReqType = wkbUnknown;
     464               0 :           OGRILI1DataSource *poDSIn = NULL;
     465               0 :           curLayer = new OGRILI1Layer(GetLayerNameString(topic, CSLGetField(tokens, 1)), poSRSIn, bWriterIn, eReqType, poDSIn);
     466               0 :           AddLayer(curLayer);
     467                 :         }
     468              25 :         if(curLayer != NULL) {
     469             110 :           for (int i=0; i < curLayer->GetLayerDefn()->GetFieldCount(); i++) {
     470              85 :             CPLDebug( "OGR_ILI", "Field %d: %s", i,  curLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef());
     471                 :           }
     472                 :         }
     473              25 :         ret = ReadTable(layername);
     474                 :       }
     475              30 :       else if (EQUAL(firsttok, "ETOP"))
     476                 :       {
     477                 :       }
     478              20 :       else if (EQUAL(firsttok, "EMOD"))
     479                 :       {
     480                 :       }
     481              10 :       else if (EQUAL(firsttok, "ENDE"))
     482                 :       {
     483              10 :         CSLDestroy(tokens);
     484              10 :         CPLFree(topic);
     485              10 :         return TRUE;
     486                 :       }
     487                 :       else
     488                 :       {
     489               0 :         CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
     490                 :       }
     491                 : 
     492              85 :       CSLDestroy(tokens);
     493              85 :       tokens = NULL;
     494                 :     }
     495                 : 
     496               0 :     CSLDestroy(tokens);
     497               0 :     CPLFree(topic);
     498                 : 
     499               0 :     return ret;
     500                 : }
     501                 : 
     502              20 : int ILI1Reader::AddIliGeom(OGRFeature *feature, int iField, long fpos)
     503                 : {
     504                 : #if defined(_WIN32) || defined(__WIN32__)
     505                 :     //Other positions on Windows !?
     506                 : #else
     507              20 :     long nBlockLen = VSIFTell( fpItf )-fpos;
     508              20 :     VSIFSeek( fpItf, fpos, SEEK_SET );
     509                 : 
     510              20 :     char *pszRawData = (char *) CPLMalloc(nBlockLen+1);
     511              20 :     if( (int) VSIFRead( pszRawData, 1, nBlockLen, fpItf ) != nBlockLen )
     512                 :     {
     513               0 :         CPLFree( pszRawData );
     514                 : 
     515               0 :         CPLError( CE_Failure, CPLE_FileIO, "Read of transfer file failed." );
     516               0 :         return FALSE;
     517                 :     }
     518              20 :     pszRawData[nBlockLen]= '\0';
     519              20 :     feature->SetField(iField, pszRawData);
     520              20 :     CPLFree( pszRawData );
     521                 : #endif
     522              20 :     return TRUE;
     523                 : }
     524                 : 
     525                 : 
     526              25 : int ILI1Reader::ReadTable(const char *layername) {
     527              25 :     char **tokens = NULL;
     528              25 :     const char *firsttok = NULL;
     529              25 :     int ret = TRUE;
     530              25 :     int warned = FALSE;
     531                 :     int fIndex;
     532              25 :     int geomIdx = 0;
     533                 : 
     534                 :     // curLayer is NULL if we have more than one
     535                 :     // point geometry column
     536              25 :     if(curLayer == NULL) {
     537               0 :       OGRFeature *metaFeature = NULL;
     538               0 :       metaLayer->ResetReading();
     539               0 :       while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
     540               0 :         if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
     541               0 :           const char *geomlayername = metaFeature->GetFieldAsString(2);
     542               0 :           curLayer = GetLayerByName(geomlayername);
     543               0 :           delete metaFeature;
     544               0 :           break;
     545                 :         }
     546               0 :         delete metaFeature;
     547                 :       }
     548                 :     }
     549                 : 
     550              25 :     OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
     551              25 :     OGRFeature *feature = NULL;
     552                 : 
     553                 :     // get the geometry index of the current layer
     554                 :     // only if the model is read
     555              25 :     if(featureDef->GetFieldCount() != 0) {
     556              25 :       OGRFeature *metaFeature = NULL;
     557              25 :       metaLayer->ResetReading();
     558              90 :       while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
     559              40 :         if(EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
     560              10 :           geomIdx = metaFeature->GetFieldAsInteger(1);
     561                 :         }
     562              40 :         delete metaFeature;
     563                 :       }
     564                 :     }
     565                 : 
     566              25 :     long fpos = VSIFTell(fpItf);
     567             125 :     while (ret && (tokens = ReadParseLine()))
     568                 :     {
     569             100 :       firsttok = CSLGetField(tokens, 0);
     570             100 :       if (EQUAL(firsttok, "OBJE"))
     571                 :       {
     572                 :         //Check for features spread over multiple objects
     573              50 :         if (featureDef->GetGeomType() == wkbPolygon)
     574                 :         {
     575                 :           //Multiple polygon rings
     576               0 :           feature = curLayer->GetFeatureRef(atol(CSLGetField(tokens, 2)));
     577                 :         }
     578              50 :         else if (featureDef->GetGeomType() == wkbGeometryCollection)
     579                 :         {
     580                 :           //AREA lines spread over mutltiple objects
     581                 :         }
     582                 :         else
     583                 :         {
     584              50 :           feature = NULL;
     585                 :         }
     586                 : 
     587              50 :         if (feature == NULL)
     588                 :         {
     589              50 :           if (featureDef->GetFieldCount() == 0)
     590                 :           {
     591               0 :             CPLDebug( "OGR_ILI", "No field definition found for table: %s", featureDef->GetName() );
     592                 :             //Model not read - use heuristics
     593               0 :             for (fIndex=1; fIndex<CSLCount(tokens); fIndex++)
     594                 :             {
     595                 :               char szFieldName[32];
     596               0 :               sprintf(szFieldName, "Field%02d", fIndex);
     597               0 :               OGRFieldDefn oFieldDefn(szFieldName, OFTString);
     598               0 :               featureDef->AddFieldDefn(&oFieldDefn);
     599                 :             }
     600                 :           }
     601                 :           //start new feature
     602              50 :           feature = new OGRFeature(featureDef);
     603                 : 
     604              50 :           int fieldno = 0;
     605             185 :           for (fIndex=1; fIndex<CSLCount(tokens) && fieldno < featureDef->GetFieldCount(); fIndex++, fieldno++)
     606                 :           {
     607             135 :             if (!(tokens[fIndex][0] == codeUndefined && tokens[fIndex][1] == '\0')) {
     608                 :               //CPLDebug( "READ TABLE OGR_ILI", "Setting Field %d (Type %d): %s", fieldno, featureDef->GetFieldDefn(fieldno)->GetType(), tokens[fIndex]);
     609             130 :               if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTString) {
     610                 :                   //Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8
     611              70 :                   char* pszRecoded = CPLRecode(tokens[fIndex], CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
     612                 :                   //Replace space marks
     613             227 :                   for(char* pszString = pszRecoded; *pszString != '\0'; pszString++ ) {
     614             157 :                       if (*pszString == codeBlank) *pszString = ' ';
     615                 :                   }
     616              70 :                   feature->SetField(fieldno, pszRecoded);
     617              70 :                   CPLFree(pszRecoded);
     618                 :               } else {
     619              60 :                 feature->SetField(fieldno, tokens[fIndex]);
     620                 :               }
     621             130 :               if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTReal
     622                 :                   && fieldno > 0
     623                 :                   && featureDef->GetFieldDefn(fieldno-1)->GetType() == OFTReal
     624                 :                   && featureDef->GetGeomType() == wkbPoint
     625                 : 
     626                 :                   /*
     627                 :                   // if there is no ili model read,
     628                 :                   // we have no chance to detect the
     629                 :                   // geometry column!!
     630                 :                   */
     631                 : 
     632                 :                   && (fieldno-2) == geomIdx) {
     633                 :                 //add Point geometry
     634              20 :                 OGRPoint *ogrPoint = new OGRPoint(atof(tokens[fIndex-1]), atof(tokens[fIndex]));
     635              20 :                 feature->SetGeometryDirectly(ogrPoint);
     636                 :               }
     637                 :             }
     638                 :           }
     639              50 :           if (!warned && featureDef->GetFieldCount() != CSLCount(tokens)-1 && !(featureDef->GetFieldCount() == CSLCount(tokens) && EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))) {
     640               0 :             CPLDebug( "OGR_ILI", "Field count doesn't match. %d declared, %d found", featureDef->GetFieldCount(), CSLCount(tokens)-1);
     641               0 :             warned = TRUE;
     642                 :           }
     643              50 :           if (featureDef->GetGeomType() == wkbPolygon)
     644               0 :             feature->SetFID(atol(feature->GetFieldAsString(1)));
     645              50 :           else if (feature->GetFieldCount() > 0)
     646              50 :             feature->SetFID(atol(feature->GetFieldAsString(0)));
     647              50 :           curLayer->AddFeature(feature);
     648                 :         }
     649                 :       }
     650              50 :       else if (EQUAL(firsttok, "STPT"))
     651                 :       {
     652              25 :         ReadGeom(tokens, featureDef->GetGeomType(), feature);
     653              25 :         if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
     654                 :         {
     655              20 :           AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos); //TODO: append multi-OBJECT geometries
     656                 :         }
     657                 :       }
     658              25 :       else if (EQUAL(firsttok, "ELIN"))
     659                 :       {
     660                 :         //empty geom
     661                 :       }
     662              25 :       else if (EQUAL(firsttok, "EDGE"))
     663                 :       {
     664               0 :         tokens = ReadParseLine(); //STPT
     665               0 :         ReadGeom(tokens, wkbMultiLineString, feature);
     666               0 :         if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
     667                 :         {
     668               0 :           AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos);
     669                 :         }
     670                 :       }
     671              25 :       else if (EQUAL(firsttok, "PERI"))
     672                 :       {
     673                 :       }
     674              25 :       else if (EQUAL(firsttok, "ETAB"))
     675                 :       {
     676              25 :         if(HasMultiplePointGeom(layername) > 0) {
     677               0 :           OGRFeature *metaFeature = NULL;
     678               0 :           metaLayer->ResetReading();
     679               0 :           while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
     680               0 :             int pntCln = 1;
     681               0 :             if(EQUAL(layername, metaFeature->GetFieldAsString(0)) && !EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
     682               0 :               pntCln++;
     683               0 :               OGRILI1Layer *curLayerTmp = GetLayerByName(metaFeature->GetFieldAsString(2));
     684               0 :               OGRFeature *tmpFeature = NULL;
     685               0 :               int geomIdxTmp = metaFeature->GetFieldAsInteger(1);
     686               0 :               curLayer->ResetReading();
     687               0 :               while((tmpFeature = curLayer->GetNextFeature()) != NULL ) {
     688               0 :                 OGRPoint *ogrPoint = new OGRPoint(atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln)), atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln + 1)));
     689               0 :                 tmpFeature->SetGeometryDirectly(ogrPoint);
     690               0 :                 curLayerTmp->AddFeature(tmpFeature);
     691                 :               }
     692                 :             }
     693               0 :             delete metaFeature;
     694                 :           }
     695                 :         }
     696              25 :         CSLDestroy(tokens);
     697              25 :         return TRUE;
     698                 :       }
     699                 :       else
     700                 :       {
     701               0 :         CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
     702                 :       }
     703                 : 
     704              75 :       CSLDestroy(tokens);
     705              75 :       fpos = VSIFTell(fpItf);
     706                 :     }
     707                 : 
     708               0 :     return ret;
     709                 : }
     710                 : 
     711              25 : void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *feature) {
     712                 : 
     713              25 :     char **tokens = NULL;
     714              25 :     const char *firsttok = NULL;
     715              25 :     int end = FALSE;
     716              25 :     int isArc = FALSE;
     717              25 :     OGRLineString *ogrLine = NULL; //current line
     718              25 :     OGRLinearRing *ogrRing = NULL; //current ring
     719              25 :     OGRPolygon *ogrPoly = NULL; //current polygon
     720              25 :     OGRPoint ogrPoint, arcPoint, endPoint; //points for arc interpolation
     721              25 :     OGRMultiLineString *ogrMultiLine = NULL; //current multi line
     722                 : 
     723                 :     //tokens = ["STPT", "1111", "22222"]
     724              25 :     ogrPoint.setX(atof(stgeom[1])); ogrPoint.setY(atof(stgeom[2]));
     725              25 :     ogrLine = (eType == wkbPolygon) ? new OGRLinearRing() : new OGRLineString();
     726              25 :     ogrLine->addPoint(&ogrPoint);
     727                 : 
     728                 :     //Set feature geometry
     729              25 :     if (eType == wkbMultiLineString)
     730                 :     {
     731              25 :       ogrMultiLine = new OGRMultiLineString();
     732              25 :       feature->SetGeometryDirectly(ogrMultiLine);
     733                 :     }
     734               0 :     else if (eType == wkbGeometryCollection) //AREA
     735                 :     {
     736               0 :       if (feature->GetGeometryRef())
     737               0 :         ogrMultiLine = (OGRMultiLineString *)feature->GetGeometryRef();
     738                 :       else
     739                 :       {
     740               0 :         ogrMultiLine = new OGRMultiLineString();
     741               0 :         feature->SetGeometryDirectly(ogrMultiLine);
     742                 :       }
     743                 :     }
     744               0 :     else if (eType == wkbPolygon)
     745                 :     {
     746               0 :       if (feature->GetGeometryRef())
     747                 :       {
     748               0 :         ogrPoly = (OGRPolygon *)feature->GetGeometryRef();
     749               0 :         if (ogrPoly->getNumInteriorRings() > 0)
     750               0 :           ogrRing = ogrPoly->getInteriorRing(ogrPoly->getNumInteriorRings()-1);
     751                 :         else
     752               0 :           ogrRing = ogrPoly->getExteriorRing();
     753               0 :         if (ogrRing && !ogrRing->get_IsClosed()) ogrLine = ogrRing; //SURFACE polygon spread over multiple OBJECTs
     754                 :       }
     755                 :       else
     756                 :       {
     757               0 :         ogrPoly = new OGRPolygon();
     758               0 :         feature->SetGeometryDirectly(ogrPoly);
     759                 :       }
     760                 :     }
     761                 :     else
     762                 :     {
     763               0 :       feature->SetGeometryDirectly(ogrLine);
     764                 :     }
     765                 : 
     766                 :     //Parse geometry
     767             180 :     while (!end && (tokens = ReadParseLine()))
     768                 :     {
     769             130 :       firsttok = CSLGetField(tokens, 0);
     770             130 :       if (EQUAL(firsttok, "LIPT"))
     771                 :       {
     772              90 :         if (isArc) {
     773              15 :           endPoint.setX(atof(tokens[1])); endPoint.setY(atof(tokens[2]));
     774              15 :           interpolateArc(ogrLine, &ogrPoint, &arcPoint, &endPoint, arcIncr);
     775                 :         }
     776              90 :         ogrPoint.setX(atof(tokens[1])); ogrPoint.setY(atof(tokens[2])); isArc = FALSE;
     777              90 :         ogrLine->addPoint(&ogrPoint);
     778                 :       }
     779              40 :       else if (EQUAL(firsttok, "ARCP"))
     780                 :       {
     781              15 :         isArc = TRUE;
     782              15 :         arcPoint.setX(atof(tokens[1])); arcPoint.setY(atof(tokens[2]));
     783                 :       }
     784              25 :       else if (EQUAL(firsttok, "ELIN"))
     785                 :       {
     786              25 :         if (ogrMultiLine)
     787                 :         {
     788              25 :           ogrMultiLine->addGeometryDirectly(ogrLine);
     789                 :         }
     790              25 :         if (ogrPoly && ogrLine != ogrRing)
     791                 :         {
     792               0 :           ogrPoly->addRingDirectly((OGRLinearRing *)ogrLine);
     793                 :         }
     794              25 :         end = TRUE;
     795                 :       }
     796               0 :       else if (EQUAL(firsttok, "EEDG"))
     797                 :       {
     798               0 :         end = TRUE;
     799                 :       }
     800               0 :       else if (EQUAL(firsttok, "LATT"))
     801                 :       {
     802                 :         //Line Attributes (ignored)
     803                 :       }
     804               0 :       else if (EQUAL(firsttok, "EFLA"))
     805                 :       {
     806               0 :         end = TRUE;
     807                 :       }
     808               0 :       else if (EQUAL(firsttok, "ETAB"))
     809                 :       {
     810               0 :         end = TRUE;
     811                 :       }
     812                 :       else
     813                 :       {
     814               0 :         CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
     815                 :       }
     816                 : 
     817             130 :       CSLDestroy(tokens);
     818              25 :     }
     819              25 : }
     820                 : 
     821                 : /************************************************************************/
     822                 : /*                              AddLayer()                              */
     823                 : /************************************************************************/
     824                 : 
     825              30 : void ILI1Reader::AddLayer( OGRILI1Layer * poNewLayer )
     826                 : 
     827                 : {
     828              30 :     nLayers++;
     829                 : 
     830                 :     papoLayers = (OGRILI1Layer **)
     831              30 :         CPLRealloc( papoLayers, sizeof(void*) * nLayers );
     832                 : 
     833              30 :     papoLayers[nLayers-1] = poNewLayer;
     834              30 : }
     835                 : 
     836                 : /************************************************************************/
     837                 : /*                              AddAreaLayer()                              */
     838                 : /************************************************************************/
     839                 : 
     840                 : /************************************************************************/
     841                 : /*                              GetLayer()                              */
     842                 : /************************************************************************/
     843                 : 
     844              23 : OGRILI1Layer *ILI1Reader::GetLayer( int iLayer )
     845                 : 
     846                 : {
     847              23 :     if( iLayer < 0 || iLayer >= nLayers )
     848               0 :         return NULL;
     849                 :     else
     850              23 :         return papoLayers[iLayer];
     851                 : }
     852                 : 
     853              25 : OGRILI1Layer *ILI1Reader::GetLayerByName( const char* pszLayerName )
     854                 : 
     855                 : {
     856              65 :     for(int iLayer = 0; iLayer < nLayers; iLayer++ )
     857                 :     {
     858              65 :         if( EQUAL(pszLayerName,
     859                 :                   papoLayers[iLayer]->GetLayerDefn()->GetName()) )
     860              25 :             return papoLayers[iLayer];
     861                 :     }
     862               0 :     return NULL;
     863                 : }
     864                 : 
     865                 : /************************************************************************/
     866                 : /*                           GetLayerCount()                            */
     867                 : /************************************************************************/
     868                 : 
     869              33 : int ILI1Reader::GetLayerCount()
     870                 : 
     871                 : {
     872              33 :     return nLayers;
     873                 : }
     874                 : 
     875                 : /************************************************************************/
     876                 : /*     Read one logical line, and return split into fields.  The return */
     877                 : /*     result is a stringlist, in the sense of the CSL functions.       */
     878                 : /************************************************************************/
     879                 : 
     880             325 : char ** ILI1Reader::ReadParseLine()
     881                 : {
     882                 :     const char  *pszLine;
     883                 :     char **tokens;
     884                 :     char **conttok;
     885                 :     char *token;
     886                 : 
     887             325 :     CPLAssert( fpItf != NULL );
     888             325 :     if( fpItf == NULL )
     889               0 :         return( NULL );
     890                 : 
     891             325 :     pszLine = CPLReadLine( fpItf );
     892             325 :     if( pszLine == NULL )
     893               0 :         return( NULL );
     894                 : 
     895             325 :     if (strlen(pszLine) == 0) return NULL;
     896                 : 
     897             325 :     tokens = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
     898             325 :     token = tokens[CSLCount(tokens)-1];
     899                 : 
     900                 :     //Append CONT lines
     901             654 :     while (strlen(pszLine) && token[0] == codeContinue && token[1] == '\0')
     902                 :     {
     903                 :        //remove last token
     904               4 :       CPLFree(tokens[CSLCount(tokens)-1]);
     905               4 :       tokens[CSLCount(tokens)-1] = NULL;
     906                 : 
     907               4 :       pszLine = CPLReadLine( fpItf );
     908               4 :       conttok = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
     909               4 :       if (!conttok || !EQUAL(conttok[0], "CONT"))
     910                 :       {
     911               0 :           CSLDestroy(conttok);
     912               0 :           break;
     913                 :       }
     914                 : 
     915                 :       //append
     916               4 :       tokens = CSLInsertStrings(tokens, -1, &conttok[1]);
     917               4 :       token = tokens[CSLCount(tokens)-1];
     918                 : 
     919               4 :       CSLDestroy(conttok);
     920                 :     }
     921             325 :     return tokens;
     922                 : }
     923                 : 
     924                 : 
     925                 : 
     926              10 : IILI1Reader *CreateILI1Reader() {
     927              10 :     return new ILI1Reader();
     928                 : }
     929                 : 
     930             289 : void DestroyILI1Reader(IILI1Reader* reader)
     931                 : {
     932             289 :     if (reader)
     933              10 :         delete reader;
     934             289 : }

Generated by: LCOV version 1.7