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