Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: S-57 Translator
4 : * Purpose: Implements OGRS57DataSource class
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1999, Frank Warmerdam
9 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 : #include "ogr_s57.h"
17 :
18 : #include <algorithm>
19 : #include <set>
20 :
21 : /************************************************************************/
22 : /* OGRS57DataSource() */
23 : /************************************************************************/
24 :
25 56 : OGRS57DataSource::OGRS57DataSource(char **papszOpenOptionsIn)
26 56 : : nLayers(0), papoLayers(nullptr), poSpatialRef(new OGRSpatialReference()),
27 : papszOptions(nullptr), nModules(0), papoModules(nullptr),
28 112 : poWriter(nullptr), poClassContentExplorer(nullptr), bExtentsSet(false)
29 : {
30 56 : poSpatialRef->SetWellKnownGeogCS("WGS84");
31 56 : poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
32 :
33 : /* -------------------------------------------------------------------- */
34 : /* Allow initialization of options from the environment. */
35 : /* -------------------------------------------------------------------- */
36 56 : const char *pszOptString = CPLGetConfigOption("OGR_S57_OPTIONS", nullptr);
37 :
38 56 : if (pszOptString != nullptr)
39 : {
40 4 : papszOptions =
41 4 : CSLTokenizeStringComplex(pszOptString, ",", FALSE, FALSE);
42 :
43 4 : if (papszOptions && *papszOptions)
44 : {
45 4 : CPLDebug("S57", "The following S57 options are being set:");
46 4 : char **papszCurOption = papszOptions;
47 16 : while (*papszCurOption)
48 12 : CPLDebug("S57", " %s", *papszCurOption++);
49 : }
50 : }
51 :
52 : /* -------------------------------------------------------------------- */
53 : /* And from open options. */
54 : /* -------------------------------------------------------------------- */
55 57 : for (char **papszIter = papszOpenOptionsIn; papszIter && *papszIter;
56 : ++papszIter)
57 : {
58 1 : char *pszKey = nullptr;
59 1 : const char *pszValue = CPLParseNameValue(*papszIter, &pszKey);
60 1 : if (pszKey && pszValue)
61 : {
62 1 : papszOptions = CSLSetNameValue(papszOptions, pszKey, pszValue);
63 : }
64 1 : CPLFree(pszKey);
65 : }
66 56 : }
67 :
68 : /************************************************************************/
69 : /* ~OGRS57DataSource() */
70 : /************************************************************************/
71 :
72 112 : OGRS57DataSource::~OGRS57DataSource()
73 :
74 : {
75 5458 : for (int i = 0; i < nLayers; i++)
76 5402 : delete papoLayers[i];
77 :
78 56 : CPLFree(papoLayers);
79 :
80 93 : for (int i = 0; i < nModules; i++)
81 37 : delete papoModules[i];
82 56 : CPLFree(papoModules);
83 :
84 56 : CSLDestroy(papszOptions);
85 :
86 56 : poSpatialRef->Release();
87 :
88 56 : if (poWriter != nullptr)
89 : {
90 19 : poWriter->Close();
91 19 : delete poWriter;
92 : }
93 56 : delete poClassContentExplorer;
94 112 : }
95 :
96 : /************************************************************************/
97 : /* SetOptionList() */
98 : /************************************************************************/
99 :
100 0 : void OGRS57DataSource::SetOptionList(char **papszNewOptions)
101 :
102 : {
103 0 : CSLDestroy(papszOptions);
104 0 : papszOptions = CSLDuplicate(papszNewOptions);
105 0 : }
106 :
107 : /************************************************************************/
108 : /* GetOption() */
109 : /************************************************************************/
110 :
111 451 : const char *OGRS57DataSource::GetOption(const char *pszOption)
112 :
113 : {
114 451 : return CSLFetchNameValue(papszOptions, pszOption);
115 : }
116 :
117 : /************************************************************************/
118 : /* TestCapability() */
119 : /************************************************************************/
120 :
121 73 : int OGRS57DataSource::TestCapability(const char *pszCap)
122 :
123 : {
124 73 : if (EQUAL(pszCap, ODsCZGeometries))
125 26 : return true;
126 :
127 47 : return false;
128 : }
129 :
130 : /************************************************************************/
131 : /* Open() */
132 : /************************************************************************/
133 :
134 37 : int OGRS57DataSource::Open(const char *pszFilename)
135 :
136 : {
137 : /* -------------------------------------------------------------------- */
138 : /* Setup reader options. */
139 : /* -------------------------------------------------------------------- */
140 37 : char **papszReaderOptions = nullptr;
141 :
142 37 : if (GetOption(S57O_LNAM_REFS) == nullptr)
143 : papszReaderOptions =
144 35 : CSLSetNameValue(papszReaderOptions, S57O_LNAM_REFS, "ON");
145 : else
146 2 : papszReaderOptions = CSLSetNameValue(papszReaderOptions, S57O_LNAM_REFS,
147 : GetOption(S57O_LNAM_REFS));
148 :
149 37 : if (GetOption(S57O_UPDATES) != nullptr)
150 0 : papszReaderOptions = CSLSetNameValue(papszReaderOptions, S57O_UPDATES,
151 : GetOption(S57O_UPDATES));
152 :
153 37 : if (GetOption(S57O_SPLIT_MULTIPOINT) != nullptr)
154 : papszReaderOptions =
155 0 : CSLSetNameValue(papszReaderOptions, S57O_SPLIT_MULTIPOINT,
156 : GetOption(S57O_SPLIT_MULTIPOINT));
157 :
158 37 : if (GetOption(S57O_ADD_SOUNDG_DEPTH) != nullptr)
159 : papszReaderOptions =
160 0 : CSLSetNameValue(papszReaderOptions, S57O_ADD_SOUNDG_DEPTH,
161 : GetOption(S57O_ADD_SOUNDG_DEPTH));
162 :
163 37 : if (GetOption(S57O_PRESERVE_EMPTY_NUMBERS) != nullptr)
164 : papszReaderOptions =
165 0 : CSLSetNameValue(papszReaderOptions, S57O_PRESERVE_EMPTY_NUMBERS,
166 : GetOption(S57O_PRESERVE_EMPTY_NUMBERS));
167 :
168 37 : if (GetOption(S57O_RETURN_PRIMITIVES) != nullptr)
169 : papszReaderOptions =
170 3 : CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
171 : GetOption(S57O_RETURN_PRIMITIVES));
172 :
173 37 : if (GetOption(S57O_RETURN_LINKAGES) != nullptr)
174 : papszReaderOptions =
175 2 : CSLSetNameValue(papszReaderOptions, S57O_RETURN_LINKAGES,
176 : GetOption(S57O_RETURN_LINKAGES));
177 :
178 37 : if (GetOption(S57O_RETURN_DSID) != nullptr)
179 0 : papszReaderOptions = CSLSetNameValue(
180 : papszReaderOptions, S57O_RETURN_DSID, GetOption(S57O_RETURN_DSID));
181 :
182 37 : if (GetOption(S57O_RECODE_BY_DSSI) != nullptr)
183 : papszReaderOptions =
184 0 : CSLSetNameValue(papszReaderOptions, S57O_RECODE_BY_DSSI,
185 : GetOption(S57O_RECODE_BY_DSSI));
186 :
187 37 : if (GetOption(S57O_LIST_AS_STRING) != nullptr)
188 : papszReaderOptions =
189 0 : CSLSetNameValue(papszReaderOptions, S57O_LIST_AS_STRING,
190 : GetOption(S57O_LIST_AS_STRING));
191 :
192 37 : S57Reader *poModule = new S57Reader(pszFilename);
193 37 : bool bRet = poModule->SetOptions(papszReaderOptions);
194 37 : CSLDestroy(papszReaderOptions);
195 :
196 37 : if (!bRet)
197 : {
198 0 : delete poModule;
199 0 : return FALSE;
200 : }
201 :
202 : /* -------------------------------------------------------------------- */
203 : /* Try opening. */
204 : /* */
205 : /* Eventually this should check for catalogs, and if found */
206 : /* instantiate a whole series of modules. */
207 : /* -------------------------------------------------------------------- */
208 37 : if (!poModule->Open(TRUE))
209 : {
210 0 : delete poModule;
211 :
212 0 : return FALSE;
213 : }
214 :
215 37 : bool bSuccess = true;
216 :
217 37 : nModules = 1;
218 37 : papoModules = static_cast<S57Reader **>(CPLMalloc(sizeof(void *)));
219 37 : papoModules[0] = poModule;
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Add the header layers if they are called for. */
223 : /* -------------------------------------------------------------------- */
224 37 : if (GetOption(S57O_RETURN_DSID) == nullptr ||
225 0 : CPLTestBool(GetOption(S57O_RETURN_DSID)))
226 : {
227 37 : OGRFeatureDefn *poDefn = S57GenerateDSIDFeatureDefn();
228 37 : AddLayer(new OGRS57Layer(this, poDefn));
229 : }
230 :
231 : /* -------------------------------------------------------------------- */
232 : /* Add the primitive layers if they are called for. */
233 : /* -------------------------------------------------------------------- */
234 37 : if (GetOption(S57O_RETURN_PRIMITIVES) != nullptr)
235 : {
236 3 : OGRFeatureDefn *poDefn = S57GenerateVectorPrimitiveFeatureDefn(
237 : RCNM_VI, poModule->GetOptionFlags());
238 3 : AddLayer(new OGRS57Layer(this, poDefn));
239 :
240 3 : poDefn = S57GenerateVectorPrimitiveFeatureDefn(
241 : RCNM_VC, poModule->GetOptionFlags());
242 3 : AddLayer(new OGRS57Layer(this, poDefn));
243 :
244 3 : poDefn = S57GenerateVectorPrimitiveFeatureDefn(
245 : RCNM_VE, poModule->GetOptionFlags());
246 3 : AddLayer(new OGRS57Layer(this, poDefn));
247 :
248 3 : poDefn = S57GenerateVectorPrimitiveFeatureDefn(
249 : RCNM_VF, poModule->GetOptionFlags());
250 3 : AddLayer(new OGRS57Layer(this, poDefn));
251 : }
252 :
253 : /* -------------------------------------------------------------------- */
254 : /* Initialize a layer for each type of geometry. Eventually */
255 : /* we will do this by object class. */
256 : /* -------------------------------------------------------------------- */
257 37 : if (OGRS57Driver::GetS57Registrar() == nullptr)
258 : {
259 : OGRFeatureDefn *poDefn =
260 0 : S57GenerateGeomFeatureDefn(wkbPoint, poModule->GetOptionFlags());
261 0 : AddLayer(new OGRS57Layer(this, poDefn));
262 :
263 0 : poDefn = S57GenerateGeomFeatureDefn(wkbLineString,
264 : poModule->GetOptionFlags());
265 0 : AddLayer(new OGRS57Layer(this, poDefn));
266 :
267 : poDefn =
268 0 : S57GenerateGeomFeatureDefn(wkbPolygon, poModule->GetOptionFlags());
269 0 : AddLayer(new OGRS57Layer(this, poDefn));
270 :
271 : poDefn =
272 0 : S57GenerateGeomFeatureDefn(wkbNone, poModule->GetOptionFlags());
273 0 : AddLayer(new OGRS57Layer(this, poDefn));
274 : }
275 :
276 : /* -------------------------------------------------------------------- */
277 : /* Initialize a feature definition for each class that actually */
278 : /* occurs in the dataset. */
279 : /* -------------------------------------------------------------------- */
280 : else
281 : {
282 37 : poClassContentExplorer =
283 37 : new S57ClassContentExplorer(OGRS57Driver::GetS57Registrar());
284 :
285 74 : for (int iModule = 0; iModule < nModules; iModule++)
286 37 : papoModules[iModule]->SetClassBased(OGRS57Driver::GetS57Registrar(),
287 : poClassContentExplorer);
288 :
289 74 : std::vector<int> anClassCount;
290 :
291 74 : for (int iModule = 0; iModule < nModules; iModule++)
292 : {
293 74 : bSuccess &= CPL_TO_BOOL(
294 37 : papoModules[iModule]->CollectClassList(anClassCount));
295 : }
296 :
297 37 : bool bGeneric = false;
298 :
299 22197 : for (unsigned int iClass = 0; iClass < anClassCount.size(); iClass++)
300 : {
301 22160 : if (anClassCount[iClass] > 0)
302 : {
303 187 : OGRFeatureDefn *poDefn = S57GenerateObjectClassDefn(
304 : OGRS57Driver::GetS57Registrar(), poClassContentExplorer,
305 : iClass, poModule->GetOptionFlags());
306 :
307 187 : if (poDefn != nullptr)
308 187 : AddLayer(
309 187 : new OGRS57Layer(this, poDefn, anClassCount[iClass]));
310 : else
311 : {
312 0 : bGeneric = true;
313 0 : CPLDebug("S57", "Unable to find definition for OBJL=%d\n",
314 : iClass);
315 : }
316 : }
317 : }
318 :
319 37 : if (bGeneric)
320 : {
321 0 : OGRFeatureDefn *poDefn = S57GenerateGeomFeatureDefn(
322 : wkbUnknown, poModule->GetOptionFlags());
323 0 : AddLayer(new OGRS57Layer(this, poDefn));
324 : }
325 : }
326 :
327 : /* -------------------------------------------------------------------- */
328 : /* Attach the layer definitions to each of the readers. */
329 : /* -------------------------------------------------------------------- */
330 74 : for (int iModule = 0; iModule < nModules; iModule++)
331 : {
332 273 : for (int iLayer = 0; iLayer < nLayers; iLayer++)
333 : {
334 236 : papoModules[iModule]->AddFeatureDefn(
335 236 : papoLayers[iLayer]->GetLayerDefn());
336 : }
337 : }
338 :
339 37 : return bSuccess;
340 : }
341 :
342 : /************************************************************************/
343 : /* GetLayer() */
344 : /************************************************************************/
345 :
346 4255 : OGRLayer *OGRS57DataSource::GetLayer(int iLayer)
347 :
348 : {
349 4255 : if (iLayer < 0 || iLayer >= nLayers)
350 2 : return nullptr;
351 :
352 4253 : return papoLayers[iLayer];
353 : }
354 :
355 : /************************************************************************/
356 : /* AddLayer() */
357 : /************************************************************************/
358 :
359 5402 : void OGRS57DataSource::AddLayer(OGRS57Layer *poNewLayer)
360 :
361 : {
362 10804 : papoLayers = static_cast<OGRS57Layer **>(
363 5402 : CPLRealloc(papoLayers, sizeof(void *) * ++nLayers));
364 :
365 5402 : papoLayers[nLayers - 1] = poNewLayer;
366 5402 : }
367 :
368 : /************************************************************************/
369 : /* GetModule() */
370 : /************************************************************************/
371 :
372 2881 : S57Reader *OGRS57DataSource::GetModule(int i)
373 :
374 : {
375 2881 : if (i < 0 || i >= nModules)
376 838 : return nullptr;
377 :
378 2043 : return papoModules[i];
379 : }
380 :
381 : /************************************************************************/
382 : /* GetDSExtent() */
383 : /************************************************************************/
384 :
385 72 : OGRErr OGRS57DataSource::GetDSExtent(OGREnvelope *psExtent, int bForce)
386 :
387 : {
388 : /* -------------------------------------------------------------------- */
389 : /* If we have it, return it immediately. */
390 : /* -------------------------------------------------------------------- */
391 72 : if (bExtentsSet)
392 : {
393 71 : *psExtent = oExtents;
394 71 : return OGRERR_NONE;
395 : }
396 :
397 1 : if (nModules == 0)
398 0 : return OGRERR_FAILURE;
399 :
400 : /* -------------------------------------------------------------------- */
401 : /* Otherwise try asking each of the readers for it. */
402 : /* -------------------------------------------------------------------- */
403 2 : for (int iModule = 0; iModule < nModules; iModule++)
404 : {
405 1 : OGREnvelope oModuleEnvelope;
406 :
407 1 : OGRErr eErr = papoModules[iModule]->GetExtent(&oModuleEnvelope, bForce);
408 1 : if (eErr != OGRERR_NONE)
409 0 : return eErr;
410 :
411 1 : if (iModule == 0)
412 1 : oExtents = oModuleEnvelope;
413 : else
414 : {
415 0 : oExtents.MinX = std::min(oExtents.MinX, oModuleEnvelope.MinX);
416 0 : oExtents.MaxX = std::max(oExtents.MaxX, oModuleEnvelope.MaxX);
417 0 : oExtents.MinY = std::min(oExtents.MinY, oModuleEnvelope.MinY);
418 0 : oExtents.MaxX = std::max(oExtents.MaxY, oModuleEnvelope.MaxY);
419 : }
420 : }
421 :
422 1 : *psExtent = oExtents;
423 1 : bExtentsSet = true;
424 :
425 1 : return OGRERR_NONE;
426 : }
427 :
428 : /************************************************************************/
429 : /* Create() */
430 : /* */
431 : /* Create a new S57 file, and represent it as a datasource. */
432 : /************************************************************************/
433 :
434 19 : int OGRS57DataSource::Create(const char *pszFilename, char **papszOptionsIn)
435 : {
436 : /* -------------------------------------------------------------------- */
437 : /* Instantiate the class registrar if possible. */
438 : /* -------------------------------------------------------------------- */
439 19 : if (OGRS57Driver::GetS57Registrar() == nullptr)
440 : {
441 0 : CPLError(CE_Failure, CPLE_AppDefined,
442 : "Unable to load s57objectclasses.csv. Unable to continue.");
443 0 : return FALSE;
444 : }
445 :
446 : /* -------------------------------------------------------------------- */
447 : /* Create the S-57 file with definition record. */
448 : /* -------------------------------------------------------------------- */
449 19 : poWriter = new S57Writer();
450 :
451 19 : if (!poWriter->CreateS57File(pszFilename))
452 1 : return FALSE;
453 :
454 18 : poClassContentExplorer =
455 18 : new S57ClassContentExplorer(OGRS57Driver::GetS57Registrar());
456 :
457 18 : poWriter->SetClassBased(OGRS57Driver::GetS57Registrar(),
458 : poClassContentExplorer);
459 :
460 : /* -------------------------------------------------------------------- */
461 : /* Add the primitive layers if they are called for. */
462 : /* -------------------------------------------------------------------- */
463 18 : int nOptionFlags = S57M_RETURN_LINKAGES | S57M_LNAM_REFS;
464 :
465 : OGRFeatureDefn *poDefn =
466 18 : S57GenerateVectorPrimitiveFeatureDefn(RCNM_VI, nOptionFlags);
467 18 : AddLayer(new OGRS57Layer(this, poDefn));
468 :
469 18 : poDefn = S57GenerateVectorPrimitiveFeatureDefn(RCNM_VC, nOptionFlags);
470 18 : AddLayer(new OGRS57Layer(this, poDefn));
471 :
472 18 : poDefn = S57GenerateVectorPrimitiveFeatureDefn(RCNM_VE, nOptionFlags);
473 18 : AddLayer(new OGRS57Layer(this, poDefn));
474 :
475 18 : poDefn = S57GenerateVectorPrimitiveFeatureDefn(RCNM_VF, nOptionFlags);
476 18 : AddLayer(new OGRS57Layer(this, poDefn));
477 :
478 : /* -------------------------------------------------------------------- */
479 : /* Initialize a feature definition for each object class. */
480 : /* -------------------------------------------------------------------- */
481 18 : poClassContentExplorer->Rewind();
482 18 : std::set<int> aoSetOBJL;
483 5112 : while (poClassContentExplorer->NextClass())
484 : {
485 5094 : const int nOBJL = poClassContentExplorer->GetOBJL();
486 : // Detect potential duplicates in the classes
487 5094 : if (aoSetOBJL.find(nOBJL) != aoSetOBJL.end())
488 : {
489 0 : CPLDebug("S57", "OBJL %d already registered!", nOBJL);
490 0 : continue;
491 : }
492 5094 : aoSetOBJL.insert(nOBJL);
493 5094 : poDefn = S57GenerateObjectClassDefn(OGRS57Driver::GetS57Registrar(),
494 : poClassContentExplorer, nOBJL,
495 : nOptionFlags);
496 :
497 5094 : AddLayer(new OGRS57Layer(this, poDefn, 0, nOBJL));
498 : }
499 :
500 : /* -------------------------------------------------------------------- */
501 : /* Write out "header" records. */
502 : /* -------------------------------------------------------------------- */
503 : int nEXPP =
504 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_EXPP",
505 : CPLSPrintf("%d", S57Writer::nDEFAULT_EXPP)));
506 : int nINTU =
507 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_INTU",
508 : CPLSPrintf("%d", S57Writer::nDEFAULT_INTU)));
509 18 : const char *pszEDTN = CSLFetchNameValue(papszOptionsIn, "S57_EDTN");
510 18 : const char *pszUPDN = CSLFetchNameValue(papszOptionsIn, "S57_UPDN");
511 18 : const char *pszUADT = CSLFetchNameValue(papszOptionsIn, "S57_UADT");
512 18 : const char *pszISDT = CSLFetchNameValue(papszOptionsIn, "S57_ISDT");
513 18 : const char *pszSTED = CSLFetchNameValue(papszOptionsIn, "S57_STED");
514 : int nAGEN =
515 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_AGEN",
516 : CPLSPrintf("%d", S57Writer::nDEFAULT_AGEN)));
517 18 : const char *pszCOMT = CSLFetchNameValue(papszOptionsIn, "S57_COMT");
518 18 : int nAALL = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_AALL", "0"));
519 18 : int nNALL = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_NALL", "0"));
520 18 : int nNOMR = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_NOMR", "0"));
521 18 : int nNOGR = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_NOGR", "0"));
522 18 : int nNOLR = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_NOLR", "0"));
523 18 : int nNOIN = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_NOIN", "0"));
524 18 : int nNOCN = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_NOCN", "0"));
525 18 : int nNOED = atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_NOED", "0"));
526 18 : poWriter->WriteDSID(nEXPP, nINTU, CPLGetFilename(pszFilename), pszEDTN,
527 : pszUPDN, pszUADT, pszISDT, pszSTED, nAGEN, pszCOMT,
528 : nAALL, nNALL, nNOMR, nNOGR, nNOLR, nNOIN, nNOCN, nNOED);
529 :
530 : int nHDAT =
531 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_HDAT",
532 : CPLSPrintf("%d", S57Writer::nDEFAULT_HDAT)));
533 : int nVDAT =
534 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_VDAT",
535 : CPLSPrintf("%d", S57Writer::nDEFAULT_VDAT)));
536 : int nSDAT =
537 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_SDAT",
538 : CPLSPrintf("%d", S57Writer::nDEFAULT_SDAT)));
539 : int nCSCL =
540 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_CSCL",
541 : CPLSPrintf("%d", S57Writer::nDEFAULT_CSCL)));
542 : int nCOMF =
543 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_COMF",
544 : CPLSPrintf("%d", S57Writer::nDEFAULT_COMF)));
545 : int nSOMF =
546 18 : atoi(CSLFetchNameValueDef(papszOptionsIn, "S57_SOMF",
547 : CPLSPrintf("%d", S57Writer::nDEFAULT_SOMF)));
548 18 : poWriter->WriteDSPM(nHDAT, nVDAT, nSDAT, nCSCL, nCOMF, nSOMF);
549 :
550 18 : return TRUE;
551 : }
|