/gdal-1.9.1-fedora/ogr/ogrsf_frmts/ili/ili1reader.cpp
C++ | 934 lines | 724 code | 116 blank | 94 comment | 223 complexity | 309f12ba3567d4f7bafaec9e2a700369 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0
- /******************************************************************************
- * $Id: ili1reader.cpp 24410 2012-05-11 21:54:08Z pka $
- *
- * Project: Interlis 1 Reader
- * Purpose: Implementation of ILI1Reader class.
- * Author: Pirmin Kalberer, Sourcepole AG
- *
- ******************************************************************************
- * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
- #include "ogr_ili1.h"
- #include "cpl_conv.h"
- #include "cpl_string.h"
- #include "ogr_api.h"
- #include "ogr_geos.h"
- #include "ilihelper.h"
- #include "iomhelper.h"
- #include "ili1reader.h"
- #include "ili1readerp.h"
- #include <vector>
- #ifdef HAVE_GEOS
- # define POLYGONIZE_AREAS
- #endif
- #ifndef POLYGONIZE_AREAS
- # if defined(__GNUC_PREREQ)
- # warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 2.1.0
- # endif
- #endif
- CPL_CVSID("$Id: ili1reader.cpp 24410 2012-05-11 21:54:08Z pka $");
- //
- // ILI1Reader
- //
- IILI1Reader::~IILI1Reader() {
- }
- ILI1Reader::ILI1Reader() {
- fpItf = NULL;
- nLayers = 0;
- papoLayers = NULL;
- curLayer = NULL;
- metaLayer = NULL;
- codeBlank = '_';
- codeUndefined = '@';
- codeContinue = '\\';
- SetArcDegrees(1);
- }
- ILI1Reader::~ILI1Reader() {
- int i;
- if (fpItf) VSIFClose( fpItf );
- for(i=0;i<nLayers;i++)
- delete papoLayers[i];
- CPLFree(papoLayers);
- delete metaLayer;
- }
- void ILI1Reader::SetArcDegrees(double arcDegrees) {
- arcIncr = arcDegrees*PI/180;
- }
- /* -------------------------------------------------------------------- */
- /* Open the source file. */
- /* -------------------------------------------------------------------- */
- int ILI1Reader::OpenFile( const char *pszFilename ) {
- fpItf = VSIFOpen( pszFilename, "r" );
- if( fpItf == NULL )
- {
- CPLError( CE_Failure, CPLE_OpenFailed,
- "Failed to open ILI file `%s'.",
- pszFilename );
- return FALSE;
- }
- return TRUE;
- }
- int ILI1Reader::HasMultiplePointGeom(const char* layername) {
- if (metaLayer != NULL) {
- OGRFeature *metaFeature = NULL;
- metaLayer->ResetReading();
- int i = -1;
- while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
- if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
- i++;
- }
- delete metaFeature;
- }
- return i;
- } else {
- return -1;
- }
- }
- char* ILI1Reader::GetPointLayerName(const char* layername, char* newlayername) {
- static char geomlayername[512];
- geomlayername[0] = '\0';
- strcat(geomlayername, layername);
- strcat(geomlayername, "__");
- strcat(geomlayername, newlayername);
- return geomlayername;
- }
- const char* ILI1Reader::GetLayerNameString(const char* topicname, const char* tablename) {
- static char layername[512];
- layername[0] = '\0';
- strcat(layername, topicname);
- strcat(layername, "__");
- strcat(layername, tablename);
- return layername;
- }
- const char* ILI1Reader::GetLayerName(IOM_BASKET model, IOM_OBJECT table) {
- static char layername[512];
- IOM_OBJECT topic = GetAttrObj(model, table, "container");
- layername[0] = '\0';
- strcat(layername, iom_getattrvalue(topic, "name"));
- strcat(layername, "__");
- strcat(layername, iom_getattrvalue(table, "name"));
- return layername;
- }
- void ILI1Reader::AddCoord(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT modelele, IOM_OBJECT typeobj) {
- unsigned int dim = ::GetCoordDim(model, typeobj);
- for (unsigned int i=0; i<dim; i++) {
- OGRFieldDefn fieldDef(CPLSPrintf("%s_%d", iom_getattrvalue(modelele, "name"), i), OFTReal);
- layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
- //CPLDebug( "AddCoord OGR_ILI", "Field %s: OFTReal", fieldDef.GetNameRef());
- }
- }
- OGRILI1Layer* ILI1Reader::AddGeomTable(const char* datalayername, const char* geomname, OGRwkbGeometryType eType) {
- static char layername[512];
- layername[0] = '\0';
- strcat(layername, datalayername);
- strcat(layername, "_");
- strcat(layername, geomname);
- OGRILI1Layer* geomlayer = new OGRILI1Layer(layername, NULL, 0, eType, NULL);
- AddLayer(geomlayer);
- OGRFieldDefn fieldDef("_TID", OFTString);
- geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef);
- if (eType == wkbPolygon)
- {
- OGRFieldDefn fieldDefRef("_RefTID", OFTString);
- geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDefRef);
- }
- OGRFieldDefn fieldDef2("ILI_Geometry", OFTString); //in write mode only?
- geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
- return geomlayer;
- }
- void ILI1Reader::AddField(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT obj) {
- const char* typenam = "Reference";
- if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.LocalAttribute")) typenam = GetTypeName(model, obj);
- //CPLDebug( "OGR_ILI", "Field %s: %s", iom_getattrvalue(obj, "name"), typenam);
- if (EQUAL(typenam, "iom04.metamodel.SurfaceType")) {
- OGRILI1Layer* polyLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbPolygon);
- layer->SetSurfacePolyLayer(polyLayer);
- //TODO: add line attributes to geometry
- } else if (EQUAL(typenam, "iom04.metamodel.AreaType")) {
- IOM_OBJECT controlPointDomain = GetAttrObj(model, GetTypeObj(model, obj), "controlPointDomain");
- if (controlPointDomain) {
- AddCoord(layer, model, obj, GetTypeObj(model, controlPointDomain));
- layer->GetLayerDefn()->SetGeomType(wkbPoint);
- }
- OGRILI1Layer* areaLineLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbMultiLineString);
- #ifdef POLYGONIZE_AREAS
- OGRILI1Layer* areaLayer = new OGRILI1Layer(CPLSPrintf("%s__Areas",layer->GetLayerDefn()->GetName()), NULL, 0, wkbPolygon, NULL);
- AddLayer(areaLayer);
- areaLayer->SetAreaLayers(layer, areaLineLayer);
- #endif
- } else if (EQUAL(typenam, "iom04.metamodel.PolylineType") ) {
- layer->GetLayerDefn()->SetGeomType(wkbMultiLineString);
- } else if (EQUAL(typenam, "iom04.metamodel.CoordType")) {
- AddCoord(layer, model, obj, GetTypeObj(model, obj));
- if (layer->GetLayerDefn()->GetGeomType() == wkbUnknown) layer->GetLayerDefn()->SetGeomType(wkbPoint);
- } else if (EQUAL(typenam, "iom04.metamodel.NumericType") ) {
- OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTReal);
- layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
- } else if (EQUAL(typenam, "iom04.metamodel.EnumerationType") ) {
- OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTInteger);
- layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
- } else {
- OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTString);
- layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
- }
- }
- int ILI1Reader::ReadModel(const char *pszModelFilename) {
- IOM_BASKET model;
- IOM_ITERATOR modelelei;
- IOM_OBJECT modelele;
- iom_init();
- // set error listener to a iom provided one, that just
- // dumps all errors to stderr
- iom_seterrlistener(iom_stderrlistener);
- // compile ili model
- char *iomarr[1] = {(char *)pszModelFilename};
- model=iom_compileIli(1, iomarr);
- if(!model){
- CPLError( CE_Failure, CPLE_FileIO, "iom_compileIli failed." );
- iom_end();
- return FALSE;
- }
- // create new layer with meta information (ILI table name and geometry column index)
- // while reading the features from the ITF we have to know which column is the geometry column
- metaLayer = new OGRILI1Layer("Metatable", NULL, 0, wkbUnknown, NULL);
- OGRFieldDefn fieldDef1("layername", OFTString);
- metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef1);
- OGRFieldDefn fieldDef2("geomIdx", OFTInteger);
- metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
- OGRFieldDefn fieldDef3("geomlayername", OFTString);
- metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef3);
- // read tables
- int j = 0;
- modelelei=iom_iteratorobject(model);
- modelele=iom_nextobject(modelelei);
- while(modelele){
- const char *tag=iom_getobjecttag(modelele);
- if (tag) {
- if (EQUAL(tag,"iom04.metamodel.Table")) {
- const char* topic = iom_getattrvalue(GetAttrObj(model, modelele, "container"), "name");
- if (!EQUAL(topic, "INTERLIS")) {
- const char* layername = GetLayerName(model, modelele);
- OGRSpatialReference *poSRSIn = NULL;
- int bWriterIn = 0;
- OGRwkbGeometryType eReqType = wkbUnknown;
- OGRILI1DataSource *poDSIn = NULL;
- CPLDebug( "OGR_ILI", "Reading table model '%s'", layername );
- // read fields
- IOM_OBJECT fields[255];
- IOM_OBJECT roledefs[255];
- memset(fields, 0, 255);
- memset(roledefs, 0, 255);
- int maxIdx = -1;
- IOM_ITERATOR fieldit=iom_iteratorobject(model);
- std::vector<IOM_OBJECT> attributes;
- for (IOM_OBJECT fieldele=iom_nextobject(fieldit); fieldele; fieldele=iom_nextobject(fieldit)){
- const char *etag=iom_getobjecttag(fieldele);
- if (etag && (EQUAL(etag,"iom04.metamodel.ViewableAttributesAndRoles"))) {
- IOM_OBJECT table = GetAttrObj(model, fieldele, "viewable");
- if (table == modelele) {
- IOM_OBJECT obj = GetAttrObj(model, fieldele, "attributesAndRoles");
- int ili1AttrIdx = GetAttrObjPos(fieldele, "attributesAndRoles")-1;
- if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.RoleDef")) {
- int ili1AttrIdxOppend = atoi(iom_getattrvalue(GetAttrObj(model, obj, "oppend"), "ili1AttrIdx"));
- if (ili1AttrIdxOppend>=0) {
- roledefs[ili1AttrIdxOppend] = obj;
- if (ili1AttrIdxOppend > maxIdx) maxIdx = ili1AttrIdxOppend;
- }
- } else {
- fields[ili1AttrIdx] = obj;
- if (ili1AttrIdx > maxIdx) maxIdx = ili1AttrIdx;
- }
- }
- }
- iom_releaseobject(fieldele);
- }
- iom_releaseiterator(fieldit);
- // if multiple gets positive we have more than one geometry column (only points)
- int multiple = -1;
- for (int i=0; i<=maxIdx; i++) {
- IOM_OBJECT obj = fields[i];
- if (obj) {
- attributes.push_back(obj);
- if (EQUAL(GetTypeName(model, obj), "iom04.metamodel.CoordType")) multiple++;
- }
- }
- for (int i=0; i<=maxIdx; i++) {
- IOM_OBJECT obj = roledefs[i];
- if (obj) attributes.insert(attributes.begin() + i, obj);
- }
- OGRFeature *feature = NULL;
- char* geomlayername = '\0';
- OGRILI1Layer* layer = NULL;
- for(size_t i=0; i<attributes.size(); i++) {
- IOM_OBJECT obj = attributes.at(i);
- const char* typenam = GetTypeName(model, obj);
- if (EQUAL(typenam, "iom04.metamodel.CoordType") || EQUAL(typenam, "iom04.metamodel.AreaType")) {
- feature = OGRFeature::CreateFeature(metaLayer->GetLayerDefn());
- feature->SetFID(j+1);
- feature->SetField("layername", layername);
- feature->SetField("geomIdx", (int)i);
- if(multiple > 0) {
- geomlayername = GetPointLayerName(layername, iom_getattrvalue(obj, "name"));
- feature->SetField("geomlayername", geomlayername);
- layer = new OGRILI1Layer(geomlayername, poSRSIn, bWriterIn, eReqType, poDSIn);
- AddLayer(layer);
- } else {
- feature->SetField("geomlayername", layername);
- layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
- AddLayer(layer);
- }
- metaLayer->AddFeature(feature);
- }
- }
- if(layer == NULL) {
- layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
- AddLayer(layer);
- }
- OGRFieldDefn fieldDef("_TID", OFTString);
- layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
- for(size_t i=0; i<attributes.size(); i++) {
- IOM_OBJECT obj = attributes.at(i);
- AddField(layer, model, obj);
- }
- // additional point layer added
- if(multiple > 0) {
- for(int i = 1; i <= multiple; i++) {
- OGRILI1Layer* pointLayer = papoLayers[nLayers-(i+1)];
- for (int j=0; j < layer->GetLayerDefn()->GetFieldCount(); j++) {
- pointLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(j));
- }
- if (pointLayer->GetLayerDefn()->GetGeomType() == wkbUnknown) pointLayer->GetLayerDefn()->SetGeomType(wkbPoint);
- }
- }
- if (papoLayers[nLayers-1]->GetLayerDefn()->GetFieldCount() == 0) {
- //Area layer added
- OGRILI1Layer* areaLayer = papoLayers[nLayers-1];
- for (int i=0; i < layer->GetLayerDefn()->GetFieldCount(); i++) {
- areaLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(i));
- }
- }
- }
- } else if (EQUAL(tag,"iom04.metamodel.Ili1Format")) {
- codeBlank = atoi(iom_getattrvalue(modelele, "blankCode"));
- CPLDebug( "OGR_ILI", "Reading Ili1Format blankCode '%c'", codeBlank );
- codeUndefined = atoi(iom_getattrvalue(modelele, "undefinedCode"));
- CPLDebug( "OGR_ILI", "Reading Ili1Format undefinedCode '%c'", codeUndefined );
- codeContinue = atoi(iom_getattrvalue(modelele, "continueCode"));
- CPLDebug( "OGR_ILI", "Reading Ili1Format continueCode '%c'", codeContinue );
- }
- iom_releaseobject(modelele);
- modelele=iom_nextobject(modelelei);
- j++;
- }
- }
- iom_releaseiterator(modelelei);
- iom_releasebasket(model);
- iom_end();
- return 0;
- }
- int ILI1Reader::ReadFeatures() {
- char **tokens = NULL;
- const char *firsttok = NULL;
- const char *pszLine;
- char *topic = NULL;
- int ret = TRUE;
- while (ret && (tokens = ReadParseLine()))
- {
- firsttok = tokens[0];
- if (EQUAL(firsttok, "SCNT"))
- {
- //read description
- do
- {
- pszLine = CPLReadLine( fpItf );
- }
- while (pszLine && !EQUALN(pszLine, "////", 4));
- ret = (pszLine != NULL);
- }
- else if (EQUAL(firsttok, "MOTR"))
- {
- //read model
- do
- {
- pszLine = CPLReadLine( fpItf );
- }
- while (pszLine && !EQUALN(pszLine, "////", 4));
- ret = (pszLine != NULL);
- }
- else if (EQUAL(firsttok, "MTID"))
- {
- }
- else if (EQUAL(firsttok, "MODL"))
- {
- }
- else if (EQUAL(firsttok, "TOPI"))
- {
- CPLFree(topic);
- topic = CPLStrdup(CSLGetField(tokens, 1));
- }
- else if (EQUAL(firsttok, "TABL"))
- {
- CPLDebug( "OGR_ILI", "Reading table '%s'", GetLayerNameString(topic, CSLGetField(tokens, 1)) );
- const char *layername = GetLayerNameString(topic, CSLGetField(tokens, 1));
- curLayer = GetLayerByName(layername);
- int multiple = HasMultiplePointGeom(layername);
- // create only a new layer if there is no curLayer AND
- // if there are more than one point geometry columns
- if (curLayer == NULL && multiple < 1) { //create one
- CPLDebug( "OGR_ILI", "No model found, using default field names." );
- OGRSpatialReference *poSRSIn = NULL;
- int bWriterIn = 0;
- OGRwkbGeometryType eReqType = wkbUnknown;
- OGRILI1DataSource *poDSIn = NULL;
- curLayer = new OGRILI1Layer(GetLayerNameString(topic, CSLGetField(tokens, 1)), poSRSIn, bWriterIn, eReqType, poDSIn);
- AddLayer(curLayer);
- }
- if(curLayer != NULL) {
- for (int i=0; i < curLayer->GetLayerDefn()->GetFieldCount(); i++) {
- CPLDebug( "OGR_ILI", "Field %d: %s", i, curLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef());
- }
- }
- ret = ReadTable(layername);
- }
- else if (EQUAL(firsttok, "ETOP"))
- {
- }
- else if (EQUAL(firsttok, "EMOD"))
- {
- }
- else if (EQUAL(firsttok, "ENDE"))
- {
- CSLDestroy(tokens);
- CPLFree(topic);
- return TRUE;
- }
- else
- {
- CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
- }
- CSLDestroy(tokens);
- tokens = NULL;
- }
- CSLDestroy(tokens);
- CPLFree(topic);
- return ret;
- }
- int ILI1Reader::AddIliGeom(OGRFeature *feature, int iField, long fpos)
- {
- #if defined(_WIN32) || defined(__WIN32__)
- //Other positions on Windows !?
- #else
- long nBlockLen = VSIFTell( fpItf )-fpos;
- VSIFSeek( fpItf, fpos, SEEK_SET );
- char *pszRawData = (char *) CPLMalloc(nBlockLen+1);
- if( (int) VSIFRead( pszRawData, 1, nBlockLen, fpItf ) != nBlockLen )
- {
- CPLFree( pszRawData );
- CPLError( CE_Failure, CPLE_FileIO, "Read of transfer file failed." );
- return FALSE;
- }
- pszRawData[nBlockLen]= '\0';
- feature->SetField(iField, pszRawData);
- CPLFree( pszRawData );
- #endif
- return TRUE;
- }
- int ILI1Reader::ReadTable(const char *layername) {
- char **tokens = NULL;
- const char *firsttok = NULL;
- int ret = TRUE;
- int warned = FALSE;
- int fIndex;
- int geomIdx = 0;
- // curLayer is NULL if we have more than one
- // point geometry column
- if(curLayer == NULL) {
- OGRFeature *metaFeature = NULL;
- metaLayer->ResetReading();
- while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
- if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
- const char *geomlayername = metaFeature->GetFieldAsString(2);
- curLayer = GetLayerByName(geomlayername);
- delete metaFeature;
- break;
- }
- delete metaFeature;
- }
- }
- OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
- OGRFeature *feature = NULL;
- // get the geometry index of the current layer
- // only if the model is read
- if(featureDef->GetFieldCount() != 0) {
- OGRFeature *metaFeature = NULL;
- metaLayer->ResetReading();
- while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
- if(EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
- geomIdx = metaFeature->GetFieldAsInteger(1);
- }
- delete metaFeature;
- }
- }
- long fpos = VSIFTell(fpItf);
- while (ret && (tokens = ReadParseLine()))
- {
- firsttok = CSLGetField(tokens, 0);
- if (EQUAL(firsttok, "OBJE"))
- {
- //Check for features spread over multiple objects
- if (featureDef->GetGeomType() == wkbPolygon)
- {
- //Multiple polygon rings
- feature = curLayer->GetFeatureRef(atol(CSLGetField(tokens, 2)));
- }
- else if (featureDef->GetGeomType() == wkbGeometryCollection)
- {
- //AREA lines spread over mutltiple objects
- }
- else
- {
- feature = NULL;
- }
- if (feature == NULL)
- {
- if (featureDef->GetFieldCount() == 0)
- {
- CPLDebug( "OGR_ILI", "No field definition found for table: %s", featureDef->GetName() );
- //Model not read - use heuristics
- for (fIndex=1; fIndex<CSLCount(tokens); fIndex++)
- {
- char szFieldName[32];
- sprintf(szFieldName, "Field%02d", fIndex);
- OGRFieldDefn oFieldDefn(szFieldName, OFTString);
- featureDef->AddFieldDefn(&oFieldDefn);
- }
- }
- //start new feature
- feature = new OGRFeature(featureDef);
- int fieldno = 0;
- for (fIndex=1; fIndex<CSLCount(tokens) && fieldno < featureDef->GetFieldCount(); fIndex++, fieldno++)
- {
- if (!(tokens[fIndex][0] == codeUndefined && tokens[fIndex][1] == '\0')) {
- //CPLDebug( "READ TABLE OGR_ILI", "Setting Field %d (Type %d): %s", fieldno, featureDef->GetFieldDefn(fieldno)->GetType(), tokens[fIndex]);
- if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTString) {
- //Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8
- char* pszRecoded = CPLRecode(tokens[fIndex], CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
- //Replace space marks
- for(char* pszString = pszRecoded; *pszString != '\0'; pszString++ ) {
- if (*pszString == codeBlank) *pszString = ' ';
- }
- feature->SetField(fieldno, pszRecoded);
- CPLFree(pszRecoded);
- } else {
- feature->SetField(fieldno, tokens[fIndex]);
- }
- if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTReal
- && fieldno > 0
- && featureDef->GetFieldDefn(fieldno-1)->GetType() == OFTReal
- && featureDef->GetGeomType() == wkbPoint
- /*
- // if there is no ili model read,
- // we have no chance to detect the
- // geometry column!!
- */
- && (fieldno-2) == geomIdx) {
- //add Point geometry
- OGRPoint *ogrPoint = new OGRPoint(atof(tokens[fIndex-1]), atof(tokens[fIndex]));
- feature->SetGeometryDirectly(ogrPoint);
- }
- }
- }
- if (!warned && featureDef->GetFieldCount() != CSLCount(tokens)-1 && !(featureDef->GetFieldCount() == CSLCount(tokens) && EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))) {
- CPLDebug( "OGR_ILI", "Field count doesn't match. %d declared, %d found", featureDef->GetFieldCount(), CSLCount(tokens)-1);
- warned = TRUE;
- }
- if (featureDef->GetGeomType() == wkbPolygon)
- feature->SetFID(atol(feature->GetFieldAsString(1)));
- else if (feature->GetFieldCount() > 0)
- feature->SetFID(atol(feature->GetFieldAsString(0)));
- curLayer->AddFeature(feature);
- }
- }
- else if (EQUAL(firsttok, "STPT"))
- {
- ReadGeom(tokens, featureDef->GetGeomType(), feature);
- if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
- {
- AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos); //TODO: append multi-OBJECT geometries
- }
- }
- else if (EQUAL(firsttok, "ELIN"))
- {
- //empty geom
- }
- else if (EQUAL(firsttok, "EDGE"))
- {
- tokens = ReadParseLine(); //STPT
- ReadGeom(tokens, wkbMultiLineString, feature);
- if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
- {
- AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos);
- }
- }
- else if (EQUAL(firsttok, "PERI"))
- {
- }
- else if (EQUAL(firsttok, "ETAB"))
- {
- if(HasMultiplePointGeom(layername) > 0) {
- OGRFeature *metaFeature = NULL;
- metaLayer->ResetReading();
- while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
- int pntCln = 1;
- if(EQUAL(layername, metaFeature->GetFieldAsString(0)) && !EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
- pntCln++;
- OGRILI1Layer *curLayerTmp = GetLayerByName(metaFeature->GetFieldAsString(2));
- OGRFeature *tmpFeature = NULL;
- int geomIdxTmp = metaFeature->GetFieldAsInteger(1);
- curLayer->ResetReading();
- while((tmpFeature = curLayer->GetNextFeature()) != NULL ) {
- OGRPoint *ogrPoint = new OGRPoint(atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln)), atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln + 1)));
- tmpFeature->SetGeometryDirectly(ogrPoint);
- curLayerTmp->AddFeature(tmpFeature);
- }
- }
- delete metaFeature;
- }
- }
- CSLDestroy(tokens);
- return TRUE;
- }
- else
- {
- CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
- }
- CSLDestroy(tokens);
- fpos = VSIFTell(fpItf);
- }
- return ret;
- }
- void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *feature) {
- char **tokens = NULL;
- const char *firsttok = NULL;
- int end = FALSE;
- int isArc = FALSE;
- OGRLineString *ogrLine = NULL; //current line
- OGRLinearRing *ogrRing = NULL; //current ring
- OGRPolygon *ogrPoly = NULL; //current polygon
- OGRPoint ogrPoint, arcPoint, endPoint; //points for arc interpolation
- OGRMultiLineString *ogrMultiLine = NULL; //current multi line
- //tokens = ["STPT", "1111", "22222"]
- ogrPoint.setX(atof(stgeom[1])); ogrPoint.setY(atof(stgeom[2]));
- ogrLine = (eType == wkbPolygon) ? new OGRLinearRing() : new OGRLineString();
- ogrLine->addPoint(&ogrPoint);
- //Set feature geometry
- if (eType == wkbMultiLineString)
- {
- ogrMultiLine = new OGRMultiLineString();
- feature->SetGeometryDirectly(ogrMultiLine);
- }
- else if (eType == wkbGeometryCollection) //AREA
- {
- if (feature->GetGeometryRef())
- ogrMultiLine = (OGRMultiLineString *)feature->GetGeometryRef();
- else
- {
- ogrMultiLine = new OGRMultiLineString();
- feature->SetGeometryDirectly(ogrMultiLine);
- }
- }
- else if (eType == wkbPolygon)
- {
- if (feature->GetGeometryRef())
- {
- ogrPoly = (OGRPolygon *)feature->GetGeometryRef();
- if (ogrPoly->getNumInteriorRings() > 0)
- ogrRing = ogrPoly->getInteriorRing(ogrPoly->getNumInteriorRings()-1);
- else
- ogrRing = ogrPoly->getExteriorRing();
- if (ogrRing && !ogrRing->get_IsClosed()) ogrLine = ogrRing; //SURFACE polygon spread over multiple OBJECTs
- }
- else
- {
- ogrPoly = new OGRPolygon();
- feature->SetGeometryDirectly(ogrPoly);
- }
- }
- else
- {
- feature->SetGeometryDirectly(ogrLine);
- }
- //Parse geometry
- while (!end && (tokens = ReadParseLine()))
- {
- firsttok = CSLGetField(tokens, 0);
- if (EQUAL(firsttok, "LIPT"))
- {
- if (isArc) {
- endPoint.setX(atof(tokens[1])); endPoint.setY(atof(tokens[2]));
- interpolateArc(ogrLine, &ogrPoint, &arcPoint, &endPoint, arcIncr);
- }
- ogrPoint.setX(atof(tokens[1])); ogrPoint.setY(atof(tokens[2])); isArc = FALSE;
- ogrLine->addPoint(&ogrPoint);
- }
- else if (EQUAL(firsttok, "ARCP"))
- {
- isArc = TRUE;
- arcPoint.setX(atof(tokens[1])); arcPoint.setY(atof(tokens[2]));
- }
- else if (EQUAL(firsttok, "ELIN"))
- {
- if (ogrMultiLine)
- {
- ogrMultiLine->addGeometryDirectly(ogrLine);
- }
- if (ogrPoly && ogrLine != ogrRing)
- {
- ogrPoly->addRingDirectly((OGRLinearRing *)ogrLine);
- }
- end = TRUE;
- }
- else if (EQUAL(firsttok, "EEDG"))
- {
- end = TRUE;
- }
- else if (EQUAL(firsttok, "LATT"))
- {
- //Line Attributes (ignored)
- }
- else if (EQUAL(firsttok, "EFLA"))
- {
- end = TRUE;
- }
- else if (EQUAL(firsttok, "ETAB"))
- {
- end = TRUE;
- }
- else
- {
- CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
- }
- CSLDestroy(tokens);
- }
- }
- /************************************************************************/
- /* AddLayer() */
- /************************************************************************/
- void ILI1Reader::AddLayer( OGRILI1Layer * poNewLayer )
- {
- nLayers++;
- papoLayers = (OGRILI1Layer **)
- CPLRealloc( papoLayers, sizeof(void*) * nLayers );
- papoLayers[nLayers-1] = poNewLayer;
- }
- /************************************************************************/
- /* AddAreaLayer() */
- /************************************************************************/
- /************************************************************************/
- /* GetLayer() */
- /************************************************************************/
- OGRILI1Layer *ILI1Reader::GetLayer( int iLayer )
- {
- if( iLayer < 0 || iLayer >= nLayers )
- return NULL;
- else
- return papoLayers[iLayer];
- }
- OGRILI1Layer *ILI1Reader::GetLayerByName( const char* pszLayerName )
- {
- for(int iLayer = 0; iLayer < nLayers; iLayer++ )
- {
- if( EQUAL(pszLayerName,
- papoLayers[iLayer]->GetLayerDefn()->GetName()) )
- return papoLayers[iLayer];
- }
- return NULL;
- }
- /************************************************************************/
- /* GetLayerCount() */
- /************************************************************************/
- int ILI1Reader::GetLayerCount()
- {
- return nLayers;
- }
- /************************************************************************/
- /* Read one logical line, and return split into fields. The return */
- /* result is a stringlist, in the sense of the CSL functions. */
- /************************************************************************/
- char ** ILI1Reader::ReadParseLine()
- {
- const char *pszLine;
- char **tokens;
- char **conttok;
- char *token;
- CPLAssert( fpItf != NULL );
- if( fpItf == NULL )
- return( NULL );
- pszLine = CPLReadLine( fpItf );
- if( pszLine == NULL )
- return( NULL );
- if (strlen(pszLine) == 0) return NULL;
- tokens = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
- token = tokens[CSLCount(tokens)-1];
- //Append CONT lines
- while (strlen(pszLine) && token[0] == codeContinue && token[1] == '\0')
- {
- //remove last token
- CPLFree(tokens[CSLCount(tokens)-1]);
- tokens[CSLCount(tokens)-1] = NULL;
- pszLine = CPLReadLine( fpItf );
- conttok = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
- if (!conttok || !EQUAL(conttok[0], "CONT"))
- {
- CSLDestroy(conttok);
- break;
- }
- //append
- tokens = CSLInsertStrings(tokens, -1, &conttok[1]);
- token = tokens[CSLCount(tokens)-1];
- CSLDestroy(conttok);
- }
- return tokens;
- }
- IILI1Reader *CreateILI1Reader() {
- return new ILI1Reader();
- }
- void DestroyILI1Reader(IILI1Reader* reader)
- {
- if (reader)
- delete reader;
- }