OpenCPN Partial API docs
Loading...
Searching...
No Matches
ogrs57datasource.cpp
1/******************************************************************************
2 *
3 * Project: S-57 Translator
4 * Purpose: Implements OGRS57DataSource class
5 * Author: Frank Warmerdam, warmerda@home.com
6 *
7 ******************************************************************************
8 * Copyright (c) 1999, Frank Warmerdam
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ******************************************************************************
28 *
29 *
30 */
31
32#include "ogr_s57.h"
33#include "gdal/cpl_conv.h"
34#include "gdal/cpl_string.h"
35
36// S57ClassRegistrar *OGRS57DataSource::poRegistrar = NULL;
37
38/************************************************************************/
39/* OGRS57DataSource() */
40/************************************************************************/
41
42OGRS57DataSource::OGRS57DataSource()
43
44{
45 nLayers = 0;
46 papoLayers = NULL;
47
48 nModules = 0;
49 papoModules = NULL;
50 poWriter = NULL;
51
52 pszName = NULL;
53
54 // poSpatialRef = new OGRSpatialReference();
55 // poSpatialRef->SetWellKnownGeogCS( "WGS84" );
56
57 bExtentsSet = FALSE;
58
59 /* -------------------------------------------------------------------- */
60 /* Allow initialization of options from the environment. */
61 /* -------------------------------------------------------------------- */
62 papszOptions = NULL;
63
64 /*
65 if( CPLGetConfigOption("OGR_S57_OPTIONS",NULL) != NULL )
66 {
67 papszOptions =
68 CSLTokenizeStringComplex( CPLGetConfigOption("OGR_S57_OPTIONS",""),
69 ",", FALSE, FALSE );
70 }
71 */
72}
73
74/************************************************************************/
75/* ~OGRS57DataSource() */
76/************************************************************************/
77
78OGRS57DataSource::~OGRS57DataSource()
79
80{
81 int i;
82
83 for (i = 0; i < nLayers; i++) delete papoLayers[i];
84
85 CPLFree(papoLayers);
86
87 for (i = 0; i < nModules; i++) {
88 if (papoModules[i]) papoModules[i]->Close();
89 delete papoModules[i];
90 }
91 CPLFree(papoModules);
92
93 CPLFree(pszName);
94
95 CSLDestroy(papszOptions);
96
97 // delete poSpatialRef;
98
99 /*
100 if( poWriter != NULL )
101 {
102 poWriter->Close();
103 delete poWriter;
104 }
105 */
106}
107
108/************************************************************************/
109/* SetOptionList() */
110/************************************************************************/
111
112void OGRS57DataSource::SetOptionList(char **papszNewOptions)
113
114{
115 CSLDestroy(papszOptions);
116 papszOptions = CSLDuplicate(papszNewOptions);
117}
118
119/************************************************************************/
120/* GetOption() */
121/************************************************************************/
122
123const char *OGRS57DataSource::GetOption(const char *pszOption)
124
125{
126 return CSLFetchNameValue(papszOptions, pszOption);
127}
128
129/************************************************************************/
130/* TestCapability() */
131/************************************************************************/
132
133int OGRS57DataSource::TestCapability(const char *)
134
135{
136 return FALSE;
137}
138
139/************************************************************************/
140/* Open() */
141/************************************************************************/
142int OGRS57DataSource::Open(const char *pszFilename, int bTestOpen,
143 CallBackFunction pcallback)
144
145{
146 int iModule;
147 int error_return = 0;
148
149 pszName = CPLStrdup(pszFilename);
150
151 /* -------------------------------------------------------------------- */
152 /* Check a few bits of the header to see if it looks like an */
153 /* S57 file (really, if it looks like an ISO8211 file). */
154 /* -------------------------------------------------------------------- */
155 if (bTestOpen) {
156 FILE *fp;
157 char pachLeader[10];
158
159 fp = VSIFOpen(pszFilename, "rb");
160 if (fp == NULL) return BAD_FILE;
161
162 if (VSIFRead(pachLeader, 1, 10, fp) != 10 ||
163 (pachLeader[5] != '1' && pachLeader[5] != '2' &&
164 pachLeader[5] != '3') ||
165 pachLeader[6] != 'L' ||
166 (pachLeader[8] != '1' && pachLeader[8] != ' ')) {
167 VSIFClose(fp);
168 return BAD_HEADER;
169 }
170
171 VSIFClose(fp);
172 }
173
174 /* -------------------------------------------------------------------- */
175 /* Setup reader options. */
176 /* -------------------------------------------------------------------- */
177 char **papszReaderOptions = NULL;
178 S57Reader *poModule;
179
180 poModule = new S57Reader(pszFilename);
181
182 papszReaderOptions =
183 CSLSetNameValue(papszReaderOptions, S57O_LNAM_REFS, "ON");
184 if (GetOption(S57O_UPDATES) != NULL)
185 papszReaderOptions = CSLSetNameValue(papszReaderOptions, S57O_UPDATES,
186 GetOption(S57O_UPDATES));
187
188 if (GetOption(S57O_SPLIT_MULTIPOINT) != NULL)
189 papszReaderOptions =
190 CSLSetNameValue(papszReaderOptions, S57O_SPLIT_MULTIPOINT,
191 GetOption(S57O_SPLIT_MULTIPOINT));
192
193 if (GetOption(S57O_ADD_SOUNDG_DEPTH) != NULL)
194 papszReaderOptions =
195 CSLSetNameValue(papszReaderOptions, S57O_ADD_SOUNDG_DEPTH,
196 GetOption(S57O_ADD_SOUNDG_DEPTH));
197
198 if (GetOption(S57O_PRESERVE_EMPTY_NUMBERS) != NULL)
199 papszReaderOptions =
200 CSLSetNameValue(papszReaderOptions, S57O_PRESERVE_EMPTY_NUMBERS,
201 GetOption(S57O_PRESERVE_EMPTY_NUMBERS));
202
203 if (GetOption(S57O_RETURN_PRIMITIVES) != NULL)
204 papszReaderOptions =
205 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
206 GetOption(S57O_RETURN_PRIMITIVES));
207
208 if (GetOption(S57O_RETURN_LINKAGES) != NULL)
209 papszReaderOptions =
210 CSLSetNameValue(papszReaderOptions, S57O_RETURN_LINKAGES,
211 GetOption(S57O_RETURN_LINKAGES));
212
213 poModule->SetOptions(papszReaderOptions);
214 CSLDestroy(papszReaderOptions);
215
216 /* -------------------------------------------------------------------- */
217 /* Try opening. */
218 /* */
219 /* Eventually this should check for catalogs, and if found */
220 /* instantiate a whole series of modules. */
221 /* -------------------------------------------------------------------- */
222 if (!poModule->Open(bTestOpen)) {
223 delete poModule;
224
225 return BAD_OPEN;
226 }
227
228 nModules = 1;
229 papoModules = (S57Reader **)CPLMalloc(sizeof(void *));
230 papoModules[0] = poModule;
231
232 /* -------------------------------------------------------------------- */
233 /* Instantiate the class registrar if possible. */
234 /* -------------------------------------------------------------------- */
235 if (poRegistrar == NULL) {
236 poRegistrar = new S57ClassRegistrar();
237
238 if (!poRegistrar->LoadInfo(NULL, FALSE)) {
239 delete poRegistrar;
240 poRegistrar = NULL;
241 }
242 }
243
244 /* -------------------------------------------------------------------- */
245 /* Add the primitive layers if they are called for. */
246 /* -------------------------------------------------------------------- */
247
248 if (GetOption(S57O_RETURN_PRIMITIVES) != NULL) {
249 OGRFeatureDefn *poDefn;
250
251 poDefn = S57GenerateVectorPrimitiveFeatureDefn(RCNM_VI,
252 poModule->GetOptionFlags());
253 AddLayer(new OGRS57Layer(this, poDefn));
254
255 poDefn = S57GenerateVectorPrimitiveFeatureDefn(RCNM_VC,
256 poModule->GetOptionFlags());
257 AddLayer(new OGRS57Layer(this, poDefn));
258
259 poDefn = S57GenerateVectorPrimitiveFeatureDefn(RCNM_VE,
260 poModule->GetOptionFlags());
261 AddLayer(new OGRS57Layer(this, poDefn));
262
263 poDefn = S57GenerateVectorPrimitiveFeatureDefn(RCNM_VF,
264 poModule->GetOptionFlags());
265 AddLayer(new OGRS57Layer(this, poDefn));
266 }
267
268 /* -------------------------------------------------------------------- */
269 /* Initialize a layer for each type of geometry. Eventually */
270 /* we will do this by object class. */
271 /* -------------------------------------------------------------------- */
272 /*
273 if( poRegistrar == NULL )
274 {
275 OGRFeatureDefn *poDefn;
276
277 poDefn = S57GenerateGeomFeatureDefn( wkbPoint,
278 poModule->GetOptionFlags() );
279 AddLayer( new OGRS57Layer( this, poDefn ) );
280
281 poDefn = S57GenerateGeomFeatureDefn( wkbLineString,
282 poModule->GetOptionFlags() );
283 AddLayer( new OGRS57Layer( this, poDefn ) );
284
285 poDefn = S57GenerateGeomFeatureDefn( wkbPolygon,
286 poModule->GetOptionFlags() );
287 AddLayer( new OGRS57Layer( this, poDefn ) );
288
289 poDefn = S57GenerateGeomFeatureDefn( wkbNone,
290 poModule->GetOptionFlags() );
291 AddLayer( new OGRS57Layer( this, poDefn ) );
292 }
293 */
294 /* -------------------------------------------------------------------- */
295 /* Initialize a feature definition for each class that actually */
296 /* occurs in the dataset. */
297 /* -------------------------------------------------------------------- */
298 // else
299 {
300 OGRFeatureDefn *poDefn;
301 int *panClassCount;
302 int iClass, bGeneric = FALSE;
303
304 for (iModule = 0; iModule < nModules; iModule++) {
305 papoModules[iModule]->SetClassBased(poRegistrar);
306 }
307
308 for (iModule = 0; iModule < nModules; iModule++) {
309 int ingest_error = papoModules[iModule]->Ingest(pcallback);
310 if (ingest_error) error_return = ingest_error;
311 }
312
313 panClassCount = (int *)CPLCalloc(sizeof(int), MAX_CLASSES);
314
315 for (iModule = 0; iModule < nModules; iModule++)
316 papoModules[iModule]->CollectClassList(panClassCount, MAX_CLASSES);
317
318 for (iClass = 0; iClass < MAX_CLASSES; iClass++) {
319 if (pcallback) {
320 if (!(*pcallback)()) {
321 break;
322 ;
323 }
324 }
325
326 if (panClassCount[iClass] > 0) {
327 poDefn = S57GenerateObjectClassDefn(poRegistrar, iClass,
328 poModule->GetOptionFlags());
329
330 if (poDefn != NULL)
331 AddLayer(new OGRS57Layer(this, poDefn, panClassCount[iClass]));
332 else {
333 bGeneric = TRUE;
334 CPLDebug("S57", "Unable to find definition for OBJL=%d\n", iClass);
335 }
336 }
337 }
338 /*
339 if( bGeneric )
340 {
341 poDefn = S57GenerateGeomFeatureDefn( wkbUnknown,
342 poModule->GetOptionFlags()
343 ); AddLayer( new OGRS57Layer( this, poDefn ) );
344 }
345 */
346 CPLFree(panClassCount);
347 }
348
349 /* -------------------------------------------------------------------- */
350 /* Attach the layer definitions to each of the readers. */
351 /* -------------------------------------------------------------------- */
352 for (iModule = 0; iModule < nModules; iModule++) {
353 for (int iLayer = 0; iLayer < nLayers; iLayer++) {
354 papoModules[iModule]->AddFeatureDefn(papoLayers[iLayer]->GetLayerDefn());
355 }
356 }
357
358 return error_return;
359}
360
361/************************************************************************/
362/* OpenMin() */
363/************************************************************************/
364
365int OGRS57DataSource::OpenMin(const char *pszFilename, int bTestOpen)
366
367{
368 pszName = CPLStrdup(pszFilename);
369
370 /* -------------------------------------------------------------------- */
371 /* Check a few bits of the header to see if it looks like an */
372 /* S57 file (really, if it looks like an ISO8211 file). */
373 /* -------------------------------------------------------------------- */
374 if (bTestOpen) {
375 FILE *fp;
376 char pachLeader[10];
377
378 fp = VSIFOpen(pszFilename, "rb");
379 if (fp == NULL) return FALSE;
380
381 if (VSIFRead(pachLeader, 1, 10, fp) != 10 ||
382 (pachLeader[5] != '1' && pachLeader[5] != '2' &&
383 pachLeader[5] != '3') ||
384 pachLeader[6] != 'L' ||
385 (pachLeader[8] != '1' && pachLeader[8] != ' ')) {
386 VSIFClose(fp);
387 return FALSE;
388 }
389
390 VSIFClose(fp);
391 }
392
393 /* -------------------------------------------------------------------- */
394 /* Setup reader options. */
395 /* -------------------------------------------------------------------- */
396 char **papszReaderOptions = NULL;
397 S57Reader *poModule;
398
399 poModule = new S57Reader(pszFilename);
400
401 papszReaderOptions =
402 CSLSetNameValue(papszReaderOptions, S57O_LNAM_REFS, "ON");
403 if (GetOption(S57O_UPDATES) != NULL)
404 papszReaderOptions = CSLSetNameValue(papszReaderOptions, S57O_UPDATES,
405 GetOption(S57O_UPDATES));
406
407 if (GetOption(S57O_SPLIT_MULTIPOINT) != NULL)
408 papszReaderOptions =
409 CSLSetNameValue(papszReaderOptions, S57O_SPLIT_MULTIPOINT,
410 GetOption(S57O_SPLIT_MULTIPOINT));
411
412 if (GetOption(S57O_ADD_SOUNDG_DEPTH) != NULL)
413 papszReaderOptions =
414 CSLSetNameValue(papszReaderOptions, S57O_ADD_SOUNDG_DEPTH,
415 GetOption(S57O_ADD_SOUNDG_DEPTH));
416
417 if (GetOption(S57O_PRESERVE_EMPTY_NUMBERS) != NULL)
418 papszReaderOptions =
419 CSLSetNameValue(papszReaderOptions, S57O_PRESERVE_EMPTY_NUMBERS,
420 GetOption(S57O_PRESERVE_EMPTY_NUMBERS));
421
422 if (GetOption(S57O_RETURN_PRIMITIVES) != NULL)
423 papszReaderOptions =
424 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
425 GetOption(S57O_RETURN_PRIMITIVES));
426
427 if (GetOption(S57O_RETURN_LINKAGES) != NULL)
428 papszReaderOptions =
429 CSLSetNameValue(papszReaderOptions, S57O_RETURN_LINKAGES,
430 GetOption(S57O_RETURN_LINKAGES));
431
432 poModule->SetOptions(papszReaderOptions);
433 CSLDestroy(papszReaderOptions);
434
435 /* -------------------------------------------------------------------- */
436 /* Try opening. */
437 /* */
438 /* Eventually this should check for catalogs, and if found */
439 /* instantiate a whole series of modules. */
440 /* -------------------------------------------------------------------- */
441 if (!poModule->Open(bTestOpen)) {
442 delete poModule;
443
444 return FALSE;
445 }
446
447 nModules = 1;
448 papoModules = (S57Reader **)CPLMalloc(sizeof(void *));
449 papoModules[0] = poModule;
450
451 /* -------------------------------------------------------------------- */
452 /* Instantiate the class registrar if possible. */
453 /* -------------------------------------------------------------------- */
454 /*
455 if( poRegistrar == NULL )
456 {
457 poRegistrar = new S57ClassRegistrar();
458
459 if( !poRegistrar->LoadInfo( NULL, FALSE ) )
460 {
461 delete poRegistrar;
462 poRegistrar = NULL;
463 }
464 }
465 */
466 /* -------------------------------------------------------------------- */
467 /* Add the primitive layers if they are called for. */
468 /* -------------------------------------------------------------------- */
469 /*
470 if( GetOption( S57O_RETURN_PRIMITIVES ) != NULL )
471 {
472 OGRFeatureDefn *poDefn;
473
474 poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VI,
475 poModule->GetOptionFlags()); AddLayer( new OGRS57Layer( this, poDefn ) );
476
477 poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VC,
478 poModule->GetOptionFlags()); AddLayer( new OGRS57Layer( this, poDefn ) );
479
480 poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VE,
481 poModule->GetOptionFlags()); AddLayer( new OGRS57Layer( this, poDefn ) );
482
483 poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VF,
484 poModule->GetOptionFlags()); AddLayer( new OGRS57Layer( this, poDefn ) );
485 }
486 */
487 /* -------------------------------------------------------------------- */
488 /* Initialize a layer for each type of geometry. Eventually */
489 /* we will do this by object class. */
490 /* -------------------------------------------------------------------- */
491 /*
492 if( poRegistrar == NULL )
493 {
494 OGRFeatureDefn *poDefn;
495
496 poDefn = S57GenerateGeomFeatureDefn( wkbPoint,
497 poModule->GetOptionFlags() );
498 AddLayer( new OGRS57Layer( this, poDefn ) );
499
500 poDefn = S57GenerateGeomFeatureDefn( wkbLineString,
501 poModule->GetOptionFlags() );
502 AddLayer( new OGRS57Layer( this, poDefn ) );
503
504 poDefn = S57GenerateGeomFeatureDefn( wkbPolygon,
505 poModule->GetOptionFlags() );
506 AddLayer( new OGRS57Layer( this, poDefn ) );
507
508 poDefn = S57GenerateGeomFeatureDefn( wkbNone,
509 poModule->GetOptionFlags() );
510 AddLayer( new OGRS57Layer( this, poDefn ) );
511 }
512 */
513 /* -------------------------------------------------------------------- */
514 /* Initialize a feature definition for each class that actually */
515 /* occurs in the dataset. */
516 /* -------------------------------------------------------------------- */
517 // else
518 /*
519 {
520 OGRFeatureDefn *poDefn;
521 int *panClassCount;
522 int iClass, bGeneric = FALSE;
523
524 for( iModule = 0; iModule < nModules; iModule++ )
525 {
526 papoModules[iModule]->SetClassBased( poRegistrar );
527 }
528
529 panClassCount = (int *) CPLCalloc(sizeof(int),MAX_CLASSES);
530
531 for( iModule = 0; iModule < nModules; iModule++ )
532 papoModules[iModule]->CollectClassList(panClassCount,MAX_CLASSES);
533
534 for( iClass = 0; iClass < MAX_CLASSES; iClass++ )
535 {
536 if( panClassCount[iClass] > 0 )
537 {
538 poDefn =
539 S57GenerateObjectClassDefn( poRegistrar, iClass,
540 poModule->GetOptionFlags() );
541
542
543 if( poDefn != NULL )
544 AddLayer( new OGRS57Layer( this, poDefn,
545 panClassCount[iClass] ) );
546 else
547 {
548 bGeneric = TRUE;
549 CPLDebug( "S57",
550 "Unable to find definition for OBJL=%d\n",
551 iClass );
552 }
553
554 }
555 }
556
557 if( bGeneric )
558 {
559 poDefn = S57GenerateGeomFeatureDefn( wkbUnknown,
560 poModule->GetOptionFlags() );
561 AddLayer( new OGRS57Layer( this, poDefn ) );
562 }
563
564 CPLFree( panClassCount );
565 }
566 */
567 /* -------------------------------------------------------------------- */
568 /* Attach the layer definitions to each of the readers. */
569 /* -------------------------------------------------------------------- */
570 /*
571 for( iModule = 0; iModule < nModules; iModule++ )
572 {
573 for( int iLayer = 0; iLayer < nLayers; iLayer++ )
574 {
575 papoModules[iModule]->AddFeatureDefn(
576 papoLayers[iLayer]->GetLayerDefn() );
577 }
578 }
579 */
580 return TRUE;
581}
582
583/************************************************************************/
584/* GetLayer() */
585/************************************************************************/
586
587OGRLayer *OGRS57DataSource::GetLayer(int iLayer)
588
589{
590 if (iLayer < 0 || iLayer >= nLayers)
591 return NULL;
592 else
593 return papoLayers[iLayer];
594}
595
596/************************************************************************/
597/* AddLayer() */
598/************************************************************************/
599
600void OGRS57DataSource::AddLayer(OGRS57Layer *poNewLayer)
601
602{
603 papoLayers =
604 (OGRS57Layer **)CPLRealloc(papoLayers, sizeof(void *) * ++nLayers);
605
606 papoLayers[nLayers - 1] = poNewLayer;
607}
608
609/************************************************************************/
610/* GetModule() */
611/************************************************************************/
612
613S57Reader *OGRS57DataSource::GetModule(int i)
614
615{
616 if (i < 0 || i >= nModules)
617 return NULL;
618 else
619 return papoModules[i];
620}
621
622/************************************************************************/
623/* GetDSExtent() */
624/************************************************************************/
625
626OGRErr OGRS57DataSource::GetDSExtent(OGREnvelope *psExtent, int bForce)
627
628{
629 /* -------------------------------------------------------------------- */
630 /* If we have it, return it immediately. */
631 /* -------------------------------------------------------------------- */
632 if (bExtentsSet) {
633 *psExtent = oExtents;
634 return OGRERR_NONE;
635 }
636
637 if (nModules == 0) return OGRERR_FAILURE;
638
639 /* -------------------------------------------------------------------- */
640 /* Otherwise try asking each of the readers for it. */
641 /* -------------------------------------------------------------------- */
642 for (int iModule = 0; iModule < nModules; iModule++) {
643 OGREnvelope oModuleEnvelope;
644 OGRErr eErr;
645
646 eErr = papoModules[iModule]->GetExtent(&oModuleEnvelope, bForce);
647 if (eErr != OGRERR_NONE) return eErr;
648
649 if (iModule == 0)
650 oExtents = oModuleEnvelope;
651 else {
652 oExtents.MinX = MIN(oExtents.MinX, oModuleEnvelope.MinX);
653 oExtents.MaxX = MAX(oExtents.MaxX, oModuleEnvelope.MaxX);
654 oExtents.MinY = MIN(oExtents.MinY, oModuleEnvelope.MinY);
655 oExtents.MaxX = MAX(oExtents.MaxY, oModuleEnvelope.MaxY);
656 }
657 }
658
659 *psExtent = oExtents;
660 bExtentsSet = TRUE;
661
662 return OGRERR_NONE;
663}
Definition: s57.h:144