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