// License: GPL. For details, see LICENSE file.
package s57;
import java.io.FileInputStream;
import java.io.IOException;
import s57.S57dat.S57field;
import s57.S57dat.S57subf;
import s57.S57map.Nflag;
/**
* @author Malcolm Herring
*/
public final class S57dec { // S57 ENC file input & map conversion
private S57dec() {
// Hide default constructor for utilities classes
}
// CHECKSTYLE.OFF: LineLength
public static void decodeChart(FileInputStream in, S57map map) throws IOException {
S57dat.rnum = 0;
byte[] leader = new byte[24];
byte[] record = new byte[0];
boolean ddr = false;
int length = 0;
int fields = 0;;
int mapfl, mapfp, mapts, entry;
String tag;
int len;
int pos;
boolean inFeature = false;
double comf = 1;
double somf = 1;
long name = 0;
S57map.Nflag nflag = Nflag.ANON;
S57map.Pflag pflag = S57map.Pflag.NOSP;
long objl = 0;
while (in.read(leader) == 24) {
try {
length = Integer.parseInt(new String(leader, 0, 5)) - 24;
record = new byte[length];
ddr = (leader[6] == 'L');
fields = Integer.parseInt(new String(leader, 12, 5)) - 24;
} catch (Exception e) {
System.err.println("Invalid file format - Encrypted/compressed ENC file?");
System.exit(-1);
}
mapfl = leader[20] - '0';
mapfp = leader[21] - '0';
mapts = leader[23] - '0';
entry = mapfl + mapfp + mapts;
if (in.read(record) != length)
break;
for (int idx = 0; idx < fields-1; idx += entry) {
tag = new String(record, idx, mapts);
len = Integer.parseInt(new String(record, idx+mapts, mapfl));
pos = Integer.parseInt(new String(record, idx+mapts+mapfl, mapfp));
if (!ddr) {
switch (tag.toString()) {
case "0001":
int i8rn = ((Long) S57dat.decSubf(record, fields + pos, S57field.I8RI, S57subf.I8RN)).intValue();
// if (i8rn != ++S57dat.rnum) {
// System.err.println("Out of order record ID");
// in.close();
// System.exit(-1);
// }
break;
case "DSSI":
S57dat.decSubf(record, fields + pos, S57field.DSSI, S57subf.AALL);
S57dat.decSubf(S57subf.NALL);
break;
case "DSPM":
comf = (Long) S57dat.decSubf(record, fields + pos, S57field.DSPM, S57subf.COMF);
somf = (Long) S57dat.decSubf(S57subf.SOMF);
break;
case "FRID":
inFeature = true;
switch (((Long) S57dat.decSubf(record, fields + pos, S57field.FRID, S57subf.PRIM)).intValue()) {
case 1:
pflag = S57map.Pflag.POINT;
break;
case 2:
pflag = S57map.Pflag.LINE;
break;
case 3:
pflag = S57map.Pflag.AREA;
break;
default:
pflag = S57map.Pflag.NOSP;
}
objl = (Long) S57dat.decSubf(S57subf.OBJL);
break;
case "FOID":
name = (long) S57dat.decSubf(record, fields + pos, S57field.LNAM, S57subf.LNAM);
map.newFeature(name, pflag, objl);
break;
case "ATTF":
S57dat.setField(record, fields + pos, S57field.ATTF, len);
do {
long attl = (Long) S57dat.decSubf(S57subf.ATTL);
String atvl = ((String) S57dat.decSubf(S57subf.ATVL)).trim();
if (!atvl.isEmpty()) {
map.newAtt(attl, atvl);
}
} while (S57dat.more());
break;
case "FFPT":
S57dat.setField(record, fields + pos, S57field.FFPT, len);
do {
name = (long) S57dat.decSubf(S57subf.LNAM);
int rind = ((Long) S57dat.decSubf(S57subf.RIND)).intValue();
S57dat.decSubf(S57subf.COMT);
map.refObj(name, rind);
} while (S57dat.more());
break;
case "FSPT":
S57dat.setField(record, fields + pos, S57field.FSPT, len);
do {
name = (long) S57dat.decSubf(S57subf.NAME) << 16;
map.newPrim(name, (Long) S57dat.decSubf(S57subf.ORNT), (Long) S57dat.decSubf(S57subf.USAG));
S57dat.decSubf(S57subf.MASK);
} while (S57dat.more());
break;
case "VRID":
inFeature = false;
name = (Long) S57dat.decSubf(record, fields + pos, S57field.VRID, S57subf.RCNM);
switch ((int) name) {
case 110:
nflag = Nflag.ISOL;
break;
case 120:
nflag = Nflag.CONN;
break;
default:
nflag = Nflag.ANON;
break;
}
name <<= 32;
name += (long) S57dat.decSubf(S57subf.RCID);
name <<= 16;
if (nflag == Nflag.ANON) {
map.newEdge(name);
}
break;
case "VRPT":
S57dat.setField(record, fields + pos, S57field.VRPT, len);
do {
long conn = (Long) S57dat.decSubf(S57subf.NAME) << 16;
int topi = ((Long) S57dat.decSubf(S57subf.TOPI)).intValue();
map.addConn(conn, topi);
S57dat.decSubf(S57subf.MASK);
} while (S57dat.more());
break;
case "SG2D":
S57dat.setField(record, fields + pos, S57field.SG2D, len);
do {
double lat = (double) ((Long) S57dat.decSubf(S57subf.YCOO)) / comf;
double lon = (double) ((Long) S57dat.decSubf(S57subf.XCOO)) / comf;
if (nflag == Nflag.ANON) {
map.newNode(++name, lat, lon, nflag);
} else {
map.newNode(name, lat, lon, nflag);
}
lat = Math.toRadians(lat);
lon = Math.toRadians(lon);
if (lat < map.bounds.minlat)
map.bounds.minlat = lat;
if (lat > map.bounds.maxlat)
map.bounds.maxlat = lat;
if (lon < map.bounds.minlon)
map.bounds.minlon = lon;
if (lon > map.bounds.maxlon)
map.bounds.maxlon = lon;
} while (S57dat.more());
break;
case "SG3D":
S57dat.setField(record, fields + pos, S57field.SG3D, len);
do {
double lat = (double) ((Long) S57dat.decSubf(S57subf.YCOO)) / comf;
double lon = (double) ((Long) S57dat.decSubf(S57subf.XCOO)) / comf;
double depth = (double) ((Long) S57dat.decSubf(S57subf.VE3D)) / somf;
map.newNode(name++, lat, lon, depth);
lat = Math.toRadians(lat);
lon = Math.toRadians(lon);
if (lat < map.bounds.minlat)
map.bounds.minlat = lat;
if (lat > map.bounds.maxlat)
map.bounds.maxlat = lat;
if (lon < map.bounds.minlon)
map.bounds.minlon = lon;
if (lon > map.bounds.maxlon)
map.bounds.maxlon = lon;
} while (S57dat.more());
break;
default:
break;
}
}
if (inFeature) {
map.endFeature();
inFeature = false;
}
}
}
map.endFile();
in.close();
return;
}
}