Reformat whole codebase using Android Studio

This commit is contained in:
Manuel Fuhr 2022-07-11 06:30:17 +02:00
parent d5322667d5
commit c15913c1ab
161 changed files with 15124 additions and 18537 deletions

View file

@ -14,113 +14,100 @@ import btools.util.IByteArrayUnifier;
* DirectWeaver does the same decoding as MicroCache2, but decodes directly
* into the instance-graph, not into the intermediate nodes-cache
*/
public final class DirectWeaver extends ByteDataWriter
{
public final class DirectWeaver extends ByteDataWriter {
private long id64Base;
private int size = 0;
public DirectWeaver( StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes )
{
super( null );
public DirectWeaver(StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes) {
super(null);
int cellsize = 1000000 / divisor;
id64Base = ((long)(lonIdx*cellsize))<<32 | (latIdx*cellsize);
id64Base = ((long) (lonIdx * cellsize)) << 32 | (latIdx * cellsize);
TagValueCoder wayTagCoder = new TagValueCoder( bc, dataBuffers, wayValidator );
TagValueCoder nodeTagCoder = new TagValueCoder( bc, dataBuffers, null );
NoisyDiffCoder nodeIdxDiff = new NoisyDiffCoder( bc );
NoisyDiffCoder nodeEleDiff = new NoisyDiffCoder( bc );
TagValueCoder wayTagCoder = new TagValueCoder(bc, dataBuffers, wayValidator);
TagValueCoder nodeTagCoder = new TagValueCoder(bc, dataBuffers, null);
NoisyDiffCoder nodeIdxDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder nodeEleDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder extLonDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder extLatDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder transEleDiff = new NoisyDiffCoder( bc );
NoisyDiffCoder transEleDiff = new NoisyDiffCoder(bc);
size = bc.decodeNoisyNumber( 5 );
size = bc.decodeNoisyNumber(5);
int[] faid = size > dataBuffers.ibuf2.length ? new int[size] : dataBuffers.ibuf2;
bc.decodeSortedArray( faid, 0, size, 29, 0 );
bc.decodeSortedArray(faid, 0, size, 29, 0);
OsmNode[] nodes = new OsmNode[size];
for( int n = 0; n<size; n++ )
{
long id = expandId( faid[n] );
int ilon = (int) ( id >> 32 );
int ilat = (int) ( id & 0xffffffff );
OsmNode node = hollowNodes.get( ilon, ilat );
if ( node == null )
{
node = new OsmNode( ilon, ilat );
}
else
{
for (int n = 0; n < size; n++) {
long id = expandId(faid[n]);
int ilon = (int) (id >> 32);
int ilat = (int) (id & 0xffffffff);
OsmNode node = hollowNodes.get(ilon, ilat);
if (node == null) {
node = new OsmNode(ilon, ilat);
} else {
node.visitID = 1;
hollowNodes.remove( node );
hollowNodes.remove(node);
}
nodes[n] = node;
}
int netdatasize = bc.decodeNoisyNumber( 10 ); // (not needed for direct weaving)
int netdatasize = bc.decodeNoisyNumber(10); // (not needed for direct weaving)
ab = dataBuffers.bbuf1;
aboffset = 0;
int selev = 0;
for( int n=0; n<size; n++ ) // loop over nodes
{
for (int n = 0; n < size; n++) // loop over nodes
{
OsmNode node = nodes[n];
int ilon = node.ilon;
int ilat = node.ilat;
// future escapes (turn restrictions?)
short trExceptions = 0;
for(;;)
{
for (; ; ) {
int featureId = bc.decodeVarBits();
if ( featureId == 0 ) break;
int bitsize = bc.decodeNoisyNumber( 5 );
if (featureId == 0) break;
int bitsize = bc.decodeNoisyNumber(5);
if ( featureId == 2 ) // exceptions to turn-restriction
if (featureId == 2) // exceptions to turn-restriction
{
trExceptions = (short)bc.decodeBounded( 1023 );
}
else if ( featureId == 1 ) // turn-restriction
trExceptions = (short) bc.decodeBounded(1023);
} else if (featureId == 1) // turn-restriction
{
TurnRestriction tr = new TurnRestriction();
tr.exceptions = trExceptions;
tr.exceptions = trExceptions;
trExceptions = 0;
tr.isPositive = bc.decodeBit();
tr.fromLon = ilon + bc.decodeNoisyDiff( 10 );
tr.fromLat = ilat + bc.decodeNoisyDiff( 10 );
tr.toLon = ilon + bc.decodeNoisyDiff( 10 );
tr.toLat = ilat + bc.decodeNoisyDiff( 10 );
node.addTurnRestriction( tr );
}
else
{
for( int i=0; i< bitsize; i++ ) bc.decodeBit(); // unknown feature, just skip
tr.isPositive = bc.decodeBit();
tr.fromLon = ilon + bc.decodeNoisyDiff(10);
tr.fromLat = ilat + bc.decodeNoisyDiff(10);
tr.toLon = ilon + bc.decodeNoisyDiff(10);
tr.toLat = ilat + bc.decodeNoisyDiff(10);
node.addTurnRestriction(tr);
} else {
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
}
}
selev += nodeEleDiff.decodeSignedValue();
node.selev = (short)selev;
node.selev = (short) selev;
TagValueWrapper nodeTags = nodeTagCoder.decodeTagValueSet();
node.nodeDescription = nodeTags == null ? null : nodeTags.data; // TODO: unified?
int links = bc.decodeNoisyNumber( 1 );
for( int li=0; li<links; li++ )
{
int links = bc.decodeNoisyNumber(1);
for (int li = 0; li < links; li++) {
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
int dlon_remaining;
int dlat_remaining;
boolean isReverse = false;
if ( nodeIdx != n ) // internal (forward-) link
if (nodeIdx != n) // internal (forward-) link
{
dlon_remaining = nodes[nodeIdx].ilon - ilon;
dlat_remaining = nodes[nodeIdx].ilat - ilat;
}
else
{
} else {
isReverse = bc.decodeBit();
dlon_remaining = extLonDiff.decodeSignedValue();
dlat_remaining = extLatDiff.decodeSignedValue();
@ -131,104 +118,92 @@ public final class DirectWeaver extends ByteDataWriter
int linklon = ilon + dlon_remaining;
int linklat = ilat + dlat_remaining;
aboffset = 0;
if ( !isReverse ) // write geometry for forward links only
if (!isReverse) // write geometry for forward links only
{
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
int ilontarget = ilon + dlon_remaining;
int ilattarget = ilat + dlat_remaining;
if ( matcher != null )
{
if ( !matcher.start( ilon, ilat, ilontarget, ilattarget ) )
{
if (matcher != null) {
if (!matcher.start(ilon, ilat, ilontarget, ilattarget)) {
matcher = null;
}
}
int transcount = bc.decodeVarBits();
int count = transcount+1;
for( int i=0; i<transcount; i++ )
{
int dlon = bc.decodePredictedValue( dlon_remaining/count );
int dlat = bc.decodePredictedValue( dlat_remaining/count );
int count = transcount + 1;
for (int i = 0; i < transcount; i++) {
int dlon = bc.decodePredictedValue(dlon_remaining / count);
int dlat = bc.decodePredictedValue(dlat_remaining / count);
dlon_remaining -= dlon;
dlat_remaining -= dlat;
count--;
int elediff = transEleDiff.decodeSignedValue();
if ( wayTags != null )
{
writeVarLengthSigned( dlon );
writeVarLengthSigned( dlat );
writeVarLengthSigned( elediff );
if (wayTags != null) {
writeVarLengthSigned(dlon);
writeVarLengthSigned(dlat);
writeVarLengthSigned(elediff);
}
if ( matcher != null ) matcher.transferNode( ilontarget - dlon_remaining, ilattarget - dlat_remaining );
if (matcher != null)
matcher.transferNode(ilontarget - dlon_remaining, ilattarget - dlat_remaining);
}
if ( matcher != null ) matcher.end();
if (matcher != null) matcher.end();
}
if ( wayTags != null )
{
if (wayTags != null) {
byte[] geometry = null;
if ( aboffset > 0 )
{
if (aboffset > 0) {
geometry = new byte[aboffset];
System.arraycopy( ab, 0, geometry, 0, aboffset );
System.arraycopy(ab, 0, geometry, 0, aboffset);
}
if ( nodeIdx != n ) // valid internal (forward-) link
if (nodeIdx != n) // valid internal (forward-) link
{
OsmNode node2 = nodes[nodeIdx];
OsmLink link = node.isLinkUnused() ? node : ( node2.isLinkUnused() ? node2 : null );
if ( link == null )
{
OsmLink link = node.isLinkUnused() ? node : (node2.isLinkUnused() ? node2 : null);
if (link == null) {
link = new OsmLink();
}
link.descriptionBitmap = wayTags.data;
link.geometry = geometry;
node.addLink( link, isReverse, node2 );
}
else // weave external link
node.addLink(link, isReverse, node2);
} else // weave external link
{
node.addLink( linklon, linklat, wayTags.data, geometry, hollowNodes, isReverse );
node.addLink(linklon, linklat, wayTags.data, geometry, hollowNodes, isReverse);
node.visitID = 1;
}
}
} // ... loop over links
} // ... loop over nodes
hollowNodes.cleanupAndCount( nodes );
hollowNodes.cleanupAndCount(nodes);
}
private static final long[] id32_00 = new long[1024];
private static final long[] id32_10 = new long[1024];
private static final long[] id32_20 = new long[1024];
static
{
for( int i=0; i<1024; i++ )
{
id32_00[i] = _expandId( i );
id32_10[i] = _expandId( i << 10 );
id32_20[i] = _expandId( i << 20 );
static {
for (int i = 0; i < 1024; i++) {
id32_00[i] = _expandId(i);
id32_10[i] = _expandId(i << 10);
id32_20[i] = _expandId(i << 20);
}
}
private static long _expandId( int id32 )
{
private static long _expandId(int id32) {
int dlon = 0;
int dlat = 0;
for( int bm = 1; bm < 0x8000; bm <<= 1 )
{
if ( (id32 & 1) != 0 ) dlon |= bm;
if ( (id32 & 2) != 0 ) dlat |= bm;
for (int bm = 1; bm < 0x8000; bm <<= 1) {
if ((id32 & 1) != 0) dlon |= bm;
if ((id32 & 2) != 0) dlat |= bm;
id32 >>= 2;
}
return ((long)dlon)<<32 | dlat;
return ((long) dlon) << 32 | dlat;
}
public long expandId( int id32 )
{
return id64Base + id32_00[ id32 & 1023 ] + id32_10[ (id32>>10) & 1023 ] + id32_20[ (id32>>20) & 1023 ];
public long expandId(int id32) {
return id64Base + id32_00[id32 & 1023] + id32_10[(id32 >> 10) & 1023] + id32_20[(id32 >> 20) & 1023];
}
}

View file

@ -8,9 +8,8 @@ package btools.mapaccess;
import btools.util.ByteDataReader;
public final class GeometryDecoder
{
private ByteDataReader r = new ByteDataReader( null );
public final class GeometryDecoder {
private ByteDataReader r = new ByteDataReader(null);
private OsmTransferNode[] cachedNodes;
private int nCachedNodes = 128;
@ -19,63 +18,53 @@ public final class GeometryDecoder
private boolean lastReverse;
private byte[] lastGeometry;
public GeometryDecoder()
{
public GeometryDecoder() {
// create some caches
cachedNodes = new OsmTransferNode[nCachedNodes];
for( int i=0; i<nCachedNodes; i++ )
{
for (int i = 0; i < nCachedNodes; i++) {
cachedNodes[i] = new OsmTransferNode();
}
}
public OsmTransferNode decodeGeometry( byte[] geometry, OsmNode sourceNode, OsmNode targetNode, boolean reverseLink )
{
if ( ( lastGeometry == geometry ) && ( lastReverse == reverseLink ) )
{
return firstTransferNode;
}
firstTransferNode = null;
OsmTransferNode lastTransferNode = null;
OsmNode startnode = reverseLink ? targetNode : sourceNode;
r.reset( geometry );
int olon = startnode.ilon;
int olat = startnode.ilat;
int oselev = startnode.selev;
int idx = 0;
while ( r.hasMoreData() )
{
OsmTransferNode trans = idx < nCachedNodes ? cachedNodes[idx++] : new OsmTransferNode();
trans.ilon = olon + r.readVarLengthSigned();
trans.ilat = olat + r.readVarLengthSigned();
trans.selev = (short)(oselev + r.readVarLengthSigned());
olon = trans.ilon;
olat = trans.ilat;
oselev = trans.selev;
if ( reverseLink ) // reverse chaining
{
trans.next = firstTransferNode;
firstTransferNode = trans;
}
else
{
trans.next = null;
if ( lastTransferNode == null )
{
firstTransferNode = trans;
}
else
{
lastTransferNode.next = trans;
}
lastTransferNode = trans;
}
}
lastReverse = reverseLink;
lastGeometry = geometry;
public OsmTransferNode decodeGeometry(byte[] geometry, OsmNode sourceNode, OsmNode targetNode, boolean reverseLink) {
if ((lastGeometry == geometry) && (lastReverse == reverseLink)) {
return firstTransferNode;
}
firstTransferNode = null;
OsmTransferNode lastTransferNode = null;
OsmNode startnode = reverseLink ? targetNode : sourceNode;
r.reset(geometry);
int olon = startnode.ilon;
int olat = startnode.ilat;
int oselev = startnode.selev;
int idx = 0;
while (r.hasMoreData()) {
OsmTransferNode trans = idx < nCachedNodes ? cachedNodes[idx++] : new OsmTransferNode();
trans.ilon = olon + r.readVarLengthSigned();
trans.ilat = olat + r.readVarLengthSigned();
trans.selev = (short) (oselev + r.readVarLengthSigned());
olon = trans.ilon;
olat = trans.ilat;
oselev = trans.selev;
if (reverseLink) // reverse chaining
{
trans.next = firstTransferNode;
firstTransferNode = trans;
} else {
trans.next = null;
if (lastTransferNode == null) {
firstTransferNode = trans;
} else {
lastTransferNode.next = trans;
}
lastTransferNode = trans;
}
}
lastReverse = reverseLink;
lastGeometry = geometry;
return firstTransferNode;
}
}

View file

@ -11,48 +11,45 @@ import java.io.IOException;
import btools.mapaccess.OsmNode;
public final class MatchedWaypoint
{
public final class MatchedWaypoint {
public OsmNode node1;
public OsmNode node2;
public OsmNode crosspoint;
public OsmNode waypoint;
public String name; // waypoint name used in error messages
public double radius; // distance in meter between waypoint and crosspoint
public boolean hasUpdate;
public void writeToStream( DataOutput dos ) throws IOException
{
dos.writeInt( node1.ilat );
dos.writeInt( node1.ilon );
dos.writeInt( node2.ilat );
dos.writeInt( node2.ilon );
dos.writeInt( crosspoint.ilat );
dos.writeInt( crosspoint.ilon );
dos.writeInt( waypoint.ilat );
dos.writeInt( waypoint.ilon );
dos.writeDouble( radius );
public void writeToStream(DataOutput dos) throws IOException {
dos.writeInt(node1.ilat);
dos.writeInt(node1.ilon);
dos.writeInt(node2.ilat);
dos.writeInt(node2.ilon);
dos.writeInt(crosspoint.ilat);
dos.writeInt(crosspoint.ilon);
dos.writeInt(waypoint.ilat);
dos.writeInt(waypoint.ilon);
dos.writeDouble(radius);
}
public static MatchedWaypoint readFromStream( DataInput dis ) throws IOException
{
MatchedWaypoint mwp = new MatchedWaypoint();
mwp.node1 = new OsmNode();
mwp.node2 = new OsmNode();
mwp.crosspoint = new OsmNode();
mwp.waypoint = new OsmNode();
public static MatchedWaypoint readFromStream(DataInput dis) throws IOException {
MatchedWaypoint mwp = new MatchedWaypoint();
mwp.node1 = new OsmNode();
mwp.node2 = new OsmNode();
mwp.crosspoint = new OsmNode();
mwp.waypoint = new OsmNode();
mwp.node1.ilat = dis.readInt();
mwp.node1.ilon = dis.readInt();
mwp.node2.ilat = dis.readInt();
mwp.node2.ilon = dis.readInt();
mwp.crosspoint.ilat = dis.readInt();
mwp.crosspoint.ilon = dis.readInt();
mwp.waypoint.ilat = dis.readInt();
mwp.waypoint.ilon = dis.readInt();
mwp.radius = dis.readDouble();
return mwp;
mwp.node1.ilat = dis.readInt();
mwp.node1.ilon = dis.readInt();
mwp.node2.ilat = dis.readInt();
mwp.node2.ilon = dis.readInt();
mwp.crosspoint.ilat = dis.readInt();
mwp.crosspoint.ilon = dis.readInt();
mwp.waypoint.ilat = dis.readInt();
mwp.waypoint.ilon = dis.readInt();
mwp.radius = dis.readDouble();
return mwp;
}
}

View file

@ -15,8 +15,7 @@ import btools.codec.MicroCache;
import btools.codec.WaypointMatcher;
import btools.expressions.BExpressionContextWay;
public final class NodesCache
{
public final class NodesCache {
private File segmentDir;
private File secondarySegmentsDir = null;
@ -40,7 +39,7 @@ public final class NodesCache
private long cacheSum = 0;
private long maxmemtiles;
private boolean detailed;
private boolean garbageCollectionEnabled = false;
private boolean ghostCleaningDone = false;
@ -48,155 +47,123 @@ public final class NodesCache
private long cacheSumClean = 0;
private long ghostSum = 0;
private long ghostWakeup = 0;
private boolean directWeaving = !Boolean.getBoolean( "disableDirectWeaving" );
public String formatStatus()
{
return "collecting=" + garbageCollectionEnabled + " noGhosts=" + ghostCleaningDone + " cacheSum=" + cacheSum + " cacheSumClean=" + cacheSumClean + " ghostSum=" + ghostSum + " ghostWakeup=" + ghostWakeup ;
private boolean directWeaving = !Boolean.getBoolean("disableDirectWeaving");
public String formatStatus() {
return "collecting=" + garbageCollectionEnabled + " noGhosts=" + ghostCleaningDone + " cacheSum=" + cacheSum + " cacheSumClean=" + cacheSumClean + " ghostSum=" + ghostSum + " ghostWakeup=" + ghostWakeup;
}
public NodesCache( File segmentDir, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache, boolean detailed )
{
public NodesCache(File segmentDir, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache, boolean detailed) {
this.maxmemtiles = maxmem / 8;
this.segmentDir = segmentDir;
this.nodesMap = new OsmNodesMap();
this.nodesMap.maxmem = (2L*maxmem) / 3L;
this.nodesMap.maxmem = (2L * maxmem) / 3L;
this.expCtxWay = ctxWay;
this.lookupVersion = ctxWay.meta.lookupVersion;
this.lookupMinorVersion = ctxWay.meta.lookupMinorVersion;
this.forceSecondaryData = forceSecondaryData;
this.detailed = detailed;
if ( ctxWay != null )
{
ctxWay.setDecodeForbidden( detailed );
if (ctxWay != null) {
ctxWay.setDecodeForbidden(detailed);
}
first_file_access_failed = false;
first_file_access_name = null;
if ( !this.segmentDir.isDirectory() )
throw new RuntimeException( "segment directory " + segmentDir.getAbsolutePath () + " does not exist" );
if (!this.segmentDir.isDirectory())
throw new RuntimeException("segment directory " + segmentDir.getAbsolutePath() + " does not exist");
if ( oldCache != null )
{
if (oldCache != null) {
fileCache = oldCache.fileCache;
dataBuffers = oldCache.dataBuffers;
secondarySegmentsDir = oldCache.secondarySegmentsDir;
// re-use old, virgin caches (if same detail-mode)
if ( oldCache.detailed == detailed)
{
if (oldCache.detailed == detailed) {
fileRows = oldCache.fileRows;
for ( OsmFile[] fileRow : fileRows )
{
if ( fileRow == null )
for (OsmFile[] fileRow : fileRows) {
if (fileRow == null)
continue;
for ( OsmFile osmf : fileRow )
{
for (OsmFile osmf : fileRow) {
cacheSum += osmf.setGhostState();
}
}
}
else
{
} else {
fileRows = new OsmFile[180][];
}
}
else
{
fileCache = new HashMap<String, PhysicalFile>( 4 );
} else {
fileCache = new HashMap<String, PhysicalFile>(4);
fileRows = new OsmFile[180][];
dataBuffers = new DataBuffers();
secondarySegmentsDir = StorageConfigHelper.getSecondarySegmentDir( segmentDir );
secondarySegmentsDir = StorageConfigHelper.getSecondarySegmentDir(segmentDir);
}
ghostSum = cacheSum;
}
public void clean( boolean all )
{
for ( OsmFile[] fileRow : fileRows )
{
if ( fileRow == null )
continue;
for ( OsmFile osmf : fileRow )
{
osmf.clean( all);
}
public void clean(boolean all) {
for (OsmFile[] fileRow : fileRows) {
if (fileRow == null)
continue;
for (OsmFile osmf : fileRow) {
osmf.clean(all);
}
}
}
// if the cache sum exceeded a threshold,
// clean all ghosts and enable garbage collection
private void checkEnableCacheCleaning()
{
if ( cacheSum < maxmemtiles )
{
private void checkEnableCacheCleaning() {
if (cacheSum < maxmemtiles) {
return;
}
for ( int i = 0; i < fileRows.length; i++ )
{
for (int i = 0; i < fileRows.length; i++) {
OsmFile[] fileRow = fileRows[i];
if ( fileRow == null )
{
if (fileRow == null) {
continue;
}
for ( OsmFile osmf : fileRow )
{
if ( garbageCollectionEnabled && !ghostCleaningDone )
{
for (OsmFile osmf : fileRow) {
if (garbageCollectionEnabled && !ghostCleaningDone) {
cacheSum -= osmf.cleanGhosts();
}
else
{
} else {
cacheSum -= osmf.collectAll();
}
}
}
if ( garbageCollectionEnabled )
{
if (garbageCollectionEnabled) {
ghostCleaningDone = true;
maxmemtiles *= 2;
}
else
{
} else {
cacheSumClean = cacheSum;
garbageCollectionEnabled = true;
}
}
public int loadSegmentFor( int ilon, int ilat )
{
MicroCache mc = getSegmentFor( ilon, ilat );
public int loadSegmentFor(int ilon, int ilat) {
MicroCache mc = getSegmentFor(ilon, ilat);
return mc == null ? 0 : mc.getSize();
}
public MicroCache getSegmentFor( int ilon, int ilat )
{
try
{
public MicroCache getSegmentFor(int ilon, int ilat) {
try {
int lonDegree = ilon / 1000000;
int latDegree = ilat / 1000000;
OsmFile osmf = null;
OsmFile[] fileRow = fileRows[latDegree];
int ndegrees = fileRow == null ? 0 : fileRow.length;
for ( int i = 0; i < ndegrees; i++ )
{
if ( fileRow[i].lonDegree == lonDegree )
{
for (int i = 0; i < ndegrees; i++) {
if (fileRow[i].lonDegree == lonDegree) {
osmf = fileRow[i];
break;
}
}
if ( osmf == null )
{
osmf = fileForSegment( lonDegree, latDegree );
if (osmf == null) {
osmf = fileForSegment(lonDegree, latDegree);
OsmFile[] newFileRow = new OsmFile[ndegrees + 1];
for ( int i = 0; i < ndegrees; i++ )
{
for (int i = 0; i < ndegrees; i++) {
newFileRow[i] = fileRow[i];
}
newFileRow[ndegrees] = osmf;
@ -204,33 +171,25 @@ public final class NodesCache
}
currentFileName = osmf.filename;
if ( !osmf.hasData() )
{
if (!osmf.hasData()) {
return null;
}
MicroCache segment = osmf.getMicroCache( ilon, ilat );
if ( segment == null )
{
MicroCache segment = osmf.getMicroCache(ilon, ilat);
if (segment == null) {
checkEnableCacheCleaning();
segment = osmf.createMicroCache( ilon, ilat, dataBuffers, expCtxWay, waypointMatcher, directWeaving ? nodesMap : null );
segment = osmf.createMicroCache(ilon, ilat, dataBuffers, expCtxWay, waypointMatcher, directWeaving ? nodesMap : null);
cacheSum += segment.getDataSize();
}
else if ( segment.ghost )
{
} else if (segment.ghost) {
segment.unGhost();
ghostWakeup += segment.getDataSize();
}
return segment;
}
catch (RuntimeException re)
{
} catch (RuntimeException re) {
throw re;
}
catch (Exception e)
{
throw new RuntimeException( "error reading datafile " + currentFileName + ": " + e, e );
} catch (Exception e) {
throw new RuntimeException("error reading datafile " + currentFileName + ": " + e, e);
}
}
@ -238,60 +197,50 @@ public final class NodesCache
* make sure the given node is non-hollow,
* which means it contains not just the id,
* but also the actual data
*
*
* @return true if successfull, false if node is still hollow
*/
public boolean obtainNonHollowNode( OsmNode node )
{
if ( !node.isHollow() )
public boolean obtainNonHollowNode(OsmNode node) {
if (!node.isHollow())
return true;
MicroCache segment = getSegmentFor( node.ilon, node.ilat );
if ( segment == null )
{
MicroCache segment = getSegmentFor(node.ilon, node.ilat);
if (segment == null) {
return false;
}
if ( !node.isHollow() )
{
if (!node.isHollow()) {
return true; // direct weaving...
}
long id = node.getIdFromPos();
if ( segment.getAndClear( id ) )
{
node.parseNodeBody( segment, nodesMap, expCtxWay );
if (segment.getAndClear(id)) {
node.parseNodeBody(segment, nodesMap, expCtxWay);
}
if ( garbageCollectionEnabled ) // garbage collection
if (garbageCollectionEnabled) // garbage collection
{
cacheSum -= segment.collect( segment.getSize() >> 1 ); // threshold = 1/2 of size is deleted
cacheSum -= segment.collect(segment.getSize() >> 1); // threshold = 1/2 of size is deleted
}
return !node.isHollow();
}
/**
* make sure all link targets of the given node are non-hollow
*/
public void expandHollowLinkTargets( OsmNode n )
{
for( OsmLink link = n.firstlink; link != null; link = link.getNext( n ) )
{
obtainNonHollowNode( link.getTarget( n ) );
public void expandHollowLinkTargets(OsmNode n) {
for (OsmLink link = n.firstlink; link != null; link = link.getNext(n)) {
obtainNonHollowNode(link.getTarget(n));
}
}
/**
* make sure all link targets of the given node are non-hollow
*/
public boolean hasHollowLinkTargets( OsmNode n )
{
for( OsmLink link = n.firstlink; link != null; link = link.getNext( n ) )
{
if ( link.getTarget( n ).isHollow() )
{
public boolean hasHollowLinkTargets(OsmNode n) {
for (OsmLink link = n.firstlink; link != null; link = link.getNext(n)) {
if (link.getTarget(n).isHollow()) {
return true;
}
}
@ -300,129 +249,107 @@ public final class NodesCache
/**
* get a node for the given id with all link-targets also non-hollow
*
* <p>
* It is required that an instance of the start-node does not yet
* exist, not even a hollow instance, so getStartNode should only
* be called once right after resetting the cache
*
*
* @param id the id of the node to load
*
* @return the fully expanded node for id, or null if it was not found
*/
public OsmNode getStartNode( long id )
{
public OsmNode getStartNode(long id) {
// initialize the start-node
OsmNode n = new OsmNode( id );
OsmNode n = new OsmNode(id);
n.setHollow();
nodesMap.put( n );
if ( !obtainNonHollowNode( n ) )
{
nodesMap.put(n);
if (!obtainNonHollowNode(n)) {
return null;
}
expandHollowLinkTargets( n );
expandHollowLinkTargets(n);
return n;
}
public OsmNode getGraphNode( OsmNode template )
{
OsmNode graphNode = new OsmNode( template.ilon, template.ilat );
public OsmNode getGraphNode(OsmNode template) {
OsmNode graphNode = new OsmNode(template.ilon, template.ilat);
graphNode.setHollow();
OsmNode existing = nodesMap.put( graphNode );
if ( existing == null )
{
OsmNode existing = nodesMap.put(graphNode);
if (existing == null) {
return graphNode;
}
nodesMap.put( existing );
nodesMap.put(existing);
return existing;
}
public void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs )
{
waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, maxDistance, islandNodePairs );
for( MatchedWaypoint mwp : unmatchedWaypoints )
{
preloadPosition( mwp.waypoint );
public void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs) {
waypointMatcher = new WaypointMatcherImpl(unmatchedWaypoints, maxDistance, islandNodePairs);
for (MatchedWaypoint mwp : unmatchedWaypoints) {
preloadPosition(mwp.waypoint);
}
if ( first_file_access_failed )
{
throw new IllegalArgumentException( "datafile " + first_file_access_name + " not found" );
if (first_file_access_failed) {
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
}
for( MatchedWaypoint mwp : unmatchedWaypoints )
{
if ( mwp.crosspoint == null )
{
throw new IllegalArgumentException( mwp.name + "-position not mapped in existing datafile" );
for (MatchedWaypoint mwp : unmatchedWaypoints) {
if (mwp.crosspoint == null) {
throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
}
}
}
private void preloadPosition( OsmNode n )
{
private void preloadPosition(OsmNode n) {
int d = 12500;
first_file_access_failed = false;
first_file_access_name = null;
loadSegmentFor( n.ilon, n.ilat );
if ( first_file_access_failed )
{
throw new IllegalArgumentException( "datafile " + first_file_access_name + " not found" );
loadSegmentFor(n.ilon, n.ilat);
if (first_file_access_failed) {
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
}
for( int idxLat=-1; idxLat<=1; idxLat++ )
for( int idxLon=-1; idxLon<=1; idxLon++ )
{
if ( idxLon != 0 || idxLat != 0 )
{
loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat );
for (int idxLat = -1; idxLat <= 1; idxLat++)
for (int idxLon = -1; idxLon <= 1; idxLon++) {
if (idxLon != 0 || idxLat != 0) {
loadSegmentFor(n.ilon + d * idxLon, n.ilat + d * idxLat);
}
}
}
private OsmFile fileForSegment( int lonDegree, int latDegree ) throws Exception
{
private OsmFile fileForSegment(int lonDegree, int latDegree) throws Exception {
int lonMod5 = lonDegree % 5;
int latMod5 = latDegree % 5;
int lon = lonDegree - 180 - lonMod5;
String slon = lon < 0 ? "W" + ( -lon ) : "E" + lon;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
int lat = latDegree - 90 - latMod5;
String slat = lat < 0 ? "S" + ( -lat ) : "N" + lat;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
String filenameBase = slon + "_" + slat;
currentFileName = filenameBase + ".rd5";
PhysicalFile ra = null;
if ( !fileCache.containsKey( filenameBase ) )
{
if (!fileCache.containsKey(filenameBase)) {
File f = null;
if ( !forceSecondaryData )
{
File primary = new File( segmentDir, filenameBase + ".rd5" );
if ( primary .exists() )
{
if (!forceSecondaryData) {
File primary = new File(segmentDir, filenameBase + ".rd5");
if (primary.exists()) {
f = primary;
}
}
if ( f == null )
{
File secondary = new File( secondarySegmentsDir, filenameBase + ".rd5" );
if ( secondary.exists() )
{
if (f == null) {
File secondary = new File(secondarySegmentsDir, filenameBase + ".rd5");
if (secondary.exists()) {
f = secondary;
}
}
if ( f != null )
{
if (f != null) {
currentFileName = f.getName();
ra = new PhysicalFile( f, dataBuffers, lookupVersion, lookupMinorVersion );
ra = new PhysicalFile(f, dataBuffers, lookupVersion, lookupMinorVersion);
}
fileCache.put( filenameBase, ra );
fileCache.put(filenameBase, ra);
}
ra = fileCache.get( filenameBase );
OsmFile osmf = new OsmFile( ra, lonDegree, latDegree, dataBuffers );
ra = fileCache.get(filenameBase);
OsmFile osmf = new OsmFile(ra, lonDegree, latDegree, dataBuffers);
if ( first_file_access_name == null )
{
if (first_file_access_name == null) {
first_file_access_name = currentFileName;
first_file_access_failed = osmf.filename == null;
}
@ -430,17 +357,12 @@ public final class NodesCache
return osmf;
}
public void close()
{
for ( PhysicalFile f : fileCache.values() )
{
try
{
if ( f != null )
public void close() {
for (PhysicalFile f : fileCache.values()) {
try {
if (f != null)
f.ra.close();
}
catch (IOException ioe)
{
} catch (IOException ioe) {
// ignore
}
}

View file

@ -1,13 +1,12 @@
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
final class NodesList
{
public OsmNode node;
public NodesList next;
}
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
final class NodesList {
public OsmNode node;
public NodesList next;
}

View file

@ -17,8 +17,7 @@ import btools.codec.WaypointMatcher;
import btools.util.ByteDataReader;
import btools.util.Crc32;
final class OsmFile
{
final class OsmFile {
private RandomAccessFile is = null;
private long fileOffset;
@ -35,16 +34,14 @@ final class OsmFile
private int ncaches;
private int indexsize;
public OsmFile( PhysicalFile rafile, int lonDegree, int latDegree, DataBuffers dataBuffers ) throws IOException
{
public OsmFile(PhysicalFile rafile, int lonDegree, int latDegree, DataBuffers dataBuffers) throws IOException {
this.lonDegree = lonDegree;
this.latDegree = latDegree;
int lonMod5 = lonDegree % 5;
int latMod5 = latDegree % 5;
int tileIndex = lonMod5 * 5 + latMod5;
if ( rafile != null )
{
if (rafile != null) {
divisor = rafile.divisor;
cellsize = 1000000 / divisor;
@ -56,197 +53,161 @@ final class OsmFile
long[] index = rafile.fileIndex;
fileOffset = tileIndex > 0 ? index[tileIndex - 1] : 200L;
if ( fileOffset == index[tileIndex] )
if (fileOffset == index[tileIndex])
return; // empty
is = rafile.ra;
posIdx = new int[ncaches];
microCaches = new MicroCache[ncaches];
is.seek( fileOffset );
is.readFully( iobuffer, 0, indexsize );
is.seek(fileOffset);
is.readFully(iobuffer, 0, indexsize);
if ( rafile.fileHeaderCrcs != null )
{
int headerCrc = Crc32.crc( iobuffer, 0, indexsize );
if ( rafile.fileHeaderCrcs[tileIndex] != headerCrc )
{
throw new IOException( "sub index checksum error" );
if (rafile.fileHeaderCrcs != null) {
int headerCrc = Crc32.crc(iobuffer, 0, indexsize);
if (rafile.fileHeaderCrcs[tileIndex] != headerCrc) {
throw new IOException("sub index checksum error");
}
}
ByteDataReader dis = new ByteDataReader( iobuffer );
for ( int i = 0; i < ncaches; i++ )
{
ByteDataReader dis = new ByteDataReader(iobuffer);
for (int i = 0; i < ncaches; i++) {
posIdx[i] = dis.readInt();
}
}
}
public boolean hasData()
{
public boolean hasData() {
return microCaches != null;
}
public MicroCache getMicroCache( int ilon, int ilat )
{
public MicroCache getMicroCache(int ilon, int ilat) {
int lonIdx = ilon / cellsize;
int latIdx = ilat / cellsize;
int subIdx = ( latIdx - divisor * latDegree ) * divisor + ( lonIdx - divisor * lonDegree );
int subIdx = (latIdx - divisor * latDegree) * divisor + (lonIdx - divisor * lonDegree);
return microCaches[subIdx];
}
public MicroCache createMicroCache( int ilon, int ilat, DataBuffers dataBuffers, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes )
throws Exception
{
public MicroCache createMicroCache(int ilon, int ilat, DataBuffers dataBuffers, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes)
throws Exception {
int lonIdx = ilon / cellsize;
int latIdx = ilat / cellsize;
MicroCache segment = createMicroCache( lonIdx, latIdx, dataBuffers, wayValidator, waypointMatcher, true, hollowNodes );
int subIdx = ( latIdx - divisor * latDegree ) * divisor + ( lonIdx - divisor * lonDegree );
MicroCache segment = createMicroCache(lonIdx, latIdx, dataBuffers, wayValidator, waypointMatcher, true, hollowNodes);
int subIdx = (latIdx - divisor * latDegree) * divisor + (lonIdx - divisor * lonDegree);
microCaches[subIdx] = segment;
return segment;
}
private int getPosIdx( int idx )
{
private int getPosIdx(int idx) {
return idx == -1 ? indexsize : posIdx[idx];
}
public int getDataInputForSubIdx( int subIdx, byte[] iobuffer ) throws IOException
{
int startPos = getPosIdx( subIdx - 1 );
int endPos = getPosIdx( subIdx );
public int getDataInputForSubIdx(int subIdx, byte[] iobuffer) throws IOException {
int startPos = getPosIdx(subIdx - 1);
int endPos = getPosIdx(subIdx);
int size = endPos - startPos;
if ( size > 0 )
{
is.seek( fileOffset + startPos );
if ( size <= iobuffer.length )
{
is.readFully( iobuffer, 0, size );
if (size > 0) {
is.seek(fileOffset + startPos);
if (size <= iobuffer.length) {
is.readFully(iobuffer, 0, size);
}
}
return size;
}
public MicroCache createMicroCache( int lonIdx, int latIdx, DataBuffers dataBuffers, TagValueValidator wayValidator,
WaypointMatcher waypointMatcher, boolean reallyDecode, OsmNodesMap hollowNodes ) throws IOException
{
int subIdx = ( latIdx - divisor * latDegree ) * divisor + ( lonIdx - divisor * lonDegree );
public MicroCache createMicroCache(int lonIdx, int latIdx, DataBuffers dataBuffers, TagValueValidator wayValidator,
WaypointMatcher waypointMatcher, boolean reallyDecode, OsmNodesMap hollowNodes) throws IOException {
int subIdx = (latIdx - divisor * latDegree) * divisor + (lonIdx - divisor * lonDegree);
byte[] ab = dataBuffers.iobuffer;
int asize = getDataInputForSubIdx( subIdx, ab );
int asize = getDataInputForSubIdx(subIdx, ab);
if ( asize == 0 )
{
if (asize == 0) {
return MicroCache.emptyCache();
}
if ( asize > ab.length )
{
if (asize > ab.length) {
ab = new byte[asize];
asize = getDataInputForSubIdx( subIdx, ab );
asize = getDataInputForSubIdx(subIdx, ab);
}
StatCoderContext bc = new StatCoderContext( ab );
StatCoderContext bc = new StatCoderContext(ab);
try
{
if ( !reallyDecode )
{
try {
if (!reallyDecode) {
return null;
}
if ( hollowNodes == null )
{
return new MicroCache2( bc, dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher );
if (hollowNodes == null) {
return new MicroCache2(bc, dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher);
}
new DirectWeaver( bc, dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher, hollowNodes );
new DirectWeaver(bc, dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher, hollowNodes);
return MicroCache.emptyNonVirgin;
}
finally
{
} finally {
// crc check only if the buffer has not been fully read
int readBytes = (bc.getReadingBitPosition()+7)>>3;
if ( readBytes != asize-4 )
{
int crcData = Crc32.crc( ab, 0, asize - 4 );
int crcFooter = new ByteDataReader( ab, asize - 4 ).readInt();
if ( crcData == crcFooter )
{
throw new IOException( "old, unsupported data-format" );
}
else if ( ( crcData ^ 2 ) != crcFooter )
{
throw new IOException( "checkum error" );
int readBytes = (bc.getReadingBitPosition() + 7) >> 3;
if (readBytes != asize - 4) {
int crcData = Crc32.crc(ab, 0, asize - 4);
int crcFooter = new ByteDataReader(ab, asize - 4).readInt();
if (crcData == crcFooter) {
throw new IOException("old, unsupported data-format");
} else if ((crcData ^ 2) != crcFooter) {
throw new IOException("checkum error");
}
}
}
}
// set this OsmFile to ghost-state:
long setGhostState()
{
long setGhostState() {
long sum = 0;
int nc = microCaches == null ? 0 : microCaches.length;
for ( int i = 0; i < nc; i++ )
{
for (int i = 0; i < nc; i++) {
MicroCache mc = microCaches[i];
if ( mc == null )
if (mc == null)
continue;
if ( mc.virgin )
{
if (mc.virgin) {
mc.ghost = true;
sum += mc.getDataSize();
}
else
{
} else {
microCaches[i] = null;
}
}
return sum;
}
long collectAll()
{
long collectAll() {
long deleted = 0;
int nc = microCaches == null ? 0 : microCaches.length;
for ( int i = 0; i < nc; i++ )
{
for (int i = 0; i < nc; i++) {
MicroCache mc = microCaches[i];
if ( mc == null )
if (mc == null)
continue;
if ( !mc.ghost )
{
deleted += mc.collect( 0 );
if (!mc.ghost) {
deleted += mc.collect(0);
}
}
return deleted;
}
long cleanGhosts()
{
long cleanGhosts() {
long deleted = 0;
int nc = microCaches == null ? 0 : microCaches.length;
for ( int i = 0; i < nc; i++ )
{
for (int i = 0; i < nc; i++) {
MicroCache mc = microCaches[i];
if ( mc == null )
if (mc == null)
continue;
if ( mc.ghost )
{
if (mc.ghost) {
microCaches[i] = null;
}
}
return deleted;
}
void clean( boolean all )
{
void clean(boolean all) {
int nc = microCaches == null ? 0 : microCaches.length;
for ( int i = 0; i < nc; i++ )
{
for (int i = 0; i < nc; i++) {
MicroCache mc = microCaches[i];
if ( mc == null )
if (mc == null)
continue;
if ( all || !mc.virgin )
{
if (all || !mc.virgin) {
microCaches[i] = null;
}
}

View file

@ -1,182 +1,155 @@
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
public class OsmLink
{
/**
* The description bitmap contains the waytags (valid for both directions)
*/
public byte[] descriptionBitmap;
/**
* The geometry contains intermediate nodes, null for none (valid for both directions)
*/
public byte[] geometry;
// a link logically knows only its target, but for the reverse link, source and target are swapped
protected OsmNode n1;
protected OsmNode n2;
// same for the next-link-for-node pointer: previous applies to the reverse link
protected OsmLink previous;
protected OsmLink next;
private OsmLinkHolder reverselinkholder = null;
private OsmLinkHolder firstlinkholder = null;
protected OsmLink()
{
}
public OsmLink( OsmNode source, OsmNode target )
{
n1 = source;
n2 = target;
}
/**
* Get the relevant target-node for the given source
*/
public final OsmNode getTarget( OsmNode source )
{
return n2 != source && n2 != null ? n2 : n1;
/* if ( n2 != null && n2 != source )
{
return n2;
}
else if ( n1 != null && n1 != source )
{
return n1;
}
else
{
new Throwable( "ups" ).printStackTrace();
throw new IllegalArgumentException( "internal error: getTarget: unknown source; " + source + " n1=" + n1 + " n2=" + n2 );
} */
}
/**
* Get the relevant next-pointer for the given source
*/
public final OsmLink getNext( OsmNode source )
{
return n2 != source && n2 != null ? next : previous;
/* if ( n2 != null && n2 != source )
{
return next;
}
else if ( n1 != null && n1 != source )
{
return previous;
}
else
{
throw new IllegalArgumentException( "internal error: gextNext: unknown source" );
} */
}
/**
* Reset this link for the given direction
*/
protected final OsmLink clear( OsmNode source )
{
OsmLink n;
if ( n2 != null && n2 != source )
{
n = next;
next = null;
n2 = null;
firstlinkholder = null;
}
else if ( n1 != null && n1 != source )
{
n = previous;
previous = null;
n1 = null;
reverselinkholder = null;
}
else
{
throw new IllegalArgumentException( "internal error: setNext: unknown source" );
}
if ( n1 == null && n2 == null )
{
descriptionBitmap = null;
geometry = null;
}
return n;
}
public final void setFirstLinkHolder( OsmLinkHolder holder, OsmNode source )
{
if ( n2 != null && n2 != source )
{
firstlinkholder = holder;
}
else if ( n1 != null && n1 != source )
{
reverselinkholder = holder;
}
else
{
throw new IllegalArgumentException( "internal error: setFirstLinkHolder: unknown source" );
}
}
public final OsmLinkHolder getFirstLinkHolder( OsmNode source )
{
if ( n2 != null && n2 != source )
{
return firstlinkholder;
}
else if ( n1 != null && n1 != source )
{
return reverselinkholder;
}
else
{
throw new IllegalArgumentException( "internal error: getFirstLinkHolder: unknown source" );
}
}
public final boolean isReverse( OsmNode source )
{
return n1 != source && n1 != null;
/* if ( n2 != null && n2 != source )
{
return false;
}
else if ( n1 != null && n1 != source )
{
return true;
}
else
{
throw new IllegalArgumentException( "internal error: isReverse: unknown source" );
} */
}
public final boolean isBidirectional()
{
return n1 != null && n2 != null;
}
public final boolean isLinkUnused()
{
return n1 == null && n2 == null;
}
public final void addLinkHolder( OsmLinkHolder holder, OsmNode source )
{
OsmLinkHolder firstHolder = getFirstLinkHolder( source );
if ( firstHolder != null ) { holder.setNextForLink( firstHolder ); }
setFirstLinkHolder( holder, source );
}
}
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
public class OsmLink {
/**
* The description bitmap contains the waytags (valid for both directions)
*/
public byte[] descriptionBitmap;
/**
* The geometry contains intermediate nodes, null for none (valid for both directions)
*/
public byte[] geometry;
// a link logically knows only its target, but for the reverse link, source and target are swapped
protected OsmNode n1;
protected OsmNode n2;
// same for the next-link-for-node pointer: previous applies to the reverse link
protected OsmLink previous;
protected OsmLink next;
private OsmLinkHolder reverselinkholder = null;
private OsmLinkHolder firstlinkholder = null;
protected OsmLink() {
}
public OsmLink(OsmNode source, OsmNode target) {
n1 = source;
n2 = target;
}
/**
* Get the relevant target-node for the given source
*/
public final OsmNode getTarget(OsmNode source) {
return n2 != source && n2 != null ? n2 : n1;
/* if ( n2 != null && n2 != source )
{
return n2;
}
else if ( n1 != null && n1 != source )
{
return n1;
}
else
{
new Throwable( "ups" ).printStackTrace();
throw new IllegalArgumentException( "internal error: getTarget: unknown source; " + source + " n1=" + n1 + " n2=" + n2 );
} */
}
/**
* Get the relevant next-pointer for the given source
*/
public final OsmLink getNext(OsmNode source) {
return n2 != source && n2 != null ? next : previous;
/* if ( n2 != null && n2 != source )
{
return next;
}
else if ( n1 != null && n1 != source )
{
return previous;
}
else
{
throw new IllegalArgumentException( "internal error: gextNext: unknown source" );
} */
}
/**
* Reset this link for the given direction
*/
protected final OsmLink clear(OsmNode source) {
OsmLink n;
if (n2 != null && n2 != source) {
n = next;
next = null;
n2 = null;
firstlinkholder = null;
} else if (n1 != null && n1 != source) {
n = previous;
previous = null;
n1 = null;
reverselinkholder = null;
} else {
throw new IllegalArgumentException("internal error: setNext: unknown source");
}
if (n1 == null && n2 == null) {
descriptionBitmap = null;
geometry = null;
}
return n;
}
public final void setFirstLinkHolder(OsmLinkHolder holder, OsmNode source) {
if (n2 != null && n2 != source) {
firstlinkholder = holder;
} else if (n1 != null && n1 != source) {
reverselinkholder = holder;
} else {
throw new IllegalArgumentException("internal error: setFirstLinkHolder: unknown source");
}
}
public final OsmLinkHolder getFirstLinkHolder(OsmNode source) {
if (n2 != null && n2 != source) {
return firstlinkholder;
} else if (n1 != null && n1 != source) {
return reverselinkholder;
} else {
throw new IllegalArgumentException("internal error: getFirstLinkHolder: unknown source");
}
}
public final boolean isReverse(OsmNode source) {
return n1 != source && n1 != null;
/* if ( n2 != null && n2 != source )
{
return false;
}
else if ( n1 != null && n1 != source )
{
return true;
}
else
{
throw new IllegalArgumentException( "internal error: isReverse: unknown source" );
} */
}
public final boolean isBidirectional() {
return n1 != null && n2 != null;
}
public final boolean isLinkUnused() {
return n1 == null && n2 == null;
}
public final void addLinkHolder(OsmLinkHolder holder, OsmNode source) {
OsmLinkHolder firstHolder = getFirstLinkHolder(source);
if (firstHolder != null) {
holder.setNextForLink(firstHolder);
}
setFirstLinkHolder(holder, source);
}
}

View file

@ -1,13 +1,12 @@
/**
* Container for routig configs
*
* @author ab
*/
package btools.mapaccess;
public interface OsmLinkHolder
{
void setNextForLink( OsmLinkHolder holder );
OsmLinkHolder getNextForLink();
}
/**
* Container for routig configs
*
* @author ab
*/
package btools.mapaccess;
public interface OsmLinkHolder {
void setNextForLink(OsmLinkHolder holder);
OsmLinkHolder getNextForLink();
}

View file

@ -11,8 +11,7 @@ import btools.util.ByteArrayUnifier;
import btools.util.CheapRuler;
import btools.util.IByteArrayUnifier;
public class OsmNode extends OsmLink implements OsmPos
{
public class OsmNode extends OsmLink implements OsmPos {
/**
* The latitude
*/
@ -34,11 +33,10 @@ public class OsmNode extends OsmLink implements OsmPos
public byte[] nodeDescription;
public TurnRestriction firstRestriction;
public int visitID;
public void addTurnRestriction( TurnRestriction tr )
{
public void addTurnRestriction(TurnRestriction tr) {
tr.next = firstRestriction;
firstRestriction = tr;
}
@ -48,62 +46,50 @@ public class OsmNode extends OsmLink implements OsmPos
*/
public OsmLink firstlink;
public OsmNode()
{
public OsmNode() {
}
public OsmNode( int ilon, int ilat )
{
public OsmNode(int ilon, int ilat) {
this.ilon = ilon;
this.ilat = ilat;
}
public OsmNode( long id )
{
ilon = (int) ( id >> 32 );
ilat = (int) ( id & 0xffffffff );
public OsmNode(long id) {
ilon = (int) (id >> 32);
ilat = (int) (id & 0xffffffff);
}
// interface OsmPos
public final int getILat()
{
public final int getILat() {
return ilat;
}
public final int getILon()
{
public final int getILon() {
return ilon;
}
public final short getSElev()
{
public final short getSElev() {
return selev;
}
public final double getElev()
{
public final double getElev() {
return selev / 4.;
}
public final void addLink( OsmLink link, boolean isReverse, OsmNode tn )
{
if ( link == firstlink )
{
throw new IllegalArgumentException( "UUUUPS" );
public final void addLink(OsmLink link, boolean isReverse, OsmNode tn) {
if (link == firstlink) {
throw new IllegalArgumentException("UUUUPS");
}
if ( isReverse )
{
if (isReverse) {
link.n1 = tn;
link.n2 = this;
link.next = tn.firstlink;
link.previous = firstlink;
tn.firstlink = link;
firstlink = link;
}
else
{
} else {
link.n1 = this;
link.n2 = tn;
link.next = firstlink;
@ -113,202 +99,167 @@ public class OsmNode extends OsmLink implements OsmPos
}
}
public final int calcDistance( OsmPos p )
{
return (int)(CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0 );
public final int calcDistance(OsmPos p) {
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
}
public String toString()
{
return "n_" + (ilon-180000000) + "_" + (ilat-90000000);
public String toString() {
return "n_" + (ilon - 180000000) + "_" + (ilat - 90000000);
}
public final void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay )
{
if ( mc instanceof MicroCache2 )
{
parseNodeBody2( (MicroCache2) mc, hollowNodes, expCtxWay );
}
else
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
public final void parseNodeBody(MicroCache mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay) {
if (mc instanceof MicroCache2) {
parseNodeBody2((MicroCache2) mc, hollowNodes, expCtxWay);
} else
throw new IllegalArgumentException("unknown cache version: " + mc.getClass());
}
public final void parseNodeBody2( MicroCache2 mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay )
{
public final void parseNodeBody2(MicroCache2 mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay) {
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
// read turn restrictions
while( mc.readBoolean() )
{
while (mc.readBoolean()) {
TurnRestriction tr = new TurnRestriction();
tr.exceptions = mc.readShort();
tr.isPositive = mc.readBoolean();
tr.exceptions = mc.readShort();
tr.isPositive = mc.readBoolean();
tr.fromLon = mc.readInt();
tr.fromLat = mc.readInt();
tr.toLon = mc.readInt();
tr.toLat = mc.readInt();
addTurnRestriction( tr );
addTurnRestriction(tr);
}
selev = mc.readShort();
int nodeDescSize = mc.readVarLengthUnsigned();
nodeDescription = nodeDescSize == 0 ? null : mc.readUnified( nodeDescSize, abUnifier );
nodeDescription = nodeDescSize == 0 ? null : mc.readUnified(nodeDescSize, abUnifier);
while (mc.hasMoreData())
{
while (mc.hasMoreData()) {
// read link data
int endPointer = mc.getEndPointer();
int linklon = ilon + mc.readVarLengthSigned();
int linklat = ilat + mc.readVarLengthSigned();
int sizecode = mc.readVarLengthUnsigned();
boolean isReverse = ( sizecode & 1 ) != 0;
boolean isReverse = (sizecode & 1) != 0;
byte[] description = null;
int descSize = sizecode >> 1;
if ( descSize > 0 )
{
description = mc.readUnified( descSize, expCtxWay );
if (descSize > 0) {
description = mc.readUnified(descSize, expCtxWay);
}
byte[] geometry = mc.readDataUntil( endPointer );
byte[] geometry = mc.readDataUntil(endPointer);
addLink( linklon, linklat, description, geometry, hollowNodes, isReverse );
addLink(linklon, linklat, description, geometry, hollowNodes, isReverse);
}
hollowNodes.remove( this );
hollowNodes.remove(this);
}
public void addLink( int linklon, int linklat, byte[] description, byte[] geometry, OsmNodesMap hollowNodes, boolean isReverse )
{
if ( linklon == ilon && linklat == ilat )
{
return; // skip self-ref
}
public void addLink(int linklon, int linklat, byte[] description, byte[] geometry, OsmNodesMap hollowNodes, boolean isReverse) {
if (linklon == ilon && linklat == ilat) {
return; // skip self-ref
}
OsmNode tn = null; // find the target node
OsmLink link = null;
OsmNode tn = null; // find the target node
OsmLink link = null;
// ...in our known links
for ( OsmLink l = firstlink; l != null; l = l.getNext( this ) )
{
OsmNode t = l.getTarget( this );
if ( t.ilon == linklon && t.ilat == linklat )
{
tn = t;
if ( isReverse || ( l.descriptionBitmap == null && !l.isReverse( this ) ) )
{
link = l; // the correct one that needs our data
break;
}
// ...in our known links
for (OsmLink l = firstlink; l != null; l = l.getNext(this)) {
OsmNode t = l.getTarget(this);
if (t.ilon == linklon && t.ilat == linklat) {
tn = t;
if (isReverse || (l.descriptionBitmap == null && !l.isReverse(this))) {
link = l; // the correct one that needs our data
break;
}
}
if ( tn == null ) // .. not found, then check the hollow nodes
}
if (tn == null) // .. not found, then check the hollow nodes
{
tn = hollowNodes.get(linklon, linklat); // target node
if (tn == null) // node not yet known, create a new hollow proxy
{
tn = hollowNodes.get( linklon, linklat ); // target node
if ( tn == null ) // node not yet known, create a new hollow proxy
{
tn = new OsmNode( linklon, linklat );
tn.setHollow();
hollowNodes.put( tn );
addLink( link = tn, isReverse, tn ); // technical inheritance: link instance in node
}
}
if ( link == null )
{
addLink( link = new OsmLink(), isReverse, tn );
}
if ( !isReverse )
{
link.descriptionBitmap = description;
link.geometry = geometry;
tn = new OsmNode(linklon, linklat);
tn.setHollow();
hollowNodes.put(tn);
addLink(link = tn, isReverse, tn); // technical inheritance: link instance in node
}
}
if (link == null) {
addLink(link = new OsmLink(), isReverse, tn);
}
if (!isReverse) {
link.descriptionBitmap = description;
link.geometry = geometry;
}
}
public final boolean isHollow()
{
public final boolean isHollow() {
return selev == -12345;
}
public final void setHollow()
{
public final void setHollow() {
selev = -12345;
}
public final long getIdFromPos()
{
return ( (long) ilon ) << 32 | ilat;
public final long getIdFromPos() {
return ((long) ilon) << 32 | ilat;
}
public void vanish()
{
if ( !isHollow() )
{
public void vanish() {
if (!isHollow()) {
OsmLink l = firstlink;
while( l != null )
{
OsmNode target = l.getTarget( this );
OsmLink nextLink = l.getNext( this );
if ( !target.isHollow() )
{
unlinkLink( l );
if ( !l.isLinkUnused() )
{
target.unlinkLink( l );
}
while (l != null) {
OsmNode target = l.getTarget(this);
OsmLink nextLink = l.getNext(this);
if (!target.isHollow()) {
unlinkLink(l);
if (!l.isLinkUnused()) {
target.unlinkLink(l);
}
}
l = nextLink;
}
}
}
public final void unlinkLink( OsmLink link )
{
OsmLink n = link.clear( this );
public final void unlinkLink(OsmLink link) {
OsmLink n = link.clear(this);
if ( link == firstlink )
{
if (link == firstlink) {
firstlink = n;
return;
}
OsmLink l = firstlink;
while( l != null )
{
while (l != null) {
// if ( l.isReverse( this ) )
if ( l.n1 != this && l.n1 != null ) // isReverse inline
if (l.n1 != this && l.n1 != null) // isReverse inline
{
OsmLink nl = l.previous;
if ( nl == link )
{
if (nl == link) {
l.previous = n;
return;
}
l = nl;
}
else if ( l.n2 != this && l.n2 != null )
{
} else if (l.n2 != this && l.n2 != null) {
OsmLink nl = l.next;
if ( nl == link )
{
if (nl == link) {
l.next = n;
return;
}
l = nl;
}
else
{
throw new IllegalArgumentException( "unlinkLink: unknown source" );
} else {
throw new IllegalArgumentException("unlinkLink: unknown source");
}
}
}
@Override
public final boolean equals( Object o )
{
return ((OsmNode)o).ilon == ilon && ((OsmNode)o).ilat == ilat;
public final boolean equals(Object o) {
return ((OsmNode) o).ilon == ilon && ((OsmNode) o).ilat == ilat;
}
@Override
public final int hashCode()
{
public final int hashCode() {
return ilon + ilat;
}
}

View file

@ -7,8 +7,7 @@ package btools.mapaccess;
import btools.util.CompactLongMap;
public class OsmNodePairSet
{
public class OsmNodePairSet {
private long[] n1a;
private long[] n2a;
private int tempNodes = 0;
@ -16,108 +15,86 @@ public class OsmNodePairSet
private int npairs = 0;
private int freezecount = 0;
public OsmNodePairSet( int maxTempNodeCount )
{
public OsmNodePairSet(int maxTempNodeCount) {
maxTempNodes = maxTempNodeCount;
n1a = new long[maxTempNodes];
n2a = new long[maxTempNodes];
}
private static class OsmNodePair
{
private static class OsmNodePair {
public long node2;
public OsmNodePair next;
}
private CompactLongMap<OsmNodePair> map;
public void addTempPair( long n1, long n2 )
{
if ( tempNodes < maxTempNodes )
{
public void addTempPair(long n1, long n2) {
if (tempNodes < maxTempNodes) {
n1a[tempNodes] = n1;
n2a[tempNodes] = n2;
tempNodes++;
}
}
public void freezeTempPairs()
{
public void freezeTempPairs() {
freezecount++;
for( int i=0; i<tempNodes; i++ )
{
addPair( n1a[i], n2a[i] );
for (int i = 0; i < tempNodes; i++) {
addPair(n1a[i], n2a[i]);
}
tempNodes = 0;
}
public void clearTempPairs()
{
public void clearTempPairs() {
tempNodes = 0;
}
private void addPair( long n1, long n2 )
{
if ( map == null )
{
private void addPair(long n1, long n2) {
if (map == null) {
map = new CompactLongMap<OsmNodePair>();
}
npairs++;
OsmNodePair e = getElement( n1, n2 );
if ( e == null )
{
OsmNodePair e = getElement(n1, n2);
if (e == null) {
e = new OsmNodePair();
e.node2 = n2;
OsmNodePair e0 = map.get( n1 );
if ( e0 != null )
{
while( e0.next != null )
{
OsmNodePair e0 = map.get(n1);
if (e0 != null) {
while (e0.next != null) {
e0 = e0.next;
}
e0.next = e;
}
else
{
map.fastPut( n1, e );
} else {
map.fastPut(n1, e);
}
}
}
public int size()
{
public int size() {
return npairs;
}
public int tempSize()
{
public int tempSize() {
return tempNodes;
}
public int getMaxTmpNodes()
{
public int getMaxTmpNodes() {
return maxTempNodes;
}
public int getFreezeCount()
{
public int getFreezeCount() {
return freezecount;
}
public boolean hasPair( long n1, long n2 )
{
return map != null && ( getElement( n1, n2 ) != null || getElement( n2, n1 ) != null );
public boolean hasPair(long n1, long n2) {
return map != null && (getElement(n1, n2) != null || getElement(n2, n1) != null);
}
private OsmNodePair getElement( long n1, long n2 )
{
OsmNodePair e = map.get( n1 );
while (e != null)
{
if ( e.node2 == n2 )
{
private OsmNodePair getElement(long n1, long n2) {
OsmNodePair e = map.get(n1);
while (e != null) {
if (e.node2 == n2) {
return e;
}
e = e.next;

View file

@ -1,348 +1,293 @@
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
import java.util.ArrayList;
import java.util.HashMap;
import btools.util.ByteArrayUnifier;
import btools.util.SortedHeap;
public final class OsmNodesMap
{
private HashMap<OsmNode,OsmNode> hmap = new HashMap<OsmNode,OsmNode>(4096);
private ByteArrayUnifier abUnifier = new ByteArrayUnifier( 16384, false );
private OsmNode testKey = new OsmNode();
public int nodesCreated;
public long maxmem;
private long currentmaxmem = 4000000; // start with 4 MB
public int lastVisitID = 1000;
public int baseID = 1000;
public OsmNode destination;
public int currentPathCost;
public int currentMaxCost = 1000000000;
public OsmNode endNode1;
public OsmNode endNode2;
public int cleanupMode = 0;
public void cleanupAndCount( OsmNode[] nodes )
{
if ( cleanupMode == 0 )
{
justCount( nodes );
}
else
{
cleanupPeninsulas( nodes );
}
}
private void justCount( OsmNode[] nodes )
{
for( int i=0; i<nodes.length; i++ )
{
OsmNode n = nodes[i];
if ( n.firstlink != null )
{
nodesCreated++;
}
}
}
private void cleanupPeninsulas( OsmNode[] nodes )
{
baseID = lastVisitID++;
for( int i=0; i<nodes.length; i++ ) // loop over nodes again just for housekeeping
{
OsmNode n = nodes[i];
if ( n.firstlink != null )
{
if ( n.visitID == 1 )
{
try
{
minVisitIdInSubtree( null, n );
}
catch( StackOverflowError soe )
{
// System.out.println( "+++++++++++++++ StackOverflowError ++++++++++++++++" );
}
}
}
}
}
private int minVisitIdInSubtree( OsmNode source, OsmNode n )
{
if ( n.visitID == 1 ) n.visitID = baseID; // border node
else n.visitID = lastVisitID++;
int minId = n.visitID;
nodesCreated++;
OsmLink nextLink = null;
for( OsmLink l = n.firstlink; l != null; l = nextLink )
{
nextLink = l.getNext( n );
OsmNode t = l.getTarget( n );
if ( t == source ) continue;
if ( t.isHollow() ) continue;
int minIdSub = t.visitID;
if ( minIdSub == 1 )
{
minIdSub = baseID;
}
else if ( minIdSub == 0 )
{
int nodesCreatedUntilHere = nodesCreated;
minIdSub = minVisitIdInSubtree( n, t);
if ( minIdSub > n.visitID ) // peninsula ?
{
nodesCreated = nodesCreatedUntilHere;
n.unlinkLink( l );
t.unlinkLink( l );
}
}
else if ( minIdSub < baseID )
{
continue;
}
else if ( cleanupMode == 2 )
{
minIdSub = baseID; // in tree-mode, hitting anything is like a gateway
}
if ( minIdSub < minId ) minId = minIdSub;
}
return minId;
}
public boolean isInMemoryBounds( int npaths, boolean extend )
{
// long total = nodesCreated * 76L + linksCreated * 48L;
long total = nodesCreated * 95L + npaths * 200L;
if ( extend )
{
total += 100000;
// when extending, try to have 1 MB space
long delta = total + 1900000 - currentmaxmem;
if ( delta > 0 )
{
currentmaxmem += delta;
if ( currentmaxmem > maxmem )
{
currentmaxmem = maxmem;
}
}
}
return total <= currentmaxmem;
}
private void addActiveNode( ArrayList<OsmNode> nodes2check, OsmNode n )
{
n.visitID = lastVisitID;
nodesCreated++;
nodes2check.add( n );
}
// is there an escape from this node
// to a hollow node (or destination node) ?
public boolean canEscape( OsmNode n0 )
{
boolean sawLowIDs = false;
lastVisitID++;
nodes2check.clear();
nodes2check.add( n0 );
while ( !nodes2check.isEmpty() )
{
OsmNode n = nodes2check.remove( nodes2check.size()-1 );
if ( n.visitID < baseID )
{
n.visitID = lastVisitID;
nodesCreated++;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
OsmNode t = l.getTarget( n );
nodes2check.add( t );
}
}
else if ( n.visitID < lastVisitID )
{
sawLowIDs = true;
}
}
if ( sawLowIDs )
{
return true;
}
nodes2check.add( n0 );
while ( !nodes2check.isEmpty() )
{
OsmNode n = nodes2check.remove( nodes2check.size()-1 );
if ( n.visitID == lastVisitID )
{
n.visitID = lastVisitID;
nodesCreated--;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
OsmNode t = l.getTarget( n );
nodes2check.add( t );
}
n.vanish();
}
}
return false;
}
private ArrayList<OsmNode> nodes2check;
public void clearTemp()
{
nodes2check = null;
}
public void collectOutreachers()
{
nodes2check = new ArrayList<OsmNode>(nodesCreated);
nodesCreated=0;
for( OsmNode n : hmap.values() )
{
addActiveNode( nodes2check, n );
}
lastVisitID++;
baseID = lastVisitID;
while ( !nodes2check.isEmpty() )
{
OsmNode n = nodes2check.remove( nodes2check.size()-1 );
n.visitID = lastVisitID;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
OsmNode t = l.getTarget( n );
if ( t.visitID != lastVisitID )
{
addActiveNode( nodes2check, t );
}
}
if ( destination != null && currentMaxCost < 1000000000 )
{
int distance = n.calcDistance( destination );
if ( distance > currentMaxCost - currentPathCost + 100 )
{
n.vanish();
}
}
if ( n.firstlink == null )
{
nodesCreated--;
}
}
}
public ByteArrayUnifier getByteArrayUnifier()
{
return abUnifier;
}
/**
* Get a node from the map
* @return the node for the given id if exist, else null
*/
public OsmNode get( int ilon, int ilat )
{
testKey.ilon = ilon;
testKey.ilat = ilat;
return hmap.get( testKey );
}
public void remove( OsmNode node )
{
if ( node != endNode1 && node != endNode2 ) // keep endnodes in hollow-map even when loaded
{ // (needed for escape analysis)
hmap.remove( node );
}
}
/**
* Put a node into the map
* @return the previous node if that id existed, else null
*/
public OsmNode put( OsmNode node )
{
return hmap.put( node, node );
}
// ********************** test cleanup **********************
private static void addLinks( OsmNode[] nodes, int idx, boolean isBorder, int[] links )
{
OsmNode n = nodes[idx];
n.visitID = isBorder ? 1 : 0;
n.selev = (short)idx;
for( int i : links )
{
OsmNode t = nodes[i];
OsmLink link = n.isLinkUnused() ? n : ( t.isLinkUnused() ? t : null );
if ( link == null )
{
link = new OsmLink();
}
n.addLink( link, false, t );
}
}
public static void main( String[] args )
{
OsmNode[] nodes = new OsmNode[12];
for( int i=0; i<nodes.length; i++ )
{
nodes[i]= new OsmNode( (i+1000)*1000,(i+1000)*1000 );
}
addLinks( nodes, 0, true , new int[]{1,5} ); // 0
addLinks( nodes, 1, true , new int[]{} ); // 1
addLinks( nodes, 2, false, new int[]{3,4} ); // 2
addLinks( nodes, 3, false, new int[]{4} ); // 3
addLinks( nodes, 4, false, new int[]{} ); // 4
addLinks( nodes, 5, true , new int[]{6,9} ); // 5
addLinks( nodes, 6, false, new int[]{7,8} ); // 6
addLinks( nodes, 7, false, new int[]{} ); // 7
addLinks( nodes, 8, false, new int[]{} ); // 8
addLinks( nodes, 9, false, new int[]{10,11} ); // 9
addLinks( nodes, 10, false, new int[]{11} ); // 10
addLinks( nodes, 11, false, new int[]{} ); // 11
OsmNodesMap nm = new OsmNodesMap();
nm.cleanupMode = 2;
nm.cleanupAndCount( nodes );
System.out.println( "nodesCreated=" + nm.nodesCreated );
nm.cleanupAndCount( nodes );
System.out.println( "nodesCreated=" + nm.nodesCreated );
}
}
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
import java.util.ArrayList;
import java.util.HashMap;
import btools.util.ByteArrayUnifier;
import btools.util.SortedHeap;
public final class OsmNodesMap {
private HashMap<OsmNode, OsmNode> hmap = new HashMap<OsmNode, OsmNode>(4096);
private ByteArrayUnifier abUnifier = new ByteArrayUnifier(16384, false);
private OsmNode testKey = new OsmNode();
public int nodesCreated;
public long maxmem;
private long currentmaxmem = 4000000; // start with 4 MB
public int lastVisitID = 1000;
public int baseID = 1000;
public OsmNode destination;
public int currentPathCost;
public int currentMaxCost = 1000000000;
public OsmNode endNode1;
public OsmNode endNode2;
public int cleanupMode = 0;
public void cleanupAndCount(OsmNode[] nodes) {
if (cleanupMode == 0) {
justCount(nodes);
} else {
cleanupPeninsulas(nodes);
}
}
private void justCount(OsmNode[] nodes) {
for (int i = 0; i < nodes.length; i++) {
OsmNode n = nodes[i];
if (n.firstlink != null) {
nodesCreated++;
}
}
}
private void cleanupPeninsulas(OsmNode[] nodes) {
baseID = lastVisitID++;
for (int i = 0; i < nodes.length; i++) // loop over nodes again just for housekeeping
{
OsmNode n = nodes[i];
if (n.firstlink != null) {
if (n.visitID == 1) {
try {
minVisitIdInSubtree(null, n);
} catch (StackOverflowError soe) {
// System.out.println( "+++++++++++++++ StackOverflowError ++++++++++++++++" );
}
}
}
}
}
private int minVisitIdInSubtree(OsmNode source, OsmNode n) {
if (n.visitID == 1) n.visitID = baseID; // border node
else n.visitID = lastVisitID++;
int minId = n.visitID;
nodesCreated++;
OsmLink nextLink = null;
for (OsmLink l = n.firstlink; l != null; l = nextLink) {
nextLink = l.getNext(n);
OsmNode t = l.getTarget(n);
if (t == source) continue;
if (t.isHollow()) continue;
int minIdSub = t.visitID;
if (minIdSub == 1) {
minIdSub = baseID;
} else if (minIdSub == 0) {
int nodesCreatedUntilHere = nodesCreated;
minIdSub = minVisitIdInSubtree(n, t);
if (minIdSub > n.visitID) // peninsula ?
{
nodesCreated = nodesCreatedUntilHere;
n.unlinkLink(l);
t.unlinkLink(l);
}
} else if (minIdSub < baseID) {
continue;
} else if (cleanupMode == 2) {
minIdSub = baseID; // in tree-mode, hitting anything is like a gateway
}
if (minIdSub < minId) minId = minIdSub;
}
return minId;
}
public boolean isInMemoryBounds(int npaths, boolean extend) {
// long total = nodesCreated * 76L + linksCreated * 48L;
long total = nodesCreated * 95L + npaths * 200L;
if (extend) {
total += 100000;
// when extending, try to have 1 MB space
long delta = total + 1900000 - currentmaxmem;
if (delta > 0) {
currentmaxmem += delta;
if (currentmaxmem > maxmem) {
currentmaxmem = maxmem;
}
}
}
return total <= currentmaxmem;
}
private void addActiveNode(ArrayList<OsmNode> nodes2check, OsmNode n) {
n.visitID = lastVisitID;
nodesCreated++;
nodes2check.add(n);
}
// is there an escape from this node
// to a hollow node (or destination node) ?
public boolean canEscape(OsmNode n0) {
boolean sawLowIDs = false;
lastVisitID++;
nodes2check.clear();
nodes2check.add(n0);
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
if (n.visitID < baseID) {
n.visitID = lastVisitID;
nodesCreated++;
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
nodes2check.add(t);
}
} else if (n.visitID < lastVisitID) {
sawLowIDs = true;
}
}
if (sawLowIDs) {
return true;
}
nodes2check.add(n0);
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
if (n.visitID == lastVisitID) {
n.visitID = lastVisitID;
nodesCreated--;
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
nodes2check.add(t);
}
n.vanish();
}
}
return false;
}
private ArrayList<OsmNode> nodes2check;
public void clearTemp() {
nodes2check = null;
}
public void collectOutreachers() {
nodes2check = new ArrayList<OsmNode>(nodesCreated);
nodesCreated = 0;
for (OsmNode n : hmap.values()) {
addActiveNode(nodes2check, n);
}
lastVisitID++;
baseID = lastVisitID;
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
n.visitID = lastVisitID;
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
if (t.visitID != lastVisitID) {
addActiveNode(nodes2check, t);
}
}
if (destination != null && currentMaxCost < 1000000000) {
int distance = n.calcDistance(destination);
if (distance > currentMaxCost - currentPathCost + 100) {
n.vanish();
}
}
if (n.firstlink == null) {
nodesCreated--;
}
}
}
public ByteArrayUnifier getByteArrayUnifier() {
return abUnifier;
}
/**
* Get a node from the map
*
* @return the node for the given id if exist, else null
*/
public OsmNode get(int ilon, int ilat) {
testKey.ilon = ilon;
testKey.ilat = ilat;
return hmap.get(testKey);
}
public void remove(OsmNode node) {
if (node != endNode1 && node != endNode2) // keep endnodes in hollow-map even when loaded
{ // (needed for escape analysis)
hmap.remove(node);
}
}
/**
* Put a node into the map
*
* @return the previous node if that id existed, else null
*/
public OsmNode put(OsmNode node) {
return hmap.put(node, node);
}
// ********************** test cleanup **********************
private static void addLinks(OsmNode[] nodes, int idx, boolean isBorder, int[] links) {
OsmNode n = nodes[idx];
n.visitID = isBorder ? 1 : 0;
n.selev = (short) idx;
for (int i : links) {
OsmNode t = nodes[i];
OsmLink link = n.isLinkUnused() ? n : (t.isLinkUnused() ? t : null);
if (link == null) {
link = new OsmLink();
}
n.addLink(link, false, t);
}
}
public static void main(String[] args) {
OsmNode[] nodes = new OsmNode[12];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = new OsmNode((i + 1000) * 1000, (i + 1000) * 1000);
}
addLinks(nodes, 0, true, new int[]{1, 5}); // 0
addLinks(nodes, 1, true, new int[]{}); // 1
addLinks(nodes, 2, false, new int[]{3, 4}); // 2
addLinks(nodes, 3, false, new int[]{4}); // 3
addLinks(nodes, 4, false, new int[]{}); // 4
addLinks(nodes, 5, true, new int[]{6, 9}); // 5
addLinks(nodes, 6, false, new int[]{7, 8}); // 6
addLinks(nodes, 7, false, new int[]{}); // 7
addLinks(nodes, 8, false, new int[]{}); // 8
addLinks(nodes, 9, false, new int[]{10, 11}); // 9
addLinks(nodes, 10, false, new int[]{11}); // 10
addLinks(nodes, 11, false, new int[]{}); // 11
OsmNodesMap nm = new OsmNodesMap();
nm.cleanupMode = 2;
nm.cleanupAndCount(nodes);
System.out.println("nodesCreated=" + nm.nodesCreated);
nm.cleanupAndCount(nodes);
System.out.println("nodesCreated=" + nm.nodesCreated);
}
}

View file

@ -1,23 +1,22 @@
/**
* Interface for a position (OsmNode or OsmPath)
*
* @author ab
*/
package btools.mapaccess;
public interface OsmPos
{
public int getILat();
public int getILon();
public short getSElev();
public double getElev();
public int calcDistance( OsmPos p );
public long getIdFromPos();
}
/**
* Interface for a position (OsmNode or OsmPath)
*
* @author ab
*/
package btools.mapaccess;
public interface OsmPos {
public int getILat();
public int getILon();
public short getSElev();
public double getElev();
public int calcDistance(OsmPos p);
public long getIdFromPos();
}

View file

@ -1,19 +1,16 @@
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
public final class OsmTransferNode
{
public OsmTransferNode next;
public int ilon;
public int ilat;
public short selev;
}
/**
* Container for link between two Osm nodes
*
* @author ab
*/
package btools.mapaccess;
public final class OsmTransferNode {
public OsmTransferNode next;
public int ilon;
public int ilat;
public short selev;
}

View file

@ -14,29 +14,27 @@ import btools.codec.MicroCache;
import btools.util.ByteDataReader;
import btools.util.Crc32;
final public class PhysicalFile
{
final public class PhysicalFile {
RandomAccessFile ra = null;
long[] fileIndex = new long[25];
int[] fileHeaderCrcs;
private int fileIndexCrc;
public long creationTime;
String fileName;
public int divisor = 80;
public static void main( String[] args )
{
public static void main(String[] args) {
MicroCache.debug = true;
try {
checkFileIntegrity( new File( args[0] ) );
checkFileIntegrity(new File(args[0]));
} catch (IOException e) {
System.err.println( "************************************" );
System.err.println("************************************");
e.printStackTrace();
System.err.println( "************************************" );
System.err.println("************************************");
}
}
@ -45,56 +43,46 @@ final public class PhysicalFile
*
* @return the error message if file corrupt, else null
*/
public static String checkFileIntegrity( File f ) throws IOException
{
public static String checkFileIntegrity(File f) throws IOException {
PhysicalFile pf = null;
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
pf = new PhysicalFile( f, dataBuffers, -1, -1 );
pf = new PhysicalFile(f, dataBuffers, -1, -1);
int div = pf.divisor;
for ( int lonDegree = 0; lonDegree < 5; lonDegree++ ) // does'nt really matter..
for (int lonDegree = 0; lonDegree < 5; lonDegree++) // does'nt really matter..
{
for ( int latDegree = 0; latDegree < 5; latDegree++ ) // ..where on earth we are
for (int latDegree = 0; latDegree < 5; latDegree++) // ..where on earth we are
{
OsmFile osmf = new OsmFile( pf, lonDegree, latDegree, dataBuffers );
if ( osmf.hasData() )
for ( int lonIdx = 0; lonIdx < div; lonIdx++ )
for ( int latIdx = 0; latIdx < div; latIdx++ )
osmf.createMicroCache( lonDegree * div + lonIdx, latDegree * div + latIdx, dataBuffers, null, null, MicroCache.debug, null );
OsmFile osmf = new OsmFile(pf, lonDegree, latDegree, dataBuffers);
if (osmf.hasData())
for (int lonIdx = 0; lonIdx < div; lonIdx++)
for (int latIdx = 0; latIdx < div; latIdx++)
osmf.createMicroCache(lonDegree * div + lonIdx, latDegree * div + latIdx, dataBuffers, null, null, MicroCache.debug, null);
}
}
}
finally
{
if ( pf != null )
try
{
} finally {
if (pf != null)
try {
pf.ra.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
return null;
}
public PhysicalFile( File f, DataBuffers dataBuffers, int lookupVersion, int lookupMinorVersion ) throws IOException
{
public PhysicalFile(File f, DataBuffers dataBuffers, int lookupVersion, int lookupMinorVersion) throws IOException {
fileName = f.getName();
byte[] iobuffer = dataBuffers.iobuffer;
ra = new RandomAccessFile( f, "r" );
ra.readFully( iobuffer, 0, 200 );
fileIndexCrc = Crc32.crc( iobuffer, 0, 200 );
ByteDataReader dis = new ByteDataReader( iobuffer );
for( int i=0; i<25; i++ )
{
ra = new RandomAccessFile(f, "r");
ra.readFully(iobuffer, 0, 200);
fileIndexCrc = Crc32.crc(iobuffer, 0, 200);
ByteDataReader dis = new ByteDataReader(iobuffer);
for (int i = 0; i < 25; i++) {
long lv = dis.readLong();
short readVersion = (short)(lv >> 48);
if ( i == 0 && lookupVersion != -1 && readVersion != lookupVersion )
{
throw new IOException( "lookup version mismatch (old rd5?) lookups.dat="
+ lookupVersion + " " + f. getAbsolutePath() + "=" + readVersion );
short readVersion = (short) (lv >> 48);
if (i == 0 && lookupVersion != -1 && readVersion != lookupVersion) {
throw new IOException("lookup version mismatch (old rd5?) lookups.dat="
+ lookupVersion + " " + f.getAbsolutePath() + "=" + readVersion);
}
fileIndex[i] = lv & 0xffffffffffffL;
}
@ -103,36 +91,30 @@ final public class PhysicalFile
long len = ra.length();
long pos = fileIndex[24];
int extraLen = 8 + 26*4;
int extraLen = 8 + 26 * 4;
if ( len == pos ) return; // old format o.k.
if (len == pos) return; // old format o.k.
if ( len < pos+extraLen ) // > is o.k. for future extensions!
if (len < pos + extraLen) // > is o.k. for future extensions!
{
throw new IOException( "file of size " + len + " too short, should be " + (pos+extraLen) );
throw new IOException("file of size " + len + " too short, should be " + (pos + extraLen));
}
ra.seek( pos );
ra.readFully( iobuffer, 0, extraLen );
dis = new ByteDataReader( iobuffer );
ra.seek(pos);
ra.readFully(iobuffer, 0, extraLen);
dis = new ByteDataReader(iobuffer);
creationTime = dis.readLong();
int crcData = dis.readInt();
if ( crcData == fileIndexCrc )
{
if (crcData == fileIndexCrc) {
divisor = 80; // old format
}
else if ( (crcData ^ 2) == fileIndexCrc )
{
} else if ((crcData ^ 2) == fileIndexCrc) {
divisor = 32; // new format
}
else
{
throw new IOException( "top index checksum error" );
} else {
throw new IOException("top index checksum error");
}
fileHeaderCrcs = new int[25];
for( int i=0; i<25; i++ )
{
for (int i = 0; i < 25; i++) {
fileHeaderCrcs[i] = dis.readInt();
}
}

View file

@ -13,90 +13,77 @@ import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
final public class Rd5DiffManager
{
public static void main( String[] args ) throws Exception
{
calcDiffs( new File( args[0] ),new File( args[1] ) );
final public class Rd5DiffManager {
public static void main(String[] args) throws Exception {
calcDiffs(new File(args[0]), new File(args[1]));
}
/**
* Compute diffs for all RD5 files
*/
public static void calcDiffs( File oldDir, File newDir ) throws Exception
{
File oldDiffDir = new File( oldDir, "diff" );
File newDiffDir = new File( newDir, "diff" );
public static void calcDiffs(File oldDir, File newDir) throws Exception {
File oldDiffDir = new File(oldDir, "diff");
File newDiffDir = new File(newDir, "diff");
File[] filesNew = newDir.listFiles();
for( File fn : filesNew )
{
for (File fn : filesNew) {
String name = fn.getName();
if ( !name.endsWith( ".rd5" ) )
{
if (!name.endsWith(".rd5")) {
continue;
}
if ( fn.length() < 1024*1024 )
{
if (fn.length() < 1024 * 1024) {
continue; // exclude very small files from diffing
}
String basename = name.substring( 0, name.length() - 4 );
File fo = new File( oldDir, name );
if ( !fo.isFile() )
{
String basename = name.substring(0, name.length() - 4);
File fo = new File(oldDir, name);
if (!fo.isFile()) {
continue;
}
// calculate MD5 of old file
String md5 = getMD5( fo );
String md5New = getMD5( fn );
System.out.println( "name=" + name + " md5=" + md5 );
File specificNewDiffs = new File( newDiffDir, basename );
// calculate MD5 of old file
String md5 = getMD5(fo);
String md5New = getMD5(fn);
System.out.println("name=" + name + " md5=" + md5);
File specificNewDiffs = new File(newDiffDir, basename);
specificNewDiffs.mkdirs();
String diffFileName = md5 + ".df5";
File diffFile = new File( specificNewDiffs, diffFileName );
File diffFile = new File(specificNewDiffs, diffFileName);
String dummyDiffFileName = md5New + ".df5";
File dummyDiffFile = new File( specificNewDiffs, dummyDiffFileName );
File dummyDiffFile = new File(specificNewDiffs, dummyDiffFileName);
dummyDiffFile.createNewFile();
// calc the new diff
Rd5DiffTool.diff2files( fo, fn, diffFile );
Rd5DiffTool.diff2files(fo, fn, diffFile);
// ... and add that to old diff files
File specificOldDiffs = new File( oldDiffDir, basename );
if ( specificOldDiffs.isDirectory() )
{
File specificOldDiffs = new File(oldDiffDir, basename);
if (specificOldDiffs.isDirectory()) {
File[] oldDiffs = specificOldDiffs.listFiles();
for( File od : oldDiffs )
{
if ( !od.getName().endsWith( ".df5" ) )
{
for (File od : oldDiffs) {
if (!od.getName().endsWith(".df5")) {
continue;
}
if ( System.currentTimeMillis() - od.lastModified() > 9*86400000L )
{
if (System.currentTimeMillis() - od.lastModified() > 9 * 86400000L) {
continue; // limit diff history to 9 days
}
File updatedDiff = new File( specificNewDiffs, od.getName() );
if ( !updatedDiff.exists() )
{
Rd5DiffTool.addDeltas( od, diffFile, updatedDiff );
updatedDiff.setLastModified( od.lastModified() );
File updatedDiff = new File(specificNewDiffs, od.getName());
if (!updatedDiff.exists()) {
Rd5DiffTool.addDeltas(od, diffFile, updatedDiff);
updatedDiff.setLastModified(od.lastModified());
}
}
}
}
}
public static String getMD5( File f ) throws IOException
{
public static String getMD5(File f) throws IOException {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
@ -121,9 +108,8 @@ final public class Rd5DiffManager
throw new IOException("MD5 algorithm not available", e);
}
}
private static char hexChar( int v )
{
return (char) ( v > 9 ? 'a' + (v-10) : '0' + v );
private static char hexChar(int v) {
return (char) (v > 9 ? 'a' + (v - 10) : '0' + v);
}
}

View file

@ -22,179 +22,147 @@ import btools.codec.StatCoderContext;
import btools.util.Crc32;
import btools.util.ProgressListener;
final public class Rd5DiffTool implements ProgressListener
{
public static void main( String[] args ) throws Exception
{
if ( args.length == 2 )
{
reEncode( new File( args[0] ),new File( args[1] ) );
final public class Rd5DiffTool implements ProgressListener {
public static void main(String[] args) throws Exception {
if (args.length == 2) {
reEncode(new File(args[0]), new File(args[1]));
return;
}
if ( args[1].endsWith( ".df5" ) )
{
if ( args[0].endsWith( ".df5" ) )
{
addDeltas( new File( args[0] ),new File( args[1] ), new File( args[2] ) );
if (args[1].endsWith(".df5")) {
if (args[0].endsWith(".df5")) {
addDeltas(new File(args[0]), new File(args[1]), new File(args[2]));
} else {
recoverFromDelta(new File(args[0]), new File(args[1]), new File(args[2]), new Rd5DiffTool() /*, new File( args[3] ) */);
}
else
{
recoverFromDelta( new File( args[0] ),new File( args[1] ), new File( args[2] ), new Rd5DiffTool() /*, new File( args[3] ) */ );
}
}
else
{
diff2files( new File( args[0] ),new File( args[1] ), new File( args[2] ) );
} else {
diff2files(new File(args[0]), new File(args[1]), new File(args[2]));
}
}
@Override
public void updateProgress(String task, int progress) {
System.out.println(task + ": " + progress + "%");
}
@Override
public boolean isCanceled()
{
return false;
}
@Override
public void updateProgress(String task, int progress) {
System.out.println(task + ": " + progress + "%");
}
private static long[] readFileIndex( DataInputStream dis, DataOutputStream dos ) throws IOException
{
@Override
public boolean isCanceled() {
return false;
}
private static long[] readFileIndex(DataInputStream dis, DataOutputStream dos) throws IOException {
long[] fileIndex = new long[25];
for( int i=0; i<25; i++ )
{
for (int i = 0; i < 25; i++) {
long lv = dis.readLong();
fileIndex[i] = lv & 0xffffffffffffL;
if ( dos != null )
{
dos.writeLong( lv );
if (dos != null) {
dos.writeLong(lv);
}
}
return fileIndex;
}
private static long getTileStart( long[] index, int tileIndex )
{
private static long getTileStart(long[] index, int tileIndex) {
return tileIndex > 0 ? index[tileIndex - 1] : 200L;
}
private static long getTileEnd( long[] index, int tileIndex )
{
private static long getTileEnd(long[] index, int tileIndex) {
return index[tileIndex];
}
private static int[] readPosIndex( DataInputStream dis, DataOutputStream dos ) throws IOException
{
private static int[] readPosIndex(DataInputStream dis, DataOutputStream dos) throws IOException {
int[] posIndex = new int[1024];
for( int i=0; i<1024; i++ )
{
for (int i = 0; i < 1024; i++) {
int iv = dis.readInt();
posIndex[i] = iv;
if ( dos != null )
{
dos.writeInt( iv );
if (dos != null) {
dos.writeInt(iv);
}
}
return posIndex;
}
private static int getPosIdx( int[] posIdx, int idx )
{
private static int getPosIdx(int[] posIdx, int idx) {
return idx == -1 ? 4096 : posIdx[idx];
}
private static byte[] createMicroCache( int[] posIdx, int tileIdx, DataInputStream dis, boolean deltaMode ) throws IOException
{
if ( posIdx == null )
{
private static byte[] createMicroCache(int[] posIdx, int tileIdx, DataInputStream dis, boolean deltaMode) throws IOException {
if (posIdx == null) {
return null;
}
int size = getPosIdx( posIdx, tileIdx ) - getPosIdx( posIdx, tileIdx-1 );
if ( size == 0 )
{
int size = getPosIdx(posIdx, tileIdx) - getPosIdx(posIdx, tileIdx - 1);
if (size == 0) {
return null;
}
if ( deltaMode )
{
if (deltaMode) {
size = dis.readInt();
}
byte[] ab = new byte[size];
dis.readFully( ab );
dis.readFully(ab);
return ab;
}
private static MicroCache createMicroCache( byte[] ab, DataBuffers dataBuffers )
{
if ( ab == null || ab.length == 0 )
{
private static MicroCache createMicroCache(byte[] ab, DataBuffers dataBuffers) {
if (ab == null || ab.length == 0) {
return MicroCache.emptyCache();
}
StatCoderContext bc = new StatCoderContext( ab );
return new MicroCache2( bc, dataBuffers, 0, 0, 32, null, null );
StatCoderContext bc = new StatCoderContext(ab);
return new MicroCache2(bc, dataBuffers, 0, 0, 32, null, null);
}
/**
* Compute the delta between 2 RD5 files and
* show statistics on the expected size of the delta file
*/
public static void diff2files( File f1, File f2, File outFile ) throws Exception
{
public static void diff2files(File f1, File f2, File outFile) throws Exception {
byte[] abBuf1 = new byte[10 * 1024 * 1024];
byte[] abBuf2 = new byte[10 * 1024 * 1024];
int nodesDiff = 0;
int diffedTiles = 0;
long bytesDiff = 0L;
DataInputStream dis1 = new DataInputStream( new BufferedInputStream( new FileInputStream( f1 ) ) );
DataInputStream dis2 = new DataInputStream( new BufferedInputStream( new FileInputStream( f2 ) ) );
DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
MCOutputStream mcOut = new MCOutputStream( dos, abBuf1 );
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
DataInputStream dis2 = new DataInputStream(new BufferedInputStream(new FileInputStream(f2)));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
MCOutputStream mcOut = new MCOutputStream(dos, abBuf1);
// copy header to outfile
long[] fileIndex1 = readFileIndex( dis1, null );
long[] fileIndex2 = readFileIndex( dis2, dos );
long[] fileIndex1 = readFileIndex(dis1, null);
long[] fileIndex2 = readFileIndex(dis2, dos);
long t0 = System.currentTimeMillis();
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
{
boolean hasData1 = getTileStart( fileIndex1, subFileIdx ) < getTileEnd( fileIndex1, subFileIdx );
boolean hasData2 = getTileStart( fileIndex2, subFileIdx ) < getTileEnd( fileIndex2, subFileIdx );
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx);
int[] posIdx1 = hasData1 ? readPosIndex( dis1, null ) : null;
int[] posIdx2 = hasData2 ? readPosIndex( dis2, dos ) : null;
int[] posIdx1 = hasData1 ? readPosIndex(dis1, null) : null;
int[] posIdx2 = hasData2 ? readPosIndex(dis2, dos) : null;
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
{
byte[] ab1 = createMicroCache( posIdx1, tileIdx, dis1, false );
byte[] ab2 = createMicroCache( posIdx2, tileIdx, dis2, false );
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
byte[] ab2 = createMicroCache(posIdx2, tileIdx, dis2, false);
MicroCache mc;
if ( Arrays.equals( ab1, ab2 ) )
{
mc = MicroCache.emptyCache(); // empty diff
}
else // calc diff of the 2 tiles
{
MicroCache mc1 = createMicroCache( ab1, dataBuffers );
MicroCache mc2 = createMicroCache( ab2, dataBuffers );
mc = new MicroCache2( mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32 );
mc.calcDelta( mc1, mc2 );
}
MicroCache mc;
if (Arrays.equals(ab1, ab2)) {
mc = MicroCache.emptyCache(); // empty diff
} else // calc diff of the 2 tiles
{
MicroCache mc1 = createMicroCache(ab1, dataBuffers);
MicroCache mc2 = createMicroCache(ab2, dataBuffers);
mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
mc.calcDelta(mc1, mc2);
}
int len = mcOut.writeMC( mc );
if ( len > 0 )
{
bytesDiff += len;
nodesDiff += mc.getSize();
diffedTiles++;
int len = mcOut.writeMC(mc);
if (len > 0) {
bytesDiff += len;
nodesDiff += mc.getSize();
diffedTiles++;
/* // do some consistemcy checks on the encoding
@ -238,116 +206,93 @@ final public class Rd5DiffTool implements ProgressListener
}
// write any remaining data to the output file
for(;;)
{
int len = dis2.read( abBuf1 );
if (len < 0)
{
for (; ; ) {
int len = dis2.read(abBuf1);
if (len < 0) {
break;
}
dos.write( abBuf1, 0, len );
dos.write(abBuf1, 0, len);
}
long t1 = System.currentTimeMillis();
System.out.println( "nodesDiff=" + nodesDiff + " bytesDiff=" + bytesDiff + " diffedTiles=" + diffedTiles + " took " + (t1-t0) + "ms" );
}
finally
{
if ( dis1 != null )
{
try
{
System.out.println("nodesDiff=" + nodesDiff + " bytesDiff=" + bytesDiff + " diffedTiles=" + diffedTiles + " took " + (t1 - t0) + "ms");
} finally {
if (dis1 != null) {
try {
dis1.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dis2 != null )
{
try
{
if (dis2 != null) {
try {
dis2.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dos != null )
{
try
{
if (dos != null) {
try {
dos.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
}
}
public static void recoverFromDelta( File f1, File f2, File outFile, ProgressListener progress /* , File cmpFile */ ) throws IOException
{
if ( f2.length() == 0L )
{
copyFile( f1, outFile, progress );
public static void recoverFromDelta(File f1, File f2, File outFile, ProgressListener progress /* , File cmpFile */) throws IOException {
if (f2.length() == 0L) {
copyFile(f1, outFile, progress);
return;
}
byte[] abBuf1 = new byte[10 * 1024 * 1024];
byte[] abBuf2 = new byte[10 * 1024 * 1024];
boolean canceled = false;
long t0 = System.currentTimeMillis();
DataInputStream dis1 = new DataInputStream( new BufferedInputStream( new FileInputStream( f1 ) ) );
DataInputStream dis2 = new DataInputStream( new BufferedInputStream( new FileInputStream( f2 ) ) );
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
DataInputStream dis2 = new DataInputStream(new BufferedInputStream(new FileInputStream(f2)));
// DataInputStream disCmp = new DataInputStream( new BufferedInputStream( new FileInputStream( cmpFile ) ) );
DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
// copy header to outfile
long[] fileIndex1 = readFileIndex( dis1, null );
long[] fileIndex2 = readFileIndex( dis2, dos );
long[] fileIndex1 = readFileIndex(dis1, null);
long[] fileIndex2 = readFileIndex(dis2, dos);
// long[] fileIndexCmp = readFileIndex( disCmp, null );
int lastPct = -1;
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
MCInputStream mcIn = new MCInputStream( dis2, dataBuffers );
MCInputStream mcIn = new MCInputStream(dis2, dataBuffers);
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
{
boolean hasData1 = getTileStart( fileIndex1, subFileIdx ) < getTileEnd( fileIndex1, subFileIdx ); // has the basefile data
boolean hasData2 = getTileStart( fileIndex2, subFileIdx ) < getTileEnd( fileIndex2, subFileIdx ); // has the *result* data
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx); // has the basefile data
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx); // has the *result* data
// boolean hasDataCmp = getTileStart( fileIndexCmp, subFileIdx ) < getTileEnd( fileIndexCmp, subFileIdx );
int[] posIdx1 = hasData1 ? readPosIndex( dis1, null ) : null;
int[] posIdx2 = hasData2 ? readPosIndex( dis2, dos ) : null;
int[] posIdx1 = hasData1 ? readPosIndex(dis1, null) : null;
int[] posIdx2 = hasData2 ? readPosIndex(dis2, dos) : null;
// int[] posIdxCmp = hasDataCmp ? readPosIndex( disCmp, null ) : null;
// int[] posIdxCmp = hasDataCmp ? readPosIndex( disCmp, null ) : null;
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
{
if ( progress.isCanceled() )
{
canceled = true;
return;
}
double bytesProcessed = getTileStart( fileIndex1, subFileIdx ) + ( posIdx1 == null ? 0 : getPosIdx( posIdx1, tileIdx-1 ) );
int pct = (int)(100. * bytesProcessed / getTileEnd( fileIndex1, 24 ) + 0.5 );
if ( pct != lastPct )
{
progress.updateProgress("Applying delta", pct);
lastPct = pct;
}
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
if (progress.isCanceled()) {
canceled = true;
return;
}
double bytesProcessed = getTileStart(fileIndex1, subFileIdx) + (posIdx1 == null ? 0 : getPosIdx(posIdx1, tileIdx - 1));
int pct = (int) (100. * bytesProcessed / getTileEnd(fileIndex1, 24) + 0.5);
if (pct != lastPct) {
progress.updateProgress("Applying delta", pct);
lastPct = pct;
}
byte[] ab1 = createMicroCache( posIdx1, tileIdx, dis1, false );
MicroCache mc2 = mcIn.readMC();
int targetSize = posIdx2 == null ? 0 : getPosIdx( posIdx2, tileIdx ) - getPosIdx( posIdx2, tileIdx-1 );
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
MicroCache mc2 = mcIn.readMC();
int targetSize = posIdx2 == null ? 0 : getPosIdx(posIdx2, tileIdx) - getPosIdx(posIdx2, tileIdx - 1);
/* int targetSizeCmp = getPosIdx( posIdxCmp, tileIdx ) - getPosIdx( posIdxCmp, tileIdx-1 );
if ( targetSizeCmp != targetSize ) throw new IllegalArgumentException( "target size mismatch: "+ targetSize + "," + targetSizeCmp );
@ -355,38 +300,33 @@ final public class Rd5DiffTool implements ProgressListener
disCmp.readFully( abCmp );
*/
// no-delta shortcut: just copy base data
if ( mc2.getSize() == 0 )
{
if ( ab1 != null )
{
dos.write( ab1 );
}
int newTargetSize = ab1 == null ? 0 : ab1.length;
if ( targetSize != newTargetSize )
{
throw new RuntimeException( "size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "!=" + newTargetSize );
}
continue;
}
// no-delta shortcut: just copy base data
if (mc2.getSize() == 0) {
if (ab1 != null) {
dos.write(ab1);
}
int newTargetSize = ab1 == null ? 0 : ab1.length;
if (targetSize != newTargetSize) {
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "!=" + newTargetSize);
}
continue;
}
// this is the real delta case (using decode->delta->encode )
// this is the real delta case (using decode->delta->encode )
MicroCache mc1 = createMicroCache( ab1, dataBuffers );
MicroCache mc1 = createMicroCache(ab1, dataBuffers);
MicroCache mc = new MicroCache2( mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32 );
mc.addDelta( mc1, mc2, false );
if ( mc.size() == 0 )
{
if ( targetSize != 0 )
{
throw new RuntimeException( "size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + ">0" );
}
continue;
}
MicroCache mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
mc.addDelta(mc1, mc2, false);
int len = mc.encodeMicroCache( abBuf1 );
if (mc.size() == 0) {
if (targetSize != 0) {
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + ">0");
}
continue;
}
int len = mc.encodeMicroCache(abBuf1);
/* System.out.println( "comparing for subFileIdx=" + subFileIdx + " tileIdx=" + tileIdx );
boolean isequal = true;
@ -406,377 +346,290 @@ final public class Rd5DiffTool implements ProgressListener
}
}
*/
dos.write( abBuf1, 0, len );
dos.writeInt( Crc32.crc( abBuf1, 0, len ) ^ 2 );
if ( targetSize != len+4 )
{
throw new RuntimeException( "size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "<>" + (len+4) );
}
dos.write(abBuf1, 0, len);
dos.writeInt(Crc32.crc(abBuf1, 0, len) ^ 2);
if (targetSize != len + 4) {
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "<>" + (len + 4));
}
}
mcIn.finish();
}
// write any remaining data to the output file
for(;;)
{
int len = dis2.read( abBuf1 );
if (len < 0)
{
for (; ; ) {
int len = dis2.read(abBuf1);
if (len < 0) {
break;
}
dos.write( abBuf1, 0, len );
dos.write(abBuf1, 0, len);
}
long t1 = System.currentTimeMillis();
System.out.println( "recovering from diffs took " + (t1-t0) + "ms" );
}
finally
{
if ( dis1 != null )
{
try
{
long t1 = System.currentTimeMillis();
System.out.println("recovering from diffs took " + (t1 - t0) + "ms");
} finally {
if (dis1 != null) {
try {
dis1.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dis2 != null )
{
try
{
if (dis2 != null) {
try {
dis2.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dos != null )
{
try
{
if (dos != null) {
try {
dos.close();
} catch (Exception ee) {
}
catch (Exception ee)
{
}
if ( canceled )
{
if (canceled) {
outFile.delete();
}
}
}
}
public static void copyFile( File f1, File outFile, ProgressListener progress ) throws IOException
{
public static void copyFile(File f1, File outFile, ProgressListener progress) throws IOException {
boolean canceled = false;
DataInputStream dis1 = new DataInputStream( new BufferedInputStream( new FileInputStream( f1 ) ) );
DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
int lastPct = -1;
long sizeTotal = f1.length();
long sizeRead = 0L;
try
{
byte buf[] = new byte[65536];
for (;;)
{
if ( progress.isCanceled() )
{
try {
byte buf[] = new byte[65536];
for (; ; ) {
if (progress.isCanceled()) {
canceled = true;
return;
}
int pct = (int)( (100. * sizeRead) / (sizeTotal+1) + 0.5 );
if ( pct != lastPct )
{
int pct = (int) ((100. * sizeRead) / (sizeTotal + 1) + 0.5);
if (pct != lastPct) {
progress.updateProgress("Copying", pct);
lastPct = pct;
}
int len = dis1.read( buf );
if ( len <= 0 )
{
int len = dis1.read(buf);
if (len <= 0) {
break;
}
sizeRead += len;
dos.write( buf, 0, len );
dos.write(buf, 0, len);
}
}
finally
{
if ( dis1 != null )
{
try
{
} finally {
if (dis1 != null) {
try {
dis1.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dos != null )
{
try
{
if (dos != null) {
try {
dos.close();
} catch (Exception ee) {
}
catch (Exception ee)
{
}
if ( canceled )
{
if (canceled) {
outFile.delete();
}
}
}
}
public static void addDeltas( File f1, File f2, File outFile ) throws Exception
{
public static void addDeltas(File f1, File f2, File outFile) throws Exception {
byte[] abBuf1 = new byte[10 * 1024 * 1024];
byte[] abBuf2 = new byte[10 * 1024 * 1024];
DataInputStream dis1 = new DataInputStream( new BufferedInputStream( new FileInputStream( f1 ) ) );
DataInputStream dis2 = new DataInputStream( new BufferedInputStream( new FileInputStream( f2 ) ) );
DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
DataInputStream dis2 = new DataInputStream(new BufferedInputStream(new FileInputStream(f2)));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
// copy subfile-header to outfile
long[] fileIndex1 = readFileIndex( dis1, null );
long[] fileIndex2 = readFileIndex( dis2, dos );
long[] fileIndex1 = readFileIndex(dis1, null);
long[] fileIndex2 = readFileIndex(dis2, dos);
long t0 = System.currentTimeMillis();
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
MCInputStream mcIn1 = new MCInputStream( dis1, dataBuffers );
MCInputStream mcIn2 = new MCInputStream( dis2, dataBuffers );
MCOutputStream mcOut = new MCOutputStream( dos, abBuf1 );
MCInputStream mcIn1 = new MCInputStream(dis1, dataBuffers);
MCInputStream mcIn2 = new MCInputStream(dis2, dataBuffers);
MCOutputStream mcOut = new MCOutputStream(dos, abBuf1);
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
{
// copy tile-header to outfile
boolean hasData1 = getTileStart( fileIndex1, subFileIdx ) < getTileEnd( fileIndex1, subFileIdx );
boolean hasData2 = getTileStart( fileIndex2, subFileIdx ) < getTileEnd( fileIndex2, subFileIdx );
int[] posIdx1 = hasData1 ? readPosIndex( dis1, null ) : null;
int[] posIdx2 = hasData2 ? readPosIndex( dis2, dos ) : null;
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
// copy tile-header to outfile
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx);
int[] posIdx1 = hasData1 ? readPosIndex(dis1, null) : null;
int[] posIdx2 = hasData2 ? readPosIndex(dis2, dos) : null;
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
{
MicroCache mc1 = mcIn1.readMC();
MicroCache mc2 = mcIn2.readMC();
MicroCache mc;
if ( mc1.getSize() == 0 && mc2.getSize() == 0 )
{
mc = mc1;
}
else
{
mc = new MicroCache2( mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32 );
mc.addDelta( mc1, mc2, true );
}
mcOut.writeMC( mc );
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
MicroCache mc1 = mcIn1.readMC();
MicroCache mc2 = mcIn2.readMC();
MicroCache mc;
if (mc1.getSize() == 0 && mc2.getSize() == 0) {
mc = mc1;
} else {
mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
mc.addDelta(mc1, mc2, true);
}
mcOut.writeMC(mc);
}
mcIn1.finish();
mcIn2.finish();
mcOut.finish();
}
// write any remaining data to the output file
for(;;)
{
int len = dis2.read( abBuf1 );
if (len < 0)
{
for (; ; ) {
int len = dis2.read(abBuf1);
if (len < 0) {
break;
}
dos.write( abBuf1, 0, len );
dos.write(abBuf1, 0, len);
}
long t1 = System.currentTimeMillis();
System.out.println( "adding diffs took " + (t1-t0) + "ms" );
}
finally
{
if ( dis1 != null )
{
try
{
System.out.println("adding diffs took " + (t1 - t0) + "ms");
} finally {
if (dis1 != null) {
try {
dis1.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dis2 != null )
{
try
{
if (dis2 != null) {
try {
dis2.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dos != null )
{
try
{
if (dos != null) {
try {
dos.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
}
}
public static void reEncode( File f1, File outFile ) throws Exception
{
public static void reEncode(File f1, File outFile) throws Exception {
byte[] abBuf1 = new byte[10 * 1024 * 1024];
DataInputStream dis1 = new DataInputStream( new BufferedInputStream( new FileInputStream( f1 ) ) );
DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
// copy header to outfile
long[] fileIndex1 = readFileIndex( dis1, dos );
long[] fileIndex1 = readFileIndex(dis1, dos);
long t0 = System.currentTimeMillis();
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
{
boolean hasData1 = getTileStart( fileIndex1, subFileIdx ) < getTileEnd( fileIndex1, subFileIdx );
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
int[] posIdx1 = hasData1 ? readPosIndex( dis1, dos ) : null;
int[] posIdx1 = hasData1 ? readPosIndex(dis1, dos) : null;
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
{
byte[] ab1 = createMicroCache( posIdx1, tileIdx, dis1, false );
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
if ( ab1 == null ) continue;
if (ab1 == null) continue;
MicroCache mc1 = createMicroCache( ab1, dataBuffers );
MicroCache mc1 = createMicroCache(ab1, dataBuffers);
int len = mc1.encodeMicroCache( abBuf1 );
int len = mc1.encodeMicroCache(abBuf1);
dos.write( abBuf1, 0, len );
dos.writeInt( Crc32.crc( abBuf1, 0, len ) ^ 2 );
dos.write(abBuf1, 0, len);
dos.writeInt(Crc32.crc(abBuf1, 0, len) ^ 2);
}
}
// write any remaining data to the output file
for(;;)
{
int len = dis1.read( abBuf1 );
if (len < 0)
{
for (; ; ) {
int len = dis1.read(abBuf1);
if (len < 0) {
break;
}
dos.write( abBuf1, 0, len );
dos.write(abBuf1, 0, len);
}
long t1 = System.currentTimeMillis();
System.out.println( "re-encoding took " + (t1-t0) + "ms" );
}
finally
{
if ( dis1 != null )
{
try
{
System.out.println("re-encoding took " + (t1 - t0) + "ms");
} finally {
if (dis1 != null) {
try {
dis1.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
if ( dos != null )
{
try
{
if (dos != null) {
try {
dos.close();
}
catch (Exception ee)
{
} catch (Exception ee) {
}
}
}
}
private static class MCOutputStream
{
private static class MCOutputStream {
private DataOutputStream dos;
private byte[] buffer;
private short skips = 0;
public MCOutputStream(DataOutputStream dos, byte[] buffer)
{
public MCOutputStream(DataOutputStream dos, byte[] buffer) {
this.dos = dos;
this.buffer = buffer;
}
public int writeMC(MicroCache mc) throws Exception
{
if ( mc.getSize() == 0 )
{
public int writeMC(MicroCache mc) throws Exception {
if (mc.getSize() == 0) {
skips++;
return 0;
}
dos.writeShort( skips );
dos.writeShort(skips);
skips = 0;
int len = mc.encodeMicroCache( buffer );
if ( len == 0 )
{
throw new IllegalArgumentException( "encoded buffer of non-empty micro-cache cannot be empty" );
int len = mc.encodeMicroCache(buffer);
if (len == 0) {
throw new IllegalArgumentException("encoded buffer of non-empty micro-cache cannot be empty");
}
dos.writeInt( len );
dos.write( buffer, 0, len );
dos.writeInt(len);
dos.write(buffer, 0, len);
return len;
}
public void finish() throws Exception
{
if ( skips > 0 )
{
dos.writeShort( skips );
public void finish() throws Exception {
if (skips > 0) {
dos.writeShort(skips);
skips = 0;
}
}
}
private static class MCInputStream
{
private static class MCInputStream {
private short skips = -1;
private DataInputStream dis;
private DataBuffers dataBuffers;
private MicroCache empty = MicroCache.emptyCache();
public MCInputStream( DataInputStream dis, DataBuffers dataBuffers )
{
public MCInputStream(DataInputStream dis, DataBuffers dataBuffers) {
this.dis = dis;
this.dataBuffers = dataBuffers;
}
public MicroCache readMC() throws IOException
{
if (skips < 0 )
{
public MicroCache readMC() throws IOException {
if (skips < 0) {
skips = dis.readShort();
}
MicroCache mc = empty;
if ( skips == 0 )
{
if (skips == 0) {
int size = dis.readInt();
byte[] ab = new byte[size];
dis.readFully( ab );
StatCoderContext bc = new StatCoderContext( ab );
mc = new MicroCache2( bc, dataBuffers, 0, 0, 32, null, null );
dis.readFully(ab);
StatCoderContext bc = new StatCoderContext(ab);
mc = new MicroCache2(bc, dataBuffers, 0, 0, 32, null, null);
}
skips--;
return mc;
}
public void finish()
{
public void finish() {
skips = -1;
}
}

View file

@ -7,62 +7,54 @@ package btools.mapaccess;
import java.io.File;
final public class Rd5DiffValidator
{
public static void main( String[] args ) throws Exception
{
validateDiffs( new File( args[0] ),new File( args[1] ) );
final public class Rd5DiffValidator {
public static void main(String[] args) throws Exception {
validateDiffs(new File(args[0]), new File(args[1]));
}
/**
* Validate diffs for all DF5 files
*/
public static void validateDiffs( File oldDir, File newDir ) throws Exception
{
File oldDiffDir = new File( oldDir, "diff" );
File newDiffDir = new File( newDir, "diff" );
public static void validateDiffs(File oldDir, File newDir) throws Exception {
File oldDiffDir = new File(oldDir, "diff");
File newDiffDir = new File(newDir, "diff");
File[] filesNew = newDir.listFiles();
for( File fn : filesNew )
{
for (File fn : filesNew) {
String name = fn.getName();
if ( !name.endsWith( ".rd5" ) )
{
if (!name.endsWith(".rd5")) {
continue;
}
if ( fn.length() < 1024*1024 )
{
if (fn.length() < 1024 * 1024) {
continue; // expecting no diff for small files
}
String basename = name.substring( 0, name.length() - 4 );
File fo = new File( oldDir, name );
if ( !fo.isFile() )
{
String basename = name.substring(0, name.length() - 4);
File fo = new File(oldDir, name);
if (!fo.isFile()) {
continue;
}
// calculate MD5 of old file
String md5 = Rd5DiffManager.getMD5( fo );
String md5 = Rd5DiffManager.getMD5(fo);
String md5New = Rd5DiffManager.getMD5( fn );
String md5New = Rd5DiffManager.getMD5(fn);
System.out.println( "name=" + name + " md5=" + md5 );
System.out.println("name=" + name + " md5=" + md5);
File specificNewDiffs = new File( newDiffDir, basename );
File specificNewDiffs = new File(newDiffDir, basename);
String diffFileName = md5 + ".df5";
File diffFile = new File( specificNewDiffs, diffFileName );
File diffFile = new File(specificNewDiffs, diffFileName);
File fcmp = new File( oldDir, name + "_tmp" );
File fcmp = new File(oldDir, name + "_tmp");
// merge old file and diff
Rd5DiffTool.recoverFromDelta( fo, diffFile, fcmp, new Rd5DiffTool() );
String md5Cmp = Rd5DiffManager.getMD5( fcmp );
Rd5DiffTool.recoverFromDelta(fo, diffFile, fcmp, new Rd5DiffTool());
String md5Cmp = Rd5DiffManager.getMD5(fcmp);
if ( !md5Cmp.equals( md5New ) )
{
throw new RuntimeException( "**************** md5 mismatch!! *****************" );
if (!md5Cmp.equals(md5New)) {
throw new RuntimeException("**************** md5 mismatch!! *****************");
}
}
}

View file

@ -9,51 +9,38 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class StorageConfigHelper
{
public static File getSecondarySegmentDir( File segmentDir )
{
return getStorageLocation( segmentDir, "secondary_segment_dir=" );
public class StorageConfigHelper {
public static File getSecondarySegmentDir(File segmentDir) {
return getStorageLocation(segmentDir, "secondary_segment_dir=");
}
public static File getAdditionalMaptoolDir( File segmentDir )
{
return getStorageLocation( segmentDir, "additional_maptool_dir=" );
public static File getAdditionalMaptoolDir(File segmentDir) {
return getStorageLocation(segmentDir, "additional_maptool_dir=");
}
private static File getStorageLocation( File segmentDir, String tag )
{
private static File getStorageLocation(File segmentDir, String tag) {
File res = null;
BufferedReader br = null;
File configFile = new File (segmentDir, "storageconfig.txt");
try
{
br = new BufferedReader( new FileReader( configFile ) );
for ( ;; )
{
File configFile = new File(segmentDir, "storageconfig.txt");
try {
br = new BufferedReader(new FileReader(configFile));
for (; ; ) {
String line = br.readLine();
if ( line == null ) break;
if (line == null) break;
line = line.trim();
if ( line.startsWith( "#" ) ) continue;
if ( line.startsWith( tag ) )
{
String path = line.substring( tag.length() ).trim();
res = path.startsWith( "/" ) ? new File( path ) : new File( segmentDir, path );
if ( !res.exists() ) res = null;
if (line.startsWith("#")) continue;
if (line.startsWith(tag)) {
String path = line.substring(tag.length()).trim();
res = path.startsWith("/") ? new File(path) : new File(segmentDir, path);
if (!res.exists()) res = null;
break;
}
}
}
catch (Exception e) { /* ignore */ }
finally
{
if ( br != null )
{
try
{
} catch (Exception e) { /* ignore */ } finally {
if (br != null) {
try {
br.close();
}
catch (Exception ee) { /* ignore */ }
} catch (Exception ee) { /* ignore */ }
}
}
return res;

View file

@ -5,8 +5,7 @@
*/
package btools.mapaccess;
public final class TurnRestriction
{
public final class TurnRestriction {
public boolean isPositive;
public short exceptions;
@ -17,57 +16,45 @@ public final class TurnRestriction
public int toLat;
public TurnRestriction next;
public boolean exceptBikes()
{
return ( exceptions & 1 ) != 0;
public boolean exceptBikes() {
return (exceptions & 1) != 0;
}
public boolean exceptMotorcars()
{
return ( exceptions & 2 ) != 0;
public boolean exceptMotorcars() {
return (exceptions & 2) != 0;
}
public static boolean isTurnForbidden( TurnRestriction first, int fromLon, int fromLat, int toLon, int toLat, boolean bikeMode, boolean carMode )
{
public static boolean isTurnForbidden(TurnRestriction first, int fromLon, int fromLat, int toLon, int toLat, boolean bikeMode, boolean carMode) {
boolean hasAnyPositive = false;
boolean hasPositive = false;
boolean hasNegative = false;
TurnRestriction tr = first;
while (tr != null)
{
if ( ( tr.exceptBikes() && bikeMode ) || ( tr.exceptMotorcars() && carMode ) )
{
while (tr != null) {
if ((tr.exceptBikes() && bikeMode) || (tr.exceptMotorcars() && carMode)) {
tr = tr.next;
continue;
}
if ( tr.fromLon == fromLon && tr.fromLat == fromLat )
{
if ( tr.isPositive )
{
if (tr.fromLon == fromLon && tr.fromLat == fromLat) {
if (tr.isPositive) {
hasAnyPositive = true;
}
if ( tr.toLon == toLon && tr.toLat == toLat )
{
if ( tr.isPositive )
{
if (tr.toLon == toLon && tr.toLat == toLat) {
if (tr.isPositive) {
hasPositive = true;
}
else
{
} else {
hasNegative = true;
}
}
}
tr = tr.next;
}
return !hasPositive && ( hasAnyPositive || hasNegative );
return !hasPositive && (hasAnyPositive || hasNegative);
}
@Override
public String toString()
{
public String toString() {
return "pos=" + isPositive + " fromLon=" + fromLon + " fromLat=" + fromLat + " toLon=" + toLon + " toLat=" + toLat;
}
}

View file

@ -10,12 +10,11 @@ import btools.util.CheapRuler;
/**
* the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
* already check for allowed access according to the current routing profile
*
* <p>
* It matches these geometries against the list of waypoints to find the best
* match for each waypoint
*/
public final class WaypointMatcherImpl implements WaypointMatcher
{
public final class WaypointMatcherImpl implements WaypointMatcher {
private List<MatchedWaypoint> waypoints;
private OsmNodePairSet islandPairs;
@ -27,57 +26,50 @@ public final class WaypointMatcherImpl implements WaypointMatcher
private int lonLast;
private int latLast;
public WaypointMatcherImpl( List<MatchedWaypoint> waypoints, double maxDistance, OsmNodePairSet islandPairs )
{
public WaypointMatcherImpl(List<MatchedWaypoint> waypoints, double maxDistance, OsmNodePairSet islandPairs) {
this.waypoints = waypoints;
this.islandPairs = islandPairs;
for ( MatchedWaypoint mwp : waypoints )
{
for (MatchedWaypoint mwp : waypoints) {
mwp.radius = maxDistance;
}
}
private void checkSegment( int lon1, int lat1, int lon2, int lat2 )
{
private void checkSegment(int lon1, int lat1, int lon2, int lat2) {
// todo: bounding-box pre-filter
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1+lat2) >> 1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lat1 + lat2) >> 1);
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
double dx = ( lon2 - lon1 ) * dlon2m;
double dy = ( lat2 - lat1 ) * dlat2m;
double d = Math.sqrt( dy * dy + dx * dx );
double dx = (lon2 - lon1) * dlon2m;
double dy = (lat2 - lat1) * dlat2m;
double d = Math.sqrt(dy * dy + dx * dx);
if ( d == 0. )
if (d == 0.)
return;
for ( MatchedWaypoint mwp : waypoints )
{
for (MatchedWaypoint mwp : waypoints) {
OsmNode wp = mwp.waypoint;
double x1 = ( lon1 - wp.ilon ) * dlon2m;
double y1 = ( lat1 - wp.ilat ) * dlat2m;
double x2 = ( lon2 - wp.ilon ) * dlon2m;
double y2 = ( lat2 - wp.ilat ) * dlat2m;
double x1 = (lon1 - wp.ilon) * dlon2m;
double y1 = (lat1 - wp.ilat) * dlat2m;
double x2 = (lon2 - wp.ilon) * dlon2m;
double y2 = (lat2 - wp.ilat) * dlat2m;
double r12 = x1 * x1 + y1 * y1;
double r22 = x2 * x2 + y2 * y2;
double radius = Math.abs( r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy ) / d;
double radius = Math.abs(r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy) / d;
if ( radius < mwp.radius )
{
if (radius < mwp.radius) {
double s1 = x1 * dx + y1 * dy;
double s2 = x2 * dx + y2 * dy;
if ( s1 < 0. )
{
if (s1 < 0.) {
s1 = -s1;
s2 = -s2;
}
if ( s2 > 0. )
{
radius = Math.sqrt( s1 < s2 ? r12 : r22 );
if ( radius > mwp.radius )
if (s2 > 0.) {
radius = Math.sqrt(s1 < s2 ? r12 : r22);
if (radius > mwp.radius)
continue;
}
// new match for that waypoint
@ -85,23 +77,18 @@ public final class WaypointMatcherImpl implements WaypointMatcher
mwp.hasUpdate = true;
anyUpdate = true;
// calculate crosspoint
if ( mwp.crosspoint == null )
if (mwp.crosspoint == null)
mwp.crosspoint = new OsmNode();
if ( s2 < 0. )
{
double wayfraction = -s2 / ( d * d );
if (s2 < 0.) {
double wayfraction = -s2 / (d * d);
double xm = x2 - wayfraction * dx;
double ym = y2 - wayfraction * dy;
mwp.crosspoint.ilon = (int) ( xm / dlon2m + wp.ilon );
mwp.crosspoint.ilat = (int) ( ym / dlat2m + wp.ilat );
}
else if ( s1 > s2 )
{
mwp.crosspoint.ilon = (int) (xm / dlon2m + wp.ilon);
mwp.crosspoint.ilat = (int) (ym / dlat2m + wp.ilat);
} else if (s1 > s2) {
mwp.crosspoint.ilon = lon2;
mwp.crosspoint.ilat = lat2;
}
else
{
} else {
mwp.crosspoint.ilon = lon1;
mwp.crosspoint.ilat = lat1;
}
@ -110,14 +97,11 @@ public final class WaypointMatcherImpl implements WaypointMatcher
}
@Override
public boolean start( int ilonStart, int ilatStart, int ilonTarget, int ilatTarget )
{
if ( islandPairs.size() > 0 )
{
long n1 = ( (long) ilonStart ) << 32 | ilatStart;
long n2 = ( (long) ilonTarget ) << 32 | ilatTarget;
if ( islandPairs.hasPair( n1, n2 ) )
{
public boolean start(int ilonStart, int ilatStart, int ilonTarget, int ilatTarget) {
if (islandPairs.size() > 0) {
long n1 = ((long) ilonStart) << 32 | ilatStart;
long n2 = ((long) ilonTarget) << 32 | ilatTarget;
if (islandPairs.hasPair(n1, n2)) {
return false;
}
}
@ -130,26 +114,21 @@ public final class WaypointMatcherImpl implements WaypointMatcher
}
@Override
public void transferNode( int ilon, int ilat )
{
checkSegment( lonLast, latLast, ilon, ilat );
public void transferNode(int ilon, int ilat) {
checkSegment(lonLast, latLast, ilon, ilat);
lonLast = ilon;
latLast = ilat;
}
@Override
public void end()
{
checkSegment( lonLast, latLast, lonTarget, latTarget );
if ( anyUpdate )
{
for ( MatchedWaypoint mwp : waypoints )
{
if ( mwp.hasUpdate )
{
public void end() {
checkSegment(lonLast, latLast, lonTarget, latTarget);
if (anyUpdate) {
for (MatchedWaypoint mwp : waypoints) {
if (mwp.hasUpdate) {
mwp.hasUpdate = false;
mwp.node1 = new OsmNode( lonStart, latStart );
mwp.node2 = new OsmNode( lonTarget, latTarget );
mwp.node1 = new OsmNode(lonStart, latStart);
mwp.node2 = new OsmNode(lonTarget, latTarget);
}
}
}