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