protected void parseTRESubfile() throws ParseException {
FATBlock treFatBlock = fatBlocks.get(SubfileType.TRE);
seek(treFatBlock.getSubfileOffset());
SubfileTRE subfile =
(SubfileTRE) parseSubfileCommonHeader(treFatBlock.getSubfileOffset());
SubfileHeaderTRE treHeader = subfile.getHeader();
// North boundary
treHeader.setNorthBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));
// East boundary
treHeader.setEastBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));
// South boundary
treHeader.setSouthBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));
// West boundary
treHeader.setWestBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));
// Map levels section offset
treHeader.setMapLevelsSectionOffset(getLittleEndianWord(4));
// Map levels section size
treHeader.setMapLevelsSectionSize(getLittleEndianWord(4));
// Subdivisions section offset
treHeader.setSubdivisionsSectionOffset(getLittleEndianWord(4));
// Subdivisions section size
treHeader.setSubdivisionsSectionSize(getLittleEndianWord(4));
// Copyright section offset
treHeader.setCopyrightSectionOffset(getLittleEndianWord(4));
// Copyright section size
treHeader.setCopyrightSectionSize(getLittleEndianWord(4));
// Copyright record size
treHeader.setCopyrightRecordSize(getLittleEndianWord(2));
// 0x00 x4
skipBytes(4);
// POI display flags
nextByte();
treHeader.setTransparentMap((currentByte & 1) == 1);
treHeader.setShowStreetBeforeStreetNumber((currentByte & 2) == 2);
treHeader.setShowZipBeforeCity((currentByte & 4) == 4);
skipBytes(3);
skipBytes(4);
// 0x0001
skipBytes(2);
// 0x00
skipBytes(1);
// Polyline overview section offset
treHeader.setPolylineOverviewSectionOffset(getLittleEndianWord(4));
// Polyline overview section length
treHeader.setPolylineOverviewSectionLength(getLittleEndianWord(4));
// Polyline overview records size
treHeader.setPolylineOverviewRecordsSize(getLittleEndianWord(2));
skipBytes(2);
// 0x0000
skipBytes(2);
// Polygon overview section offset
treHeader.setPolygonOverviewSectionOffset(getLittleEndianWord(4));
// Polygon overview section length
treHeader.setPolygonOverviewSectionLength(getLittleEndianWord(4));
// Polygon overview records size
treHeader.setPolygonOverviewRecordsSize(getLittleEndianWord(2));
skipBytes(2);
// 0x0000
skipBytes(2);
// Point overview section offset
treHeader.setPointOverviewSectionOffset(getLittleEndianWord(4));
// Point overview section length
treHeader.setPointOverviewSectionLength(getLittleEndianWord(4));
// Point overview records size
treHeader.setPointOverviewRecordsSize(getLittleEndianWord(2));
skipBytes(2);
// 0x0000
skipBytes(2);
// Header longer than 116 bytes
if (subfile.getCommonHeader().getHeadersLength() > SubfileHeaderTRE.LENGTH_116) {
// Map ID
treHeader.setMapID(String.valueOf(getLittleEndianWord(4)));
// Header longer than 120 bytes
if (subfile.getCommonHeader().getHeadersLength() > SubfileHeaderTRE.LENGTH_120) {
// 0x00000000
skipBytes(4);
// TRE7 section offset
treHeader.setTre7SectionOffset(getLittleEndianWord(4));
// TRE7 section length
treHeader.setTre7SectionLength(getLittleEndianWord(4));
// TRE7 records size
treHeader.setTre7RecordsSize(getLittleEndianWord(2));
skipBytes(4);
// TRE8 section offset
treHeader.setTre8SectionOffset(getLittleEndianWord(4));
// TRE8 secion length
treHeader.setTre8SectionLength(getLittleEndianWord(4));
skipBytes(4);
// 0x0000
skipBytes(4);
// Header longer than 154 bytes
if (subfile.getCommonHeader().getHeadersLength() > SubfileHeaderTRE.LENGTH_154) {
// Map level encryption key
treHeader.setMapLevelsSectionEncryptionKey(parseString(20));
// TRE9 section offset
treHeader.setTre9SectionOffset(getLittleEndianWord(4));
// TRE9 section length
treHeader.setTre9SectionLength(getLittleEndianWord(4));
// TRE9 records size
treHeader.setTre9RecordsSize(getLittleEndianWord(2));
// 0x00000000
skipBytes(4);
}
}
}
// Map descriptor
String mapDescriptor = "";
nextByte();
while (currentByte != 0) {
mapDescriptor += (char) currentByte;
nextByte();
}
treHeader.setMapDescriptor(mapDescriptor);
// Copyright section
seek(treFatBlock.getSubfileOffset() + treHeader.getCopyrightSectionOffset());
int numberOfRecords =
treHeader.getCopyrightSectionSize() / treHeader.getCopyrightRecordSize();
for (int i = 0; i < numberOfRecords; i++) {
subfile.getCopyrights().add(getLittleEndianWord(treHeader.getCopyrightRecordSize()));
}
// Map levels section
seek(treFatBlock.getSubfileOffset() + treHeader.getMapLevelsSectionOffset());
int numberOfLevels = treHeader.getMapLevelsSectionSize() / 4; // fixme, porque 4?
for (int i = 0; i < numberOfLevels; i++) {
MapLevel mapLevel = new MapLevel();
mapLevel.setNumber(numberOfLevels - i - 1);
// Inherited
nextByte();
mapLevel.setInherited((currentByte & 128) == 128);
// Zoom level
mapLevel.setZoomLevel(currentByte & 15);
// Bits per coord
mapLevel.setBitsPerCoordinate(nextByte());
// Subdivisions
mapLevel.setQuantityOfSubdivisions(getLittleEndianWord(2));
subfile.getMapLevels().add(mapLevel);
}
// Subdivisions section
seek(treFatBlock.getSubfileOffset() + treHeader.getSubdivisionsSectionOffset());
boolean firstSubdivision = true;
int subdivisionCounter = 1;
Subdivision contiguousPreviousSubdivision = null;
Collection<Subdivision> subdivisionsTemp = new ArrayList<Subdivision>();
for (MapLevel mapLevel : subfile.getMapLevels()) {
for (int i = 0; i < mapLevel.getQuantityOfSubdivisions(); i++) {
Subdivision subdivision = new Subdivision();
subdivision.setLevel(mapLevel);
subdivision.setNumber(subdivisionCounter++);
// Offset in RGN subfile
subdivision.setOffsetInRGNSubfile(getLittleEndianWord(3));
// Object types
subdivision.setObjectTypes(getTRESubfileObjectTypes());
// Longitude center
subdivision.setLongitudeCenter(
Utils.convertMapUnitsToDegrees(getSignedInteger(3)));
// Latitude center
subdivision.setLatitudeCenter(
Utils.convertMapUnitsToDegrees(getSignedInteger(3)));
// Width
int value = getLittleEndianWord(2);
subdivision.setWidth(value & 32767);
subdivision.setTotalWidth((subdivision.getWidth() * 2) + 1);
subdivision.setTerminatingFlag((value & 32768) == 32768);
if (contiguousPreviousSubdivision != null) {
contiguousPreviousSubdivision.setContiguousSubdivision(subdivision);
}
if (subdivision.isTerminatingFlag()) {
contiguousPreviousSubdivision = null;
} else {
contiguousPreviousSubdivision = subdivision;
}
// Height
subdivision.setHeight(getLittleEndianWord(2));
subdivision.setTotalHeight((subdivision.getHeight() * 2) + 1);
if (mapLevel.getNumber() != 0) {
// Next level subdivision
int nextSubdivisionNumber = getLittleEndianWord(2);
if (nextSubdivisionNumber != 0) {
Subdivision subdivisionTemp = new Subdivision();
subdivisionTemp.setNumber(nextSubdivisionNumber);
subdivision.setNextLevelSubdivision(subdivisionTemp);
}
}
if (firstSubdivision) {
subfile.setFirstSubdivision(subdivision);
firstSubdivision = false;
}
for (Subdivision subdivisionTemp : subdivisionsTemp) {
if (subdivisionTemp.getNextLevelSubdivision() != null) {
if (subdivisionTemp.getNextLevelSubdivision().getNumber() == subdivision.getNumber()) {
subdivisionTemp.setNextLevelSubdivision(subdivision);
}
}
}
subdivisionsTemp.add(subdivision);
}
}
// Polyline section
seek(treFatBlock.getSubfileOffset() + treHeader.getPolylineOverviewSectionOffset());
int numberOfPolylines =
treHeader.getPolylineOverviewSectionLength() /
treHeader.getPolylineOverviewRecordsSize();
for (int i = 0; i < numberOfPolylines; i++) {
Polyline polyline = new Polyline();
polyline.setNumber(i + 1);
// Polyline type
nextByte(); // fixme, siempre es por default? no se usa el byte?
polyline.setType(PolylineType.DEFAULT);
// Maximum level
polyline.setMaximumLevelWherePresent(nextByte());
if (treHeader.getPolylineOverviewRecordsSize() == 3) {
skipBytes(1);
}
subfile.getPolylines().add(polyline);
}
// Polygon section
seek(treFatBlock.getSubfileOffset() + treHeader.getPolygonOverviewSectionOffset());
int numberOfPolygons =
treHeader.getPolygonOverviewSectionLength() /
treHeader.getPolygonOverviewRecordsSize();
for (int i = 0; i < numberOfPolygons; i++) {
Polygon polygon = new Polygon();
polygon.setNumber(i + 1);
// Polygon type
nextByte(); // fixme, siempre es por default? no se usa el byte?
polygon.setType(PolygonType.DEFAULT);
// Maximum level
polygon.setMaximumLevelWherePresent(nextByte());
if (treHeader.getPolygonOverviewRecordsSize() == 3) {
skipBytes(1);
}
subfile.getPolygons().add(polygon);
}
// Point section
seek(treFatBlock.getSubfileOffset() + treHeader.getPointOverviewSectionOffset());
int numberOfPoints =
treHeader.getPointOverviewSectionLength() /
treHeader.getPointOverviewRecordsSize();
for (int i = 0; i < numberOfPoints; i++) {
Point point = new Point();
point.setNumber(i + 1);
// Point type
nextByte(); // fixme, siempre es por default? no se usa el byte?
point.setType(PointType.DEFAULT);
// Maximum level
point.setMaximumLevelWherePresent(nextByte());
// Point subtype
nextByte(); // fixme, siempre es por default? no se usa el byte?
point.setSubtype(PointSubtype.DEFAULT);
subfile.getPoints().add(point);
}
img.getSubfiles().add(subfile);
}