Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: S-57 Translator
4 : * Purpose: Implements methods to create OGRFeatureDefns for various
5 : * object classes, and primitive features.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, 2001, 2003 Frank Warmerdam
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 : #include "ogr_api.h"
17 : #include "s57.h"
18 :
19 : /************************************************************************/
20 : /* S57GenerateGeomFeatureDefn() */
21 : /************************************************************************/
22 :
23 37 : OGRFeatureDefn *S57GenerateDSIDFeatureDefn()
24 :
25 : {
26 37 : OGRFeatureDefn *poFDefn = new OGRFeatureDefn("DSID");
27 :
28 37 : poFDefn->SetGeomType(wkbNone);
29 37 : poFDefn->Reference();
30 :
31 : /* -------------------------------------------------------------------- */
32 : /* DSID fields. */
33 : /* -------------------------------------------------------------------- */
34 37 : OGRFieldDefn oField("", OFTInteger);
35 :
36 37 : oField.Set("DSID_EXPP", OFTInteger, 3, 0);
37 37 : poFDefn->AddFieldDefn(&oField);
38 :
39 37 : oField.Set("DSID_INTU", OFTInteger, 3, 0);
40 37 : poFDefn->AddFieldDefn(&oField);
41 :
42 37 : oField.Set("DSID_DSNM", OFTString, 0, 0);
43 37 : poFDefn->AddFieldDefn(&oField);
44 :
45 37 : oField.Set("DSID_EDTN", OFTString, 0, 0);
46 37 : poFDefn->AddFieldDefn(&oField);
47 :
48 37 : oField.Set("DSID_UPDN", OFTString, 0, 0);
49 37 : poFDefn->AddFieldDefn(&oField);
50 :
51 37 : oField.Set("DSID_UADT", OFTString, 8, 0);
52 37 : poFDefn->AddFieldDefn(&oField);
53 :
54 37 : oField.Set("DSID_ISDT", OFTString, 8, 0);
55 37 : poFDefn->AddFieldDefn(&oField);
56 :
57 37 : oField.Set("DSID_STED", OFTReal, 11, 6);
58 37 : poFDefn->AddFieldDefn(&oField);
59 :
60 37 : oField.Set("DSID_PRSP", OFTInteger, 3, 0);
61 37 : poFDefn->AddFieldDefn(&oField);
62 :
63 37 : oField.Set("DSID_PSDN", OFTString, 0, 0);
64 37 : poFDefn->AddFieldDefn(&oField);
65 :
66 37 : oField.Set("DSID_PRED", OFTString, 0, 0);
67 37 : poFDefn->AddFieldDefn(&oField);
68 :
69 37 : oField.Set("DSID_PROF", OFTInteger, 3, 0);
70 37 : poFDefn->AddFieldDefn(&oField);
71 :
72 37 : oField.Set("DSID_AGEN", OFTInteger, 5, 0);
73 37 : poFDefn->AddFieldDefn(&oField);
74 :
75 37 : oField.Set("DSID_COMT", OFTString, 0, 0);
76 37 : poFDefn->AddFieldDefn(&oField);
77 :
78 : /* -------------------------------------------------------------------- */
79 : /* DSSI fields. */
80 : /* -------------------------------------------------------------------- */
81 :
82 37 : oField.Set("DSSI_DSTR", OFTInteger, 3, 0);
83 37 : poFDefn->AddFieldDefn(&oField);
84 :
85 37 : oField.Set("DSSI_AALL", OFTInteger, 3, 0);
86 37 : poFDefn->AddFieldDefn(&oField);
87 :
88 37 : oField.Set("DSSI_NALL", OFTInteger, 3, 0);
89 37 : poFDefn->AddFieldDefn(&oField);
90 :
91 37 : oField.Set("DSSI_NOMR", OFTInteger, 10, 0);
92 37 : poFDefn->AddFieldDefn(&oField);
93 :
94 37 : oField.Set("DSSI_NOCR", OFTInteger, 10, 0);
95 37 : poFDefn->AddFieldDefn(&oField);
96 :
97 37 : oField.Set("DSSI_NOGR", OFTInteger, 10, 0);
98 37 : poFDefn->AddFieldDefn(&oField);
99 :
100 37 : oField.Set("DSSI_NOLR", OFTInteger, 10, 0);
101 37 : poFDefn->AddFieldDefn(&oField);
102 :
103 37 : oField.Set("DSSI_NOIN", OFTInteger, 10, 0);
104 37 : poFDefn->AddFieldDefn(&oField);
105 :
106 37 : oField.Set("DSSI_NOCN", OFTInteger, 10, 0);
107 37 : poFDefn->AddFieldDefn(&oField);
108 :
109 37 : oField.Set("DSSI_NOED", OFTInteger, 10, 0);
110 37 : poFDefn->AddFieldDefn(&oField);
111 :
112 37 : oField.Set("DSSI_NOFA", OFTInteger, 10, 0);
113 37 : poFDefn->AddFieldDefn(&oField);
114 :
115 : /* -------------------------------------------------------------------- */
116 : /* DSPM fields. */
117 : /* -------------------------------------------------------------------- */
118 :
119 37 : oField.Set("DSPM_HDAT", OFTInteger, 3, 0);
120 37 : poFDefn->AddFieldDefn(&oField);
121 :
122 37 : oField.Set("DSPM_VDAT", OFTInteger, 3, 0);
123 37 : poFDefn->AddFieldDefn(&oField);
124 :
125 37 : oField.Set("DSPM_SDAT", OFTInteger, 3, 0);
126 37 : poFDefn->AddFieldDefn(&oField);
127 :
128 37 : oField.Set("DSPM_CSCL", OFTInteger, 10, 0);
129 37 : poFDefn->AddFieldDefn(&oField);
130 :
131 37 : oField.Set("DSPM_DUNI", OFTInteger, 3, 0);
132 37 : poFDefn->AddFieldDefn(&oField);
133 :
134 37 : oField.Set("DSPM_HUNI", OFTInteger, 3, 0);
135 37 : poFDefn->AddFieldDefn(&oField);
136 :
137 37 : oField.Set("DSPM_PUNI", OFTInteger, 3, 0);
138 37 : poFDefn->AddFieldDefn(&oField);
139 :
140 37 : oField.Set("DSPM_COUN", OFTInteger, 3, 0);
141 37 : poFDefn->AddFieldDefn(&oField);
142 :
143 37 : oField.Set("DSPM_COMF", OFTInteger, 10, 0);
144 37 : poFDefn->AddFieldDefn(&oField);
145 :
146 37 : oField.Set("DSPM_SOMF", OFTInteger, 10, 0);
147 37 : poFDefn->AddFieldDefn(&oField);
148 :
149 37 : oField.Set("DSPM_COMT", OFTString, 0, 0);
150 37 : poFDefn->AddFieldDefn(&oField);
151 :
152 74 : return poFDefn;
153 : }
154 :
155 : /************************************************************************/
156 : /* S57GenerateGeomFeatureDefn() */
157 : /************************************************************************/
158 :
159 0 : OGRFeatureDefn *S57GenerateGeomFeatureDefn(OGRwkbGeometryType eGType,
160 : int nOptionFlags)
161 :
162 : {
163 0 : OGRFeatureDefn *poFDefn = nullptr;
164 :
165 0 : if (eGType == wkbPoint)
166 : {
167 0 : poFDefn = new OGRFeatureDefn("Point");
168 0 : poFDefn->SetGeomType(eGType);
169 : }
170 0 : else if (eGType == wkbLineString)
171 : {
172 0 : poFDefn = new OGRFeatureDefn("Line");
173 0 : poFDefn->SetGeomType(eGType);
174 : }
175 0 : else if (eGType == wkbPolygon)
176 : {
177 0 : poFDefn = new OGRFeatureDefn("Area");
178 0 : poFDefn->SetGeomType(eGType);
179 : }
180 0 : else if (eGType == wkbNone)
181 : {
182 0 : poFDefn = new OGRFeatureDefn("Meta");
183 0 : poFDefn->SetGeomType(eGType);
184 : }
185 0 : else if (eGType == wkbUnknown)
186 : {
187 0 : poFDefn = new OGRFeatureDefn("Generic");
188 0 : poFDefn->SetGeomType(eGType);
189 : }
190 : else
191 0 : return nullptr;
192 :
193 0 : poFDefn->Reference();
194 0 : S57GenerateStandardAttributes(poFDefn, nOptionFlags);
195 :
196 0 : return poFDefn;
197 : }
198 :
199 : /************************************************************************/
200 : /* S57GenerateVectorPrimitiveFeatureDefn() */
201 : /************************************************************************/
202 :
203 84 : OGRFeatureDefn *S57GenerateVectorPrimitiveFeatureDefn(int nRCNM,
204 : int /* nOptionFlags */)
205 : {
206 84 : OGRFeatureDefn *poFDefn = nullptr;
207 :
208 84 : if (nRCNM == RCNM_VI)
209 : {
210 21 : poFDefn = new OGRFeatureDefn(OGRN_VI);
211 21 : poFDefn->SetGeomType(wkbPoint);
212 : }
213 63 : else if (nRCNM == RCNM_VC)
214 : {
215 21 : poFDefn = new OGRFeatureDefn(OGRN_VC);
216 21 : poFDefn->SetGeomType(wkbPoint);
217 : }
218 42 : else if (nRCNM == RCNM_VE)
219 : {
220 21 : poFDefn = new OGRFeatureDefn(OGRN_VE);
221 21 : poFDefn->SetGeomType(wkbUnknown);
222 : }
223 21 : else if (nRCNM == RCNM_VF)
224 : {
225 21 : poFDefn = new OGRFeatureDefn(OGRN_VF);
226 21 : poFDefn->SetGeomType(wkbPolygon);
227 : }
228 : else
229 0 : return nullptr;
230 :
231 84 : poFDefn->Reference();
232 :
233 : /* -------------------------------------------------------------------- */
234 : /* Core vector primitive attributes */
235 : /* -------------------------------------------------------------------- */
236 84 : OGRFieldDefn oField("", OFTInteger);
237 :
238 84 : oField.Set("RCNM", OFTInteger, 3, 0);
239 84 : poFDefn->AddFieldDefn(&oField);
240 :
241 84 : oField.Set("RCID", OFTInteger, 8, 0);
242 84 : poFDefn->AddFieldDefn(&oField);
243 :
244 84 : oField.Set("RVER", OFTInteger, 2, 0);
245 84 : poFDefn->AddFieldDefn(&oField);
246 :
247 84 : oField.Set("RUIN", OFTInteger, 2, 0);
248 84 : poFDefn->AddFieldDefn(&oField);
249 :
250 : /* -------------------------------------------------------------------- */
251 : /* Geometric primitive attributes */
252 : /* -------------------------------------------------------------------- */
253 84 : oField.Set("POSACC", OFTReal, 10, 2);
254 84 : poFDefn->AddFieldDefn(&oField);
255 :
256 84 : oField.Set("QUAPOS", OFTInteger, 2, 0);
257 84 : poFDefn->AddFieldDefn(&oField);
258 :
259 : /* -------------------------------------------------------------------- */
260 : /* For lines we want to capture the point links for the first */
261 : /* and last nodes. */
262 : /* -------------------------------------------------------------------- */
263 84 : if (nRCNM == RCNM_VE)
264 : {
265 21 : oField.Set("NAME_RCNM_0", OFTInteger, 3, 0);
266 21 : poFDefn->AddFieldDefn(&oField);
267 :
268 21 : oField.Set("NAME_RCID_0", OFTInteger, 8, 0);
269 21 : poFDefn->AddFieldDefn(&oField);
270 :
271 21 : oField.Set("ORNT_0", OFTInteger, 3, 0);
272 21 : poFDefn->AddFieldDefn(&oField);
273 :
274 21 : oField.Set("USAG_0", OFTInteger, 3, 0);
275 21 : poFDefn->AddFieldDefn(&oField);
276 :
277 21 : oField.Set("TOPI_0", OFTInteger, 1, 0);
278 21 : poFDefn->AddFieldDefn(&oField);
279 :
280 21 : oField.Set("MASK_0", OFTInteger, 3, 0);
281 21 : poFDefn->AddFieldDefn(&oField);
282 :
283 21 : oField.Set("NAME_RCNM_1", OFTInteger, 3, 0);
284 21 : poFDefn->AddFieldDefn(&oField);
285 :
286 21 : oField.Set("NAME_RCID_1", OFTInteger, 8, 0);
287 21 : poFDefn->AddFieldDefn(&oField);
288 :
289 21 : oField.Set("ORNT_1", OFTInteger, 3, 0);
290 21 : poFDefn->AddFieldDefn(&oField);
291 :
292 21 : oField.Set("USAG_1", OFTInteger, 3, 0);
293 21 : poFDefn->AddFieldDefn(&oField);
294 :
295 21 : oField.Set("TOPI_1", OFTInteger, 1, 0);
296 21 : poFDefn->AddFieldDefn(&oField);
297 :
298 21 : oField.Set("MASK_1", OFTInteger, 3, 0);
299 21 : poFDefn->AddFieldDefn(&oField);
300 : }
301 :
302 84 : return poFDefn;
303 : }
304 :
305 : /************************************************************************/
306 : /* S57GenerateObjectClassDefn() */
307 : /************************************************************************/
308 :
309 : OGRFeatureDefn *
310 5281 : S57GenerateObjectClassDefn(S57ClassRegistrar *poCR,
311 : S57ClassContentExplorer *poClassContentExplorer,
312 : int nOBJL, int nOptionFlags)
313 :
314 : {
315 5281 : if (!poClassContentExplorer->SelectClass(nOBJL))
316 0 : return nullptr;
317 :
318 : /* -------------------------------------------------------------------- */
319 : /* Create the feature definition based on the object class */
320 : /* acronym. */
321 : /* -------------------------------------------------------------------- */
322 : OGRFeatureDefn *poFDefn =
323 5281 : new OGRFeatureDefn(poClassContentExplorer->GetAcronym());
324 5281 : poFDefn->Reference();
325 :
326 : /* -------------------------------------------------------------------- */
327 : /* Try and establish the geometry type. If more than one */
328 : /* geometry type is allowed we just fall back to wkbUnknown. */
329 : /* -------------------------------------------------------------------- */
330 5281 : char **papszGeomPrim = poClassContentExplorer->GetPrimitives();
331 5281 : if (CSLCount(papszGeomPrim) == 0)
332 : {
333 144 : poFDefn->SetGeomType(wkbNone);
334 : }
335 5137 : else if (CSLCount(papszGeomPrim) > 1)
336 : {
337 : // leave as unknown geometry type.
338 : }
339 3158 : else if (papszGeomPrim[0][0] == 'P')
340 : {
341 1018 : if (EQUAL(poClassContentExplorer->GetAcronym(), "SOUNDG"))
342 : {
343 35 : if (nOptionFlags & S57M_SPLIT_MULTIPOINT)
344 0 : poFDefn->SetGeomType(wkbPoint25D);
345 : else
346 35 : poFDefn->SetGeomType(wkbMultiPoint25D);
347 : }
348 : else
349 983 : poFDefn->SetGeomType(wkbPoint);
350 : }
351 2140 : else if (papszGeomPrim[0][0] == 'A')
352 : {
353 1577 : poFDefn->SetGeomType(wkbPolygon);
354 : }
355 563 : else if (papszGeomPrim[0][0] == 'L')
356 : {
357 : // unfortunately this could be a multilinestring
358 545 : poFDefn->SetGeomType(wkbUnknown);
359 : }
360 :
361 : /* -------------------------------------------------------------------- */
362 : /* Add the standard attributes. */
363 : /* -------------------------------------------------------------------- */
364 5281 : S57GenerateStandardAttributes(poFDefn, nOptionFlags);
365 :
366 : /* -------------------------------------------------------------------- */
367 : /* Add the attributes specific to this object class. */
368 : /* -------------------------------------------------------------------- */
369 5281 : char **papszAttrList = poClassContentExplorer->GetAttributeList();
370 :
371 113111 : for (int iAttr = 0;
372 113111 : papszAttrList != nullptr && papszAttrList[iAttr] != nullptr; iAttr++)
373 : {
374 107830 : const int iAttrIndex = poCR->FindAttrByAcronym(papszAttrList[iAttr]);
375 :
376 107830 : if (iAttrIndex == -1)
377 : {
378 54 : CPLDebug("S57", "Can't find attribute %s from class %s:%s.",
379 54 : papszAttrList[iAttr], poClassContentExplorer->GetAcronym(),
380 : poClassContentExplorer->GetDescription());
381 54 : continue;
382 : }
383 :
384 215552 : OGRFieldDefn oField(papszAttrList[iAttr], OFTInteger);
385 :
386 107776 : switch (poCR->GetAttrType(iAttrIndex))
387 : {
388 21649 : case SAT_ENUM:
389 : case SAT_INT:
390 21649 : oField.SetType(OFTInteger);
391 21649 : break;
392 :
393 12518 : case SAT_FLOAT:
394 12518 : oField.SetType(OFTReal);
395 12518 : break;
396 :
397 65424 : case SAT_CODE_STRING:
398 : case SAT_FREE_TEXT:
399 65424 : oField.SetType(OFTString);
400 65424 : break;
401 :
402 8005 : case SAT_LIST:
403 8005 : if ((nOptionFlags & S57M_LIST_AS_STRING))
404 : {
405 : // Legacy behavior
406 0 : oField.SetType(OFTString);
407 : }
408 : else
409 : {
410 8005 : oField.SetType(OFTStringList);
411 : }
412 8005 : break;
413 : }
414 :
415 107776 : poFDefn->AddFieldDefn(&oField);
416 : }
417 :
418 : /* -------------------------------------------------------------------- */
419 : /* Do we need to add DEPTH attributes to soundings? */
420 : /* -------------------------------------------------------------------- */
421 5281 : const char *pszClassAcronym = poClassContentExplorer->GetAcronym();
422 5281 : if (pszClassAcronym != nullptr && EQUAL(pszClassAcronym, "SOUNDG") &&
423 35 : (nOptionFlags & S57M_ADD_SOUNDG_DEPTH))
424 : {
425 0 : OGRFieldDefn oField("DEPTH", OFTReal);
426 0 : poFDefn->AddFieldDefn(&oField);
427 : }
428 :
429 5281 : return poFDefn;
430 : }
431 :
432 : /************************************************************************/
433 : /* S57GenerateStandardAttributes() */
434 : /* */
435 : /* Attach standard feature attributes to a feature definition. */
436 : /************************************************************************/
437 :
438 5281 : void S57GenerateStandardAttributes(OGRFeatureDefn *poFDefn, int nOptionFlags)
439 :
440 : {
441 10562 : OGRFieldDefn oField("", OFTInteger);
442 :
443 : /* -------------------------------------------------------------------- */
444 : /* RCID */
445 : /* -------------------------------------------------------------------- */
446 5281 : oField.Set("RCID", OFTInteger, 10, 0);
447 5281 : poFDefn->AddFieldDefn(&oField);
448 :
449 : /* -------------------------------------------------------------------- */
450 : /* PRIM */
451 : /* -------------------------------------------------------------------- */
452 5281 : oField.Set("PRIM", OFTInteger, 3, 0);
453 5281 : poFDefn->AddFieldDefn(&oField);
454 :
455 : /* -------------------------------------------------------------------- */
456 : /* GRUP */
457 : /* -------------------------------------------------------------------- */
458 5281 : oField.Set("GRUP", OFTInteger, 3, 0);
459 5281 : poFDefn->AddFieldDefn(&oField);
460 :
461 : /* -------------------------------------------------------------------- */
462 : /* OBJL */
463 : /* -------------------------------------------------------------------- */
464 5281 : oField.Set("OBJL", OFTInteger, 5, 0);
465 5281 : poFDefn->AddFieldDefn(&oField);
466 :
467 : /* -------------------------------------------------------------------- */
468 : /* RVER */
469 : /* -------------------------------------------------------------------- */
470 5281 : oField.Set("RVER", OFTInteger, 3, 0);
471 5281 : poFDefn->AddFieldDefn(&oField);
472 :
473 : /* -------------------------------------------------------------------- */
474 : /* AGEN */
475 : /* -------------------------------------------------------------------- */
476 5281 : oField.Set("AGEN", OFTInteger, 5, 0);
477 5281 : poFDefn->AddFieldDefn(&oField);
478 :
479 : /* -------------------------------------------------------------------- */
480 : /* FIDN */
481 : /* -------------------------------------------------------------------- */
482 5281 : oField.Set("FIDN", OFTInteger, 10, 0);
483 5281 : poFDefn->AddFieldDefn(&oField);
484 :
485 : /* -------------------------------------------------------------------- */
486 : /* FIDS */
487 : /* -------------------------------------------------------------------- */
488 5281 : oField.Set("FIDS", OFTInteger, 5, 0);
489 5281 : poFDefn->AddFieldDefn(&oField);
490 :
491 : /* -------------------------------------------------------------------- */
492 : /* LNAM - only generated when LNAM strings are being used. */
493 : /* -------------------------------------------------------------------- */
494 5281 : if (nOptionFlags & S57M_LNAM_REFS)
495 : {
496 5281 : oField.Set("LNAM", OFTString, 16, 0);
497 5281 : poFDefn->AddFieldDefn(&oField);
498 :
499 5281 : oField.Set("LNAM_REFS", OFTStringList, 16, 0);
500 5281 : poFDefn->AddFieldDefn(&oField);
501 :
502 5281 : oField.Set("FFPT_RIND", OFTIntegerList, 1, 0);
503 5281 : poFDefn->AddFieldDefn(&oField);
504 :
505 : // We should likely include FFPT_COMT here.
506 : }
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* Values from FSPT field. */
510 : /* -------------------------------------------------------------------- */
511 5281 : if (nOptionFlags & S57M_RETURN_LINKAGES)
512 : {
513 5118 : oField.Set("NAME_RCNM", OFTIntegerList, 3, 0);
514 5118 : poFDefn->AddFieldDefn(&oField);
515 :
516 5118 : oField.Set("NAME_RCID", OFTIntegerList, 10, 0);
517 5118 : poFDefn->AddFieldDefn(&oField);
518 :
519 5118 : oField.Set("ORNT", OFTIntegerList, 1, 0);
520 5118 : poFDefn->AddFieldDefn(&oField);
521 :
522 5118 : oField.Set("USAG", OFTIntegerList, 1, 0);
523 5118 : poFDefn->AddFieldDefn(&oField);
524 :
525 5118 : oField.Set("MASK", OFTIntegerList, 3, 0);
526 5118 : poFDefn->AddFieldDefn(&oField);
527 : }
528 5281 : }
|