source: osm/applications/editors/josm/plugins/seachart/src/s57/S57enc.java@ 32095

Last change on this file since 32095 was 31846, checked in by malcolmh, 9 years ago

[seachart] add jbasemap

File size: 18.9 KB
Line 
1/* Copyright 2015 Malcolm Herring
2 *
3 * This is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License.
6 *
7 * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
8 */
9
10package s57;
11
12import java.io.UnsupportedEncodingException;
13import java.nio.ByteBuffer;
14import java.text.SimpleDateFormat;
15import java.util.ArrayList;
16import java.util.Arrays;
17import java.util.Calendar;
18import java.util.HashMap;
19import java.util.Map;
20import java.util.Map.Entry;
21import java.util.zip.CRC32;
22
23import s57.S57obj.*;
24import s57.S57val.AttVal;
25import s57.S57att.Att;
26import s57.S57dat.*;
27import s57.S57map.*;
28
29public class S57enc { // S57 ENC file generation
30
31 private static final byte[] header = {
32
33 '0', '1', '5', '7', '6', '3', 'L', 'E', '1', ' ', '0', '9', '0', '0', '2', '0', '1', ' ', '!', ' ', '3', '4', '0', '4', // Leader
34 '0', '0', '0', '0', '1', '2', '3', '0', '0', '0', '0', '0', '0', '0', '1', '0', '4', '7', '0', '1', '2', '3',
35 'D', 'S', 'I', 'D', '1', '5', '9', '0', '1', '7', '0', 'D', 'S', 'S', 'I', '1', '1', '3', '0', '3', '2', '9',
36 'D', 'S', 'P', 'M', '1', '3', '0', '0', '4', '4', '2', 'F', 'R', 'I', 'D', '1', '0', '0', '0', '5', '7', '2',
37 'F', 'O', 'I', 'D', '0', '7', '0', '0', '6', '7', '2', 'A', 'T', 'T', 'F', '0', '5', '9', '0', '7', '4', '2',
38 'N', 'A', 'T', 'F', '0', '6', '8', '0', '8', '0', '1', 'F', 'F', 'P', 'T', '0', '8', '6', '0', '8', '6', '9',
39 'F', 'S', 'P', 'T', '0', '9', '0', '0', '9', '5', '5', 'V', 'R', 'I', 'D', '0', '7', '8', '1', '0', '4', '5',
40 'A', 'T', 'T', 'V', '0', '5', '8', '1', '1', '2', '3', 'V', 'R', 'P', 'T', '0', '7', '6', '1', '1', '8', '1',
41 'S', 'G', '2', 'D', '0', '4', '8', '1', '2', '5', '7', 'S', 'G', '3', 'D', '0', '7', '0', '1', '3', '0', '5', 0x1e,
42 // File control field
43 '0', '0', '0', '0', ';', '&', ' ', ' ', ' ', 0x1f,
44 '0', '0', '0', '1', 'D', 'S', 'I', 'D', 'D', 'S', 'I', 'D', 'D', 'S', 'S', 'I', '0', '0', '0', '1', 'D', 'S', 'P', 'M',
45 '0', '0', '0', '1', 'F', 'R', 'I', 'D', 'F', 'R', 'I', 'D', 'F', 'O', 'I', 'D', 'F', 'R', 'I', 'D', 'A', 'T', 'T', 'F',
46 'F', 'R', 'I', 'D', 'N', 'A', 'T', 'F', 'F', 'R', 'I', 'D', 'F', 'F', 'P', 'T', 'F', 'R', 'I', 'D', 'F', 'S', 'P', 'T',
47 '0', '0', '0', '1', 'V', 'R', 'I', 'D', 'V', 'R', 'I', 'D', 'A', 'T', 'T', 'V', 'V', 'R', 'I', 'D', 'V', 'R', 'P', 'T',
48 'V', 'R', 'I', 'D', 'S', 'G', '2', 'D', 'V', 'R', 'I', 'D', 'S', 'G', '3', 'D', 0x1e,
49 // Record identifier fields
50 '0', '5', '0', '0', ';', '&', ' ', ' ', ' ', 'I', 'S', 'O', '/', 'I', 'E', 'C', ' ', '8', '2', '1', '1', ' ',
51 'R', 'e', 'c', 'o', 'r', 'd', ' ', 'I', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', 0x1f, 0x1f, '(', 'b', '1', '2', ')', 0x1e,
52 '1', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'D', 'a', 't', 'a', ' ', 'S', 'e', 't', ' ', 'I', 'd', 'e', 'n', 't', 'i',
53 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', 0x1f, 'R', 'C', 'N', 'M', '!', 'R', 'C', 'I', 'D', '!', 'E', 'X', 'P', 'P', '!',
54 'I', 'N', 'T', 'U', '!', 'D', 'S', 'N', 'M', '!', 'E', 'D', 'T', 'N', '!', 'U', 'P', 'D', 'N', '!', 'U', 'A', 'D', 'T',
55 '!', 'I', 'S', 'D', 'T', '!', 'S', 'T', 'E', 'D', '!', 'P', 'R', 'S', 'P', '!', 'P', 'S', 'D', 'N', '!', 'P', 'R', 'E',
56 'D', '!', 'P', 'R', 'O', 'F', '!', 'A', 'G', 'E', 'N', '!', 'C', 'O', 'M', 'T', 0x1f, '(', 'b', '1', '1', ',', 'b', '1',
57 '4', ',', '2', 'b', '1', '1', ',', '3', 'A', ',', '2', 'A', '(', '8', ')', ',', 'R', '(', '4', ')', ',', 'b', '1', '1',
58 ',', '2', 'A', ',', 'b', '1', '1', ',', 'b', '1', '2', ',', 'A', ')', 0x1e,
59 '1', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'D', 'a', 't', 'a', ' ', 's', 'e', 't', ' ', 's', 't', 'r', 'u', 'c', 't',
60 'u', 'r', 'e', ' ', 'i', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f,
61 'D', 'S', 'T', 'R', '!', 'A', 'A', 'L', 'L', '!', 'N', 'A', 'L', 'L', '!', 'N', 'O', 'M', 'R', '!', 'N', 'O', 'C', 'R',
62 '!', 'N', 'O', 'G', 'R', '!', 'N', 'O', 'L', 'R', '!', 'N', 'O', 'I', 'N', '!', 'N', 'O', 'C', 'N', '!', 'N', 'O', 'E',
63 'D', '!', 'N', 'O', 'F', 'A', 0x1f, '(', '3', 'b', '1', '1', ',', '8', 'b', '1', '4', ')', 0x1e,
64 '1', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'D', 'a', 't', 'a', ' ', 's', 'e', 't', ' ', 'p', 'a', 'r', 'a', 'm', 'e',
65 't', 'e', 'r', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, 'R', 'C', 'N', 'M', '!', 'R', 'C', 'I', 'D', '!', 'H', 'D', 'A', 'T',
66 '!', 'V', 'D', 'A', 'T', '!', 'S', 'D', 'A', 'T', '!', 'C', 'S', 'C', 'L', '!', 'D', 'U', 'N', 'I', '!', 'H', 'U', 'N',
67 'I', '!', 'P', 'U', 'N', 'I', '!', 'C', 'O', 'U', 'N', '!', 'C', 'O', 'M', 'F', '!', 'S', 'O', 'M', 'F', '!', 'C', 'O',
68 'M', 'T', 0x1f, '(', 'b', '1', '1', ',', 'b', '1', '4', ',', '3', 'b', '1', '1', ',', 'b', '1', '4', ',', '4', 'b', '1',
69 '1', ',', '2', 'b', '1', '4', ',', 'A', ')', 0x1e,
70 '1', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'F', 'e', 'a', 't', 'u', 'r', 'e', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 'i',
71 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, 'R', 'C', 'N', 'M', '!', 'R', 'C', 'I', 'D',
72 '!', 'P', 'R', 'I', 'M', '!', 'G', 'R', 'U', 'P', '!', 'O', 'B', 'J', 'L', '!', 'R', 'V', 'E', 'R', '!', 'R', 'U', 'I', 'N', 0x1f,
73 '(', 'b', '1', '1', ',', 'b', '1', '4', ',', '2', 'b', '1', '1', ',', '2', 'b', '1', '2', ',', 'b', '1', '1', ')', 0x1e,
74 '1', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'F', 'e', 'a', 't', 'u', 'r', 'e', ' ', 'o', 'b', 'j', 'e', 'c', 't', ' ', 'i',
75 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, 'A', 'G', 'E', 'N', '!', 'F', 'I', 'D', 'N',
76 '!', 'F', 'I', 'D', 'S', 0x1f, '(', 'b', '1', '2', ',', 'b', '1', '4', ',', 'b', '1', '2', ')', 0x1e,
77 '2', '6', '0', '0', ';', '&', '-', 'A', ' ', 'F', 'e', 'a', 't', 'u', 'r', 'e', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 'a',
78 't', 't', 'r', 'i', 'b', 'u', 't', 'e', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, '*', 'A', 'T', 'T', 'L', '!', 'A', 'T', 'V', 'L', 0x1f,
79 '(', 'b', '1', '2', ',', 'A', ')', 0x1e,
80 '2', '6', '0', '0', ';', '&', '-', 'A', ' ', 'F', 'e', 'a', 't', 'u', 'r', 'e', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 'n', 'a',
81 't', 'i', 'o', 'n', 'a', 'l', ' ', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, '*', 'A', 'T',
82 'T', 'L', '!', 'A', 'T', 'V', 'L', 0x1f, '(', 'b', '1', '2', ',', 'A', ')', 0x1e,
83 '2', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'F', 'e', 'a', 't', 'u', 'r', 'e', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 't', 'o',
84 ' ', 'f', 'e', 'a', 't', 'u', 'r', 'e', ' ', 'o', 'b', 'j', 'e', 'c', 't', ' ', 'p', 'o', 'i', 'n', 't', 'e', 'r', ' ', 'f', 'i',
85 'e', 'l', 'd', 0x1f, '*', 'L', 'N', 'A', 'M', '!', 'R', 'I', 'N', 'D', '!', 'C', 'O', 'M', 'T', 0x1f, '(', 'B', '(', '6', '4',
86 ')', ',', 'b', '1', '1', ',', 'A', ')', 0x1e,
87 '2', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'F', 'e', 'a', 't', 'u', 'r', 'e', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 't', 'o',
88 ' ', 's', 'p', 'a', 't', 'i', 'a', 'l', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 'p', 'o', 'i', 'n', 't', 'e', 'r', ' ', 'f', 'i',
89 'e', 'l', 'd', 0x1f, '*', 'N', 'A', 'M', 'E', '!', 'O', 'R', 'N', 'T', '!', 'U', 'S', 'A', 'G', '!', 'M', 'A', 'S', 'K', 0x1f,
90 '(', 'B', '(', '4', '0', ')', ',', '3', 'b', '1', '1', ')', 0x1e,
91 '1', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'V', 'e', 'c', 't', 'o', 'r', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 'i', 'd', 'e',
92 'n', 't', 'i', 'f', 'i', 'e', 'r', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, 'R', 'C', 'N', 'M', '!', 'R', 'C', 'I', 'D', '!', 'R', 'V',
93 'E', 'R', '!', 'R', 'U', 'I', 'N', 0x1f, '(', 'b', '1', '1', ',', 'b', '1', '4', ',', 'b', '1', '2', ',', 'b', '1', '1', ')', 0x1e,
94 '2', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'V', 'e', 'c', 't', 'o', 'r', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 'a', 't', 't',
95 'r', 'i', 'b', 'u', 't', 'e', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, '*', 'A', 'T', 'T', 'L', '!', 'A', 'T', 'V', 'L', 0x1f, '(', 'b',
96 '1', '2', ',', 'A', ')', 0x1e,
97 '2', '6', '0', '0', ';', '&', ' ', ' ', ' ', 'V', 'e', 'c', 't', 'o', 'r', ' ', 'r', 'e', 'c', 'o', 'r', 'd', ' ', 'p', 'o', 'i',
98 'n', 't', 'e', 'r', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, '*', 'N', 'A', 'M', 'E', '!', 'O', 'R', 'N', 'T', '!', 'U', 'S', 'A', 'G',
99 '!', 'T', 'O', 'P', 'I', '!', 'M', 'A', 'S', 'K', 0x1f, '(', 'B', '(', '4', '0', ')', ',', '4', 'b', '1', '1', ')', 0x1e,
100 '2', '6', '0', '0', ';', '&', ' ', ' ', ' ', '2', '-', 'D', ' ', 'c', 'o', 'o', 'r', 'd', 'i', 'n', 'a', 't', 'e', ' ', 'f', 'i',
101 'e', 'l', 'd', 0x1f, '*', 'Y', 'C', 'O', 'O', '!', 'X', 'C', 'O', 'O', 0x1f, '(', '2', 'b', '2', '4', ')', 0x1e,
102 '2', '6', '0', '0', ';', '&', ' ', ' ', ' ', '3', '-', 'D', ' ', 'c', 'o', 'o', 'r', 'd', 'i', 'n', 'a', 't', 'e', ' ', '(', 's',
103 'o', 'u', 'n', 'd', 'i', 'n', 'g', ' ', 'a', 'r', 'r', 'a', 'y', ')', ' ', 'f', 'i', 'e', 'l', 'd', 0x1f, '*', 'Y', 'C', 'O', 'O',
104 '!', 'X', 'C', 'O', 'O', '!', 'V', 'E', '3', 'D', 0x1f, '(', '3', 'b', '2', '4', ')', 0x1e
105 };
106
107 static final double COMF=10000000;
108 static final double SOMF=10;
109
110 static String file = "0S000000.000";
111 static int intu = 0;
112 static String code = "0S";
113 static int agen = 3878;
114 static int cscl = 10000;
115 static int vdat = 23;
116 static int duni = 1;
117 static int huni = 1;
118
119 static int idx;
120 static int recs;
121
122 static int isols;
123 static int conns;
124 static int metas;
125 static int geos;
126 static int edges;
127
128 static long hash(long val) {
129 byte[] bval = ByteBuffer.allocate(Long.SIZE).putLong(val).array();
130 CRC32 crc = new CRC32();
131 crc.update(bval);
132 return crc.getValue();
133 }
134
135 public static int encodeChart(S57map map, HashMap<String, String> meta, byte[] buf) throws IndexOutOfBoundsException, UnsupportedEncodingException {
136
137 for (Entry<String, String> entry : meta.entrySet()) {
138 try {
139 switch (entry.getKey()) {
140 case "FILE":
141 file = entry.getValue();
142 break;
143 case "INTU":
144 intu = Integer.parseInt(entry.getValue());
145 break;
146 case "AGEN":
147 String[] tokens = entry.getValue().split("/");
148 code = tokens[0];
149 agen = Integer.parseInt(tokens[1]);
150 break;
151 case "VDAT":
152 vdat = Integer.parseInt(entry.getValue());
153 break;
154 case "CSCL":
155 cscl = Integer.parseInt(entry.getValue());
156 break;
157 case "DUNI":
158 duni = Integer.parseInt(entry.getValue());
159 break;
160 case "HUNI":
161 huni = Integer.parseInt(entry.getValue());
162 break;
163 }
164 } catch (Exception e) {
165 System.err.println("Meta data (" + entry.getKey() + "=" + entry.getValue() + "):" + e.getMessage());
166 System.exit(-1);
167 }
168 }
169
170 //M_COVR & MNSYS in BB if not in map
171 if (!map.features.containsKey(Obj.M_COVR)) {
172 S57osm.OSMmeta(map);
173 }
174
175 S57dat.S57geoms(map);
176
177 byte[] record;
178 ArrayList<Fparams> fields;
179
180 isols = conns = metas = geos = edges = 0;
181 String date = new SimpleDateFormat("yyyyMMdd").format(Calendar.getInstance().getTime());
182 ArrayList<Fparams> ds = new ArrayList<>();
183 ds.add(new Fparams(S57field.DSID, new Object[] { 10, 1, 1, intu, file, "1", "0", date, date, "03.1", 1, "ENC", "2.0", 1, agen, "Generated by OpenSeaMap.org" }));
184 ds.add(new Fparams(S57field.DSSI, new Object[] { 2, 1, 2, metas, 0, geos, 0, isols, conns, edges, 0 }));
185 ArrayList<Fparams> dp = new ArrayList<>();
186 dp.add(new Fparams(S57field.DSPM, new Object[] { 20, 2, 2, vdat, vdat, cscl, duni, huni, 1, 1, 10000000, 10, "" }));
187
188 System.arraycopy(header, 0, buf, 0, header.length);
189 idx = header.length;
190 record = S57dat.encRecord(1, ds);
191 System.arraycopy(record, 0, buf, idx, record.length);
192 idx += record.length;
193 record = S57dat.encRecord(2, dp);
194 System.arraycopy(record, 0, buf, idx, record.length);
195 idx += record.length;
196 recs = 3;
197
198 // Depths
199 Object[] depths = new Object[0];
200 for (Map.Entry<Long, S57map.Snode> entry : map.nodes.entrySet()) {
201 S57map.Snode node = entry.getValue();
202 if (node.flg == Nflag.DPTH) {
203 Object[] dval = new Object[] { (Math.toDegrees(node.lat) * COMF), (Math.toDegrees(node.lon) * COMF), (node.val * SOMF) };
204 depths = Arrays.copyOf(depths, (depths.length + dval.length));
205 System.arraycopy(dval, 0, depths, (depths.length - dval.length), dval.length);
206 }
207 }
208 if (depths.length > 0) {
209 fields = new ArrayList<>();
210 fields.add(new Fparams(S57field.VRID, new Object[] { 110, -2, 1, 1 }));
211 fields.add(new Fparams(S57field.SG3D, depths));
212 record = S57dat.encRecord(recs++, fields);
213 System.arraycopy(record, 0, buf, idx, record.length);
214 idx += record.length;
215 isols++;
216 }
217
218 // Isolated nodes
219 for (Map.Entry<Long, S57map.Snode> entry : map.nodes.entrySet()) {
220 S57map.Snode node = entry.getValue();
221 if (node.flg == Nflag.ISOL) {
222 fields = new ArrayList<>();
223 fields.add(new Fparams(S57field.VRID, new Object[] { 110, hash(entry.getKey()), 1, 1 }));
224 fields.add(new Fparams(S57field.SG2D, new Object[] { (Math.toDegrees(node.lat) * COMF), (Math.toDegrees(node.lon) * COMF) }));
225 record = S57dat.encRecord(recs++, fields);
226 System.arraycopy(record, 0, buf, idx, record.length);
227 idx += record.length;
228 isols++;
229 }
230 }
231
232 // Connected nodes
233 for (Map.Entry<Long, S57map.Snode> entry : map.nodes.entrySet()) {
234 S57map.Snode node = entry.getValue();
235 if (node.flg == Nflag.CONN) {
236 fields = new ArrayList<>();
237 fields.add(new Fparams(S57field.VRID, new Object[] { 120, hash(entry.getKey()), 1, 1 }));
238 fields.add(new Fparams(S57field.SG2D, new Object[] { (Math.toDegrees(node.lat) * COMF), (Math.toDegrees(node.lon) * COMF) }));
239 record = S57dat.encRecord(recs++, fields);
240 System.arraycopy(record, 0, buf, idx, record.length);
241 idx += record.length;
242 conns++;
243 }
244 }
245
246 // Edges
247 for (Map.Entry<Long, S57map.Edge> entry : map.edges.entrySet()) {
248 S57map.Edge edge = entry.getValue();
249 fields = new ArrayList<>();
250 fields.add(new Fparams(S57field.VRID, new Object[] { 130, hash(entry.getKey()), 1, 1 }));
251 fields.add(new Fparams(S57field.VRPT, new Object[] { (((hash(edge.first) & 0xffffffff) << 8) + 120l), 255, 255, 1, 255, (((hash(edge.last) & 0xffffffff) << 8) + 120l), 255, 255, 2, 255 }));
252 Object[] nodes = new Object[0];
253 for (long ref : edge.nodes) {
254 Object[] nval = new Object[] { (Math.toDegrees(map.nodes.get(ref).lat) * COMF), (Math.toDegrees(map.nodes.get(ref).lon) * COMF) };
255 nodes = Arrays.copyOf(nodes, (nodes.length + nval.length));
256 System.arraycopy(nval, 0, nodes, (nodes.length - nval.length), nval.length);
257 }
258 if (nodes.length > 0) {
259 fields.add(new Fparams(S57field.SG2D, nodes));
260 }
261 record = S57dat.encRecord(recs++, fields);
262 System.arraycopy(record, 0, buf, idx, record.length);
263 idx += record.length;
264 edges++;
265 }
266
267 // Meta & Geo objects
268 boolean soundings = false;
269 for (Entry<Obj, ArrayList<Feature>> entry : map.features.entrySet()) {
270 Obj obj = entry.getKey();
271 for (Feature feature : entry.getValue()) {
272 if (obj == Obj.SOUNDG) {
273 if (soundings) {
274 continue;
275 } else {
276 soundings = true;
277 }
278 }
279 int prim = feature.geom.prim.ordinal();
280 prim = (prim == 0) ? 255 : prim;
281 int grup = ((obj == Obj.DEPARE) || (obj == Obj.DRGARE) || (obj == Obj.FLODOC) || (obj == Obj.HULKES) || (obj == Obj.LNDARE) || (obj == Obj.PONTON) || (obj == Obj.UNSARE)) ? 1 : 2;
282
283 ArrayList<Fparams> geom = new ArrayList<>();
284 int outers = 0;
285 outers = (feature.geom.prim == Pflag.POINT) ? 1 : feature.geom.comps.get(0).size;
286 for (Prim elem : feature.geom.elems) {
287 if (feature.geom.prim == Pflag.POINT) {
288 if (obj == Obj.SOUNDG) {
289 geom.add(new Fparams(S57field.FSPT, new Object[] { ((-2 << 8) + 110l), 255, 255, 255 }));
290 } else {
291 geom.add(new Fparams(S57field.FSPT, new Object[] { ((hash(elem.id) << 8) + ((map.nodes.get(elem.id).flg == Nflag.CONN) ? 120l : 110l)), 255, 255, 255 }));
292 }
293 } else {
294 geom.add(new Fparams(S57field.FSPT, new Object[] { ((hash(elem.id) << 8) + 130l), (elem.forward ? 1 : 2), ((outers-- > 0) ? 1 : 2), 2 }));
295 }
296 }
297
298 ArrayList<ArrayList<Fparams>> objects = new ArrayList<>();
299 ArrayList<Long> slaves = new ArrayList<>();
300 long slaveid = feature.id + 0x0100000000000000l;
301 for (Entry<Obj, ObjTab> objs : feature.objs.entrySet()) {
302 Obj objobj = objs.getKey();
303 boolean master = true;
304 for (Entry<Integer, AttMap> object : objs.getValue().entrySet()) {
305 ArrayList<Fparams> objatts = new ArrayList<>();
306 master = (feature.type == objobj) && ((object.getKey() == 0) || (object.getKey() == 1));
307 long id = hash(master ? feature.id : slaveid);
308 objatts.add(new Fparams(S57field.FRID, new Object[] { 100, id, prim, grup, S57obj.encodeType(objobj), 1, 1 }));
309 objatts.add(new Fparams(S57field.FOID, new Object[] { agen, id, 1 }));
310 Object[] attf = new Object[0];
311 Object[] natf = new Object[0];
312 AttMap atts = map.new AttMap();
313 atts.putAll(object.getValue());
314 if (master) {
315 atts.putAll(feature.atts);
316 }
317 for (Entry<Att, AttVal<?>> att : atts.entrySet()) {
318 if (!((obj == Obj.SOUNDG) && (att.getKey() == Att.VALSOU))) {
319 long attl = S57att.encodeAttribute(att.getKey());
320 Object[] next = new Object[] { attl, S57val.encodeValue(att.getValue(), att.getKey()) };
321 if ((attl < 300) || (attl > 304)) {
322 attf = Arrays.copyOf(attf, (attf.length + next.length));
323 System.arraycopy(next, 0, attf, (attf.length - next.length), next.length);
324 } else {
325 natf = Arrays.copyOf(natf, (natf.length + next.length));
326 System.arraycopy(next, 0, natf, (natf.length - next.length), next.length);
327 }
328 }
329 }
330 if (attf.length > 0) {
331 objatts.add(new Fparams(S57field.ATTF, attf));
332 }
333 if (natf.length > 0) {
334 objatts.add(new Fparams(S57field.NATF, attf));
335 }
336 if (master) {
337 objects.add(objatts);
338 } else {
339 slaves.add(id);
340 objects.add(0, objatts);
341 slaveid += 0x0100000000000000l;
342 }
343 }
344 }
345
346 if (!slaves.isEmpty()) {
347 ArrayList<Fparams> refs = new ArrayList<>();
348 Object[] params = new Object[0];
349 while (!slaves.isEmpty()) {
350 long id = slaves.remove(0);
351 Object[] next = new Object[] { (long) ((((id & 0xffffffff) + 0x100000000l) << 16) + (agen & 0xffff)), 2, "" };
352 params = Arrays.copyOf(params, (params.length + next.length));
353 System.arraycopy(next, 0, params, (params.length - next.length), next.length);
354 }
355 refs.add(new Fparams(S57field.FFPT, params));
356 objects.get(objects.size() - 1).addAll(refs);
357 }
358
359 for (ArrayList<Fparams> object : objects) {
360 object.addAll(geom);
361 record = S57dat.encRecord(recs++, object);
362 System.arraycopy(record, 0, buf, idx, record.length);
363 idx += record.length;
364 if ((obj == Obj.M_COVR) || (obj == Obj.M_NSYS)) {
365 metas++;
366 } else {
367 geos++;
368 }
369 }
370 }
371 }
372
373 // Re-write DSID/DSSI with final totals
374 ds = new ArrayList<>();
375 ds.add(new Fparams(S57field.DSID, new Object[] { 10, 1, 1, intu, file, "1", "0", date, date, "03.1", 1, "ENC", "2.0", 1, agen, "Generated by OpenSeaMap.org" }));
376 ds.add(new Fparams(S57field.DSSI, new Object[] { 2, 1, 2, metas, 0, geos, 0, isols, conns, edges, 0 }));
377 record = S57dat.encRecord(1, ds);
378 System.arraycopy(record, 0, buf, header.length, record.length);
379
380 return idx;
381 }
382
383}
Note: See TracBrowser for help on using the repository browser.