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

Last change on this file since 35070 was 32909, checked in by donvip, 8 years ago

fix some error-prone warnings

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