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 13 : IILI1Reader::~IILI1Reader()
39 : {
40 13 : }
41 :
42 13 : ILI1Reader::ILI1Reader()
43 : : fpItf(nullptr), nLayers(0), papoLayers(nullptr), curLayer(nullptr),
44 13 : codeBlank('_'), codeUndefined('@'), codeContinue('\\')
45 : {
46 13 : }
47 :
48 26 : ILI1Reader::~ILI1Reader()
49 : {
50 13 : if (fpItf)
51 13 : VSIFCloseL(fpItf);
52 :
53 59 : for (int i = 0; i < nLayers; i++)
54 46 : delete papoLayers[i];
55 13 : CPLFree(papoLayers);
56 26 : }
57 :
58 : /* -------------------------------------------------------------------- */
59 : /* Open the source file. */
60 : /* -------------------------------------------------------------------- */
61 13 : int ILI1Reader::OpenFile(const char *pszFilename)
62 : {
63 13 : fpItf = VSIFOpenL(pszFilename, "r");
64 13 : 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 13 : return TRUE;
72 : }
73 :
74 39 : const char *ILI1Reader::GetLayerNameString(const char *topicname,
75 : const char *tablename)
76 : {
77 :
78 39 : return CPLSPrintf("%s__%s", topicname, tablename);
79 : }
80 :
81 13 : int ILI1Reader::ReadModel(ImdReader *poImdReader, const char *pszModelFilename,
82 : OGRILI1DataSource *poDS)
83 : {
84 :
85 13 : poImdReader->ReadModel(pszModelFilename);
86 32 : for (FeatureDefnInfos::const_iterator it =
87 13 : poImdReader->featureDefnInfos.begin();
88 77 : 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 32 : new OGRILI1Layer(it->GetTableDefnRef(), it->poGeomFieldInfos, poDS);
96 32 : AddLayer(layer);
97 : // Create additional layers for surface and area geometries.
98 52 : for (GeomFieldInfos::const_iterator it2 = it->poGeomFieldInfos.begin();
99 72 : it2 != it->poGeomFieldInfos.end(); ++it2)
100 : {
101 20 : if (it2->second.GetGeomTableDefnRef())
102 : {
103 : OGRFeatureDefn *poGeomTableDefn =
104 14 : it2->second.GetGeomTableDefnRef();
105 : OGRGeomFieldDefn *poOGRGeomFieldDefn =
106 14 : poGeomTableDefn->GetGeomFieldDefn(0);
107 28 : GeomFieldInfos oGeomFieldInfos;
108 : // We add iliGeomType to recognize Ili1 geom tables
109 28 : oGeomFieldInfos[poOGRGeomFieldDefn->GetNameRef()].iliGeomType =
110 28 : 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 14 : new OGRILI1Layer(poGeomTableDefn, oGeomFieldInfos, poDS);
118 14 : AddLayer(geomlayer);
119 : }
120 : }
121 : }
122 :
123 13 : codeBlank = poImdReader->codeBlank;
124 13 : CPLDebug("OGR_ILI", "Ili1Format blankCode '%c'", poImdReader->codeBlank);
125 13 : codeUndefined = poImdReader->codeUndefined;
126 13 : CPLDebug("OGR_ILI", "Ili1Format undefinedCode '%c'",
127 13 : poImdReader->codeUndefined);
128 13 : codeContinue = poImdReader->codeContinue;
129 13 : CPLDebug("OGR_ILI", "Ili1Format continueCode '%c'",
130 13 : poImdReader->codeContinue);
131 13 : return 0;
132 : }
133 :
134 13 : int ILI1Reader::ReadFeatures()
135 : {
136 13 : char **tokens = nullptr;
137 13 : const char *pszLine = nullptr;
138 13 : char *topic = CPLStrdup("(null)");
139 13 : int ret = TRUE;
140 :
141 130 : while (ret && (tokens = ReadParseLine()) != nullptr)
142 : {
143 130 : const char *firsttok = tokens[0];
144 130 : if (EQUAL(firsttok, "SCNT"))
145 : {
146 : // read description
147 10 : do
148 : {
149 23 : pszLine = CPLReadLineL(fpItf);
150 23 : } while (pszLine && !STARTS_WITH_CI(pszLine, "////"));
151 13 : ret = (pszLine != nullptr);
152 : }
153 117 : 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 117 : else if (EQUAL(firsttok, "MTID"))
163 : {
164 : }
165 104 : else if (EQUAL(firsttok, "MODL"))
166 : {
167 : }
168 91 : else if (EQUAL(firsttok, "TOPI") && CSLCount(tokens) >= 2)
169 : {
170 13 : CPLFree(topic);
171 13 : topic = CPLStrdup(CSLGetField(tokens, 1));
172 : }
173 78 : else if (EQUAL(firsttok, "TABL") && CSLCount(tokens) >= 2)
174 : {
175 : const char *layername =
176 39 : GetLayerNameString(topic, CSLGetField(tokens, 1));
177 39 : CPLDebug("OGR_ILI", "Reading table '%s'", layername);
178 39 : curLayer = GetLayerByName(layername);
179 :
180 39 : if (curLayer == nullptr)
181 : { // create one
182 0 : 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 0 : GetLayerNameString(topic, CSLGetField(tokens, 1)));
188 0 : poFeatureDefn->SetGeomType(wkbUnknown);
189 0 : GeomFieldInfos oGeomFieldInfos;
190 0 : curLayer =
191 0 : new OGRILI1Layer(poFeatureDefn, oGeomFieldInfos, nullptr);
192 0 : AddLayer(curLayer);
193 : }
194 39 : if (curLayer != nullptr)
195 : {
196 173 : for (int i = 0; i < curLayer->GetLayerDefn()->GetFieldCount();
197 : i++)
198 : {
199 134 : CPLDebug("OGR_ILI", "Field %d: %s", i,
200 134 : curLayer->GetLayerDefn()
201 134 : ->GetFieldDefn(i)
202 : ->GetNameRef());
203 : }
204 : }
205 39 : ret = ReadTable(layername);
206 : }
207 39 : else if (EQUAL(firsttok, "ETOP"))
208 : {
209 : }
210 26 : else if (EQUAL(firsttok, "EMOD"))
211 : {
212 : }
213 13 : else if (EQUAL(firsttok, "ENDE"))
214 : {
215 13 : CSLDestroy(tokens);
216 13 : CPLFree(topic);
217 13 : return TRUE;
218 : }
219 : else
220 : {
221 0 : CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
222 : firsttok);
223 : }
224 :
225 117 : CSLDestroy(tokens);
226 117 : tokens = nullptr;
227 : }
228 :
229 0 : CSLDestroy(tokens);
230 0 : CPLFree(topic);
231 :
232 0 : return ret;
233 : }
234 :
235 39 : int ILI1Reader::ReadTable(CPL_UNUSED const char *layername)
236 : {
237 39 : char **tokens = nullptr;
238 39 : int warned = FALSE;
239 39 : int geomIdx = -1;
240 :
241 39 : OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
242 39 : OGRFeature *feature = nullptr;
243 39 : bool bFeatureAdded = false;
244 :
245 195 : while ((tokens = ReadParseLine()) != nullptr)
246 : {
247 195 : const char *firsttok = CSLGetField(tokens, 0);
248 195 : if (EQUAL(firsttok, "OBJE"))
249 : {
250 100 : if (featureDef->GetFieldCount() == 0 &&
251 0 : curLayer->GetFeatureCount() == 0)
252 : {
253 0 : CPLError(CE_Warning, CPLE_AppDefined,
254 : "No field definition found for table: %s",
255 0 : featureDef->GetName());
256 : // Model not read - use heuristics.
257 0 : for (int fIndex = 1; tokens[fIndex] != nullptr; fIndex++)
258 : {
259 : char szFieldName[32];
260 0 : snprintf(szFieldName, sizeof(szFieldName), "Field%02d",
261 : fIndex);
262 0 : OGRFieldDefn oFieldDefn(szFieldName, OFTString);
263 0 : featureDef->AddFieldDefn(&oFieldDefn);
264 : }
265 : }
266 : // start new feature
267 100 : if (!bFeatureAdded)
268 39 : delete feature;
269 100 : feature = new OGRFeature(featureDef);
270 :
271 421 : for (int fIndex = 1, fieldno = 0;
272 748 : tokens[fIndex] != nullptr &&
273 327 : fieldno < featureDef->GetFieldCount();
274 : fIndex++, fieldno++)
275 : {
276 321 : if (!(tokens[fIndex][0] == codeUndefined &&
277 3 : 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 318 : if (featureDef->GetFieldDefn(fieldno)->GetType() ==
286 : OFTString)
287 : {
288 : // Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode
289 : // to UTF-8
290 308 : char *pszRecoded = CPLRecode(
291 154 : tokens[fIndex], CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
292 : // Replace space marks
293 807 : for (char *pszString = pszRecoded; *pszString != '\0';
294 : pszString++)
295 : {
296 653 : if (*pszString == codeBlank)
297 25 : *pszString = ' ';
298 : }
299 154 : feature->SetField(fieldno, pszRecoded);
300 154 : CPLFree(pszRecoded);
301 : }
302 : else
303 : {
304 164 : feature->SetField(fieldno, tokens[fIndex]);
305 : }
306 318 : if (featureDef->GetFieldDefn(fieldno)->GetType() ==
307 149 : OFTReal &&
308 467 : fieldno > 0 &&
309 149 : 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 206 : featureDef->GetFieldDefn(fieldno)->GetNameRef();
318 : // Check if name ends with _1.
319 206 : if (geomfldname.size() >= 2 &&
320 103 : geomfldname[geomfldname.size() - 2] == '_')
321 : {
322 : geomfldname =
323 26 : geomfldname.substr(0, geomfldname.size() - 2);
324 26 : geomIdx = featureDef->GetGeomFieldIndex(
325 26 : geomfldname.c_str());
326 26 : 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 103 : if (geomIdx >= 0)
340 : {
341 52 : if (featureDef->GetGeomFieldDefn(geomIdx)
342 26 : ->GetType() == wkbPoint)
343 : {
344 : // Add Point geometry.
345 : OGRPoint *ogrPoint =
346 23 : new OGRPoint(CPLAtof(tokens[fIndex - 1]),
347 23 : CPLAtof(tokens[fIndex]));
348 23 : 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 100 : if (!warned && featureDef->GetFieldCount() != CSLCount(tokens) - 1)
370 : {
371 2 : CPLError(CE_Warning, CPLE_AppDefined,
372 : "Field count of table %s doesn't match. %d declared, "
373 : "%d found (e.g. ignored LINEATTR)",
374 2 : featureDef->GetName(), featureDef->GetFieldCount(),
375 2 : CSLCount(tokens) - 1);
376 2 : warned = TRUE;
377 : }
378 100 : if (feature->GetFieldCount() > 0)
379 : {
380 : // USE _TID as FID. TODO: respect IDENT field from model.
381 100 : feature->SetFID(feature->GetFieldAsInteger64(0));
382 : }
383 100 : curLayer->AddFeature(feature);
384 100 : bFeatureAdded = true;
385 100 : geomIdx = -1; // Reset
386 : }
387 95 : else if (EQUAL(firsttok, "STPT") && feature != nullptr)
388 : {
389 : // Find next non-Point geometry
390 55 : if (geomIdx < 0)
391 55 : geomIdx = 0;
392 110 : while (geomIdx < featureDef->GetGeomFieldCount() &&
393 55 : featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint)
394 : {
395 0 : geomIdx++;
396 : }
397 : OGRwkbGeometryType geomType =
398 55 : (geomIdx < featureDef->GetGeomFieldCount())
399 55 : ? featureDef->GetGeomFieldDefn(geomIdx)->GetType()
400 55 : : wkbNone;
401 55 : if (CSLCount(tokens) >= 3)
402 55 : ReadGeom(tokens, geomIdx, geomType, feature);
403 : }
404 40 : else if (EQUAL(firsttok, "ELIN"))
405 : {
406 : // Empty geom.
407 : }
408 39 : 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 39 : else if (EQUAL(firsttok, "PERI"))
423 : {
424 : }
425 39 : else if (EQUAL(firsttok, "ETAB"))
426 : {
427 39 : CPLDebug("OGR_ILI", "Total features: " CPL_FRMT_GIB,
428 39 : curLayer->GetFeatureCount());
429 39 : CSLDestroy(tokens);
430 39 : if (!bFeatureAdded)
431 0 : delete feature;
432 39 : return TRUE;
433 : }
434 : else
435 : {
436 0 : CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s",
437 : firsttok);
438 : }
439 :
440 156 : CSLDestroy(tokens);
441 : }
442 :
443 0 : if (!bFeatureAdded)
444 0 : delete feature;
445 :
446 0 : return TRUE;
447 : }
448 :
449 55 : 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 55 : if (eType == wkbNone)
457 : {
458 0 : CPLError(CE_Warning, CPLE_AppDefined,
459 : "Calling ILI1Reader::ReadGeom with wkbNone");
460 : }
461 :
462 : // Initialize geometry.
463 :
464 55 : OGRCompoundCurve *ogrCurve = new OGRCompoundCurve();
465 55 : OGRCurvePolygon *ogrPoly = nullptr; // current polygon
466 55 : OGRMultiCurve *ogrMultiLine = nullptr; // current multi line
467 :
468 55 : if (eType == wkbMultiCurve || eType == wkbMultiLineString)
469 : {
470 55 : ogrMultiLine = new OGRMultiCurve();
471 : }
472 0 : else if (eType == wkbPolygon || eType == wkbCurvePolygon)
473 : {
474 0 : ogrPoly = new OGRCurvePolygon();
475 : }
476 :
477 110 : OGRPoint ogrPoint; // Current point.
478 55 : ogrPoint.setX(CPLAtof(stgeom[1]));
479 55 : ogrPoint.setY(CPLAtof(stgeom[2]));
480 :
481 55 : OGRLineString *ogrLine = new OGRLineString();
482 55 : ogrLine->addPoint(&ogrPoint);
483 :
484 : // Parse geometry.
485 :
486 55 : char **tokens = nullptr;
487 55 : bool end = false;
488 55 : OGRCircularString *arc = nullptr; // current arc
489 :
490 422 : while (!end && (tokens = ReadParseLine()) != nullptr)
491 : {
492 367 : const char *firsttok = CSLGetField(tokens, 0);
493 367 : if (firsttok == nullptr)
494 : {
495 : // do nothing
496 : }
497 367 : else if (EQUAL(firsttok, "LIPT") && CSLCount(tokens) >= 3)
498 : {
499 292 : ogrPoint.setX(CPLAtof(tokens[1]));
500 292 : ogrPoint.setY(CPLAtof(tokens[2]));
501 292 : if (arc)
502 : {
503 20 : arc->addPoint(&ogrPoint);
504 20 : OGRErr error = ogrCurve->addCurveDirectly(arc);
505 20 : 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 20 : arc = nullptr;
515 : }
516 292 : ogrLine->addPoint(&ogrPoint);
517 : }
518 75 : else if (EQUAL(firsttok, "ARCP") && CSLCount(tokens) >= 3)
519 : {
520 : // Finish line and start arc
521 20 : if (ogrLine->getNumPoints() > 1)
522 : {
523 9 : OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
524 9 : 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 9 : ogrLine = new OGRLineString();
534 : }
535 : else
536 : {
537 11 : ogrLine->empty();
538 : }
539 20 : delete arc;
540 20 : arc = new OGRCircularString();
541 20 : arc->addPoint(&ogrPoint);
542 20 : ogrPoint.setX(CPLAtof(tokens[1]));
543 20 : ogrPoint.setY(CPLAtof(tokens[2]));
544 20 : arc->addPoint(&ogrPoint);
545 : }
546 55 : else if (EQUAL(firsttok, "ELIN"))
547 : {
548 55 : if (ogrLine->getNumPoints() > 1)
549 : { // Ignore single LIPT after ARCP
550 55 : OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
551 55 : 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 55 : ogrLine = nullptr;
561 : }
562 55 : if (!ogrCurve->IsEmpty())
563 : {
564 55 : if (ogrMultiLine)
565 : {
566 55 : OGRErr error = ogrMultiLine->addGeometryDirectly(ogrCurve);
567 55 : 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 55 : ogrCurve = nullptr;
577 : }
578 55 : 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 55 : 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 367 : CSLDestroy(tokens);
618 : }
619 55 : delete arc;
620 :
621 55 : delete ogrLine;
622 :
623 : // Set feature geometry
624 55 : if (eType == wkbMultiCurve)
625 : {
626 37 : feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine);
627 37 : delete ogrCurve;
628 : }
629 18 : else if (eType == wkbMultiLineString)
630 : {
631 18 : feature->SetGeomFieldDirectly(geomIdx,
632 18 : ogrMultiLine->getLinearGeometry());
633 18 : delete ogrMultiLine;
634 18 : delete ogrCurve;
635 : }
636 0 : else if (eType == wkbCurvePolygon)
637 : {
638 0 : feature->SetGeomFieldDirectly(geomIdx, ogrPoly);
639 0 : delete ogrCurve;
640 : }
641 0 : 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 0 : feature->SetGeomFieldDirectly(geomIdx, ogrCurve);
650 : }
651 55 : }
652 :
653 : /************************************************************************/
654 : /* AddLayer() */
655 : /************************************************************************/
656 :
657 46 : void ILI1Reader::AddLayer(OGRILI1Layer *poNewLayer)
658 :
659 : {
660 46 : nLayers++;
661 :
662 46 : papoLayers = static_cast<OGRILI1Layer **>(
663 46 : CPLRealloc(papoLayers, sizeof(void *) * nLayers));
664 :
665 46 : papoLayers[nLayers - 1] = poNewLayer;
666 46 : }
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 65 : OGRILI1Layer *ILI1Reader::GetLayerByName(const char *pszLayerName)
682 :
683 : {
684 196 : for (int iLayer = 0; iLayer < nLayers; iLayer++)
685 : {
686 196 : if (EQUAL(pszLayerName, papoLayers[iLayer]->GetLayerDefn()->GetName()))
687 65 : return papoLayers[iLayer];
688 : }
689 0 : return nullptr;
690 : }
691 :
692 : /************************************************************************/
693 : /* GetLayerCount() */
694 : /************************************************************************/
695 :
696 29 : int ILI1Reader::GetLayerCount()
697 :
698 : {
699 29 : 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 692 : char **ILI1Reader::ReadParseLine()
708 : {
709 692 : CPLAssert(fpItf != nullptr);
710 692 : if (fpItf == nullptr)
711 0 : return nullptr;
712 :
713 692 : const char *pszLine = CPLReadLineL(fpItf);
714 692 : if (pszLine == nullptr)
715 0 : return nullptr;
716 :
717 692 : if (strlen(pszLine) == 0)
718 0 : return nullptr;
719 :
720 692 : char **tokens = CSLTokenizeString2(pszLine, " ", CSLT_PRESERVEESCAPES);
721 692 : int nCount = CSLCount(tokens);
722 692 : if (nCount == 0)
723 : {
724 0 : CSLDestroy(tokens);
725 0 : return nullptr;
726 : }
727 692 : const char *token = tokens[nCount - 1];
728 :
729 : // Append CONT lines
730 694 : while (strlen(pszLine) && token[0] == codeContinue && token[1] == '\0')
731 : {
732 : // remove last token
733 2 : CPLFree(tokens[CSLCount(tokens) - 1]);
734 2 : tokens[CSLCount(tokens) - 1] = nullptr;
735 :
736 2 : pszLine = CPLReadLineL(fpItf);
737 2 : if (pszLine == nullptr)
738 : {
739 0 : break;
740 : }
741 2 : char **conttok = CSLTokenizeString2(pszLine, " ", CSLT_PRESERVEESCAPES);
742 2 : if (!conttok || conttok[0] == nullptr || !EQUAL(conttok[0], "CONT") ||
743 2 : conttok[1] == nullptr)
744 : {
745 0 : CSLDestroy(conttok);
746 0 : break;
747 : }
748 :
749 : // append
750 2 : tokens = CSLInsertStrings(tokens, -1, &conttok[1]);
751 2 : token = tokens[CSLCount(tokens) - 1];
752 :
753 2 : CSLDestroy(conttok);
754 : }
755 692 : if (tokens[0] == nullptr)
756 : {
757 0 : CSLDestroy(tokens);
758 0 : tokens = nullptr;
759 : }
760 692 : return tokens;
761 : }
762 :
763 13 : IILI1Reader *CreateILI1Reader()
764 : {
765 13 : return new ILI1Reader();
766 : }
767 :
768 67 : void DestroyILI1Reader(IILI1Reader *reader)
769 : {
770 67 : if (reader)
771 13 : delete reader;
772 67 : }
|