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