Ignore:
Timestamp:
2016-06-24T03:48:12+02:00 (10 years ago)
Author:
donvip
Message:

checkstyle

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/seachart/src/s57/S57enc.java

    r31846 r32394  
    2121import java.util.zip.CRC32;
    2222
    23 import s57.S57obj.*;
     23import s57.S57att.Att;
     24import s57.S57dat.Fparams;
     25import s57.S57dat.S57field;
     26import s57.S57map.AttMap;
     27import s57.S57map.Feature;
     28import s57.S57map.Nflag;
     29import s57.S57map.ObjTab;
     30import s57.S57map.Pflag;
     31import s57.S57map.Prim;
     32import s57.S57obj.Obj;
    2433import s57.S57val.AttVal;
    25 import s57.S57att.Att;
    26 import s57.S57dat.*;
    27 import s57.S57map.*;
    2834
    2935public 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    }
    382389
    383390}
Note: See TracChangeset for help on using the changeset viewer.