/src/gdal/ogr/ogrsf_frmts/s57/s57writer.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: S-57 Translator |
4 | | * Purpose: Implements S57Writer class. |
5 | | * Author: Frank Warmerdam, warmerdam@pobox.com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2003, Frank Warmerdam |
9 | | * Copyright (c) 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_api.h" |
17 | | #include "s57.h" |
18 | | |
19 | | /************************************************************************/ |
20 | | /* S57Writer() */ |
21 | | /************************************************************************/ |
22 | | |
23 | | S57Writer::S57Writer() |
24 | 0 | : poModule(nullptr), nNext0001Index(0), poRegistrar(nullptr), |
25 | 0 | poClassContentExplorer(nullptr), m_nCOMF(nDEFAULT_COMF), |
26 | 0 | m_nSOMF(nDEFAULT_SOMF) |
27 | 0 | { |
28 | 0 | } |
29 | | |
30 | | /************************************************************************/ |
31 | | /* ~S57Writer() */ |
32 | | /************************************************************************/ |
33 | | |
34 | | S57Writer::~S57Writer() |
35 | | |
36 | 0 | { |
37 | 0 | Close(); |
38 | 0 | } |
39 | | |
40 | | /************************************************************************/ |
41 | | /* Close() */ |
42 | | /* */ |
43 | | /* Close the current S-57 dataset. */ |
44 | | /************************************************************************/ |
45 | | |
46 | | bool S57Writer::Close() |
47 | | |
48 | 0 | { |
49 | 0 | if (poModule != nullptr) |
50 | 0 | { |
51 | 0 | poModule->Close(); |
52 | 0 | delete poModule; |
53 | 0 | poModule = nullptr; |
54 | 0 | } |
55 | 0 | return true; |
56 | 0 | } |
57 | | |
58 | | /************************************************************************/ |
59 | | /* CreateS57File() */ |
60 | | /* */ |
61 | | /* Create a new output ISO8211 file with all the S-57 data */ |
62 | | /* definitions. */ |
63 | | /************************************************************************/ |
64 | | |
65 | | bool S57Writer::CreateS57File(const char *pszFilename) |
66 | | |
67 | 0 | { |
68 | | // TODO: What was oModule for if it was unused? |
69 | | // DDFModule oModule; |
70 | 0 | Close(); |
71 | |
|
72 | 0 | nNext0001Index = 1; |
73 | | |
74 | | /* -------------------------------------------------------------------- */ |
75 | | /* Create and initialize new module. */ |
76 | | /* -------------------------------------------------------------------- */ |
77 | 0 | poModule = new DDFModule(); |
78 | 0 | poModule->Initialize(); |
79 | | |
80 | | /* -------------------------------------------------------------------- */ |
81 | | /* Create the '0000' definition. */ |
82 | | /* -------------------------------------------------------------------- */ |
83 | 0 | DDFFieldDefn *poFDefn = new DDFFieldDefn(); |
84 | |
|
85 | 0 | poFDefn->Create("0000", "", |
86 | 0 | "0001DSIDDSIDDSSI0001DSPM0001VRIDVRIDATTVVRIDVRPCVRID" |
87 | 0 | "VRPTVRIDSGCCVRIDSG2DVRIDSG3D0001FRIDFRIDFOIDFRIDATTF" |
88 | 0 | "FRIDNATFFRIDFFPCFRIDFFPTFRIDFSPCFRIDFSPT", |
89 | 0 | dsc_elementary, dtc_char_string); |
90 | |
|
91 | 0 | poModule->AddField(poFDefn); |
92 | | |
93 | | /* -------------------------------------------------------------------- */ |
94 | | /* Create the '0001' definition. */ |
95 | | /* -------------------------------------------------------------------- */ |
96 | 0 | poFDefn = new DDFFieldDefn(); |
97 | |
|
98 | 0 | poFDefn->Create("0001", "ISO 8211 Record Identifier", "", dsc_elementary, |
99 | 0 | dtc_bit_string, "(b12)"); |
100 | |
|
101 | 0 | poModule->AddField(poFDefn); |
102 | | |
103 | | /* -------------------------------------------------------------------- */ |
104 | | /* Create the DSID field. */ |
105 | | /* -------------------------------------------------------------------- */ |
106 | 0 | poFDefn = new DDFFieldDefn(); |
107 | |
|
108 | 0 | poFDefn->Create("DSID", "Data set identification field", "", dsc_vector, |
109 | 0 | dtc_mixed_data_type); |
110 | |
|
111 | 0 | poFDefn->AddSubfield("RCNM", "b11"); |
112 | 0 | poFDefn->AddSubfield("RCID", "b14"); |
113 | 0 | poFDefn->AddSubfield("EXPP", "b11"); |
114 | 0 | poFDefn->AddSubfield("INTU", "b11"); |
115 | 0 | poFDefn->AddSubfield("DSNM", "A"); |
116 | 0 | poFDefn->AddSubfield("EDTN", "A"); |
117 | 0 | poFDefn->AddSubfield("UPDN", "A"); |
118 | 0 | poFDefn->AddSubfield("UADT", "A(8)"); |
119 | 0 | poFDefn->AddSubfield("ISDT", "A(8)"); |
120 | 0 | poFDefn->AddSubfield("STED", "R(4)"); |
121 | 0 | poFDefn->AddSubfield("PRSP", "b11"); |
122 | 0 | poFDefn->AddSubfield("PSDN", "A"); |
123 | 0 | poFDefn->AddSubfield("PRED", "A"); |
124 | 0 | poFDefn->AddSubfield("PROF", "b11"); |
125 | 0 | poFDefn->AddSubfield("AGEN", "b12"); |
126 | 0 | poFDefn->AddSubfield("COMT", "A"); |
127 | |
|
128 | 0 | poModule->AddField(poFDefn); |
129 | | |
130 | | /* -------------------------------------------------------------------- */ |
131 | | /* Create the DSSI field. */ |
132 | | /* -------------------------------------------------------------------- */ |
133 | 0 | poFDefn = new DDFFieldDefn(); |
134 | |
|
135 | 0 | poFDefn->Create("DSSI", "Data set structure information field", "", |
136 | 0 | dsc_vector, dtc_mixed_data_type); |
137 | |
|
138 | 0 | poFDefn->AddSubfield("DSTR", "b11"); |
139 | 0 | poFDefn->AddSubfield("AALL", "b11"); |
140 | 0 | poFDefn->AddSubfield("NALL", "b11"); |
141 | 0 | poFDefn->AddSubfield("NOMR", "b14"); |
142 | 0 | poFDefn->AddSubfield("NOCR", "b14"); |
143 | 0 | poFDefn->AddSubfield("NOGR", "b14"); |
144 | 0 | poFDefn->AddSubfield("NOLR", "b14"); |
145 | 0 | poFDefn->AddSubfield("NOIN", "b14"); |
146 | 0 | poFDefn->AddSubfield("NOCN", "b14"); |
147 | 0 | poFDefn->AddSubfield("NOED", "b14"); |
148 | 0 | poFDefn->AddSubfield("NOFA", "b14"); |
149 | |
|
150 | 0 | poModule->AddField(poFDefn); |
151 | | |
152 | | /* -------------------------------------------------------------------- */ |
153 | | /* Create the DSPM field. */ |
154 | | /* -------------------------------------------------------------------- */ |
155 | 0 | poFDefn = new DDFFieldDefn(); |
156 | |
|
157 | 0 | poFDefn->Create("DSPM", "Data set parameter field", "", dsc_vector, |
158 | 0 | dtc_mixed_data_type); |
159 | |
|
160 | 0 | poFDefn->AddSubfield("RCNM", "b11"); |
161 | 0 | poFDefn->AddSubfield("RCID", "b14"); |
162 | 0 | poFDefn->AddSubfield("HDAT", "b11"); |
163 | 0 | poFDefn->AddSubfield("VDAT", "b11"); |
164 | 0 | poFDefn->AddSubfield("SDAT", "b11"); |
165 | 0 | poFDefn->AddSubfield("CSCL", "b14"); |
166 | 0 | poFDefn->AddSubfield("DUNI", "b11"); |
167 | 0 | poFDefn->AddSubfield("HUNI", "b11"); |
168 | 0 | poFDefn->AddSubfield("PUNI", "b11"); |
169 | 0 | poFDefn->AddSubfield("COUN", "b11"); |
170 | 0 | poFDefn->AddSubfield("COMF", "b14"); |
171 | 0 | poFDefn->AddSubfield("SOMF", "b14"); |
172 | 0 | poFDefn->AddSubfield("COMT", "A"); |
173 | |
|
174 | 0 | poModule->AddField(poFDefn); |
175 | | |
176 | | /* -------------------------------------------------------------------- */ |
177 | | /* Create the VRID field. */ |
178 | | /* -------------------------------------------------------------------- */ |
179 | 0 | poFDefn = new DDFFieldDefn(); |
180 | |
|
181 | 0 | poFDefn->Create("VRID", "Vector record identifier field", "", dsc_vector, |
182 | 0 | dtc_mixed_data_type); |
183 | |
|
184 | 0 | poFDefn->AddSubfield("RCNM", "b11"); |
185 | 0 | poFDefn->AddSubfield("RCID", "b14"); |
186 | 0 | poFDefn->AddSubfield("RVER", "b12"); |
187 | 0 | poFDefn->AddSubfield("RUIN", "b11"); |
188 | |
|
189 | 0 | poModule->AddField(poFDefn); |
190 | | |
191 | | /* -------------------------------------------------------------------- */ |
192 | | /* Create the VRPC field. */ |
193 | | /* -------------------------------------------------------------------- */ |
194 | 0 | poFDefn = new DDFFieldDefn(); |
195 | |
|
196 | 0 | poFDefn->Create("VRPC", "Vector Record Pointer Control field", "", |
197 | 0 | dsc_vector, dtc_mixed_data_type); |
198 | |
|
199 | 0 | poFDefn->AddSubfield("VPUI", "b11"); |
200 | 0 | poFDefn->AddSubfield("VPIX", "b12"); |
201 | 0 | poFDefn->AddSubfield("NVPT", "b12"); |
202 | |
|
203 | 0 | poModule->AddField(poFDefn); |
204 | | |
205 | | /* -------------------------------------------------------------------- */ |
206 | | /* Create the VRPT field. */ |
207 | | /* -------------------------------------------------------------------- */ |
208 | 0 | poFDefn = new DDFFieldDefn(); |
209 | |
|
210 | 0 | poFDefn->Create("VRPT", "Vector record pointer field", "*", dsc_array, |
211 | 0 | dtc_mixed_data_type); |
212 | |
|
213 | 0 | poFDefn->AddSubfield("NAME", "B(40)"); |
214 | 0 | poFDefn->AddSubfield("ORNT", "b11"); |
215 | 0 | poFDefn->AddSubfield("USAG", "b11"); |
216 | 0 | poFDefn->AddSubfield("TOPI", "b11"); |
217 | 0 | poFDefn->AddSubfield("MASK", "b11"); |
218 | |
|
219 | 0 | poModule->AddField(poFDefn); |
220 | | |
221 | | /* -------------------------------------------------------------------- */ |
222 | | /* Create the ATTV field. */ |
223 | | /* -------------------------------------------------------------------- */ |
224 | 0 | poFDefn = new DDFFieldDefn(); |
225 | |
|
226 | 0 | poFDefn->Create("ATTV", "Vector record attribute field", "*", dsc_array, |
227 | 0 | dtc_mixed_data_type); |
228 | |
|
229 | 0 | poFDefn->AddSubfield("ATTL", "b12"); |
230 | 0 | poFDefn->AddSubfield("ATVL", "A"); |
231 | |
|
232 | 0 | poModule->AddField(poFDefn); |
233 | | |
234 | | /* -------------------------------------------------------------------- */ |
235 | | /* Create the SGCC field. */ |
236 | | /* -------------------------------------------------------------------- */ |
237 | 0 | poFDefn = new DDFFieldDefn(); |
238 | |
|
239 | 0 | poFDefn->Create("SGCC", "Coordinate Control Field", "", dsc_vector, |
240 | 0 | dtc_mixed_data_type); |
241 | |
|
242 | 0 | poFDefn->AddSubfield("CCUI", "b11"); |
243 | 0 | poFDefn->AddSubfield("CCIX", "b12"); |
244 | 0 | poFDefn->AddSubfield("CCNC", "b12"); |
245 | |
|
246 | 0 | poModule->AddField(poFDefn); |
247 | | |
248 | | /* -------------------------------------------------------------------- */ |
249 | | /* Create the SG2D field. */ |
250 | | /* -------------------------------------------------------------------- */ |
251 | 0 | poFDefn = new DDFFieldDefn(); |
252 | |
|
253 | 0 | poFDefn->Create("SG2D", "2-D coordinate field", "*", dsc_array, |
254 | 0 | dtc_bit_string); |
255 | |
|
256 | 0 | poFDefn->AddSubfield("YCOO", "b24"); |
257 | 0 | poFDefn->AddSubfield("XCOO", "b24"); |
258 | |
|
259 | 0 | poModule->AddField(poFDefn); |
260 | | |
261 | | /* -------------------------------------------------------------------- */ |
262 | | /* Create the SG3D field. */ |
263 | | /* -------------------------------------------------------------------- */ |
264 | 0 | poFDefn = new DDFFieldDefn(); |
265 | |
|
266 | 0 | poFDefn->Create("SG3D", "3-D coordinate (sounding array) field", "*", |
267 | 0 | dsc_array, dtc_bit_string); |
268 | |
|
269 | 0 | poFDefn->AddSubfield("YCOO", "b24"); |
270 | 0 | poFDefn->AddSubfield("XCOO", "b24"); |
271 | 0 | poFDefn->AddSubfield("VE3D", "b24"); |
272 | |
|
273 | 0 | poModule->AddField(poFDefn); |
274 | | |
275 | | /* -------------------------------------------------------------------- */ |
276 | | /* Create the FRID field. */ |
277 | | /* -------------------------------------------------------------------- */ |
278 | 0 | poFDefn = new DDFFieldDefn(); |
279 | |
|
280 | 0 | poFDefn->Create("FRID", "Feature record identifier field", "", dsc_vector, |
281 | 0 | dtc_mixed_data_type); |
282 | |
|
283 | 0 | poFDefn->AddSubfield("RCNM", "b11"); |
284 | 0 | poFDefn->AddSubfield("RCID", "b14"); |
285 | 0 | poFDefn->AddSubfield("PRIM", "b11"); |
286 | 0 | poFDefn->AddSubfield("GRUP", "b11"); |
287 | 0 | poFDefn->AddSubfield("OBJL", "b12"); |
288 | 0 | poFDefn->AddSubfield("RVER", "b12"); |
289 | 0 | poFDefn->AddSubfield("RUIN", "b11"); |
290 | |
|
291 | 0 | poModule->AddField(poFDefn); |
292 | | |
293 | | /* -------------------------------------------------------------------- */ |
294 | | /* Create the FOID field. */ |
295 | | /* -------------------------------------------------------------------- */ |
296 | 0 | poFDefn = new DDFFieldDefn(); |
297 | |
|
298 | 0 | poFDefn->Create("FOID", "Feature object identifier field", "", dsc_vector, |
299 | 0 | dtc_mixed_data_type); |
300 | |
|
301 | 0 | poFDefn->AddSubfield("AGEN", "b12"); |
302 | 0 | poFDefn->AddSubfield("FIDN", "b14"); |
303 | 0 | poFDefn->AddSubfield("FIDS", "b12"); |
304 | |
|
305 | 0 | poModule->AddField(poFDefn); |
306 | | |
307 | | /* -------------------------------------------------------------------- */ |
308 | | /* Create the ATTF field. */ |
309 | | /* -------------------------------------------------------------------- */ |
310 | 0 | poFDefn = new DDFFieldDefn(); |
311 | |
|
312 | 0 | poFDefn->Create("ATTF", "Feature record attribute field", "*", dsc_array, |
313 | 0 | dtc_mixed_data_type); |
314 | |
|
315 | 0 | poFDefn->AddSubfield("ATTL", "b12"); |
316 | 0 | poFDefn->AddSubfield("ATVL", "A"); |
317 | |
|
318 | 0 | poModule->AddField(poFDefn); |
319 | | |
320 | | /* -------------------------------------------------------------------- */ |
321 | | /* Create the NATF field. */ |
322 | | /* -------------------------------------------------------------------- */ |
323 | 0 | poFDefn = new DDFFieldDefn(); |
324 | |
|
325 | 0 | poFDefn->Create("NATF", "Feature record national attribute field", "*", |
326 | 0 | dsc_array, dtc_mixed_data_type); |
327 | |
|
328 | 0 | poFDefn->AddSubfield("ATTL", "b12"); |
329 | 0 | poFDefn->AddSubfield("ATVL", "A"); |
330 | |
|
331 | 0 | poModule->AddField(poFDefn); |
332 | | |
333 | | /* -------------------------------------------------------------------- */ |
334 | | /* Create the FFPC field. */ |
335 | | /* -------------------------------------------------------------------- */ |
336 | 0 | poFDefn = new DDFFieldDefn(); |
337 | |
|
338 | 0 | poFDefn->Create("FFPC", |
339 | 0 | "Feature record to feature object pointer control field", |
340 | 0 | "", dsc_vector, dtc_mixed_data_type); |
341 | |
|
342 | 0 | poFDefn->AddSubfield("FFUI", "b11"); |
343 | 0 | poFDefn->AddSubfield("FFIX", "b12"); |
344 | 0 | poFDefn->AddSubfield("NFPT", "b12"); |
345 | |
|
346 | 0 | poModule->AddField(poFDefn); |
347 | | |
348 | | /* -------------------------------------------------------------------- */ |
349 | | /* Create the FFPT field. */ |
350 | | /* -------------------------------------------------------------------- */ |
351 | 0 | poFDefn = new DDFFieldDefn(); |
352 | |
|
353 | 0 | poFDefn->Create("FFPT", "Feature record to feature object pointer field", |
354 | 0 | "*", dsc_array, dtc_mixed_data_type); |
355 | |
|
356 | 0 | poFDefn->AddSubfield("LNAM", "B(64)"); |
357 | 0 | poFDefn->AddSubfield("RIND", "b11"); |
358 | 0 | poFDefn->AddSubfield("COMT", "A"); |
359 | |
|
360 | 0 | poModule->AddField(poFDefn); |
361 | | |
362 | | /* -------------------------------------------------------------------- */ |
363 | | /* Create the FSPC field. */ |
364 | | /* -------------------------------------------------------------------- */ |
365 | 0 | poFDefn = new DDFFieldDefn(); |
366 | |
|
367 | 0 | poFDefn->Create("FSPC", |
368 | 0 | "Feature record to spatial record pointer control field", |
369 | 0 | "", dsc_vector, dtc_mixed_data_type); |
370 | |
|
371 | 0 | poFDefn->AddSubfield("FSUI", "b11"); |
372 | 0 | poFDefn->AddSubfield("FSIX", "b12"); |
373 | 0 | poFDefn->AddSubfield("NSPT", "b12"); |
374 | |
|
375 | 0 | poModule->AddField(poFDefn); |
376 | | |
377 | | /* -------------------------------------------------------------------- */ |
378 | | /* Create the FSPT field. */ |
379 | | /* -------------------------------------------------------------------- */ |
380 | 0 | poFDefn = new DDFFieldDefn(); |
381 | |
|
382 | 0 | poFDefn->Create("FSPT", "Feature record to spatial record pointer field", |
383 | 0 | "*", dsc_array, dtc_mixed_data_type); |
384 | |
|
385 | 0 | poFDefn->AddSubfield("NAME", "B(40)"); |
386 | 0 | poFDefn->AddSubfield("ORNT", "b11"); |
387 | 0 | poFDefn->AddSubfield("USAG", "b11"); |
388 | 0 | poFDefn->AddSubfield("MASK", "b11"); |
389 | |
|
390 | 0 | poModule->AddField(poFDefn); |
391 | | |
392 | | /* -------------------------------------------------------------------- */ |
393 | | /* Create file. */ |
394 | | /* -------------------------------------------------------------------- */ |
395 | 0 | if (!poModule->Create(pszFilename)) |
396 | 0 | { |
397 | 0 | delete poModule; |
398 | 0 | poModule = nullptr; |
399 | 0 | return false; |
400 | 0 | } |
401 | | |
402 | 0 | return true; |
403 | 0 | } |
404 | | |
405 | | /************************************************************************/ |
406 | | /* WriteDSID() */ |
407 | | /************************************************************************/ |
408 | | |
409 | | bool S57Writer::WriteDSID(int nEXPP, int nINTU, const char *pszDSNM, |
410 | | const char *pszEDTN, const char *pszUPDN, |
411 | | const char *pszUADT, const char *pszISDT, |
412 | | const char *pszSTED, int nAGEN, const char *pszCOMT, |
413 | | int nAALL, int nNALL, int nNOMR, int nNOGR, int nNOLR, |
414 | | int nNOIN, int nNOCN, int nNOED) |
415 | | |
416 | 0 | { |
417 | | /* -------------------------------------------------------------------- */ |
418 | | /* Default values. */ |
419 | | /* -------------------------------------------------------------------- */ |
420 | 0 | if (pszDSNM == nullptr) |
421 | 0 | pszDSNM = ""; |
422 | 0 | if (pszEDTN == nullptr) |
423 | 0 | pszEDTN = "2"; |
424 | 0 | if (pszUPDN == nullptr) |
425 | 0 | pszUPDN = "0"; |
426 | 0 | if (pszISDT == nullptr) |
427 | 0 | pszISDT = "20030801"; |
428 | 0 | if (pszUADT == nullptr) |
429 | 0 | pszUADT = pszISDT; |
430 | 0 | if (pszSTED == nullptr) |
431 | 0 | pszSTED = "03.1"; |
432 | 0 | if (pszCOMT == nullptr) |
433 | 0 | pszCOMT = ""; |
434 | | |
435 | | /* -------------------------------------------------------------------- */ |
436 | | /* Add the DSID field. */ |
437 | | /* -------------------------------------------------------------------- */ |
438 | 0 | DDFRecord *poRec = MakeRecord(); |
439 | | |
440 | | // DDFField *poField = |
441 | 0 | poRec->AddField(poModule->FindFieldDefn("DSID")); |
442 | |
|
443 | 0 | poRec->SetIntSubfield("DSID", 0, "RCNM", 0, 10); |
444 | 0 | poRec->SetIntSubfield("DSID", 0, "RCID", 0, 1); |
445 | 0 | poRec->SetIntSubfield("DSID", 0, "EXPP", 0, nEXPP); |
446 | 0 | poRec->SetIntSubfield("DSID", 0, "INTU", 0, nINTU); |
447 | 0 | poRec->SetStringSubfield("DSID", 0, "DSNM", 0, pszDSNM); |
448 | 0 | poRec->SetStringSubfield("DSID", 0, "EDTN", 0, pszEDTN); |
449 | 0 | poRec->SetStringSubfield("DSID", 0, "UPDN", 0, pszUPDN); |
450 | 0 | poRec->SetStringSubfield("DSID", 0, "UADT", 0, pszUADT); |
451 | 0 | poRec->SetStringSubfield("DSID", 0, "ISDT", 0, pszISDT); |
452 | 0 | poRec->SetStringSubfield("DSID", 0, "STED", 0, pszSTED); |
453 | 0 | poRec->SetIntSubfield("DSID", 0, "PRSP", 0, 1); |
454 | 0 | poRec->SetStringSubfield("DSID", 0, "PSDN", 0, ""); |
455 | 0 | poRec->SetStringSubfield("DSID", 0, "PRED", 0, "2.0"); |
456 | 0 | poRec->SetIntSubfield("DSID", 0, "PROF", 0, 1); |
457 | 0 | poRec->SetIntSubfield("DSID", 0, "AGEN", 0, nAGEN); |
458 | 0 | poRec->SetStringSubfield("DSID", 0, "COMT", 0, pszCOMT); |
459 | | |
460 | | /* -------------------------------------------------------------------- */ |
461 | | /* Add the DSSI record. Eventually we will need to return and */ |
462 | | /* correct these when we are finished writing. */ |
463 | | /* -------------------------------------------------------------------- */ |
464 | | /* poField = */ poRec->AddField(poModule->FindFieldDefn("DSSI")); |
465 | |
|
466 | 0 | poRec->SetIntSubfield("DSSI", 0, "DSTR", 0, 2); // "Chain node" |
467 | 0 | poRec->SetIntSubfield("DSSI", 0, "AALL", 0, nAALL); |
468 | 0 | poRec->SetIntSubfield("DSSI", 0, "NALL", 0, nNALL); |
469 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOMR", 0, nNOMR); // Meta records |
470 | | // Cartographic records are not permitted in ENC. |
471 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOCR", 0, 0); |
472 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOGR", 0, nNOGR); // Geo records |
473 | | // Collection records. |
474 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOLR", 0, nNOLR); |
475 | | // Isolated node records. |
476 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOIN", 0, nNOIN); |
477 | | // Connected node records. |
478 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOCN", 0, nNOCN); |
479 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOED", 0, nNOED); // Edge records |
480 | | // Face are not permitted in chain node structure. |
481 | 0 | poRec->SetIntSubfield("DSSI", 0, "NOFA", 0, 0); |
482 | | |
483 | | /* -------------------------------------------------------------------- */ |
484 | | /* Write out the record. */ |
485 | | /* -------------------------------------------------------------------- */ |
486 | 0 | poRec->Write(); |
487 | 0 | delete poRec; |
488 | |
|
489 | 0 | return true; |
490 | 0 | } |
491 | | |
492 | | /************************************************************************/ |
493 | | /* WriteDSPM() */ |
494 | | /************************************************************************/ |
495 | | |
496 | | bool S57Writer::WriteDSPM(int nHDAT, int nVDAT, int nSDAT, int nCSCL, int nCOMF, |
497 | | int nSOMF) |
498 | | |
499 | 0 | { |
500 | 0 | m_nCOMF = nCOMF; |
501 | 0 | m_nSOMF = nSOMF; |
502 | | |
503 | | /* -------------------------------------------------------------------- */ |
504 | | /* Add the DSID field. */ |
505 | | /* -------------------------------------------------------------------- */ |
506 | 0 | DDFRecord *poRec = MakeRecord(); |
507 | | |
508 | | // DDFField *poField = |
509 | 0 | poRec->AddField(poModule->FindFieldDefn("DSPM")); |
510 | |
|
511 | 0 | poRec->SetIntSubfield("DSPM", 0, "RCNM", 0, 20); |
512 | 0 | poRec->SetIntSubfield("DSPM", 0, "RCID", 0, 1); |
513 | | // Must be 2 for ENC. |
514 | 0 | poRec->SetIntSubfield("DSPM", 0, "HDAT", 0, nHDAT); |
515 | 0 | poRec->SetIntSubfield("DSPM", 0, "VDAT", 0, nVDAT); |
516 | 0 | poRec->SetIntSubfield("DSPM", 0, "SDAT", 0, nSDAT); |
517 | 0 | poRec->SetIntSubfield("DSPM", 0, "CSCL", 0, nCSCL); |
518 | 0 | poRec->SetIntSubfield("DSPM", 0, "DUNI", 0, 1); |
519 | 0 | poRec->SetIntSubfield("DSPM", 0, "HUNI", 0, 1); |
520 | 0 | poRec->SetIntSubfield("DSPM", 0, "PUNI", 0, 1); |
521 | 0 | poRec->SetIntSubfield("DSPM", 0, "COUN", 0, 1); |
522 | 0 | poRec->SetIntSubfield("DSPM", 0, "COMF", 0, nCOMF); |
523 | 0 | poRec->SetIntSubfield("DSPM", 0, "SOMF", 0, nSOMF); |
524 | | |
525 | | /* -------------------------------------------------------------------- */ |
526 | | /* Write out the record. */ |
527 | | /* -------------------------------------------------------------------- */ |
528 | 0 | poRec->Write(); |
529 | 0 | delete poRec; |
530 | |
|
531 | 0 | return true; |
532 | 0 | } |
533 | | |
534 | | /************************************************************************/ |
535 | | /* MakeRecord() */ |
536 | | /* */ |
537 | | /* Create a new empty record, and append a 0001 field with a */ |
538 | | /* properly set record index in it. */ |
539 | | /************************************************************************/ |
540 | | |
541 | | DDFRecord *S57Writer::MakeRecord() |
542 | | |
543 | 0 | { |
544 | 0 | unsigned char abyData[2] = { |
545 | 0 | static_cast<unsigned char>(nNext0001Index % 256), |
546 | 0 | static_cast<unsigned char>(nNext0001Index / 256)}; |
547 | |
|
548 | 0 | DDFRecord *poRec = new DDFRecord(poModule); |
549 | 0 | DDFField *poField = poRec->AddField(poModule->FindFieldDefn("0001")); |
550 | 0 | poRec->SetFieldRaw(poField, 0, (const char *)abyData, 2); |
551 | |
|
552 | 0 | nNext0001Index++; |
553 | |
|
554 | 0 | return poRec; |
555 | 0 | } |
556 | | |
557 | | /************************************************************************/ |
558 | | /* WriteGeometry() */ |
559 | | /************************************************************************/ |
560 | | |
561 | | bool S57Writer::WriteGeometry(DDFRecord *poRec, int nVertCount, |
562 | | const double *padfX, const double *padfY, |
563 | | const double *padfZ) |
564 | | |
565 | 0 | { |
566 | 0 | const char *pszFieldName = "SG2D"; |
567 | |
|
568 | 0 | if (padfZ != nullptr) |
569 | 0 | pszFieldName = "SG3D"; |
570 | |
|
571 | 0 | DDFField *poField = poRec->AddField(poModule->FindFieldDefn(pszFieldName)); |
572 | |
|
573 | 0 | const int nRawDataSize = padfZ ? 12 * nVertCount : 8 * nVertCount; |
574 | |
|
575 | 0 | unsigned char *pabyRawData = |
576 | 0 | static_cast<unsigned char *>(CPLMalloc(nRawDataSize)); |
577 | |
|
578 | 0 | for (int i = 0; i < nVertCount; i++) |
579 | 0 | { |
580 | 0 | const GInt32 nXCOO = |
581 | 0 | CPL_LSBWORD32(static_cast<GInt32>(floor(padfX[i] * m_nCOMF + 0.5))); |
582 | 0 | const GInt32 nYCOO = |
583 | 0 | CPL_LSBWORD32(static_cast<GInt32>(floor(padfY[i] * m_nCOMF + 0.5))); |
584 | |
|
585 | 0 | if (padfZ == nullptr) |
586 | 0 | { |
587 | 0 | memcpy(pabyRawData + i * 8, &nYCOO, 4); |
588 | 0 | memcpy(pabyRawData + i * 8 + 4, &nXCOO, 4); |
589 | 0 | } |
590 | 0 | else |
591 | 0 | { |
592 | 0 | const GInt32 nVE3D = CPL_LSBWORD32( |
593 | 0 | static_cast<GInt32>(floor(padfZ[i] * m_nSOMF + 0.5))); |
594 | 0 | memcpy(pabyRawData + i * 12, &nYCOO, 4); |
595 | 0 | memcpy(pabyRawData + i * 12 + 4, &nXCOO, 4); |
596 | 0 | memcpy(pabyRawData + i * 12 + 8, &nVE3D, 4); |
597 | 0 | } |
598 | 0 | } |
599 | |
|
600 | 0 | const bool nSuccess = CPL_TO_BOOL(poRec->SetFieldRaw( |
601 | 0 | poField, 0, reinterpret_cast<const char *>(pabyRawData), nRawDataSize)); |
602 | |
|
603 | 0 | CPLFree(pabyRawData); |
604 | |
|
605 | 0 | return nSuccess; |
606 | 0 | } |
607 | | |
608 | | /************************************************************************/ |
609 | | /* WritePrimitive() */ |
610 | | /************************************************************************/ |
611 | | |
612 | | bool S57Writer::WritePrimitive(OGRFeature *poFeature) |
613 | | |
614 | 0 | { |
615 | 0 | DDFRecord *poRec = MakeRecord(); |
616 | 0 | const OGRGeometry *poGeom = poFeature->GetGeometryRef(); |
617 | | |
618 | | /* -------------------------------------------------------------------- */ |
619 | | /* Add the VRID field. */ |
620 | | /* -------------------------------------------------------------------- */ |
621 | | |
622 | | // DDFField *poField = |
623 | 0 | poRec->AddField(poModule->FindFieldDefn("VRID")); |
624 | |
|
625 | 0 | poRec->SetIntSubfield("VRID", 0, "RCNM", 0, |
626 | 0 | poFeature->GetFieldAsInteger("RCNM")); |
627 | 0 | poRec->SetIntSubfield("VRID", 0, "RCID", 0, |
628 | 0 | poFeature->GetFieldAsInteger("RCID")); |
629 | 0 | poRec->SetIntSubfield("VRID", 0, "RVER", 0, 1); |
630 | 0 | poRec->SetIntSubfield("VRID", 0, "RUIN", 0, 1); |
631 | |
|
632 | 0 | bool bRet = true; |
633 | | |
634 | | /* -------------------------------------------------------------------- */ |
635 | | /* Handle simple point. */ |
636 | | /* -------------------------------------------------------------------- */ |
637 | 0 | if (poGeom != nullptr && wkbFlatten(poGeom->getGeometryType()) == wkbPoint) |
638 | 0 | { |
639 | 0 | const OGRPoint *poPoint = poGeom->toPoint(); |
640 | |
|
641 | 0 | CPLAssert(poFeature->GetFieldAsInteger("RCNM") == RCNM_VI || |
642 | 0 | poFeature->GetFieldAsInteger("RCNM") == RCNM_VC); |
643 | |
|
644 | 0 | const double adfX[1] = {poPoint->getX()}; |
645 | 0 | const double adfY[1] = {poPoint->getY()}; |
646 | 0 | const double adfZ[1] = {poPoint->getZ()}; |
647 | |
|
648 | 0 | if (adfZ[0] == 0.0) |
649 | 0 | bRet = WriteGeometry(poRec, 1, &adfX[0], &adfY[0], nullptr); |
650 | 0 | else |
651 | 0 | bRet = WriteGeometry(poRec, 1, &adfX[0], &adfY[0], &adfZ[0]); |
652 | 0 | } |
653 | | |
654 | | /* -------------------------------------------------------------------- */ |
655 | | /* For multipoints we assuming SOUNDG, and write out as SG3D. */ |
656 | | /* -------------------------------------------------------------------- */ |
657 | 0 | else if (poGeom != nullptr && |
658 | 0 | wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint) |
659 | 0 | { |
660 | 0 | const OGRMultiPoint *poMP = poGeom->toMultiPoint(); |
661 | 0 | const int nVCount = poMP->getNumGeometries(); |
662 | |
|
663 | 0 | CPLAssert(poFeature->GetFieldAsInteger("RCNM") == RCNM_VI || |
664 | 0 | poFeature->GetFieldAsInteger("RCNM") == RCNM_VC); |
665 | |
|
666 | 0 | double *padfX = (double *)CPLMalloc(sizeof(double) * nVCount); |
667 | 0 | double *padfY = (double *)CPLMalloc(sizeof(double) * nVCount); |
668 | 0 | double *padfZ = (double *)CPLMalloc(sizeof(double) * nVCount); |
669 | |
|
670 | 0 | for (int i = 0; i < nVCount; i++) |
671 | 0 | { |
672 | 0 | const OGRPoint *poPoint = poMP->getGeometryRef(i); |
673 | 0 | padfX[i] = poPoint->getX(); |
674 | 0 | padfY[i] = poPoint->getY(); |
675 | 0 | padfZ[i] = poPoint->getZ(); |
676 | 0 | } |
677 | |
|
678 | 0 | bRet = WriteGeometry(poRec, nVCount, padfX, padfY, padfZ); |
679 | |
|
680 | 0 | CPLFree(padfX); |
681 | 0 | CPLFree(padfY); |
682 | 0 | CPLFree(padfZ); |
683 | 0 | } |
684 | | |
685 | | /* -------------------------------------------------------------------- */ |
686 | | /* Handle LINESTRINGs (edge) geometry. */ |
687 | | /* -------------------------------------------------------------------- */ |
688 | 0 | else if (poGeom != nullptr && |
689 | 0 | wkbFlatten(poGeom->getGeometryType()) == wkbLineString) |
690 | 0 | { |
691 | 0 | const OGRLineString *poLS = poGeom->toLineString(); |
692 | 0 | const int nVCount = poLS->getNumPoints(); |
693 | |
|
694 | 0 | CPLAssert(poFeature->GetFieldAsInteger("RCNM") == RCNM_VE); |
695 | |
|
696 | 0 | double *padfX = (double *)CPLMalloc(sizeof(double) * nVCount); |
697 | 0 | double *padfY = (double *)CPLMalloc(sizeof(double) * nVCount); |
698 | |
|
699 | 0 | for (int i = 0; i < nVCount; i++) |
700 | 0 | { |
701 | 0 | padfX[i] = poLS->getX(i); |
702 | 0 | padfY[i] = poLS->getY(i); |
703 | 0 | } |
704 | |
|
705 | 0 | if (nVCount) |
706 | 0 | bRet = WriteGeometry(poRec, nVCount, padfX, padfY, nullptr); |
707 | |
|
708 | 0 | CPLFree(padfX); |
709 | 0 | CPLFree(padfY); |
710 | 0 | } |
711 | | |
712 | | /* -------------------------------------------------------------------- */ |
713 | | /* edge node linkages. */ |
714 | | /* -------------------------------------------------------------------- */ |
715 | 0 | if (poFeature->GetDefnRef()->GetFieldIndex("NAME_RCNM_0") >= 0) |
716 | 0 | { |
717 | 0 | CPLAssert(poFeature->GetFieldAsInteger("NAME_RCNM_0") == RCNM_VC); |
718 | | |
719 | | // DDFField *poField = |
720 | 0 | poRec->AddField(poModule->FindFieldDefn("VRPT")); |
721 | |
|
722 | 0 | const int nRCID0 = poFeature->GetFieldAsInteger("NAME_RCID_0"); |
723 | 0 | char szName0[5] = {RCNM_VC, static_cast<char>(nRCID0 & 0xff), |
724 | 0 | static_cast<char>((nRCID0 & 0xff00) >> 8), |
725 | 0 | static_cast<char>((nRCID0 & 0xff0000) >> 16), |
726 | 0 | static_cast<char>((nRCID0 & 0xff000000) >> 24)}; |
727 | |
|
728 | 0 | poRec->SetStringSubfield("VRPT", 0, "NAME", 0, szName0, 5); |
729 | 0 | poRec->SetIntSubfield("VRPT", 0, "ORNT", 0, |
730 | 0 | poFeature->GetFieldAsInteger("ORNT_0")); |
731 | 0 | poRec->SetIntSubfield("VRPT", 0, "USAG", 0, |
732 | 0 | poFeature->GetFieldAsInteger("USAG_0")); |
733 | 0 | poRec->SetIntSubfield("VRPT", 0, "TOPI", 0, |
734 | 0 | poFeature->GetFieldAsInteger("TOPI_0")); |
735 | 0 | poRec->SetIntSubfield("VRPT", 0, "MASK", 0, |
736 | 0 | poFeature->GetFieldAsInteger("MASK_0")); |
737 | |
|
738 | 0 | const int nRCID1 = poFeature->GetFieldAsInteger("NAME_RCID_1"); |
739 | 0 | const char szName1[5] = { |
740 | 0 | RCNM_VC, static_cast<char>(nRCID1 & 0xff), |
741 | 0 | static_cast<char>((nRCID1 & 0xff00) >> 8), |
742 | 0 | static_cast<char>((nRCID1 & 0xff0000) >> 16), |
743 | 0 | static_cast<char>((nRCID1 & 0xff000000) >> 24)}; |
744 | |
|
745 | 0 | poRec->SetStringSubfield("VRPT", 0, "NAME", 1, szName1, 5); |
746 | 0 | poRec->SetIntSubfield("VRPT", 0, "ORNT", 1, |
747 | 0 | poFeature->GetFieldAsInteger("ORNT_1")); |
748 | 0 | poRec->SetIntSubfield("VRPT", 0, "USAG", 1, |
749 | 0 | poFeature->GetFieldAsInteger("USAG_1")); |
750 | 0 | poRec->SetIntSubfield("VRPT", 0, "TOPI", 1, |
751 | 0 | poFeature->GetFieldAsInteger("TOPI_1")); |
752 | 0 | poRec->SetIntSubfield("VRPT", 0, "MASK", 1, |
753 | 0 | poFeature->GetFieldAsInteger("MASK_1")); |
754 | 0 | } |
755 | | |
756 | | /* -------------------------------------------------------------------- */ |
757 | | /* Write out the record. */ |
758 | | /* -------------------------------------------------------------------- */ |
759 | 0 | if (!poRec->Write()) |
760 | 0 | bRet = false; |
761 | 0 | delete poRec; |
762 | |
|
763 | 0 | return bRet; |
764 | 0 | } |
765 | | |
766 | | /************************************************************************/ |
767 | | /* GetHEXChar() */ |
768 | | /************************************************************************/ |
769 | | |
770 | | static char GetHEXChar(const char *pszSrcHEXString) |
771 | | |
772 | 0 | { |
773 | 0 | if (pszSrcHEXString[0] == '\0' || pszSrcHEXString[1] == '\0') |
774 | 0 | return (char)0; |
775 | | |
776 | 0 | int nResult = 0; |
777 | |
|
778 | 0 | if (pszSrcHEXString[0] >= '0' && pszSrcHEXString[0] <= '9') |
779 | 0 | nResult += (pszSrcHEXString[0] - '0') * 16; |
780 | 0 | else if (pszSrcHEXString[0] >= 'a' && pszSrcHEXString[0] <= 'f') |
781 | 0 | nResult += (pszSrcHEXString[0] - 'a' + 10) * 16; |
782 | 0 | else if (pszSrcHEXString[0] >= 'A' && pszSrcHEXString[0] <= 'F') |
783 | 0 | nResult += (pszSrcHEXString[0] - 'A' + 10) * 16; |
784 | |
|
785 | 0 | if (pszSrcHEXString[1] >= '0' && pszSrcHEXString[1] <= '9') |
786 | 0 | nResult += pszSrcHEXString[1] - '0'; |
787 | 0 | else if (pszSrcHEXString[1] >= 'a' && pszSrcHEXString[1] <= 'f') |
788 | 0 | nResult += pszSrcHEXString[1] - 'a' + 10; |
789 | 0 | else if (pszSrcHEXString[1] >= 'A' && pszSrcHEXString[1] <= 'F') |
790 | 0 | nResult += pszSrcHEXString[1] - 'A' + 10; |
791 | |
|
792 | 0 | return (char)nResult; |
793 | 0 | } |
794 | | |
795 | | /************************************************************************/ |
796 | | /* WriteCompleteFeature() */ |
797 | | /************************************************************************/ |
798 | | |
799 | | bool S57Writer::WriteCompleteFeature(OGRFeature *poFeature) |
800 | | |
801 | 0 | { |
802 | 0 | const OGRFeatureDefn *poFDefn = poFeature->GetDefnRef(); |
803 | | |
804 | | /* -------------------------------------------------------------------- */ |
805 | | /* We handle primitives in a separate method. */ |
806 | | /* -------------------------------------------------------------------- */ |
807 | 0 | if (EQUAL(poFDefn->GetName(), OGRN_VI) || |
808 | 0 | EQUAL(poFDefn->GetName(), OGRN_VC) || |
809 | 0 | EQUAL(poFDefn->GetName(), OGRN_VE)) |
810 | 0 | return WritePrimitive(poFeature); |
811 | | |
812 | | /* -------------------------------------------------------------------- */ |
813 | | /* Create the record. */ |
814 | | /* -------------------------------------------------------------------- */ |
815 | 0 | DDFRecord *poRec = MakeRecord(); |
816 | | |
817 | | /* -------------------------------------------------------------------- */ |
818 | | /* Add the FRID. */ |
819 | | /* -------------------------------------------------------------------- */ |
820 | | // DDFField *poField = |
821 | 0 | poRec->AddField(poModule->FindFieldDefn("FRID")); |
822 | |
|
823 | 0 | poRec->SetIntSubfield("FRID", 0, "RCNM", 0, 100); |
824 | 0 | poRec->SetIntSubfield("FRID", 0, "RCID", 0, |
825 | 0 | poFeature->GetFieldAsInteger("RCID")); |
826 | 0 | poRec->SetIntSubfield("FRID", 0, "PRIM", 0, |
827 | 0 | poFeature->GetFieldAsInteger("PRIM")); |
828 | 0 | poRec->SetIntSubfield("FRID", 0, "GRUP", 0, |
829 | 0 | poFeature->GetFieldAsInteger("GRUP")); |
830 | 0 | poRec->SetIntSubfield("FRID", 0, "OBJL", 0, |
831 | 0 | poFeature->GetFieldAsInteger("OBJL")); |
832 | 0 | poRec->SetIntSubfield("FRID", 0, "RVER", 0, 1); /* always new insert*/ |
833 | 0 | poRec->SetIntSubfield("FRID", 0, "RUIN", 0, 1); |
834 | | |
835 | | /* -------------------------------------------------------------------- */ |
836 | | /* Add the FOID */ |
837 | | /* -------------------------------------------------------------------- */ |
838 | | /*poField = */ poRec->AddField(poModule->FindFieldDefn("FOID")); |
839 | |
|
840 | 0 | poRec->SetIntSubfield("FOID", 0, "AGEN", 0, |
841 | 0 | poFeature->GetFieldAsInteger("AGEN")); |
842 | 0 | poRec->SetIntSubfield("FOID", 0, "FIDN", 0, |
843 | 0 | poFeature->GetFieldAsInteger("FIDN")); |
844 | 0 | poRec->SetIntSubfield("FOID", 0, "FIDS", 0, |
845 | 0 | poFeature->GetFieldAsInteger("FIDS")); |
846 | | |
847 | | /* -------------------------------------------------------------------- */ |
848 | | /* ATTF support. */ |
849 | | /* -------------------------------------------------------------------- */ |
850 | |
|
851 | 0 | if (poRegistrar != nullptr && |
852 | 0 | poClassContentExplorer->SelectClass( |
853 | 0 | poFeature->GetDefnRef()->GetName()) && |
854 | 0 | !WriteATTF(poRec, poFeature)) |
855 | 0 | { |
856 | 0 | delete poRec; |
857 | 0 | return false; |
858 | 0 | } |
859 | | |
860 | | /* -------------------------------------------------------------------- */ |
861 | | /* Add the FSPT if needed. */ |
862 | | /* -------------------------------------------------------------------- */ |
863 | 0 | if (poFeature->IsFieldSetAndNotNull(poFeature->GetFieldIndex("NAME_RCNM"))) |
864 | 0 | { |
865 | 0 | int nItemCount = 0; |
866 | |
|
867 | 0 | const int *panRCNM = |
868 | 0 | poFeature->GetFieldAsIntegerList("NAME_RCNM", &nItemCount); |
869 | 0 | const int *panRCID = |
870 | 0 | poFeature->GetFieldAsIntegerList("NAME_RCID", &nItemCount); |
871 | 0 | const int *panORNT = |
872 | 0 | poFeature->GetFieldAsIntegerList("ORNT", &nItemCount); |
873 | 0 | const int *panUSAG = |
874 | 0 | poFeature->GetFieldAsIntegerList("USAG", &nItemCount); |
875 | 0 | const int *panMASK = |
876 | 0 | poFeature->GetFieldAsIntegerList("MASK", &nItemCount); |
877 | | |
878 | | // cppcheck-suppress duplicateExpression |
879 | 0 | CPLAssert(sizeof(int) == sizeof(GInt32)); |
880 | |
|
881 | 0 | const int nRawDataSize = nItemCount * 8; |
882 | 0 | unsigned char *pabyRawData = (unsigned char *)CPLMalloc(nRawDataSize); |
883 | |
|
884 | 0 | for (int i = 0; i < nItemCount; i++) |
885 | 0 | { |
886 | 0 | GInt32 nRCID = CPL_LSBWORD32(panRCID[i]); |
887 | |
|
888 | 0 | pabyRawData[i * 8 + 0] = (GByte)panRCNM[i]; |
889 | 0 | memcpy(pabyRawData + i * 8 + 1, &nRCID, 4); |
890 | 0 | pabyRawData[i * 8 + 5] = (GByte)panORNT[i]; |
891 | 0 | pabyRawData[i * 8 + 6] = (GByte)panUSAG[i]; |
892 | 0 | pabyRawData[i * 8 + 7] = (GByte)panMASK[i]; |
893 | 0 | } |
894 | |
|
895 | 0 | DDFField *poField = poRec->AddField(poModule->FindFieldDefn("FSPT")); |
896 | 0 | poRec->SetFieldRaw(poField, 0, (const char *)pabyRawData, nRawDataSize); |
897 | 0 | CPLFree(pabyRawData); |
898 | 0 | } |
899 | | |
900 | | /* -------------------------------------------------------------------- */ |
901 | | /* Add the FFPT if needed. */ |
902 | | /* -------------------------------------------------------------------- */ |
903 | 0 | char **papszLNAM_REFS = poFeature->GetFieldAsStringList("LNAM_REFS"); |
904 | |
|
905 | 0 | if (CSLCount(papszLNAM_REFS) > 0) |
906 | 0 | { |
907 | 0 | int i, nRefCount = CSLCount(papszLNAM_REFS); |
908 | 0 | const int *panRIND = |
909 | 0 | poFeature->GetFieldAsIntegerList("FFPT_RIND", nullptr); |
910 | |
|
911 | 0 | poRec->AddField(poModule->FindFieldDefn("FFPT")); |
912 | |
|
913 | 0 | for (i = 0; i < nRefCount; i++) |
914 | 0 | { |
915 | 0 | char szLNAM[9]; |
916 | |
|
917 | 0 | if (strlen(papszLNAM_REFS[i]) < 16) |
918 | 0 | continue; |
919 | | |
920 | | // AGEN |
921 | 0 | szLNAM[1] = GetHEXChar(papszLNAM_REFS[i] + 0); |
922 | 0 | szLNAM[0] = GetHEXChar(papszLNAM_REFS[i] + 2); |
923 | | |
924 | | // FIDN |
925 | 0 | szLNAM[5] = GetHEXChar(papszLNAM_REFS[i] + 4); |
926 | 0 | szLNAM[4] = GetHEXChar(papszLNAM_REFS[i] + 6); |
927 | 0 | szLNAM[3] = GetHEXChar(papszLNAM_REFS[i] + 8); |
928 | 0 | szLNAM[2] = GetHEXChar(papszLNAM_REFS[i] + 10); |
929 | | |
930 | | // FIDS |
931 | 0 | szLNAM[7] = GetHEXChar(papszLNAM_REFS[i] + 12); |
932 | 0 | szLNAM[6] = GetHEXChar(papszLNAM_REFS[i] + 14); |
933 | |
|
934 | 0 | szLNAM[8] = '\0'; |
935 | |
|
936 | 0 | poRec->SetStringSubfield("FFPT", 0, "LNAM", i, (char *)szLNAM, 8); |
937 | 0 | poRec->SetIntSubfield("FFPT", 0, "RIND", i, panRIND[i]); |
938 | 0 | } |
939 | 0 | } |
940 | | |
941 | | /* -------------------------------------------------------------------- */ |
942 | | /* Write out the record. */ |
943 | | /* -------------------------------------------------------------------- */ |
944 | 0 | poRec->Write(); |
945 | 0 | delete poRec; |
946 | |
|
947 | 0 | return true; |
948 | 0 | } |
949 | | |
950 | | /************************************************************************/ |
951 | | /* SetClassBased() */ |
952 | | /************************************************************************/ |
953 | | |
954 | | void S57Writer::SetClassBased(S57ClassRegistrar *poReg, |
955 | | S57ClassContentExplorer *poClassContentExplorerIn) |
956 | | |
957 | 0 | { |
958 | 0 | poRegistrar = poReg; |
959 | 0 | poClassContentExplorer = poClassContentExplorerIn; |
960 | 0 | } |
961 | | |
962 | | /************************************************************************/ |
963 | | /* WriteATTF() */ |
964 | | /************************************************************************/ |
965 | | |
966 | | bool S57Writer::WriteATTF(DDFRecord *poRec, OGRFeature *poFeature) |
967 | 0 | { |
968 | 0 | CPLAssert(poRegistrar != nullptr); |
969 | | |
970 | | /* -------------------------------------------------------------------- */ |
971 | | /* Loop over all attributes. */ |
972 | | /* -------------------------------------------------------------------- */ |
973 | 0 | int nRawSize = 0; |
974 | 0 | int nACount = 0; |
975 | 0 | char achRawData[5000] = {}; |
976 | |
|
977 | 0 | char **papszAttrList = poClassContentExplorer->GetAttributeList(nullptr); |
978 | |
|
979 | 0 | for (int iAttr = 0; papszAttrList[iAttr] != nullptr; iAttr++) |
980 | 0 | { |
981 | 0 | const int iField = poFeature->GetFieldIndex(papszAttrList[iAttr]); |
982 | 0 | if (iField < 0) |
983 | 0 | continue; |
984 | | |
985 | 0 | const OGRFieldType eFldType = |
986 | 0 | poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType(); |
987 | |
|
988 | 0 | if (!poFeature->IsFieldSetAndNotNull(iField)) |
989 | 0 | continue; |
990 | | |
991 | 0 | const int nATTLInt = |
992 | 0 | poRegistrar->FindAttrByAcronym(papszAttrList[iAttr]); |
993 | 0 | if (nATTLInt == -1) |
994 | 0 | continue; |
995 | | |
996 | 0 | GUInt16 nATTL = (GUInt16)nATTLInt; |
997 | 0 | CPL_LSBPTR16(&nATTL); |
998 | 0 | memcpy(achRawData + nRawSize, &nATTL, 2); |
999 | 0 | nRawSize += 2; |
1000 | |
|
1001 | 0 | CPLString osATVL; |
1002 | 0 | if (eFldType == OFTStringList) |
1003 | 0 | { |
1004 | 0 | const char *const *papszTokens = |
1005 | 0 | poFeature->GetFieldAsStringList(iField); |
1006 | 0 | for (auto papszIter = papszTokens; papszIter && *papszIter; |
1007 | 0 | ++papszIter) |
1008 | 0 | { |
1009 | 0 | if (!osATVL.empty()) |
1010 | 0 | osATVL += ','; |
1011 | 0 | osATVL += *papszIter; |
1012 | 0 | } |
1013 | 0 | } |
1014 | 0 | else |
1015 | 0 | { |
1016 | 0 | osATVL = poFeature->GetFieldAsString(iField); |
1017 | 0 | } |
1018 | | |
1019 | | // Special hack to handle special "empty" marker in integer fields. |
1020 | 0 | if ((eFldType == OFTInteger || eFldType == OFTReal) && |
1021 | 0 | atoi(osATVL) == EMPTY_NUMBER_MARKER) |
1022 | 0 | osATVL.clear(); |
1023 | | |
1024 | | // Watch for really long data. |
1025 | 0 | if (osATVL.size() + nRawSize + 10 > sizeof(achRawData)) |
1026 | 0 | { |
1027 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
1028 | 0 | "Too much ATTF data for fixed buffer size."); |
1029 | 0 | return false; |
1030 | 0 | } |
1031 | | |
1032 | | // copy data into record buffer. |
1033 | 0 | if (!osATVL.empty()) |
1034 | 0 | { |
1035 | 0 | memcpy(achRawData + nRawSize, osATVL.data(), osATVL.size()); |
1036 | 0 | nRawSize += static_cast<int>(osATVL.size()); |
1037 | 0 | } |
1038 | 0 | achRawData[nRawSize++] = DDF_UNIT_TERMINATOR; |
1039 | |
|
1040 | 0 | nACount++; |
1041 | 0 | } |
1042 | | |
1043 | | /* -------------------------------------------------------------------- */ |
1044 | | /* If we got no attributes, return without adding ATTF. */ |
1045 | | /* -------------------------------------------------------------------- */ |
1046 | 0 | if (nACount == 0) |
1047 | 0 | return true; |
1048 | | |
1049 | | /* -------------------------------------------------------------------- */ |
1050 | | /* Write the new field value. */ |
1051 | | /* -------------------------------------------------------------------- */ |
1052 | 0 | DDFField *poField = poRec->AddField(poModule->FindFieldDefn("ATTF")); |
1053 | |
|
1054 | 0 | return CPL_TO_BOOL(poRec->SetFieldRaw(poField, 0, achRawData, nRawSize)); |
1055 | 0 | } |