Reformat whole codebase using Android Studio
This commit is contained in:
parent
d5322667d5
commit
c15913c1ab
161 changed files with 15124 additions and 18537 deletions
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!! *****************");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue