PageRenderTime 51ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

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