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