Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Interlis 1 Reader
4 : * Purpose: Implementation of ILI1Reader class.
5 : * Author: Pirmin Kalberer, Sourcepole AG
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
9 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 : #include "ogr_api.h"
17 : #include "ogr_ili1.h"
18 : #include "ogr_geos.h"
19 :
20 : #include "ili1reader.h"
21 : #include "ili1readerp.h"
22 :
23 : #include <vector>
24 :
25 : #ifdef HAVE_GEOS
26 : #define POLYGONIZE_AREAS
27 : #endif
28 :
29 : #ifndef POLYGONIZE_AREAS
30 : #if defined(__GNUC_PREREQ)
31 : // # warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 3.1.0
32 : #endif
33 : #endif
34 :
35 : //
36 : // ILI1Reader
37 : //
38 48 : IILI1Reader::~IILI1Reader()
39 : {
40 48 : }
41 :
42 48 : ILI1Reader::ILI1Reader()
43 : : fpItf(nullptr), nLayers(0), papoLayers(nullptr), curLayer(nullptr),
44 48 : codeBlank('_'), codeUndefined('@'), codeContinue('\\')
45 : {
46 48 : }
47 :
48 96 : ILI1Reader::~ILI1Reader()
49 : {
50 48 : if (fpItf)
51 48 : VSIFCloseL(fpItf);
52 :
53 163 : for (int i = 0; i < nLayers; i++)
54 115 : delete papoLayers[i];
55 48 : CPLFree(papoLayers);
56 96 : }
57 :
58 : /* -------------------------------------------------------------------- */
59 : /* Open the source file. */
60 : /* -------------------------------------------------------------------- */
61 48 : int ILI1Reader::OpenFile(const char *pszFilename)
62 : {
63 48 : fpItf = VSIFOpenL(pszFilename, "r");
64 48 : if (fpItf == nullptr)
65 : {
66 0 : CPLError(CE_Failure, CPLE_OpenFailed, "Failed to open ILI file `%s'.",
67 : pszFilename);
68 :
69 0 : return FALSE;
70 : }
71 48 : return TRUE;
72 : }
73 :
74 171 : const char *ILI1Reader::GetLayerNameString(const char *topicname,
75 : const char *tablename)
76 : {
77 :
78 171 : return CPLSPrintf("%s__%s", topicname, tablename);
79 : }
80 :
81 16 : int ILI1Reader::ReadModel(ImdReader *poImdReader, const char *pszModelFilename,
82 : OGRILI1DataSource *poDS)
83 : {
84 :
85 16 : poImdReader->ReadModel(pszModelFilename);
86 37 : for (FeatureDefnInfos::const_iterator it =
87 16 : poImdReader->featureDefnInfos.begin();
88 90 : it != poImdReader->featureDefnInfos.end(); ++it)
89 : {
90 : #if DEBUG_VERBOSE
91 : CPLDebug("OGR_ILI", "Adding OGRILI1Layer with table '%s'",
92 : it->GetTableDefnRef()->GetName());
93 : #endif
94 : OGRILI1Layer *layer =
95 37 : new OGRILI1Layer(it->GetTableDefnRef(), it->poGeomFieldInfos, poDS);
96 37 : AddLayer(layer);
97 : // Create additional layers for surface and area geometries.
98 59 : for (GeomFieldInfos::const_iterator it2 = it->poGeomFieldInfos.begin();
99 81 : it2 != it->poGeomFieldInfos.end(); ++it2)
100 : {
101 22 : if (it2->second.GetGeomTableDefnRef())
102 : {
103 : OGRFeatureDefn *poGeomTableDefn =
104 15 : it2->second.GetGeomTableDefnRef();
105 : OGRGeomFieldDefn *poOGRGeomFieldDefn =
106 15 : poGeomTableDefn->GetGeomFieldDefn(0);
107 30 : GeomFieldInfos oGeomFieldInfos;
108 : // We add iliGeomType to recognize Ili1 geom tables
109 30 : oGeomFieldInfos[poOGRGeomFieldDefn->GetNameRef()].iliGeomType =
110 30 : it2->second.iliGeomType;
111 : #if DEBUG_VERBOSE
112 : CPLDebug("OGR_ILI",
113 : "Adding OGRILI1Layer with geometry table '%s'",
114 : poGeomTableDefn->GetName());
115 : #endif
116 : OGRILI1Layer *geomlayer =
117 15 : new OGRILI1Layer(poGeomTableDefn, oGeomFieldInfos, poDS);
118 15 : AddLayer(geomlayer);
119 : }
120 : }
121 : }
122 :
123 16 : codeBlank = poImdReader->codeBlank;
124 16 : CPLDebug("OGR_ILI", "Ili1Format blankCode '%c'", poImdReader->codeBlank);
125 16 : codeUndefined = poImdReader->codeUndefined;
126 16 : CPLDebug("OGR_ILI", "Ili1Format undefinedCode '%c'",
127 16 : poImdReader->codeUndefined);
128 16 : codeContinue = poImdReader->codeContinue;
129 16 : CPLDebug("OGR_ILI", "Ili1Format continueCode '%c'",
130 16 : poImdReader->codeContinue);
131 16 : return 0;
132 : }
133 :
134 48 : int ILI1Reader::ReadFeatures()
135 : {
136 48 : char **tokens = nullptr;
137 48 : const char *pszLine = nullptr;
138 48 : char *topic = CPLStrdup("(null)");
139 48 : int ret = TRUE;
140 :
141 475 : while (ret && (tokens = ReadParseLine()) != nullptr)
142 : {
143 475 : const char *firsttok = tokens[0];
144 475 : if (EQUAL(firsttok, "SCNT"))
145 : {
146 : // read description
147 45 : do
148 : {
149 93 : pszLine = CPLReadLineL(fpItf);
150 93 : } while (pszLine && !STARTS_WITH_CI(pszLine, "////"));
151 48 : ret = (pszLine != nullptr);
152 : }
153 427 : else if (EQUAL(firsttok, "MOTR"))
154 : {
155 : // read model
156 0 : do
157 : {
158 0 : pszLine = CPLReadLineL(fpItf);
159 0 : } while (pszLine && !STARTS_WITH_CI(pszLine, "////"));
160 0 : ret = (pszLine != nullptr);
161 : }
162 427 : else if (EQUAL(firsttok, "MTID"))
163 : {
164 : }
165 379 : else if (EQUAL(firsttok, "MODL"))
166 : {
167 : }
168 331 : else if (EQUAL(firsttok, "TOPI") && CSLCount(tokens) >= 2)
169 : {
170 79 : CPLFree(topic);
171 79 : topic = CPLStrdup(CSLGetField(tokens, 1));
172 : }
173 252 : else if (EQUAL(firsttok, "TABL") && CSLCount(tokens) >= 2)
174 : {
175 : const char *layername =
176 108 : GetLayerNameString(topic, CSLGetField(tokens, 1));
177 108 : CPLDebug("OGR_ILI", "Reading table '%s'", layername);
178 108 : curLayer = GetLayerByName(layername);
179 :
180 108 : if (curLayer == nullptr)
181 : { // create one
182 63 : CPLError(CE_Warning, CPLE_AppDefined,
183 : "No model definition for table '%s' found, "
184 : "using default field names.",
185 : layername);
186 : OGRFeatureDefn *poFeatureDefn = new OGRFeatureDefn(
187 63 : GetLayerNameString(topic, CSLGetField(tokens, 1)));
188 63 : poFeatureDefn->SetGeomType(wkbUnknown);
189 126 : GeomFieldInfos oGeomFieldInfos;
190 63 : curLayer =
191 63 : new OGRILI1Layer(poFeatureDefn, oGeomFieldInfos, nullptr);
192 63 : AddLayer(curLayer);
193 : }
194 108 : if (curLayer != nullptr)
195 : {
196 263 : for (int i = 0; i < curLayer->GetLayerDefn()->GetFieldCount();
197 : i++)
198 : {
199 155 : CPLDebug("OGR_ILI", "Field %d: %s", i,
200 155 : curLayer->GetLayerDefn()
201 155 : ->GetFieldDefn(i)
202 : ->GetNameRef());
203 : }
204 : }
205 108 : ret = ReadTable(layername);
206 : }
207 144 : else if (EQUAL(firsttok, "ETOP"))
208 : {
209 : }
210 96 : else if (EQUAL(firsttok, "EMOD"))
211 : {
212 : }
213 48 : else if (EQUAL(firsttok, "ENDE"))
214 : {
215 48 : CSLDestroy(tokens);
216 48 : CPLFree(topic);
217 48 : return TRUE;
218 : }
219 : else
220 : {
221 0 : CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
222 : firsttok);
223 : }
224 :
225 427 : CSLDestroy(tokens);
226 427 : tokens = nullptr;
227 : }
228 :
229 0 : CSLDestroy(tokens);
230 0 : CPLFree(topic);
231 :
232 0 : return ret;
233 : }
234 :
235 108 : int ILI1Reader::ReadTable(CPL_UNUSED const char *layername)
236 : {
237 108 : char **tokens = nullptr;
238 108 : int warned = FALSE;
239 108 : int geomIdx = -1;
240 :
241 108 : OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
242 108 : OGRFeature *feature = nullptr;
243 108 : bool bFeatureAdded = false;
244 :
245 508 : while ((tokens = ReadParseLine()) != nullptr)
246 : {
247 508 : const char *firsttok = CSLGetField(tokens, 0);
248 508 : if (EQUAL(firsttok, "OBJE"))
249 : {
250 328 : if (featureDef->GetFieldCount() == 0 &&
251 62 : curLayer->GetFeatureCount() == 0)
252 : {
253 62 : CPLError(CE_Warning, CPLE_AppDefined,
254 : "No field definition found for table: %s",
255 62 : featureDef->GetName());
256 : // Model not read - use heuristics.
257 322 : for (int fIndex = 1; tokens[fIndex] != nullptr; fIndex++)
258 : {
259 : char szFieldName[32];
260 260 : snprintf(szFieldName, sizeof(szFieldName), "Field%02d",
261 : fIndex);
262 520 : OGRFieldDefn oFieldDefn(szFieldName, OFTString);
263 260 : featureDef->AddFieldDefn(&oFieldDefn);
264 : }
265 : }
266 : // start new feature
267 266 : if (!bFeatureAdded)
268 107 : delete feature;
269 266 : feature = new OGRFeature(featureDef);
270 :
271 1437 : for (int fIndex = 1, fieldno = 0;
272 2707 : tokens[fIndex] != nullptr &&
273 1270 : fieldno < featureDef->GetFieldCount();
274 : fIndex++, fieldno++)
275 : {
276 1171 : if (!(tokens[fIndex][0] == codeUndefined &&
277 191 : tokens[fIndex][1] == '\0'))
278 : {
279 : #ifdef DEBUG_VERBOSE
280 : CPLDebug("READ TABLE OGR_ILI",
281 : "Setting Field %d (Type %d): %s", fieldno,
282 : featureDef->GetFieldDefn(fieldno)->GetType(),
283 : tokens[fIndex]);
284 : #endif
285 980 : if (featureDef->GetFieldDefn(fieldno)->GetType() ==
286 : OFTString)
287 : {
288 : // Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode
289 : // to UTF-8
290 1606 : char *pszRecoded = CPLRecode(
291 803 : tokens[fIndex], CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
292 : // Replace space marks
293 4427 : for (char *pszString = pszRecoded; *pszString != '\0';
294 : pszString++)
295 : {
296 3624 : if (*pszString == codeBlank)
297 27 : *pszString = ' ';
298 : }
299 803 : feature->SetField(fieldno, pszRecoded);
300 803 : CPLFree(pszRecoded);
301 : }
302 : else
303 : {
304 177 : feature->SetField(fieldno, tokens[fIndex]);
305 : }
306 980 : if (featureDef->GetFieldDefn(fieldno)->GetType() ==
307 159 : OFTReal &&
308 1139 : fieldno > 0 &&
309 159 : featureDef->GetFieldDefn(fieldno - 1)->GetType() ==
310 : OFTReal)
311 : {
312 : // Check for Point geometry (Coord type).
313 : // If there is no ili model read,
314 : // we have no chance to detect the
315 : // geometry column.
316 : CPLString geomfldname =
317 214 : featureDef->GetFieldDefn(fieldno)->GetNameRef();
318 : // Check if name ends with _1.
319 214 : if (geomfldname.size() >= 2 &&
320 107 : geomfldname[geomfldname.size() - 2] == '_')
321 : {
322 : geomfldname =
323 30 : geomfldname.substr(0, geomfldname.size() - 2);
324 30 : geomIdx = featureDef->GetGeomFieldIndex(
325 30 : geomfldname.c_str());
326 30 : if (geomIdx == -1)
327 : {
328 0 : CPLError(
329 : CE_Warning, CPLE_AppDefined,
330 : "No matching definition for field '%s' of "
331 : "table %s found",
332 0 : geomfldname.c_str(), featureDef->GetName());
333 : }
334 : }
335 : else
336 : {
337 77 : geomIdx = -1;
338 : }
339 107 : if (geomIdx >= 0)
340 : {
341 60 : if (featureDef->GetGeomFieldDefn(geomIdx)
342 30 : ->GetType() == wkbPoint)
343 : {
344 : // Add Point geometry.
345 : OGRPoint *ogrPoint =
346 27 : new OGRPoint(CPLAtof(tokens[fIndex - 1]),
347 27 : CPLAtof(tokens[fIndex]));
348 27 : feature->SetGeomFieldDirectly(geomIdx,
349 : ogrPoint);
350 : }
351 6 : else if (featureDef->GetGeomFieldDefn(geomIdx)
352 6 : ->GetType() == wkbPoint25D &&
353 6 : fieldno > 1 &&
354 3 : featureDef->GetFieldDefn(fieldno - 2)
355 3 : ->GetType() == OFTReal)
356 : {
357 : // Add 3D Point geometry.
358 : OGRPoint *ogrPoint =
359 3 : new OGRPoint(CPLAtof(tokens[fIndex - 2]),
360 3 : CPLAtof(tokens[fIndex - 1]),
361 3 : CPLAtof(tokens[fIndex]));
362 3 : feature->SetGeomFieldDirectly(geomIdx,
363 : ogrPoint);
364 : }
365 : }
366 : }
367 : }
368 : }
369 266 : if (!warned && featureDef->GetFieldCount() != CSLCount(tokens) - 1)
370 : {
371 33 : CPLError(CE_Warning, CPLE_AppDefined,
372 : "Field count of table %s doesn't match. %d declared, "
373 : "%d found (e.g. ignored LINEATTR)",
374 33 : featureDef->GetName(), featureDef->GetFieldCount(),
375 33 : CSLCount(tokens) - 1);
376 33 : warned = TRUE;
377 : }
378 266 : if (feature->GetFieldCount() > 0)
379 : {
380 : // USE _TID as FID. TODO: respect IDENT field from model.
381 266 : feature->SetFID(feature->GetFieldAsInteger64(0));
382 : }
383 266 : curLayer->AddFeature(feature);
384 266 : bFeatureAdded = true;
385 266 : geomIdx = -1; // Reset
386 : }
387 242 : else if (EQUAL(firsttok, "STPT") && feature != nullptr)
388 : {
389 : // Find next non-Point geometry
390 133 : if (geomIdx < 0)
391 121 : geomIdx = 0;
392 266 : while (geomIdx < featureDef->GetGeomFieldCount() &&
393 133 : featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint)
394 : {
395 0 : geomIdx++;
396 : }
397 : OGRwkbGeometryType geomType =
398 133 : (geomIdx < featureDef->GetGeomFieldCount())
399 133 : ? featureDef->GetGeomFieldDefn(geomIdx)->GetType()
400 133 : : wkbNone;
401 133 : if (CSLCount(tokens) >= 3)
402 133 : ReadGeom(tokens, geomIdx, geomType, feature);
403 : }
404 109 : else if (EQUAL(firsttok, "ELIN"))
405 : {
406 : // Empty geom.
407 : }
408 108 : else if (EQUAL(firsttok, "EDGE") && feature != nullptr)
409 : {
410 0 : CSLDestroy(tokens);
411 0 : tokens = ReadParseLine(); // STPT
412 : // Find next non-Point geometry
413 0 : do
414 : {
415 0 : geomIdx++;
416 0 : } while (geomIdx < featureDef->GetGeomFieldCount() &&
417 0 : featureDef->GetGeomFieldDefn(geomIdx)->GetType() ==
418 : wkbPoint);
419 0 : if (CSLCount(tokens) >= 3)
420 0 : ReadGeom(tokens, geomIdx, wkbMultiLineString, feature);
421 : }
422 108 : else if (EQUAL(firsttok, "PERI"))
423 : {
424 : }
425 108 : else if (EQUAL(firsttok, "ETAB"))
426 : {
427 108 : CPLDebug("OGR_ILI", "Total features: " CPL_FRMT_GIB,
428 108 : curLayer->GetFeatureCount());
429 108 : CSLDestroy(tokens);
430 108 : if (!bFeatureAdded)
431 1 : delete feature;
432 108 : return TRUE;
433 : }
434 : else
435 : {
436 0 : CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
437 : firsttok);
438 : }
439 :
440 400 : CSLDestroy(tokens);
441 : }
442 :
443 0 : if (!bFeatureAdded)
444 0 : delete feature;
445 :
446 0 : return TRUE;
447 : }
448 :
449 133 : void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType,
450 : OGRFeature *feature)
451 : {
452 : #ifdef DEBUG_VERBOSE
453 : CPLDebug("OGR_ILI", "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s",
454 : geomIdx, OGRGeometryTypeToName(eType));
455 : #endif
456 133 : if (eType == wkbNone)
457 : {
458 0 : CPLError(CE_Warning, CPLE_AppDefined,
459 : "Calling ILI1Reader::ReadGeom with wkbNone");
460 : }
461 :
462 : // Initialize geometry.
463 :
464 133 : OGRCompoundCurve *ogrCurve = new OGRCompoundCurve();
465 133 : OGRCurvePolygon *ogrPoly = nullptr; // current polygon
466 133 : OGRMultiCurve *ogrMultiLine = nullptr; // current multi line
467 :
468 133 : if (eType == wkbMultiCurve || eType == wkbMultiLineString)
469 : {
470 60 : ogrMultiLine = new OGRMultiCurve();
471 : }
472 73 : else if (eType == wkbPolygon || eType == wkbCurvePolygon)
473 : {
474 0 : ogrPoly = new OGRCurvePolygon();
475 : }
476 :
477 266 : OGRPoint ogrPoint; // Current point.
478 133 : ogrPoint.setX(CPLAtof(stgeom[1]));
479 133 : ogrPoint.setY(CPLAtof(stgeom[2]));
480 :
481 133 : OGRLineString *ogrLine = new OGRLineString();
482 133 : ogrLine->addPoint(&ogrPoint);
483 :
484 : // Parse geometry.
485 :
486 133 : char **tokens = nullptr;
487 133 : bool end = false;
488 133 : OGRCircularString *arc = nullptr; // current arc
489 :
490 780 : while (!end && (tokens = ReadParseLine()) != nullptr)
491 : {
492 647 : const char *firsttok = CSLGetField(tokens, 0);
493 647 : if (firsttok == nullptr)
494 : {
495 : // do nothing
496 : }
497 647 : else if (EQUAL(firsttok, "LIPT") && CSLCount(tokens) >= 3)
498 : {
499 491 : ogrPoint.setX(CPLAtof(tokens[1]));
500 491 : ogrPoint.setY(CPLAtof(tokens[2]));
501 491 : if (arc)
502 : {
503 23 : arc->addPoint(&ogrPoint);
504 23 : OGRErr error = ogrCurve->addCurveDirectly(arc);
505 23 : if (error != OGRERR_NONE)
506 : {
507 0 : char *pszJSon = arc->exportToJson();
508 0 : CPLError(CE_Warning, CPLE_AppDefined,
509 : "Could not add geometry: %s",
510 : pszJSon ? pszJSon : "(null)");
511 0 : CPLFree(pszJSon);
512 0 : delete arc;
513 : }
514 23 : arc = nullptr;
515 : }
516 491 : ogrLine->addPoint(&ogrPoint);
517 : }
518 156 : else if (EQUAL(firsttok, "ARCP") && CSLCount(tokens) >= 3)
519 : {
520 : // Finish line and start arc
521 23 : if (ogrLine->getNumPoints() > 1)
522 : {
523 10 : OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
524 10 : if (error != OGRERR_NONE)
525 : {
526 0 : char *pszJSon = ogrLine->exportToJson();
527 0 : CPLError(CE_Warning, CPLE_AppDefined,
528 : "Could not add geometry: %s",
529 : pszJSon ? pszJSon : "(null)");
530 0 : CPLFree(pszJSon);
531 0 : delete ogrLine;
532 : }
533 10 : ogrLine = new OGRLineString();
534 : }
535 : else
536 : {
537 13 : ogrLine->empty();
538 : }
539 23 : delete arc;
540 23 : arc = new OGRCircularString();
541 23 : arc->addPoint(&ogrPoint);
542 23 : ogrPoint.setX(CPLAtof(tokens[1]));
543 23 : ogrPoint.setY(CPLAtof(tokens[2]));
544 23 : arc->addPoint(&ogrPoint);
545 : }
546 133 : else if (EQUAL(firsttok, "ELIN"))
547 : {
548 133 : if (ogrLine->getNumPoints() > 1)
549 : { // Ignore single LIPT after ARCP
550 133 : OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
551 133 : if (error != OGRERR_NONE)
552 : {
553 0 : char *pszJSon = ogrLine->exportToJson();
554 0 : CPLError(CE_Warning, CPLE_AppDefined,
555 : "Could not add geometry: %s",
556 : pszJSon ? pszJSon : "(null)");
557 0 : CPLFree(pszJSon);
558 0 : delete ogrLine;
559 : }
560 133 : ogrLine = nullptr;
561 : }
562 133 : if (!ogrCurve->IsEmpty())
563 : {
564 133 : if (ogrMultiLine)
565 : {
566 60 : OGRErr error = ogrMultiLine->addGeometryDirectly(ogrCurve);
567 60 : if (error != OGRERR_NONE)
568 : {
569 0 : char *pszJSon = ogrCurve->exportToJson();
570 0 : CPLError(CE_Warning, CPLE_AppDefined,
571 : "Could not add geometry: %s",
572 : pszJSon ? pszJSon : "(null)");
573 0 : CPLFree(pszJSon);
574 0 : delete ogrCurve;
575 : }
576 60 : ogrCurve = nullptr;
577 : }
578 133 : if (ogrPoly)
579 : {
580 0 : OGRErr error = ogrPoly->addRingDirectly(ogrCurve);
581 0 : if (error != OGRERR_NONE)
582 : {
583 0 : char *pszJSon = ogrCurve->exportToJson();
584 0 : CPLError(CE_Warning, CPLE_AppDefined,
585 : "Could not add geometry: %s",
586 : pszJSon ? pszJSon : "(null)");
587 0 : CPLFree(pszJSon);
588 0 : delete ogrCurve;
589 : }
590 0 : ogrCurve = nullptr;
591 : }
592 : }
593 133 : end = true;
594 : }
595 0 : else if (EQUAL(firsttok, "EEDG"))
596 : {
597 0 : end = true;
598 : }
599 0 : else if (EQUAL(firsttok, "LATT"))
600 : {
601 : // Line Attributes (ignored)
602 : }
603 0 : else if (EQUAL(firsttok, "EFLA"))
604 : {
605 0 : end = true;
606 : }
607 0 : else if (EQUAL(firsttok, "ETAB"))
608 : {
609 0 : end = true;
610 : }
611 : else
612 : {
613 0 : CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
614 : firsttok);
615 : }
616 :
617 647 : CSLDestroy(tokens);
618 : }
619 133 : delete arc;
620 :
621 133 : delete ogrLine;
622 :
623 : // Set feature geometry
624 133 : if (eType == wkbMultiCurve)
625 : {
626 42 : feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine);
627 42 : delete ogrCurve;
628 : }
629 91 : else if (eType == wkbMultiLineString)
630 : {
631 18 : feature->SetGeomFieldDirectly(geomIdx,
632 18 : ogrMultiLine->getLinearGeometry());
633 18 : delete ogrMultiLine;
634 18 : delete ogrCurve;
635 : }
636 73 : else if (eType == wkbCurvePolygon)
637 : {
638 0 : feature->SetGeomFieldDirectly(geomIdx, ogrPoly);
639 0 : delete ogrCurve;
640 : }
641 73 : else if (eType == wkbPolygon)
642 : {
643 0 : feature->SetGeomFieldDirectly(geomIdx, ogrPoly->getLinearGeometry());
644 0 : delete ogrPoly;
645 0 : delete ogrCurve;
646 : }
647 : else
648 : {
649 73 : feature->SetGeomFieldDirectly(geomIdx, ogrCurve);
650 : }
651 133 : }
652 :
653 : /************************************************************************/
654 : /* AddLayer() */
655 : /************************************************************************/
656 :
657 115 : void ILI1Reader::AddLayer(OGRILI1Layer *poNewLayer)
658 :
659 : {
660 115 : nLayers++;
661 :
662 115 : papoLayers = static_cast<OGRILI1Layer **>(
663 115 : CPLRealloc(papoLayers, sizeof(void *) * nLayers));
664 :
665 115 : papoLayers[nLayers - 1] = poNewLayer;
666 115 : }
667 :
668 : /************************************************************************/
669 : /* GetLayer() */
670 : /************************************************************************/
671 :
672 23 : OGRILI1Layer *ILI1Reader::GetLayer(int iLayer)
673 :
674 : {
675 23 : if (iLayer < 0 || iLayer >= nLayers)
676 0 : return nullptr;
677 :
678 23 : return papoLayers[iLayer];
679 : }
680 :
681 152 : OGRILI1Layer *ILI1Reader::GetLayerByName(const char *pszLayerName)
682 :
683 : {
684 347 : for (int iLayer = 0; iLayer < nLayers; iLayer++)
685 : {
686 269 : if (EQUAL(pszLayerName, papoLayers[iLayer]->GetLayerDefn()->GetName()))
687 74 : return papoLayers[iLayer];
688 : }
689 78 : return nullptr;
690 : }
691 :
692 : /************************************************************************/
693 : /* GetLayerCount() */
694 : /************************************************************************/
695 :
696 64 : int ILI1Reader::GetLayerCount()
697 :
698 : {
699 64 : return nLayers;
700 : }
701 :
702 : /************************************************************************/
703 : /* Read one logical line, and return split into fields. The return */
704 : /* result is a stringlist, in the sense of the CSL functions. */
705 : /************************************************************************/
706 :
707 1630 : char **ILI1Reader::ReadParseLine()
708 : {
709 1630 : CPLAssert(fpItf != nullptr);
710 1630 : if (fpItf == nullptr)
711 0 : return nullptr;
712 :
713 1630 : const char *pszLine = CPLReadLineL(fpItf);
714 1630 : if (pszLine == nullptr)
715 0 : return nullptr;
716 :
717 1630 : if (strlen(pszLine) == 0)
718 0 : return nullptr;
719 :
720 1630 : char **tokens = CSLTokenizeString2(pszLine, " ", CSLT_PRESERVEESCAPES);
721 1630 : int nCount = CSLCount(tokens);
722 1630 : if (nCount == 0)
723 : {
724 0 : CSLDestroy(tokens);
725 0 : return nullptr;
726 : }
727 1630 : const char *token = tokens[nCount - 1];
728 :
729 : // Append CONT lines
730 1634 : while (strlen(pszLine) && token[0] == codeContinue && token[1] == '\0')
731 : {
732 : // remove last token
733 4 : CPLFree(tokens[CSLCount(tokens) - 1]);
734 4 : tokens[CSLCount(tokens) - 1] = nullptr;
735 :
736 4 : pszLine = CPLReadLineL(fpItf);
737 4 : if (pszLine == nullptr)
738 : {
739 0 : break;
740 : }
741 4 : char **conttok = CSLTokenizeString2(pszLine, " ", CSLT_PRESERVEESCAPES);
742 4 : if (!conttok || conttok[0] == nullptr || !EQUAL(conttok[0], "CONT") ||
743 4 : conttok[1] == nullptr)
744 : {
745 0 : CSLDestroy(conttok);
746 0 : break;
747 : }
748 :
749 : // append
750 4 : tokens = CSLInsertStrings(tokens, -1, &conttok[1]);
751 4 : token = tokens[CSLCount(tokens) - 1];
752 :
753 4 : CSLDestroy(conttok);
754 : }
755 1630 : if (tokens[0] == nullptr)
756 : {
757 0 : CSLDestroy(tokens);
758 0 : tokens = nullptr;
759 : }
760 1630 : return tokens;
761 : }
762 :
763 48 : IILI1Reader *CreateILI1Reader()
764 : {
765 48 : return new ILI1Reader();
766 : }
767 :
768 130 : void DestroyILI1Reader(IILI1Reader *reader)
769 : {
770 130 : if (reader)
771 48 : delete reader;
772 130 : }
|