Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: NTF Translator
4 : * Purpose: NTFFileReader methods related to establishing the schemas
5 : * of features that could occur in this product and the functions
6 : * for actually performing the NTFRecord to OGRFeature conversion.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Frank Warmerdam
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #include <stdarg.h>
16 : #include "ntf.h"
17 : #include "cpl_string.h"
18 :
19 : /************************************************************************/
20 : /* TranslateCodePoint() */
21 : /* */
22 : /* Used for code point, and code point plus. */
23 : /************************************************************************/
24 :
25 0 : static OGRFeature *TranslateCodePoint(NTFFileReader *poReader,
26 : OGRNTFLayer *poLayer,
27 : NTFRecord **papoGroup)
28 :
29 : {
30 0 : if (CSLCount((char **)papoGroup) < 2 ||
31 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
32 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
33 0 : return nullptr;
34 :
35 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
36 :
37 : // POINT_ID
38 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
39 :
40 : // Geometry
41 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
42 :
43 : // Attributes
44 0 : if (EQUAL(poLayer->GetLayerDefn()->GetName(), "CODE_POINT"))
45 0 : poReader->ApplyAttributeValues(
46 : poFeature, papoGroup, "PC", 1, "PQ", 2, "PR", 3, "TP", 4, "DQ", 5,
47 : "RP", 6, "BP", 7, "PD", 8, "MP", 9, "UM", 10, "RV", 11, NULL);
48 : else
49 0 : poReader->ApplyAttributeValues(
50 : poFeature, papoGroup, "PC", 1, "PQ", 2, "PR", 3, "TP", 4, "DQ", 5,
51 : "RP", 6, "BP", 7, "PD", 8, "MP", 9, "UM", 10, "RV", 11, "RH", 12,
52 : "LH", 13, "CC", 14, "DC", 15, "WC", 16, NULL);
53 :
54 0 : return poFeature;
55 : }
56 :
57 : /************************************************************************/
58 : /* TranslateAddressPoint() */
59 : /************************************************************************/
60 :
61 0 : static OGRFeature *TranslateAddressPoint(NTFFileReader *poReader,
62 : OGRNTFLayer *poLayer,
63 : NTFRecord **papoGroup)
64 :
65 : {
66 0 : if (CSLCount((char **)papoGroup) < 2 ||
67 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
68 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
69 0 : return nullptr;
70 :
71 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
72 :
73 : // POINT_ID
74 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
75 :
76 : // CHG_TYPE
77 0 : poFeature->SetField(17, papoGroup[0]->GetField(22, 22));
78 :
79 : // CHG_DATE
80 0 : poFeature->SetField(18, papoGroup[0]->GetField(23, 28));
81 :
82 : // Geometry
83 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
84 :
85 : // Attributes
86 0 : poReader->ApplyAttributeValues(
87 : poFeature, papoGroup, "OA", 1, "ON", 2, "DP", 3, "PB", 4, "SB", 5, "BD",
88 : 6, "BN", 7, "DR", 8, "TN", 9, "DD", 10, "DL", 11, "PT", 12, "CN", 13,
89 : "PC", 14, "SF", 15, "RV", 16, NULL);
90 :
91 0 : return poFeature;
92 : }
93 :
94 : /************************************************************************/
95 : /* TranslateOscarPoint() */
96 : /* */
97 : /* Used for OSCAR Traffic and Asset datasets. */
98 : /************************************************************************/
99 :
100 0 : static OGRFeature *TranslateOscarPoint(NTFFileReader *poReader,
101 : OGRNTFLayer *poLayer,
102 : NTFRecord **papoGroup)
103 :
104 : {
105 0 : if (CSLCount((char **)papoGroup) < 2 ||
106 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
107 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
108 0 : return nullptr;
109 :
110 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
111 :
112 : // POINT_ID
113 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
114 :
115 : // Geometry
116 0 : int nGeomId = 0;
117 :
118 0 : poFeature->SetGeometryDirectly(
119 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
120 :
121 0 : poFeature->SetField(1, nGeomId);
122 :
123 : // Attributes
124 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "JN",
125 : 4, "SN", 5, NULL);
126 :
127 0 : return poFeature;
128 : }
129 :
130 : /************************************************************************/
131 : /* TranslateOscarLine() */
132 : /************************************************************************/
133 :
134 0 : static OGRFeature *TranslateOscarLine(NTFFileReader *poReader,
135 : OGRNTFLayer *poLayer,
136 : NTFRecord **papoGroup)
137 :
138 : {
139 0 : if (CSLCount((char **)papoGroup) < 2 ||
140 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
141 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
142 0 : return nullptr;
143 :
144 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
145 :
146 : // LINE_ID
147 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
148 :
149 : // Geometry
150 0 : int nGeomId = 0;
151 :
152 0 : poFeature->SetGeometryDirectly(
153 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
154 :
155 0 : poFeature->SetField(1, nGeomId);
156 :
157 : // Attributes
158 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "PN",
159 : 4, "LL", 5, "SC", 6, "FW", 7, "RN", 8, "TR",
160 : 9, NULL);
161 :
162 0 : return poFeature;
163 : }
164 :
165 : /************************************************************************/
166 : /* TranslateOscarRoutePoint() */
167 : /************************************************************************/
168 :
169 0 : static OGRFeature *TranslateOscarRoutePoint(NTFFileReader *poReader,
170 : OGRNTFLayer *poLayer,
171 : NTFRecord **papoGroup)
172 :
173 : {
174 0 : if (CSLCount((char **)papoGroup) < 2 ||
175 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
176 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
177 0 : return nullptr;
178 :
179 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
180 :
181 : // POINT_ID
182 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
183 :
184 : // Geometry
185 0 : int nGeomId = 0;
186 :
187 0 : poFeature->SetGeometryDirectly(
188 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
189 :
190 0 : poFeature->SetField(1, nGeomId);
191 :
192 : // Attributes
193 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "JN",
194 : 4, "SN", 5, "NP", 6, "RT", 8, NULL);
195 :
196 : // PARENT_OSODR
197 : char **papszTypes, **papszValues;
198 :
199 0 : if (poReader->ProcessAttRecGroup(papoGroup, &papszTypes, &papszValues))
200 : {
201 0 : char **papszOSODRList = nullptr;
202 :
203 0 : for (int i = 0; papszTypes != nullptr && papszTypes[i] != nullptr; i++)
204 : {
205 0 : if (EQUAL(papszTypes[i], "PO"))
206 0 : papszOSODRList = CSLAddString(papszOSODRList, papszValues[i]);
207 : }
208 :
209 0 : poFeature->SetField(7, papszOSODRList);
210 0 : CPLAssert(CSLCount(papszOSODRList) == poFeature->GetFieldAsInteger(6));
211 :
212 0 : CSLDestroy(papszOSODRList);
213 0 : CSLDestroy(papszTypes);
214 0 : CSLDestroy(papszValues);
215 : }
216 :
217 0 : return poFeature;
218 : }
219 :
220 : /************************************************************************/
221 : /* TranslateOscarRouteLine() */
222 : /************************************************************************/
223 :
224 0 : static OGRFeature *TranslateOscarRouteLine(NTFFileReader *poReader,
225 : OGRNTFLayer *poLayer,
226 : NTFRecord **papoGroup)
227 :
228 : {
229 0 : if (CSLCount((char **)papoGroup) < 2 ||
230 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
231 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
232 0 : return nullptr;
233 :
234 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
235 :
236 : // LINE_ID
237 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
238 :
239 : // Geometry
240 0 : int nGeomId = 0;
241 :
242 0 : poFeature->SetGeometryDirectly(
243 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
244 :
245 0 : poFeature->SetField(1, nGeomId);
246 :
247 : // Attributes
248 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "PN",
249 : 4, "LL", 5, "RN", 6, "TR", 7, "NP", 8, NULL);
250 :
251 : // PARENT_OSODR
252 : char **papszTypes, **papszValues;
253 :
254 0 : if (poReader->ProcessAttRecGroup(papoGroup, &papszTypes, &papszValues))
255 : {
256 0 : char **papszOSODRList = nullptr;
257 :
258 0 : for (int i = 0; papszTypes != nullptr && papszTypes[i] != nullptr; i++)
259 : {
260 0 : if (EQUAL(papszTypes[i], "PO"))
261 0 : papszOSODRList = CSLAddString(papszOSODRList, papszValues[i]);
262 : }
263 :
264 0 : poFeature->SetField(9, papszOSODRList);
265 0 : CPLAssert(CSLCount(papszOSODRList) == poFeature->GetFieldAsInteger(8));
266 :
267 0 : CSLDestroy(papszOSODRList);
268 0 : CSLDestroy(papszTypes);
269 0 : CSLDestroy(papszValues);
270 : }
271 :
272 0 : return poFeature;
273 : }
274 :
275 : /************************************************************************/
276 : /* TranslateOscarComment() */
277 : /************************************************************************/
278 :
279 0 : static OGRFeature *TranslateOscarComment(CPL_UNUSED NTFFileReader *poReader,
280 : OGRNTFLayer *poLayer,
281 : NTFRecord **papoGroup)
282 :
283 : {
284 0 : if (CSLCount((char **)papoGroup) != 1 ||
285 0 : papoGroup[0]->GetType() != NRT_COMMENT)
286 0 : return nullptr;
287 :
288 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
289 :
290 : // RECORD_TYPE
291 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 4)));
292 :
293 : // RECORD_ID
294 0 : poFeature->SetField(1, papoGroup[0]->GetField(5, 17));
295 :
296 : // CHANGE_TYPE
297 0 : poFeature->SetField(2, papoGroup[0]->GetField(18, 18));
298 :
299 0 : return poFeature;
300 : }
301 :
302 : /************************************************************************/
303 : /* TranslateOscarNetworkPoint() */
304 : /************************************************************************/
305 :
306 0 : static OGRFeature *TranslateOscarNetworkPoint(NTFFileReader *poReader,
307 : OGRNTFLayer *poLayer,
308 : NTFRecord **papoGroup)
309 :
310 : {
311 0 : if (CSLCount((char **)papoGroup) < 2 ||
312 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
313 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
314 0 : return nullptr;
315 :
316 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
317 :
318 : // POINT_ID
319 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
320 :
321 : // Geometry
322 0 : int nGeomId = 0;
323 :
324 0 : poFeature->SetGeometryDirectly(
325 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
326 :
327 0 : poFeature->SetField(1, nGeomId);
328 :
329 : // Attributes
330 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "JN",
331 : 4, "SN", 5, "RT", 6, NULL);
332 :
333 0 : return poFeature;
334 : }
335 :
336 : /************************************************************************/
337 : /* TranslateOscarNetworkLine() */
338 : /************************************************************************/
339 :
340 0 : static OGRFeature *TranslateOscarNetworkLine(NTFFileReader *poReader,
341 : OGRNTFLayer *poLayer,
342 : NTFRecord **papoGroup)
343 :
344 : {
345 0 : if (CSLCount((char **)papoGroup) < 2 ||
346 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
347 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
348 0 : return nullptr;
349 :
350 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
351 :
352 : // LINE_ID
353 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
354 :
355 : // Geometry
356 0 : int nGeomId = 0;
357 :
358 0 : poFeature->SetGeometryDirectly(
359 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
360 :
361 0 : poFeature->SetField(1, nGeomId);
362 :
363 : // Attributes
364 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "PN",
365 : 4, "LL", 5, "RN", 6, NULL);
366 :
367 0 : return poFeature;
368 : }
369 :
370 : /************************************************************************/
371 : /* TranslateBasedataPoint() */
372 : /************************************************************************/
373 :
374 0 : static OGRFeature *TranslateBasedataPoint(NTFFileReader *poReader,
375 : OGRNTFLayer *poLayer,
376 : NTFRecord **papoGroup)
377 :
378 : {
379 0 : if (CSLCount((char **)papoGroup) < 2 ||
380 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
381 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
382 0 : return nullptr;
383 :
384 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
385 :
386 : // POINT_ID
387 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
388 :
389 : // Geometry
390 0 : int nGeomId = 0;
391 :
392 0 : poFeature->SetGeometryDirectly(
393 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
394 :
395 : // GEOM_ID
396 0 : poFeature->SetField(1, nGeomId);
397 :
398 : // Attributes
399 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "PN", 3, "NU",
400 : 4, "CM", 5, "UN", 6, "OR", 7, NULL);
401 :
402 0 : return poFeature;
403 : }
404 :
405 : /************************************************************************/
406 : /* TranslateBasedataLine() */
407 : /************************************************************************/
408 :
409 0 : static OGRFeature *TranslateBasedataLine(NTFFileReader *poReader,
410 : OGRNTFLayer *poLayer,
411 : NTFRecord **papoGroup)
412 :
413 : {
414 0 : if (CSLCount((char **)papoGroup) < 2 ||
415 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
416 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
417 0 : return nullptr;
418 :
419 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
420 :
421 : // LINE_ID
422 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
423 :
424 : // Geometry
425 0 : int nGeomId = 0;
426 :
427 0 : poFeature->SetGeometryDirectly(
428 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
429 :
430 : // GEOM_ID
431 0 : poFeature->SetField(2, nGeomId);
432 :
433 : // Attributes
434 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PN", 3, "NU",
435 : 4, "RB", 5, NULL);
436 :
437 0 : return poFeature;
438 : }
439 :
440 : /************************************************************************/
441 : /* TranslateBoundarylineCollection() */
442 : /************************************************************************/
443 :
444 0 : static OGRFeature *TranslateBoundarylineCollection(NTFFileReader *poReader,
445 : OGRNTFLayer *poLayer,
446 : NTFRecord **papoGroup)
447 :
448 : {
449 0 : if (CSLCount((char **)papoGroup) != 2 ||
450 0 : papoGroup[0]->GetType() != NRT_COLLECT ||
451 0 : papoGroup[1]->GetType() != NRT_ATTREC)
452 0 : return nullptr;
453 :
454 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
455 :
456 : // COLL_ID
457 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
458 :
459 : // NUM_PARTS
460 0 : int nNumLinks = atoi(papoGroup[0]->GetField(9, 12));
461 :
462 0 : if (nNumLinks > MAX_LINK)
463 : {
464 0 : CPLError(CE_Failure, CPLE_AppDefined,
465 : "MAX_LINK exceeded in ntf_estlayers.cpp.");
466 0 : return poFeature;
467 : }
468 :
469 0 : poFeature->SetField(1, nNumLinks);
470 :
471 : // POLY_ID
472 0 : int i, anList[MAX_LINK] = {0};
473 :
474 0 : for (i = 0; i < nNumLinks; i++)
475 0 : anList[i] = atoi(papoGroup[0]->GetField(15 + i * 8, 20 + i * 8));
476 :
477 0 : poFeature->SetField(2, nNumLinks, anList);
478 :
479 : // Attributes
480 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "AI", 3, "OP", 4, "NM",
481 : 5, NULL);
482 :
483 0 : return poFeature;
484 : }
485 :
486 : /************************************************************************/
487 : /* TranslateBoundarylinePoly() */
488 : /************************************************************************/
489 :
490 0 : static OGRFeature *TranslateBoundarylinePoly(NTFFileReader *poReader,
491 : OGRNTFLayer *poLayer,
492 : NTFRecord **papoGroup)
493 :
494 : {
495 : /* ==================================================================== */
496 : /* Traditional POLYGON record groups. */
497 : /* ==================================================================== */
498 0 : if (CSLCount((char **)papoGroup) == 4 &&
499 0 : papoGroup[0]->GetType() == NRT_POLYGON &&
500 0 : papoGroup[1]->GetType() == NRT_ATTREC &&
501 0 : papoGroup[2]->GetType() == NRT_CHAIN &&
502 0 : papoGroup[3]->GetType() == NRT_GEOMETRY)
503 : {
504 :
505 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
506 :
507 : // POLY_ID
508 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
509 :
510 : // NUM_PARTS
511 0 : int nNumLinks = atoi(papoGroup[2]->GetField(9, 12));
512 :
513 0 : if (nNumLinks > MAX_LINK)
514 : {
515 0 : CPLError(CE_Failure, CPLE_AppDefined,
516 : "MAX_LINK exceeded in ntf_estlayers.cpp.");
517 0 : return poFeature;
518 : }
519 :
520 0 : poFeature->SetField(4, nNumLinks);
521 :
522 : // DIR
523 0 : int i, anList[MAX_LINK] = {0};
524 :
525 0 : for (i = 0; i < nNumLinks; i++)
526 0 : anList[i] = atoi(papoGroup[2]->GetField(19 + i * 7, 19 + i * 7));
527 :
528 0 : poFeature->SetField(5, nNumLinks, anList);
529 :
530 : // GEOM_ID_OF_LINK
531 0 : for (i = 0; i < nNumLinks; i++)
532 0 : anList[i] = atoi(papoGroup[2]->GetField(13 + i * 7, 18 + i * 7));
533 :
534 0 : poFeature->SetField(6, nNumLinks, anList);
535 :
536 : // RingStart
537 0 : int nRingList = 0;
538 0 : poFeature->SetField(7, 1, &nRingList);
539 :
540 : // Attributes
541 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PI", 2,
542 : "HA", 3, NULL);
543 :
544 : // Read point geometry
545 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[3]));
546 :
547 : // Try to assemble polygon geometry.
548 0 : poReader->FormPolygonFromCache(poFeature);
549 :
550 0 : return poFeature;
551 : }
552 :
553 : /* ==================================================================== */
554 : /* CPOLYGON Group */
555 : /* ==================================================================== */
556 :
557 : /* -------------------------------------------------------------------- */
558 : /* First we do validation of the grouping. */
559 : /* -------------------------------------------------------------------- */
560 0 : int iRec = 0; // Used after for.
561 :
562 0 : for (; papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr &&
563 0 : papoGroup[iRec]->GetType() == NRT_POLYGON &&
564 0 : papoGroup[iRec + 1]->GetType() == NRT_CHAIN;
565 0 : iRec += 2)
566 : {
567 : }
568 :
569 0 : if (CSLCount((char **)papoGroup) != iRec + 3)
570 0 : return nullptr;
571 :
572 0 : if (papoGroup[iRec]->GetType() != NRT_CPOLY ||
573 0 : papoGroup[iRec + 1]->GetType() != NRT_ATTREC ||
574 0 : papoGroup[iRec + 2]->GetType() != NRT_GEOMETRY)
575 0 : return nullptr;
576 :
577 : /* -------------------------------------------------------------------- */
578 : /* Collect the chains for each of the rings, and just aggregate */
579 : /* these into the master list without any concept of where the */
580 : /* boundaries are. The boundary information will be emitted */
581 : /* in the RingStart field. */
582 : /* -------------------------------------------------------------------- */
583 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
584 0 : int nNumLink = 0;
585 0 : int anDirList[MAX_LINK * 2] = {};
586 0 : int anGeomList[MAX_LINK * 2] = {};
587 0 : int anRingStart[MAX_LINK] = {};
588 0 : int nRings = 0;
589 :
590 0 : for (iRec = 0;
591 0 : papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr &&
592 0 : papoGroup[iRec]->GetType() == NRT_POLYGON &&
593 0 : papoGroup[iRec + 1]->GetType() == NRT_CHAIN;
594 0 : iRec += 2)
595 : {
596 0 : const int nLineCount = atoi(papoGroup[iRec + 1]->GetField(9, 12));
597 :
598 0 : anRingStart[nRings++] = nNumLink;
599 :
600 0 : for (int i = 0; i < nLineCount && nNumLink < MAX_LINK * 2; i++)
601 : {
602 0 : anDirList[nNumLink] =
603 0 : atoi(papoGroup[iRec + 1]->GetField(19 + i * 7, 19 + i * 7));
604 0 : anGeomList[nNumLink] =
605 0 : atoi(papoGroup[iRec + 1]->GetField(13 + i * 7, 18 + i * 7));
606 0 : nNumLink++;
607 : }
608 :
609 0 : if (nNumLink == MAX_LINK * 2)
610 : {
611 0 : CPLError(CE_Failure, CPLE_AppDefined,
612 : "MAX_LINK exceeded in ntf_estlayers.cpp.");
613 :
614 0 : delete poFeature;
615 0 : return nullptr;
616 : }
617 : }
618 :
619 : // NUM_PART
620 0 : poFeature->SetField(4, nNumLink);
621 :
622 : // DIR
623 0 : poFeature->SetField(5, nNumLink, anDirList);
624 :
625 : // GEOM_ID_OF_LINK
626 0 : poFeature->SetField(6, nNumLink, anGeomList);
627 :
628 : // RingStart
629 0 : poFeature->SetField(7, nRings, anRingStart);
630 :
631 : /* -------------------------------------------------------------------- */
632 : /* collect information for whole complex polygon. */
633 : /* -------------------------------------------------------------------- */
634 : // POLY_ID
635 0 : if (papoGroup[iRec] != nullptr)
636 0 : poFeature->SetField(0, atoi(papoGroup[iRec]->GetField(3, 8)));
637 :
638 : // Attributes
639 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PI", 2, "HA",
640 : 3, NULL);
641 :
642 : // point geometry for seed.
643 0 : poFeature->SetGeometryDirectly(
644 0 : poReader->ProcessGeometry(papoGroup[iRec + 2]));
645 :
646 : // Try to assemble polygon geometry.
647 0 : poReader->FormPolygonFromCache(poFeature);
648 :
649 0 : return poFeature;
650 : }
651 :
652 : /************************************************************************/
653 : /* TranslateBoundarylineLink() */
654 : /************************************************************************/
655 :
656 0 : static OGRFeature *TranslateBoundarylineLink(NTFFileReader *poReader,
657 : OGRNTFLayer *poLayer,
658 : NTFRecord **papoGroup)
659 :
660 : {
661 0 : if (CSLCount((char **)papoGroup) != 2 ||
662 0 : papoGroup[0]->GetType() != NRT_GEOMETRY ||
663 0 : papoGroup[1]->GetType() != NRT_ATTREC)
664 0 : return nullptr;
665 :
666 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
667 :
668 : // Geometry
669 0 : int nGeomId = 0;
670 :
671 0 : poFeature->SetGeometryDirectly(
672 : poReader->ProcessGeometry(papoGroup[0], &nGeomId));
673 :
674 : // GEOM_ID
675 0 : poFeature->SetField(0, nGeomId);
676 :
677 : // Attributes
678 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "LK", 2, "HW",
679 : 3, NULL);
680 :
681 0 : return poFeature;
682 : }
683 :
684 : /************************************************************************/
685 : /* TranslateBL2000Poly() */
686 : /************************************************************************/
687 :
688 0 : static OGRFeature *TranslateBL2000Poly(NTFFileReader *poReader,
689 : OGRNTFLayer *poLayer,
690 : NTFRecord **papoGroup)
691 :
692 : {
693 : /* ==================================================================== */
694 : /* Traditional POLYGON record groups. */
695 : /* ==================================================================== */
696 0 : if (CSLCount((char **)papoGroup) == 3 &&
697 0 : papoGroup[0]->GetType() == NRT_POLYGON &&
698 0 : papoGroup[1]->GetType() == NRT_ATTREC &&
699 0 : papoGroup[2]->GetType() == NRT_CHAIN)
700 : {
701 :
702 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
703 :
704 : // POLY_ID
705 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
706 :
707 : // NUM_PARTS
708 0 : int nNumLinks = atoi(papoGroup[2]->GetField(9, 12));
709 :
710 0 : if (nNumLinks > MAX_LINK)
711 : {
712 0 : CPLError(CE_Failure, CPLE_AppDefined,
713 : "MAX_LINK exceeded in ntf_estlayers.cpp.");
714 :
715 0 : return poFeature;
716 : }
717 :
718 0 : poFeature->SetField(3, nNumLinks);
719 :
720 : // DIR
721 0 : int i, anList[MAX_LINK] = {0};
722 :
723 0 : for (i = 0; i < nNumLinks; i++)
724 0 : anList[i] = atoi(papoGroup[2]->GetField(19 + i * 7, 19 + i * 7));
725 :
726 0 : poFeature->SetField(4, nNumLinks, anList);
727 :
728 : // GEOM_ID_OF_LINK
729 0 : for (i = 0; i < nNumLinks; i++)
730 0 : anList[i] = atoi(papoGroup[2]->GetField(13 + i * 7, 18 + i * 7));
731 :
732 0 : poFeature->SetField(5, nNumLinks, anList);
733 :
734 : // RingStart
735 0 : int nRingList = 0;
736 0 : poFeature->SetField(6, 1, &nRingList);
737 :
738 : // Attributes
739 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "PI", 1, "HA", 2,
740 : NULL);
741 :
742 : // Try to assemble polygon geometry.
743 0 : poReader->FormPolygonFromCache(poFeature);
744 :
745 0 : return poFeature;
746 : }
747 :
748 : /* ==================================================================== */
749 : /* CPOLYGON Group */
750 : /* ==================================================================== */
751 :
752 : /* -------------------------------------------------------------------- */
753 : /* First we do validation of the grouping. */
754 : /* -------------------------------------------------------------------- */
755 0 : int iRec = 0; // Used after for.
756 :
757 0 : for (; papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr &&
758 0 : papoGroup[iRec]->GetType() == NRT_POLYGON &&
759 0 : papoGroup[iRec + 1]->GetType() == NRT_CHAIN;
760 0 : iRec += 2)
761 : {
762 : }
763 :
764 0 : if (CSLCount((char **)papoGroup) != iRec + 2)
765 0 : return nullptr;
766 :
767 0 : if (papoGroup[iRec]->GetType() != NRT_CPOLY ||
768 0 : papoGroup[iRec + 1]->GetType() != NRT_ATTREC)
769 0 : return nullptr;
770 :
771 : /* -------------------------------------------------------------------- */
772 : /* Collect the chains for each of the rings, and just aggregate */
773 : /* these into the master list without any concept of where the */
774 : /* boundaries are. The boundary information will be emitted */
775 : /* in the RingStart field. */
776 : /* -------------------------------------------------------------------- */
777 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
778 0 : int nNumLink = 0;
779 0 : int anDirList[MAX_LINK * 2] = {};
780 0 : int anGeomList[MAX_LINK * 2] = {};
781 0 : int anRingStart[MAX_LINK] = {};
782 0 : int nRings = 0;
783 :
784 0 : for (iRec = 0;
785 0 : papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr &&
786 0 : papoGroup[iRec]->GetType() == NRT_POLYGON &&
787 0 : papoGroup[iRec + 1]->GetType() == NRT_CHAIN;
788 0 : iRec += 2)
789 : {
790 0 : const int nLineCount = atoi(papoGroup[iRec + 1]->GetField(9, 12));
791 :
792 0 : anRingStart[nRings++] = nNumLink;
793 :
794 0 : for (int i = 0; i < nLineCount && nNumLink < MAX_LINK * 2; i++)
795 : {
796 0 : anDirList[nNumLink] =
797 0 : atoi(papoGroup[iRec + 1]->GetField(19 + i * 7, 19 + i * 7));
798 0 : anGeomList[nNumLink] =
799 0 : atoi(papoGroup[iRec + 1]->GetField(13 + i * 7, 18 + i * 7));
800 0 : nNumLink++;
801 : }
802 :
803 0 : if (nNumLink == MAX_LINK * 2)
804 : {
805 0 : CPLError(CE_Failure, CPLE_AppDefined,
806 : "MAX_LINK exceeded in ntf_estlayers.cpp.");
807 :
808 0 : delete poFeature;
809 0 : return nullptr;
810 : }
811 : }
812 :
813 : // NUM_PART
814 0 : poFeature->SetField(3, nNumLink);
815 :
816 : // DIR
817 0 : poFeature->SetField(4, nNumLink, anDirList);
818 :
819 : // GEOM_ID_OF_LINK
820 0 : poFeature->SetField(5, nNumLink, anGeomList);
821 :
822 : // RingStart
823 0 : poFeature->SetField(6, nRings, anRingStart);
824 :
825 : /* -------------------------------------------------------------------- */
826 : /* collect information for whole complex polygon. */
827 : /* -------------------------------------------------------------------- */
828 : // POLY_ID
829 0 : if (papoGroup[iRec] != nullptr)
830 0 : poFeature->SetField(0, atoi(papoGroup[iRec]->GetField(3, 8)));
831 :
832 : // Attributes
833 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "PI", 1, "HA", 2,
834 : NULL);
835 :
836 : // Try to assemble polygon geometry.
837 0 : poReader->FormPolygonFromCache(poFeature);
838 :
839 0 : return poFeature;
840 : }
841 :
842 : /************************************************************************/
843 : /* TranslateBL2000Link() */
844 : /************************************************************************/
845 :
846 0 : static OGRFeature *TranslateBL2000Link(NTFFileReader *poReader,
847 : OGRNTFLayer *poLayer,
848 : NTFRecord **papoGroup)
849 :
850 : {
851 0 : if (CSLCount((char **)papoGroup) != 3 ||
852 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
853 0 : papoGroup[1]->GetType() != NRT_GEOMETRY ||
854 0 : papoGroup[2]->GetType() != NRT_ATTREC)
855 0 : return nullptr;
856 :
857 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
858 :
859 : // LINE_ID
860 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
861 :
862 : // Geometry
863 0 : int nGeomId = 0;
864 :
865 0 : poFeature->SetGeometryDirectly(
866 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
867 :
868 : // GEOM_ID
869 0 : poFeature->SetField(1, nGeomId);
870 :
871 : // Attributes
872 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "LK", 3,
873 : NULL);
874 :
875 0 : return poFeature;
876 : }
877 :
878 : /************************************************************************/
879 : /* TranslateBL2000Collection() */
880 : /************************************************************************/
881 :
882 0 : static OGRFeature *TranslateBL2000Collection(NTFFileReader *poReader,
883 : OGRNTFLayer *poLayer,
884 : NTFRecord **papoGroup)
885 :
886 : {
887 0 : if (CSLCount((char **)papoGroup) < 2 ||
888 0 : papoGroup[0]->GetType() != NRT_COLLECT ||
889 0 : papoGroup[1]->GetType() != NRT_ATTREC)
890 0 : return nullptr;
891 :
892 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
893 :
894 : // COLL_ID
895 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
896 :
897 : // NUM_PARTS
898 0 : int nNumLinks = atoi(papoGroup[0]->GetField(9, 12));
899 :
900 0 : if (nNumLinks > MAX_LINK)
901 : {
902 0 : CPLError(CE_Failure, CPLE_AppDefined,
903 : "MAX_LINK exceeded in ntf_estlayers.cpp.");
904 :
905 0 : return poFeature;
906 : }
907 :
908 0 : poFeature->SetField(1, nNumLinks);
909 :
910 : // POLY_ID / COLL_ID_REFS
911 0 : int anList[MAX_LINK] = {0}, anCollList[MAX_LINK] = {0};
912 0 : int nPolys = 0, nCollections = 0;
913 :
914 0 : for (int i = 0; i < nNumLinks; i++)
915 : {
916 0 : if (atoi(papoGroup[0]->GetField(13 + i * 8, 14 + i * 8)) == 34)
917 0 : anCollList[nCollections++] =
918 0 : atoi(papoGroup[0]->GetField(15 + i * 8, 20 + i * 8));
919 : else
920 0 : anList[nPolys++] =
921 0 : atoi(papoGroup[0]->GetField(15 + i * 8, 20 + i * 8));
922 : }
923 :
924 : // coverity[uninit_use_in_call]
925 0 : poFeature->SetField(2, nPolys, anList);
926 : // coverity[uninit_use_in_call]
927 0 : poFeature->SetField(10, nCollections, anCollList);
928 :
929 : // Attributes
930 : // Node that _CODE_DESC values are automatically applied if
931 : // the target fields exist.
932 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "AI", 3, "OP", 4, "NM",
933 : 5, "TY", 6, "AC", 7, "NB", 8, "NA", 9, NULL);
934 :
935 0 : return poFeature;
936 : }
937 :
938 : /************************************************************************/
939 : /* TranslateMeridianPoint() */
940 : /************************************************************************/
941 :
942 0 : static OGRFeature *TranslateMeridianPoint(NTFFileReader *poReader,
943 : OGRNTFLayer *poLayer,
944 : NTFRecord **papoGroup)
945 :
946 : {
947 0 : if (CSLCount((char **)papoGroup) < 2 ||
948 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
949 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
950 0 : return nullptr;
951 :
952 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
953 :
954 : // POINT_ID
955 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
956 :
957 : // Geometry
958 0 : int nGeomId = 0;
959 :
960 0 : poFeature->SetGeometryDirectly(
961 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
962 :
963 : // GEOM_ID
964 0 : poFeature->SetField(1, nGeomId);
965 :
966 : // Attributes
967 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "PN", 3, "OS",
968 : 4, "JN", 5, "RT", 6, "SI", 7, "PI", 8, "NM",
969 : 9, "DA", 10, NULL);
970 :
971 0 : return poFeature;
972 : }
973 :
974 : /************************************************************************/
975 : /* TranslateMeridianLine() */
976 : /************************************************************************/
977 :
978 0 : static OGRFeature *TranslateMeridianLine(NTFFileReader *poReader,
979 : OGRNTFLayer *poLayer,
980 : NTFRecord **papoGroup)
981 :
982 : {
983 0 : if (CSLCount((char **)papoGroup) < 2 ||
984 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
985 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
986 0 : return nullptr;
987 :
988 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
989 :
990 : // LINE_ID
991 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
992 :
993 : // Geometry
994 0 : int nGeomId = 0;
995 :
996 0 : poFeature->SetGeometryDirectly(
997 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
998 :
999 : // GEOM_ID
1000 0 : poFeature->SetField(2, nGeomId);
1001 :
1002 : // Attributes
1003 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "OM", 3, "RN",
1004 : 4, "TR", 5, "RI", 6, "LC", 7, "RC", 8, "LD",
1005 : 9, "RD", 10, NULL);
1006 :
1007 0 : return poFeature;
1008 : }
1009 :
1010 : /************************************************************************/
1011 : /* TranslateMeridian2Point() */
1012 : /************************************************************************/
1013 :
1014 0 : static OGRFeature *TranslateMeridian2Point(NTFFileReader *poReader,
1015 : OGRNTFLayer *poLayer,
1016 : NTFRecord **papoGroup)
1017 :
1018 : {
1019 0 : if (CSLCount((char **)papoGroup) < 2 ||
1020 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
1021 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1022 0 : return nullptr;
1023 :
1024 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1025 :
1026 : // POINT_ID
1027 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1028 :
1029 : // Geometry
1030 0 : int nGeomId = 0;
1031 :
1032 0 : poFeature->SetGeometryDirectly(
1033 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
1034 :
1035 : // GEOM_ID
1036 0 : poFeature->SetField(1, nGeomId);
1037 :
1038 : // Attributes
1039 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "PN", 3, "OD",
1040 : 4, "PO", 5, "JN", 6, "RT", 7, "SN", 8, "SI",
1041 : 9, "PI", 10, "NM", 11, "DA", 12, "WA", 13,
1042 : "HT", 14, "FA", 15, NULL);
1043 :
1044 0 : return poFeature;
1045 : }
1046 :
1047 : /************************************************************************/
1048 : /* TranslateMeridian2Line() */
1049 : /************************************************************************/
1050 :
1051 0 : static OGRFeature *TranslateMeridian2Line(NTFFileReader *poReader,
1052 : OGRNTFLayer *poLayer,
1053 : NTFRecord **papoGroup)
1054 :
1055 : {
1056 0 : if (CSLCount((char **)papoGroup) < 2 ||
1057 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
1058 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1059 0 : return nullptr;
1060 :
1061 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1062 :
1063 : // LINE_ID
1064 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1065 :
1066 : // Geometry
1067 0 : int nGeomId = 0;
1068 :
1069 0 : poFeature->SetGeometryDirectly(
1070 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
1071 :
1072 : // GEOM_ID
1073 0 : poFeature->SetField(2, nGeomId);
1074 :
1075 : // Attributes
1076 0 : poReader->ApplyAttributeValues(
1077 : poFeature, papoGroup, "FC", 1, "OD", 3, "PO", 4, "RN", 5, "TR", 6, "PN",
1078 : 7, "RI", 8, "LC", 9, "RC", 10, "LD", 11, "RD", 12, "WI", 14, NULL);
1079 :
1080 0 : return poFeature;
1081 : }
1082 :
1083 : /************************************************************************/
1084 : /* TranslateStrategiNode() */
1085 : /* */
1086 : /* Also used for Meridian, Oscar and BaseData.GB nodes. */
1087 : /************************************************************************/
1088 :
1089 0 : static OGRFeature *TranslateStrategiNode(CPL_UNUSED NTFFileReader *poReader,
1090 : OGRNTFLayer *poLayer,
1091 : NTFRecord **papoGroup)
1092 :
1093 : {
1094 0 : if (CSLCount((char **)papoGroup) != 1 ||
1095 0 : papoGroup[0]->GetType() != NRT_NODEREC)
1096 0 : return nullptr;
1097 :
1098 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1099 :
1100 : // NODE_ID
1101 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1102 :
1103 : // GEOM_ID_OF_POINT
1104 0 : poFeature->SetField(1, atoi(papoGroup[0]->GetField(9, 14)));
1105 :
1106 : // NUM_LINKS
1107 0 : int nNumLinks = atoi(papoGroup[0]->GetField(15, 18));
1108 :
1109 0 : if (nNumLinks < 0 || nNumLinks > MAX_LINK)
1110 : {
1111 0 : CPLError(CE_Failure, CPLE_AppDefined,
1112 : "MAX_LINK exceeded in ntf_estlayers.cpp.");
1113 :
1114 0 : return poFeature;
1115 : }
1116 :
1117 0 : poFeature->SetField(2, nNumLinks);
1118 :
1119 : // DIR
1120 0 : int i, anList[MAX_LINK] = {0};
1121 :
1122 0 : for (i = 0; i < nNumLinks; i++)
1123 0 : anList[i] = atoi(papoGroup[0]->GetField(19 + i * 12, 19 + i * 12));
1124 :
1125 0 : poFeature->SetField(3, nNumLinks, anList);
1126 :
1127 : // GEOM_ID_OF_POINT
1128 0 : for (i = 0; i < nNumLinks; i++)
1129 0 : anList[i] =
1130 0 : atoi(papoGroup[0]->GetField(19 + i * 12 + 1, 19 + i * 12 + 6));
1131 :
1132 0 : poFeature->SetField(4, nNumLinks, anList);
1133 :
1134 : // LEVEL
1135 0 : for (i = 0; i < nNumLinks; i++)
1136 0 : anList[i] =
1137 0 : atoi(papoGroup[0]->GetField(19 + i * 12 + 11, 19 + i * 12 + 11));
1138 :
1139 0 : poFeature->SetField(5, nNumLinks, anList);
1140 :
1141 : // ORIENT (optional)
1142 0 : if (EQUAL(poFeature->GetDefnRef()->GetFieldDefn(6)->GetNameRef(), "ORIENT"))
1143 : {
1144 0 : double adfList[MAX_LINK] = {0};
1145 :
1146 0 : for (i = 0; i < nNumLinks; i++)
1147 0 : adfList[i] = atoi(papoGroup[0]->GetField(19 + i * 12 + 7,
1148 0 : 19 + i * 12 + 10)) *
1149 : 0.1;
1150 :
1151 0 : poFeature->SetField(6, nNumLinks, adfList);
1152 : }
1153 :
1154 0 : return poFeature;
1155 : }
1156 :
1157 : /************************************************************************/
1158 : /* TranslateStrategiText() */
1159 : /* */
1160 : /* Also used for Meridian, BaseData and Generic text. */
1161 : /************************************************************************/
1162 :
1163 0 : static OGRFeature *TranslateStrategiText(NTFFileReader *poReader,
1164 : OGRNTFLayer *poLayer,
1165 : NTFRecord **papoGroup)
1166 :
1167 : {
1168 0 : if (CSLCount((char **)papoGroup) < 4 ||
1169 0 : papoGroup[0]->GetType() != NRT_TEXTREC ||
1170 0 : papoGroup[1]->GetType() != NRT_TEXTPOS ||
1171 0 : papoGroup[2]->GetType() != NRT_TEXTREP ||
1172 0 : papoGroup[3]->GetType() != NRT_GEOMETRY)
1173 0 : return nullptr;
1174 :
1175 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1176 :
1177 : // POINT_ID
1178 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1179 :
1180 : // FONT
1181 0 : poFeature->SetField(2, atoi(papoGroup[2]->GetField(9, 12)));
1182 :
1183 : // TEXT_HT
1184 0 : poFeature->SetField(3, atoi(papoGroup[2]->GetField(13, 15)) * 0.1);
1185 :
1186 : // DIG_POSTN
1187 0 : poFeature->SetField(4, atoi(papoGroup[2]->GetField(16, 16)));
1188 :
1189 : // ORIENT
1190 0 : poFeature->SetField(5, atoi(papoGroup[2]->GetField(17, 20)) * 0.1);
1191 :
1192 : // TEXT_HT_GROUND
1193 0 : poFeature->SetField(7, poFeature->GetFieldAsDouble(3) *
1194 0 : poReader->GetPaperToGround());
1195 :
1196 : // Geometry
1197 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[3]));
1198 :
1199 : // Attributes
1200 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "TX", 6, "DE",
1201 : 8, NULL);
1202 :
1203 0 : return poFeature;
1204 : }
1205 :
1206 : /************************************************************************/
1207 : /* TranslateStrategiPoint() */
1208 : /************************************************************************/
1209 :
1210 0 : static OGRFeature *TranslateStrategiPoint(NTFFileReader *poReader,
1211 : OGRNTFLayer *poLayer,
1212 : NTFRecord **papoGroup)
1213 :
1214 : {
1215 0 : if (CSLCount((char **)papoGroup) < 2 ||
1216 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
1217 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1218 0 : return nullptr;
1219 :
1220 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1221 :
1222 : // POINT_ID
1223 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1224 :
1225 : // Geometry
1226 0 : int nGeomId = 0;
1227 :
1228 0 : poFeature->SetGeometryDirectly(
1229 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
1230 :
1231 : // GEOM_ID
1232 0 : poFeature->SetField(10, nGeomId);
1233 :
1234 : // Attributes
1235 0 : poReader->ApplyAttributeValues(
1236 : poFeature, papoGroup, "FC", 1, "PN", 2, "NU", 3, "RB", 4, "RU", 5, "AN",
1237 : 6, "AO", 7, "CM", 8, "UN", 9, "DE", 11, "DN", 12, "FM", 13, "GS", 14,
1238 : "HI", 15, "HM", 16, "LO", 17, "OR", 18, "OW", 19, "RJ", 20, "RL", 21,
1239 : "RM", 22, "RQ", 23, "RW", 24, "RZ", 25, "UE", 26, NULL);
1240 :
1241 0 : return poFeature;
1242 : }
1243 :
1244 : /************************************************************************/
1245 : /* TranslateStrategiLine() */
1246 : /************************************************************************/
1247 :
1248 0 : static OGRFeature *TranslateStrategiLine(NTFFileReader *poReader,
1249 : OGRNTFLayer *poLayer,
1250 : NTFRecord **papoGroup)
1251 :
1252 : {
1253 0 : if (CSLCount((char **)papoGroup) < 2 ||
1254 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
1255 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1256 0 : return nullptr;
1257 :
1258 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1259 :
1260 : // LINE_ID
1261 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1262 :
1263 : // Geometry
1264 0 : int nGeomId = 0;
1265 :
1266 0 : poFeature->SetGeometryDirectly(
1267 0 : poReader->ProcessGeometry(papoGroup[1], &nGeomId));
1268 :
1269 : // GEOM_ID
1270 0 : poFeature->SetField(3, nGeomId);
1271 :
1272 : // Attributes
1273 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PN", 2, "DE",
1274 : 4, "FE", 5, "FF", 6, "FI", 7, "FM", 8, "FP",
1275 : 9, "FR", 10, "FT", 11, "GS", 12, "NU", 13,
1276 : "TX", 14, NULL);
1277 :
1278 0 : return poFeature;
1279 : }
1280 :
1281 : /************************************************************************/
1282 : /* TranslateLandrangerPoint() */
1283 : /************************************************************************/
1284 :
1285 0 : static OGRFeature *TranslateLandrangerPoint(NTFFileReader *poReader,
1286 : OGRNTFLayer *poLayer,
1287 : NTFRecord **papoGroup)
1288 :
1289 : {
1290 0 : if (CSLCount((char **)papoGroup) != 2 ||
1291 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
1292 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1293 0 : return nullptr;
1294 :
1295 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1296 :
1297 : // POINT_ID
1298 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1299 :
1300 : // FEAT_CODE
1301 0 : poFeature->SetField(1, papoGroup[0]->GetField(17, 20));
1302 :
1303 : // HEIGHT
1304 0 : poFeature->SetField(2, atoi(papoGroup[0]->GetField(11, 16)));
1305 :
1306 : // Geometry
1307 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
1308 :
1309 0 : return poFeature;
1310 : }
1311 :
1312 : /************************************************************************/
1313 : /* TranslateLandrangerLine() */
1314 : /************************************************************************/
1315 :
1316 0 : static OGRFeature *TranslateLandrangerLine(NTFFileReader *poReader,
1317 : OGRNTFLayer *poLayer,
1318 : NTFRecord **papoGroup)
1319 :
1320 : {
1321 0 : if (CSLCount((char **)papoGroup) != 2 ||
1322 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
1323 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1324 0 : return nullptr;
1325 :
1326 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1327 :
1328 : // LINE_ID
1329 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1330 :
1331 : // FEAT_CODE
1332 0 : poFeature->SetField(1, papoGroup[0]->GetField(17, 20));
1333 :
1334 : // HEIGHT
1335 0 : poFeature->SetField(2, atoi(papoGroup[0]->GetField(11, 16)));
1336 :
1337 : // Geometry
1338 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
1339 :
1340 0 : return poFeature;
1341 : }
1342 :
1343 : /************************************************************************/
1344 : /* TranslateProfilePoint() */
1345 : /************************************************************************/
1346 :
1347 0 : static OGRFeature *TranslateProfilePoint(NTFFileReader *poReader,
1348 : OGRNTFLayer *poLayer,
1349 : NTFRecord **papoGroup)
1350 :
1351 : {
1352 0 : if (CSLCount((char **)papoGroup) < 2 ||
1353 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
1354 0 : (papoGroup[1]->GetType() != NRT_GEOMETRY &&
1355 0 : papoGroup[1]->GetType() != NRT_GEOMETRY3D))
1356 0 : return nullptr;
1357 :
1358 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1359 :
1360 : // POINT_ID
1361 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1362 :
1363 : // FEAT_CODE
1364 0 : poFeature->SetField(1, papoGroup[0]->GetField(17, 20));
1365 :
1366 : // Geometry
1367 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
1368 :
1369 : // Attributes
1370 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "HT", 2, NULL);
1371 :
1372 : // Set HEIGHT/elevation
1373 0 : OGRPoint *poPoint = dynamic_cast<OGRPoint *>(poFeature->GetGeometryRef());
1374 :
1375 0 : if (poPoint != nullptr && poPoint->getCoordinateDimension() == 3)
1376 : {
1377 0 : poFeature->SetField(2, poPoint->getZ());
1378 : }
1379 0 : else if (poPoint != nullptr)
1380 : {
1381 0 : poFeature->SetField(2, poFeature->GetFieldAsDouble(2) * 0.01);
1382 0 : poPoint->setZ(poFeature->GetFieldAsDouble(2));
1383 : }
1384 :
1385 0 : return poFeature;
1386 : }
1387 :
1388 : /************************************************************************/
1389 : /* TranslateProfileLine() */
1390 : /************************************************************************/
1391 :
1392 0 : static OGRFeature *TranslateProfileLine(NTFFileReader *poReader,
1393 : OGRNTFLayer *poLayer,
1394 : NTFRecord **papoGroup)
1395 :
1396 : {
1397 0 : if (CSLCount((char **)papoGroup) < 2 ||
1398 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
1399 0 : (papoGroup[1]->GetType() != NRT_GEOMETRY &&
1400 0 : papoGroup[1]->GetType() != NRT_GEOMETRY3D))
1401 0 : return nullptr;
1402 :
1403 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1404 :
1405 : // LINE_ID
1406 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1407 :
1408 : // FEAT_CODE
1409 0 : poFeature->SetField(1, papoGroup[0]->GetField(17, 20));
1410 :
1411 : // Geometry
1412 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
1413 :
1414 : // Attributes
1415 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "HT", 2, NULL);
1416 :
1417 : // Set HEIGHT/elevation
1418 : OGRLineString *poLine =
1419 0 : dynamic_cast<OGRLineString *>(poFeature->GetGeometryRef());
1420 :
1421 0 : poFeature->SetField(2, poFeature->GetFieldAsDouble(2) * 0.01);
1422 0 : if (poLine != nullptr && poLine->getCoordinateDimension() == 2)
1423 : {
1424 0 : for (int i = 0; i < poLine->getNumPoints(); i++)
1425 : {
1426 0 : poLine->setPoint(i, poLine->getX(i), poLine->getY(i),
1427 : poFeature->GetFieldAsDouble(2));
1428 : }
1429 : }
1430 0 : else if (poLine != nullptr)
1431 : {
1432 0 : double dfAccum = 0.0;
1433 :
1434 0 : for (int i = 0; i < poLine->getNumPoints(); i++)
1435 : {
1436 0 : dfAccum += poLine->getZ(i);
1437 : }
1438 0 : poFeature->SetField(2, dfAccum / poLine->getNumPoints());
1439 : }
1440 :
1441 0 : return poFeature;
1442 : }
1443 :
1444 : /************************************************************************/
1445 : /* TranslateLandlinePoint() */
1446 : /************************************************************************/
1447 :
1448 0 : static OGRFeature *TranslateLandlinePoint(NTFFileReader *poReader,
1449 : OGRNTFLayer *poLayer,
1450 : NTFRecord **papoGroup)
1451 :
1452 : {
1453 0 : if (CSLCount((char **)papoGroup) < 2 ||
1454 0 : papoGroup[0]->GetType() != NRT_POINTREC ||
1455 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1456 0 : return nullptr;
1457 :
1458 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1459 :
1460 : // POINT_ID
1461 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1462 :
1463 : // FEAT_CODE
1464 0 : poFeature->SetField(1, papoGroup[0]->GetField(17, 20));
1465 :
1466 : // ORIENT
1467 0 : poFeature->SetField(2, atoi(papoGroup[0]->GetField(11, 16)) * 0.1);
1468 :
1469 : // DISTANCE
1470 0 : poReader->ApplyAttributeValues(poFeature, papoGroup, "DT", 3, NULL);
1471 :
1472 : // Geometry
1473 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
1474 :
1475 : // CHG_DATE (optional)
1476 0 : if (poFeature->GetFieldIndex("CHG_DATE") == 4)
1477 : {
1478 0 : poFeature->SetField(4, papoGroup[0]->GetField(23, 28));
1479 : }
1480 :
1481 : // CHG_TYPE (optional)
1482 0 : if (poFeature->GetFieldIndex("CHG_TYPE") == 5)
1483 : {
1484 0 : poFeature->SetField(5, papoGroup[0]->GetField(22, 22));
1485 : }
1486 :
1487 0 : return poFeature;
1488 : }
1489 :
1490 : /************************************************************************/
1491 : /* TranslateLandlineLine() */
1492 : /************************************************************************/
1493 :
1494 0 : static OGRFeature *TranslateLandlineLine(NTFFileReader *poReader,
1495 : OGRNTFLayer *poLayer,
1496 : NTFRecord **papoGroup)
1497 :
1498 : {
1499 0 : if (CSLCount((char **)papoGroup) != 2 ||
1500 0 : papoGroup[0]->GetType() != NRT_LINEREC ||
1501 0 : papoGroup[1]->GetType() != NRT_GEOMETRY)
1502 0 : return nullptr;
1503 :
1504 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1505 :
1506 : // LINE_ID
1507 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1508 :
1509 : // FEAT_CODE
1510 0 : poFeature->SetField(1, papoGroup[0]->GetField(17, 20));
1511 :
1512 : // Geometry
1513 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
1514 :
1515 : // CHG_DATE (optional)
1516 0 : if (poFeature->GetFieldIndex("CHG_DATE") == 2)
1517 : {
1518 0 : poFeature->SetField(2, papoGroup[0]->GetField(23, 28));
1519 : }
1520 :
1521 : // CHG_TYPE (optional)
1522 0 : if (poFeature->GetFieldIndex("CHG_TYPE") == 3)
1523 : {
1524 0 : poFeature->SetField(3, papoGroup[0]->GetField(22, 22));
1525 : }
1526 0 : return poFeature;
1527 : }
1528 :
1529 : /************************************************************************/
1530 : /* TranslateLandlineName() */
1531 : /************************************************************************/
1532 :
1533 0 : static OGRFeature *TranslateLandlineName(NTFFileReader *poReader,
1534 : OGRNTFLayer *poLayer,
1535 : NTFRecord **papoGroup)
1536 :
1537 : {
1538 0 : if (CSLCount((char **)papoGroup) != 3 ||
1539 0 : papoGroup[0]->GetType() != NRT_NAMEREC ||
1540 0 : papoGroup[1]->GetType() != NRT_NAMEPOSTN ||
1541 0 : papoGroup[2]->GetType() != NRT_GEOMETRY)
1542 0 : return nullptr;
1543 :
1544 0 : int nNumChar = atoi(papoGroup[0]->GetField(13, 14));
1545 0 : if (nNumChar <= 0)
1546 0 : return nullptr;
1547 :
1548 0 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
1549 :
1550 : // NAME_ID
1551 0 : poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8)));
1552 :
1553 : // TEXT_CODE
1554 0 : poFeature->SetField(1, papoGroup[0]->GetField(9, 12));
1555 :
1556 : // TEXT
1557 0 : poFeature->SetField(2, papoGroup[0]->GetField(15, 15 + nNumChar - 1));
1558 :
1559 : // FONT
1560 0 : poFeature->SetField(3, atoi(papoGroup[1]->GetField(3, 6)));
1561 :
1562 : // TEXT_HT
1563 0 : poFeature->SetField(4, atoi(papoGroup[1]->GetField(7, 9)) * 0.1);
1564 :
1565 : // DIG_POSTN
1566 0 : poFeature->SetField(5, atoi(papoGroup[1]->GetField(10, 10)));
1567 :
1568 : // ORIENT
1569 0 : poFeature->SetField(6, CPLAtof(papoGroup[1]->GetField(11, 14)) * 0.1);
1570 :
1571 : // TEXT_HT_GROUND
1572 0 : poFeature->SetField(7, poFeature->GetFieldAsDouble(4) *
1573 0 : poReader->GetPaperToGround());
1574 :
1575 : // CHG_DATE (optional)
1576 0 : if (poFeature->GetFieldIndex("CHG_DATE") == 7)
1577 : {
1578 0 : poFeature->SetField(8, papoGroup[0]->GetField(15 + nNumChar + 2,
1579 : 15 + nNumChar + 2 + 5));
1580 : }
1581 :
1582 : // CHG_TYPE (optional)
1583 0 : if (poFeature->GetFieldIndex("CHG_TYPE") == 9)
1584 : {
1585 0 : poFeature->SetField(
1586 : 9, papoGroup[0]->GetField(15 + nNumChar + 1, 15 + nNumChar + 1));
1587 : }
1588 :
1589 : // Geometry
1590 0 : poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[2]));
1591 :
1592 0 : return poFeature;
1593 : }
1594 :
1595 : /************************************************************************/
1596 : /* EstablishLayer() */
1597 : /* */
1598 : /* Establish one layer based on a simplified description of the */
1599 : /* fields to be present. */
1600 : /************************************************************************/
1601 :
1602 0 : void NTFFileReader::EstablishLayer(const char *pszLayerName,
1603 : OGRwkbGeometryType eGeomType,
1604 : NTFFeatureTranslator pfnTranslator,
1605 : int nLeadRecordType,
1606 : NTFGenericClass *poClass, ...)
1607 :
1608 : {
1609 : /* -------------------------------------------------------------------- */
1610 : /* Does this layer already exist? If so, we do nothing */
1611 : /* ... note that we don't check the definition. */
1612 : /* -------------------------------------------------------------------- */
1613 0 : OGRNTFLayer *poLayer = poDS->GetNamedLayer(pszLayerName);
1614 :
1615 : /* ==================================================================== */
1616 : /* Create a new layer matching the request if we don't already */
1617 : /* have one. */
1618 : /* ==================================================================== */
1619 0 : if (poLayer == nullptr)
1620 : {
1621 : /* --------------------------------------------------------------------
1622 : */
1623 : /* Create a new feature definition. */
1624 : /* --------------------------------------------------------------------
1625 : */
1626 0 : OGRFeatureDefn *poDefn = new OGRFeatureDefn(pszLayerName);
1627 0 : poDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->DSGetSpatialRef());
1628 0 : poDefn->SetGeomType(eGeomType);
1629 0 : poDefn->Reference();
1630 :
1631 : /* --------------------------------------------------------------------
1632 : */
1633 : /* Fetch definitions of each field in turn. */
1634 : /* --------------------------------------------------------------------
1635 : */
1636 : va_list hVaArgs;
1637 0 : va_start(hVaArgs, poClass);
1638 : while (true)
1639 : {
1640 0 : const char *pszFieldName = va_arg(hVaArgs, const char *);
1641 :
1642 0 : if (pszFieldName == nullptr)
1643 0 : break;
1644 :
1645 0 : const OGRFieldType eType = (OGRFieldType)va_arg(hVaArgs, int);
1646 0 : const int nWidth = va_arg(hVaArgs, int);
1647 0 : const int nPrecision = va_arg(hVaArgs, int);
1648 :
1649 0 : OGRFieldDefn oFieldDefn(pszFieldName, eType);
1650 0 : oFieldDefn.SetWidth(nWidth);
1651 0 : oFieldDefn.SetPrecision(nPrecision);
1652 :
1653 0 : poDefn->AddFieldDefn(&oFieldDefn);
1654 0 : }
1655 :
1656 0 : va_end(hVaArgs);
1657 :
1658 : /* --------------------------------------------------------------------
1659 : */
1660 : /* Add attributes collected in the generic class survey. */
1661 : /* --------------------------------------------------------------------
1662 : */
1663 0 : if (poClass != nullptr)
1664 : {
1665 0 : for (int iGAtt = 0; iGAtt < poClass->nAttrCount; iGAtt++)
1666 : {
1667 0 : const char *pszFormat = poClass->papszAttrFormats[iGAtt];
1668 0 : OGRFieldDefn oFieldDefn(poClass->papszAttrNames[iGAtt],
1669 0 : OFTInteger);
1670 :
1671 0 : if (STARTS_WITH_CI(pszFormat, "I"))
1672 : {
1673 0 : oFieldDefn.SetType(OFTInteger);
1674 0 : oFieldDefn.SetWidth(poClass->panAttrMaxWidth[iGAtt]);
1675 : }
1676 0 : else if (STARTS_WITH_CI(pszFormat, "D") ||
1677 0 : STARTS_WITH_CI(pszFormat, "A"))
1678 : {
1679 0 : oFieldDefn.SetType(OFTString);
1680 0 : oFieldDefn.SetWidth(poClass->panAttrMaxWidth[iGAtt]);
1681 : }
1682 0 : else if (STARTS_WITH_CI(pszFormat, "R"))
1683 : {
1684 0 : oFieldDefn.SetType(OFTReal);
1685 0 : oFieldDefn.SetWidth(poClass->panAttrMaxWidth[iGAtt] + 1);
1686 0 : const size_t nFormatLen = strlen(pszFormat);
1687 0 : if (nFormatLen >= 4 && pszFormat[2] == ',')
1688 0 : oFieldDefn.SetPrecision(atoi(pszFormat + 3));
1689 0 : else if (nFormatLen >= 5 && pszFormat[3] == ',')
1690 0 : oFieldDefn.SetPrecision(atoi(pszFormat + 4));
1691 : }
1692 :
1693 0 : poDefn->AddFieldDefn(&oFieldDefn);
1694 :
1695 : /*
1696 : ** If this field can appear multiple times, create an
1697 : ** additional attribute to hold lists of values. This
1698 : ** is always created as a variable length string field.
1699 : */
1700 0 : if (poClass->pabAttrMultiple[iGAtt])
1701 : {
1702 : char szName[128];
1703 :
1704 0 : snprintf(szName, sizeof(szName), "%s_LIST",
1705 0 : poClass->papszAttrNames[iGAtt]);
1706 :
1707 0 : OGRFieldDefn oFieldDefnL(szName, OFTString);
1708 :
1709 0 : poDefn->AddFieldDefn(&oFieldDefnL);
1710 : }
1711 : }
1712 : }
1713 :
1714 : /* --------------------------------------------------------------------
1715 : */
1716 : /* Add the TILE_REF attribute. */
1717 : /* --------------------------------------------------------------------
1718 : */
1719 0 : OGRFieldDefn oTileID("TILE_REF", OFTString);
1720 :
1721 0 : oTileID.SetWidth(10);
1722 :
1723 0 : poDefn->AddFieldDefn(&oTileID);
1724 :
1725 : /* --------------------------------------------------------------------
1726 : */
1727 : /* Create the layer, and give over to the data source object to */
1728 : /* maintain. */
1729 : /* --------------------------------------------------------------------
1730 : */
1731 0 : poLayer = new OGRNTFLayer(poDS, poDefn, pfnTranslator);
1732 :
1733 0 : poDS->AddLayer(poLayer);
1734 : }
1735 :
1736 : /* -------------------------------------------------------------------- */
1737 : /* Register this translator with this file reader for handling */
1738 : /* the indicate record type. */
1739 : /* -------------------------------------------------------------------- */
1740 0 : apoTypeTranslation[nLeadRecordType] = poLayer;
1741 0 : }
1742 :
1743 : /************************************************************************/
1744 : /* EstablishLayers() */
1745 : /* */
1746 : /* This method is responsible for creating any missing */
1747 : /* OGRNTFLayers needed for the current product based on the */
1748 : /* product name. */
1749 : /* */
1750 : /* NOTE: Any changes to the order of attribute fields in the */
1751 : /* following EstablishLayer() calls must also result in updates */
1752 : /* to the translate functions. Changes of names, widths and to */
1753 : /* some extent types can be done without side effects. */
1754 : /************************************************************************/
1755 :
1756 0 : void NTFFileReader::EstablishLayers()
1757 :
1758 : {
1759 0 : if (poDS == nullptr || fp == nullptr)
1760 0 : return;
1761 :
1762 0 : if (GetProductId() == NPC_LANDLINE)
1763 : {
1764 0 : EstablishLayer("LANDLINE_POINT", wkbPoint, TranslateLandlinePoint,
1765 : NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0,
1766 : "FEAT_CODE", OFTString, 4, 0, "ORIENT", OFTReal, 5, 1,
1767 : "DISTANCE", OFTReal, 6, 3, NULL);
1768 :
1769 0 : EstablishLayer("LANDLINE_LINE", wkbLineString, TranslateLandlineLine,
1770 : NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0,
1771 : "FEAT_CODE", OFTString, 4, 0, NULL);
1772 :
1773 0 : EstablishLayer("LANDLINE_NAME", wkbPoint, TranslateLandlineName,
1774 : NRT_NAMEREC, nullptr, "NAME_ID", OFTInteger, 6, 0,
1775 : "TEXT_CODE", OFTString, 4, 0, "TEXT", OFTString, 0, 0,
1776 : "FONT", OFTInteger, 4, 0, "TEXT_HT", OFTReal, 4, 1,
1777 : "DIG_POSTN", OFTInteger, 1, 0, "ORIENT", OFTReal, 5, 1,
1778 : "TEXT_HT_GROUND", OFTReal, 10, 3, NULL);
1779 : }
1780 0 : else if (GetProductId() == NPC_LANDLINE99)
1781 : {
1782 0 : EstablishLayer("LANDLINE99_POINT", wkbPoint, TranslateLandlinePoint,
1783 : NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0,
1784 : "FEAT_CODE", OFTString, 4, 0, "ORIENT", OFTReal, 5, 1,
1785 : "DISTANCE", OFTReal, 6, 3, "CHG_DATE", OFTString, 6, 0,
1786 : "CHG_TYPE", OFTString, 1, 0, NULL);
1787 :
1788 0 : EstablishLayer("LANDLINE99_LINE", wkbLineString, TranslateLandlineLine,
1789 : NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0,
1790 : "FEAT_CODE", OFTString, 4, 0, "CHG_DATE", OFTString, 6,
1791 : 0, "CHG_TYPE", OFTString, 1, 0, NULL);
1792 :
1793 0 : EstablishLayer("LANDLINE99_NAME", wkbPoint, TranslateLandlineName,
1794 : NRT_NAMEREC, nullptr, "NAME_ID", OFTInteger, 6, 0,
1795 : "TEXT_CODE", OFTString, 4, 0, "TEXT", OFTString, 0, 0,
1796 : "FONT", OFTInteger, 4, 0, "TEXT_HT", OFTReal, 4, 1,
1797 : "DIG_POSTN", OFTInteger, 1, 0, "ORIENT", OFTReal, 5, 1,
1798 : "TEXT_HT_GROUND", OFTReal, 10, 3, "CHG_DATE", OFTString,
1799 : 6, 0, "CHG_TYPE", OFTString, 1, 0, NULL);
1800 : }
1801 0 : else if (GetProductId() == NPC_LANDRANGER_CONT)
1802 : {
1803 0 : EstablishLayer("PANORAMA_POINT", wkbPoint, TranslateLandrangerPoint,
1804 : NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0,
1805 : "FEAT_CODE", OFTString, 4, 0, "HEIGHT", OFTReal, 7, 2,
1806 : NULL);
1807 :
1808 0 : EstablishLayer("PANORAMA_CONTOUR", wkbLineString,
1809 : TranslateLandrangerLine, NRT_LINEREC, nullptr, "LINE_ID",
1810 : OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0, "HEIGHT",
1811 : OFTReal, 7, 2, NULL);
1812 : }
1813 0 : else if (GetProductId() == NPC_LANDFORM_PROFILE_CONT)
1814 : {
1815 0 : EstablishLayer("PROFILE_POINT", wkbPoint25D, TranslateProfilePoint,
1816 : NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0,
1817 : "FEAT_CODE", OFTString, 4, 0, "HEIGHT", OFTReal, 7, 2,
1818 : NULL);
1819 :
1820 0 : EstablishLayer("PROFILE_LINE", wkbLineString25D, TranslateProfileLine,
1821 : NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0,
1822 : "FEAT_CODE", OFTString, 4, 0, "HEIGHT", OFTReal, 7, 2,
1823 : NULL);
1824 : }
1825 0 : else if (GetProductId() == NPC_STRATEGI)
1826 : {
1827 0 : EstablishLayer(
1828 : "STRATEGI_POINT", wkbPoint, TranslateStrategiPoint, NRT_POINTREC,
1829 : nullptr, "POINT_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0,
1830 : "PROPER_NAME", OFTString, 0, 0, "FEATURE_NUMBER", OFTString, 0, 0,
1831 : "RB", OFTString, 1, 0, "RU", OFTString, 1, 0, "AN", OFTString, 0, 0,
1832 : "AO", OFTString, 0, 0, "COUNTY_NAME", OFTString, 0, 0,
1833 : "UNITARY_NAME", OFTString, 0, 0, "GEOM_ID", OFTInteger, 6, 0,
1834 : "DATE", OFTInteger, 8, 0, "DISTRICT_NAME", OFTString, 0, 0,
1835 : "FEATURE_NAME", OFTString, 0, 0, "GIS", OFTString, 0, 0,
1836 : "HEIGHT_IMPERIAL", OFTInteger, 4, 0, "HEIGHT_METRIC", OFTInteger, 4,
1837 : 0, "LOCATION", OFTInteger, 1, 0, "ORIENTATION", OFTReal, 4, 1,
1838 : "OWNER", OFTString, 0, 0, "RESTRICTION_NORTH", OFTString, 0, 0,
1839 : "RESTRICTION_SOUTH", OFTString, 0, 0, "RESTRICTION_EAST", OFTString,
1840 : 0, 0, "RESTRICTION_WEST", OFTString, 0, 0, "RESTRICTION_CLOCKWISE",
1841 : OFTString, 0, 0, "RESTRICTION_ANTICLOCKWISE", OFTString, 0, 0,
1842 : "USAGE", OFTInteger, 1, 0, NULL);
1843 :
1844 0 : EstablishLayer(
1845 : "STRATEGI_LINE", wkbLineString, TranslateStrategiLine, NRT_LINEREC,
1846 : nullptr, "LINE_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0,
1847 : "PROPER_NAME", OFTString, 0, 0, "GEOM_ID", OFTInteger, 6, 0, "DATE",
1848 : OFTInteger, 8, 0, "FERRY_ACCESS", OFTString, 0, 0, "FERRY_FROM",
1849 : OFTString, 0, 0, "FERRY_TIME", OFTString, 0, 0, "FEATURE_NAME",
1850 : OFTString, 0, 0, "FERRY_TYPE", OFTString, 0, 0,
1851 : "FERRY_RESTRICTIONS", OFTString, 0, 0, "FERRY_TO", OFTString, 0, 0,
1852 : "GIS", OFTString, 0, 0, "FEATURE_NUMBER", OFTString, 0, 0, NULL);
1853 :
1854 0 : EstablishLayer(
1855 : "STRATEGI_TEXT", wkbPoint, TranslateStrategiText, NRT_TEXTREC,
1856 : nullptr, "TEXT_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0,
1857 : "FONT", OFTInteger, 4, 0, "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN",
1858 : OFTInteger, 1, 0, "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0,
1859 : "TEXT_HT_GROUND", OFTReal, 10, 3, "DATE", OFTInteger, 8, 0, NULL);
1860 :
1861 0 : EstablishLayer("STRATEGI_NODE", wkbNone, TranslateStrategiNode,
1862 : NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0,
1863 : "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS",
1864 : OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0,
1865 : "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL",
1866 : OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL);
1867 : }
1868 0 : else if (GetProductId() == NPC_MERIDIAN)
1869 : {
1870 0 : EstablishLayer("MERIDIAN_POINT", wkbPoint, TranslateMeridianPoint,
1871 : NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0,
1872 : "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4,
1873 : 0, "PROPER_NAME", OFTString, 0, 0, "OSMDR", OFTString,
1874 : 13, 0, "JUNCTION_NAME", OFTString, 0, 0, "ROUNDABOUT",
1875 : OFTString, 1, 0, "STATION_ID", OFTString, 13, 0,
1876 : "GLOBAL_ID", OFTInteger, 6, 0, "ADMIN_NAME", OFTString,
1877 : 0, 0, "DA_DLUA_ID", OFTString, 13, 0, NULL);
1878 :
1879 0 : EstablishLayer("MERIDIAN_LINE", wkbLineString, TranslateMeridianLine,
1880 : NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0,
1881 : "FEAT_CODE", OFTString, 4, 0, "GEOM_ID", OFTInteger, 6,
1882 : 0, "OSMDR", OFTString, 13, 0, "ROAD_NUM", OFTString, 0,
1883 : 0, "TRUNK_ROAD", OFTString, 1, 0, "RAIL_ID", OFTString,
1884 : 13, 0, "LEFT_COUNTY", OFTInteger, 6, 0, "RIGHT_COUNTY",
1885 : OFTInteger, 6, 0, "LEFT_DISTRICT", OFTInteger, 6, 0,
1886 : "RIGHT_DISTRICT", OFTInteger, 6, 0, NULL);
1887 :
1888 0 : EstablishLayer("MERIDIAN_TEXT", wkbPoint, TranslateStrategiText,
1889 : NRT_TEXTREC, nullptr, "TEXT_ID", OFTInteger, 6, 0,
1890 : "FEAT_CODE", OFTString, 4, 0, "FONT", OFTInteger, 4, 0,
1891 : "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN", OFTInteger, 1, 0,
1892 : "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0,
1893 : "TEXT_HT_GROUND", OFTReal, 10, 3, NULL);
1894 :
1895 0 : EstablishLayer("MERIDIAN_NODE", wkbNone, TranslateStrategiNode,
1896 : NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0,
1897 : "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS",
1898 : OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0,
1899 : "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL",
1900 : OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL);
1901 : }
1902 0 : else if (GetProductId() == NPC_MERIDIAN2)
1903 : {
1904 0 : EstablishLayer(
1905 : "MERIDIAN2_POINT", wkbPoint, TranslateMeridian2Point, NRT_POINTREC,
1906 : nullptr, "POINT_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0,
1907 : "FEAT_CODE", OFTString, 4, 0, "PROPER_NAME", OFTString, 0, 0,
1908 : "OSODR", OFTString, 13, 0, "PARENT_OSODR", OFTString, 13, 0,
1909 : "JUNCTION_NAME", OFTString, 0, 0, "ROUNDABOUT", OFTString, 1, 0,
1910 : "SETTLEMENT_NAME", OFTString, 0, 0, "STATION_ID", OFTString, 13, 0,
1911 : "GLOBAL_ID", OFTInteger, 6, 0, "ADMIN_NAME", OFTString, 0, 0,
1912 : "DA_DLUA_ID", OFTString, 13, 0, "WATER_AREA", OFTString, 13, 0,
1913 : "HEIGHT", OFTInteger, 8, 0, "FOREST_ID", OFTString, 13, 0, NULL);
1914 :
1915 0 : EstablishLayer("MERIDIAN2_LINE", wkbLineString, TranslateMeridian2Line,
1916 : NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0,
1917 : "FEAT_CODE", OFTString, 4, 0, "GEOM_ID", OFTInteger, 6,
1918 : 0, "OSODR", OFTString, 13, 0, "PARENT_OSODR", OFTString,
1919 : 13, 0, "ROAD_NUM", OFTString, 0, 0, "TRUNK_ROAD",
1920 : OFTString, 1, 0, "PROPER_NAME", OFTString, 0, 0,
1921 : "RAIL_ID", OFTString, 13, 0, "LEFT_COUNTY", OFTInteger,
1922 : 6, 0, "RIGHT_COUNTY", OFTInteger, 6, 0, "LEFT_DISTRICT",
1923 : OFTInteger, 6, 0, "RIGHT_DISTRICT", OFTInteger, 6, 0,
1924 : "WATER_LINK_ID", OFTString, 13, 0, NULL);
1925 :
1926 0 : EstablishLayer("MERIDIAN2_TEXT", wkbPoint, TranslateStrategiText,
1927 : NRT_TEXTREC, nullptr, "TEXT_ID", OFTInteger, 6, 0,
1928 : "FEAT_CODE", OFTString, 4, 0, "FONT", OFTInteger, 4, 0,
1929 : "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN", OFTInteger, 1, 0,
1930 : "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0,
1931 : "TEXT_HT_GROUND", OFTReal, 10, 3, NULL);
1932 :
1933 0 : EstablishLayer("MERIDIAN2_NODE", wkbNone, TranslateStrategiNode,
1934 : NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0,
1935 : "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS",
1936 : OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0,
1937 : "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL",
1938 : OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL);
1939 : }
1940 0 : else if (GetProductId() == NPC_BOUNDARYLINE)
1941 : {
1942 0 : EstablishLayer("BOUNDARYLINE_LINK", wkbLineString,
1943 : TranslateBoundarylineLink, NRT_GEOMETRY, nullptr,
1944 : "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4,
1945 : 0, "GLOBAL_LINK_ID", OFTInteger, 10, 0, "HWM_FLAG",
1946 : OFTInteger, 1, 0, NULL);
1947 :
1948 0 : EstablishLayer("BOUNDARYLINE_POLY", bCacheLines ? wkbPolygon : wkbPoint,
1949 : TranslateBoundarylinePoly, NRT_POLYGON, nullptr,
1950 : "POLY_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4,
1951 : 0, "GLOBAL_SEED_ID", OFTInteger, 6, 0, "HECTARES",
1952 : OFTReal, 9, 3, "NUM_PARTS", OFTInteger, 4, 0, "DIR",
1953 : OFTIntegerList, 1, 0, "GEOM_ID_OF_LINK", OFTIntegerList,
1954 : 6, 0, "RingStart", OFTIntegerList, 6, 0, NULL);
1955 :
1956 0 : EstablishLayer("BOUNDARYLINE_COLLECTIONS", wkbNone,
1957 : TranslateBoundarylineCollection, NRT_COLLECT, nullptr,
1958 : "COLL_ID", OFTInteger, 6, 0, "NUM_PARTS", OFTInteger, 4,
1959 : 0, "POLY_ID", OFTIntegerList, 6, 0, "ADMIN_AREA_ID",
1960 : OFTInteger, 6, 0, "OPCS_CODE", OFTString, 6, 0,
1961 : "ADMIN_NAME", OFTString, 0, 0, NULL);
1962 : }
1963 0 : else if (GetProductId() == NPC_BL2000)
1964 : {
1965 0 : EstablishLayer("BL2000_LINK", wkbLineString, TranslateBL2000Link,
1966 : NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0,
1967 : "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4,
1968 : 0, "GLOBAL_LINK_ID", OFTInteger, 10, 0, NULL);
1969 0 : EstablishLayer("BL2000_POLY", bCacheLines ? wkbPolygon : wkbNone,
1970 : TranslateBL2000Poly, NRT_POLYGON, nullptr, "POLY_ID",
1971 : OFTInteger, 6, 0, "GLOBAL_SEED_ID", OFTInteger, 6, 0,
1972 : "HECTARES", OFTReal, 12, 3, "NUM_PARTS", OFTInteger, 4,
1973 : 0, "DIR", OFTIntegerList, 1, 0, "GEOM_ID_OF_LINK",
1974 : OFTIntegerList, 6, 0, "RingStart", OFTIntegerList, 6, 0,
1975 : NULL);
1976 0 : if (poDS->GetOption("CODELIST") != nullptr &&
1977 0 : EQUAL(poDS->GetOption("CODELIST"), "ON"))
1978 0 : EstablishLayer(
1979 : "BL2000_COLLECTIONS", wkbNone, TranslateBL2000Collection,
1980 : NRT_COLLECT, nullptr, "COLL_ID", OFTInteger, 6, 0, "NUM_PARTS",
1981 : OFTInteger, 4, 0, "POLY_ID", OFTIntegerList, 6, 0,
1982 : "ADMIN_AREA_ID", OFTInteger, 6, 0, "CENSUS_CODE", OFTString, 7,
1983 : 0, "ADMIN_NAME", OFTString, 0, 0, "AREA_TYPE", OFTString, 2, 0,
1984 : "AREA_CODE", OFTString, 3, 0, "NON_TYPE_CODE", OFTString, 3, 0,
1985 : "NON_INLAND_AREA", OFTReal, 12, 3, "COLL_ID_REFS",
1986 : OFTIntegerList, 6, 0, "AREA_TYPE_DESC", OFTString, 0, 0,
1987 : "AREA_CODE_DESC", OFTString, 0, 0, "NON_TYPE_CODE_DESC",
1988 : OFTString, 0, 0, NULL);
1989 : else
1990 0 : EstablishLayer(
1991 : "BL2000_COLLECTIONS", wkbNone, TranslateBL2000Collection,
1992 : NRT_COLLECT, nullptr, "COLL_ID", OFTInteger, 6, 0, "NUM_PARTS",
1993 : OFTInteger, 4, 0, "POLY_ID", OFTIntegerList, 6, 0,
1994 : "ADMIN_AREA_ID", OFTInteger, 6, 0, "CENSUS_CODE", OFTString, 7,
1995 : 0, "ADMIN_NAME", OFTString, 0, 0, "AREA_TYPE", OFTString, 2, 0,
1996 : "AREA_CODE", OFTString, 3, 0, "NON_TYPE_CODE", OFTString, 3, 0,
1997 : "NON_INLAND_AREA", OFTReal, 12, 3, "COLL_ID_REFS",
1998 : OFTIntegerList, 6, 0, NULL);
1999 : }
2000 0 : else if (GetProductId() == NPC_BASEDATA)
2001 : {
2002 0 : EstablishLayer(
2003 : "BASEDATA_POINT", wkbPoint, TranslateBasedataPoint, NRT_POINTREC,
2004 : nullptr, "POINT_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0,
2005 : "FEAT_CODE", OFTString, 4, 0, "PROPER_NAME", OFTString, 0, 0,
2006 : "FEATURE_NUMBER", OFTString, 0, 0, "COUNTY_NAME", OFTString, 0, 0,
2007 : "UNITARY_NAME", OFTString, 0, 0, "ORIENT", OFTRealList, 5, 1, NULL);
2008 :
2009 0 : EstablishLayer("BASEDATA_LINE", wkbLineString, TranslateBasedataLine,
2010 : NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0,
2011 : "FEAT_CODE", OFTString, 4, 0, "GEOM_ID", OFTInteger, 6,
2012 : 0, "PROPER_NAME", OFTString, 0, 0, "FEATURE_NUMBER",
2013 : OFTString, 0, 0, "RB", OFTString, 1, 0, NULL);
2014 :
2015 0 : EstablishLayer("BASEDATA_TEXT", wkbPoint, TranslateStrategiText,
2016 : NRT_TEXTREC, nullptr, "TEXT_ID", OFTInteger, 6, 0,
2017 : "FEAT_CODE", OFTString, 4, 0, "FONT", OFTInteger, 4, 0,
2018 : "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN", OFTInteger, 1, 0,
2019 : "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0,
2020 : "TEXT_HT_GROUND", OFTReal, 10, 3, NULL);
2021 :
2022 0 : EstablishLayer("BASEDATA_NODE", wkbNone, TranslateStrategiNode,
2023 : NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0,
2024 : "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS",
2025 : OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0,
2026 : "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL",
2027 : OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL);
2028 : }
2029 0 : else if (GetProductId() == NPC_OSCAR_ASSET ||
2030 0 : GetProductId() == NPC_OSCAR_TRAFFIC)
2031 : {
2032 0 : EstablishLayer("OSCAR_POINT", wkbPoint, TranslateOscarPoint,
2033 : NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0,
2034 : "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4,
2035 : 0, "OSODR", OFTString, 13, 0, "JUNCTION_NAME", OFTString,
2036 : 0, 0, "SETTLE_NAME", OFTString, 0, 0, NULL);
2037 :
2038 0 : EstablishLayer(
2039 : "OSCAR_LINE", wkbLineString, TranslateOscarLine, NRT_LINEREC,
2040 : nullptr, "LINE_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0,
2041 : "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13, 0,
2042 : "PROPER_NAME", OFTString, 0, 0, "LINE_LENGTH", OFTInteger, 5, 0,
2043 : "SOURCE", OFTString, 1, 0, "FORM_OF_WAY", OFTString, 1, 0,
2044 : "ROAD_NUM", OFTString, 0, 0, "TRUNK_ROAD", OFTString, 1, 0, NULL);
2045 :
2046 0 : EstablishLayer("OSCAR_NODE", wkbNone, TranslateStrategiNode,
2047 : NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0,
2048 : "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS",
2049 : OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0,
2050 : "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL",
2051 : OFTIntegerList, 1, 0, NULL);
2052 :
2053 0 : EstablishLayer("OSCAR_COMMENT", wkbNone, TranslateOscarComment,
2054 : NRT_COMMENT, nullptr, "RECORD_TYPE", OFTInteger, 2, 0,
2055 : "RECORD_ID", OFTString, 13, 0, "CHANGE_TYPE", OFTString,
2056 : 1, 0, NULL);
2057 : }
2058 0 : else if (GetProductId() == NPC_OSCAR_ROUTE)
2059 : {
2060 0 : EstablishLayer("OSCAR_ROUTE_POINT", wkbPoint, TranslateOscarRoutePoint,
2061 : NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0,
2062 : "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4,
2063 : 0, "OSODR", OFTString, 13, 0, "JUNCTION_NAME", OFTString,
2064 : 0, 0, "SETTLE_NAME", OFTString, 0, 0, "NUM_PARENTS",
2065 : OFTInteger, 2, 0, "PARENT_OSODR", OFTStringList, 13, 0,
2066 : "ROUNDABOUT", OFTString, 1, 0, NULL);
2067 :
2068 0 : EstablishLayer("OSCAR_ROUTE_LINE", wkbLineString,
2069 : TranslateOscarRouteLine, NRT_LINEREC, nullptr, "LINE_ID",
2070 : OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0,
2071 : "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13, 0,
2072 : "PROPER_NAME", OFTString, 0, 0, "LINE_LENGTH",
2073 : OFTInteger, 5, 0, "ROAD_NUM", OFTString, 0, 0,
2074 : "TRUNK_ROAD", OFTString, 1, 0, "NUM_PARENTS", OFTInteger,
2075 : 2, 0, "PARENT_OSODR", OFTStringList, 13, 0, NULL);
2076 :
2077 0 : EstablishLayer("OSCAR_ROUTE_NODE", wkbNone, TranslateStrategiNode,
2078 : NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0,
2079 : "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS",
2080 : OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0,
2081 : "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL",
2082 : OFTIntegerList, 1, 0, NULL);
2083 :
2084 0 : EstablishLayer("OSCAR_COMMENT", wkbNone, TranslateOscarComment,
2085 : NRT_COMMENT, nullptr, "RECORD_TYPE", OFTInteger, 2, 0,
2086 : "RECORD_ID", OFTString, 13, 0, "CHANGE_TYPE", OFTString,
2087 : 1, 0, NULL);
2088 : }
2089 0 : else if (GetProductId() == NPC_OSCAR_NETWORK)
2090 : {
2091 0 : EstablishLayer("OSCAR_NETWORK_POINT", wkbPoint,
2092 : TranslateOscarNetworkPoint, NRT_POINTREC, nullptr,
2093 : "POINT_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6,
2094 : 0, "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13,
2095 : 0, "JUNCTION_NAME", OFTString, 0, 0, "SETTLE_NAME",
2096 : OFTString, 0, 0, "ROUNDABOUT", OFTString, 1, 0, NULL);
2097 :
2098 0 : EstablishLayer("OSCAR_NETWORK_LINE", wkbLineString,
2099 : TranslateOscarNetworkLine, NRT_LINEREC, nullptr,
2100 : "LINE_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0,
2101 : "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13, 0,
2102 : "PROPER_NAME", OFTString, 0, 0, "LINE_LENGTH",
2103 : OFTInteger, 5, 0, "ROAD_NUM", OFTString, 0, 0, NULL);
2104 :
2105 0 : EstablishLayer("OSCAR_NETWORK_NODE", wkbNone, TranslateStrategiNode,
2106 : NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0,
2107 : "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS",
2108 : OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0,
2109 : "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL",
2110 : OFTIntegerList, 1, 0, NULL);
2111 :
2112 0 : EstablishLayer("OSCAR_COMMENT", wkbNone, TranslateOscarComment,
2113 : NRT_COMMENT, nullptr, "RECORD_TYPE", OFTInteger, 2, 0,
2114 : "RECORD_ID", OFTString, 13, 0, "CHANGE_TYPE", OFTString,
2115 : 1, 0, NULL);
2116 : }
2117 0 : else if (GetProductId() == NPC_ADDRESS_POINT)
2118 : {
2119 0 : EstablishLayer(
2120 : "ADDRESS_POINT", wkbPoint, TranslateAddressPoint, NRT_POINTREC,
2121 : nullptr, "POINT_ID", OFTInteger, 6, 0, "OSAPR", OFTString, 18, 0,
2122 : "ORGANISATION_NAME", OFTString, 0, 0, "DEPARTMENT_NAME", OFTString,
2123 : 0, 0, "PO_BOX", OFTString, 6, 0, "SUBBUILDING_NAME", OFTString, 0,
2124 : 0, "BUILDING_NAME", OFTString, 0, 0, "BUILDING_NUMBER", OFTInteger,
2125 : 4, 0, "DEPENDENT_THOROUGHFARE_NAME", OFTString, 0, 0,
2126 : "THOROUGHFARE_NAME", OFTString, 0, 0,
2127 : "DOUBLE_DEPENDENT_LOCALITY_NAME", OFTString, 0, 0,
2128 : "DEPENDENT_LOCALITY_NAME", OFTString, 0, 0, "POST_TOWN_NAME",
2129 : OFTString, 0, 0, "COUNTY_NAME", OFTString, 0, 0, "POSTCODE",
2130 : OFTString, 7, 0, "STATUS_FLAG", OFTString, 4, 0, "RM_VERSION_DATE",
2131 : OFTString, 8, 0, "CHG_TYPE", OFTString, 1, 0, "CHG_DATE", OFTString,
2132 : 6, 0, NULL);
2133 : }
2134 0 : else if (GetProductId() == NPC_CODE_POINT)
2135 : {
2136 0 : EstablishLayer(
2137 : "CODE_POINT", wkbPoint, TranslateCodePoint, NRT_POINTREC, nullptr,
2138 : "POINT_ID", OFTInteger, 6, 0, "UNIT_POSTCODE", OFTString, 7, 0,
2139 : "POSITIONAL_QUALITY", OFTInteger, 1, 0, "PO_BOX_INDICATOR",
2140 : OFTString, 1, 0, "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0,
2141 : "DELIVERY_POINTS", OFTInteger, 3, 0, "DOMESTIC_DELIVERY_POINTS",
2142 : OFTInteger, 3, 0, "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0,
2143 : "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0,
2144 : "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0,
2145 : "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, "RM_VERSION_DATA",
2146 : OFTString, 8, 0, NULL);
2147 : }
2148 0 : else if (GetProductId() == NPC_CODE_POINT_PLUS)
2149 : {
2150 0 : EstablishLayer(
2151 : "CODE_POINT_PLUS", wkbPoint, TranslateCodePoint, NRT_POINTREC,
2152 : nullptr, "POINT_ID", OFTInteger, 6, 0, "UNIT_POSTCODE", OFTString,
2153 : 7, 0, "POSITIONAL_QUALITY", OFTInteger, 1, 0, "PO_BOX_INDICATOR",
2154 : OFTString, 1, 0, "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0,
2155 : "DELIVERY_POINTS", OFTInteger, 3, 0, "DOMESTIC_DELIVERY_POINTS",
2156 : OFTInteger, 3, 0, "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0,
2157 : "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0,
2158 : "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0,
2159 : "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, "RM_VERSION_DATA",
2160 : OFTString, 8, 0, "NHS_REGIONAL_HEALTH_AUTHORITY", OFTString, 3, 0,
2161 : "NHS_HEALTH_AUTHORITY", OFTString, 3, 0, "ADMIN_COUNTY", OFTString,
2162 : 2, 0, "ADMIN_DISTRICT", OFTString, 2, 0, "ADMIN_WARD", OFTString, 2,
2163 : 0, NULL);
2164 : }
2165 : else // generic case
2166 : {
2167 0 : CPLAssert(GetProductId() == NPC_UNKNOWN);
2168 :
2169 0 : poDS->WorkupGeneric(this);
2170 : }
2171 : }
|