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