Reformat whole codebase using Android Studio

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

View File

@ -5,8 +5,7 @@ import btools.util.BitCoderContext;
/**
* Container for some re-usable databuffers for the decoder
*/
public final class DataBuffers
{
public final class DataBuffers {
public byte[] iobuffer;
public byte[] tagbuf1 = new byte[256];
public BitCoderContext bctx1 = new BitCoderContext(tagbuf1);
@ -17,8 +16,7 @@ public final class DataBuffers
public int[] alon = new int[2048];
public int[] alat = new int[2048];
public DataBuffers()
{
public DataBuffers() {
this(new byte[65636]);
}
@ -26,8 +24,7 @@ public final class DataBuffers
* construct a set of databuffers except
* for 'iobuffer', where the given array is used
*/
public DataBuffers( byte[] iobuffer )
{
public DataBuffers(byte[] iobuffer) {
this.iobuffer = iobuffer;
}

View File

@ -3,16 +3,14 @@ package btools.codec;
/**
* Special integer fifo suitable for 3-pass encoding
*/
public class IntegerFifo3Pass
{
public class IntegerFifo3Pass {
private int[] a;
private int size;
private int pos;
private int pass;
public IntegerFifo3Pass( int capacity )
{
public IntegerFifo3Pass(int capacity) {
a = capacity < 4 ? new int[4] : new int[capacity];
}
@ -20,8 +18,7 @@ public class IntegerFifo3Pass
* Starts a new encoding pass and resets the reading pointer
* from the stats collected in pass2 and writes that to the given context
*/
public void init()
{
public void init() {
pass++;
pos = 0;
}
@ -29,12 +26,9 @@ public class IntegerFifo3Pass
/**
* writes to the fifo in pass2
*/
public void add( int value )
{
if ( pass == 2 )
{
if ( size == a.length )
{
public void add(int value) {
if (pass == 2) {
if (size == a.length) {
int[] aa = new int[2 * size];
System.arraycopy(a, 0, aa, 0, size);
a = aa;
@ -46,15 +40,12 @@ public class IntegerFifo3Pass
/**
* reads from the fifo in pass3 (in pass1/2 returns just 1)
*/
public int getNext()
{
public int getNext() {
return pass == 3 ? get(pos++) : 1;
}
private int get( int idx )
{
if ( idx >= size )
{
private int get(int idx) {
if (idx >= size) {
throw new IndexOutOfBoundsException("list size=" + size + " idx=" + idx);
}
return a[idx];

View File

@ -3,8 +3,7 @@ package btools.codec;
/**
* Simple container for a list of lists of integers
*/
public class LinkedListContainer
{
public class LinkedListContainer {
private int[] ia; // prev, data, prev, data, ...
private int size;
private int[] startpointer; // 0=void, odd=head-data-cell
@ -12,15 +11,14 @@ public class LinkedListContainer
/**
* Construct a container for the given number of lists
*
* <p>
* If no default-buffer is given, an int[nlists*4] is constructed,
* able to hold 2 entries per list on average
*
* @param nlists the number of lists
* @param defaultbuffer an optional data array for re-use (gets replaced if too small)
*/
public LinkedListContainer( int nlists, int[] defaultbuffer )
{
public LinkedListContainer(int nlists, int[] defaultbuffer) {
ia = defaultbuffer == null ? new int[nlists * 4] : defaultbuffer;
startpointer = new int[nlists];
}
@ -31,10 +29,8 @@ public class LinkedListContainer
* @param listNr the list to add the data to
* @param data the data value
*/
public void addDataElement( int listNr, int data )
{
if ( size + 2 > ia.length )
{
public void addDataElement(int listNr, int data) {
if (size + 2 > ia.length) {
resize();
}
ia[size++] = startpointer[listNr];
@ -48,12 +44,10 @@ public class LinkedListContainer
* @param listNr the list to initialize
* @return the number of entries in that list
*/
public int initList( int listNr )
{
public int initList(int listNr) {
int cnt = 0;
int lp = listpointer = startpointer[listNr];
while( lp != 0 )
{
while (lp != 0) {
lp = ia[lp - 1];
cnt++;
}
@ -67,10 +61,8 @@ public class LinkedListContainer
* @return the data element
* @throws IllegalArgumentException if no more element
*/
public int getDataElement()
{
if ( listpointer == 0 )
{
public int getDataElement() {
if (listpointer == 0) {
throw new IllegalArgumentException("no more element!");
}
int data = ia[listpointer];
@ -78,8 +70,7 @@ public class LinkedListContainer
return data;
}
private void resize()
{
private void resize() {
int[] ia2 = new int[2 * ia.length];
System.arraycopy(ia, 0, ia2, 0, ia.length);
ia = ia2;

View File

@ -5,21 +5,20 @@ import btools.util.ByteDataWriter;
/**
* a micro-cache is a data cache for an area of some square kilometers or some
* hundreds or thousands nodes
*
* <p>
* This is the basic io-unit: always a full microcache is loaded from the
* data-file if a node is requested at a position not yet covered by the caches
* already loaded
*
* <p>
* The nodes are represented in a compact way (typical 20-50 bytes per node),
* but in a way that they do not depend on each other, and garbage collection is
* supported to remove the nodes already consumed from the cache.
*
* <p>
* The cache-internal data representation is different from that in the
* data-files, where a cache is encoded as a whole, allowing more
* redundancy-removal for a more compact encoding
*/
public class MicroCache extends ByteDataWriter
{
public class MicroCache extends ByteDataWriter {
protected int[] faid;
protected int[] fapos;
protected int size = 0;
@ -35,25 +34,21 @@ public class MicroCache extends ByteDataWriter
public static boolean debug = false;
protected MicroCache( byte[] ab )
{
protected MicroCache(byte[] ab) {
super(ab);
}
public final static MicroCache emptyNonVirgin = new MicroCache(null);
static
{
static {
emptyNonVirgin.virgin = false;
}
public static MicroCache emptyCache()
{
public static MicroCache emptyCache() {
return new MicroCache(null); // TODO: singleton?
}
protected void init( int size )
{
protected void init(int size) {
this.size = size;
delcount = 0;
delbytes = 0;
@ -62,35 +57,31 @@ public class MicroCache extends ByteDataWriter
p2size >>= 1;
}
public final void finishNode( long id )
{
public final void finishNode(long id) {
fapos[size] = aboffset;
faid[size] = shrinkId(id);
size++;
}
public final void discardNode()
{
public final void discardNode() {
aboffset = startPos(size);
}
public final int getSize()
{
public final int getSize() {
return size;
}
public final int getDataSize()
{
public final int getDataSize() {
return ab == null ? 0 : ab.length;
}
/**
* Set the internal reader (aboffset, aboffsetEnd) to the body data for the given id
*
* <p>
* If a node is not found in an empty cache, this is usually an edge-effect
* (data-file does not exist or neighboured data-files of differnt age),
* but is can as well be a symptom of a node-identity breaking bug.
*
* <p>
* Current implementation always returns false for not-found, however, for
* regression testing, at least for the case that is most likely a bug
* (node found but marked as deleted = ready for garbage collection
@ -98,10 +89,8 @@ public class MicroCache extends ByteDataWriter
*
* @return true if id was found
*/
public final boolean getAndClear( long id64 )
{
if ( size == 0 )
{
public final boolean getAndClear(long id64) {
if (size == 0) {
return false;
}
int id = shrinkId(id64);
@ -109,27 +98,22 @@ public class MicroCache extends ByteDataWriter
int offset = p2size;
int n = 0;
while (offset > 0)
{
while (offset > 0) {
int nn = n + offset;
if ( nn < size && a[nn] <= id )
{
if (nn < size && a[nn] <= id) {
n = nn;
}
offset >>= 1;
}
if ( a[n] == id )
{
if ( ( fapos[n] & 0x80000000 ) == 0 )
{
if (a[n] == id) {
if ((fapos[n] & 0x80000000) == 0) {
aboffset = startPos(n);
aboffsetEnd = fapos[n];
fapos[n] |= 0x80000000; // mark deleted
delbytes += aboffsetEnd - aboffset;
delcount++;
return true;
}
else // .. marked as deleted
} else // .. marked as deleted
{
// throw new RuntimeException( "MicroCache: node already consumed: id=" + id );
}
@ -137,39 +121,31 @@ public class MicroCache extends ByteDataWriter
return false;
}
protected final int startPos( int n )
{
protected final int startPos(int n) {
return n > 0 ? fapos[n - 1] & 0x7fffffff : 0;
}
public final int collect( int threshold )
{
if ( delcount <= threshold )
{
public final int collect(int threshold) {
if (delcount <= threshold) {
return 0;
}
virgin = false;
int nsize = size - delcount;
if ( nsize == 0 )
{
if (nsize == 0) {
faid = null;
fapos = null;
}
else
{
} else {
int[] nfaid = new int[nsize];
int[] nfapos = new int[nsize];
int idx = 0;
byte[] nab = new byte[ab.length - delbytes];
int nab_off = 0;
for ( int i = 0; i < size; i++ )
{
for (int i = 0; i < size; i++) {
int pos = fapos[i];
if ( ( pos & 0x80000000 ) == 0 )
{
if ((pos & 0x80000000) == 0) {
int start = startPos(i);
int end = fapos[i];
int len = end - start;
@ -189,13 +165,11 @@ public class MicroCache extends ByteDataWriter
return deleted;
}
public final void unGhost()
{
public final void unGhost() {
ghost = false;
delcount = 0;
delbytes = 0;
for ( int i = 0; i < size; i++ )
{
for (int i = 0; i < size; i++) {
fapos[i] &= 0x7fffffff; // clear deleted flags
}
}
@ -203,8 +177,7 @@ public class MicroCache extends ByteDataWriter
/**
* @return the 64-bit global id for the given cache-position
*/
public final long getIdForIndex( int i )
{
public final long getIdForIndex(int i) {
int id32 = faid[i];
return expandId(id32);
}
@ -214,8 +187,7 @@ public class MicroCache extends ByteDataWriter
*
* @see #shrinkId
*/
public long expandId( int id32 )
{
public long expandId(int id32) {
throw new IllegalArgumentException("expandId for empty cache");
}
@ -224,28 +196,24 @@ public class MicroCache extends ByteDataWriter
*
* @see #expandId
*/
public int shrinkId( long id64 )
{
public int shrinkId(long id64) {
throw new IllegalArgumentException("shrinkId for empty cache");
}
/**
* @return true if the given lon/lat position is internal for that micro-cache
*/
public boolean isInternal( int ilon, int ilat )
{
public boolean isInternal(int ilon, int ilat) {
throw new IllegalArgumentException("isInternal for empty cache");
}
/**
* (stasticially) encode the micro-cache into the format used in the datafiles
*
* @param buffer
* byte array to encode into (considered big enough)
* @param buffer byte array to encode into (considered big enough)
* @return the size of the encoded data
*/
public int encodeMicroCache( byte[] buffer )
{
public int encodeMicroCache(byte[] buffer) {
throw new IllegalArgumentException("encodeMicroCache for empty cache");
}
@ -254,11 +222,9 @@ public class MicroCache extends ByteDataWriter
*
* @return null if equals, else a diff-report
*/
public String compareWith( MicroCache mc )
{
public String compareWith(MicroCache mc) {
String msg = _compareWith(mc);
if ( msg != null )
{
if (msg != null) {
StringBuilder sb = new StringBuilder(msg);
sb.append("\nencode cache:\n").append(summary());
sb.append("\ndecode cache:\n").append(mc.summary());
@ -267,96 +233,75 @@ public class MicroCache extends ByteDataWriter
return null;
}
private String summary()
{
private String summary() {
StringBuilder sb = new StringBuilder("size=" + size + " aboffset=" + aboffset);
for ( int i = 0; i < size; i++ )
{
for (int i = 0; i < size; i++) {
sb.append("\nidx=" + i + " faid=" + faid[i] + " fapos=" + fapos[i]);
}
return sb.toString();
}
private String _compareWith( MicroCache mc )
{
if ( size != mc.size )
{
private String _compareWith(MicroCache mc) {
if (size != mc.size) {
return "size missmatch: " + size + "->" + mc.size;
}
for ( int i = 0; i < size; i++ )
{
if ( faid[i] != mc.faid[i] )
{
for (int i = 0; i < size; i++) {
if (faid[i] != mc.faid[i]) {
return "faid missmatch at index " + i + ":" + faid[i] + "->" + mc.faid[i];
}
int start = i > 0 ? fapos[i - 1] : 0;
int end = fapos[i] < mc.fapos[i] ? fapos[i] : mc.fapos[i];
int len = end - start;
for ( int offset = 0; offset < len; offset++ )
{
if ( mc.ab.length <= start + offset )
{
for (int offset = 0; offset < len; offset++) {
if (mc.ab.length <= start + offset) {
return "data buffer too small";
}
if ( ab[start + offset] != mc.ab[start + offset] )
{
if (ab[start + offset] != mc.ab[start + offset]) {
return "data missmatch at index " + i + " offset=" + offset;
}
}
if ( fapos[i] != mc.fapos[i] )
{
if (fapos[i] != mc.fapos[i]) {
return "fapos missmatch at index " + i + ":" + fapos[i] + "->" + mc.fapos[i];
}
}
if ( aboffset != mc.aboffset )
{
if (aboffset != mc.aboffset) {
return "datasize missmatch: " + aboffset + "->" + mc.aboffset;
}
return null;
}
public void calcDelta( MicroCache mc1, MicroCache mc2 )
{
public void calcDelta(MicroCache mc1, MicroCache mc2) {
int idx1 = 0;
int idx2 = 0;
while( idx1 < mc1.size || idx2 < mc2.size )
{
while (idx1 < mc1.size || idx2 < mc2.size) {
int id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
int id;
if ( id1 >= id2 )
{
if (id1 >= id2) {
id = id2;
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
int len2 = mc2.fapos[idx2++] - start2;
if ( id1 == id2 )
{
if (id1 == id2) {
// id exists in both caches, compare data
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
int len1 = mc1.fapos[idx1++] - start1;
if ( len1 == len2 )
{
if (len1 == len2) {
int i = 0;
while( i<len1 )
{
if ( mc1.ab[start1+i] != mc2.ab[start2+i] )
{
while (i < len1) {
if (mc1.ab[start1 + i] != mc2.ab[start2 + i]) {
break;
}
i++;
}
if ( i == len1 )
{
if (i == len1) {
continue; // same data -> do nothing
}
}
}
write(mc2.ab, start2, len2);
}
else
{
} else {
idx1++;
id = id1; // deleted node
}
@ -366,21 +311,18 @@ public class MicroCache extends ByteDataWriter
}
}
public void addDelta( MicroCache mc1, MicroCache mc2, boolean keepEmptyNodes )
{
public void addDelta(MicroCache mc1, MicroCache mc2, boolean keepEmptyNodes) {
int idx1 = 0;
int idx2 = 0;
while( idx1 < mc1.size || idx2 < mc2.size )
{
while (idx1 < mc1.size || idx2 < mc2.size) {
int id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
if (id1 >= id2) // data from diff file wins
{
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
int len2 = mc2.fapos[idx2++] - start2;
if ( keepEmptyNodes || len2 > 0 )
{
if (keepEmptyNodes || len2 > 0) {
write(mc2.ab, start2, len2);
fapos[size] = aboffset;
faid[size++] = id2;
@ -389,8 +331,7 @@ public class MicroCache extends ByteDataWriter
{
idx1++;
}
}
else // use data from base file
} else // use data from base file
{
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
int len1 = mc1.fapos[idx1++] - start1;

View File

@ -9,14 +9,12 @@ import btools.util.IByteArrayUnifier;
* MicroCache2 is the new format that uses statistical encoding and
* is able to do access filtering and waypoint matching during encoding
*/
public final class MicroCache2 extends MicroCache
{
public final class MicroCache2 extends MicroCache {
private int lonBase;
private int latBase;
private int cellsize;
public MicroCache2( int size, byte[] databuffer, int lonIdx, int latIdx, int divisor )
{
public MicroCache2(int size, byte[] databuffer, int lonIdx, int latIdx, int divisor) {
super(databuffer); // sets ab=databuffer, aboffset=0
faid = new int[size];
@ -27,15 +25,13 @@ public final class MicroCache2 extends MicroCache
latBase = latIdx * cellsize;
}
public byte[] readUnified( int len, IByteArrayUnifier u )
{
public byte[] readUnified(int len, IByteArrayUnifier u) {
byte[] b = u.unify(ab, aboffset, len);
aboffset += len;
return b;
}
public MicroCache2( StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher )
{
public MicroCache2(StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher) {
super(null);
cellsize = 1000000 / divisor;
lonBase = lonIdx * cellsize;
@ -54,16 +50,15 @@ public final class MicroCache2 extends MicroCache
fapos = size > dataBuffers.ibuf3.length ? new int[size] : dataBuffers.ibuf3;
int[] alon = size > dataBuffers.alon.length ? new int[size] : dataBuffers.alon;
int[] alat = size > dataBuffers.alat.length ? new int[size] : dataBuffers.alat;
if ( debug ) System.out.println( "*** decoding cache of size=" + size + " for lonIdx=" + lonIdx + " latIdx=" + latIdx );
if (debug)
System.out.println("*** decoding cache of size=" + size + " for lonIdx=" + lonIdx + " latIdx=" + latIdx);
bc.decodeSortedArray(faid, 0, size, 29, 0);
for( int n = 0; n<size; n++ )
{
for (int n = 0; n < size; n++) {
long id64 = expandId(faid[n]);
alon[n] = (int) (id64 >> 32);
alat[n] = (int) (id64 & 0xffffffff);
@ -88,21 +83,18 @@ public final class MicroCache2 extends MicroCache
// future escapes (turn restrictions?)
short trExceptions = 0;
int featureId = bc.decodeVarBits();
if ( featureId == 13 )
{
if (featureId == 13) {
fapos[n] = aboffset;
validBits[n >> 5] |= 1 << n; // mark dummy-node valid
continue; // empty node escape (delta files only)
}
while( featureId != 0 )
{
while (featureId != 0) {
int bitsize = bc.decodeNoisyNumber(5);
if (featureId == 2) // exceptions to turn-restriction
{
trExceptions = (short) bc.decodeBounded(1023);
}
else if ( featureId == 1 ) // turn-restriction
} else if (featureId == 1) // turn-restriction
{
writeBoolean(true);
writeShort(trExceptions); // exceptions from previous feature
@ -113,9 +105,7 @@ public final class MicroCache2 extends MicroCache
writeInt(ilat + bc.decodeNoisyDiff(10)); // fromLat
writeInt(ilon + bc.decodeNoisyDiff(10)); // toLon
writeInt(ilat + bc.decodeNoisyDiff(10)); // toLat
}
else
{
} else {
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
}
featureId = bc.decodeVarBits();
@ -128,9 +118,9 @@ public final class MicroCache2 extends MicroCache
writeVarBytes(nodeTags == null ? null : nodeTags.data);
int links = bc.decodeNoisyNumber(1);
if ( debug ) System.out.println( "*** decoding node " + ilon + "/" + ilat + " with links=" + links );
for( int li=0; li<links; li++ )
{
if (debug)
System.out.println("*** decoding node " + ilon + "/" + ilat + " with links=" + links);
for (int li = 0; li < links; li++) {
int sizeoffset = 0;
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
@ -142,20 +132,18 @@ public final class MicroCache2 extends MicroCache
{
dlon_remaining = alon[nodeIdx] - ilon;
dlat_remaining = alat[nodeIdx] - ilat;
}
else
{
} else {
isReverse = bc.decodeBit();
dlon_remaining = extLonDiff.decodeSignedValue();
dlat_remaining = extLatDiff.decodeSignedValue();
}
if ( debug ) System.out.println( "*** decoding link to " + (ilon+dlon_remaining) + "/" + (ilat+dlat_remaining) + " extern=" + (nodeIdx == n) );
if (debug)
System.out.println("*** decoding link to " + (ilon + dlon_remaining) + "/" + (ilat + dlat_remaining) + " extern=" + (nodeIdx == n));
TagValueWrapper wayTags = wayTagCoder.decodeTagValueSet();
boolean linkValid = wayTags != null || wayValidator == null;
if ( linkValid )
{
if (linkValid) {
int startPointer = aboffset;
sizeoffset = writeSizePlaceHolder();
@ -177,10 +165,8 @@ public final class MicroCache2 extends MicroCache
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;
}
}
@ -188,27 +174,25 @@ public final class MicroCache2 extends MicroCache
int transcount = bc.decodeVarBits();
if (debug) System.out.println("*** decoding geometry with count=" + transcount);
int count = transcount + 1;
for( int i=0; i<transcount; i++ )
{
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 )
{
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 ( linkValid )
{
if (linkValid) {
injectSize(sizeoffset);
}
}
@ -218,11 +202,9 @@ public final class MicroCache2 extends MicroCache
// calculate final data size
int finalsize = 0;
int startpos = 0;
for( int i=0; i<size; i++ )
{
for (int i = 0; i < size; i++) {
int endpos = fapos[i];
if ( ( validBits[ i >> 5 ] & (1 << i ) ) != 0 )
{
if ((validBits[i >> 5] & (1 << i)) != 0) {
finaldatasize += endpos - startpos;
finalsize++;
}
@ -240,11 +222,9 @@ public final class MicroCache2 extends MicroCache
size = 0;
startpos = 0;
for ( int n = 0; n < sizeOld; n++ )
{
for (int n = 0; n < sizeOld; n++) {
int endpos = faposOld[n];
if ( ( validBits[ n >> 5 ] & (1 << n ) ) != 0 )
{
if ((validBits[n >> 5] & (1 << n)) != 0) {
int len = endpos - startpos;
System.arraycopy(abOld, startpos, ab, aboffset, len);
if (debug)
@ -255,8 +235,7 @@ public final class MicroCache2 extends MicroCache
if (debug)
System.out.println("*** appending " + cnt + " reverse links for node " + n);
for ( int ri = 0; ri < cnt; ri++ )
{
for (int ri = 0; ri < cnt; ri++) {
int nodeIdx = reverseLinks.getDataElement();
int sizeoffset = writeSizePlaceHolder();
writeVarLengthSigned(alon[nodeIdx] - alon[n]);
@ -274,13 +253,11 @@ public final class MicroCache2 extends MicroCache
}
@Override
public long expandId( int id32 )
{
public long expandId(int id32) {
int dlon = 0;
int dlat = 0;
for( int bm = 1; bm < 0x8000; bm <<= 1 )
{
for (int bm = 1; bm < 0x8000; bm <<= 1) {
if ((id32 & 1) != 0) dlon |= bm;
if ((id32 & 2) != 0) dlat |= bm;
id32 >>= 2;
@ -293,16 +270,14 @@ public final class MicroCache2 extends MicroCache
}
@Override
public int shrinkId( long id64 )
{
public int shrinkId(long id64) {
int lon32 = (int) (id64 >> 32);
int lat32 = (int) (id64 & 0xffffffff);
int dlon = lon32 - lonBase;
int dlat = lat32 - latBase;
int id32 = 0;
for( int bm = 0x4000; bm > 0; bm >>= 1 )
{
for (int bm = 0x4000; bm > 0; bm >>= 1) {
id32 <<= 2;
if ((dlon & bm) != 0) id32 |= 1;
if ((dlat & bm) != 0) id32 |= 2;
@ -311,15 +286,13 @@ public final class MicroCache2 extends MicroCache
}
@Override
public boolean isInternal( int ilon, int ilat )
{
public boolean isInternal(int ilon, int ilat) {
return ilon >= lonBase && ilon < lonBase + cellsize
&& ilat >= latBase && ilat < latBase + cellsize;
}
@Override
public int encodeMicroCache( byte[] buffer )
{
public int encodeMicroCache(byte[] buffer) {
HashMap<Long, Integer> idMap = new HashMap<Long, Integer>();
for (int n = 0; n < size; n++) // loop over nodes
{
@ -376,24 +349,22 @@ public final class MicroCache2 extends MicroCache
{
aboffset = startPos(n);
aboffsetEnd = fapos[n];
if ( dodebug ) System.out.println( "*** encoding node " + n + " from " + aboffset + " to " + aboffsetEnd );
if (dodebug)
System.out.println("*** encoding node " + n + " from " + aboffset + " to " + aboffsetEnd);
long id64 = expandId(faid[n]);
int ilon = (int) (id64 >> 32);
int ilat = (int) (id64 & 0xffffffff);
if ( aboffset == aboffsetEnd )
{
if (aboffset == aboffsetEnd) {
bc.encodeVarBits(13); // empty node escape (delta files only)
continue;
}
// write turn restrictions
while( readBoolean() )
{
while (readBoolean()) {
short exceptions = readShort(); // except bikes, psv, ...
if ( exceptions != 0 )
{
if (exceptions != 0) {
bc.encodeVarBits(2); // 2 = tr exceptions
bc.encodeNoisyNumber(10, 5); // bit-count
bc.encodeBounded(1023, exceptions & 1023);
@ -437,8 +408,7 @@ public final class MicroCache2 extends MicroCache
boolean isReverse = (sizecode & 1) != 0;
int descSize = sizecode >> 1;
byte[] description = null;
if ( descSize > 0 )
{
if (descSize > 0) {
description = new byte[descSize];
readFully(description);
}
@ -447,25 +417,23 @@ public final class MicroCache2 extends MicroCache
Integer idx = idMap.get(Long.valueOf(link64));
boolean isInternal = idx != null;
if ( isReverse && isInternal )
{
if ( dodebug ) System.out.println( "*** NOT encoding link reverse=" + isReverse + " internal=" + isInternal );
if (isReverse && isInternal) {
if (dodebug)
System.out.println("*** NOT encoding link reverse=" + isReverse + " internal=" + isInternal);
netdatasize -= aboffset - startPointer;
continue; // do not encode internal reverse links
}
if ( dodebug ) System.out.println( "*** encoding link reverse=" + isReverse + " internal=" + isInternal );
if (dodebug)
System.out.println("*** encoding link reverse=" + isReverse + " internal=" + isInternal);
nlinks++;
if ( isInternal )
{
if (isInternal) {
int nodeIdx = idx.intValue();
if (dodebug) System.out.println("*** target nodeIdx=" + nodeIdx);
if (nodeIdx == n) throw new RuntimeException("ups: self ref?");
nodeIdxDiff.encodeSignedValue(nodeIdx - n);
if (dostats) bc.assignBits("nodeIdx");
}
else
{
} else {
nodeIdxDiff.encodeSignedValue(0);
bc.encodeBit(isReverse);
extLonDiff.encodeSignedValue(ilonlink - ilon);
@ -475,8 +443,7 @@ public final class MicroCache2 extends MicroCache
wayTagCoder.encodeTagValueSet(description);
if (dostats) bc.assignBits("wayDescIdx");
if ( !isReverse )
{
if (!isReverse) {
byte[] geometry = readDataUntil(endPointer);
// write transition nodes
int count = transCounts.getNext();
@ -484,14 +451,12 @@ public final class MicroCache2 extends MicroCache
bc.encodeVarBits(count++);
if (dostats) bc.assignBits("transcount");
int transcount = 0;
if ( geometry != null )
{
if (geometry != null) {
int dlon_remaining = ilonlink - ilon;
int dlat_remaining = ilatlink - ilat;
ByteDataReader r = new ByteDataReader(geometry);
while ( r.hasMoreData() )
{
while (r.hasMoreData()) {
transcount++;
int dlon = r.readVarLengthSigned();
@ -511,8 +476,7 @@ public final class MicroCache2 extends MicroCache
}
linkCounts.add(nlinks);
}
if ( pass == 3 )
{
if (pass == 3) {
return bc.closeAndGetEncodedLength();
}
}

View File

@ -4,12 +4,11 @@ package btools.codec;
* Encoder/Decoder for signed integers that automatically detects the typical
* range of these numbers to determine a noisy-bit count as a very simple
* dictionary
*
* <p>
* Adapted for 3-pass encoding (counters -&gt; statistics -&gt; encoding )
* but doesn't do anything at pass1
*/
public final class NoisyDiffCoder
{
public final class NoisyDiffCoder {
private int tot;
private int[] freqs;
private int noisybits;
@ -19,8 +18,7 @@ public final class NoisyDiffCoder
/**
* Create a decoder and read the noisy-bit count from the gibe context
*/
public NoisyDiffCoder( StatCoderContext bc )
{
public NoisyDiffCoder(StatCoderContext bc) {
noisybits = bc.decodeVarBits();
this.bc = bc;
}
@ -28,21 +26,16 @@ public final class NoisyDiffCoder
/**
* Create an encoder for 3-pass-encoding
*/
public NoisyDiffCoder()
{
public NoisyDiffCoder() {
}
/**
* encodes a signed int (pass3 only, stats collection in pass2)
*/
public void encodeSignedValue( int value )
{
if ( pass == 3 )
{
public void encodeSignedValue(int value) {
if (pass == 3) {
bc.encodeNoisyDiff(value, noisybits);
}
else if ( pass == 2 )
{
} else if (pass == 2) {
count(value < 0 ? -value : value);
}
}
@ -50,8 +43,7 @@ public final class NoisyDiffCoder
/**
* decodes a signed int
*/
public int decodeSignedValue()
{
public int decodeSignedValue() {
return bc.decodeNoisyDiff(noisybits);
}
@ -59,13 +51,10 @@ public final class NoisyDiffCoder
* Starts a new encoding pass and (in pass3) calculates the noisy-bit count
* from the stats collected in pass2 and writes that to the given context
*/
public void encodeDictionary( StatCoderContext bc )
{
if ( ++pass == 3 )
{
public void encodeDictionary(StatCoderContext bc) {
if (++pass == 3) {
// how many noisy bits?
for ( noisybits = 0; noisybits < 14 && tot > 0; noisybits++ )
{
for (noisybits = 0; noisybits < 14 && tot > 0; noisybits++) {
if (freqs[noisybits] < (tot >> 1))
break;
}
@ -74,13 +63,11 @@ public final class NoisyDiffCoder
this.bc = bc;
}
private void count( int value )
{
private void count(int value) {
if (freqs == null)
freqs = new int[14];
int bm = 1;
for ( int i = 0; i < 14; i++ )
{
for (int i = 0; i < 14; i++) {
if (value < bm)
break;
else

View File

@ -4,23 +4,19 @@ import java.util.TreeMap;
import btools.util.BitCoderContext;
public final class StatCoderContext extends BitCoderContext
{
public final class StatCoderContext extends BitCoderContext {
private static TreeMap<String, long[]> statsPerName;
private long lastbitpos = 0;
private static final int[] noisy_bits = new int[1024];
static
{
static {
// noisybits lookup
for( int i=0; i<1024; i++ )
{
for (int i = 0; i < 1024; i++) {
int p = i;
int noisybits = 0;
while (p > 2)
{
while (p > 2) {
noisybits++;
p >>= 1;
}
@ -29,8 +25,7 @@ public final class StatCoderContext extends BitCoderContext
}
public StatCoderContext( byte[] ab )
{
public StatCoderContext(byte[] ab) {
super(ab);
}
@ -40,16 +35,13 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #getBitReport
*/
public void assignBits( String name )
{
public void assignBits(String name) {
long bitpos = getWritingBitPosition();
if ( statsPerName == null )
{
if (statsPerName == null) {
statsPerName = new TreeMap<String, long[]>();
}
long[] stats = statsPerName.get(name);
if ( stats == null )
{
if (stats == null) {
stats = new long[2];
statsPerName.put(name, stats);
}
@ -63,15 +55,12 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #assignBits
*/
public static String getBitReport()
{
if ( statsPerName == null )
{
public static String getBitReport() {
if (statsPerName == null) {
return "<empty bit report>";
}
StringBuilder sb = new StringBuilder();
for ( String name : statsPerName.keySet() )
{
for (String name : statsPerName.keySet()) {
long[] stats = statsPerName.get(name);
sb.append(name + " count=" + stats[1] + " bits=" + stats[0] + "\n");
}
@ -85,14 +74,11 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #decodeNoisyNumber
*/
public void encodeNoisyNumber( int value, int noisybits )
{
if ( value < 0 )
{
public void encodeNoisyNumber(int value, int noisybits) {
if (value < 0) {
throw new IllegalArgumentException("encodeVarBits expects positive value");
}
if ( noisybits > 0 )
{
if (noisybits > 0) {
int mask = 0xffffffff >>> (32 - noisybits);
encodeBounded(mask, value & mask);
value >>= noisybits;
@ -106,8 +92,7 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #encodeNoisyNumber
*/
public int decodeNoisyNumber( int noisybits )
{
public int decodeNoisyNumber(int noisybits) {
int value = decodeBits(noisybits);
return value | (decodeVarBits() << noisybits);
}
@ -118,18 +103,15 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #decodeNoisyDiff
*/
public void encodeNoisyDiff( int value, int noisybits )
{
if ( noisybits > 0 )
{
public void encodeNoisyDiff(int value, int noisybits) {
if (noisybits > 0) {
value += 1 << (noisybits - 1);
int mask = 0xffffffff >>> (32 - noisybits);
encodeBounded(mask, value & mask);
value >>= noisybits;
}
encodeVarBits(value < 0 ? -value : value);
if ( value != 0 )
{
if (value != 0) {
encodeBit(value < 0);
}
}
@ -140,18 +122,14 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #encodeNoisyDiff
*/
public int decodeNoisyDiff( int noisybits )
{
public int decodeNoisyDiff(int noisybits) {
int value = 0;
if ( noisybits > 0 )
{
if (noisybits > 0) {
value = decodeBits(noisybits) - (1 << (noisybits - 1));
}
int val2 = decodeVarBits() << noisybits;
if ( val2 != 0 )
{
if ( decodeBit() )
{
if (val2 != 0) {
if (decodeBit()) {
val2 = -val2;
}
}
@ -164,13 +142,11 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #decodePredictedValue
*/
public void encodePredictedValue( int value, int predictor )
{
public void encodePredictedValue(int value, int predictor) {
int p = predictor < 0 ? -predictor : predictor;
int noisybits = 0;
while (p > 2)
{
while (p > 2) {
noisybits++;
p >>= 1;
}
@ -183,12 +159,10 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #encodePredictedValue
*/
public int decodePredictedValue( int predictor )
{
public int decodePredictedValue(int predictor) {
int p = predictor < 0 ? -predictor : predictor;
int noisybits = 0;
while (p > 1023)
{
while (p > 1023) {
noisybits++;
p >>= 1;
}
@ -202,29 +176,21 @@ public final class StatCoderContext extends BitCoderContext
* bits per value that only depends on the typical distance between subsequent
* values and also benefits
*
* @param values
* the array to encode
* @param offset
* position in this array where to start
* @param subsize
* number of values to encode
* @param nextbit
* bitmask with the most significant bit set to 1
* @param mask
* should be 0
* @param values the array to encode
* @param offset position in this array where to start
* @param subsize number of values to encode
* @param nextbit bitmask with the most significant bit set to 1
* @param mask should be 0
*/
public void encodeSortedArray( int[] values, int offset, int subsize, int nextbit, int mask )
{
public void encodeSortedArray(int[] values, int offset, int subsize, int nextbit, int mask) {
if (subsize == 1) // last-choice shortcut
{
while (nextbit != 0)
{
while (nextbit != 0) {
encodeBit((values[offset] & nextbit) != 0);
nextbit >>= 1;
}
}
if ( nextbit == 0 )
{
if (nextbit == 0) {
return;
}
@ -234,10 +200,8 @@ public final class StatCoderContext extends BitCoderContext
// count 0-bit-fraction
int i = offset;
int end = subsize + offset;
for ( ; i < end; i++ )
{
if ( ( values[i] & mask ) != data )
{
for (; i < end; i++) {
if ((values[i] & mask) != data) {
break;
}
}
@ -245,45 +209,33 @@ public final class StatCoderContext extends BitCoderContext
int size2 = subsize - size1;
encodeBounded(subsize, size1);
if ( size1 > 0 )
{
if (size1 > 0) {
encodeSortedArray(values, offset, size1, nextbit >> 1, mask);
}
if ( size2 > 0 )
{
if (size2 > 0) {
encodeSortedArray(values, i, size2, nextbit >> 1, mask);
}
}
/**
* @param values the array to encode
* @param offset position in this array where to start
* @param subsize number of values to encode
* @param nextbit bitmask with the most significant bit set to 1
* @param value should be 0
* @see #encodeSortedArray
*
* @param values
* the array to encode
* @param offset
* position in this array where to start
* @param subsize
* number of values to encode
* @param nextbit
* bitmask with the most significant bit set to 1
* @param value
* should be 0
*/
public void decodeSortedArray( int[] values, int offset, int subsize, int nextbitpos, int value )
{
public void decodeSortedArray(int[] values, int offset, int subsize, int nextbitpos, int value) {
if (subsize == 1) // last-choice shortcut
{
if ( nextbitpos >= 0 )
{
if (nextbitpos >= 0) {
value |= decodeBitsReverse(nextbitpos + 1);
}
values[offset] = value;
return;
}
if ( nextbitpos < 0 )
{
while (subsize-- > 0)
{
if (nextbitpos < 0) {
while (subsize-- > 0) {
values[offset++] = value;
}
return;
@ -292,12 +244,10 @@ public final class StatCoderContext extends BitCoderContext
int size1 = decodeBounded(subsize);
int size2 = subsize - size1;
if ( size1 > 0 )
{
if (size1 > 0) {
decodeSortedArray(values, offset, size1, nextbitpos - 1, value);
}
if ( size2 > 0 )
{
if (size2 > 0) {
decodeSortedArray(values, offset + size1, size2, nextbitpos - 1, value | (1 << nextbitpos));
}
}

View File

@ -8,38 +8,31 @@ import btools.util.BitCoderContext;
/**
* Encoder/Decoder for way-/node-descriptions
*
* <p>
* It detects identical descriptions and sorts them
* into a huffman-tree according to their frequencies
*
* <p>
* Adapted for 3-pass encoding (counters -&gt; statistics -&gt; encoding )
* but doesn't do anything at pass1
*/
public final class TagValueCoder
{
public final class TagValueCoder {
private HashMap<TagValueSet, TagValueSet> identityMap;
private Object tree;
private BitCoderContext bc;
private int pass;
private int nextTagValueSetId;
public void encodeTagValueSet( byte[] data )
{
if ( pass == 1 )
{
public void encodeTagValueSet(byte[] data) {
if (pass == 1) {
return;
}
TagValueSet tvsProbe = new TagValueSet(nextTagValueSetId);
tvsProbe.data = data;
TagValueSet tvs = identityMap.get(tvsProbe);
if ( pass == 3 )
{
if (pass == 3) {
bc.encodeBounded(tvs.range - 1, tvs.code);
}
else if ( pass == 2 )
{
if ( tvs == null )
{
} else if (pass == 2) {
if (tvs == null) {
tvs = tvsProbe;
nextTagValueSetId++;
identityMap.put(tvs, tvs);
@ -48,11 +41,9 @@ public final class TagValueCoder
}
}
public TagValueWrapper decodeTagValueSet()
{
public TagValueWrapper decodeTagValueSet() {
Object node = tree;
while (node instanceof TreeNode)
{
while (node instanceof TreeNode) {
TreeNode tn = (TreeNode) node;
boolean nextBit = bc.decodeBit();
node = nextBit ? tn.child2 : tn.child1;
@ -60,19 +51,15 @@ public final class TagValueCoder
return (TagValueWrapper) node;
}
public void encodeDictionary( BitCoderContext bc )
{
if ( ++pass == 3 )
{
if ( identityMap.size() == 0 )
{
public void encodeDictionary(BitCoderContext bc) {
if (++pass == 3) {
if (identityMap.size() == 0) {
TagValueSet dummy = new TagValueSet(nextTagValueSetId++);
identityMap.put(dummy, dummy);
}
PriorityQueue<TagValueSet> queue = new PriorityQueue<TagValueSet>(2 * identityMap.size(), new TagValueSet.FrequencyComparator());
queue.addAll(identityMap.values());
while (queue.size() > 1)
{
while (queue.size() > 1) {
TagValueSet node = new TagValueSet(nextTagValueSetId++);
node.child1 = queue.poll();
node.child2 = queue.poll();
@ -85,22 +72,18 @@ public final class TagValueCoder
this.bc = bc;
}
public TagValueCoder( BitCoderContext bc, DataBuffers buffers, TagValueValidator validator )
{
public TagValueCoder(BitCoderContext bc, DataBuffers buffers, TagValueValidator validator) {
tree = decodeTree(bc, buffers, validator);
this.bc = bc;
}
public TagValueCoder()
{
public TagValueCoder() {
identityMap = new HashMap<TagValueSet, TagValueSet>();
}
private Object decodeTree( BitCoderContext bc, DataBuffers buffers, TagValueValidator validator )
{
private Object decodeTree(BitCoderContext bc, DataBuffers buffers, TagValueValidator validator) {
boolean isNode = bc.decodeBit();
if ( isNode )
{
if (isNode) {
TreeNode node = new TreeNode();
node.child1 = decodeTree(bc, buffers, validator);
node.child2 = decodeTree(bc, buffers, validator);
@ -115,18 +98,14 @@ public final class TagValueCoder
int lastEncodedInum = 0;
boolean hasdata = false;
for ( ;; )
{
for (; ; ) {
int delta = bc.decodeVarBits();
if ( !hasdata )
{
if ( delta == 0 )
{
if (!hasdata) {
if (delta == 0) {
return null;
}
}
if ( delta == 0 )
{
if (delta == 0) {
ctx.encodeVarBits(0);
break;
}
@ -134,8 +113,7 @@ public final class TagValueCoder
int data = bc.decodeVarBits();
if ( validator == null || validator.isLookupIdxUsed( inum ) )
{
if (validator == null || validator.isLookupIdxUsed(inum)) {
hasdata = true;
ctx.encodeVarBits(inum - lastEncodedInum);
ctx.encodeVarBits(data);
@ -145,19 +123,15 @@ public final class TagValueCoder
byte[] res;
int len = ctx.closeAndGetEncodedLength();
if ( validator == null )
{
if (validator == null) {
res = new byte[len];
System.arraycopy(buffer, 0, res, 0, len);
}
else
{
} else {
res = validator.unify(buffer, 0, len);
}
int accessType = validator == null ? 2 : validator.accessType(res);
if ( accessType > 0 )
{
if (accessType > 0) {
TagValueWrapper w = new TagValueWrapper();
w.data = res;
w.accessType = accessType;
@ -166,14 +140,12 @@ public final class TagValueCoder
return null;
}
public static final class TreeNode
{
public static final class TreeNode {
public Object child1;
public Object child2;
}
public static final class TagValueSet
{
public static final class TagValueSet {
public byte[] data;
public int frequency;
public int code;
@ -182,36 +154,28 @@ public final class TagValueCoder
public TagValueSet child2;
private int id; // serial number to make the comparator well defined in case of equal frequencies
public TagValueSet( int id )
{
public TagValueSet(int id) {
this.id = id;
}
public void encode( BitCoderContext bc, int range, int code )
{
public void encode(BitCoderContext bc, int range, int code) {
this.range = range;
this.code = code;
boolean isNode = child1 != null;
bc.encodeBit(isNode);
if ( isNode )
{
if (isNode) {
child1.encode(bc, range << 1, code);
child2.encode(bc, range << 1, code + range);
}
else
{
if ( data == null )
{
} else {
if (data == null) {
bc.encodeVarBits(0);
return;
}
BitCoderContext src = new BitCoderContext(data);
for ( ;; )
{
for (; ; ) {
int delta = src.decodeVarBits();
bc.encodeVarBits(delta);
if ( delta == 0 )
{
if (delta == 0) {
break;
}
int data = src.decodeVarBits();
@ -221,27 +185,20 @@ public final class TagValueCoder
}
@Override
public boolean equals( Object o )
{
if ( o instanceof TagValueSet )
{
public boolean equals(Object o) {
if (o instanceof TagValueSet) {
TagValueSet tvs = (TagValueSet) o;
if ( data == null )
{
if (data == null) {
return tvs.data == null;
}
if ( tvs.data == null )
{
if (tvs.data == null) {
return data == null;
}
if ( data.length != tvs.data.length )
{
if (data.length != tvs.data.length) {
return false;
}
for ( int i = 0; i < data.length; i++ )
{
if ( data[i] != tvs.data[i] )
{
for (int i = 0; i < data.length; i++) {
if (data[i] != tvs.data[i]) {
return false;
}
}
@ -251,22 +208,18 @@ public final class TagValueCoder
}
@Override
public int hashCode()
{
if ( data == null )
{
public int hashCode() {
if (data == null) {
return 0;
}
int h = 17;
for ( int i = 0; i < data.length; i++ )
{
for (int i = 0; i < data.length; i++) {
h = (h << 8) + data[i];
}
return h;
}
public static class FrequencyComparator implements Comparator<TagValueSet>
{
public static class FrequencyComparator implements Comparator<TagValueSet> {
@Override
public int compare(TagValueSet tvs1, TagValueSet tvs2) {
@ -281,8 +234,7 @@ public final class TagValueCoder
if (tvs1.id > tvs2.id)
return 1;
if ( tvs1 != tvs2 )
{
if (tvs1 != tvs2) {
throw new RuntimeException("identity corruption!");
}
return 0;

View File

@ -1,8 +1,7 @@
package btools.codec;
public interface TagValueValidator
{
public interface TagValueValidator {
/**
* @param tagValueSet the way description to check
* @return 0 = nothing, 1=no matching, 2=normal

View File

@ -5,8 +5,7 @@ package btools.codec;
* TagValueWrapper wrapps a description bitmap
* to add the access-type
*/
public final class TagValueWrapper
{
public final class TagValueWrapper {
public byte[] data;
public int accessType;
}

View File

@ -5,9 +5,10 @@ package btools.codec;
* from the decoder to find the closest
* matches to the waypoints
*/
public interface WaypointMatcher
{
public interface WaypointMatcher {
boolean start(int ilonStart, int ilatStart, int ilonTarget, int ilatTarget);
void transferNode(int ilon, int ilat);
void end();
}

View File

@ -3,50 +3,39 @@ package btools.codec;
import org.junit.Assert;
import org.junit.Test;
public class LinkedListContainerTest
{
public class LinkedListContainerTest {
@Test
public void linkedListTest1()
{
public void linkedListTest1() {
int nlists = 553;
LinkedListContainer llc = new LinkedListContainer(nlists, null);
for ( int ln = 0; ln < nlists; ln++ )
{
for ( int i = 0; i < 10; i++ )
{
for (int ln = 0; ln < nlists; ln++) {
for (int i = 0; i < 10; i++) {
llc.addDataElement(ln, ln * i);
}
}
for ( int i = 0; i < 10; i++ )
{
for ( int ln = 0; ln < nlists; ln++ )
{
for (int i = 0; i < 10; i++) {
for (int ln = 0; ln < nlists; ln++) {
llc.addDataElement(ln, ln * i);
}
}
for ( int ln = 0; ln < nlists; ln++ )
{
for (int ln = 0; ln < nlists; ln++) {
int cnt = llc.initList(ln);
Assert.assertTrue("list size test", cnt == 20);
for ( int i = 19; i >= 0; i-- )
{
for (int i = 19; i >= 0; i--) {
int data = llc.getDataElement();
Assert.assertTrue("data value test", data == ln * (i % 10));
}
}
try
{
try {
llc.getDataElement();
Assert.fail("no more elements expected");
}
catch (IllegalArgumentException e)
{
} catch (IllegalArgumentException e) {
}
}
}

View File

@ -6,30 +6,23 @@ import java.util.Random;
import org.junit.Assert;
import org.junit.Test;
public class StatCoderContextTest
{
public class StatCoderContextTest {
@Test
public void noisyVarBitsEncodeDecodeTest()
{
public void noisyVarBitsEncodeDecodeTest() {
byte[] ab = new byte[40000];
StatCoderContext ctx = new StatCoderContext(ab);
for ( int noisybits = 1; noisybits < 12; noisybits++ )
{
for ( int i = 0; i < 1000; i++ )
{
for (int noisybits = 1; noisybits < 12; noisybits++) {
for (int i = 0; i < 1000; i++) {
ctx.encodeNoisyNumber(i, noisybits);
}
}
ctx.closeAndGetEncodedLength();
ctx = new StatCoderContext(ab);
for ( int noisybits = 1; noisybits < 12; noisybits++ )
{
for ( int i = 0; i < 1000; i++ )
{
for (int noisybits = 1; noisybits < 12; noisybits++) {
for (int i = 0; i < 1000; i++) {
int value = ctx.decodeNoisyNumber(noisybits);
if ( value != i )
{
if (value != i) {
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
}
}
@ -37,27 +30,21 @@ public class StatCoderContextTest
}
@Test
public void noisySignedVarBitsEncodeDecodeTest()
{
public void noisySignedVarBitsEncodeDecodeTest() {
byte[] ab = new byte[80000];
StatCoderContext ctx = new StatCoderContext(ab);
for ( int noisybits = 0; noisybits < 12; noisybits++ )
{
for ( int i = -1000; i < 1000; i++ )
{
for (int noisybits = 0; noisybits < 12; noisybits++) {
for (int i = -1000; i < 1000; i++) {
ctx.encodeNoisyDiff(i, noisybits);
}
}
ctx.closeAndGetEncodedLength();
ctx = new StatCoderContext(ab);
for ( int noisybits = 0; noisybits < 12; noisybits++ )
{
for ( int i = -1000; i < 1000; i++ )
{
for (int noisybits = 0; noisybits < 12; noisybits++) {
for (int i = -1000; i < 1000; i++) {
int value = ctx.decodeNoisyDiff(noisybits);
if ( value != i )
{
if (value != i) {
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
}
}
@ -65,27 +52,21 @@ public class StatCoderContextTest
}
@Test
public void predictedValueEncodeDecodeTest()
{
public void predictedValueEncodeDecodeTest() {
byte[] ab = new byte[80000];
StatCoderContext ctx = new StatCoderContext(ab);
for ( int value = -100; value < 100; value += 5 )
{
for ( int predictor = -200; predictor < 200; predictor += 7 )
{
for (int value = -100; value < 100; value += 5) {
for (int predictor = -200; predictor < 200; predictor += 7) {
ctx.encodePredictedValue(value, predictor);
}
}
ctx.closeAndGetEncodedLength();
ctx = new StatCoderContext(ab);
for ( int value = -100; value < 100; value += 5 )
{
for ( int predictor = -200; predictor < 200; predictor += 7 )
{
for (int value = -100; value < 100; value += 5) {
for (int predictor = -200; predictor < 200; predictor += 7) {
int decodedValue = ctx.decodePredictedValue(predictor);
if ( value != decodedValue )
{
if (value != decodedValue) {
Assert.fail("value mismatch: value=" + value + " predictor=" + predictor + " decodedValue=" + decodedValue);
}
}
@ -93,13 +74,11 @@ public class StatCoderContextTest
}
@Test
public void sortedArrayEncodeDecodeTest()
{
public void sortedArrayEncodeDecodeTest() {
Random rand = new Random();
int size = 1000000;
int[] values = new int[size];
for ( int i = 0; i < size; i++ )
{
for (int i = 0; i < size; i++) {
values[i] = rand.nextInt() & 0x0fffffff;
}
values[5] = 175384; // force collision
@ -120,10 +99,8 @@ public class StatCoderContextTest
int[] decodedValues = new int[size];
ctx.decodeSortedArray(decodedValues, 0, size, 27, 0);
for ( int i = 0; i < size; i++ )
{
if ( values[i] != decodedValues[i] )
{
for (int i = 0; i < size; i++) {
if (values[i] != decodedValues[i]) {
Assert.fail("mismatch at i=" + i + " " + values[i] + "<>" + decodedValues[i]);
}
}

View File

@ -11,15 +11,12 @@ import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
final class KinematicModel extends OsmPathModel
{
public OsmPrePath createPrePath()
{
final class KinematicModel extends OsmPathModel {
public OsmPrePath createPrePath() {
return new KinematicPrePath();
}
public OsmPath createPath()
{
public OsmPath createPath() {
return new KinematicPath();
}
@ -55,10 +52,8 @@ final class KinematicModel extends OsmPathModel
private double lastBreakingSpeed;
@Override
public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String,String> extraParams )
{
if ( !initDone )
{
public void init(BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String, String> extraParams) {
if (!initDone) {
ctxWay = expctxWay;
ctxNode = expctxNode;
wayIdxMaxspeed = ctxWay.getOutputVariableIndex("maxspeed", false);
@ -86,46 +81,38 @@ final class KinematicModel extends OsmPathModel
cost0 = (pw + p_standby) / vmax + f_roll + f_air * vmax * vmax;
}
protected float getParam( String name, float defaultValue )
{
protected float getParam(String name, float defaultValue) {
String sval = params == null ? null : params.get(name);
if ( sval != null )
{
if (sval != null) {
return Float.parseFloat(sval);
}
float v = ctxWay.getVariableValue(name, defaultValue);
if ( params != null )
{
if (params != null) {
params.put(name, "" + v);
}
return v;
}
public float getWayMaxspeed()
{
public float getWayMaxspeed() {
return ctxWay.getBuildInVariable(wayIdxMaxspeed) / 3.6f;
}
public float getWayMaxspeedExplicit()
{
public float getWayMaxspeedExplicit() {
return ctxWay.getBuildInVariable(wayIdxMaxspeedExplicit) / 3.6f;
}
public float getWayMinspeed()
{
public float getWayMinspeed() {
return ctxWay.getBuildInVariable(wayIdxMinspeed) / 3.6f;
}
public float getNodeMaxspeed()
{
public float getNodeMaxspeed() {
return ctxNode.getBuildInVariable(nodeIdxMaxspeed) / 3.6f;
}
/**
* get the effective speed limit from the way-limit and vmax/vmin
*/
public double getEffectiveSpeedLimit( )
{
public double getEffectiveSpeedLimit() {
// performance related inline coding
double minspeed = getWayMinspeed();
double espeed = minspeed > vmax ? minspeed : vmax;
@ -136,10 +123,8 @@ final class KinematicModel extends OsmPathModel
/**
* get the breaking speed for current balance-power (pw) and effective speed limit (vl)
*/
public double getBreakingSpeed( double vl )
{
if ( vl == lastEffectiveLimit )
{
public double getBreakingSpeed(double vl) {
if (vl == lastEffectiveLimit) {
return lastBreakingSpeed;
}
@ -147,8 +132,7 @@ final class KinematicModel extends OsmPathModel
double pw2 = pw + p_standby;
double e = recup_efficiency;
double x0 = pw2 / vl + f_air * e * vl * vl + (1. - e) * f_roll;
for(int i=0;i<5;i++)
{
for (int i = 0; i < 5; i++) {
double v2 = v * v;
double x = pw2 / v + f_air * e * v2 - x0;
double dx = 2. * e * f_air * v - pw2 / v2;

View File

@ -8,8 +8,7 @@ package btools.router;
import btools.util.FastMath;
final class KinematicPath extends OsmPath
{
final class KinematicPath extends OsmPath {
private double ekin; // kinetic energy (Joule)
private double totalTime; // travel time (seconds)
private double totalEnergy; // total route energy (Joule)
@ -17,8 +16,7 @@ final class KinematicPath extends OsmPath
private float floatingAngleRight; // sliding average right bend (degree)
@Override
protected void init( OsmPath orig )
{
protected void init(OsmPath orig) {
KinematicPath origin = (KinematicPath) orig;
ekin = origin.ekin;
totalTime = origin.totalTime;
@ -29,8 +27,7 @@ final class KinematicPath extends OsmPath
}
@Override
protected void resetState()
{
protected void resetState() {
ekin = 0.;
totalTime = 0.;
totalEnergy = 0.;
@ -39,23 +36,18 @@ final class KinematicPath extends OsmPath
}
@Override
protected double processWaySection( RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier )
{
protected double processWaySection(RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier) {
KinematicModel km = (KinematicModel) rc.pm;
double cost = 0.;
double extraTime = 0.;
if ( isStartpoint )
{
if (isStartpoint) {
// for forward direction, we start with target speed
if ( !rc.inverseDirection )
{
if (!rc.inverseDirection) {
extraTime = 0.5 * (1. - cosangle) * 40.; // 40 seconds turn penalty
}
}
else
{
} else {
double turnspeed = 999.; // just high
if (km.turnAngleDecayTime != 0.) // process turn-angle slowdown
@ -70,8 +62,7 @@ final class KinematicPath extends OsmPath
floatingAngleLeft = (float) (floatingAngleLeft * decayFactor);
floatingAngleRight = (float) (floatingAngleRight * decayFactor);
if ( curveSpeed < 20. )
{
if (curveSpeed < 20.) {
turnspeed = curveSpeed;
}
}
@ -86,8 +77,7 @@ final class KinematicPath extends OsmPath
boolean hasLeftWay = false;
boolean hasRightWay = false;
boolean hasResidential = false;
for( OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next )
{
for (OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next) {
KinematicPrePath pp = (KinematicPrePath) prePath;
if (((pp.classifiermask ^ classifiermask) & 8) != 0) // exactly one is linktype
@ -100,8 +90,7 @@ final class KinematicPath extends OsmPath
hasResidential = true;
}
if ( pp.priorityclassifier > priorityclassifier || pp.priorityclassifier == priorityclassifier && priorityclassifier < 20 )
{
if (pp.priorityclassifier > priorityclassifier || pp.priorityclassifier == priorityclassifier && priorityclassifier < 20) {
double diff = pp.angle - angle;
if (diff < -40. && diff > -140.) hasLeftWay = true;
if (diff > 40. && diff < 140.) hasRightWay = true;
@ -113,20 +102,17 @@ final class KinematicPath extends OsmPath
if (hasRightWay && junctionspeed > km.rightWaySpeed) junctionspeed = km.rightWaySpeed;
if (hasResidential && junctionspeed > residentialSpeed) junctionspeed = residentialSpeed;
if ( (lastpriorityclassifier < 20) ^ (priorityclassifier < 20) )
{
if ((lastpriorityclassifier < 20) ^ (priorityclassifier < 20)) {
extraTime += 10.;
junctionspeed = 0; // full stop for entering or leaving road network
}
if ( lastpriorityclassifier != priorityclassifier && (classifiermask & 8) != 0 )
{
if (lastpriorityclassifier != priorityclassifier && (classifiermask & 8) != 0) {
extraTime += 2.; // two seconds for entering a link-type
}
turnspeed = turnspeed > junctionspeed ? junctionspeed : turnspeed;
if ( message != null )
{
if (message != null) {
message.vnode0 = (int) (junctionspeed * 3.6 + 0.5);
}
}
@ -143,8 +129,7 @@ final class KinematicPath extends OsmPath
double distanceCost = evolveDistance(km, dist, delta_h, f_air);
if ( message != null )
{
if (message != null) {
message.costfactor = (float) (distanceCost / dist);
message.vmax = (int) (km.getWayMaxspeed() * 3.6 + 0.5);
message.vmaxExplicit = (int) (km.getWayMaxspeedExplicit() * 3.6 + 0.5);
@ -159,15 +144,13 @@ final class KinematicPath extends OsmPath
}
protected double evolveDistance( KinematicModel km, double dist, double delta_h, double f_air )
{
protected double evolveDistance(KinematicModel km, double dist, double delta_h, double f_air) {
// elevation force
double fh = delta_h * km.totalweight * 9.81 / dist;
double effectiveSpeedLimit = km.getEffectiveSpeedLimit();
double emax = 0.5 * km.totalweight * effectiveSpeedLimit * effectiveSpeedLimit;
if ( emax <= 0. )
{
if (emax <= 0.) {
return -1.;
}
double vb = km.getBreakingSpeed(effectiveSpeedLimit);
@ -178,8 +161,7 @@ final class KinematicPath extends OsmPath
double v = Math.sqrt(2. * ekin / km.totalweight);
double d = dist;
while( d > 0. )
{
while (d > 0.) {
boolean slow = ekin < elow;
boolean fast = ekin >= emax;
double etarget = slow ? elow : emax;
@ -190,30 +172,24 @@ final class KinematicPath extends OsmPath
double delta_ekin;
double timeStep;
double x;
if ( fast )
{
if (fast) {
x = d;
delta_ekin = x * f;
timeStep = x / v;
ekin = etarget;
}
else
{
} else {
delta_ekin = etarget - ekin;
double b = 2. * f_air / km.totalweight;
double x0 = delta_ekin / f;
double x0b = x0 * b;
x = x0 * (1. - x0b * (0.5 + x0b * (0.333333333 - x0b * 0.25))); // = ln( delta_ekin*b/f + 1.) / b;
double maxstep = Math.min(50., d);
if ( x >= maxstep )
{
if (x >= maxstep) {
x = maxstep;
double xb = x * b;
delta_ekin = x * f * (1. + xb * (0.5 + xb * (0.166666667 + xb * 0.0416666667))); // = f/b* exp(xb-1)
ekin += delta_ekin;
}
else
{
} else {
ekin = etarget;
}
double v2 = Math.sqrt(2. * ekin / km.totalweight);
@ -242,23 +218,19 @@ final class KinematicPath extends OsmPath
}
@Override
protected double processTargetNode( RoutingContext rc )
{
protected double processTargetNode(RoutingContext rc) {
KinematicModel km = (KinematicModel) rc.pm;
// finally add node-costs for target node
if ( targetNode.nodeDescription != null )
{
if (targetNode.nodeDescription != null) {
rc.expctxNode.evaluate(false, targetNode.nodeDescription);
float initialcost = rc.expctxNode.getInitialcost();
if ( initialcost >= 1000000. )
{
if (initialcost >= 1000000.) {
return -1.;
}
cutEkin(km.totalweight, km.getNodeMaxspeed()); // apply node maxspeed
if ( message != null )
{
if (message != null) {
message.linknodecost += (int) initialcost;
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(false, targetNode.nodeDescription);
@ -269,22 +241,19 @@ final class KinematicPath extends OsmPath
return 0.;
}
private void cutEkin( double weight, double speed )
{
private void cutEkin(double weight, double speed) {
double e = 0.5 * weight * speed * speed;
if (ekin > e) ekin = e;
}
@Override
public int elevationCorrection( RoutingContext rc )
{
public int elevationCorrection(RoutingContext rc) {
return 0;
}
@Override
public boolean definitlyWorseThan( OsmPath path, RoutingContext rc )
{
public boolean definitlyWorseThan(OsmPath path, RoutingContext rc) {
KinematicPath p = (KinematicPath) path;
int c = p.cost;
@ -292,14 +261,12 @@ final class KinematicPath extends OsmPath
}
@Override
public double getTotalTime()
{
public double getTotalTime() {
return totalTime;
}
@Override
public double getTotalEnergy()
{
public double getTotalEnergy() {
return totalEnergy;
}
}

View File

@ -8,14 +8,12 @@ package btools.router;
import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmTransferNode;
final class KinematicPrePath extends OsmPrePath
{
final class KinematicPrePath extends OsmPrePath {
public double angle;
public int priorityclassifier;
public int classifiermask;
protected void initPrePath(OsmPath origin, RoutingContext rc )
{
protected void initPrePath(OsmPath origin, RoutingContext rc) {
byte[] description = link.descriptionBitmap;
if (description == null) throw new IllegalArgumentException("null description for: " + link);
@ -38,13 +36,10 @@ final class KinematicPrePath extends OsmPrePath
int lon2;
int lat2;
if ( transferNode == null )
{
if (transferNode == null) {
lon2 = targetNode.ilon;
lat2 = targetNode.ilat;
}
else
{
} else {
lon2 = transferNode.ilon;
lat2 = transferNode.ilat;
}

View File

@ -6,9 +6,7 @@
package btools.router;
final class MessageData implements Cloneable
{
final class MessageData implements Cloneable {
int linkdist = 0;
int linkelevationcost = 0;
int linkturncost = 0;
@ -37,10 +35,8 @@ final class MessageData implements Cloneable
int vnode1 = 999;
int extraTime = 0;
String toMessage()
{
if ( wayKeyValues == null )
{
String toMessage() {
if (wayKeyValues == null) {
return null;
}
@ -60,8 +56,7 @@ final class MessageData implements Cloneable
+ "\t" + ((int) energy);
}
void add( MessageData d )
{
void add(MessageData d) {
linkdist += d.linkdist;
linkelevationcost += d.linkelevationcost;
linkturncost += d.linkturncost;
@ -69,51 +64,40 @@ final class MessageData implements Cloneable
linkinitcost += d.linkinitcost;
}
MessageData copy()
{
try
{
MessageData copy() {
try {
return (MessageData) clone();
}
catch( CloneNotSupportedException e )
{
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString()
{
public String toString() {
return "dist=" + linkdist + " prio=" + priorityclassifier + " turn=" + turnangle;
}
public int getPrio()
{
public int getPrio() {
return priorityclassifier;
}
public boolean isBadOneway()
{
public boolean isBadOneway() {
return (classifiermask & 1) != 0;
}
public boolean isGoodOneway()
{
public boolean isGoodOneway() {
return (classifiermask & 2) != 0;
}
public boolean isRoundabout()
{
public boolean isRoundabout() {
return (classifiermask & 4) != 0;
}
public boolean isLinktType()
{
public boolean isLinktType() {
return (classifiermask & 8) != 0;
}
public boolean isGoodForCars()
{
public boolean isGoodForCars() {
return (classifiermask & 16) != 0;
}

View File

@ -8,25 +8,21 @@ package btools.router;
import btools.mapaccess.OsmNode;
import btools.util.CheapRuler;
public class OsmNodeNamed extends OsmNode
{
public class OsmNodeNamed extends OsmNode {
public String name;
public double radius; // radius of nogopoint (in meters)
public double nogoWeight; // weight for nogopoint
public boolean isNogo = false;
public OsmNodeNamed()
{
public OsmNodeNamed() {
}
public OsmNodeNamed( OsmNode n)
{
public OsmNodeNamed(OsmNode n) {
super(n.ilon, n.ilat);
}
@Override
public String toString()
{
public String toString() {
if (Double.isNaN(nogoWeight)) {
return ilon + "," + ilat + "," + name;
} else {
@ -82,8 +78,7 @@ public class OsmNodeNamed extends OsmNode
return 2 * halfDistanceWithin;
}
public static OsmNodeNamed decodeNogo( String s )
{
public static OsmNodeNamed decodeNogo(String s) {
OsmNodeNamed n = new OsmNodeNamed();
int idx1 = s.indexOf(',');
n.ilon = Integer.parseInt(s.substring(0, idx1));

View File

@ -5,7 +5,6 @@
http://geomalgorithms.com/a03-_inclusion.html
cn_PnPoly, wn_PnPoly, inSegment, intersect2D_2Segments
**********************************************************************************************/
package btools.router;
@ -14,15 +13,12 @@ import java.util.List;
import btools.util.CheapRuler;
public class OsmNogoPolygon extends OsmNodeNamed
{
public final static class Point
{
public class OsmNogoPolygon extends OsmNodeNamed {
public final static class Point {
public final int y;
public final int x;
Point(final int lon, final int lat)
{
Point(final int lon, final int lat) {
x = lon;
y = lat;
}
@ -32,15 +28,13 @@ public class OsmNogoPolygon extends OsmNodeNamed
public final boolean isClosed;
public OsmNogoPolygon(boolean closed)
{
public OsmNogoPolygon(boolean closed) {
this.isClosed = closed;
this.isNogo = true;
this.name = "";
}
public final void addVertex(int lon, int lat)
{
public final void addVertex(int lon, int lat) {
points.add(new Point(lon, lat));
}
@ -54,36 +48,30 @@ public class OsmNogoPolygon extends OsmNodeNamed
* with each iteration.
* This is done to ensure the calculated radius being used
* in RoutingContext.calcDistance will actually contain the whole polygon.
*
* <p>
* For reasonable distributed vertices the implemented algorithm runs in O(n*ln(n)).
* As this is only run once on initialization of OsmNogoPolygon this methods
* overall usage of cpu is neglegible in comparism to the cpu-usage of the
* actual routing algoritm.
*/
public void calcBoundingCircle()
{
public void calcBoundingCircle() {
int cxmin, cxmax, cymin, cymax;
cxmin = cymin = Integer.MAX_VALUE;
cxmax = cymax = Integer.MIN_VALUE;
// first calculate a starting center point as center of boundingbox
for (int i = 0; i < points.size(); i++)
{
for (int i = 0; i < points.size(); i++) {
final Point p = points.get(i);
if (p.x < cxmin)
{
if (p.x < cxmin) {
cxmin = p.x;
}
if (p.x > cxmax)
{
if (p.x > cxmax) {
cxmax = p.x;
}
if (p.y < cymin)
{
if (p.y < cymin) {
cymin = p.y;
}
if (p.y > cymax)
{
if (p.y > cymax) {
cymax = p.y;
}
}
@ -100,11 +88,9 @@ public class OsmNogoPolygon extends OsmNodeNamed
double dmax = 0; // length of vector from center to point
int i_max = -1;
do
{
do {
// now identify the point outside of the circle that has the greatest distance
for (int i = 0; i < points.size(); i++)
{
for (int i = 0; i < points.size(); i++) {
final Point p = points.get(i);
// to get precisely the same results as in RoutingContext.calcDistance()
@ -113,19 +99,16 @@ public class OsmNogoPolygon extends OsmNodeNamed
final double y1 = (cy - p.y) * dlat2m;
final double dist = Math.sqrt(x1 * x1 + y1 * y1);
if (dist <= rad)
{
if (dist <= rad) {
continue;
}
if (dist > dmax)
{
if (dist > dmax) {
// new maximum distance found
dmax = dist;
i_max = i;
}
}
if (i_max < 0)
{
if (i_max < 0) {
break; // leave loop when no point outside the circle is found any more.
}
final double dd = 0.5 * (1 - rad / dmax);
@ -165,18 +148,15 @@ public class OsmNogoPolygon extends OsmNodeNamed
* @param lat1 latitude of start point
* @return true if segment or any of it's points are 'inside' of polygon
*/
public boolean intersects(int lon0, int lat0, int lon1, int lat1)
{
public boolean intersects(int lon0, int lat0, int lon1, int lat1) {
final Point p0 = new Point(lon0, lat0);
final Point p1 = new Point(lon1, lat1);
int i_last = points.size() - 1;
Point p2 = points.get(isClosed ? i_last : 0);
for (int i = isClosed ? 0 : 1 ; i <= i_last; i++)
{
for (int i = isClosed ? 0 : 1; i <= i_last; i++) {
Point p3 = points.get(i);
// does it intersect with at least one of the polygon's segments?
if (intersect2D_2Segments(p0,p1,p2,p3) > 0)
{
if (intersect2D_2Segments(p0, p1, p2, p3) > 0) {
return true;
}
p2 = p3;
@ -184,15 +164,12 @@ public class OsmNogoPolygon extends OsmNodeNamed
return false;
}
public boolean isOnPolyline( long px, long py )
{
public boolean isOnPolyline(long px, long py) {
int i_last = points.size() - 1;
Point p1 = points.get(0);
for (int i = 1 ; i <= i_last; i++)
{
for (int i = 1; i <= i_last; i++) {
final Point p2 = points.get(i);
if (OsmNogoPolygon.isOnLine(px,py,p1.x,p1.y,p2.x,p2.y))
{
if (OsmNogoPolygon.isOnLine(px, py, p1.x, p1.y, p2.x, p2.y)) {
return true;
}
p1 = p2;
@ -200,8 +177,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
return false;
}
public static boolean isOnLine( long px, long py, long p0x, long p0y, long p1x, long p1y )
{
public static boolean isOnLine(long px, long py, long p0x, long p0y, long p1x, long p1y) {
final double v10x = px - p0x;
final double v10y = py - p0y;
final double v12x = p1x - p0x;
@ -229,8 +205,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
return (v12x / v10x) >= 1; // P1->P2 at least as long as P1->P0?
}
final double kx = v12x / v10x;
if ( kx < 1 )
{
if (kx < 1) {
return false;
}
return kx == v12y / v10y;
@ -242,6 +217,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
this code, and cannot be held liable for any real or imagined damage
resulting from its use. Users of this code must verify correctness for
their application. */
/**
* winding number test for a point in a polygon
*
@ -249,8 +225,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
* @param py latitude of the point to check
* @return a boolean whether the point is within the polygon or not.
*/
public boolean isWithin(final long px, final long py)
{
public boolean isWithin(final long px, final long py) {
int wn = 0; // the winding number counter
// loop through all edges of the polygon
@ -266,8 +241,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
final long p1x = p1.x;
final long p1y = p1.y;
if (OsmNogoPolygon.isOnLine(px, py, p0x, p0y, p1x, p1y))
{
if (OsmNogoPolygon.isOnLine(px, py, p0x, p0y, p1x, p1y)) {
return true;
}
@ -275,18 +249,15 @@ public class OsmNogoPolygon extends OsmNodeNamed
{
if (p1y > py) // an upward crossing
{ // p left of edge
if (((p1x - p0x) * (py - p0y) - (px - p0x) * (p1y - p0y)) > 0)
{
if (((p1x - p0x) * (py - p0y) - (px - p0x) * (p1y - p0y)) > 0) {
++wn; // have a valid up intersect
}
}
}
else // start y > p.y (no test needed)
} else // start y > p.y (no test needed)
{
if (p1y <= py) // a downward crossing
{ // p right of edge
if (((p1x - p0x) * (py - p0y) - (px - p0x) * (p1y - p0y)) < 0)
{
if (((p1x - p0x) * (py - p0y) - (px - p0x) * (p1y - p0y)) < 0) {
--wn; // have a valid down intersect
}
}
@ -304,7 +275,6 @@ public class OsmNogoPolygon extends OsmNodeNamed
* @param lat1 Integer latitude of the first point of the segment.
* @param lon2 Integer longitude of the last point of the segment.
* @param lat2 Integer latitude of the last point of the segment.
*
* @return The length, in meters, of the portion of the segment which is
* included in the polygon.
*/
@ -316,8 +286,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
final Point p2 = new Point(lon2, lat2);
Point previousIntersectionOnSegment = null;
if (isWithin(lon1, lat1))
{
if (isWithin(lon1, lat1)) {
// Start point of the segment is within the polygon, this is the first
// "intersection".
previousIntersectionOnSegment = p1;
@ -325,14 +294,12 @@ public class OsmNogoPolygon extends OsmNodeNamed
// Loop over edges of the polygon to find intersections
int i_last = points.size() - 1;
for (int i = (isClosed ? 0 : 1), j = (isClosed ? i_last : 0); i <= i_last; j = i++)
{
for (int i = (isClosed ? 0 : 1), j = (isClosed ? i_last : 0); i <= i_last; j = i++) {
Point edgePoint1 = points.get(j);
Point edgePoint2 = points.get(i);
int intersectsEdge = intersect2D_2Segments(p1, p2, edgePoint1, edgePoint2);
if (isClosed && intersectsEdge == 1)
{
if (isClosed && intersectsEdge == 1) {
// Intersects with a (closed) polygon edge on a single point
// Distance is zero when crossing a polyline.
// Let's find this intersection point
@ -363,8 +330,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
);
}
previousIntersectionOnSegment = intersection;
}
else if (intersectsEdge == 2) {
} else if (intersectsEdge == 2) {
// Segment and edge overlaps
// FIXME: Could probably be done in a smarter way
distance += Math.min(
@ -401,6 +367,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
this code, and cannot be held liable for any real or imagined damage
resulting from its use. Users of this code must verify correctness for
their application. */
/**
* inSegment(): determine if a point is inside a segment
*
@ -410,35 +377,29 @@ public class OsmNogoPolygon extends OsmNodeNamed
* @return 1 = P is inside S
* 0 = P is not inside S
*/
private static boolean inSegment( final Point p, final Point seg_p0, final Point seg_p1)
{
private static boolean inSegment(final Point p, final Point seg_p0, final Point seg_p1) {
final int sp0x = seg_p0.x;
final int sp1x = seg_p1.x;
if (sp0x != sp1x) // S is not vertical
{
final int px = p.x;
if (sp0x <= px && px <= sp1x)
{
if (sp0x <= px && px <= sp1x) {
return true;
}
if (sp0x >= px && px >= sp1x)
{
if (sp0x >= px && px >= sp1x) {
return true;
}
}
else // S is vertical, so test y coordinate
} else // S is vertical, so test y coordinate
{
final int sp0y = seg_p0.y;
final int sp1y = seg_p1.y;
final int py = p.y;
if (sp0y <= py && py <= sp1y)
{
if (sp0y <= py && py <= sp1y) {
return true;
}
if (sp0y >= py && py >= sp1y)
{
if (sp0y >= py && py >= sp1y) {
return true;
}
}
@ -451,8 +412,10 @@ public class OsmNogoPolygon extends OsmNodeNamed
this code, and cannot be held liable for any real or imagined damage
resulting from its use. Users of this code must verify correctness for
their application. */
/**
* intersect2D_2Segments(): find the 2D intersection of 2 finite segments
*
* @param s1p0 start point of segment 1
* @param s1p1 end point of segment 1
* @param s2p0 start point of segment 2
@ -461,8 +424,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
* 1=intersect in unique point I0
* 2=overlap in segment from I0 to I1
*/
private static int intersect2D_2Segments( final Point s1p0, final Point s1p1, final Point s2p0, final Point s2p1 )
{
private static int intersect2D_2Segments(final Point s1p0, final Point s1p1, final Point s2p0, final Point s2p1) {
final long ux = s1p1.x - s1p0.x; // vector u = S1P1-S1P0 (segment 1)
final long uy = s1p1.y - s1p0.y;
final long vx = s2p1.x - s2p0.x; // vector v = S2P1-S2P0 (segment 2)
@ -475,8 +437,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
// test if they are parallel (includes either being a point)
if (d == 0) // S1 and S2 are parallel
{
if ((ux * wy - uy * wx) != 0 || (vx * wy - vy * wx) != 0)
{
if ((ux * wy - uy * wx) != 0 || (vx * wy - vy * wx) != 0) {
return 0; // they are NOT collinear
}
@ -500,13 +461,10 @@ public class OsmNogoPolygon extends OsmNodeNamed
double t0, t1; // endpoints of S1 in eqn for S2
final int w2x = s1p1.x - s2p0.x; // vector w2 = S1P1-S2P0 (from start of segment 2 to end of segment 1)
final int w2y = s1p1.y - s2p0.y;
if (vx != 0)
{
if (vx != 0) {
t0 = wx / vx;
t1 = w2x / vx;
}
else
{
} else {
t0 = wy / vy;
t1 = w2y / vy;
}
@ -516,8 +474,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
t0 = t1;
t1 = t;
}
if (t0 > 1 || t1 < 0)
{
if (t0 > 1 || t1 < 0) {
return 0; // NO overlap
}
t0 = t0 < 0 ? 0 : t0; // clip to min 0

View File

@ -14,8 +14,7 @@ import btools.mapaccess.OsmTransferNode;
import btools.mapaccess.TurnRestriction;
import btools.util.CheapRuler;
abstract class OsmPath implements OsmLinkHolder
{
abstract class OsmPath implements OsmLinkHolder {
/**
* The cost of that path (a modified distance)
*/
@ -57,54 +56,42 @@ abstract class OsmPath implements OsmLinkHolder
private static final int HAD_DESTINATION_START_BIT = 8;
protected int bitfield = PATH_START_BIT;
private boolean getBit( int mask )
{
private boolean getBit(int mask) {
return (bitfield & mask) != 0;
}
private void setBit( int mask, boolean bit )
{
if ( getBit( mask ) != bit )
{
private void setBit(int mask, boolean bit) {
if (getBit(mask) != bit) {
bitfield ^= mask;
}
}
public boolean didEnterDestinationArea()
{
public boolean didEnterDestinationArea() {
return !getBit(HAD_DESTINATION_START_BIT) && getBit(IS_ON_DESTINATION_BIT);
}
public MessageData message;
public void unregisterUpTree( RoutingContext rc )
{
try
{
public void unregisterUpTree(RoutingContext rc) {
try {
OsmPathElement pe = originElement;
while( pe instanceof OsmPathElementWithTraffic && ((OsmPathElementWithTraffic)pe).unregister(rc) )
{
while (pe instanceof OsmPathElementWithTraffic && ((OsmPathElementWithTraffic) pe).unregister(rc)) {
pe = pe.origin;
}
}
catch( IOException ioe )
{
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
public void registerUpTree()
{
if ( originElement instanceof OsmPathElementWithTraffic )
{
public void registerUpTree() {
if (originElement instanceof OsmPathElementWithTraffic) {
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) originElement;
ot.register();
ot.addTraffic(traffic);
}
}
public void init( OsmLink link )
{
public void init(OsmLink link) {
this.link = link;
targetNode = link.getTarget(null);
selev = targetNode.getSElev();
@ -113,10 +100,8 @@ abstract class OsmPath implements OsmLinkHolder
originLat = -1;
}
public void init( OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc )
{
if ( origin.myElement == null )
{
public void init(OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc) {
if (origin.myElement == null) {
origin.myElement = OsmPathElement.create(origin, rc.countTraffic);
}
this.originElement = origin.myElement;
@ -136,11 +121,9 @@ abstract class OsmPath implements OsmLinkHolder
protected abstract void resetState();
protected void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc )
{
protected void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc) {
byte[] description = link.descriptionBitmap;
if ( description == null )
{
if (description == null) {
return; // could be a beeline path
}
@ -176,18 +159,15 @@ abstract class OsmPath implements OsmLinkHolder
float newClassifier = rc.expctxWay.getInitialClassifier();
float newInitialCost = rc.expctxWay.getInitialcost();
float classifierDiff = newClassifier - lastClassifier;
if ( newClassifier != 0. && lastClassifier != 0. && ( classifierDiff > 0.0005 || classifierDiff < -0.0005 ) )
{
if (newClassifier != 0. && lastClassifier != 0. && (classifierDiff > 0.0005 || classifierDiff < -0.0005)) {
float initialcost = rc.inverseDirection ? lastInitialCost : newInitialCost;
if ( initialcost >= 1000000. )
{
if (initialcost >= 1000000.) {
cost = -1;
return;
}
int iicost = (int) initialcost;
if ( message != null )
{
if (message != null) {
message.linkinitcost += iicost;
}
cost += iicost;
@ -199,22 +179,15 @@ abstract class OsmPath implements OsmLinkHolder
int classifiermask = (int) rc.expctxWay.getClassifierMask();
boolean newDestination = (classifiermask & 64) != 0;
boolean oldDestination = getBit(IS_ON_DESTINATION_BIT);
if ( getBit( PATH_START_BIT ) )
{
if (getBit(PATH_START_BIT)) {
setBit(PATH_START_BIT, false);
setBit(CAN_LEAVE_DESTINATION_BIT, newDestination);
setBit(HAD_DESTINATION_START_BIT, newDestination);
}
else
{
if ( oldDestination && !newDestination )
{
if ( getBit( CAN_LEAVE_DESTINATION_BIT ) )
{
} else {
if (oldDestination && !newDestination) {
if (getBit(CAN_LEAVE_DESTINATION_BIT)) {
setBit(CAN_LEAVE_DESTINATION_BIT, false);
}
else
{
} else {
cost = -1;
return;
}
@ -226,8 +199,7 @@ abstract class OsmPath implements OsmLinkHolder
OsmTransferNode transferNode = link.geometry == null ? null
: rc.geometryDecoder.decodeGeometry(link.geometry, sourceNode, targetNode, isReverse);
for(int nsection=0; ;nsection++)
{
for (int nsection = 0; ; nsection++) {
originLon = lon1;
originLat = lat1;
@ -236,14 +208,11 @@ abstract class OsmPath implements OsmLinkHolder
int lat2;
short ele2;
if ( transferNode == null )
{
if (transferNode == null) {
lon2 = targetNode.ilon;
lat2 = targetNode.ilat;
ele2 = targetNode.selev;
}
else
{
} else {
lon2 = transferNode.ilon;
lat2 = transferNode.ilat;
ele2 = transferNode.selev;
@ -252,20 +221,17 @@ abstract class OsmPath implements OsmLinkHolder
boolean isStartpoint = lon0 == -1 && lat0 == -1;
// check turn restrictions (n detail mode (=final pass) no TR to not mess up voice hints)
if ( nsection == 0 && rc.considerTurnRestrictions && !detailMode&& !isStartpoint )
{
if (nsection == 0 && rc.considerTurnRestrictions && !detailMode && !isStartpoint) {
if (rc.inverseDirection
? TurnRestriction.isTurnForbidden(sourceNode.firstRestriction, lon2, lat2, lon0, lat0, rc.bikeMode || rc.footMode, rc.carMode)
: TurnRestriction.isTurnForbidden( sourceNode.firstRestriction, lon0, lat0, lon2, lat2, rc.bikeMode || rc.footMode, rc.carMode ) )
{
: TurnRestriction.isTurnForbidden(sourceNode.firstRestriction, lon0, lat0, lon2, lat2, rc.bikeMode || rc.footMode, rc.carMode)) {
cost = -1;
return;
}
}
// if recording, new MessageData for each section (needed for turn-instructions)
if ( message != null && message.wayKeyValues != null )
{
if (message != null && message.wayKeyValues != null) {
originElement.message = message;
message = new MessageData();
}
@ -273,15 +239,11 @@ abstract class OsmPath implements OsmLinkHolder
int dist = rc.calcDistance(lon1, lat1, lon2, lat2);
boolean stopAtEndpoint = false;
if ( rc.shortestmatch )
{
if ( rc.isEndpoint )
{
if (rc.shortestmatch) {
if (rc.isEndpoint) {
stopAtEndpoint = true;
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
}
else
{
} else {
// we just start here, reset everything
cost = 0;
resetState();
@ -289,24 +251,18 @@ abstract class OsmPath implements OsmLinkHolder
lat0 = -1;
isStartpoint = true;
if ( recordTransferNodes )
{
if ( rc.wayfraction > 0. )
{
if (recordTransferNodes) {
if (rc.wayfraction > 0.) {
ele1 = interpolateEle(ele1, ele2, 1. - rc.wayfraction);
originElement = OsmPathElement.create(rc.ilonshortest, rc.ilatshortest, ele1, null, rc.countTraffic);
}
else
{
} else {
originElement = null; // prevent duplicate point
}
}
if ( rc.checkPendingEndpoint() )
{
if (rc.checkPendingEndpoint()) {
dist = rc.calcDistance(rc.ilonshortest, rc.ilatshortest, lon2, lat2);
if ( rc.shortestmatch )
{
if (rc.shortestmatch) {
stopAtEndpoint = true;
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
}
@ -314,24 +270,19 @@ abstract class OsmPath implements OsmLinkHolder
}
}
if ( message != null )
{
if (message != null) {
message.linkdist += dist;
}
linkdisttotal += dist;
// apply a start-direction if appropriate (by faking the origin position)
if ( isStartpoint )
{
if ( rc.startDirectionValid )
{
if (isStartpoint) {
if (rc.startDirectionValid) {
double dir = rc.startDirection.intValue() * CheapRuler.DEG_TO_RAD;
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lon0 + lat1) >> 1);
lon0 = lon1 - (int) (1000. * Math.sin(dir) / lonlat2m[0]);
lat0 = lat1 - (int) (1000. * Math.cos(dir) / lonlat2m[1]);
}
else
{
} else {
lon0 = lon1 - (lon2 - lon1);
lat0 = lat1 - (lat2 - lat1);
}
@ -342,37 +293,30 @@ abstract class OsmPath implements OsmLinkHolder
// *** elevation stuff
double delta_h = 0.;
if (ele2 == Short.MIN_VALUE) ele2 = ele1;
if ( ele1 != Short.MIN_VALUE )
{
if (ele1 != Short.MIN_VALUE) {
delta_h = (ele2 - ele1) / 4.;
if ( rc.inverseDirection )
{
if (rc.inverseDirection) {
delta_h = -delta_h;
}
}
double elevation = ele2 == Short.MIN_VALUE ? 100. : ele2 / 4.;
double sectionCost = processWaySection(rc, dist, delta_h, elevation, angle, cosangle, isStartpoint, nsection, lastpriorityclassifier);
if ( ( sectionCost < 0. || costfactor > 9998. && !detailMode ) || sectionCost + cost >= 2000000000. )
{
if ((sectionCost < 0. || costfactor > 9998. && !detailMode) || sectionCost + cost >= 2000000000.) {
cost = -1;
return;
}
if ( isTrafficBackbone )
{
if (isTrafficBackbone) {
sectionCost = 0.;
}
cost += (int) sectionCost;
// calculate traffic
if ( rc.countTraffic )
{
if (rc.countTraffic) {
int minDist = (int) rc.trafficSourceMinDist;
int cost2 = cost < minDist ? minDist : cost;
traffic += dist * rc.expctxWay.getTrafficSourceDensity() * Math.pow(cost2 / 10000.f, rc.trafficSourceExponent);
@ -381,8 +325,7 @@ abstract class OsmPath implements OsmLinkHolder
// compute kinematic
computeKinematic(rc, dist, delta_h, detailMode);
if ( message != null )
{
if (message != null) {
message.turnangle = (float) angle;
message.time = (float) getTotalTime();
message.energy = (float) getTotalEnergy();
@ -394,33 +337,25 @@ abstract class OsmPath implements OsmLinkHolder
message.wayKeyValues = rc.expctxWay.getKeyValueDescription(isReverse, description);
}
if ( stopAtEndpoint )
{
if ( recordTransferNodes )
{
if (stopAtEndpoint) {
if (recordTransferNodes) {
originElement = OsmPathElement.create(rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic);
originElement.cost = cost;
if ( message != null )
{
if (message != null) {
originElement.message = message;
}
}
if ( rc.nogoCost < 0)
{
if (rc.nogoCost < 0) {
cost = -1;
}
else
{
} else {
cost += rc.nogoCost;
}
return;
}
if ( transferNode == null )
{
if (transferNode == null) {
// *** penalty for being part of the reference track
if ( refTrack != null && refTrack.containsNode( targetNode ) && refTrack.containsNode( sourceNode ) )
{
if (refTrack != null && refTrack.containsNode(targetNode) && refTrack.containsNode(sourceNode)) {
int reftrackcost = linkdisttotal;
cost += reftrackcost;
}
@ -429,8 +364,7 @@ abstract class OsmPath implements OsmLinkHolder
}
transferNode = transferNode.next;
if ( recordTransferNodes )
{
if (recordTransferNodes) {
originElement = OsmPathElement.create(lon2, lat2, ele2, originElement, rc.countTraffic);
originElement.cost = cost;
originElement.addTraffic(traffic);
@ -444,20 +378,16 @@ abstract class OsmPath implements OsmLinkHolder
}
// check for nogo-matches (after the *actual* start of segment)
if ( rc.nogoCost < 0)
{
if (rc.nogoCost < 0) {
cost = -1;
return;
}
else
{
} else {
cost += rc.nogoCost;
}
// add target-node costs
double targetCost = processTargetNode(rc);
if ( targetCost < 0. || targetCost + cost >= 2000000000. )
{
if (targetCost < 0. || targetCost + cost >= 2000000000.) {
cost = -1;
return;
}
@ -465,10 +395,8 @@ abstract class OsmPath implements OsmLinkHolder
}
public short interpolateEle( short e1, short e2, double fraction )
{
if ( e1 == Short.MIN_VALUE || e2 == Short.MIN_VALUE )
{
public short interpolateEle(short e1, short e2, double fraction) {
if (e1 == Short.MIN_VALUE || e2 == Short.MIN_VALUE) {
return Short.MIN_VALUE;
}
return (short) (e1 * (1. - fraction) + e2 * fraction);
@ -478,47 +406,39 @@ abstract class OsmPath implements OsmLinkHolder
protected abstract double processTargetNode(RoutingContext rc);
protected void computeKinematic( RoutingContext rc, double dist, double delta_h, boolean detailMode )
{
protected void computeKinematic(RoutingContext rc, double dist, double delta_h, boolean detailMode) {
}
public abstract int elevationCorrection(RoutingContext rc);
public abstract boolean definitlyWorseThan(OsmPath p, RoutingContext rc);
public OsmNode getSourceNode()
{
public OsmNode getSourceNode() {
return sourceNode;
}
public OsmNode getTargetNode()
{
public OsmNode getTargetNode() {
return targetNode;
}
public OsmLink getLink()
{
public OsmLink getLink() {
return link;
}
public void setNextForLink( OsmLinkHolder holder )
{
public void setNextForLink(OsmLinkHolder holder) {
nextForLink = holder;
}
public OsmLinkHolder getNextForLink()
{
public OsmLinkHolder getNextForLink() {
return nextForLink;
}
public double getTotalTime()
{
public double getTotalTime() {
return 0.;
}
public double getTotalEnergy()
{
public double getTotalEnergy() {
return 0.;
}
}

View File

@ -14,8 +14,7 @@ import btools.util.CheapRuler;
* @author ab
*/
public class OsmPathElement implements OsmPos
{
public class OsmPathElement implements OsmPos {
private int ilat; // latitude
private int ilon; // longitude
private short selev; // longitude
@ -25,67 +24,54 @@ public class OsmPathElement implements OsmPos
public int cost;
// 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 float getTime()
{
public final float getTime() {
return message == null ? 0.f : message.time;
}
public final void setTime( float t )
{
if ( message != null )
{
public final void setTime(float t) {
if (message != null) {
message.time = t;
}
}
public final float getEnergy()
{
public final float getEnergy() {
return message == null ? 0.f : message.energy;
}
public final void setEnergy( float e )
{
if ( message != null )
{
public final void setEnergy(float e) {
if (message != null) {
message.energy = e;
}
}
public final long getIdFromPos()
{
public final long getIdFromPos() {
return ((long) ilon) << 32 | ilat;
}
public final int calcDistance( OsmPos p )
{
public final int calcDistance(OsmPos p) {
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
}
public OsmPathElement origin;
// construct a path element from a path
public static final OsmPathElement create( OsmPath path, boolean countTraffic )
{
public static final OsmPathElement create(OsmPath path, boolean countTraffic) {
OsmNode n = path.getTargetNode();
OsmPathElement pe = create(n.getILon(), n.getILat(), path.selev, path.originElement, countTraffic);
pe.cost = path.cost;
@ -93,8 +79,7 @@ public class OsmPathElement implements OsmPos
return pe;
}
public static final OsmPathElement create( int ilon, int ilat, short selev, OsmPathElement origin, boolean countTraffic )
{
public static final OsmPathElement create(int ilon, int ilat, short selev, OsmPathElement origin, boolean countTraffic) {
OsmPathElement pe = countTraffic ? new OsmPathElementWithTraffic() : new OsmPathElement();
pe.ilon = ilon;
pe.ilat = ilat;
@ -103,29 +88,24 @@ public class OsmPathElement implements OsmPos
return pe;
}
protected OsmPathElement()
{
protected OsmPathElement() {
}
public void addTraffic( float traffic )
{
public void addTraffic(float traffic) {
}
public String toString()
{
public String toString() {
return ilon + "_" + ilat;
}
public void writeToStream( DataOutput dos ) throws IOException
{
public void writeToStream(DataOutput dos) throws IOException {
dos.writeInt(ilat);
dos.writeInt(ilon);
dos.writeShort(selev);
dos.writeInt(cost);
}
public static OsmPathElement readFromStream( DataInput dis ) throws IOException
{
public static OsmPathElement readFromStream(DataInput dis) throws IOException {
OsmPathElement pe = new OsmPathElement();
pe.ilat = dis.readInt();
pe.ilon = dis.readInt();

View File

@ -9,18 +9,14 @@ import java.io.IOException;
* @author ab
*/
public final class OsmPathElementWithTraffic extends OsmPathElement
{
public final class OsmPathElementWithTraffic extends OsmPathElement {
private int registerCount;
private float farTraffic;
private float nearTraffic;
public void register()
{
if ( registerCount++ == 0 )
{
if ( origin instanceof OsmPathElementWithTraffic )
{
public void register() {
if (registerCount++ == 0) {
if (origin instanceof OsmPathElementWithTraffic) {
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
ot.register();
ot.farTraffic += farTraffic;
@ -32,8 +28,7 @@ public final class OsmPathElementWithTraffic extends OsmPathElement
}
@Override
public void addTraffic( float traffic )
{
public void addTraffic(float traffic) {
this.farTraffic += traffic;
this.nearTraffic += traffic;
}
@ -42,12 +37,9 @@ public final class OsmPathElementWithTraffic extends OsmPathElement
public static double maxtraffic = 0.;
public boolean unregister( RoutingContext rc ) throws IOException
{
if ( --registerCount == 0 )
{
if ( origin instanceof OsmPathElementWithTraffic )
{
public boolean unregister(RoutingContext rc) throws IOException {
if (--registerCount == 0) {
if (origin instanceof OsmPathElementWithTraffic) {
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
int costdelta = cost - ot.cost;
@ -58,11 +50,9 @@ if ( costdelta > 0 && farTraffic > maxtraffic ) maxtraffic = farTraffic;
int t2 = cost == ot.cost ? -1 : (int) (rc.farTrafficWeight * farTraffic + rc.nearTrafficWeight * nearTraffic);
if ( t2 > 4000 || t2 == -1 )
{
if (t2 > 4000 || t2 == -1) {
// System.out.println( "unregistered: " + this + " origin=" + ot + " farTraffic =" + farTraffic + " nearTraffic =" + nearTraffic + " cost=" + cost );
if ( rc.trafficOutputStream != null )
{
if (rc.trafficOutputStream != null) {
rc.trafficOutputStream.writeLong(getIdFromPos());
rc.trafficOutputStream.writeLong(ot.getIdFromPos());
rc.trafficOutputStream.writeInt(t2);

View File

@ -11,8 +11,7 @@ import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
abstract class OsmPathModel
{
abstract class OsmPathModel {
public abstract OsmPrePath createPrePath();
public abstract OsmPath createPath();

View File

@ -9,16 +9,14 @@ import btools.mapaccess.OsmLink;
import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmTransferNode;
public abstract class OsmPrePath
{
public abstract class OsmPrePath {
protected OsmNode sourceNode;
protected OsmNode targetNode;
protected OsmLink link;
public OsmPrePath next;
public void init( OsmPath origin, OsmLink link, RoutingContext rc )
{
public void init(OsmPath origin, OsmLink link, RoutingContext rc) {
this.link = link;
this.sourceNode = origin.getTargetNode();
this.targetNode = link.getTarget(sourceNode);

View File

@ -31,8 +31,7 @@ import btools.util.CompactLongMap;
import btools.util.FrozenLongMap;
import btools.util.StringUtils;
public final class OsmTrack
{
public final class OsmTrack {
final public static String version = "1.6.3";
final public static String versionDate = "21122021";
@ -49,8 +48,7 @@ public final class OsmTrack
public List<OsmNodeNamed> pois = new ArrayList<OsmNodeNamed>();
private static class OsmPathElementHolder
{
private static class OsmPathElementHolder {
public OsmPathElement node;
public OsmPathElementHolder nextHolder;
}
@ -71,108 +69,83 @@ public final class OsmTrack
protected List<MatchedWaypoint> matchedWaypoints;
public boolean exportWaypoints = false;
public void addNode( OsmPathElement node )
{
public void addNode(OsmPathElement node) {
nodes.add(0, node);
}
public void registerDetourForId( long id, OsmPathElement detour )
{
if ( detourMap == null )
{
public void registerDetourForId(long id, OsmPathElement detour) {
if (detourMap == null) {
detourMap = new CompactLongMap<OsmPathElementHolder>();
}
OsmPathElementHolder nh = new OsmPathElementHolder();
nh.node = detour;
OsmPathElementHolder h = detourMap.get(id);
if ( h != null )
{
while ( h.nextHolder != null )
{
if (h != null) {
while (h.nextHolder != null) {
h = h.nextHolder;
}
h.nextHolder = nh;
}
else
{
} else {
detourMap.fastPut(id, nh);
}
}
public void copyDetours( OsmTrack source )
{
public void copyDetours(OsmTrack source) {
detourMap = source.detourMap == null ? null : new FrozenLongMap<OsmPathElementHolder>(source.detourMap);
}
public void buildMap()
{
public void buildMap() {
nodesMap = new CompactLongMap<OsmPathElementHolder>();
for ( OsmPathElement node : nodes )
{
for (OsmPathElement node : nodes) {
long id = node.getIdFromPos();
OsmPathElementHolder nh = new OsmPathElementHolder();
nh.node = node;
OsmPathElementHolder h = nodesMap.get(id);
if ( h != null )
{
while (h.nextHolder != null)
{
if (h != null) {
while (h.nextHolder != null) {
h = h.nextHolder;
}
h.nextHolder = nh;
}
else
{
} else {
nodesMap.fastPut(id, nh);
}
}
nodesMap = new FrozenLongMap<OsmPathElementHolder>(nodesMap);
}
private ArrayList<String> aggregateMessages()
{
private ArrayList<String> aggregateMessages() {
ArrayList<String> res = new ArrayList<String>();
MessageData current = null;
for ( OsmPathElement n : nodes )
{
if ( n.message != null && n.message.wayKeyValues != null )
{
for (OsmPathElement n : nodes) {
if (n.message != null && n.message.wayKeyValues != null) {
MessageData md = n.message.copy();
if ( current != null )
{
if ( current.nodeKeyValues != null || !current.wayKeyValues.equals( md.wayKeyValues ) )
{
if (current != null) {
if (current.nodeKeyValues != null || !current.wayKeyValues.equals(md.wayKeyValues)) {
res.add(current.toMessage());
}
else
{
} else {
md.add(current);
}
}
current = md;
}
}
if ( current != null )
{
if (current != null) {
res.add(current.toMessage());
}
return res;
}
private ArrayList<String> aggregateSpeedProfile()
{
private ArrayList<String> aggregateSpeedProfile() {
ArrayList<String> res = new ArrayList<String>();
int vmax = -1;
int vmaxe = -1;
int vmin = -1;
int extraTime = 0;
for( int i = nodes.size()-1; i > 0; i-- )
{
for (int i = nodes.size() - 1; i > 0; i--) {
OsmPathElement n = nodes.get(i);
MessageData m = n.message;
int vnode = getVNode(i);
if ( m != null && ( vmax != m.vmax || vmin != m.vmin || vmaxe != m.vmaxExplicit || vnode < m.vmax || extraTime != m.extraTime ) )
{
if (m != null && (vmax != m.vmax || vmin != m.vmin || vmaxe != m.vmaxExplicit || vnode < m.vmax || extraTime != m.extraTime)) {
vmax = m.vmax;
vmin = m.vmin;
vmaxe = m.vmaxExplicit;
@ -187,17 +160,14 @@ public final class OsmTrack
/**
* writes the track in binary-format to a file
*
* @param filename
* the filename to write to
* @param filename the filename to write to
*/
public void writeBinary( String filename ) throws Exception
{
public void writeBinary(String filename) throws Exception {
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
endPoint.writeToStream(dos);
dos.writeInt(nodes.size());
for ( OsmPathElement node : nodes )
{
for (OsmPathElement node : nodes) {
node.writeToStream(dos);
}
dos.writeLong(nogoChecksums[0]);
@ -208,33 +178,26 @@ public final class OsmTrack
dos.close();
}
public static OsmTrack readBinary( String filename, OsmNodeNamed newEp, long[] nogoChecksums, long profileChecksum, StringBuilder debugInfo )
{
public static OsmTrack readBinary(String filename, OsmNodeNamed newEp, long[] nogoChecksums, long profileChecksum, StringBuilder debugInfo) {
OsmTrack t = null;
if ( filename != null )
{
if (filename != null) {
File f = new File(filename);
if ( f.exists() )
{
try
{
if (f.exists()) {
try {
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
MatchedWaypoint ep = MatchedWaypoint.readFromStream(dis);
int dlon = ep.waypoint.ilon - newEp.ilon;
int dlat = ep.waypoint.ilat - newEp.ilat;
boolean targetMatch = dlon < 20 && dlon > -20 && dlat < 20 && dlat > -20;
if ( debugInfo != null )
{
if (debugInfo != null) {
debugInfo.append("target-delta = " + dlon + "/" + dlat + " targetMatch=" + targetMatch);
}
if ( targetMatch )
{
if (targetMatch) {
t = new OsmTrack();
t.endPoint = ep;
int n = dis.readInt();
OsmPathElement last_pe = null;
for ( int i = 0; i < n; i++ )
{
for (int i = 0; i < n; i++) {
OsmPathElement pe = OsmPathElement.readFromStream(dis);
pe.origin = last_pe;
last_pe = pe;
@ -246,39 +209,30 @@ public final class OsmTrack
// check cheecksums, too
long[] al = new long[3];
long pchecksum = 0;
try
{
try {
al[0] = dis.readLong();
al[1] = dis.readLong();
al[2] = dis.readLong();
}
catch (EOFException eof) { /* kind of expected */ }
try
{
} catch (EOFException eof) { /* kind of expected */ }
try {
t.isDirty = dis.readBoolean();
}
catch (EOFException eof) { /* kind of expected */ }
try
{
} catch (EOFException eof) { /* kind of expected */ }
try {
pchecksum = dis.readLong();
}
catch (EOFException eof) { /* kind of expected */ }
} catch (EOFException eof) { /* kind of expected */ }
boolean nogoCheckOk = Math.abs(al[0] - nogoChecksums[0]) <= 20
&& Math.abs(al[1] - nogoChecksums[1]) <= 20
&& Math.abs(al[2] - nogoChecksums[2]) <= 20;
boolean profileCheckOk = pchecksum == profileChecksum;
if ( debugInfo != null )
{
if (debugInfo != null) {
debugInfo.append(" nogoCheckOk=" + nogoCheckOk + " profileCheckOk=" + profileCheckOk);
debugInfo.append(" al=" + formatLongs(al) + " nogoChecksums=" + formatLongs(nogoChecksums));
}
if (!(nogoCheckOk && profileCheckOk)) return null;
}
dis.close();
}
catch (Exception e)
{
} catch (Exception e) {
throw new RuntimeException("Exception reading rawTrack: " + e);
}
}
@ -286,12 +240,10 @@ public final class OsmTrack
return t;
}
private static String formatLongs( long[] al )
{
private static String formatLongs(long[] al) {
StringBuilder sb = new StringBuilder();
sb.append('{');
for( long l : al )
{
for (long l : al) {
sb.append(l);
sb.append(' ');
}
@ -300,26 +252,21 @@ public final class OsmTrack
}
public void addNodes( OsmTrack t )
{
public void addNodes(OsmTrack t) {
for (OsmPathElement n : t.nodes)
addNode(n);
buildMap();
}
public boolean containsNode( OsmPos node )
{
public boolean containsNode(OsmPos node) {
return nodesMap.contains(node.getIdFromPos());
}
public OsmPathElement getLink( long n1, long n2 )
{
public OsmPathElement getLink(long n1, long n2) {
OsmPathElementHolder h = nodesMap.get(n2);
while (h != null)
{
while (h != null) {
OsmPathElement e1 = h.node.origin;
if ( e1 != null && e1.getIdFromPos() == n1 )
{
if (e1 != null && e1.getIdFromPos() == n1) {
return h.node;
}
h = h.nextHolder;
@ -327,15 +274,12 @@ public final class OsmTrack
return null;
}
public void appendTrack( OsmTrack t )
{
public void appendTrack(OsmTrack t) {
int ourSize = nodes.size();
float t0 = ourSize > 0 ? nodes.get(ourSize - 1).getTime() : 0;
float e0 = ourSize > 0 ? nodes.get(ourSize - 1).getEnergy() : 0;
for ( int i = 0; i < t.nodes.size(); i++ )
{
if ( i > 0 || ourSize == 0 )
{
for (int i = 0; i < t.nodes.size(); i++) {
if (i > 0 || ourSize == 0) {
OsmPathElement e = t.nodes.get(i);
e.setTime(e.getTime() + t0);
e.setEnergy(e.getEnergy() + e0);
@ -343,19 +287,15 @@ public final class OsmTrack
}
}
if ( t.voiceHints != null )
{
if (t.voiceHints != null) {
if (ourSize > 0) {
for (VoiceHint hint : t.voiceHints.list) {
hint.indexInTrack = hint.indexInTrack + ourSize - 1;
}
}
if ( voiceHints == null )
{
if (voiceHints == null) {
voiceHints = t.voiceHints;
}
else
{
} else {
voiceHints.list.addAll(t.voiceHints.list);
}
}
@ -379,39 +319,31 @@ public final class OsmTrack
/**
* writes the track in gpx-format to a file
*
* @param filename
* the filename to write to
* @param filename the filename to write to
*/
public void writeGpx( String filename ) throws Exception
{
public void writeGpx(String filename) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
formatAsGpx(bw);
bw.close();
}
public String formatAsGpx()
{
try
{
public String formatAsGpx() {
try {
StringWriter sw = new StringWriter(8192);
BufferedWriter bw = new BufferedWriter(sw);
formatAsGpx(bw);
bw.close();
return sw.toString();
}
catch( Exception e )
{
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String formatAsGpx( BufferedWriter sb ) throws IOException
{
public String formatAsGpx(BufferedWriter sb) throws IOException {
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
for ( int i = messageList.size() - 1; i >= 0; i-- )
{
for (int i = messageList.size() - 1; i >= 0; i--) {
String message = messageList.get(i);
if (i < messageList.size() - 1)
message = "(alt-index " + i + ": " + message + " )";
@ -424,8 +356,7 @@ public final class OsmTrack
sb.append("<!-- $transport-mode$").append(voiceHints.getTransportMode()).append("$ -->\n");
sb.append("<!-- cmd idx lon lat d2next geometry -->\n");
sb.append("<!-- $turn-instruction-start$\n");
for( VoiceHint hint: voiceHints.list )
{
for (VoiceHint hint : voiceHints.list) {
sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(), hint.indexInTrack,
formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry()));
}
@ -440,12 +371,9 @@ public final class OsmTrack
}
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
if ( turnInstructionMode == 3)
{
if (turnInstructionMode == 3) {
sb.append(" creator=\"OsmAndRouter\" version=\"1.1\">\n");
}
else
{
} else {
sb.append(" creator=\"BRouter-" + version + "\" version=\"1.1\">\n");
}
@ -469,8 +397,7 @@ public final class OsmTrack
}
sb.append(" <offset>0</offset>\n </extensions>\n </rtept>\n");
for( int i = 0 ; i < voiceHints.list.size(); i++ )
{
for (int i = 0; i < voiceHints.list.size(); i++) {
VoiceHint hint = voiceHints.list.get(i);
sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
.append(formatILon(hint.ilon)).append("\">\n")
@ -500,8 +427,7 @@ public final class OsmTrack
{
float lastRteTime = getVoiceHintTime(0);
for( int i=0; i<voiceHints.list.size(); i++ )
{
for (int i = 0; i < voiceHints.list.size(); i++) {
VoiceHint hint = voiceHints.list.get(i);
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">")
@ -523,8 +449,7 @@ public final class OsmTrack
}
if (turnInstructionMode == 5) // gpsies style
{
for( VoiceHint hint: voiceHints.list )
{
for (VoiceHint hint : voiceHints.list) {
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">")
.append("<name>").append(hint.getMessageString()).append("</name>")
@ -536,8 +461,7 @@ public final class OsmTrack
if (turnInstructionMode == 6) // orux style
{
for( VoiceHint hint: voiceHints.list )
{
for (VoiceHint hint : voiceHints.list) {
sb.append(" <wpt lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
.append(formatILon(hint.ilon)).append("\">")
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
@ -551,8 +475,7 @@ public final class OsmTrack
}
}
for( int i=0; i<=pois.size() - 1; i++ )
{
for (int i = 0; i <= pois.size() - 1; i++) {
OsmNodeNamed poi = pois.get(i);
sb.append(" <wpt lon=\"").append(formatILon(poi.ilon)).append("\" lat=\"")
.append(formatILat(poi.ilat)).append("\">\n")
@ -560,23 +483,17 @@ public final class OsmTrack
.append(" </wpt>\n");
}
if ( exportWaypoints )
{
for( int i=0; i<=matchedWaypoints.size() - 1; i++ )
{
if (exportWaypoints) {
for (int i = 0; i <= matchedWaypoints.size() - 1; i++) {
MatchedWaypoint wt = matchedWaypoints.get(i);
sb.append(" <wpt lon=\"").append(formatILon(wt.waypoint.ilon)).append("\" lat=\"")
.append(formatILat(wt.waypoint.ilat)).append("\">\n")
.append(" <name>").append(StringUtils.escapeXml10(wt.name)).append("</name>\n");
if(i == 0)
{
if (i == 0) {
sb.append(" <type>from</type>\n");
}
else if (i == matchedWaypoints.size() - 1)
{
} else if (i == matchedWaypoints.size() - 1) {
sb.append(" <type>to</type>\n");
}
else {
} else {
sb.append(" <type>via</type>\n");
}
sb.append(" </wpt>\n");
@ -589,8 +506,7 @@ public final class OsmTrack
sb.append(" <type>").append(voiceHints.getTransportMode()).append("</type>\n");
}
if ( turnInstructionMode == 2 )
{
if (turnInstructionMode == 2) {
sb.append(" <extensions>\n");
sb.append(" <locus:rteComputeType>").append("" + voiceHints.getLocusRouteType()).append("</locus:rteComputeType>\n");
sb.append(" <locus:rteSimpleRoundabouts>1</locus:rteSimpleRoundabouts>\n");
@ -599,16 +515,13 @@ public final class OsmTrack
sb.append(" <trkseg>\n");
for ( int idx = 0; idx < nodes.size(); idx++ )
{
for (int idx = 0; idx < nodes.size(); idx++) {
OsmPathElement n = nodes.get(idx);
String sele = n.getSElev() == Short.MIN_VALUE ? "" : "<ele>" + n.getElev() + "</ele>";
if (turnInstructionMode == 1) // trkpt/sym style
{
for ( VoiceHint hint : voiceHints.list )
{
if ( hint.indexInTrack == idx )
{
for (VoiceHint hint : voiceHints.list) {
if (hint.indexInTrack == idx) {
sele += "<sym>" + hint.getCommandString() + "</sym>";
}
}
@ -624,16 +537,14 @@ public final class OsmTrack
return sb.toString();
}
public void writeKml( String filename ) throws Exception
{
public void writeKml(String filename) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
bw.write(formatAsKml());
bw.close();
}
public String formatAsKml()
{
public String formatAsKml() {
StringBuilder sb = new StringBuilder(8192);
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
@ -657,8 +568,7 @@ public final class OsmTrack
sb.append(" <tessellate>1</tessellate>\n");
sb.append(" <coordinates>");
for ( OsmPathElement n : nodes )
{
for (OsmPathElement n : nodes) {
sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
}
@ -666,8 +576,7 @@ public final class OsmTrack
sb.append(" </LineString>\n");
sb.append(" </Placemark>\n");
sb.append(" </Folder>\n");
if ( exportWaypoints || !pois.isEmpty() )
{
if (exportWaypoints || !pois.isEmpty()) {
if (!pois.isEmpty()) {
sb.append(" <Folder>\n");
sb.append(" <name>poi</name>\n");
@ -678,8 +587,7 @@ public final class OsmTrack
sb.append(" </Folder>\n");
}
if (exportWaypoints)
{
if (exportWaypoints) {
int size = matchedWaypoints.size();
createFolder(sb, "start", matchedWaypoints.subList(0, 1));
if (matchedWaypoints.size() > 2) {
@ -715,8 +623,7 @@ public final class OsmTrack
public List<String> iternity;
public void writeJson( String filename ) throws Exception
{
public void writeJson(String filename) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
bw.write(formatAsGeoJson());
@ -724,8 +631,7 @@ public final class OsmTrack
}
public String formatAsGeoJson()
{
public String formatAsGeoJson() {
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
StringBuilder sb = new StringBuilder(8192);
@ -744,11 +650,9 @@ public final class OsmTrack
sb.append(" \"total-time\": \"").append(getTotalSeconds()).append("\",\n");
sb.append(" \"total-energy\": \"").append(energy).append("\",\n");
sb.append(" \"cost\": \"").append(cost).append("\",\n");
if ( voiceHints != null && !voiceHints.list.isEmpty() )
{
if (voiceHints != null && !voiceHints.list.isEmpty()) {
sb.append(" \"voicehints\": [\n");
for( VoiceHint hint: voiceHints.list )
{
for (VoiceHint hint : voiceHints.list) {
sb.append(" [");
sb.append(hint.indexInTrack);
sb.append(',').append(hint.getCommand());
@ -770,11 +674,9 @@ public final class OsmTrack
if (showSpeedProfile) // set in profile
{
ArrayList<String> sp = aggregateSpeedProfile();
if ( sp.size() > 0 )
{
if (sp.size() > 0) {
sb.append(" \"speedprofile\": [\n");
for( int i=sp.size()-1; i>=0; i-- )
{
for (int i = sp.size() - 1; i >= 0; i--) {
sb.append(" [").append(sp.get(i)).append(i > 0 ? "],\n" : "]\n");
}
sb.append(" ],\n");
@ -784,8 +686,7 @@ public final class OsmTrack
{
sb.append(" \"messages\": [\n");
sb.append(" [\"").append(MESSAGES_HEADER.replaceAll("\t", "\", \"")).append("\"],\n");
for ( String m : aggregateMessages() )
{
for (String m : aggregateMessages()) {
sb.append(" [\"").append(m.replaceAll("\t", "\", \"")).append("\"],\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
@ -807,11 +708,9 @@ public final class OsmTrack
sb.append(" },\n");
if ( iternity != null )
{
if (iternity != null) {
sb.append(" \"iternity\": [\n");
for ( String s : iternity )
{
for (String s : iternity) {
sb.append(" \"").append(s).append("\",\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
@ -822,18 +721,15 @@ public final class OsmTrack
sb.append(" \"coordinates\": [\n");
OsmPathElement nn = null;
for ( OsmPathElement n : nodes )
{
for (OsmPathElement n : nodes) {
String sele = n.getSElev() == Short.MIN_VALUE ? "" : ", " + n.getElev();
if (showspeed) // hack: show speed instead of elevation
{
double speed = 0;
if ( nn != null )
{
if (nn != null) {
int dist = n.calcDistance(nn);
float dt = n.getTime() - nn.getTime();
if ( dt != 0.f )
{
if (dt != 0.f) {
speed = ((3.6f * dist) / dt + 0.5);
}
}
@ -847,11 +743,9 @@ public final class OsmTrack
sb.append(" ]\n");
sb.append(" }\n");
if ( exportWaypoints || !pois.isEmpty())
{
if (exportWaypoints || !pois.isEmpty()) {
sb.append(" },\n");
for( int i=0; i<=pois.size() - 1; i++ )
{
for (int i = 0; i <= pois.size() - 1; i++) {
OsmNodeNamed poi = pois.get(i);
addFeature(sb, "poi", poi.name, poi.ilat, poi.ilon);
if (i < matchedWaypoints.size() - 1) {
@ -878,8 +772,7 @@ public final class OsmTrack
sb.append(" \n");
}
}
}
else {
} else {
sb.append(" }\n");
}
sb.append(" ]\n");
@ -905,8 +798,7 @@ public final class OsmTrack
sb.append(" }");
}
private int getVNode( int i )
{
private int getVNode(int i) {
MessageData m1 = i + 1 < nodes.size() ? nodes.get(i + 1).message : null;
MessageData m0 = i < nodes.size() ? nodes.get(i).message : null;
int vnode0 = m1 == null ? 999 : m1.vnode0;
@ -914,19 +806,16 @@ public final class OsmTrack
return vnode0 < vnode1 ? vnode0 : vnode1;
}
private int getTotalSeconds()
{
private int getTotalSeconds() {
float s = nodes.size() < 2 ? 0 : nodes.get(nodes.size() - 1).getTime() - nodes.get(0).getTime();
return (int) (s + 0.5);
}
public String getFormattedTime()
{
public String getFormattedTime() {
return format1(getTotalSeconds() / 60.) + "m";
}
public String getFormattedTime2()
{
public String getFormattedTime2() {
int seconds = (int) (getTotalSeconds() + 0.5);
int hours = seconds / 3600;
int minutes = (seconds - hours * 3600) / 60;
@ -941,30 +830,25 @@ public final class OsmTrack
return time;
}
public String getFormattedEnergy()
{
public String getFormattedEnergy() {
return format1(energy / 3600000.) + "kwh";
}
private static String formatILon( int ilon )
{
private static String formatILon(int ilon) {
return formatPos(ilon - 180000000);
}
private static String formatILat( int ilat )
{
private static String formatILat(int ilat) {
return formatPos(ilat - 90000000);
}
private static String formatPos( int p )
{
private static String formatPos(int p) {
boolean negative = p < 0;
if (negative)
p = -p;
char[] ac = new char[12];
int i = 11;
while (p != 0 || i > 3)
{
while (p != 0 || i > 3) {
ac[i--] = (char) ('0' + (p % 10));
p /= 10;
if (i == 5)
@ -975,59 +859,48 @@ public final class OsmTrack
return new String(ac, i + 1, 11 - i);
}
private String format1( double n )
{
private String format1(double n) {
String s = "" + (long) (n * 10 + 0.5);
int len = s.length();
return s.substring(0, len - 1) + "." + s.charAt(len - 1);
}
public void dumpMessages( String filename, RoutingContext rc ) throws Exception
{
public void dumpMessages(String filename, RoutingContext rc) throws Exception {
BufferedWriter bw = filename == null ? null : new BufferedWriter(new FileWriter(filename));
writeMessages(bw, rc);
}
public void writeMessages( BufferedWriter bw, RoutingContext rc ) throws Exception
{
public void writeMessages(BufferedWriter bw, RoutingContext rc) throws Exception {
dumpLine(bw, MESSAGES_HEADER);
for ( String m : aggregateMessages() )
{
for (String m : aggregateMessages()) {
dumpLine(bw, m);
}
if (bw != null)
bw.close();
}
private void dumpLine( BufferedWriter bw, String s ) throws Exception
{
if ( bw == null )
{
private void dumpLine(BufferedWriter bw, String s) throws Exception {
if (bw == null) {
System.out.println(s);
}
else
{
} else {
bw.write(s);
bw.write("\n");
}
}
public void readGpx( String filename ) throws Exception
{
public void readGpx(String filename) throws Exception {
File f = new File(filename);
if (!f.exists())
return;
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
for ( ;; )
{
for (; ; ) {
String line = br.readLine();
if (line == null)
break;
int idx0 = line.indexOf("<trkpt lon=\"");
if ( idx0 >= 0 )
{
if (idx0 >= 0) {
idx0 += 12;
int idx1 = line.indexOf('"', idx0);
int ilon = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 180.) * 1000000. + 0.5);
@ -1043,12 +916,10 @@ public final class OsmTrack
br.close();
}
public boolean equalsTrack( OsmTrack t )
{
public boolean equalsTrack(OsmTrack t) {
if (nodes.size() != t.nodes.size())
return false;
for ( int i = 0; i < nodes.size(); i++ )
{
for (int i = 0; i < nodes.size(); i++) {
OsmPathElement e1 = nodes.get(i);
OsmPathElement e2 = t.nodes.get(i);
if (e1.getILon() != e2.getILon() || e1.getILat() != e2.getILat())
@ -1057,28 +928,23 @@ public final class OsmTrack
return true;
}
public void prepareSpeedProfile( RoutingContext rc )
{
public void prepareSpeedProfile(RoutingContext rc) {
// sendSpeedProfile = rc.keyValues != null && rc.keyValues.containsKey( "vmax" );
}
public void processVoiceHints( RoutingContext rc )
{
public void processVoiceHints(RoutingContext rc) {
voiceHints = new VoiceHintList();
voiceHints.setTransportMode(rc.carMode, rc.bikeMode);
voiceHints.turnInstructionMode = rc.turnInstructionMode;
if ( detourMap == null )
{
if (detourMap == null) {
return;
}
int nodeNr = nodes.size() - 1;
OsmPathElement node = nodes.get(nodeNr);
List<VoiceHint> inputs = new ArrayList<VoiceHint>();
while (node != null)
{
if ( node.origin != null )
{
while (node != null) {
if (node.origin != null) {
VoiceHint input = new VoiceHint();
inputs.add(input);
input.ilat = node.origin.getILat();
@ -1089,11 +955,9 @@ public final class OsmTrack
input.oldWay = node.origin.message == null ? node.message : node.origin.message;
OsmPathElementHolder detours = detourMap.get(node.origin.getIdFromPos());
if ( detours != null )
{
if (detours != null) {
OsmPathElementHolder h = detours;
while (h != null)
{
while (h != null) {
OsmPathElement e = h.node;
input.addBadWay(startSection(e, node.origin));
h = h.nextHolder;
@ -1105,43 +969,34 @@ public final class OsmTrack
VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts);
List<VoiceHint> results = vproc.process(inputs);
for( VoiceHint hint : results )
{
for (VoiceHint hint : results) {
voiceHints.list.add(hint);
}
}
private float getVoiceHintTime( int i )
{
if ( voiceHints.list.isEmpty() )
{
private float getVoiceHintTime(int i) {
if (voiceHints.list.isEmpty()) {
return 0f;
}
if ( i < voiceHints.list.size() )
{
if (i < voiceHints.list.size()) {
return voiceHints.list.get(i).getTime();
}
if ( nodes.isEmpty() )
{
if (nodes.isEmpty()) {
return 0f;
}
return nodes.get(nodes.size() - 1).getTime();
}
private MessageData startSection( OsmPathElement element, OsmPathElement root )
{
private MessageData startSection(OsmPathElement element, OsmPathElement root) {
OsmPathElement e = element;
int cnt = 0;
while( e != null && e.origin != null )
{
if ( e.origin.getILat() == root.getILat() && e.origin.getILon() == root.getILon() )
{
while (e != null && e.origin != null) {
if (e.origin.getILat() == root.getILat() && e.origin.getILon() == root.getILon()) {
return e.message;
}
e = e.origin;
if ( cnt++ == 1000000 )
{
if (cnt++ == 1000000) {
throw new IllegalArgumentException("ups: " + root + "->" + element);
}
}

View File

@ -11,8 +11,7 @@ import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
import btools.expressions.BExpressionMetaData;
public final class ProfileCache
{
public final class ProfileCache {
private static File lastLookupFile;
private static long lastLookupTimestamp;
@ -27,23 +26,18 @@ public final class ProfileCache
private static ProfileCache[] apc = new ProfileCache[1];
private static boolean debug = Boolean.getBoolean("debugProfileCache");
public static synchronized void setSize( int size )
{
public static synchronized void setSize(int size) {
apc = new ProfileCache[size];
}
public static synchronized boolean parseProfile( RoutingContext rc )
{
public static synchronized boolean parseProfile(RoutingContext rc) {
String profileBaseDir = System.getProperty("profileBaseDir");
File profileDir;
File profileFile;
if ( profileBaseDir == null )
{
if (profileBaseDir == null) {
profileDir = new File(rc.localFunction).getParentFile();
profileFile = new File(rc.localFunction);
}
else
{
} else {
profileDir = new File(profileBaseDir);
profileFile = new File(profileDir, rc.localFunction + ".brf");
}
@ -52,10 +46,8 @@ public final class ProfileCache
File lookupFile = new File(profileDir, "lookups.dat");
// invalidate cache at lookup-table update
if ( !(lookupFile.equals( lastLookupFile ) && lookupFile.lastModified() == lastLookupTimestamp ) )
{
if ( lastLookupFile != null )
{
if (!(lookupFile.equals(lastLookupFile) && lookupFile.lastModified() == lastLookupTimestamp)) {
if (lastLookupFile != null) {
System.out.println("******** invalidating profile-cache after lookup-file update ******** ");
}
apc = new ProfileCache[apc.length];
@ -67,16 +59,12 @@ public final class ProfileCache
int unusedSlot = -1;
// check for re-use
for( int i=0; i<apc.length; i++)
{
for (int i = 0; i < apc.length; i++) {
ProfileCache pc = apc[i];
if ( pc != null )
{
if ( (!pc.profilesBusy) && profileFile.equals( pc.lastProfileFile ) )
{
if ( rc.profileTimestamp == pc.lastProfileTimestamp )
{
if (pc != null) {
if ((!pc.profilesBusy) && profileFile.equals(pc.lastProfileFile)) {
if (rc.profileTimestamp == pc.lastProfileTimestamp) {
rc.expctxWay = pc.expctxWay;
rc.expctxNode = pc.expctxNode;
rc.readGlobalConfig();
@ -87,13 +75,10 @@ public final class ProfileCache
unusedSlot = -1;
break;
}
if ( lru == null || lru.lastUseTime > pc.lastUseTime )
{
if (lru == null || lru.lastUseTime > pc.lastUseTime) {
lru = pc;
}
}
else if ( unusedSlot < 0 )
{
} else if (unusedSlot < 0) {
unusedSlot = i;
}
}
@ -111,24 +96,22 @@ public final class ProfileCache
rc.readGlobalConfig();
if ( rc.processUnusedTags )
{
if (rc.processUnusedTags) {
rc.expctxWay.setAllTagsUsed();
}
if ( lru == null || unusedSlot >= 0 )
{
if (lru == null || unusedSlot >= 0) {
lru = new ProfileCache();
if ( unusedSlot >= 0 )
{
if (unusedSlot >= 0) {
apc[unusedSlot] = lru;
if ( debug ) System.out.println( "******* adding new profile at idx=" + unusedSlot + " for " + profileFile );
if (debug)
System.out.println("******* adding new profile at idx=" + unusedSlot + " for " + profileFile);
}
}
if ( lru.lastProfileFile != null )
{
if ( debug ) System.out.println( "******* replacing profile of age " + ((System.currentTimeMillis()-lru.lastUseTime)/1000L) + " sec " + lru.lastProfileFile + "->" + profileFile );
if (lru.lastProfileFile != null) {
if (debug)
System.out.println("******* replacing profile of age " + ((System.currentTimeMillis() - lru.lastUseTime) / 1000L) + " sec " + lru.lastProfileFile + "->" + profileFile);
}
lru.lastProfileTimestamp = rc.profileTimestamp;
@ -140,17 +123,13 @@ public final class ProfileCache
return false;
}
public static synchronized void releaseProfile( RoutingContext rc )
{
for( int i=0; i<apc.length; i++)
{
public static synchronized void releaseProfile(RoutingContext rc) {
for (int i = 0; i < apc.length; i++) {
ProfileCache pc = apc[i];
if ( pc != null )
{
if (pc != null) {
// only the thread that holds the cached instance can release it
if ( rc.expctxWay == pc.expctxWay && rc.expctxNode == pc.expctxNode )
{
if (rc.expctxWay == pc.expctxWay && rc.expctxNode == pc.expctxNode) {
pc.profilesBusy = false;
break;
}

View File

@ -20,16 +20,15 @@ import btools.mapaccess.OsmNode;
import btools.util.CheapAngleMeter;
import btools.util.CheapRuler;
public final class RoutingContext
{
public void setAlternativeIdx(int idx )
{
public final class RoutingContext {
public void setAlternativeIdx(int idx) {
alternativeIdx = idx;
}
public int getAlternativeIdx(int min, int max)
{
public int getAlternativeIdx(int min, int max) {
return alternativeIdx < min ? min : (alternativeIdx > max ? max : alternativeIdx);
}
public int alternativeIdx = 0;
public String localFunction;
public long profileTimestamp;
@ -38,8 +37,7 @@ public final class RoutingContext
public String rawTrackPath;
public String getProfileName()
{
public String getProfileName() {
String name = localFunction == null ? "unknown" : localFunction;
if (name.endsWith(".brf")) name = name.substring(0, localFunction.length() - 4);
int idx = name.lastIndexOf(File.separatorChar);
@ -81,47 +79,35 @@ public final class RoutingContext
public double waypointCatchingRange;
private void setModel( String className )
{
if ( className == null )
{
private void setModel(String className) {
if (className == null) {
pm = new StdModel();
}
else
{
try
{
} else {
try {
Class clazz = Class.forName(className);
pm = (OsmPathModel) clazz.newInstance();
}
catch( Exception e )
{
} catch (Exception e) {
throw new RuntimeException("Cannot create path-model: " + e);
}
}
initModel();
}
public void initModel()
{
public void initModel() {
pm.init(expctxWay, expctxNode, keyValues);
}
public long getKeyValueChecksum()
{
public long getKeyValueChecksum() {
long s = 0L;
if ( keyValues != null )
{
for( Map.Entry<String,String> e : keyValues.entrySet() )
{
if (keyValues != null) {
for (Map.Entry<String, String> e : keyValues.entrySet()) {
s += e.getKey().hashCode() + e.getValue().hashCode();
}
}
return s;
}
public void readGlobalConfig()
{
public void readGlobalConfig() {
BExpressionContext expctxGlobal = expctxWay; // just one of them...
if (keyValues != null) {
@ -256,22 +242,19 @@ public final class RoutingContext
public double defaultC_r;
public double bikerPower;
public static void prepareNogoPoints( List<OsmNodeNamed> nogos )
{
for( OsmNodeNamed nogo : nogos )
{
if (nogo instanceof OsmNogoPolygon)
{
public static void prepareNogoPoints(List<OsmNodeNamed> nogos) {
for (OsmNodeNamed nogo : nogos) {
if (nogo instanceof OsmNogoPolygon) {
continue;
}
String s = nogo.name;
int idx = s.indexOf(' ');
if (idx > 0) s = s.substring(0, idx);
int ir = 20; // default radius
if ( s.length() > 4 )
{
try { ir = Integer.parseInt( s.substring( 4 ) ); }
catch( Exception e ) { /* ignore */ }
if (s.length() > 4) {
try {
ir = Integer.parseInt(s.substring(4));
} catch (Exception e) { /* ignore */ }
}
// Radius of the nogo point in meters
nogo.radius = ir;
@ -281,8 +264,7 @@ public final class RoutingContext
/**
* restore the full nogolist previously saved by cleanNogoList
*/
public void restoreNogoList()
{
public void restoreNogoList() {
nogopoints = nogopoints_all;
}
@ -292,22 +274,18 @@ public final class RoutingContext
*
* @return true if all wayoints are all in the same (full-weigth) nogo area (triggering bee-line-mode)
*/
public void cleanNogoList( List<OsmNode> waypoints )
{
public void cleanNogoList(List<OsmNode> waypoints) {
nogopoints_all = nogopoints;
if (nogopoints == null) return;
List<OsmNodeNamed> nogos = new ArrayList<OsmNodeNamed>();
for( OsmNodeNamed nogo : nogopoints )
{
for (OsmNodeNamed nogo : nogopoints) {
boolean goodGuy = true;
for( OsmNode wp : waypoints )
{
for (OsmNode wp : waypoints) {
if (wp.calcDistance(nogo) < nogo.radius
&& (!(nogo instanceof OsmNogoPolygon)
|| (((OsmNogoPolygon) nogo).isClosed
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
: ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat))))
{
: ((OsmNogoPolygon) nogo).isOnPolyline(wp.ilon, wp.ilat)))) {
goodGuy = false;
}
}
@ -316,22 +294,18 @@ public final class RoutingContext
nogopoints = nogos.isEmpty() ? null : nogos;
}
public boolean allInOneNogo( List<OsmNode> waypoints )
{
public boolean allInOneNogo(List<OsmNode> waypoints) {
if (nogopoints == null) return false;
boolean allInTotal = false;
for( OsmNodeNamed nogo : nogopoints )
{
for (OsmNodeNamed nogo : nogopoints) {
boolean allIn = Double.isNaN(nogo.nogoWeight);
for( OsmNode wp : waypoints )
{
for (OsmNode wp : waypoints) {
int dist = wp.calcDistance(nogo);
if (dist < nogo.radius
&& (!(nogo instanceof OsmNogoPolygon)
|| (((OsmNogoPolygon) nogo).isClosed
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
: ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat))))
{
: ((OsmNogoPolygon) nogo).isOnPolyline(wp.ilon, wp.ilat)))) {
continue;
}
allIn = false;
@ -341,12 +315,10 @@ public final class RoutingContext
return allInTotal;
}
public long[] getNogoChecksums()
{
public long[] getNogoChecksums() {
long[] cs = new long[3];
int n = nogopoints == null ? 0 : nogopoints.size();
for( int i=0; i<n; i++ )
{
for (int i = 0; i < n; i++) {
OsmNodeNamed nogo = nogopoints.get(i);
cs[0] += nogo.ilon;
cs[1] += nogo.ilat;
@ -356,13 +328,11 @@ public final class RoutingContext
return cs;
}
public void setWaypoint( OsmNodeNamed wp, boolean endpoint )
{
public void setWaypoint(OsmNodeNamed wp, boolean endpoint) {
setWaypoint(wp, null, endpoint);
}
public void setWaypoint( OsmNodeNamed wp, OsmNodeNamed pendingEndpoint, boolean endpoint )
{
public void setWaypoint(OsmNodeNamed wp, OsmNodeNamed pendingEndpoint, boolean endpoint) {
keepnogopoints = nogopoints;
nogopoints = new ArrayList<OsmNodeNamed>();
nogopoints.add(wp);
@ -371,10 +341,8 @@ public final class RoutingContext
this.pendingEndpoint = pendingEndpoint;
}
public boolean checkPendingEndpoint()
{
if ( pendingEndpoint != null )
{
public boolean checkPendingEndpoint() {
if (pendingEndpoint != null) {
isEndpoint = true;
nogopoints.set(0, pendingEndpoint);
pendingEndpoint = null;
@ -383,15 +351,13 @@ public final class RoutingContext
return false;
}
public void unsetWaypoint()
{
public void unsetWaypoint() {
nogopoints = keepnogopoints;
pendingEndpoint = null;
isEndpoint = false;
}
public int calcDistance( int lon1, int lat1, int lon2, int lat2 )
{
public int calcDistance(int lon1, int lat1, int lon2, int lat2) {
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lat1 + lat2) >> 1);
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
@ -401,10 +367,8 @@ public final class RoutingContext
shortestmatch = false;
if ( nogopoints != null && !nogopoints.isEmpty() && d > 0. )
{
for( int ngidx = 0; ngidx < nogopoints.size(); ngidx++ )
{
if (nogopoints != null && !nogopoints.isEmpty() && d > 0.) {
for (int ngidx = 0; ngidx < nogopoints.size(); ngidx++) {
OsmNodeNamed nogo = nogopoints.get(ngidx);
double x1 = (lon1 - nogo.ilon) * dlon2m;
double y1 = (lat1 - nogo.ilat) * dlat2m;
@ -420,14 +384,15 @@ public final class RoutingContext
double s2 = x2 * dx + y2 * dy;
if ( s1 < 0. ) { s1 = -s1; s2 = -s2; }
if ( s2 > 0. )
{
if (s1 < 0.) {
s1 = -s1;
s2 = -s2;
}
if (s2 > 0.) {
radius = Math.sqrt(s1 < s2 ? r12 : r22);
if (radius > nogo.radius) continue;
}
if ( nogo.isNogo )
{
if (nogo.isNogo) {
if (!(nogo instanceof OsmNogoPolygon)) { // nogo is a circle
if (Double.isNaN(nogo.nogoWeight)) {
// default nogo behaviour (ignore completely)
@ -436,9 +401,7 @@ public final class RoutingContext
// nogo weight, compute distance within the circle
nogoCost = nogo.distanceWithinRadius(lon1, lat1, lon2, lat2, d) * nogo.nogoWeight;
}
}
else if (((OsmNogoPolygon)nogo).intersects(lon1, lat1, lon2, lat2))
{
} else if (((OsmNogoPolygon) nogo).intersects(lon1, lat1, lon2, lat2)) {
// nogo is a polyline/polygon, we have to check there is indeed
// an intersection in this case (radius check is not enough).
if (Double.isNaN(nogo.nogoWeight)) {
@ -454,28 +417,21 @@ public final class RoutingContext
}
}
}
}
else
{
} else {
shortestmatch = true;
nogo.radius = radius; // shortest distance to way
// calculate remaining distance
if ( s2 < 0. )
{
if (s2 < 0.) {
wayfraction = -s2 / (d * d);
double xm = x2 - wayfraction * dx;
double ym = y2 - wayfraction * dy;
ilonshortest = (int) (xm / dlon2m + nogo.ilon);
ilatshortest = (int) (ym / dlat2m + nogo.ilat);
}
else if ( s1 > s2 )
{
} else if (s1 > s2) {
wayfraction = 0.;
ilonshortest = lon2;
ilatshortest = lat2;
}
else
{
} else {
wayfraction = 1.;
ilonshortest = lon1;
ilatshortest = lat1;
@ -485,14 +441,11 @@ public final class RoutingContext
// *after* the shortest distance point. In case of a shortest-match
// we use the reduced way segment for nogo-matching, in order not
// to cut our escape-way if we placed a nogo just in front of where we are
if ( isEndpoint )
{
if (isEndpoint) {
wayfraction = 1. - wayfraction;
lon2 = ilonshortest;
lat2 = ilatshortest;
}
else
{
} else {
nogoCost = 0.;
lon1 = ilonshortest;
lat1 = ilatshortest;
@ -509,25 +462,21 @@ public final class RoutingContext
public OsmPathModel pm;
public OsmPrePath createPrePath( OsmPath origin, OsmLink link )
{
public OsmPrePath createPrePath(OsmPath origin, OsmLink link) {
OsmPrePath p = pm.createPrePath();
if ( p != null )
{
if (p != null) {
p.init(origin, link, this);
}
return p;
}
public OsmPath createPath( OsmLink link )
{
public OsmPath createPath(OsmLink link) {
OsmPath p = pm.createPath();
p.init(link);
return p;
}
public OsmPath createPath( OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode )
{
public OsmPath createPath(OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode) {
OsmPath p = pm.createPath();
p.init(origin, link, refTrack, detailMode, this);
return p;

File diff suppressed because it is too large Load Diff

View File

@ -9,39 +9,31 @@ import java.io.File;
import btools.mapaccess.StorageConfigHelper;
public final class RoutingHelper
{
public static File getAdditionalMaptoolDir( File segmentDir )
{
public final class RoutingHelper {
public static File getAdditionalMaptoolDir(File segmentDir) {
return StorageConfigHelper.getAdditionalMaptoolDir(segmentDir);
}
public static File getSecondarySegmentDir( File segmentDir )
{
public static File getSecondarySegmentDir(File segmentDir) {
return StorageConfigHelper.getSecondarySegmentDir(segmentDir);
}
public static boolean hasDirectoryAnyDatafiles( File segmentDir )
{
if ( hasAnyDatafiles( segmentDir ) )
{
public static boolean hasDirectoryAnyDatafiles(File segmentDir) {
if (hasAnyDatafiles(segmentDir)) {
return true;
}
// check secondary, too
File secondary = StorageConfigHelper.getSecondarySegmentDir(segmentDir);
if ( secondary != null )
{
if (secondary != null) {
return hasAnyDatafiles(secondary);
}
return false;
}
private static boolean hasAnyDatafiles( File dir )
{
private static boolean hasAnyDatafiles(File dir) {
String[] fileNames = dir.list();
for( String fileName : fileNames )
{
for (String fileName : fileNames) {
if (fileName.endsWith(".rd5")) return true;
}
return false;

View File

@ -1,5 +1,4 @@
package btools.router;
public class RoutingIslandException extends RuntimeException
{
public class RoutingIslandException extends RuntimeException {
}

View File

@ -8,8 +8,7 @@ package btools.router;
import btools.mapaccess.OsmNode;
public final class SearchBoundary
{
public final class SearchBoundary {
private int minlon0;
private int minlat0;
@ -28,8 +27,7 @@ public final class SearchBoundary
/**
* @param radius Search radius in meters.
*/
public SearchBoundary( OsmNode n, int radius, int direction )
{
public SearchBoundary(OsmNode n, int radius, int direction) {
this.radius = radius;
this.direction = direction;
@ -49,8 +47,7 @@ public final class SearchBoundary
maxlat = lat + 6000000;
}
public static String getFileName( OsmNode n )
{
public static String getFileName(OsmNode n) {
int lon = (n.ilon / 5000000) * 5000000;
int lat = (n.ilat / 5000000) * 5000000;
@ -62,28 +59,28 @@ public final class SearchBoundary
return slon + "_" + slat + ".trf";
}
public boolean isInBoundary( OsmNode n, int cost )
{
if ( radius > 0 )
{
public boolean isInBoundary(OsmNode n, int cost) {
if (radius > 0) {
return n.calcDistance(p) < radius;
}
if ( cost == 0 )
{
if (cost == 0) {
return n.ilon > minlon0 && n.ilon < maxlon0 && n.ilat > minlat0 && n.ilat < maxlat0;
}
return n.ilon > minlon && n.ilon < maxlon && n.ilat > minlat && n.ilat < maxlat;
}
public int getBoundaryDistance( OsmNode n )
{
switch( direction )
{
case 0: return n.calcDistance( new OsmNode( n.ilon, minlat ) );
case 1: return n.calcDistance( new OsmNode( minlon, n.ilat ) );
case 2: return n.calcDistance( new OsmNode( n.ilon, maxlat ) );
case 3: return n.calcDistance( new OsmNode( maxlon, n.ilat ) );
default: throw new IllegalArgumentException( "undefined direction: "+ direction );
public int getBoundaryDistance(OsmNode n) {
switch (direction) {
case 0:
return n.calcDistance(new OsmNode(n.ilon, minlat));
case 1:
return n.calcDistance(new OsmNode(minlon, n.ilat));
case 2:
return n.calcDistance(new OsmNode(n.ilon, maxlat));
case 3:
return n.calcDistance(new OsmNode(maxlon, n.ilat));
default:
throw new IllegalArgumentException("undefined direction: " + direction);
}
}

View File

@ -12,15 +12,12 @@ import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
final class StdModel extends OsmPathModel
{
public OsmPrePath createPrePath()
{
final class StdModel extends OsmPathModel {
public OsmPrePath createPrePath() {
return null;
}
public OsmPath createPath()
{
public OsmPath createPath() {
return new StdPath();
}
@ -29,8 +26,7 @@ final class StdModel extends OsmPathModel
@Override
public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String,String> keyValues )
{
public void init(BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String, String> keyValues) {
ctxWay = expctxWay;
ctxNode = expctxNode;

View File

@ -7,8 +7,7 @@ package btools.router;
import btools.util.FastMath;
final class StdPath extends OsmPath
{
final class StdPath extends OsmPath {
/**
* The elevation-hysteresis-buffer (0-10 m)
*/
@ -23,8 +22,7 @@ final class StdPath extends OsmPath
private static final double GRAVITY = 9.81; // in meters per second^(-2)
@Override
public void init( OsmPath orig )
{
public void init(OsmPath orig) {
StdPath origin = (StdPath) orig;
this.ehbd = origin.ehbd;
this.ehbu = origin.ehbu;
@ -34,8 +32,7 @@ final class StdPath extends OsmPath
}
@Override
protected void resetState()
{
protected void resetState() {
ehbd = 0;
ehbu = 0;
totalTime = 0.f;
@ -44,8 +41,7 @@ final class StdPath extends OsmPath
}
@Override
protected double processWaySection( RoutingContext rc, double distance, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier )
{
protected double processWaySection(RoutingContext rc, double distance, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier) {
// calculate the costfactor inputs
float turncostbase = rc.expctxWay.getTurncost();
float cfup = rc.expctxWay.getUphillCostfactor();
@ -58,8 +54,7 @@ final class StdPath extends OsmPath
// penalty for turning angle
int turncost = (int) ((1. - cosangle) * turncostbase + 0.2); // e.g. turncost=90 -> 90 degree = 90m penalty
if ( message != null )
{
if (message != null) {
message.linkturncost += turncost;
message.turnangle = (float) angle;
}
@ -75,76 +70,61 @@ final class StdPath extends OsmPath
ehbu += delta_h_micros - dist * rc.uphillcutoff;
float downweight = 0.f;
if ( ehbd > rc.elevationpenaltybuffer )
{
if (ehbd > rc.elevationpenaltybuffer) {
downweight = 1.f;
int excess = ehbd - rc.elevationpenaltybuffer;
int reduce = dist * rc.elevationbufferreduce;
if ( reduce > excess )
{
if (reduce > excess) {
downweight = ((float) excess) / reduce;
reduce = excess;
}
excess = ehbd - rc.elevationmaxbuffer;
if ( reduce < excess )
{
if (reduce < excess) {
reduce = excess;
}
ehbd -= reduce;
if ( rc.downhillcostdiv > 0 )
{
if (rc.downhillcostdiv > 0) {
int elevationCost = reduce / rc.downhillcostdiv;
sectionCost += elevationCost;
if ( message != null )
{
if (message != null) {
message.linkelevationcost += elevationCost;
}
}
}
else if ( ehbd < 0 )
{
} else if (ehbd < 0) {
ehbd = 0;
}
float upweight = 0.f;
if ( ehbu > rc.elevationpenaltybuffer )
{
if (ehbu > rc.elevationpenaltybuffer) {
upweight = 1.f;
int excess = ehbu - rc.elevationpenaltybuffer;
int reduce = dist * rc.elevationbufferreduce;
if ( reduce > excess )
{
if (reduce > excess) {
upweight = ((float) excess) / reduce;
reduce = excess;
}
excess = ehbu - rc.elevationmaxbuffer;
if ( reduce < excess )
{
if (reduce < excess) {
reduce = excess;
}
ehbu -= reduce;
if ( rc.uphillcostdiv > 0 )
{
if (rc.uphillcostdiv > 0) {
int elevationCost = reduce / rc.uphillcostdiv;
sectionCost += elevationCost;
if ( message != null )
{
if (message != null) {
message.linkelevationcost += elevationCost;
}
}
}
else if ( ehbu < 0 )
{
} else if (ehbu < 0) {
ehbu = 0;
}
// get the effective costfactor (slope dependent)
float costfactor = cfup * upweight + cf * (1.f - upweight - downweight) + cfdown * downweight;
if ( message != null )
{
if (message != null) {
message.costfactor = costfactor;
}
@ -154,20 +134,16 @@ final class StdPath extends OsmPath
}
@Override
protected double processTargetNode( RoutingContext rc )
{
protected double processTargetNode(RoutingContext rc) {
// finally add node-costs for target node
if ( targetNode.nodeDescription != null )
{
if (targetNode.nodeDescription != null) {
boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.;
rc.expctxNode.evaluate(nodeAccessGranted, targetNode.nodeDescription);
float initialcost = rc.expctxNode.getInitialcost();
if ( initialcost >= 1000000. )
{
if (initialcost >= 1000000.) {
return -1.;
}
if ( message != null )
{
if (message != null) {
message.linknodecost += (int) initialcost;
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(nodeAccessGranted, targetNode.nodeDescription);
}
@ -177,25 +153,21 @@ final class StdPath extends OsmPath
}
@Override
public int elevationCorrection( RoutingContext rc )
{
public int elevationCorrection(RoutingContext rc) {
return (rc.downhillcostdiv > 0 ? ehbd / rc.downhillcostdiv : 0)
+ (rc.uphillcostdiv > 0 ? ehbu / rc.uphillcostdiv : 0);
}
@Override
public boolean definitlyWorseThan( OsmPath path, RoutingContext rc )
{
public boolean definitlyWorseThan(OsmPath path, RoutingContext rc) {
StdPath p = (StdPath) path;
int c = p.cost;
if ( rc.downhillcostdiv > 0 )
{
if (rc.downhillcostdiv > 0) {
int delta = p.ehbd - ehbd;
if (delta > 0) c += delta / rc.downhillcostdiv;
}
if ( rc.uphillcostdiv > 0 )
{
if (rc.uphillcostdiv > 0) {
int delta = p.ehbu - ehbu;
if (delta > 0) c += delta / rc.uphillcostdiv;
}
@ -203,20 +175,14 @@ final class StdPath extends OsmPath
return cost > c;
}
private double calcIncline( double dist )
{
private double calcIncline(double dist) {
double min_delta = 3.;
double shift;
if ( elevation_buffer > min_delta )
{
if (elevation_buffer > min_delta) {
shift = -min_delta;
}
else if ( elevation_buffer < min_delta )
{
} else if (elevation_buffer < min_delta) {
shift = -min_delta;
}
else
{
} else {
return 0.;
}
double decayFactor = FastMath.exp(-dist / 100.);
@ -227,10 +193,8 @@ final class StdPath extends OsmPath
}
@Override
protected void computeKinematic( RoutingContext rc, double dist, double delta_h, boolean detailMode )
{
if ( !detailMode )
{
protected void computeKinematic(RoutingContext rc, double dist, double delta_h, boolean detailMode) {
if (!detailMode) {
return;
}
@ -241,26 +205,21 @@ final class StdPath extends OsmPath
double wayMaxspeed;
wayMaxspeed = rc.expctxWay.getMaxspeed() / 3.6f;
if (wayMaxspeed == 0)
{
if (wayMaxspeed == 0) {
wayMaxspeed = rc.maxSpeed;
}
wayMaxspeed = Math.min(wayMaxspeed, rc.maxSpeed);
double speed; // Travel speed
double f_roll = rc.totalMass * GRAVITY * (rc.defaultC_r + incline);
if (rc.footMode || rc.expctxWay.getCostfactor() > 4.9 )
{
if (rc.footMode || rc.expctxWay.getCostfactor() > 4.9) {
// Use Tobler's hiking function for walking sections
speed = rc.maxSpeed * 3.6;
speed = (speed * FastMath.exp(-3.5 * Math.abs(incline + 0.05))) / 3.6;
}
else if (rc.bikeMode)
{
} else if (rc.bikeMode) {
speed = solveCubic(rc.S_C_x, f_roll, rc.bikerPower);
speed = Math.min(speed, wayMaxspeed);
}
else // all other
} else // all other
{
speed = wayMaxspeed;
}
@ -269,26 +228,21 @@ final class StdPath extends OsmPath
// Calc energy assuming biking (no good model yet for hiking)
// (Count only positive, negative would mean breaking to enforce maxspeed)
double energy = dist * (rc.S_C_x * speed * speed + f_roll);
if ( energy > 0. )
{
if (energy > 0.) {
totalEnergy += energy;
}
}
private static double solveCubic( double a, double c, double d )
{
private static double solveCubic(double a, double c, double d) {
// Solves a * v^3 + c * v = d with a Newton method
// to get the speed v for the section.
double v = 8.;
boolean findingStartvalue = true;
for ( int i = 0; i < 10; i++ )
{
for (int i = 0; i < 10; i++) {
double y = (a * v * v + c) * v - d;
if ( y < .1 )
{
if ( findingStartvalue )
{
if (y < .1) {
if (findingStartvalue) {
v *= 2.;
continue;
}
@ -302,14 +256,12 @@ final class StdPath extends OsmPath
}
@Override
public double getTotalTime()
{
public double getTotalTime() {
return totalTime;
}
@Override
public double getTotalEnergy()
{
public double getTotalEnergy() {
return totalEnergy;
}
}

View File

@ -2,8 +2,7 @@ package btools.router;
import java.util.Map;
public class SuspectInfo
{
public class SuspectInfo {
public static final int TRIGGER_DEAD_END = 1;
public static final int TRIGGER_DEAD_START = 2;
public static final int TRIGGER_NODE_BLOCK = 4;
@ -17,12 +16,10 @@ public class SuspectInfo
public int prio;
public int triggers;
public static void addSuspect( Map<Long,SuspectInfo> map, long id, int prio, int trigger )
{
public static void addSuspect(Map<Long, SuspectInfo> map, long id, int prio, int trigger) {
Long iD = Long.valueOf(id);
SuspectInfo info = map.get(iD);
if ( info == null )
{
if (info == null) {
info = new SuspectInfo();
map.put(iD, info);
}
@ -30,10 +27,8 @@ public class SuspectInfo
info.triggers |= trigger;
}
public static SuspectInfo addTrigger( SuspectInfo old, int prio, int trigger )
{
if ( old == null )
{
public static SuspectInfo addTrigger(SuspectInfo old, int prio, int trigger) {
if (old == null) {
old = new SuspectInfo();
}
old.prio = Math.max(old.prio, prio);
@ -41,8 +36,7 @@ public class SuspectInfo
return old;
}
public static String getTriggerText( int triggers )
{
public static String getTriggerText(int triggers) {
StringBuilder sb = new StringBuilder();
addText(sb, "dead-end", triggers, TRIGGER_DEAD_END);
addText(sb, "dead-start", triggers, TRIGGER_DEAD_START);
@ -56,8 +50,7 @@ public class SuspectInfo
return sb.toString();
}
private static void addText( StringBuilder sb, String text, int mask, int bit )
{
private static void addText(StringBuilder sb, String text, int mask, int bit) {
if ((bit & mask) == 0) return;
if (sb.length() > 0) sb.append(",");
sb.append(text);

View File

@ -9,8 +9,7 @@ package btools.router;
import java.util.ArrayList;
import java.util.List;
public class VoiceHint
{
public class VoiceHint {
static final int C = 1; // continue (go straight)
static final int TL = 2; // turn left
static final int TSLL = 3; // turn slightly left
@ -36,8 +35,7 @@ public class VoiceHint
double distanceToNext;
int indexInTrack;
public float getTime()
{
public float getTime() {
return oldWay == null ? 0.f : oldWay.time;
}
@ -47,157 +45,205 @@ public class VoiceHint
int roundaboutExit;
boolean isRoundabout()
{
boolean isRoundabout() {
return roundaboutExit != 0;
}
public void addBadWay( MessageData badWay )
{
if ( badWay == null )
{
public void addBadWay(MessageData badWay) {
if (badWay == null) {
return;
}
if ( badWays == null )
{
if (badWays == null) {
badWays = new ArrayList<MessageData>();
}
badWays.add(badWay);
}
public int getCommand()
{
public int getCommand() {
return cmd;
}
public int getExitNumber()
{
public int getExitNumber() {
return roundaboutExit;
}
public String getCommandString()
{
switch ( cmd )
{
case TU : return "TU";
case TSHL : return "TSHL";
case TL : return "TL";
case TSLL : return "TSLL";
case KL : return "KL";
case C : return "C";
case KR : return "KR";
case TSLR : return "TSLR";
case TR : return "TR";
case TSHR : return "TSHR";
case TRU : return "TRU";
case RNDB : return "RNDB" + roundaboutExit;
case RNLB : return "RNLB" + (-roundaboutExit);
default : throw new IllegalArgumentException( "unknown command: " + cmd );
public String getCommandString() {
switch (cmd) {
case TU:
return "TU";
case TSHL:
return "TSHL";
case TL:
return "TL";
case TSLL:
return "TSLL";
case KL:
return "KL";
case C:
return "C";
case KR:
return "KR";
case TSLR:
return "TSLR";
case TR:
return "TR";
case TSHR:
return "TSHR";
case TRU:
return "TRU";
case RNDB:
return "RNDB" + roundaboutExit;
case RNLB:
return "RNLB" + (-roundaboutExit);
default:
throw new IllegalArgumentException("unknown command: " + cmd);
}
}
public String getSymbolString()
{
switch ( cmd )
{
case TU : return "TU";
case TSHL : return "TSHL";
case TL : return "Left";
case TSLL : return "TSLL";
case KL : return "TSLL"; // ?
case C : return "Straight";
case KR : return "TSLR"; // ?
case TSLR : return "TSLR";
case TR : return "Right";
case TSHR : return "TSHR";
case TRU : return "TU";
case RNDB : return "RNDB" + roundaboutExit;
case RNLB : return "RNLB" + (-roundaboutExit);
default : throw new IllegalArgumentException( "unknown command: " + cmd );
public String getSymbolString() {
switch (cmd) {
case TU:
return "TU";
case TSHL:
return "TSHL";
case TL:
return "Left";
case TSLL:
return "TSLL";
case KL:
return "TSLL"; // ?
case C:
return "Straight";
case KR:
return "TSLR"; // ?
case TSLR:
return "TSLR";
case TR:
return "Right";
case TSHR:
return "TSHR";
case TRU:
return "TU";
case RNDB:
return "RNDB" + roundaboutExit;
case RNLB:
return "RNLB" + (-roundaboutExit);
default:
throw new IllegalArgumentException("unknown command: " + cmd);
}
}
public String getMessageString()
{
switch ( cmd )
{
case TU : return "u-turn";
case TSHL : return "sharp left";
case TL : return "left";
case TSLL : return "slight left";
case KL : return "keep left";
case C : return "straight";
case KR : return "keep right";
case TSLR : return "slight right";
case TR : return "right";
case TSHR : return "sharp right";
case TRU : return "u-turn";
case RNDB : return "Take exit " + roundaboutExit;
case RNLB : return "Take exit " + (-roundaboutExit);
default : throw new IllegalArgumentException( "unknown command: " + cmd );
public String getMessageString() {
switch (cmd) {
case TU:
return "u-turn";
case TSHL:
return "sharp left";
case TL:
return "left";
case TSLL:
return "slight left";
case KL:
return "keep left";
case C:
return "straight";
case KR:
return "keep right";
case TSLR:
return "slight right";
case TR:
return "right";
case TSHR:
return "sharp right";
case TRU:
return "u-turn";
case RNDB:
return "Take exit " + roundaboutExit;
case RNLB:
return "Take exit " + (-roundaboutExit);
default:
throw new IllegalArgumentException("unknown command: " + cmd);
}
}
public int getLocusAction()
{
switch ( cmd )
{
case TU : return 13;
case TSHL : return 5;
case TL : return 4;
case TSLL : return 3;
case KL : return 9; // ?
case C : return 1;
case KR : return 10; // ?
case TSLR : return 6;
case TR : return 7;
case TSHR : return 8;
case TRU : return 14;
case RNDB : return 26 + roundaboutExit;
case RNLB : return 26 - roundaboutExit;
default : throw new IllegalArgumentException( "unknown command: " + cmd );
public int getLocusAction() {
switch (cmd) {
case TU:
return 13;
case TSHL:
return 5;
case TL:
return 4;
case TSLL:
return 3;
case KL:
return 9; // ?
case C:
return 1;
case KR:
return 10; // ?
case TSLR:
return 6;
case TR:
return 7;
case TSHR:
return 8;
case TRU:
return 14;
case RNDB:
return 26 + roundaboutExit;
case RNLB:
return 26 - roundaboutExit;
default:
throw new IllegalArgumentException("unknown command: " + cmd);
}
}
public int getOruxAction()
{
switch ( cmd )
{
case TU : return 1003;
case TSHL : return 1019;
case TL : return 1000;
case TSLL : return 1017;
case KL : return 1015; // ?
case C : return 1002;
case KR : return 1014; // ?
case TSLR : return 1016;
case TR : return 1001;
case TSHR : return 1018;
case TRU : return 1003;
case RNDB : return 1008 + roundaboutExit;
case RNLB : return 1008 + roundaboutExit;
default : throw new IllegalArgumentException( "unknown command: " + cmd );
public int getOruxAction() {
switch (cmd) {
case TU:
return 1003;
case TSHL:
return 1019;
case TL:
return 1000;
case TSLL:
return 1017;
case KL:
return 1015; // ?
case C:
return 1002;
case KR:
return 1014; // ?
case TSLR:
return 1016;
case TR:
return 1001;
case TSHR:
return 1018;
case TRU:
return 1003;
case RNDB:
return 1008 + roundaboutExit;
case RNLB:
return 1008 + roundaboutExit;
default:
throw new IllegalArgumentException("unknown command: " + cmd);
}
}
public void calcCommand()
{
public void calcCommand() {
float lowerBadWayAngle = -181;
float higherBadWayAngle = 181;
if ( badWays != null )
{
for ( MessageData badWay : badWays )
{
if ( badWay.isBadOneway() )
{
if (badWays != null) {
for (MessageData badWay : badWays) {
if (badWay.isBadOneway()) {
continue;
}
if ( lowerBadWayAngle < badWay.turnangle && badWay.turnangle < goodWay.turnangle )
{
if (lowerBadWayAngle < badWay.turnangle && badWay.turnangle < goodWay.turnangle) {
lowerBadWayAngle = badWay.turnangle;
}
if ( higherBadWayAngle > badWay.turnangle && badWay.turnangle > goodWay.turnangle )
{
if (higherBadWayAngle > badWay.turnangle && badWay.turnangle > goodWay.turnangle) {
higherBadWayAngle = badWay.turnangle;
}
}
@ -206,100 +252,65 @@ public class VoiceHint
float cmdAngle = angle;
// fall back to local angle if otherwise inconsistent
if ( lowerBadWayAngle > angle || higherBadWayAngle < angle )
{
if (lowerBadWayAngle > angle || higherBadWayAngle < angle) {
cmdAngle = goodWay.turnangle;
}
if (roundaboutExit > 0)
{
if (roundaboutExit > 0) {
cmd = RNDB;
}
else if (roundaboutExit < 0)
{
} else if (roundaboutExit < 0) {
cmd = RNLB;
}
else if ( cmdAngle < -159. )
{
} else if (cmdAngle < -159.) {
cmd = TU;
}
else if ( cmdAngle < -135. )
{
} else if (cmdAngle < -135.) {
cmd = TSHL;
}
else if ( cmdAngle < -45. )
{
} else if (cmdAngle < -45.) {
// a TL can be pushed in either direction by a close-by alternative
if ( higherBadWayAngle > -90. && higherBadWayAngle < -15. && lowerBadWayAngle < -180. )
{
if (higherBadWayAngle > -90. && higherBadWayAngle < -15. && lowerBadWayAngle < -180.) {
cmd = TSHL;
}
else if ( lowerBadWayAngle > -180. && lowerBadWayAngle < -90. && higherBadWayAngle > 0. )
{
} else if (lowerBadWayAngle > -180. && lowerBadWayAngle < -90. && higherBadWayAngle > 0.) {
cmd = TSLL;
}
else
{
} else {
cmd = TL;
}
}
else if ( cmdAngle < -21. )
{
} else if (cmdAngle < -21.) {
if (cmd != KR) // don't overwrite KR with TSLL
{
cmd = TSLL;
}
}
else if ( cmdAngle < 21. )
{
} else if (cmdAngle < 21.) {
if (cmd != KR && cmd != KL) // don't overwrite KL/KR hints!
{
cmd = C;
}
}
else if ( cmdAngle < 45. )
{
} else if (cmdAngle < 45.) {
if (cmd != KL) // don't overwrite KL with TSLR
{
cmd = TSLR;
}
}
else if ( cmdAngle < 135. )
{
} else if (cmdAngle < 135.) {
// a TR can be pushed in either direction by a close-by alternative
if ( higherBadWayAngle > 90. && higherBadWayAngle < 180. && lowerBadWayAngle < 0. )
{
if (higherBadWayAngle > 90. && higherBadWayAngle < 180. && lowerBadWayAngle < 0.) {
cmd = TSLR;
}
else if ( lowerBadWayAngle > 15. && lowerBadWayAngle < 90. && higherBadWayAngle > 180. )
{
} else if (lowerBadWayAngle > 15. && lowerBadWayAngle < 90. && higherBadWayAngle > 180.) {
cmd = TSHR;
}
else
{
} else {
cmd = TR;
}
}
else if ( cmdAngle < 159. )
{
} else if (cmdAngle < 159.) {
cmd = TSHR;
}
else
{
} else {
cmd = TRU;
}
}
public String formatGeometry()
{
public String formatGeometry() {
float oldPrio = oldWay == null ? 0.f : oldWay.priorityclassifier;
StringBuilder sb = new StringBuilder(30);
sb.append(' ').append((int) oldPrio);
appendTurnGeometry(sb, goodWay);
if ( badWays != null )
{
for ( MessageData badWay : badWays )
{
if (badWays != null) {
for (MessageData badWay : badWays) {
sb.append(" ");
appendTurnGeometry(sb, badWay);
}
@ -307,8 +318,7 @@ public class VoiceHint
return sb.toString();
}
private void appendTurnGeometry( StringBuilder sb, MessageData msg )
{
private void appendTurnGeometry(StringBuilder sb, MessageData msg) {
sb.append("(").append((int) (msg.turnangle + 0.5)).append(")").append((int) (msg.priorityclassifier));
}

View File

@ -9,30 +9,24 @@ package btools.router;
import java.util.ArrayList;
import java.util.List;
public class VoiceHintList
{
public class VoiceHintList {
private String transportMode;
int turnInstructionMode;
ArrayList<VoiceHint> list = new ArrayList<VoiceHint>();
public void setTransportMode( boolean isCar, boolean isBike )
{
public void setTransportMode(boolean isCar, boolean isBike) {
transportMode = isCar ? "car" : (isBike ? "bike" : "foot");
}
public String getTransportMode()
{
public String getTransportMode() {
return transportMode;
}
public int getLocusRouteType()
{
if ( "car".equals( transportMode ) )
{
public int getLocusRouteType() {
if ("car".equals(transportMode)) {
return 0;
}
if ( "bike".equals( transportMode ) )
{
if ("bike".equals(transportMode)) {
return 5;
}
return 3; // foot

View File

@ -8,26 +8,21 @@ package btools.router;
import java.util.ArrayList;
import java.util.List;
public final class VoiceHintProcessor
{
public final class VoiceHintProcessor {
private double catchingRange; // range to catch angles and merge turns
private boolean explicitRoundabouts;
public VoiceHintProcessor( double catchingRange, boolean explicitRoundabouts )
{
public VoiceHintProcessor(double catchingRange, boolean explicitRoundabouts) {
this.catchingRange = catchingRange;
this.explicitRoundabouts = explicitRoundabouts;
}
private float sumNonConsumedWithinCatchingRange( List<VoiceHint> inputs, int offset )
{
private float sumNonConsumedWithinCatchingRange(List<VoiceHint> inputs, int offset) {
double distance = 0.;
float angle = 0.f;
while( offset >= 0 && distance < catchingRange )
{
while (offset >= 0 && distance < catchingRange) {
VoiceHint input = inputs.get(offset--);
if ( input.turnAngleConsumed )
{
if (input.turnAngleConsumed) {
break;
}
angle += input.goodWay.turnangle;
@ -44,10 +39,10 @@ public final class VoiceHintProcessor
* order (from target to start), but output is
* returned in travel-direction and only for
* those nodes that trigger a voice hint.
*
* <p>
* Input objects are expected for every segment
* of the track, also for those without a junction
*
* <p>
* VoiceHint objects in the output list are enriched
* by the voice-command, the total angle and the distance
* to the next hint
@ -55,16 +50,14 @@ public final class VoiceHintProcessor
* @param inputs tracknodes, un reverse order
* @return voice hints, in forward order
*/
public List<VoiceHint> process( List<VoiceHint> inputs )
{
public List<VoiceHint> process(List<VoiceHint> inputs) {
List<VoiceHint> results = new ArrayList<VoiceHint>();
double distance = 0.;
float roundAboutTurnAngle = 0.f; // sums up angles in roundabout
int roundaboutExit = 0;
for ( int hintIdx = 0; hintIdx < inputs.size(); hintIdx++ )
{
for (int hintIdx = 0; hintIdx < inputs.size(); hintIdx++) {
VoiceHint input = inputs.get(hintIdx);
float turnAngle = input.goodWay.turnangle;
@ -75,28 +68,22 @@ public final class VoiceHintProcessor
boolean isLink2Highway = input.oldWay.isLinktType() && !input.goodWay.isLinktType();
if ( input.oldWay.isRoundabout() )
{
if (input.oldWay.isRoundabout()) {
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
boolean isExit = roundaboutExit == 0; // exit point is always exit
if ( input.badWays != null )
{
for ( MessageData badWay : input.badWays )
{
if ( !badWay.isBadOneway() && badWay.isGoodForCars() && Math.abs( badWay.turnangle ) < 120. )
{
if (input.badWays != null) {
for (MessageData badWay : input.badWays) {
if (!badWay.isBadOneway() && badWay.isGoodForCars() && Math.abs(badWay.turnangle) < 120.) {
isExit = true;
}
}
}
if ( isExit )
{
if (isExit) {
roundaboutExit++;
}
continue;
}
if ( roundaboutExit > 0 )
{
if (roundaboutExit > 0) {
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
input.angle = roundAboutTurnAngle;
input.distanceToNext = distance;
@ -114,50 +101,40 @@ public final class VoiceHintProcessor
float minAngle = 180.f;
float minAbsAngeRaw = 180.f;
if ( input.badWays != null )
{
for ( MessageData badWay : input.badWays )
{
if (input.badWays != null) {
for (MessageData badWay : input.badWays) {
int badPrio = badWay.getPrio();
float badTurn = badWay.turnangle;
boolean isHighway2Link = !input.oldWay.isLinktType() && badWay.isLinktType();
if ( badPrio > maxPrioAll && !isHighway2Link )
{
if (badPrio > maxPrioAll && !isHighway2Link) {
maxPrioAll = badPrio;
}
if ( badWay.costfactor < 20.f && Math.abs( badTurn ) < minAbsAngeRaw )
{
if (badWay.costfactor < 20.f && Math.abs(badTurn) < minAbsAngeRaw) {
minAbsAngeRaw = Math.abs(badTurn);
}
if ( badPrio < minPrio )
{
if (badPrio < minPrio) {
continue; // ignore low prio ways
}
if ( badWay.isBadOneway() )
{
if (badWay.isBadOneway()) {
continue; // ignore wrong oneways
}
if ( Math.abs( badTurn ) - Math.abs( turnAngle ) > 80.f )
{
if (Math.abs(badTurn) - Math.abs(turnAngle) > 80.f) {
continue; // ways from the back should not trigger a slight turn
}
if ( badPrio > maxPrioCandidates )
{
if (badPrio > maxPrioCandidates) {
maxPrioCandidates = badPrio;
}
if ( badTurn > maxAngle )
{
if (badTurn > maxAngle) {
maxAngle = badTurn;
}
if ( badTurn < minAngle )
{
if (badTurn < minAngle) {
minAngle = badTurn;
}
}
@ -174,20 +151,17 @@ public final class VoiceHintProcessor
// with candidate detours equal in priority than the route exit leg
boolean conditionalTrigger = maxPrioCandidates >= minPrio;
if ( unconditionalTrigger || conditionalTrigger )
{
if (unconditionalTrigger || conditionalTrigger) {
input.angle = turnAngle;
input.calcCommand();
boolean isStraight = input.cmd == VoiceHint.C;
input.needsRealTurn = (!unconditionalTrigger) && isStraight;
// check for KR/KL
if ( maxAngle < turnAngle && maxAngle > turnAngle - 45.f - (turnAngle > 0.f ? turnAngle : 0.f ) )
{
if (maxAngle < turnAngle && maxAngle > turnAngle - 45.f - (turnAngle > 0.f ? turnAngle : 0.f)) {
input.cmd = VoiceHint.KR;
}
if ( minAngle > turnAngle && minAngle < turnAngle + 45.f - (turnAngle < 0.f ? turnAngle : 0.f ) )
{
if (minAngle > turnAngle && minAngle < turnAngle + 45.f - (turnAngle < 0.f ? turnAngle : 0.f)) {
input.cmd = VoiceHint.KL;
}
@ -196,8 +170,7 @@ public final class VoiceHintProcessor
distance = 0.;
results.add(input);
}
if ( results.size() > 0 && distance < catchingRange )
{
if (results.size() > 0 && distance < catchingRange) {
results.get(results.size() - 1).angle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
}
}
@ -207,19 +180,15 @@ public final class VoiceHintProcessor
List<VoiceHint> results2 = new ArrayList<VoiceHint>();
int i = results.size();
while( i > 0 )
{
while (i > 0) {
VoiceHint hint = results.get(--i);
if ( hint.cmd == 0 )
{
if (hint.cmd == 0) {
hint.calcCommand();
}
if ( ! ( hint.needsRealTurn && hint.cmd == VoiceHint.C ) )
{
if (!(hint.needsRealTurn && hint.cmd == VoiceHint.C)) {
double dist = hint.distanceToNext;
// sum up other hints within the catching range (e.g. 40m)
while( dist < catchingRange && i > 0 )
{
while (dist < catchingRange && i > 0) {
VoiceHint h2 = results.get(i - 1);
dist = h2.distanceToNext;
hint.distanceToNext += dist;
@ -233,8 +202,7 @@ public final class VoiceHintProcessor
}
}
if ( !explicitRoundabouts )
{
if (!explicitRoundabouts) {
hint.roundaboutExit = 0; // use an angular hint instead
}
hint.calcCommand();

View File

@ -2,8 +2,7 @@ package btools.expressions;
import java.util.StringTokenizer;
final class BExpression
{
final class BExpression {
private static final int OR_EXP = 10;
private static final int AND_EXP = 11;
private static final int NOT_EXP = 12;
@ -37,35 +36,28 @@ final class BExpression
private int[] lookupValueIdxArray;
// Parse the expression and all subexpression
public static BExpression parse( BExpressionContext ctx, int level ) throws Exception
{
public static BExpression parse(BExpressionContext ctx, int level) throws Exception {
return parse(ctx, level, null);
}
private static BExpression parse( BExpressionContext ctx, int level, String optionalToken ) throws Exception
{
private static BExpression parse(BExpressionContext ctx, int level, String optionalToken) throws Exception {
boolean brackets = false;
String operator = ctx.parseToken();
if ( optionalToken != null && optionalToken.equals( operator ) )
{
if (optionalToken != null && optionalToken.equals(operator)) {
operator = ctx.parseToken();
}
if ( "(".equals( operator ) )
{
if ("(".equals(operator)) {
brackets = true;
operator = ctx.parseToken();
}
if ( operator == null )
{
if (operator == null) {
if (level == 0) return null;
else throw new IllegalArgumentException("unexpected end of file");
}
if ( level == 0 )
{
if ( !"assign".equals( operator ) )
{
if (level == 0) {
if (!"assign".equals(operator)) {
throw new IllegalArgumentException("operator " + operator + " is invalid on toplevel (only 'assign' allowed)");
}
}
@ -74,94 +66,62 @@ final class BExpression
int nops = 3;
boolean ifThenElse = false;
if ( "switch".equals( operator ) )
{
if ("switch".equals(operator)) {
exp.typ = SWITCH_EXP;
}
else if ( "if".equals( operator ) )
{
} else if ("if".equals(operator)) {
exp.typ = SWITCH_EXP;
ifThenElse = true;
}
else
{
} else {
nops = 2; // check binary expressions
if ( "or".equals( operator ) )
{
if ("or".equals(operator)) {
exp.typ = OR_EXP;
}
else if ( "and".equals( operator ) )
{
} else if ("and".equals(operator)) {
exp.typ = AND_EXP;
}
else if ( "multiply".equals( operator ) )
{
} else if ("multiply".equals(operator)) {
exp.typ = MULTIPLY_EXP;
}
else if ( "add".equals( operator ) )
{
} else if ("add".equals(operator)) {
exp.typ = ADD_EXP;
}
else if ( "max".equals( operator ) )
{
} else if ("max".equals(operator)) {
exp.typ = MAX_EXP;
}
else if ( "min".equals( operator ) )
{
} else if ("min".equals(operator)) {
exp.typ = MIN_EXP;
}
else if ( "equal".equals( operator ) )
{
} else if ("equal".equals(operator)) {
exp.typ = EQUAL_EXP;
}
else if ( "greater".equals( operator ) )
{
} else if ("greater".equals(operator)) {
exp.typ = GREATER_EXP;
}
else if ( "sub".equals( operator ) )
{
} else if ("sub".equals(operator)) {
exp.typ = SUB_EXP;
}
else if ( "lesser".equals( operator ) )
{
} else if ("lesser".equals(operator)) {
exp.typ = LESSER_EXP;
}
else if ( "xor".equals( operator ) )
{
} else if ("xor".equals(operator)) {
exp.typ = XOR_EXP;
}
else
{
} else {
nops = 1; // check unary expressions
if ( "assign".equals( operator ) )
{
if ("assign".equals(operator)) {
if (level > 0) throw new IllegalArgumentException("assign operator within expression");
exp.typ = ASSIGN_EXP;
String variable = ctx.parseToken();
if (variable == null) throw new IllegalArgumentException("unexpected end of file");
if ( variable.indexOf( '=' ) >= 0 ) throw new IllegalArgumentException( "variable name cannot contain '=': " + variable );
if ( variable.indexOf( ':' ) >= 0 ) throw new IllegalArgumentException( "cannot assign context-prefixed variable: " + variable );
if (variable.indexOf('=') >= 0)
throw new IllegalArgumentException("variable name cannot contain '=': " + variable);
if (variable.indexOf(':') >= 0)
throw new IllegalArgumentException("cannot assign context-prefixed variable: " + variable);
exp.variableIdx = ctx.getVariableIdx(variable, true);
if ( exp.variableIdx < ctx.getMinWriteIdx() ) throw new IllegalArgumentException( "cannot assign to readonly variable " + variable );
}
else if ( "not".equals( operator ) )
{
if (exp.variableIdx < ctx.getMinWriteIdx())
throw new IllegalArgumentException("cannot assign to readonly variable " + variable);
} else if ("not".equals(operator)) {
exp.typ = NOT_EXP;
}
else
{
} else {
nops = 0; // check elemantary expressions
int idx = operator.indexOf('=');
if ( idx >= 0 )
{
if (idx >= 0) {
exp.typ = LOOKUP_EXP;
String name = operator.substring(0, idx);
String values = operator.substring(idx + 1);
exp.lookupNameIdx = ctx.getLookupNameIdx(name);
if ( exp.lookupNameIdx < 0 )
{
if (exp.lookupNameIdx < 0) {
throw new IllegalArgumentException("unknown lookup name: " + name);
}
ctx.markLookupIdxUsed(exp.lookupNameIdx);
@ -169,18 +129,14 @@ final class BExpression
int nt = tk.countTokens();
int nt2 = nt == 0 ? 1 : nt;
exp.lookupValueIdxArray = new int[nt2];
for( int ti=0; ti<nt2; ti++ )
{
for (int ti = 0; ti < nt2; ti++) {
String value = ti < nt ? tk.nextToken() : "";
exp.lookupValueIdxArray[ti] = ctx.getLookupValueIdx(exp.lookupNameIdx, value);
if ( exp.lookupValueIdxArray[ti] < 0 )
{
if (exp.lookupValueIdxArray[ti] < 0) {
throw new IllegalArgumentException("unknown lookup value: " + value);
}
}
}
else if ( ( idx = operator.indexOf( ':' ) ) >= 0 )
{
} else if ((idx = operator.indexOf(':')) >= 0) {
/*
use of variable values
assign no_height
@ -198,31 +154,20 @@ final class BExpression
exp.typ = FOREIGN_VARIABLE_EXP;
exp.variableIdx = ctx.getForeignVariableIdx(context, varname);
}
}
else if ( (idx = ctx.getVariableIdx( operator, false )) >= 0 )
{
} else if ((idx = ctx.getVariableIdx(operator, false)) >= 0) {
exp.typ = VARIABLE_EXP;
exp.variableIdx = idx;
}
else if ( "true".equals( operator ) )
{
} else if ("true".equals(operator)) {
exp.numberValue = 1.f;
exp.typ = NUMBER_EXP;
}
else if ( "false".equals( operator ) )
{
} else if ("false".equals(operator)) {
exp.numberValue = 0.f;
exp.typ = NUMBER_EXP;
}
else
{
try
{
} else {
try {
exp.numberValue = Float.parseFloat(operator);
exp.typ = NUMBER_EXP;
}
catch( NumberFormatException nfe )
{
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("unknown expression: " + operator);
}
}
@ -230,71 +175,81 @@ final class BExpression
}
}
// parse operands
if ( nops > 0 )
{
if (nops > 0) {
exp.op1 = BExpression.parse(ctx, level + 1, exp.typ == ASSIGN_EXP ? "=" : null);
}
if ( nops > 1 )
{
if (nops > 1) {
if (ifThenElse) checkExpectedToken(ctx, "then");
exp.op2 = BExpression.parse(ctx, level + 1, null);
}
if ( nops > 2 )
{
if (nops > 2) {
if (ifThenElse) checkExpectedToken(ctx, "else");
exp.op3 = BExpression.parse(ctx, level + 1, null);
}
if ( brackets )
{
if (brackets) {
checkExpectedToken(ctx, ")");
}
return exp;
}
private static void checkExpectedToken( BExpressionContext ctx, String expected ) throws Exception
{
private static void checkExpectedToken(BExpressionContext ctx, String expected) throws Exception {
String token = ctx.parseToken();
if ( ! expected.equals( token ) )
{
if (!expected.equals(token)) {
throw new IllegalArgumentException("unexpected token: " + token + ", expected: " + expected);
}
}
// Evaluate the expression
public float evaluate( BExpressionContext ctx )
{
switch( typ )
{
case OR_EXP: return op1.evaluate(ctx) != 0.f ? 1.f : ( op2.evaluate(ctx) != 0.f ? 1.f : 0.f );
case XOR_EXP: return ( (op1.evaluate(ctx) != 0.f) ^ ( op2.evaluate(ctx) != 0.f ) ? 1.f : 0.f );
case AND_EXP: return op1.evaluate(ctx) != 0.f ? ( op2.evaluate(ctx) != 0.f ? 1.f : 0.f ) : 0.f;
case ADD_EXP: return op1.evaluate(ctx) + op2.evaluate(ctx);
case SUB_EXP: return op1.evaluate(ctx) - op2.evaluate(ctx);
case MULTIPLY_EXP: return op1.evaluate(ctx) * op2.evaluate(ctx);
case MAX_EXP: return max( op1.evaluate(ctx), op2.evaluate(ctx) );
case MIN_EXP: return min( op1.evaluate(ctx), op2.evaluate(ctx) );
case EQUAL_EXP: return op1.evaluate(ctx) == op2.evaluate(ctx) ? 1.f : 0.f;
case GREATER_EXP: return op1.evaluate(ctx) > op2.evaluate(ctx) ? 1.f : 0.f;
case LESSER_EXP: return op1.evaluate(ctx) < op2.evaluate(ctx) ? 1.f : 0.f;
case SWITCH_EXP: return op1.evaluate(ctx) != 0.f ? op2.evaluate(ctx) : op3.evaluate(ctx);
case ASSIGN_EXP: return ctx.assign( variableIdx, op1.evaluate(ctx) );
case LOOKUP_EXP: return ctx.getLookupMatch( lookupNameIdx, lookupValueIdxArray );
case NUMBER_EXP: return numberValue;
case VARIABLE_EXP: return ctx.getVariableValue( variableIdx );
case FOREIGN_VARIABLE_EXP: return ctx.getForeignVariableValue( variableIdx );
case VARIABLE_GET_EXP: return ctx.getLookupValue(lookupNameIdx);
case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f;
default: throw new IllegalArgumentException( "unknown op-code: " + typ );
public float evaluate(BExpressionContext ctx) {
switch (typ) {
case OR_EXP:
return op1.evaluate(ctx) != 0.f ? 1.f : (op2.evaluate(ctx) != 0.f ? 1.f : 0.f);
case XOR_EXP:
return ((op1.evaluate(ctx) != 0.f) ^ (op2.evaluate(ctx) != 0.f) ? 1.f : 0.f);
case AND_EXP:
return op1.evaluate(ctx) != 0.f ? (op2.evaluate(ctx) != 0.f ? 1.f : 0.f) : 0.f;
case ADD_EXP:
return op1.evaluate(ctx) + op2.evaluate(ctx);
case SUB_EXP:
return op1.evaluate(ctx) - op2.evaluate(ctx);
case MULTIPLY_EXP:
return op1.evaluate(ctx) * op2.evaluate(ctx);
case MAX_EXP:
return max(op1.evaluate(ctx), op2.evaluate(ctx));
case MIN_EXP:
return min(op1.evaluate(ctx), op2.evaluate(ctx));
case EQUAL_EXP:
return op1.evaluate(ctx) == op2.evaluate(ctx) ? 1.f : 0.f;
case GREATER_EXP:
return op1.evaluate(ctx) > op2.evaluate(ctx) ? 1.f : 0.f;
case LESSER_EXP:
return op1.evaluate(ctx) < op2.evaluate(ctx) ? 1.f : 0.f;
case SWITCH_EXP:
return op1.evaluate(ctx) != 0.f ? op2.evaluate(ctx) : op3.evaluate(ctx);
case ASSIGN_EXP:
return ctx.assign(variableIdx, op1.evaluate(ctx));
case LOOKUP_EXP:
return ctx.getLookupMatch(lookupNameIdx, lookupValueIdxArray);
case NUMBER_EXP:
return numberValue;
case VARIABLE_EXP:
return ctx.getVariableValue(variableIdx);
case FOREIGN_VARIABLE_EXP:
return ctx.getForeignVariableValue(variableIdx);
case VARIABLE_GET_EXP:
return ctx.getLookupValue(lookupNameIdx);
case NOT_EXP:
return op1.evaluate(ctx) == 0.f ? 1.f : 0.f;
default:
throw new IllegalArgumentException("unknown op-code: " + typ);
}
}
private float max( float v1, float v2 )
{
private float max(float v1, float v2) {
return v1 > v2 ? v1 : v2;
}
private float min( float v1, float v2 )
{
private float min(float v1, float v2) {
return v1 < v2 ? v1 : v2;
}
}

View File

@ -25,8 +25,7 @@ import btools.util.IByteArrayUnifier;
import btools.util.LruMap;
public abstract class BExpressionContext implements IByteArrayUnifier
{
public abstract class BExpressionContext implements IByteArrayUnifier {
private static final String CONTEXT_TAG = "---context:";
private static final String MODEL_TAG = "---model:";
@ -76,15 +75,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
private BExpressionContext foreignContext;
protected void setInverseVars()
{
protected void setInverseVars() {
currentVarOffset = nBuildInVars;
}
abstract String[] getBuildInVariableNames();
public final float getBuildInVariable( int idx )
{
public final float getBuildInVariable(int idx) {
return currentVars[idx + currentVarOffset];
}
@ -93,8 +90,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
public BExpressionMetaData meta;
private boolean lookupDataValid = false;
protected BExpressionContext( String context, BExpressionMetaData meta )
{
protected BExpressionContext(String context, BExpressionMetaData meta) {
this(context, 4096, meta);
}
@ -104,8 +100,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
* @param context global, way or node - context of that instance
* @param hashSize size of hashmap for result caching
*/
protected BExpressionContext( String context, int hashSize, BExpressionMetaData meta )
{
protected BExpressionContext(String context, int hashSize, BExpressionMetaData meta) {
this.context = context;
this.meta = meta;
@ -114,8 +109,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
if (Boolean.getBoolean("disableExpressionCache")) hashSize = 1;
// create the expression cache
if ( hashSize > 0 )
{
if (hashSize > 0) {
cache = new LruMap(4 * hashSize, hashSize);
resultVarCache = new LruMap(4096, 4096);
}
@ -124,14 +118,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
/**
* encode internal lookup data to a byte array
*/
public byte[] encode()
{
if ( !lookupDataValid ) throw new IllegalArgumentException( "internal error: encoding undefined data?" );
public byte[] encode() {
if (!lookupDataValid)
throw new IllegalArgumentException("internal error: encoding undefined data?");
return encode(lookupData);
}
public byte[] encode( int[] ld )
{
public byte[] encode(int[] ld) {
BitCoderContext ctx = ctxEndode;
ctx.reset();
@ -144,8 +137,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
for (int inum = 1; inum < lookupValues.size(); inum++) // loop over lookup names
{
int d = ld[inum];
if ( d == 0 )
{
if (d == 0) {
skippedTags++;
continue;
}
@ -172,7 +164,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
decode(ld2, false, ab);
for (int inum = 1; inum < lookupValues.size(); inum++) // loop over lookup names (except reverse dir)
{
if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab) );
if (ld2[inum] != ld[inum])
throw new RuntimeException("assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab));
}
return ab;
@ -182,19 +175,16 @@ public abstract class BExpressionContext implements IByteArrayUnifier
/**
* decode byte array to internal lookup data
*/
public void decode( byte[] ab )
{
public void decode(byte[] ab) {
decode(lookupData, false, ab);
lookupDataValid = true;
}
/**
* decode a byte-array into a lookup data array
*/
private void decode( int[] ld, boolean inverseDirection, byte[] ab )
{
private void decode(int[] ld, boolean inverseDirection, byte[] ab) {
BitCoderContext ctx = ctxDecode;
ctx.reset(ab);
@ -203,8 +193,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
// all others are generic
int inum = 1;
for(;;)
{
for (; ; ) {
int delta = ctx.decodeVarBits();
if (delta == 0) break;
if (inum + delta > ld.length) break; // higher minor version is o.k.
@ -220,8 +209,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
while (inum < ld.length) ld[inum++] = 0;
}
public String getKeyValueDescription( boolean inverseDirection, byte[] ab )
{
public String getKeyValueDescription(boolean inverseDirection, byte[] ab) {
StringBuilder sb = new StringBuilder(200);
decode(lookupData, inverseDirection, ab);
for (int inum = 0; inum < lookupValues.size(); inum++) // loop over lookup names
@ -229,8 +217,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
BExpressionLookupValue[] va = lookupValues.get(inum);
int val = lookupData[inum];
String value = (val >= 1000) ? Float.toString((val - 1000) / 100f) : va[val].toString();
if ( value != null && value.length() > 0 )
{
if (value != null && value.length() > 0) {
if (sb.length() > 0) sb.append(' ');
sb.append(lookupNames.get(inum) + "=" + value);
}
@ -238,8 +225,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
return sb.toString();
}
public List<String> getKeyValueList( boolean inverseDirection, byte[] ab )
{
public List<String> getKeyValueList(boolean inverseDirection, byte[] ab) {
ArrayList<String> res = new ArrayList<String>();
decode(lookupData, inverseDirection, ab);
for (int inum = 0; inum < lookupValues.size(); inum++) // loop over lookup names
@ -248,8 +234,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
int val = lookupData[inum];
// no negative values
String value = (val >= 1000) ? Float.toString((val - 1000) / 100f) : va[val].toString();
if ( value != null && value.length() > 0 )
{
if (value != null && value.length() > 0) {
res.add(lookupNames.get(inum));
res.add(value);
}
@ -261,7 +246,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
int res = -1;
try {
res = lookupNumbers.get(name).intValue();
} catch (Exception e ) {}
} catch (Exception e) {
}
return res;
}
@ -285,8 +271,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
private int parsedLines = 0;
private boolean fixTagsWritten = false;
public void parseMetaLine( String line )
{
public void parseMetaLine(String line) {
parsedLines++;
StringTokenizer tk = new StringTokenizer(line, " ");
String name = tk.nextToken();
@ -294,8 +279,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
int idx = name.indexOf(';');
if (idx >= 0) name = name.substring(0, idx);
if ( !fixTagsWritten )
{
if (!fixTagsWritten) {
fixTagsWritten = true;
if ("way".equals(context)) addLookupValue("reversedirection", "yes", null);
else if ("node".equals(context)) addLookupValue("nodeaccessgranted", "yes", null);
@ -308,10 +292,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
while (newValue != null && tk.hasMoreTokens()) newValue.addAlias(tk.nextToken());
}
public void finishMetaParsing()
{
if ( parsedLines == 0 && !"global".equals(context) )
{
public void finishMetaParsing() {
if (parsedLines == 0 && !"global".equals(context)) {
throw new IllegalArgumentException("lookup table does not contain data for context " + context + " (old version?)");
}
@ -321,17 +303,14 @@ public abstract class BExpressionContext implements IByteArrayUnifier
lookupIdxUsed = new boolean[lookupValues.size()];
}
public final void evaluate( int[] lookupData2 )
{
public final void evaluate(int[] lookupData2) {
lookupData = lookupData2;
evaluate();
}
private void evaluate()
{
private void evaluate() {
int n = expressionList.size();
for( int expidx = 0; expidx < n; expidx++ )
{
for (int expidx = 0; expidx < n; expidx++) {
expressionList.get(expidx).evaluate(this);
}
}
@ -340,35 +319,28 @@ public abstract class BExpressionContext implements IByteArrayUnifier
private long requests2;
private long cachemisses;
public String cacheStats()
{
public String cacheStats() {
return "requests=" + requests + " requests2=" + requests2 + " cachemisses=" + cachemisses;
}
private CacheNode lastCacheNode = new CacheNode();
// @Override
public final byte[] unify( byte[] ab, int offset, int len )
{
public final byte[] unify(byte[] ab, int offset, int len) {
probeCacheNode.ab = null; // crc based cache lookup only
probeCacheNode.hash = Crc32.crc(ab, offset, len);
CacheNode cn = (CacheNode) cache.get(probeCacheNode);
if ( cn != null )
{
if (cn != null) {
byte[] cab = cn.ab;
if ( cab.length == len )
{
for( int i=0; i<len; i++ )
{
if ( cab[i] != ab[i+offset] )
{
if (cab.length == len) {
for (int i = 0; i < len; i++) {
if (cab[i] != ab[i + offset]) {
cn = null;
break;
}
}
if ( cn != null )
{
if (cn != null) {
lastCacheNode = cn;
return cn.ab;
}
@ -380,16 +352,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
}
public final void evaluate( boolean inverseDirection, byte[] ab )
{
public final void evaluate(boolean inverseDirection, byte[] ab) {
requests++;
lookupDataValid = false; // this is an assertion for a nasty pifall
if ( cache == null )
{
if (cache == null) {
decode(lookupData, inverseDirection, ab);
if ( currentVars == null || currentVars.length != nBuildInVars )
{
if (currentVars == null || currentVars.length != nBuildInVars) {
currentVars = new float[nBuildInVars];
}
evaluateInto(currentVars, 0);
@ -398,32 +367,26 @@ public abstract class BExpressionContext implements IByteArrayUnifier
}
CacheNode cn;
if ( lastCacheNode.ab == ab )
{
if (lastCacheNode.ab == ab) {
cn = lastCacheNode;
}
else
{
} else {
probeCacheNode.ab = ab;
probeCacheNode.hash = Crc32.crc(ab, 0, ab.length);
cn = (CacheNode) cache.get(probeCacheNode);
}
if ( cn == null )
{
if (cn == null) {
cachemisses++;
cn = (CacheNode) cache.removeLru();
if ( cn == null )
{
if (cn == null) {
cn = new CacheNode();
}
cn.hash = probeCacheNode.hash;
cn.ab = ab;
cache.put(cn);
if ( probeVarSet.vars == null )
{
if (probeVarSet.vars == null) {
probeVarSet.vars = new float[2 * nBuildInVars];
}
@ -439,11 +402,9 @@ public abstract class BExpressionContext implements IByteArrayUnifier
// unify the result variable set
VarWrapper vw = (VarWrapper) resultVarCache.get(probeVarSet);
if ( vw == null )
{
if (vw == null) {
vw = (VarWrapper) resultVarCache.removeLru();
if ( vw == null )
{
if (vw == null) {
vw = new VarWrapper();
}
vw.hash = probeVarSet.hash;
@ -452,9 +413,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
resultVarCache.put(vw);
}
cn.vars = vw.vars;
}
else
{
} else {
if (ab == cn.ab) requests2++;
cache.touch(cn);
@ -464,36 +423,30 @@ public abstract class BExpressionContext implements IByteArrayUnifier
currentVarOffset = inverseDirection ? nBuildInVars : 0;
}
private void evaluateInto( float[] vars, int offset )
{
private void evaluateInto(float[] vars, int offset) {
evaluate();
for ( int vi = 0; vi < nBuildInVars; vi++ )
{
for (int vi = 0; vi < nBuildInVars; vi++) {
int idx = buildInVariableIdx[vi];
vars[vi + offset] = idx == -1 ? 0.f : variableData[idx];
}
}
public void dumpStatistics()
{
public void dumpStatistics() {
TreeMap<String, String> counts = new TreeMap<String, String>();
// first count
for( String name: lookupNumbers.keySet() )
{
for (String name : lookupNumbers.keySet()) {
int cnt = 0;
int inum = lookupNumbers.get(name).intValue();
int[] histo = lookupHistograms.get(inum);
// if ( histo.length == 500 ) continue;
for( int i=2; i<histo.length; i++ )
{
for (int i = 2; i < histo.length; i++) {
cnt += histo[i];
}
counts.put("" + (1000000000 + cnt) + "_" + name, name);
}
while( counts.size() > 0 )
{
while (counts.size() > 0) {
String key = counts.lastEntry().getKey();
String name = counts.get(key);
counts.remove(key);
@ -502,15 +455,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
int[] histo = lookupHistograms.get(inum);
if (values.length == 1000) continue;
String[] svalues = new String[values.length];
for( int i=0; i<values.length; i++ )
{
for (int i = 0; i < values.length; i++) {
String scnt = "0000000000" + histo[i];
scnt = scnt.substring(scnt.length() - 10);
svalues[i] = scnt + " " + values[i].toString();
}
Arrays.sort(svalues);
for( int i=svalues.length-1; i>=0; i-- )
{
for (int i = svalues.length - 1; i >= 0; i--) {
System.out.println(name + ";" + svalues[i]);
}
}
@ -519,10 +470,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
/**
* @return a new lookupData array, or null if no metadata defined
*/
public int[] createNewLookupData()
{
if ( lookupDataFrozen )
{
public int[] createNewLookupData() {
if (lookupDataFrozen) {
return new int[lookupValues.size()];
}
return null;
@ -531,12 +480,10 @@ public abstract class BExpressionContext implements IByteArrayUnifier
/**
* generate random values for regression testing
*/
public int[] generateRandomValues( Random rnd )
{
public int[] generateRandomValues(Random rnd) {
int[] data = createNewLookupData();
data[0] = 2 * rnd.nextInt(2); // reverse-direction = 0 or 2
for( int inum = 1; inum < data.length; inum++ )
{
for (int inum = 1; inum < data.length; inum++) {
int nvalues = lookupValues.get(inum).length;
data[inum] = 0;
if (inum > 1 && rnd.nextInt(10) > 0) continue; // tags other than highway only 10%
@ -546,27 +493,21 @@ public abstract class BExpressionContext implements IByteArrayUnifier
return data;
}
public void assertAllVariablesEqual( BExpressionContext other )
{
public void assertAllVariablesEqual(BExpressionContext other) {
int nv = variableData.length;
int nv2 = other.variableData.length;
if (nv != nv2) throw new RuntimeException("mismatch in variable-count: " + nv + "<->" + nv2);
for( int i=0; i<nv; i++ )
{
if ( variableData[i] != other.variableData[i] )
{
for (int i = 0; i < nv; i++) {
if (variableData[i] != other.variableData[i]) {
throw new RuntimeException("mismatch in variable " + variableName(i) + " " + variableData[i] + "<->" + other.variableData[i]
+ "\ntags = " + getKeyValueDescription(false, encode()));
}
}
}
public String variableName( int idx )
{
for( Map.Entry<String,Integer> e : variableNumbers.entrySet() )
{
if ( e.getValue().intValue() == idx )
{
public String variableName(int idx) {
for (Map.Entry<String, Integer> e : variableNumbers.entrySet()) {
if (e.getValue().intValue() == idx) {
return e.getKey();
}
}
@ -581,14 +522,11 @@ public abstract class BExpressionContext implements IByteArrayUnifier
*
* @return a newly created value element, if any, to optionally add aliases
*/
public BExpressionLookupValue addLookupValue( String name, String value, int[] lookupData2 )
{
public BExpressionLookupValue addLookupValue(String name, String value, int[] lookupData2) {
BExpressionLookupValue newValue = null;
Integer num = lookupNumbers.get(name);
if ( num == null )
{
if ( lookupData2 != null )
{
if (num == null) {
if (lookupData2 != null) {
// do not create unknown name for external data array
return newValue;
}
@ -611,16 +549,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
int[] histo = lookupHistograms.get(inum);
int i = 0;
boolean bFoundAsterix = false;
for( ; i<values.length; i++ )
{
for (; i < values.length; i++) {
BExpressionLookupValue v = values[i];
if (v.equals("*")) bFoundAsterix = true;
if (v.matches(value)) break;
}
if ( i == values.length )
{
if ( lookupData2 != null )
{
if (i == values.length) {
if (lookupData2 != null) {
// do not create unknown value for external data array,
// record as 'unknown' instead
lookupData2[inum] = 1; // 1 == unknown
@ -666,58 +601,48 @@ public abstract class BExpressionContext implements IByteArrayUnifier
foot += inch / 12f;
}
value = String.format(Locale.US, "%3.1f", foot * 0.3048f);
}
else if (value.contains("in") || value.contains("\"")) {
} else if (value.contains("in") || value.contains("\"")) {
float inch = 0f;
if (value.indexOf("in") > 0) value = value.substring(0, value.indexOf("in"));
if (value.indexOf("\"") > 0) value = value.substring(0, value.indexOf("\""));
inch = Float.parseFloat(value.trim());
value = String.format(Locale.US, "%3.1f", inch * 0.0254f);
}
else if (value.toLowerCase().contains("feet") || value.toLowerCase().contains("foot")) {
} else if (value.toLowerCase().contains("feet") || value.toLowerCase().contains("foot")) {
float feet = 0f;
String s = value.substring(0, value.toLowerCase().indexOf("f"));
feet = Float.parseFloat(s.trim());
value = String.format(Locale.US, "%3.1f", feet * 0.3048f);
}
else if (value.toLowerCase().contains("fathom") || value.toLowerCase().contains("fm")) {
} else if (value.toLowerCase().contains("fathom") || value.toLowerCase().contains("fm")) {
float fathom = 0f;
String s = value.substring(0, value.toLowerCase().indexOf("f"));
fathom = Float.parseFloat(s.trim());
value = String.format(Locale.US, "%3.1f", fathom * 1.8288f);
}
else if (value.contains("cm")) {
} else if (value.contains("cm")) {
String[] sa = value.trim().split("cm");
if (sa.length == 1) value = sa[0].trim();
float cm = Float.parseFloat(value.trim());
value = String.format(Locale.US, "%3.1f", cm * 100f);
}
else if (value.toLowerCase().contains("meter")) {
} else if (value.toLowerCase().contains("meter")) {
String s = value.substring(0, value.toLowerCase().indexOf("m"));
value = s.trim();
}
else if (value.toLowerCase().contains("mph")) {
} else if (value.toLowerCase().contains("mph")) {
value = value.replace("_", "");
String[] sa = value.trim().toLowerCase().split("mph");
if (sa.length >= 1) value = sa[0].trim();
float mph = Float.parseFloat(value.trim());
value = String.format(Locale.US, "%3.1f", mph * 1.609344f);
}
else if (value.toLowerCase().contains("knot")) {
} else if (value.toLowerCase().contains("knot")) {
String[] sa = value.trim().toLowerCase().split("knot");
if (sa.length >= 1) value = sa[0].trim();
float nm = Float.parseFloat(value.trim());
value = String.format(Locale.US, "%3.1f", nm * 1.852f);
}
else if (value.contains("kmh") || value.contains("km/h") || value.contains("kph")) {
} else if (value.contains("kmh") || value.contains("km/h") || value.contains("kph")) {
String[] sa = value.trim().split("k");
if (sa.length == 1) value = sa[0].trim();
}
else if (value.contains("m")) {
} else if (value.contains("m")) {
String s = value.substring(0, value.toLowerCase().indexOf("m"));
value = s.trim();
}
else if (value.contains("(")) {
} else if (value.contains("(")) {
String s = value.substring(0, value.toLowerCase().indexOf("("));
value = s.trim();
}
@ -734,12 +659,10 @@ public abstract class BExpressionContext implements IByteArrayUnifier
return newValue;
}
if ( i == 499 )
{
if (i == 499) {
// System.out.println( "value limit reached for: " + name );
}
if ( i == 500 )
{
if (i == 500) {
return newValue;
}
// unknown value, create
@ -767,18 +690,17 @@ public abstract class BExpressionContext implements IByteArrayUnifier
* add a value-index to to internal array
* value-index means 0=unknown, 1=other, 2=value-x, ...
*/
public void addLookupValue( String name, int valueIndex )
{
public void addLookupValue(String name, int valueIndex) {
Integer num = lookupNumbers.get(name);
if ( num == null )
{
if (num == null) {
return;
}
// look for that value
int inum = num.intValue();
int nvalues = lookupValues.get(inum).length;
if ( valueIndex < 0 || valueIndex >= nvalues ) throw new IllegalArgumentException( "value index out of range for name " + name + ": " + valueIndex );
if (valueIndex < 0 || valueIndex >= nvalues)
throw new IllegalArgumentException("value index out of range for name " + name + ": " + valueIndex);
lookupData[inum] = valueIndex;
}
@ -789,11 +711,9 @@ public abstract class BExpressionContext implements IByteArrayUnifier
* add a 2=yes if the provided value is out of range
* value-index means here 0=unknown, 1=other, 2=yes, 3=proposed
*/
public void addSmallestLookupValue( String name, int valueIndex )
{
public void addSmallestLookupValue(String name, int valueIndex) {
Integer num = lookupNumbers.get(name);
if ( num == null )
{
if (num == null) {
return;
}
@ -801,42 +721,33 @@ public abstract class BExpressionContext implements IByteArrayUnifier
int inum = num.intValue();
int nvalues = lookupValues.get(inum).length;
int oldValueIndex = lookupData[inum];
if ( oldValueIndex > 1 && oldValueIndex < valueIndex )
{
if (oldValueIndex > 1 && oldValueIndex < valueIndex) {
return;
}
if ( valueIndex >= nvalues )
{
if (valueIndex >= nvalues) {
valueIndex = nvalues - 1;
}
if ( valueIndex < 0 ) throw new IllegalArgumentException( "value index out of range for name " + name + ": " + valueIndex );
if (valueIndex < 0)
throw new IllegalArgumentException("value index out of range for name " + name + ": " + valueIndex);
lookupData[inum] = valueIndex;
}
public boolean getBooleanLookupValue( String name )
{
public boolean getBooleanLookupValue(String name) {
Integer num = lookupNumbers.get(name);
return num != null && lookupData[num.intValue()] == 2;
}
public int getOutputVariableIndex( String name, boolean mustExist )
{
public int getOutputVariableIndex(String name, boolean mustExist) {
int idx = getVariableIdx(name, false);
if ( idx < 0 )
{
if ( mustExist )
{
if (idx < 0) {
if (mustExist) {
throw new IllegalArgumentException("unknown variable: " + name);
}
}
else if ( idx < minWriteIdx )
{
} else if (idx < minWriteIdx) {
throw new IllegalArgumentException("bad access to global variable: " + name);
}
for( int i=0; i<nBuildInVars; i++ )
{
if ( buildInVariableIdx[i] == idx )
{
for (int i = 0; i < nBuildInVars; i++) {
if (buildInVariableIdx[i] == idx) {
return i;
}
}
@ -847,35 +758,27 @@ public abstract class BExpressionContext implements IByteArrayUnifier
return nBuildInVars++;
}
public void setForeignContext( BExpressionContext foreignContext )
{
public void setForeignContext(BExpressionContext foreignContext) {
this.foreignContext = foreignContext;
}
public float getForeignVariableValue( int foreignIndex )
{
public float getForeignVariableValue(int foreignIndex) {
return foreignContext.getBuildInVariable(foreignIndex);
}
public int getForeignVariableIdx( String context, String name )
{
if ( foreignContext == null || !context.equals( foreignContext.context ) )
{
public int getForeignVariableIdx(String context, String name) {
if (foreignContext == null || !context.equals(foreignContext.context)) {
throw new IllegalArgumentException("unknown foreign context: " + context);
}
return foreignContext.getOutputVariableIndex(name, true);
}
public void parseFile( File file, String readOnlyContext )
{
if ( !file.exists() )
{
public void parseFile(File file, String readOnlyContext) {
if (!file.exists()) {
throw new IllegalArgumentException("profile " + file + " does not exist");
}
try
{
if ( readOnlyContext != null )
{
try {
if (readOnlyContext != null) {
linenr = 1;
String realContext = context;
context = readOnlyContext;
@ -893,40 +796,32 @@ public abstract class BExpressionContext implements IByteArrayUnifier
String[] varNames = getBuildInVariableNames();
nBuildInVars = varNames.length;
buildInVariableIdx = new int[nBuildInVars];
for( int vi=0; vi<varNames.length; vi++ )
{
for (int vi = 0; vi < varNames.length; vi++) {
buildInVariableIdx[vi] = getVariableIdx(varNames[vi], false);
}
float[] readOnlyData = variableData;
variableData = new float[variableNumbers.size()];
for( int i=0; i<minWriteIdx; i++ )
{
for (int i = 0; i < minWriteIdx; i++) {
variableData[i] = readOnlyData[i];
}
}
catch( Exception e )
{
if ( e instanceof IllegalArgumentException )
{
} catch (Exception e) {
if (e instanceof IllegalArgumentException) {
throw new IllegalArgumentException("ParseException " + file + " at line " + linenr + ": " + e.getMessage());
}
throw new RuntimeException(e);
}
if ( expressionList.size() == 0 )
{
if (expressionList.size() == 0) {
throw new IllegalArgumentException(file.getAbsolutePath()
+ " does not contain expressions for context " + context + " (old version?)");
}
}
private List<BExpression> _parseFile( File file ) throws Exception
{
private List<BExpression> _parseFile(File file) throws Exception {
_br = new BufferedReader(new FileReader(file));
_readerDone = false;
List<BExpression> result = new ArrayList<BExpression>();
for(;;)
{
for (; ; ) {
BExpression exp = BExpression.parse(this, 0);
if (exp == null) break;
result.add(exp);
@ -938,124 +833,95 @@ public abstract class BExpressionContext implements IByteArrayUnifier
public void setVariableValue(String name, float value, boolean create) {
Integer num = variableNumbers.get(name);
if ( num != null )
{
if (num != null) {
variableData[num.intValue()] = value;
}
}
public float getVariableValue( String name, float defaultValue )
{
public float getVariableValue(String name, float defaultValue) {
Integer num = variableNumbers.get(name);
return num == null ? defaultValue : getVariableValue(num.intValue());
}
float getVariableValue( int variableIdx )
{
float getVariableValue(int variableIdx) {
return variableData[variableIdx];
}
int getVariableIdx( String name, boolean create )
{
int getVariableIdx(String name, boolean create) {
Integer num = variableNumbers.get(name);
if ( num == null )
{
if ( create )
{
if (num == null) {
if (create) {
num = new Integer(variableNumbers.size());
variableNumbers.put(name, num);
}
else
{
} else {
return -1;
}
}
return num.intValue();
}
int getMinWriteIdx()
{
int getMinWriteIdx() {
return minWriteIdx;
}
float getLookupMatch( int nameIdx, int[] valueIdxArray )
{
for( int i=0; i<valueIdxArray.length; i++ )
{
if ( lookupData[nameIdx] == valueIdxArray[i] )
{
float getLookupMatch(int nameIdx, int[] valueIdxArray) {
for (int i = 0; i < valueIdxArray.length; i++) {
if (lookupData[nameIdx] == valueIdxArray[i]) {
return 1.0f;
}
}
return 0.0f;
}
public int getLookupNameIdx( String name )
{
public int getLookupNameIdx(String name) {
Integer num = lookupNumbers.get(name);
return num == null ? -1 : num.intValue();
}
public final void markLookupIdxUsed( int idx )
{
public final void markLookupIdxUsed(int idx) {
lookupIdxUsed[idx] = true;
}
public final boolean isLookupIdxUsed( int idx )
{
public final boolean isLookupIdxUsed(int idx) {
return idx < lookupIdxUsed.length ? lookupIdxUsed[idx] : false;
}
public final void setAllTagsUsed()
{
for( int i=0; i<lookupIdxUsed.length; i++ )
{
public final void setAllTagsUsed() {
for (int i = 0; i < lookupIdxUsed.length; i++) {
lookupIdxUsed[i] = true;
}
}
int getLookupValueIdx( int nameIdx, String value )
{
int getLookupValueIdx(int nameIdx, String value) {
BExpressionLookupValue[] values = lookupValues.get(nameIdx);
for( int i=0; i< values.length; i++ )
{
for (int i = 0; i < values.length; i++) {
if (values[i].equals(value)) return i;
}
return -1;
}
String parseToken() throws Exception
{
for(;;)
{
String parseToken() throws Exception {
for (; ; ) {
String token = _parseToken();
if (token == null) return null;
if ( token.startsWith( CONTEXT_TAG ) )
{
if (token.startsWith(CONTEXT_TAG)) {
_inOurContext = token.substring(CONTEXT_TAG.length()).equals(context);
}
else if ( token.startsWith( MODEL_TAG ) )
{
} else if (token.startsWith(MODEL_TAG)) {
_modelClass = token.substring(MODEL_TAG.length()).trim();
}
else if ( _inOurContext )
{
} else if (_inOurContext) {
return token;
}
}
}
private String _parseToken() throws Exception
{
private String _parseToken() throws Exception {
StringBuilder sb = new StringBuilder(32);
boolean inComment = false;
for(;;)
{
for (; ; ) {
int ic = _readerDone ? -1 : _br.read();
if ( ic < 0 )
{
if (ic < 0) {
if (sb.length() == 0) return null;
_readerDone = true;
return sb.toString();
@ -1063,13 +929,11 @@ public abstract class BExpressionContext implements IByteArrayUnifier
char c = (char) ic;
if (c == '\n') linenr++;
if ( inComment )
{
if (inComment) {
if (c == '\r' || c == '\n') inComment = false;
continue;
}
if ( Character.isWhitespace( c ) )
{
if (Character.isWhitespace(c)) {
if (sb.length() > 0) return sb.toString();
else continue;
}
@ -1078,8 +942,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
}
}
float assign( int variableIdx, float value )
{
float assign(int variableIdx, float value) {
variableData[variableIdx] = value;
return value;
}

View File

@ -7,22 +7,20 @@
package btools.expressions;
public final class BExpressionContextNode extends BExpressionContext
{
public final class BExpressionContextNode extends BExpressionContext {
private static String[] buildInVariables =
{"initialcost"};
protected String[] getBuildInVariableNames()
{
protected String[] getBuildInVariableNames() {
return buildInVariables;
}
public float getInitialcost() { return getBuildInVariable(0); }
public float getInitialcost() {
return getBuildInVariable(0);
}
public BExpressionContextNode( BExpressionMetaData meta )
{
public BExpressionContextNode(BExpressionMetaData meta) {
super("node", meta);
}
@ -31,8 +29,7 @@ public final class BExpressionContextNode extends BExpressionContext
*
* @param hashSize size of hashmap for result caching
*/
public BExpressionContextNode( int hashSize, BExpressionMetaData meta )
{
public BExpressionContextNode(int hashSize, BExpressionMetaData meta) {
super("node", hashSize, meta);
}
}

View File

@ -8,33 +8,65 @@ package btools.expressions;
import btools.codec.TagValueValidator;
public final class BExpressionContextWay extends BExpressionContext implements TagValueValidator
{
public final class BExpressionContextWay extends BExpressionContext implements TagValueValidator {
private boolean decodeForbidden = true;
private static String[] buildInVariables =
{"costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier", "trafficsourcedensity", "istrafficbackbone", "priorityclassifier", "classifiermask", "maxspeed"};
protected String[] getBuildInVariableNames()
{
protected String[] getBuildInVariableNames() {
return buildInVariables;
}
public float getCostfactor() { return getBuildInVariable(0); }
public float getTurncost() { return getBuildInVariable(1); }
public float getUphillCostfactor() { return getBuildInVariable(2); }
public float getDownhillCostfactor() { return getBuildInVariable(3); }
public float getInitialcost() { return getBuildInVariable(4); }
public float getNodeAccessGranted() { return getBuildInVariable(5); }
public float getInitialClassifier() { return getBuildInVariable(6); }
public float getTrafficSourceDensity() { return getBuildInVariable(7); }
public float getIsTrafficBackbone() { return getBuildInVariable(8); }
public float getPriorityClassifier() { return getBuildInVariable(9); }
public float getClassifierMask() { return getBuildInVariable(10); }
public float getMaxspeed() { return getBuildInVariable(11); }
public float getCostfactor() {
return getBuildInVariable(0);
}
public BExpressionContextWay( BExpressionMetaData meta )
{
public float getTurncost() {
return getBuildInVariable(1);
}
public float getUphillCostfactor() {
return getBuildInVariable(2);
}
public float getDownhillCostfactor() {
return getBuildInVariable(3);
}
public float getInitialcost() {
return getBuildInVariable(4);
}
public float getNodeAccessGranted() {
return getBuildInVariable(5);
}
public float getInitialClassifier() {
return getBuildInVariable(6);
}
public float getTrafficSourceDensity() {
return getBuildInVariable(7);
}
public float getIsTrafficBackbone() {
return getBuildInVariable(8);
}
public float getPriorityClassifier() {
return getBuildInVariable(9);
}
public float getClassifierMask() {
return getBuildInVariable(10);
}
public float getMaxspeed() {
return getBuildInVariable(11);
}
public BExpressionContextWay(BExpressionMetaData meta) {
super("way", meta);
}
@ -43,22 +75,18 @@ public final class BExpressionContextWay extends BExpressionContext implements T
*
* @param hashSize size of hashmap for result caching
*/
public BExpressionContextWay( int hashSize, BExpressionMetaData meta )
{
public BExpressionContextWay(int hashSize, BExpressionMetaData meta) {
super("way", hashSize, meta);
}
@Override
public int accessType( byte[] description )
{
public int accessType(byte[] description) {
evaluate(false, description);
float minCostFactor = getCostfactor();
if ( minCostFactor >= 9999.f )
{
if (minCostFactor >= 9999.f) {
setInverseVars();
float reverseCostFactor = getCostfactor();
if ( reverseCostFactor < minCostFactor )
{
if (reverseCostFactor < minCostFactor) {
minCostFactor = reverseCostFactor;
}
}
@ -66,8 +94,7 @@ public final class BExpressionContextWay extends BExpressionContext implements T
}
@Override
public void setDecodeForbidden( boolean decodeForbidden )
{
public void setDecodeForbidden(boolean decodeForbidden) {
this.decodeForbidden = decodeForbidden;
}
}

View File

@ -1,6 +1,6 @@
/**
* A lookup value with optional aliases
*
* <p>
* toString just gives the primary value,
* equals just compares against primary value
* matches() also compares aliases
@ -11,38 +11,31 @@ package btools.expressions;
import java.util.ArrayList;
final class BExpressionLookupValue
{
final class BExpressionLookupValue {
String value;
ArrayList<String> aliases;
@Override
public String toString()
{
public String toString() {
return value;
}
public BExpressionLookupValue( String value )
{
public BExpressionLookupValue(String value) {
this.value = value;
}
public void addAlias( String alias )
{
public void addAlias(String alias) {
if (aliases == null) aliases = new ArrayList<String>();
aliases.add(alias);
}
@Override
public boolean equals( Object o )
{
if ( o instanceof String )
{
public boolean equals(Object o) {
if (o instanceof String) {
String v = (String) o;
return value.equals(v);
}
if ( o instanceof BExpressionLookupValue )
{
if (o instanceof BExpressionLookupValue) {
BExpressionLookupValue v = (BExpressionLookupValue) o;
return value.equals(v.value);
@ -50,13 +43,10 @@ final class BExpressionLookupValue
return false;
}
public boolean matches( String s )
{
public boolean matches(String s) {
if (value.equals(s)) return true;
if ( aliases != null )
{
for( String alias : aliases )
{
if (aliases != null) {
for (String alias : aliases) {
if (alias.equals(s)) return true;
}
}

View File

@ -21,8 +21,7 @@ import btools.util.BitCoderContext;
import btools.util.Crc32;
public final class BExpressionMetaData
{
public final class BExpressionMetaData {
private static final String CONTEXT_TAG = "---context:";
private static final String VERSION_TAG = "---lookupversion:";
private static final String MINOR_VERSION_TAG = "---minorversion:";
@ -33,37 +32,30 @@ public final class BExpressionMetaData
private HashMap<String, BExpressionContext> listeners = new HashMap<String, BExpressionContext>();
public void registerListener( String context, BExpressionContext ctx )
{
public void registerListener(String context, BExpressionContext ctx) {
listeners.put(context, ctx);
}
public void readMetaData( File lookupsFile )
{
try
{
public void readMetaData(File lookupsFile) {
try {
BufferedReader br = new BufferedReader(new FileReader(lookupsFile));
BExpressionContext ctx = null;
for(;;)
{
for (; ; ) {
String line = br.readLine();
if (line == null) break;
line = line.trim();
if (line.length() == 0 || line.startsWith("#")) continue;
if ( line.startsWith( CONTEXT_TAG ) )
{
if (line.startsWith(CONTEXT_TAG)) {
ctx = listeners.get(line.substring(CONTEXT_TAG.length()));
continue;
}
if ( line.startsWith( VERSION_TAG ) )
{
if (line.startsWith(VERSION_TAG)) {
lookupVersion = Short.parseShort(line.substring(VERSION_TAG.length()));
continue;
}
if ( line.startsWith( MINOR_VERSION_TAG ) )
{
if (line.startsWith(MINOR_VERSION_TAG)) {
lookupMinorVersion = Short.parseShort(line.substring(MINOR_VERSION_TAG.length()));
continue;
}
@ -75,14 +67,11 @@ public final class BExpressionMetaData
}
br.close();
for( BExpressionContext c : listeners.values() )
{
for (BExpressionContext c : listeners.values()) {
c.finishMetaParsing();
}
}
catch( Exception e )
{
} catch (Exception e) {
throw new RuntimeException(e);
}
}

View File

@ -4,27 +4,22 @@ import java.util.Arrays;
import btools.util.LruMapNode;
public final class CacheNode extends LruMapNode
{
public final class CacheNode extends LruMapNode {
byte[] ab;
float[] vars;
@Override
public int hashCode()
{
public int hashCode() {
return hash;
}
@Override
public boolean equals( Object o )
{
public boolean equals(Object o) {
CacheNode n = (CacheNode) o;
if ( hash != n.hash )
{
if (hash != n.hash) {
return false;
}
if ( ab == null )
{
if (ab == null) {
return true; // hack: null = crc match only
}
return Arrays.equals(ab, n.ab);

View File

@ -3,12 +3,9 @@ package btools.expressions;
import java.io.File;
import java.util.Random;
public final class ProfileComparator
{
public static void main( String[] args )
{
if ( args.length != 4 )
{
public final class ProfileComparator {
public static void main(String[] args) {
if (args.length != 4) {
System.out.println("usage: java ProfileComparator <lookup-file> <profile1> <profile2> <nsamples>");
return;
}
@ -22,8 +19,7 @@ public final class ProfileComparator
}
private static void testContext( File lookupFile, File profile1File, File profile2File, int nsamples, boolean nodeContext )
{
private static void testContext(File lookupFile, File profile1File, File profile2File, int nsamples, boolean nodeContext) {
// read lookup.dat + profiles
BExpressionMetaData meta1 = new BExpressionMetaData();
BExpressionMetaData meta2 = new BExpressionMetaData();
@ -35,8 +31,7 @@ public final class ProfileComparator
expctx2.parseFile(profile2File, "global");
Random rnd = new Random();
for( int i=0; i<nsamples; i++ )
{
for (int i = 0; i < nsamples; i++) {
int[] data = expctx1.generateRandomValues(rnd);
expctx1.evaluate(data);
expctx2.evaluate(data);

View File

@ -4,22 +4,18 @@ import java.util.Arrays;
import btools.util.LruMapNode;
public final class VarWrapper extends LruMapNode
{
public final class VarWrapper extends LruMapNode {
float[] vars;
@Override
public int hashCode()
{
public int hashCode() {
return hash;
}
@Override
public boolean equals( Object o )
{
public boolean equals(Object o) {
VarWrapper n = (VarWrapper) o;
if ( hash != n.hash )
{
if (hash != n.hash) {
return false;
}
return Arrays.equals(vars, n.vars);

View File

@ -7,11 +7,9 @@ import java.net.URL;
import org.junit.Assert;
import org.junit.Test;
public class EncodeDecodeTest
{
public class EncodeDecodeTest {
@Test
public void encodeDecodeTest()
{
public void encodeDecodeTest() {
URL testpurl = this.getClass().getResource("/dummy.txt");
File workingDir = new File(testpurl.getFile()).getParentFile();
File profileDir = new File(workingDir, "/../../../../misc/profiles2");
@ -38,10 +36,10 @@ public class EncodeDecodeTest
// encode the tags into 64 bit description word
int[] lookupData = expctxWay.createNewLookupData();
for( String arg: tags )
{
for (String arg : tags) {
int idx = arg.indexOf('=');
if ( idx < 0 ) throw new IllegalArgumentException( "bad argument (should be <tag>=<value>): " + arg );
if (idx < 0)
throw new IllegalArgumentException("bad argument (should be <tag>=<value>): " + arg);
String key = arg.substring(0, idx);
String value = arg.substring(idx + 1);

View File

@ -11,8 +11,7 @@ import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ConvertLidarTile
{
public class ConvertLidarTile {
public static int NROWS;
public static int NCOLS;
@ -21,37 +20,28 @@ public class ConvertLidarTile
static short[] imagePixels;
private static void readHgtZip( String filename, int rowOffset, int colOffset ) throws Exception
{
private static void readHgtZip(String filename, int rowOffset, int colOffset) throws Exception {
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(filename)));
try
{
for ( ;; )
{
try {
for (; ; ) {
ZipEntry ze = zis.getNextEntry();
if ( ze.getName().endsWith( ".hgt" ) )
{
if (ze.getName().endsWith(".hgt")) {
readHgtFromStream(zis, rowOffset, colOffset);
return;
}
}
}
finally
{
} finally {
zis.close();
}
}
private static void readHgtFromStream(InputStream is, int rowOffset, int colOffset)
throws Exception
{
throws Exception {
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
for ( int ir = 0; ir < 1201; ir++ )
{
for (int ir = 0; ir < 1201; ir++) {
int row = rowOffset + ir;
for ( int ic = 0; ic < 1201; ic++ )
{
for (int ic = 0; ic < 1201; ic++) {
int col = colOffset + ic;
int i1 = dis.read(); // msb first!
@ -62,8 +52,7 @@ public class ConvertLidarTile
short val = (short) ((i1 << 8) | i0);
if ( val == NODATA2 )
{
if (val == NODATA2) {
val = NODATA;
}
@ -73,26 +62,21 @@ public class ConvertLidarTile
}
private static void setPixel( int row, int col, short val )
{
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
{
private static void setPixel(int row, int col, short val) {
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
imagePixels[row * NCOLS + col] = val;
}
}
private static short getPixel( int row, int col )
{
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
{
private static short getPixel(int row, int col) {
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
return imagePixels[row * NCOLS + col];
}
return NODATA;
}
public static void doConvert( String inputDir, int lonDegreeStart, int latDegreeStart, String outputFile ) throws Exception
{
public static void doConvert(String inputDir, int lonDegreeStart, int latDegreeStart, String outputFile) throws Exception {
int extraBorder = 0;
NROWS = 5 * 1200 + 1 + 2 * extraBorder;
@ -101,33 +85,26 @@ public class ConvertLidarTile
imagePixels = new short[NROWS * NCOLS]; // 650 MB !
// prefill as NODATA
for ( int row = 0; row < NROWS; row++ )
{
for ( int col = 0; col < NCOLS; col++ )
{
for (int row = 0; row < NROWS; row++) {
for (int col = 0; col < NCOLS; col++) {
imagePixels[row * NCOLS + col] = NODATA;
}
}
for ( int latIdx = -1; latIdx <= 5; latIdx++ )
{
for (int latIdx = -1; latIdx <= 5; latIdx++) {
int latDegree = latDegreeStart + latIdx;
int rowOffset = extraBorder + (4 - latIdx) * 1200;
for ( int lonIdx = -1; lonIdx <= 5; lonIdx++ )
{
for (int lonIdx = -1; lonIdx <= 5; lonIdx++) {
int lonDegree = lonDegreeStart + lonIdx;
int colOffset = extraBorder + lonIdx * 1200;
String filename = inputDir + "/" + formatLat(latDegree) + formatLon(lonDegree) + ".zip";
File f = new File(filename);
if ( f.exists() && f.length() > 0 )
{
if (f.exists() && f.length() > 0) {
System.out.println("exist: " + filename);
readHgtZip(filename, rowOffset, colOffset);
}
else
{
} else {
System.out.println("none : " + filename);
}
}
@ -161,29 +138,24 @@ public class ConvertLidarTile
throw new RuntimeException("length mismatch!");
// compare decoding result
for ( int row = 0; row < NROWS; row++ )
{
for (int row = 0; row < NROWS; row++) {
int colstep = halfCol5 ? 2 : 1;
for ( int col = 0; col < NCOLS; col += colstep )
{
for (int col = 0; col < NCOLS; col += colstep) {
int idx = row * NCOLS + col;
short p2 = pix2[idx];
if ( p2 != imagePixels[idx] )
{
if (p2 != imagePixels[idx]) {
throw new RuntimeException("content mismatch: p2=" + p2 + " p1=" + imagePixels[idx]);
}
}
}
}
private static String formatLon( int lon )
{
private static String formatLon(int lon) {
if (lon >= 180)
lon -= 180; // TODO: w180 oder E180 ?
String s = "E";
if ( lon < 0 )
{
if (lon < 0) {
lon = -lon;
s = "E";
}
@ -191,11 +163,9 @@ public class ConvertLidarTile
return s + n.substring(n.length() - 3);
}
private static String formatLat( int lat )
{
private static String formatLat(int lat) {
String s = "N";
if ( lat < 0 )
{
if (lat < 0) {
lat = -lat;
s = "S";
}
@ -203,8 +173,7 @@ public class ConvertLidarTile
return s + n.substring(n.length() - 2);
}
public static void main( String[] args ) throws Exception
{
public static void main(String[] args) throws Exception {
String filename90 = args[0];
String filename30 = filename90.substring(0, filename90.length() - 3) + "bef";

View File

@ -3,8 +3,7 @@ package btools.mapcreator;
import java.io.*;
import java.util.zip.*;
public class ConvertSrtmTile
{
public class ConvertSrtmTile {
public static int NROWS;
public static int NCOLS;
@ -16,43 +15,32 @@ public class ConvertSrtmTile
public static int[] diffs = new int[100];
private static void readBilZip( String filename, int rowOffset, int colOffset, boolean halfCols ) throws Exception
{
private static void readBilZip(String filename, int rowOffset, int colOffset, boolean halfCols) throws Exception {
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(filename)));
try
{
for ( ;; )
{
try {
for (; ; ) {
ZipEntry ze = zis.getNextEntry();
if ( ze.getName().endsWith( ".bil" ) )
{
if (ze.getName().endsWith(".bil")) {
readBilFromStream(zis, rowOffset, colOffset, halfCols);
return;
}
}
}
finally
{
} finally {
zis.close();
}
}
private static void readBilFromStream(InputStream is, int rowOffset, int colOffset, boolean halfCols)
throws Exception
{
throws Exception {
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
for ( int ir = 0; ir < 3601; ir++ )
{
for (int ir = 0; ir < 3601; ir++) {
int row = rowOffset + ir;
for ( int ic = 0; ic < 3601; ic++ )
{
for (int ic = 0; ic < 3601; ic++) {
int col = colOffset + ic;
if ( ( ic % 2 ) == 1 && halfCols )
{
if ( getPixel( row, col ) == NODATA )
{
if ((ic % 2) == 1 && halfCols) {
if (getPixel(row, col) == NODATA) {
setPixel(row, col, SKIPDATA);
}
continue;
@ -66,8 +54,7 @@ public class ConvertSrtmTile
short val = (short) ((i1 << 8) | i0);
if ( val == NODATA2 )
{
if (val == NODATA2) {
val = NODATA;
}
@ -77,26 +64,21 @@ public class ConvertSrtmTile
}
private static void setPixel( int row, int col, short val )
{
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
{
private static void setPixel(int row, int col, short val) {
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
imagePixels[row * NCOLS + col] = val;
}
}
private static short getPixel( int row, int col )
{
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
{
private static short getPixel(int row, int col) {
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
return imagePixels[row * NCOLS + col];
}
return NODATA;
}
public static void doConvert( String inputDir, String v1Dir, int lonDegreeStart, int latDegreeStart, String outputFile, SrtmRaster raster90 ) throws Exception
{
public static void doConvert(String inputDir, String v1Dir, int lonDegreeStart, int latDegreeStart, String outputFile, SrtmRaster raster90) throws Exception {
int extraBorder = 10;
int datacells = 0;
int mismatches = 0;
@ -107,34 +89,27 @@ public class ConvertSrtmTile
imagePixels = new short[NROWS * NCOLS]; // 650 MB !
// prefill as NODATA
for ( int row = 0; row < NROWS; row++ )
{
for ( int col = 0; col < NCOLS; col++ )
{
for (int row = 0; row < NROWS; row++) {
for (int col = 0; col < NCOLS; col++) {
imagePixels[row * NCOLS + col] = NODATA;
}
}
for ( int latIdx = -1; latIdx <= 5; latIdx++ )
{
for (int latIdx = -1; latIdx <= 5; latIdx++) {
int latDegree = latDegreeStart + latIdx;
int rowOffset = extraBorder + (4 - latIdx) * 3600;
for ( int lonIdx = -1; lonIdx <= 5; lonIdx++ )
{
for (int lonIdx = -1; lonIdx <= 5; lonIdx++) {
int lonDegree = lonDegreeStart + lonIdx;
int colOffset = extraBorder + lonIdx * 3600;
String filename = inputDir + "/" + formatLat(latDegree) + "_" + formatLon(lonDegree) + "_1arc_v3_bil.zip";
File f = new File(filename);
if ( f.exists() && f.length() > 0 )
{
if (f.exists() && f.length() > 0) {
System.out.println("exist: " + filename);
boolean halfCol = latDegree >= 50 || latDegree < -50;
readBilZip(filename, rowOffset, colOffset, halfCol);
}
else
{
} else {
System.out.println("none : " + filename);
}
}
@ -142,60 +117,46 @@ public class ConvertSrtmTile
boolean halfCol5 = latDegreeStart >= 50 || latDegreeStart < -50;
for ( int row90 = 0; row90 < 6001; row90++ )
{
for (int row90 = 0; row90 < 6001; row90++) {
int crow = 3 * row90 + extraBorder; // center row of 3x3
for ( int col90 = 0; col90 < 6001; col90++ )
{
for (int col90 = 0; col90 < 6001; col90++) {
int ccol = 3 * col90 + extraBorder; // center col of 3x3
// evaluate 3x3 area
if ( raster90 != null && (!halfCol5 || (col90 % 2) == 0 ) )
{
if (raster90 != null && (!halfCol5 || (col90 % 2) == 0)) {
short v90 = raster90.eval_array[row90 * 6001 + col90];
int sum = 0;
int nodatas = 0;
int datas = 0;
int colstep = halfCol5 ? 2 : 1;
for ( int row = crow - 1; row <= crow + 1; row++ )
{
for ( int col = ccol - colstep; col <= ccol + colstep; col += colstep )
{
for (int row = crow - 1; row <= crow + 1; row++) {
for (int col = ccol - colstep; col <= ccol + colstep; col += colstep) {
short v30 = imagePixels[row * NCOLS + col];
if ( v30 == NODATA )
{
if (v30 == NODATA) {
nodatas++;
}
else if ( v30 != SKIPDATA )
{
} else if (v30 != SKIPDATA) {
sum += v30;
datas++;
}
}
}
boolean doReplace = nodatas > 0 || v90 == NODATA || datas < 7;
if ( !doReplace )
{
if (!doReplace) {
datacells++;
int diff = sum - datas * v90;
if ( diff < -4 || diff > 4 )
{
if (diff < -4 || diff > 4) {
doReplace = true;
mismatches++;
}
if ( diff > -50 && diff < 50 && ( row90 % 1200 ) != 0 && ( col90 % 1200 ) != 0 )
{
if (diff > -50 && diff < 50 && (row90 % 1200) != 0 && (col90 % 1200) != 0) {
diffs[diff + 50]++;
}
}
if ( doReplace )
{
for ( int row = crow - 1; row <= crow + 1; row++ )
{
for ( int col = ccol - colstep; col <= ccol + colstep; col += colstep )
{
if (doReplace) {
for (int row = crow - 1; row <= crow + 1; row++) {
for (int col = ccol - colstep; col <= ccol + colstep; col += colstep) {
imagePixels[row * NCOLS + col] = v90;
}
}
@ -229,23 +190,18 @@ public class ConvertSrtmTile
throw new RuntimeException("length mismatch!");
// compare decoding result
for ( int row = 0; row < NROWS; row++ )
{
for (int row = 0; row < NROWS; row++) {
int colstep = halfCol5 ? 2 : 1;
for ( int col = 0; col < NCOLS; col += colstep )
{
for (int col = 0; col < NCOLS; col += colstep) {
int idx = row * NCOLS + col;
if ( imagePixels[idx] == SKIPDATA )
{
if (imagePixels[idx] == SKIPDATA) {
continue;
}
short p2 = pix2[idx];
if ( p2 > SKIPDATA )
{
if (p2 > SKIPDATA) {
p2 /= 2;
}
if ( p2 != imagePixels[idx] )
{
if (p2 != imagePixels[idx]) {
throw new RuntimeException("content mismatch!");
}
}
@ -260,16 +216,13 @@ btools.util.MixCoderDataOutputStream.stats();
// 39828330 &lon=3115280&layer=OpenStreetMap
}
private static void test( SrtmRaster raster )
{
private static void test(SrtmRaster raster) {
int lat0 = 39828330;
int lon0 = 3115280;
for ( int iy = -9; iy <= 9; iy++ )
{
for (int iy = -9; iy <= 9; iy++) {
StringBuilder sb = new StringBuilder();
for ( int ix = -9; ix <= 9; ix++ )
{
for (int ix = -9; ix <= 9; ix++) {
int lat = lat0 + 90000000 - 100 * iy;
int lon = lon0 + 180000000 + 100 * ix;
int ival = (int) (raster.getElevation(lon, lat) / 4.);
@ -281,14 +234,12 @@ btools.util.MixCoderDataOutputStream.stats();
}
}
private static String formatLon( int lon )
{
private static String formatLon(int lon) {
if (lon >= 180)
lon -= 180; // TODO: w180 oder E180 ?
String s = "e";
if ( lon < 0 )
{
if (lon < 0) {
lon = -lon;
s = "w";
}
@ -296,11 +247,9 @@ btools.util.MixCoderDataOutputStream.stats();
return s + n.substring(n.length() - 3);
}
private static String formatLat( int lat )
{
private static String formatLat(int lat) {
String s = "n";
if ( lat < 0 )
{
if (lat < 0) {
lat = -lat;
s = "s";
}

View File

@ -4,32 +4,26 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class ConvertUrlList
{
public class ConvertUrlList {
public static final short NODATA = -32767;
public static void main( String[] args ) throws Exception
{
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader(args[0]));
for ( ;; )
{
for (; ; ) {
String line = br.readLine();
if ( line == null )
{
if (line == null) {
break;
}
int idx1 = line.indexOf("srtm_");
if ( idx1 < 0 )
{
if (idx1 < 0) {
continue;
}
String filename90 = line.substring(idx1);
String filename30 = filename90.substring(0, filename90.length() - 3) + "bef";
if ( new File( filename30 ).exists() )
{
if (new File(filename30).exists()) {
continue;
}
@ -45,8 +39,7 @@ public class ConvertUrlList
SrtmRaster raster90 = null;
File file90 = new File(new File(args[1]), filename90);
if ( file90.exists() )
{
if (file90.exists()) {
System.out.println("reading " + file90);
raster90 = new SrtmData(file90).getRaster();
}

View File

@ -9,34 +9,28 @@ import java.util.ArrayList;
import btools.util.CheapRuler;
public class DPFilter
{
public class DPFilter {
private static double dp_sql_threshold = 0.4 * 0.4;
/*
* for each node (except first+last), eventually set the DP_SURVIVOR_BIT
*/
public static void doDPFilter( ArrayList<OsmNodeP> nodes )
{
public static void doDPFilter(ArrayList<OsmNodeP> nodes) {
int first = 0;
int last = nodes.size() - 1;
while( first < last && (nodes.get(first+1).bits & OsmNodeP.DP_SURVIVOR_BIT) != 0 )
{
while (first < last && (nodes.get(first + 1).bits & OsmNodeP.DP_SURVIVOR_BIT) != 0) {
first++;
}
while( first < last && (nodes.get(last-1).bits & OsmNodeP.DP_SURVIVOR_BIT) != 0 )
{
while (first < last && (nodes.get(last - 1).bits & OsmNodeP.DP_SURVIVOR_BIT) != 0) {
last--;
}
if ( last - first > 1 )
{
if (last - first > 1) {
doDPFilter(nodes, first, last);
}
}
public static void doDPFilter( ArrayList<OsmNodeP> nodes, int first, int last )
{
public static void doDPFilter(ArrayList<OsmNodeP> nodes, int first, int last) {
double maxSqDist = -1.;
int index = -1;
OsmNodeP p1 = nodes.get(first);
@ -48,36 +42,29 @@ public class DPFilter
double dx = (p2.ilon - p1.ilon) * dlon2m;
double dy = (p2.ilat - p1.ilat) * dlat2m;
double d2 = dx * dx + dy * dy;
for ( int i = first + 1; i < last; i++ )
{
for (int i = first + 1; i < last; i++) {
OsmNodeP p = nodes.get(i);
double t = 0.;
if ( d2 != 0f )
{
if (d2 != 0f) {
t = ((p.ilon - p1.ilon) * dlon2m * dx + (p.ilat - p1.ilat) * dlat2m * dy) / d2;
t = t > 1. ? 1. : (t < 0. ? 0. : t);
}
double dx2 = (p.ilon - (p1.ilon + t * (p2.ilon - p1.ilon))) * dlon2m;
double dy2 = (p.ilat - (p1.ilat + t * (p2.ilat - p1.ilat))) * dlat2m;
double sqDist = dx2 * dx2 + dy2 * dy2;
if ( sqDist > maxSqDist )
{
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if ( index >= 0 )
{
if ( index - first > 1 )
{
if (index >= 0) {
if (index - first > 1) {
doDPFilter(nodes, first, index);
}
if ( maxSqDist >= dp_sql_threshold )
{
if (maxSqDist >= dp_sql_threshold) {
nodes.get(index).bits |= OsmNodeP.DP_SURVIVOR_BIT;
}
if ( last - index > 1 )
{
if (last - index > 1) {
doDPFilter(nodes, index, last);
}
}

View File

@ -17,36 +17,30 @@ import java.util.HashMap;
import btools.util.DiffCoderDataOutputStream;
public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener
{
public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener {
private DiffCoderDataOutputStream[] tileOutStreams;
protected File outTileDir;
protected HashMap<String, String> tags;
public void putTag( String key, String value )
{
public void putTag(String key, String value) {
if (tags == null) tags = new HashMap<String, String>();
tags.put(key, value);
}
public String getTag( String key )
{
public String getTag(String key) {
return tags == null ? null : tags.get(key);
}
public HashMap<String,String> getTagsOrNull()
{
public HashMap<String, String> getTagsOrNull() {
return tags;
}
public void setTags( HashMap<String,String> tags )
{
public void setTags(HashMap<String, String> tags) {
this.tags = tags;
}
protected static long readId( DataInputStream is) throws IOException
{
protected static long readId(DataInputStream is) throws IOException {
int offset = is.readByte();
if (offset == 32) return -1;
long i = is.readInt();
@ -54,10 +48,8 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
return i | offset;
}
protected static void writeId( DataOutputStream o, long id ) throws IOException
{
if ( id == -1 )
{
protected static void writeId(DataOutputStream o, long id) throws IOException {
if (id == -1) {
o.writeByte(32);
return;
}
@ -68,20 +60,16 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
}
protected static File[] sortBySizeAsc( File[] files )
{
protected static File[] sortBySizeAsc(File[] files) {
int n = files.length;
long[] sizes = new long[n];
File[] sorted = new File[n];
for (int i = 0; i < n; i++) sizes[i] = files[i].length();
for(int nf=0; nf<n; nf++)
{
for (int nf = 0; nf < n; nf++) {
int idx = -1;
long min = -1;
for( int i=0; i<n; i++ )
{
if ( sizes[i] != -1 && ( idx == -1 || sizes[i] < min ) )
{
for (int i = 0; i < n; i++) {
if (sizes[i] != -1 && (idx == -1 || sizes[i] < min)) {
min = sizes[i];
idx = i;
}
@ -92,50 +80,40 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
return sorted;
}
protected File fileFromTemplate( File template, File dir, String suffix )
{
protected File fileFromTemplate(File template, File dir, String suffix) {
String filename = template.getName();
filename = filename.substring(0, filename.length() - 3) + suffix;
return new File(dir, filename);
}
protected DataInputStream createInStream( File inFile ) throws IOException
{
protected DataInputStream createInStream(File inFile) throws IOException {
return new DataInputStream(new BufferedInputStream(new FileInputStream(inFile)));
}
protected DiffCoderDataOutputStream createOutStream( File outFile ) throws IOException
{
protected DiffCoderDataOutputStream createOutStream(File outFile) throws IOException {
return new DiffCoderDataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
}
protected DiffCoderDataOutputStream getOutStreamForTile( int tileIndex ) throws Exception
{
if ( tileOutStreams == null )
{
protected DiffCoderDataOutputStream getOutStreamForTile(int tileIndex) throws Exception {
if (tileOutStreams == null) {
tileOutStreams = new DiffCoderDataOutputStream[64];
}
if ( tileOutStreams[tileIndex] == null )
{
if (tileOutStreams[tileIndex] == null) {
tileOutStreams[tileIndex] = createOutStream(new File(outTileDir, getNameForTile(tileIndex)));
}
return tileOutStreams[tileIndex];
}
protected String getNameForTile( int tileIndex )
{
protected String getNameForTile(int tileIndex) {
throw new IllegalArgumentException("getNameForTile not implemented");
}
protected void closeTileOutStreams() throws Exception
{
if ( tileOutStreams == null )
{
protected void closeTileOutStreams() throws Exception {
if (tileOutStreams == null) {
return;
}
for( int tileIndex=0; tileIndex<tileOutStreams.length; tileIndex++ )
{
for (int tileIndex = 0; tileIndex < tileOutStreams.length; tileIndex++) {
if (tileOutStreams[tileIndex] != null) tileOutStreams[tileIndex].close();
tileOutStreams[tileIndex] = null;
}
@ -145,27 +123,36 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
// interface dummys
@Override
public void nodeFileStart( File nodefile ) throws Exception {}
public void nodeFileStart(File nodefile) throws Exception {
}
@Override
public void nextNode( NodeData n ) throws Exception {}
public void nextNode(NodeData n) throws Exception {
}
@Override
public void nodeFileEnd( File nodefile ) throws Exception {}
public void nodeFileEnd(File nodefile) throws Exception {
}
@Override
public boolean wayFileStart( File wayfile ) throws Exception { return true; }
public boolean wayFileStart(File wayfile) throws Exception {
return true;
}
@Override
public void nextWay( WayData data ) throws Exception {}
public void nextWay(WayData data) throws Exception {
}
@Override
public void wayFileEnd( File wayfile ) throws Exception {}
public void wayFileEnd(File wayfile) throws Exception {
}
@Override
public void nextRelation( RelationData data ) throws Exception {}
public void nextRelation(RelationData data) throws Exception {
}
@Override
public void nextRestriction( RelationData data, long fromWid, long toWid, long viaNid ) throws Exception {}
public void nextRestriction(RelationData data, long fromWid, long toWid, long viaNid) throws Exception {
}
}

View File

@ -4,60 +4,51 @@ import java.io.File;
/**
* NodeCutter does 1 step in map-processing:
*
* <p>
* - cuts the 45*30 node tiles into 5*5 pieces
*
* @author ab
*/
public class NodeCutter extends MapCreatorBase
{
public class NodeCutter extends MapCreatorBase {
private int lonoffset;
private int latoffset;
public static void main(String[] args) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** NodeCutter: Cut big node-tiles into 5x5 tiles");
if (args.length != 2)
{
if (args.length != 2) {
System.out.println("usage: java NodeCutter <node-tiles-in> <node-tiles-out>");
return;
}
new NodeCutter().process(new File(args[0]), new File(args[1]));
}
public void init( File nodeTilesOut )
{
public void init(File nodeTilesOut) {
this.outTileDir = nodeTilesOut;
}
public void process( File nodeTilesIn, File nodeTilesOut ) throws Exception
{
public void process(File nodeTilesIn, File nodeTilesOut) throws Exception {
init(nodeTilesOut);
new NodeIterator(this, true).processDir(nodeTilesIn, ".tlf");
}
@Override
public void nodeFileStart( File nodefile ) throws Exception
{
public void nodeFileStart(File nodefile) throws Exception {
lonoffset = -1;
latoffset = -1;
}
@Override
public void nextNode( NodeData n ) throws Exception
{
public void nextNode(NodeData n) throws Exception {
n.writeTo(getOutStreamForTile(getTileIndex(n.ilon, n.ilat)));
}
@Override
public void nodeFileEnd( File nodeFile ) throws Exception
{
public void nodeFileEnd(File nodeFile) throws Exception {
closeTileOutStreams();
}
private int getTileIndex( int ilon, int ilat )
{
private int getTileIndex(int ilon, int ilat) {
int lonoff = (ilon / 45000000) * 45;
int latoff = (ilat / 30000000) * 30;
if (lonoffset == -1) lonoffset = lonoff;
@ -67,13 +58,13 @@ public class NodeCutter extends MapCreatorBase
int lon = (ilon / 5000000) % 9;
int lat = (ilat / 5000000) % 6;
if ( lon < 0 || lon > 8 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
if (lon < 0 || lon > 8 || lat < 0 || lat > 5)
throw new IllegalArgumentException("illegal pos: " + ilon + "," + ilat);
return lon * 6 + lat;
}
protected String getNameForTile( int tileIndex )
{
protected String getNameForTile(int tileIndex) {
int lon = (tileIndex / 6) * 5 + lonoffset - 180;
int lat = (tileIndex % 6) * 5 + latoffset - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;

View File

@ -8,39 +8,42 @@ import btools.util.DiffCoderDataOutputStream;
*
* @author ab
*/
public class NodeData extends MapCreatorBase
{
public class NodeData extends MapCreatorBase {
public long nid;
public int ilon;
public int ilat;
public byte[] description;
public short selev = Short.MIN_VALUE;
public NodeData( long id, double lon, double lat )
{
public NodeData(long id, double lon, double lat) {
nid = id;
ilat = (int) ((lat + 90.) * 1000000. + 0.5);
ilon = (int) ((lon + 180.) * 1000000. + 0.5);
}
public NodeData( DiffCoderDataInputStream dis ) throws Exception
{
public NodeData(DiffCoderDataInputStream dis) throws Exception {
nid = dis.readDiffed(0);
ilon = (int) dis.readDiffed(1);
ilat = (int) dis.readDiffed(2);
int mode = dis.readByte();
if ( ( mode & 1 ) != 0 ) { int dlen = dis.readShort(); description = new byte[dlen]; dis.readFully( description ); }
if ((mode & 1) != 0) {
int dlen = dis.readShort();
description = new byte[dlen];
dis.readFully(description);
}
if ((mode & 2) != 0) selev = dis.readShort();
}
public void writeTo( DiffCoderDataOutputStream dos ) throws Exception
{
public void writeTo(DiffCoderDataOutputStream dos) throws Exception {
dos.writeDiffed(nid, 0);
dos.writeDiffed(ilon, 1);
dos.writeDiffed(ilat, 2);
int mode = (description == null ? 0 : 1) | (selev == Short.MIN_VALUE ? 0 : 2);
dos.writeByte((byte) mode);
if ( ( mode & 1 ) != 0 ) { dos.writeShort( description.length ); dos.write( description ); }
if ((mode & 1) != 0) {
dos.writeShort(description.length);
dos.write(description);
}
if ((mode & 2) != 0) dos.writeShort(selev);
}
}

View File

@ -10,22 +10,19 @@ import btools.util.TinyDenseLongMap;
/**
* NodeFilter does 1 step in map-processing:
*
* <p>
* - filters out unused nodes according to the way file
*
* @author ab
*/
public class NodeFilter extends MapCreatorBase
{
public class NodeFilter extends MapCreatorBase {
private DiffCoderDataOutputStream nodesOutStream;
private File nodeTilesOut;
protected DenseLongMap nodebitmap;
public static void main(String[] args) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** NodeFilter: Filter way related nodes");
if (args.length != 3)
{
if (args.length != 3) {
System.out.println("usage: java NodeFilter <node-tiles-in> <way-file-in> <node-tiles-out>");
return;
}
@ -33,13 +30,11 @@ public class NodeFilter extends MapCreatorBase
new NodeFilter().process(new File(args[0]), new File(args[1]), new File(args[2]));
}
public void init() throws Exception
{
public void init() throws Exception {
nodebitmap = Boolean.getBoolean("useDenseMaps") ? new DenseLongMap(512) : new TinyDenseLongMap();
}
public void process( File nodeTilesIn, File wayFileIn, File nodeTilesOut ) throws Exception
{
public void process(File nodeTilesIn, File wayFileIn, File nodeTilesOut) throws Exception {
init();
this.nodeTilesOut = nodeTilesOut;
@ -52,41 +47,34 @@ public class NodeFilter extends MapCreatorBase
}
@Override
public void nextWay( WayData data ) throws Exception
{
public void nextWay(WayData data) throws Exception {
int nnodes = data.nodes.size();
for (int i=0; i<nnodes; i++ )
{
for (int i = 0; i < nnodes; i++) {
nodebitmap.put(data.nodes.get(i), 0);
}
}
@Override
public void nodeFileStart( File nodefile ) throws Exception
{
public void nodeFileStart(File nodefile) throws Exception {
String filename = nodefile.getName();
File outfile = new File(nodeTilesOut, filename);
nodesOutStream = new DiffCoderDataOutputStream(new BufferedOutputStream(new FileOutputStream(outfile)));
}
@Override
public void nextNode( NodeData n ) throws Exception
{
if ( isRelevant( n ) )
{
public void nextNode(NodeData n) throws Exception {
if (isRelevant(n)) {
n.writeTo(nodesOutStream);
}
}
public boolean isRelevant( NodeData n )
{
public boolean isRelevant(NodeData n) {
// check if node passes bitmap
return nodebitmap.getInt(n.nid) == 0; // 0 -> bit set, -1 -> unset
}
@Override
public void nodeFileEnd( File nodeFile ) throws Exception
{
public void nodeFileEnd(File nodeFile) throws Exception {
nodesOutStream.close();
}
}

View File

@ -13,58 +13,46 @@ import btools.util.DiffCoderDataInputStream;
*
* @author ab
*/
public class NodeIterator extends MapCreatorBase
{
public class NodeIterator extends MapCreatorBase {
private NodeListener listener;
private boolean delete;
public NodeIterator( NodeListener nodeListener, boolean deleteAfterReading )
{
public NodeIterator(NodeListener nodeListener, boolean deleteAfterReading) {
listener = nodeListener;
delete = deleteAfterReading;
}
public void processDir( File indir, String inSuffix ) throws Exception
{
if ( !indir.isDirectory() )
{
public void processDir(File indir, String inSuffix) throws Exception {
if (!indir.isDirectory()) {
throw new IllegalArgumentException("not a directory: " + indir);
}
File[] af = sortBySizeAsc(indir.listFiles());
for( int i=0; i<af.length; i++ )
{
for (int i = 0; i < af.length; i++) {
File nodefile = af[i];
if ( nodefile.getName().endsWith( inSuffix ) )
{
if (nodefile.getName().endsWith(inSuffix)) {
processFile(nodefile);
}
}
}
public void processFile(File nodefile) throws Exception
{
public void processFile(File nodefile) throws Exception {
System.out.println("*** NodeIterator reading: " + nodefile);
listener.nodeFileStart(nodefile);
DiffCoderDataInputStream di = new DiffCoderDataInputStream(new BufferedInputStream(new FileInputStream(nodefile)));
try
{
for(;;)
{
try {
for (; ; ) {
NodeData n = new NodeData(di);
listener.nextNode(n);
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
di.close();
}
listener.nodeFileEnd(nodefile);
if ( delete && "true".equals( System.getProperty( "deletetmpfiles" ) ))
{
if (delete && "true".equals(System.getProperty("deletetmpfiles"))) {
nodefile.delete();
}
}

View File

@ -7,8 +7,7 @@ import java.io.File;
*
* @author ab
*/
public interface NodeListener
{
public interface NodeListener {
void nodeFileStart(File nodefile) throws Exception;
void nextNode(NodeData data) throws Exception;

View File

@ -18,8 +18,7 @@ import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
import btools.expressions.BExpressionMetaData;
public class OsmCutter extends MapCreatorBase
{
public class OsmCutter extends MapCreatorBase {
private long recordCnt;
private long nodesParsed;
private long waysParsed;
@ -34,11 +33,9 @@ public class OsmCutter extends MapCreatorBase
public RestrictionCutter restrictionCutter;
public NodeFilter nodeFilter;
public static void main(String[] args) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** OsmCutter: cut an osm map in node-tiles + a way file");
if (args.length != 6 && args.length != 7)
{
if (args.length != 6 && args.length != 7) {
System.out.println("usage: bzip2 -dc <map> | java OsmCutter <lookup-file> <out-tile-dir> <out-way-file> <out-rel-file> <out-res-file> <filter-profile>");
System.out.println("or : java OsmCutter <lookup-file> <out-tile-dir> <out-way-file> <out-rel-file> <out-res-file> <filter-profile> <inputfile> ");
return;
@ -61,10 +58,8 @@ public class OsmCutter extends MapCreatorBase
// private BExpressionContextWay _expctxWayStat;
// private BExpressionContextNode _expctxNodeStat;
public void process (File lookupFile, File outTileDir, File wayFile, File relFile, File resFile, File profileFile, File mapFile ) throws Exception
{
if ( !lookupFile.exists() )
{
public void process(File lookupFile, File outTileDir, File wayFile, File relFile, File resFile, File profileFile, File mapFile) throws Exception {
if (!lookupFile.exists()) {
throw new IllegalArgumentException("lookup-file: " + lookupFile + " does not exist");
}
@ -80,12 +75,12 @@ public class OsmCutter extends MapCreatorBase
// _expctxNodeStat = new BExpressionContextNode( null );
this.outTileDir = outTileDir;
if ( !outTileDir.isDirectory() ) throw new RuntimeException( "out tile directory " + outTileDir + " does not exist" );
if (!outTileDir.isDirectory())
throw new RuntimeException("out tile directory " + outTileDir + " does not exist");
wayDos = wayFile == null ? null : new DataOutputStream(new BufferedOutputStream(new FileOutputStream(wayFile)));
cyclewayDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(relFile)));
if ( resFile != null )
{
if (resFile != null) {
restrictionsDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(resFile)));
}
@ -98,13 +93,11 @@ public class OsmCutter extends MapCreatorBase
// close all files
closeTileOutStreams();
if ( wayDos != null )
{
if (wayDos != null) {
wayDos.close();
}
cyclewayDos.close();
if ( restrictionsDos != null )
{
if (restrictionsDos != null) {
restrictionsDos.close();
}
@ -116,28 +109,23 @@ public class OsmCutter extends MapCreatorBase
System.out.println(statsLine());
}
private void checkStats()
{
private void checkStats() {
if ((++recordCnt % 100000) == 0) System.out.println(statsLine());
}
private String statsLine()
{
private String statsLine() {
return "records read: " + recordCnt + " nodes=" + nodesParsed + " ways=" + waysParsed + " rels=" + relsParsed + " changesets=" + changesetsParsed;
}
@Override
public void nextNode( NodeData n ) throws Exception
{
public void nextNode(NodeData n) throws Exception {
nodesParsed++;
checkStats();
if ( n.getTagsOrNull() != null )
{
if (n.getTagsOrNull() != null) {
int[] lookupData = _expctxNode.createNewLookupData();
for( Map.Entry<String,String> e : n.getTagsOrNull().entrySet() )
{
for (Map.Entry<String, String> e : n.getTagsOrNull().entrySet()) {
_expctxNode.addLookupValue(e.getKey(), e.getValue(), lookupData);
// _expctxNodeStat.addLookupValue( key, value, null );
}
@ -145,49 +133,40 @@ public class OsmCutter extends MapCreatorBase
}
// write node to file
int tileIndex = getTileIndex(n.ilon, n.ilat);
if ( tileIndex >= 0 )
{
if (tileIndex >= 0) {
n.writeTo(getOutStreamForTile(tileIndex));
if ( wayCutter != null )
{
if (wayCutter != null) {
wayCutter.nextNode(n);
}
}
}
private void generatePseudoTags( HashMap<String,String> map )
{
private void generatePseudoTags(HashMap<String, String> map) {
// add pseudo.tags for concrete:lanes and concrete:plates
String concrete = null;
for( Map.Entry<String,String> e : map.entrySet() )
{
for (Map.Entry<String, String> e : map.entrySet()) {
String key = e.getKey();
if ( "concrete".equals( key ) )
{
if ("concrete".equals(key)) {
return;
}
if ( "surface".equals( key ) )
{
if ("surface".equals(key)) {
String value = e.getValue();
if ( value.startsWith( "concrete:" ) )
{
if (value.startsWith("concrete:")) {
concrete = value.substring("concrete:".length());
}
}
}
if ( concrete != null )
{
if (concrete != null) {
map.put("concrete", concrete);
}
}
@Override
public void nextWay( WayData w ) throws Exception
{
public void nextWay(WayData w) throws Exception {
waysParsed++;
checkStats();
@ -197,8 +176,7 @@ public class OsmCutter extends MapCreatorBase
generatePseudoTags(w.getTagsOrNull());
int[] lookupData = _expctxWay.createNewLookupData();
for( String key : w.getTagsOrNull().keySet() )
{
for (String key : w.getTagsOrNull().keySet()) {
String value = w.getTag(key);
_expctxWay.addLookupValue(key, value.replace(' ', '_'), lookupData);
// _expctxWayStat.addLookupValue( key, value, null );
@ -214,30 +192,25 @@ public class OsmCutter extends MapCreatorBase
ok |= _expctxWay.getCostfactor() < 10000.;
if (!ok) return;
if ( wayDos != null )
{
if (wayDos != null) {
w.writeTo(wayDos);
}
if ( wayCutter != null )
{
if (wayCutter != null) {
wayCutter.nextWay(w);
}
if ( nodeFilter != null )
{
if (nodeFilter != null) {
nodeFilter.nextWay(w);
}
}
@Override
public void nextRelation( RelationData r ) throws Exception
{
public void nextRelation(RelationData r) throws Exception {
relsParsed++;
checkStats();
String route = r.getTag("route");
// filter out non-cycle relations
if ( route == null )
{
if (route == null) {
return;
}
@ -249,8 +222,7 @@ public class OsmCutter extends MapCreatorBase
cyclewayDos.writeUTF(route);
cyclewayDos.writeUTF(network);
cyclewayDos.writeUTF(state);
for ( int i=0; i<r.ways.size();i++ )
{
for (int i = 0; i < r.ways.size(); i++) {
long wid = r.ways.get(i);
writeId(cyclewayDos, wid);
}
@ -258,17 +230,14 @@ public class OsmCutter extends MapCreatorBase
}
@Override
public void nextRestriction( RelationData r, long fromWid, long toWid, long viaNid ) throws Exception
{
public void nextRestriction(RelationData r, long fromWid, long toWid, long viaNid) throws Exception {
String type = r.getTag("type");
if ( type == null || !"restriction".equals( type ) )
{
if (type == null || !"restriction".equals(type)) {
return;
}
short exceptions = 0;
String except = r.getTag("except");
if ( except != null )
{
if (except != null) {
exceptions |= toBit("bicycle", 0, except);
exceptions |= toBit("motorcar", 1, except);
exceptions |= toBit("agricultural", 2, except);
@ -277,10 +246,8 @@ public class OsmCutter extends MapCreatorBase
exceptions |= toBit("hgv", 4, except);
}
for( String restrictionKey : r.getTagsOrNull().keySet() )
{
if ( !( restrictionKey.equals( "restriction" ) || restrictionKey.startsWith( "restriction:" ) ) )
{
for (String restrictionKey : r.getTagsOrNull().keySet()) {
if (!(restrictionKey.equals("restriction") || restrictionKey.startsWith("restriction:"))) {
continue;
}
String restriction = r.getTag(restrictionKey);
@ -293,36 +260,30 @@ public class OsmCutter extends MapCreatorBase
res.toWid = toWid;
res.viaNid = viaNid;
if ( restrictionsDos != null )
{
if (restrictionsDos != null) {
res.writeTo(restrictionsDos);
}
if ( restrictionCutter != null )
{
if (restrictionCutter != null) {
restrictionCutter.nextRestriction(res);
}
}
}
private static short toBit( String tag, int bitpos, String s )
{
private static short toBit(String tag, int bitpos, String s) {
return (short) (s.indexOf(tag) < 0 ? 0 : 1 << bitpos);
}
private int getTileIndex( int ilon, int ilat )
{
private int getTileIndex(int ilon, int ilat) {
int lon = ilon / 45000000;
int lat = ilat / 30000000;
if ( lon < 0 || lon > 7 || lat < 0 || lat > 5 )
{
if (lon < 0 || lon > 7 || lat < 0 || lat > 5) {
System.out.println("warning: ignoring illegal pos: " + ilon + "," + ilat);
return -1;
}
return lon * 6 + lat;
}
protected String getNameForTile( int tileIndex )
{
protected String getNameForTile(int tileIndex) {
int lon = (tileIndex / 6) * 45 - 180;
int lat = (tileIndex % 6) * 30 - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;

View File

@ -9,13 +9,10 @@ package btools.mapcreator;
import java.io.File;
public class OsmFastCutter extends MapCreatorBase
{
public static void main(String[] args) throws Exception
{
public class OsmFastCutter extends MapCreatorBase {
public static void main(String[] args) throws Exception {
System.out.println("*** OsmFastCutter: cut an osm map in node-tiles + way-tiles");
if (args.length != 11 && args.length != 12)
{
if (args.length != 11 && args.length != 12) {
String common = "java OsmFastCutter <lookup-file> <node-dir> <way-dir> <node55-dir> <way55-dir> <border-file> <out-rel-file> <out-res-file> <filter-profile> <report-profile> <check-profile>";
System.out.println("usage: bzip2 -dc <map> | " + common);
@ -39,8 +36,7 @@ public class OsmFastCutter extends MapCreatorBase
);
}
public static void doCut (File lookupFile, File nodeDir, File wayDir, File node55Dir, File way55Dir, File borderFile, File relFile, File resFile, File profileAll, File profileReport, File profileCheck, File mapFile ) throws Exception
{
public static void doCut(File lookupFile, File nodeDir, File wayDir, File node55Dir, File way55Dir, File borderFile, File relFile, File resFile, File profileAll, File profileReport, File profileCheck, File mapFile) throws Exception {
// **** run OsmCutter ****
OsmCutter cutter = new OsmCutter();

View File

@ -6,8 +6,7 @@
package btools.mapcreator;
public class OsmLinkP
{
public class OsmLinkP {
/**
* The description bitmap is mainly the way description
* used to calculate the costfactor
@ -24,36 +23,27 @@ public class OsmLinkP
protected OsmLinkP next;
public OsmLinkP( OsmNodeP source, OsmNodeP target )
{
public OsmLinkP(OsmNodeP source, OsmNodeP target) {
sourceNode = source;
targetNode = target;
}
protected OsmLinkP()
{
protected OsmLinkP() {
}
public final boolean counterLinkWritten( )
{
public final boolean counterLinkWritten() {
return descriptionBitmap == null;
}
/**
* Set the relevant next-pointer for the given source
*/
public void setNext( OsmLinkP link, OsmNodeP source )
{
if ( sourceNode == source )
{
public void setNext(OsmLinkP link, OsmNodeP source) {
if (sourceNode == source) {
next = link;
}
else if ( targetNode == source )
{
} else if (targetNode == source) {
previous = link;
}
else
{
} else {
throw new IllegalArgumentException("internal error: setNext: unknown source");
}
}
@ -61,18 +51,12 @@ public class OsmLinkP
/**
* Get the relevant next-pointer for the given source
*/
public OsmLinkP getNext( OsmNodeP source )
{
if ( sourceNode == source )
{
public OsmLinkP getNext(OsmNodeP source) {
if (sourceNode == source) {
return next;
}
else if ( targetNode == source )
{
} else if (targetNode == source) {
return previous;
}
else
{
} else {
throw new IllegalArgumentException("internal error: gextNext: unknown source");
}
}
@ -80,18 +64,12 @@ public class OsmLinkP
/**
* Get the relevant target-node for the given source
*/
public OsmNodeP getTarget( OsmNodeP source )
{
if ( sourceNode == source )
{
public OsmNodeP getTarget(OsmNodeP source) {
if (sourceNode == source) {
return targetNode;
}
else if ( targetNode == source )
{
} else if (targetNode == source) {
return sourceNode;
}
else
{
} else {
throw new IllegalArgumentException("internal error: getTarget: unknown source");
}
}
@ -99,18 +77,12 @@ public class OsmLinkP
/**
* Check if reverse link for the given source
*/
public boolean isReverse( OsmNodeP source )
{
if ( sourceNode == source )
{
public boolean isReverse(OsmNodeP source) {
if (sourceNode == source) {
return false;
}
else if ( targetNode == source )
{
} else if (targetNode == source) {
return true;
}
else
{
} else {
throw new IllegalArgumentException("internal error: isReverse: unknown source");
}
}

View File

@ -12,8 +12,7 @@ import java.util.HashMap;
import btools.codec.MicroCache;
import btools.codec.MicroCache2;
public class OsmNodeP extends OsmLinkP
{
public class OsmNodeP extends OsmLinkP {
/**
* The latitude
*/
@ -40,33 +39,27 @@ public class OsmNodeP extends OsmLinkP
public byte bits = 0;
// interface OsmPos
public int getILat()
{
public int getILat() {
return ilat;
}
public int getILon()
{
public int getILon() {
return ilon;
}
public short getSElev()
{
public short getSElev() {
// if all bridge or all tunnel, elevation=no-data
return (bits & NO_BRIDGE_BIT) == 0 || (bits & NO_TUNNEL_BIT) == 0 ? Short.MIN_VALUE : selev;
}
public double getElev()
{
public double getElev() {
return selev / 4.;
}
// populate and return the inherited link, if available,
// else create a new one
public OsmLinkP createLink( OsmNodeP source )
{
if ( sourceNode == null && targetNode == null )
{
public OsmLinkP createLink(OsmNodeP source) {
if (sourceNode == null && targetNode == null) {
// inherited instance is available, use this
sourceNode = source;
targetNode = this;
@ -81,67 +74,52 @@ public class OsmNodeP extends OsmLinkP
// memory-squeezing-hack: OsmLinkP's "previous" also used as firstlink..
public void addLink( OsmLinkP link )
{
public void addLink(OsmLinkP link) {
link.setNext(previous, this);
previous = link;
}
public OsmLinkP getFirstLink()
{
public OsmLinkP getFirstLink() {
return sourceNode == null && targetNode == null ? previous : this;
}
public byte[] getNodeDecsription()
{
public byte[] getNodeDecsription() {
return null;
}
public RestrictionData getFirstRestriction()
{
public RestrictionData getFirstRestriction() {
return null;
}
public void writeNodeData( MicroCache mc, OsmTrafficMap trafficMap ) throws IOException
{
public void writeNodeData(MicroCache mc, OsmTrafficMap trafficMap) throws IOException {
boolean valid = true;
if ( mc instanceof MicroCache2 )
{
if (mc instanceof MicroCache2) {
valid = writeNodeData2((MicroCache2) mc, trafficMap);
}
else
} else
throw new IllegalArgumentException("unknown cache version: " + mc.getClass());
if ( valid )
{
if (valid) {
mc.finishNode(getIdFromPos());
}
else
{
} else {
mc.discardNode();
}
}
public void checkDuplicateTargets()
{
public void checkDuplicateTargets() {
HashMap<OsmNodeP, OsmLinkP> targets = new HashMap<OsmNodeP, OsmLinkP>();
for ( OsmLinkP link0 = getFirstLink(); link0 != null; link0 = link0.getNext( this ) )
{
for (OsmLinkP link0 = getFirstLink(); link0 != null; link0 = link0.getNext(this)) {
OsmLinkP link = link0;
OsmNodeP origin = this;
OsmNodeP target = null;
// first pass just to see if that link is consistent
while (link != null)
{
while (link != null) {
target = link.getTarget(origin);
if ( !target.isTransferNode() )
{
if (!target.isTransferNode()) {
break;
}
// next link is the one (of two), does does'nt point back
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
{
for (link = target.getFirstLink(); link != null; link = link.getNext(target)) {
if (link.getTarget(target) != origin)
break;
}
@ -149,34 +127,28 @@ public class OsmNodeP extends OsmLinkP
}
if (link == null) continue;
OsmLinkP oldLink = targets.put(target, link0);
if ( oldLink != null )
{
if (oldLink != null) {
unifyLink(oldLink);
unifyLink(link0);
}
}
}
private void unifyLink( OsmLinkP link )
{
private void unifyLink(OsmLinkP link) {
if (link.isReverse(this)) return;
OsmNodeP target = link.getTarget(this);
if ( target.isTransferNode() )
{
if (target.isTransferNode()) {
target.incWayCount();
}
}
public boolean writeNodeData2( MicroCache2 mc, OsmTrafficMap trafficMap ) throws IOException
{
public boolean writeNodeData2(MicroCache2 mc, OsmTrafficMap trafficMap) throws IOException {
boolean hasLinks = false;
// write turn restrictions
RestrictionData r = getFirstRestriction();
while( r != null )
{
if ( r.isValid() && r.fromLon != 0 && r.toLon != 0 )
{
while (r != null) {
if (r.isValid() && r.fromLon != 0 && r.toLon != 0) {
mc.writeBoolean(true); // restriction follows
mc.writeShort(r.exceptions);
mc.writeBoolean(r.isPositive());
@ -195,8 +167,7 @@ public class OsmNodeP extends OsmLinkP
// buffer internal reverse links
ArrayList<OsmNodeP> internalReverse = new ArrayList<OsmNodeP>();
for ( OsmLinkP link0 = getFirstLink(); link0 != null; link0 = link0.getNext( this ) )
{
for (OsmLinkP link0 = getFirstLink(); link0 != null; link0 = link0.getNext(this)) {
OsmLinkP link = link0;
OsmNodeP origin = this;
OsmNodeP target = null;
@ -205,24 +176,20 @@ public class OsmNodeP extends OsmLinkP
linkNodes.add(this);
// first pass just to see if that link is consistent
while (link != null)
{
while (link != null) {
target = link.getTarget(origin);
linkNodes.add(target);
if ( !target.isTransferNode() )
{
if (!target.isTransferNode()) {
break;
}
// next link is the one (of two), does does'nt point back
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
{
for (link = target.getFirstLink(); link != null; link = link.getNext(target)) {
if (link.getTarget(target) != origin)
break;
}
if ( link != null && link.descriptionBitmap != link0.descriptionBitmap )
{
if (link != null && link.descriptionBitmap != link0.descriptionBitmap) {
throw new IllegalArgumentException("assertion failed: description change along transfer nodes");
}
@ -236,10 +203,8 @@ public class OsmNodeP extends OsmLinkP
// internal reverse links later
boolean isReverse = link0.isReverse(this);
if ( isReverse )
{
if ( mc.isInternal( target.ilon, target.ilat ) )
{
if (isReverse) {
if (mc.isInternal(target.ilon, target.ilat)) {
internalReverse.add(target);
continue;
}
@ -247,8 +212,7 @@ public class OsmNodeP extends OsmLinkP
// add traffic simulation, if present
byte[] description = link0.descriptionBitmap;
if ( trafficMap != null )
{
if (trafficMap != null) {
description = trafficMap.addTrafficClass(linkNodes, description);
}
@ -261,11 +225,9 @@ public class OsmNodeP extends OsmLinkP
{
DPFilter.doDPFilter(linkNodes);
origin = this;
for( int i=1; i<linkNodes.size()-1; i++ )
{
for (int i = 1; i < linkNodes.size() - 1; i++) {
OsmNodeP tranferNode = linkNodes.get(i);
if ( ( tranferNode.bits & OsmNodeP.DP_SURVIVOR_BIT ) != 0 )
{
if ((tranferNode.bits & OsmNodeP.DP_SURVIVOR_BIT) != 0) {
mc.writeVarLengthSigned(tranferNode.ilon - origin.ilon);
mc.writeVarLengthSigned(tranferNode.ilat - origin.ilat);
mc.writeVarLengthSigned(tranferNode.getSElev() - origin.getSElev());
@ -276,17 +238,13 @@ public class OsmNodeP extends OsmLinkP
mc.injectSize(sizeoffset);
}
while (internalReverse.size() > 0)
{
while (internalReverse.size() > 0) {
int nextIdx = 0;
if ( internalReverse.size() > 1 )
{
if (internalReverse.size() > 1) {
int max32 = Integer.MIN_VALUE;
for ( int i = 0; i < internalReverse.size(); i++ )
{
for (int i = 0; i < internalReverse.size(); i++) {
int id32 = mc.shrinkId(internalReverse.get(i).getIdFromPos());
if ( id32 > max32 )
{
if (id32 > max32) {
max32 = id32;
nextIdx = i;
}
@ -302,49 +260,40 @@ public class OsmNodeP extends OsmLinkP
return hasLinks;
}
public String toString2()
{
public String toString2() {
return (ilon - 180000000) + "_" + (ilat - 90000000) + "_" + (selev / 4);
}
public long getIdFromPos()
{
public long getIdFromPos() {
return ((long) ilon) << 32 | ilat;
}
public boolean isBorderNode()
{
public boolean isBorderNode() {
return (bits & BORDER_BIT) != 0;
}
public boolean hasTraffic()
{
public boolean hasTraffic() {
return (bits & TRAFFIC_BIT) != 0;
}
/**
* Not really count the ways, just detect if more than one
*/
public void incWayCount()
{
if ( ( bits & ANY_WAY_BIT ) != 0 )
{
public void incWayCount() {
if ((bits & ANY_WAY_BIT) != 0) {
bits |= MULTI_WAY_BIT;
}
bits |= ANY_WAY_BIT;
}
public boolean isTransferNode()
{
public boolean isTransferNode() {
return (bits & BORDER_BIT) == 0 && (bits & MULTI_WAY_BIT) == 0 && _linkCnt() == 2;
}
private int _linkCnt()
{
private int _linkCnt() {
int cnt = 0;
for ( OsmLinkP link = getFirstLink(); link != null; link = link.getNext( this ) )
{
for (OsmLinkP link = getFirstLink(); link != null; link = link.getNext(this)) {
cnt++;
}
return cnt;

View File

@ -6,44 +6,37 @@
package btools.mapcreator;
public class OsmNodePT extends OsmNodeP
{
public class OsmNodePT extends OsmNodeP {
public byte[] descriptionBits;
public RestrictionData firstRestriction;
public OsmNodePT()
{
public OsmNodePT() {
}
public OsmNodePT( OsmNodeP n )
{
public OsmNodePT(OsmNodeP n) {
ilat = n.ilat;
ilon = n.ilon;
selev = n.selev;
bits = n.bits;
}
public OsmNodePT( byte[] descriptionBits )
{
public OsmNodePT(byte[] descriptionBits) {
this.descriptionBits = descriptionBits;
}
@Override
public final byte[] getNodeDecsription()
{
public final byte[] getNodeDecsription() {
return descriptionBits;
}
@Override
public final RestrictionData getFirstRestriction()
{
public final RestrictionData getFirstRestriction() {
return firstRestriction;
}
@Override
public boolean isTransferNode()
{
public boolean isTransferNode() {
return false; // always have descriptionBits so never transfernode
}

View File

@ -11,8 +11,7 @@ import java.util.zip.GZIPInputStream;
*
* @author ab
*/
public class OsmParser extends MapCreatorBase
{
public class OsmParser extends MapCreatorBase {
private BufferedReader _br;
private NodeListener nListener;
@ -22,31 +21,23 @@ public class OsmParser extends MapCreatorBase
public void readMap(File mapFile,
NodeListener nListener,
WayListener wListener,
RelationListener rListener ) throws Exception
{
RelationListener rListener) throws Exception {
this.nListener = nListener;
this.wListener = wListener;
this.rListener = rListener;
if ( mapFile == null )
{
if (mapFile == null) {
_br = new BufferedReader(new InputStreamReader(System.in));
}
else
{
if ( mapFile.getName().endsWith( ".gz" ) )
{
} else {
if (mapFile.getName().endsWith(".gz")) {
_br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(mapFile))));
}
else
{
} else {
_br = new BufferedReader(new InputStreamReader(new FileInputStream(mapFile)));
}
}
for(;;)
{
for (; ; ) {
String line = _br.readLine();
if (line == null) break;
@ -56,15 +47,13 @@ public class OsmParser extends MapCreatorBase
if (checkChangeset(line)) continue;
}
if ( mapFile != null )
{
if (mapFile != null) {
_br.close();
}
}
private boolean checkNode( String line ) throws Exception
{
private boolean checkNode(String line) throws Exception {
int idx0 = line.indexOf("<node id=\"");
if (idx0 < 0) return false;
idx0 += 10;
@ -85,32 +74,26 @@ public class OsmParser extends MapCreatorBase
NodeData n = new NodeData(nodeId, lon, lat);
if ( !line.endsWith( "/>" ) )
{
if (!line.endsWith("/>")) {
// read additional tags
for(;;)
{
for (; ; ) {
String l2 = _br.readLine();
if (l2 == null) return false;
int i2;
if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
{ // property-tag
if ((i2 = l2.indexOf("<tag k=\"")) >= 0) { // property-tag
i2 += 8;
int ri2 = l2.indexOf('"', i2);
String key = l2.substring(i2, ri2);
i2 = l2.indexOf(" v=\"", ri2);
if ( i2 >= 0 )
{
if (i2 >= 0) {
i2 += 4;
int ri3 = l2.indexOf('"', i2);
String value = l2.substring(i2, ri3);
n.putTag(key, value);
}
}
else if ( l2.indexOf( "</node>" ) >= 0 )
{ // end-tag
} else if (l2.indexOf("</node>") >= 0) { // end-tag
break;
}
}
@ -120,8 +103,7 @@ public class OsmParser extends MapCreatorBase
}
private boolean checkWay( String line ) throws Exception
{
private boolean checkWay(String line) throws Exception {
int idx0 = line.indexOf("<way id=\"");
if (idx0 < 0) return false;
@ -132,35 +114,28 @@ public class OsmParser extends MapCreatorBase
WayData w = new WayData(id);
// read the nodes
for(;;)
{
for (; ; ) {
String l2 = _br.readLine();
if (l2 == null) return false;
int i2;
if ( (i2 = l2.indexOf( "<nd ref=\"" )) >= 0 )
{ // node reference
if ((i2 = l2.indexOf("<nd ref=\"")) >= 0) { // node reference
i2 += 9;
int ri2 = l2.indexOf('"', i2);
long nid = Long.parseLong(l2.substring(i2, ri2));
w.nodes.add(nid);
}
else if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
{ // property-tag
} else if ((i2 = l2.indexOf("<tag k=\"")) >= 0) { // property-tag
i2 += 8;
int ri2 = l2.indexOf('"', i2);
String key = l2.substring(i2, ri2);
i2 = l2.indexOf(" v=\"", ri2);
if ( i2 >= 0 )
{
if (i2 >= 0) {
i2 += 4;
int ri3 = l2.indexOf('"', i2);
String value = l2.substring(i2, ri3);
w.putTag(key, value);
}
}
else if ( l2.indexOf( "</way>" ) >= 0 )
{ // end-tag
} else if (l2.indexOf("</way>") >= 0) { // end-tag
break;
}
}
@ -168,16 +143,13 @@ public class OsmParser extends MapCreatorBase
return true;
}
private boolean checkChangeset( String line ) throws Exception
{
private boolean checkChangeset(String line) throws Exception {
int idx0 = line.indexOf("<changeset id=\"");
if (idx0 < 0) return false;
if ( !line.endsWith( "/>" ) )
{
if (!line.endsWith("/>")) {
int loopcheck = 0;
for(;;)
{
for (; ; ) {
String l2 = _br.readLine();
if (l2.indexOf("</changeset>") >= 0 || ++loopcheck > 10000) break;
}
@ -185,8 +157,7 @@ public class OsmParser extends MapCreatorBase
return true;
}
private boolean checkRelation( String line ) throws Exception
{
private boolean checkRelation(String line) throws Exception {
int idx0 = line.indexOf("<relation id=\"");
if (idx0 < 0) return false;
@ -197,35 +168,28 @@ public class OsmParser extends MapCreatorBase
RelationData r = new RelationData(rid);
// read the nodes
for(;;)
{
for (; ; ) {
String l2 = _br.readLine();
if (l2 == null) return false;
int i2;
if ( (i2 = l2.indexOf( "<member type=\"way\" ref=\"" )) >= 0 )
{ // node reference
if ((i2 = l2.indexOf("<member type=\"way\" ref=\"")) >= 0) { // node reference
i2 += 24;
int ri2 = l2.indexOf('"', i2);
long wid = Long.parseLong(l2.substring(i2, ri2));
r.ways.add(wid);
}
else if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
{ // property-tag
} else if ((i2 = l2.indexOf("<tag k=\"")) >= 0) { // property-tag
i2 += 8;
int ri2 = l2.indexOf('"', i2);
String key = l2.substring(i2, ri2);
i2 = l2.indexOf(" v=\"", ri2);
if ( i2 >= 0 )
{
if (i2 >= 0) {
i2 += 4;
int ri3 = l2.indexOf('"', i2);
String value = l2.substring(i2, ri3);
r.putTag(key, value);
}
}
else if ( l2.indexOf( "</relation>" ) >= 0 )
{ // end-tag
} else if (l2.indexOf("</relation>") >= 0) { // end-tag
break;
}
}

View File

@ -22,8 +22,7 @@ import btools.util.CompactLongMap;
import btools.util.FrozenLongMap;
public class OsmTrafficMap
{
public class OsmTrafficMap {
int minLon;
int minLat;
int maxLon;
@ -42,14 +41,12 @@ public class OsmTrafficMap
private boolean doNotAdd = false;
private boolean debug = false;
public OsmTrafficMap( BExpressionContextWay expctxWay )
{
public OsmTrafficMap(BExpressionContextWay expctxWay) {
this.expctxWay = expctxWay;
debug = Boolean.getBoolean("debugTrafficMap");
}
public static class OsmTrafficElement
{
public static class OsmTrafficElement {
public long node2;
public int traffic;
public OsmTrafficElement next;
@ -57,14 +54,12 @@ public class OsmTrafficMap
private CompactLongMap<OsmTrafficElement> map = new CompactLongMap<OsmTrafficElement>();
public void loadAll( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception
{
public void loadAll(File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways) throws Exception {
load(file, minLon, minLat, maxLon, maxLat, includeMotorways);
// check for old traffic data
oldTrafficFile = new File(file.getParentFile(), file.getName() + "_old");
if ( oldTrafficFile.exists() )
{
if (oldTrafficFile.exists()) {
oldTrafficClasses = new OsmTrafficMap(null);
oldTrafficClasses.doNotAdd = true;
oldTrafficClasses.load(oldTrafficFile, minLon, minLat, maxLon, maxLat, false);
@ -75,10 +70,8 @@ public class OsmTrafficMap
newTrafficDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newTrafficFile)));
}
public void finish() throws Exception
{
if ( newTrafficDos != null )
{
public void finish() throws Exception {
if (newTrafficDos != null) {
newTrafficDos.close();
newTrafficDos = null;
oldTrafficFile.delete();
@ -87,8 +80,7 @@ public class OsmTrafficMap
}
}
public void load( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception
{
public void load(File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways) throws Exception {
this.minLon = minLon;
this.minLat = minLat;
this.maxLon = maxLon;
@ -96,86 +88,70 @@ public class OsmTrafficMap
int trafficElements = 0;
DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
try
{
for(;;)
{
try {
for (; ; ) {
long n1 = is.readLong();
long n2 = is.readLong();
int traffic = is.readInt();
if ( traffic == -1 && !includeMotorways )
{
if (traffic == -1 && !includeMotorways) {
continue;
}
if ( isInsideBounds( n1 ) || isInsideBounds( n2 ) )
{
if ( addElement( n1, n2, traffic ) )
{
if (isInsideBounds(n1) || isInsideBounds(n2)) {
if (addElement(n1, n2, traffic)) {
trafficElements++;
}
}
}
} catch (EOFException eof) {
} finally {
is.close();
}
catch( EOFException eof ) {}
finally{ is.close(); }
map = new FrozenLongMap<OsmTrafficElement>(map);
System.out.println("read traffic-elements: " + trafficElements);
}
public boolean addElement( long n1, long n2, int traffic )
{
public boolean addElement(long n1, long n2, int traffic) {
OsmTrafficElement e = getElement(n1, n2);
if ( e == null )
{
if (e == null) {
e = new OsmTrafficElement();
e.node2 = n2;
e.traffic = traffic;
OsmTrafficElement e0 = map.get(n1);
if ( e0 != null )
{
while( e0.next != null )
{
if (e0 != null) {
while (e0.next != null) {
e0 = e0.next;
}
e0.next = e;
}
else
{
} else {
map.fastPut(n1, e);
}
return true;
}
if ( doNotAdd )
{
if (doNotAdd) {
e.traffic = Math.max(e.traffic, traffic);
}
else
{
} else {
e.traffic = e.traffic == -1 || traffic == -1 ? -1 : e.traffic + traffic;
}
return false;
}
private boolean isInsideBounds( long id )
{
private boolean isInsideBounds(long id) {
int ilon = (int) (id >> 32);
int ilat = (int) (id & 0xffffffff);
return ilon >= minLon && ilon < maxLon && ilat >= minLat && ilat < maxLat;
}
public int getTrafficClass( long n1, long n2 )
{
public int getTrafficClass(long n1, long n2) {
// used for the old data, where we stpre traffic-classes, not volumes
OsmTrafficElement e = getElement(n1, n2);
return e == null ? 0 : e.traffic;
}
public int getTrafficClassForTraffic( int traffic )
{
public int getTrafficClassForTraffic(int traffic) {
if (traffic < 0) return -1;
if (traffic < 40000) return 0;
if (traffic < 80000) return 2;
@ -186,8 +162,7 @@ public class OsmTrafficMap
return 7;
}
private int getTraffic( long n1, long n2 )
{
private int getTraffic(long n1, long n2) {
OsmTrafficElement e1 = getElement(n1, n2);
int traffic1 = e1 == null ? 0 : e1.traffic;
OsmTrafficElement e2 = getElement(n2, n1);
@ -195,17 +170,13 @@ public class OsmTrafficMap
return traffic1 == -1 || traffic2 == -1 ? -1 : traffic1 > traffic2 ? traffic1 : traffic2;
}
public void freeze()
{
public void freeze() {
}
private OsmTrafficElement getElement( long n1, long n2 )
{
private OsmTrafficElement getElement(long n1, long n2) {
OsmTrafficElement e = map.get(n1);
while( e != null )
{
if ( e.node2 == n2 )
{
while (e != null) {
if (e.node2 == n2) {
return e;
}
e = e.next;
@ -213,18 +184,15 @@ public class OsmTrafficMap
return null;
}
public OsmTrafficElement getElement( long n )
{
public OsmTrafficElement getElement(long n) {
return map.get(n);
}
public byte[] addTrafficClass( ArrayList<OsmNodeP> linkNodes, byte[] description ) throws IOException
{
public byte[] addTrafficClass(ArrayList<OsmNodeP> linkNodes, byte[] description) throws IOException {
double distance = 0.;
double sum = 0.;
for( int i=0; i<linkNodes.size()-1; i++ )
{
for (int i = 0; i < linkNodes.size() - 1; i++) {
OsmNodeP n1 = linkNodes.get(i);
OsmNodeP n2 = linkNodes.get(i + 1);
int traffic = getTraffic(n1.getIdFromPos(), n2.getIdFromPos());
@ -233,8 +201,7 @@ public class OsmTrafficMap
sum += dist * traffic;
}
if ( distance == 0. )
{
if (distance == 0.) {
return description;
}
int traffic = (int) (sum / distance + 0.5);
@ -245,30 +212,25 @@ public class OsmTrafficMap
int trafficClass = getTrafficClassForTraffic(traffic);
// delta suppression: keep old traffic classes within some buffer range
if ( oldTrafficClasses != null )
{
if (oldTrafficClasses != null) {
int oldTrafficClass = oldTrafficClasses.getTrafficClass(id0, id1);
if ( oldTrafficClass != trafficClass )
{
if (oldTrafficClass != trafficClass) {
totalChanges++;
boolean supressChange =
oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 1.3))
|| oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 0.77));
if ( debug )
{
if (debug) {
System.out.println("traffic class change " + oldTrafficClass + "->" + trafficClass + " supress=" + supressChange);
}
if ( supressChange )
{
if (supressChange) {
trafficClass = oldTrafficClass;
supressedChanges++;
}
}
}
if ( trafficClass > 0 )
{
if (trafficClass > 0) {
newTrafficDos.writeLong(id0);
newTrafficDos.writeLong(id1);
newTrafficDos.writeInt(trafficClass);

View File

@ -14,14 +14,13 @@ import btools.util.FrozenLongSet;
/**
* PosUnifier does 3 steps in map-processing:
*
* <p>
* - unify positions - add srtm elevation data - make a bordernodes file
* containing net data from the bordernids-file just containing ids
*
* @author ab
*/
public class PosUnifier extends MapCreatorBase
{
public class PosUnifier extends MapCreatorBase {
private DiffCoderDataOutputStream nodesOutStream;
private DiffCoderDataOutputStream borderNodesOut;
private File nodeTilesOut;
@ -35,36 +34,29 @@ public class PosUnifier extends MapCreatorBase
private CompactLongSet borderNids;
public static void main( String[] args ) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** PosUnifier: Unify position values and enhance elevation");
if ( args.length != 5 )
{
if (args.length != 5) {
System.out.println("usage: java PosUnifier <node-tiles-in> <node-tiles-out> <bordernids-in> <bordernodes-out> <srtm-data-dir>");
return;
}
new PosUnifier().process(new File(args[0]), new File(args[1]), new File(args[2]), new File(args[3]), args[4]);
}
public void process( File nodeTilesIn, File nodeTilesOut, File bordernidsinfile, File bordernodesoutfile, String srtmdir ) throws Exception
{
public void process(File nodeTilesIn, File nodeTilesOut, File bordernidsinfile, File bordernodesoutfile, String srtmdir) throws Exception {
this.nodeTilesOut = nodeTilesOut;
this.srtmdir = srtmdir;
// read border nids set
DataInputStream dis = createInStream(bordernidsinfile);
borderNids = new CompactLongSet();
try
{
for ( ;; )
{
try {
for (; ; ) {
long nid = readId(dis);
if (!borderNids.contains(nid))
borderNids.fastAdd(nid);
}
}
catch (EOFException eof)
{
} catch (EOFException eof) {
dis.close();
}
borderNids = new FrozenLongSet(borderNids);
@ -76,8 +68,7 @@ public class PosUnifier extends MapCreatorBase
}
@Override
public void nodeFileStart( File nodefile ) throws Exception
{
public void nodeFileStart(File nodefile) throws Exception {
resetSrtm();
nodesOutStream = createOutStream(fileFromTemplate(nodefile, nodeTilesOut, "u5d"));
@ -86,37 +77,31 @@ public class PosUnifier extends MapCreatorBase
}
@Override
public void nextNode( NodeData n ) throws Exception
{
public void nextNode(NodeData n) throws Exception {
SrtmRaster srtm = srtmForNode(n.ilon, n.ilat);
n.selev = srtm == null ? Short.MIN_VALUE : srtm.getElevation(n.ilon, n.ilat);
findUniquePos(n);
n.writeTo(nodesOutStream);
if ( borderNids.contains( n.nid ) )
{
if (borderNids.contains(n.nid)) {
n.writeTo(borderNodesOut);
}
}
@Override
public void nodeFileEnd( File nodeFile ) throws Exception
{
public void nodeFileEnd(File nodeFile) throws Exception {
nodesOutStream.close();
}
private boolean checkAdd( int lon, int lat )
{
private boolean checkAdd(int lon, int lat) {
int slot = ((lon % 5000000) / 100000) * 50 + ((lat % 5000000) / 100000);
long id = ((long) lon) << 32 | lat;
CompactLongSet set = positionSets[slot];
if ( set == null )
{
if (set == null) {
positionSets[slot] = set = new CompactLongSet();
}
if ( !set.contains( id ) )
{
if (!set.contains(id)) {
set.fastAdd(id);
return true;
}
@ -124,31 +109,23 @@ public class PosUnifier extends MapCreatorBase
}
private void findUniquePos( NodeData n )
{
if ( !checkAdd( n.ilon, n.ilat ) )
{
private void findUniquePos(NodeData n) {
if (!checkAdd(n.ilon, n.ilat)) {
_findUniquePos(n);
}
}
private void _findUniquePos( NodeData n )
{
private void _findUniquePos(NodeData n) {
// fix the position for uniqueness
int lonmod = n.ilon % 1000000;
int londelta = lonmod < 500000 ? 1 : -1;
int latmod = n.ilat % 1000000;
int latdelta = latmod < 500000 ? 1 : -1;
for ( int latsteps = 0; latsteps < 100; latsteps++ )
{
for ( int lonsteps = 0; lonsteps <= latsteps; lonsteps++ )
{
for (int latsteps = 0; latsteps < 100; latsteps++) {
for (int lonsteps = 0; lonsteps <= latsteps; lonsteps++) {
int lon = n.ilon + lonsteps * londelta;
int lat = n.ilat + latsteps * latdelta;
if ( checkAdd( lon, lat ) )
{
if (checkAdd(lon, lat)) {
n.ilon = lon;
n.ilat = lat;
return;
@ -162,13 +139,11 @@ public class PosUnifier extends MapCreatorBase
* get the srtm data set for a position srtm coords are
* srtm_<srtmLon>_<srtmLat> where srtmLon = 180 + lon, srtmLat = 60 - lat
*/
private SrtmRaster srtmForNode( int ilon, int ilat ) throws Exception
{
private SrtmRaster srtmForNode(int ilon, int ilat) throws Exception {
int srtmLonIdx = (ilon + 5000000) / 5000000;
int srtmLatIdx = (654999999 - ilat) / 5000000 - 100; // ugly negative rounding...
if ( srtmLonIdx == lastSrtmLonIdx && srtmLatIdx == lastSrtmLatIdx )
{
if (srtmLonIdx == lastSrtmLonIdx && srtmLatIdx == lastSrtmLatIdx) {
return lastSrtmRaster;
}
lastSrtmLonIdx = srtmLonIdx;
@ -179,21 +154,16 @@ public class PosUnifier extends MapCreatorBase
String filename = "srtm_" + slonidx.substring(slonidx.length() - 2) + "_" + slatidx.substring(slatidx.length() - 2);
lastSrtmRaster = srtmmap.get(filename);
if ( lastSrtmRaster == null && !srtmmap.containsKey( filename ) )
{
if (lastSrtmRaster == null && !srtmmap.containsKey(filename)) {
File f = new File(new File(srtmdir), filename + ".bef");
System.out.println("checking: " + f + " ilon=" + ilon + " ilat=" + ilat);
if ( f.exists() )
{
if (f.exists()) {
System.out.println("*** reading: " + f);
try
{
try {
InputStream isc = new BufferedInputStream(new FileInputStream(f));
lastSrtmRaster = new RasterCoder().decodeRaster(isc);
isc.close();
}
catch (Exception e)
{
} catch (Exception e) {
System.out.println("**** ERROR reading " + f + " ****");
}
srtmmap.put(filename, lastSrtmRaster);
@ -202,14 +172,10 @@ public class PosUnifier extends MapCreatorBase
f = new File(new File(srtmdir), filename + ".zip");
System.out.println("reading: " + f + " ilon=" + ilon + " ilat=" + ilat);
if ( f.exists() )
{
try
{
if (f.exists()) {
try {
lastSrtmRaster = new SrtmData(f).getRaster();
}
catch (Exception e)
{
} catch (Exception e) {
System.out.println("**** ERROR reading " + f + " ****");
}
}
@ -218,8 +184,7 @@ public class PosUnifier extends MapCreatorBase
return lastSrtmRaster;
}
private void resetSrtm()
{
private void resetSrtm() {
srtmmap = new HashMap<String, SrtmRaster>();
lastSrtmLonIdx = -1;
lastSrtmLatIdx = -1;

View File

@ -1,16 +1,15 @@
package btools.mapcreator;
import java.io.*;
import btools.util.*;
//
// Encode/decode a raster
//
public class RasterCoder
{
public void encodeRaster(SrtmRaster raster, OutputStream os) throws IOException
{
public class RasterCoder {
public void encodeRaster(SrtmRaster raster, OutputStream os) throws IOException {
DataOutputStream dos = new DataOutputStream(os);
long t0 = System.currentTimeMillis();
@ -29,8 +28,7 @@ public class RasterCoder
System.out.println("finished encoding in " + (t1 - t0) + " ms");
}
public SrtmRaster decodeRaster(InputStream is) throws IOException
{
public SrtmRaster decodeRaster(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
long t0 = System.currentTimeMillis();
@ -55,26 +53,20 @@ public class RasterCoder
}
private void _encodeRaster(SrtmRaster raster, OutputStream os) throws IOException
{
private void _encodeRaster(SrtmRaster raster, OutputStream os) throws IOException {
MixCoderDataOutputStream mco = new MixCoderDataOutputStream(os);
int nrows = raster.nrows;
int ncols = raster.ncols;
short[] pixels = raster.eval_array;
int colstep = raster.halfcol ? 2 : 1;
for (int row = 0; row < nrows; row++)
{
for (int row = 0; row < nrows; row++) {
short lastval = Short.MIN_VALUE; // nodata
for (int col = 0; col < ncols; col += colstep )
{
for (int col = 0; col < ncols; col += colstep) {
short val = pixels[row * ncols + col];
if ( val == -32766 )
{
if (val == -32766) {
val = lastval; // replace remaining (border) skips
}
else
{
} else {
lastval = val;
}
@ -86,37 +78,30 @@ public class RasterCoder
mco.flush();
}
private void _decodeRaster(SrtmRaster raster, InputStream is) throws IOException
{
private void _decodeRaster(SrtmRaster raster, InputStream is) throws IOException {
MixCoderDataInputStream mci = new MixCoderDataInputStream(is);
int nrows = raster.nrows;
int ncols = raster.ncols;
short[] pixels = raster.eval_array;
int colstep = raster.halfcol ? 2 : 1;
for (int row = 0; row < nrows; row++)
{
for (int col = 0; col < ncols; col += colstep )
{
for (int row = 0; row < nrows; row++) {
for (int col = 0; col < ncols; col += colstep) {
int code = mci.readMixed();
// remap nodata
int v30 = code == -1 ? Short.MIN_VALUE : (code < 0 ? code + 1 : code);
if ( raster.usingWeights && v30 > -32766 )
{
if (raster.usingWeights && v30 > -32766) {
v30 *= 2;
}
pixels[row * ncols + col] = (short) (v30);
}
if ( raster.halfcol )
{
for (int col = 1; col < ncols-1; col += colstep )
{
if (raster.halfcol) {
for (int col = 1; col < ncols - 1; col += colstep) {
int l = (int) pixels[row * ncols + col - 1];
int r = (int) pixels[row * ncols + col + 1];
short v30 = Short.MIN_VALUE; // nodata
if ( l > -32766 && r > -32766 )
{
if (l > -32766 && r > -32766) {
v30 = (short) ((l + r) / 2);
}
pixels[row * ncols + col] = v30;

View File

@ -7,20 +7,17 @@ import btools.util.LongList;
*
* @author ab
*/
public class RelationData extends MapCreatorBase
{
public class RelationData extends MapCreatorBase {
public long rid;
public long description;
public LongList ways;
public RelationData( long id )
{
public RelationData(long id) {
rid = id;
ways = new LongList(16);
}
public RelationData( long id, LongList ways )
{
public RelationData(long id, LongList ways) {
rid = id;
this.ways = ways;
}

View File

@ -6,8 +6,7 @@ package btools.mapcreator;
*
* @author ab
*/
public interface RelationListener
{
public interface RelationListener {
void nextRelation(RelationData data) throws Exception;
void nextRestriction(RelationData data, long fromWid, long toWid, long viaNid) throws Exception;

View File

@ -13,13 +13,12 @@ import btools.util.FrozenLongSet;
/**
* RelationMerger does 1 step in map processing:
*
* <p>
* - enrich ways with relation information
*
* @author ab
*/
public class RelationMerger extends MapCreatorBase
{
public class RelationMerger extends MapCreatorBase {
private HashMap<String, CompactLongSet> routesets;
private CompactLongSet routesetall;
private BExpressionContextWay expctxReport;
@ -28,11 +27,9 @@ public class RelationMerger extends MapCreatorBase
private DataOutputStream wayOutStream;
public static void main(String[] args) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** RelationMerger: merge relations into ways");
if (args.length != 6)
{
if (args.length != 6) {
System.out.println("usage: java RelationMerger <way-file-in> <way-file-out> <relation-file> <lookup-file> <report-profile> <check-profile>");
return;
@ -40,8 +37,7 @@ public class RelationMerger extends MapCreatorBase
new RelationMerger().process(new File(args[0]), new File(args[1]), new File(args[2]), new File(args[3]), new File(args[4]), new File(args[5]));
}
public void init( File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception
{
public void init(File relationFileIn, File lookupFile, File reportProfile, File checkProfile) throws Exception {
// read lookup + profile for relation access-check
BExpressionMetaData metaReport = new BExpressionMetaData();
expctxReport = new BExpressionContextWay(metaReport);
@ -59,10 +55,8 @@ public class RelationMerger extends MapCreatorBase
routesets = new HashMap<String, CompactLongSet>();
routesetall = new CompactLongSet();
DataInputStream dis = createInStream(relationFileIn);
try
{
for(;;)
{
try {
for (; ; ) {
long rid = readId(dis);
String route = dis.readUTF();
String network = dis.readUTF();
@ -72,44 +66,36 @@ public class RelationMerger extends MapCreatorBase
String tagname = "route_" + route + "_" + network;
CompactLongSet routeset = null;
if ( expctxCheck.getLookupNameIdx(tagname) >= 0 )
{
if (expctxCheck.getLookupNameIdx(tagname) >= 0) {
String key = tagname + "_" + value;
routeset = routesets.get(key);
if ( routeset == null )
{
if (routeset == null) {
routeset = new CompactLongSet();
routesets.put(key, routeset);
}
}
for(;;)
{
for (; ; ) {
long wid = readId(dis);
if (wid == -1) break;
// expctxStat.addLookupValue( tagname, "yes", null );
if ( routeset != null && !routeset.contains( wid ) )
{
if (routeset != null && !routeset.contains(wid)) {
routeset.add(wid);
routesetall.add(wid);
}
}
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
dis.close();
}
for( String key : routesets.keySet() )
{
for (String key : routesets.keySet()) {
CompactLongSet routeset = new FrozenLongSet(routesets.get(key));
routesets.put(key, routeset);
System.out.println("marked " + routeset.size() + " routes for key: " + key);
}
}
public void process( File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception
{
public void process(File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile) throws Exception {
init(relationFileIn, lookupFile, reportProfile, checkProfile);
// *** finally process the way-file
@ -122,31 +108,25 @@ public class RelationMerger extends MapCreatorBase
}
@Override
public void nextWay( WayData data ) throws Exception
{
public void nextWay(WayData data) throws Exception {
// propagate the route-bits
if ( routesetall.contains( data.wid ) )
{
if (routesetall.contains(data.wid)) {
boolean ok = true;
// check access and log a warning for conflicts
expctxReport.evaluate(false, data.description);
boolean warn = expctxReport.getCostfactor() >= 10000.;
if ( warn )
{
if (warn) {
expctxCheck.evaluate(false, data.description);
ok = expctxCheck.getCostfactor() < 10000.;
System.out.println("** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription(false, data.description) + " (ok=" + ok + ")");
}
if ( ok )
{
if (ok) {
expctxReport.decode(data.description);
for( String key : routesets.keySet() )
{
for (String key : routesets.keySet()) {
CompactLongSet routeset = routesets.get(key);
if ( routeset.contains( data.wid ) )
{
if (routeset.contains(data.wid)) {
int sepIdx = key.lastIndexOf('_');
String tagname = key.substring(0, sepIdx);
int val = Integer.valueOf(key.substring(sepIdx + 1));
@ -156,8 +136,7 @@ public class RelationMerger extends MapCreatorBase
data.description = expctxReport.encode();
}
}
if ( wayOutStream != null )
{
if (wayOutStream != null) {
data.writeTo(wayOutStream);
}
}

View File

@ -10,19 +10,16 @@ import btools.util.TinyDenseLongMap;
/**
* WayCutter does 2 step in map-processing:
*
* <p>
* - cut the way file into 45*30 - pieces
* - enrich ways with relation information
*
* @author ab
*/
public class RelationStatistics extends MapCreatorBase
{
public static void main(String[] args) throws Exception
{
public class RelationStatistics extends MapCreatorBase {
public static void main(String[] args) throws Exception {
System.out.println("*** RelationStatistics: count relation networks");
if (args.length != 1)
{
if (args.length != 1) {
System.out.println("usage: java WayCutter <relation-file>");
return;
@ -30,41 +27,33 @@ public class RelationStatistics extends MapCreatorBase
new RelationStatistics().process(new File(args[0]));
}
public void process( File relationFileIn ) throws Exception
{
public void process(File relationFileIn) throws Exception {
HashMap<String, long[]> relstats = new HashMap<String, long[]>();
DataInputStream dis = createInStream(relationFileIn);
try
{
for(;;)
{
try {
for (; ; ) {
long rid = readId(dis);
String network = dis.readUTF();
int waycount = 0;
for(;;)
{
for (; ; ) {
long wid = readId(dis);
if (wid == -1) break;
waycount++;
}
long[] stat = relstats.get(network);
if ( stat == null )
{
if (stat == null) {
stat = new long[2];
relstats.put(network, stat);
}
stat[0]++;
stat[1] += waycount;
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
dis.close();
}
for( String network : relstats.keySet() )
{
for (String network : relstats.keySet()) {
long[] stat = relstats.get(network);
System.out.println("network: " + network + " has " + stat[0] + " relations with " + stat[1] + " ways");
}

View File

@ -4,39 +4,33 @@ import java.io.File;
/**
* RestrictionCutter writes Restrictions to tiles
*
* <p>
* - cut the way file into 45*30 - pieces
* - enrich ways with relation information
*
* @author ab
*/
public class RestrictionCutter extends MapCreatorBase
{
public class RestrictionCutter extends MapCreatorBase {
private WayCutter wayCutter;
public void init( File outTileDir, WayCutter wayCutter ) throws Exception
{
public void init(File outTileDir, WayCutter wayCutter) throws Exception {
outTileDir.mkdir();
this.outTileDir = outTileDir;
this.wayCutter = wayCutter;
}
public void finish() throws Exception
{
public void finish() throws Exception {
closeTileOutStreams();
}
public void nextRestriction( RestrictionData data ) throws Exception
{
public void nextRestriction(RestrictionData data) throws Exception {
int tileIndex = wayCutter.getTileIndexForNid(data.viaNid);
if ( tileIndex != -1 )
{
if (tileIndex != -1) {
data.writeTo(getOutStreamForTile(tileIndex));
}
}
protected String getNameForTile( int tileIndex )
{
protected String getNameForTile(int tileIndex) {
String name = wayCutter.getNameForTile(tileIndex);
return name.substring(0, name.length() - 3) + "rtl";
}

View File

@ -4,39 +4,33 @@ import java.io.File;
/**
* RestrictionCutter5 does 1 step in map-processing:
*
* <p>
* - cut the 45*30 restriction files into 5*5 pieces
*
* @author ab
*/
public class RestrictionCutter5 extends MapCreatorBase
{
public class RestrictionCutter5 extends MapCreatorBase {
private WayCutter5 wayCutter5;
public void init( File outTileDir, WayCutter5 wayCutter5 ) throws Exception
{
public void init(File outTileDir, WayCutter5 wayCutter5) throws Exception {
outTileDir.mkdir();
this.outTileDir = outTileDir;
this.wayCutter5 = wayCutter5;
}
public void finish() throws Exception
{
public void finish() throws Exception {
closeTileOutStreams();
}
public void nextRestriction( RestrictionData data ) throws Exception
{
public void nextRestriction(RestrictionData data) throws Exception {
int tileIndex = wayCutter5.getTileIndexForNid(data.viaNid);
if ( tileIndex != -1 )
{
if (tileIndex != -1) {
data.writeTo(getOutStreamForTile(tileIndex));
}
}
protected String getNameForTile( int tileIndex )
{
protected String getNameForTile(int tileIndex) {
String name = wayCutter5.getNameForTile(tileIndex);
return name.substring(0, name.length() - 3) + "rt5";
}

View File

@ -15,8 +15,7 @@ import btools.util.CheapAngleMeter;
*
* @author ab
*/
public class RestrictionData extends MapCreatorBase
{
public class RestrictionData extends MapCreatorBase {
public String restrictionKey;
public String restriction;
public short exceptions;
@ -39,77 +38,58 @@ public class RestrictionData extends MapCreatorBase
private static HashMap<String, String> names = new HashMap<>();
private static TreeSet<Long> badTRs = new TreeSet<>();
public RestrictionData()
{
public RestrictionData() {
}
public boolean isPositive()
{
public boolean isPositive() {
return restriction.startsWith("only_");
}
public boolean isValid()
{
public boolean isValid() {
boolean valid = fromLon != 0 && toLon != 0 && (restriction.startsWith("only_") || restriction.startsWith("no_"));
if ( (!valid) || badWayMatch || !(checkGeometry()) )
{
synchronized( badTRs )
{
if ((!valid) || badWayMatch || !(checkGeometry())) {
synchronized (badTRs) {
badTRs.add(((long) viaLon) << 32 | viaLat);
}
}
return valid && "restriction".equals(restrictionKey);
}
private boolean checkGeometry()
{
private boolean checkGeometry() {
double a = (new CheapAngleMeter()).calcAngle(fromLon, fromLat, viaLon, viaLat, toLon, toLat);
String t;
if ( restriction.startsWith( "only_" ) )
{
if (restriction.startsWith("only_")) {
t = restriction.substring("only_".length());
}
else if ( restriction.startsWith( "no_" ) )
{
} else if (restriction.startsWith("no_")) {
t = restriction.substring("no_".length());
}
else throw new RuntimeException( "ups" );
} else throw new RuntimeException("ups");
if ( restrictionKey.endsWith( ":conditional" ) )
{
if (restrictionKey.endsWith(":conditional")) {
int idx = t.indexOf('@');
if ( idx >= 0 )
{
if (idx >= 0) {
t = t.substring(0, idx).trim();
}
}
if ( "left_turn".equals( t ) )
{
if ("left_turn".equals(t)) {
return a < -5. && a > -175.;
}
if ( "right_turn".equals( t ) )
{
if ("right_turn".equals(t)) {
return a > 5. && a < 175.;
}
if ( "straight_on".equals( t ) )
{
if ("straight_on".equals(t)) {
return a > -85. && a < 85.;
}
if ( "u_turn".equals( t ) )
{
if ("u_turn".equals(t)) {
return a < -95. || a > 95.;
}
return "entry".equals(t) || "exit".equals(t);
}
private static String unifyName( String name )
{
synchronized( names )
{
private static String unifyName(String name) {
synchronized (names) {
String n = names.get(name);
if ( n == null )
{
if (n == null) {
names.put(name, name);
n = name;
}
@ -117,23 +97,17 @@ public class RestrictionData extends MapCreatorBase
}
}
public static void dumpBadTRs()
{
try( BufferedWriter bw = new BufferedWriter( new FileWriter( "badtrs.txt" ) ) )
{
for( Long id : badTRs )
{
public static void dumpBadTRs() {
try (BufferedWriter bw = new BufferedWriter(new FileWriter("badtrs.txt"))) {
for (Long id : badTRs) {
bw.write("" + id + " 26\n");
}
}
catch( IOException ioe )
{
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
public RestrictionData( DataInputStream di ) throws Exception
{
public RestrictionData(DataInputStream di) throws Exception {
restrictionKey = unifyName(di.readUTF());
restriction = unifyName(di.readUTF());
exceptions = di.readShort();
@ -142,8 +116,7 @@ public class RestrictionData extends MapCreatorBase
viaNid = readId(di);
}
public void writeTo( DataOutputStream dos ) throws Exception
{
public void writeTo(DataOutputStream dos) throws Exception {
dos.writeUTF(restrictionKey);
dos.writeUTF(restriction);
dos.writeShort(exceptions);

View File

@ -2,7 +2,7 @@ package btools.mapcreator;
/**
* This is a wrapper for a 5*5 degree srtm file in ascii/zip-format
*
* <p>
* - filter out unused nodes according to the way file
* - enhance with SRTM elevation data
* - split further in smaller (5*5 degree) tiles
@ -23,54 +23,42 @@ import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class SrtmData
{
public class SrtmData {
private SrtmRaster raster;
public SrtmData( File file ) throws Exception
{
public SrtmData(File file) throws Exception {
raster = new SrtmRaster();
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
try
{
for ( ;; )
{
try {
for (; ; ) {
ZipEntry ze = zis.getNextEntry();
if ( ze.getName().endsWith( ".asc" ) )
{
if (ze.getName().endsWith(".asc")) {
readFromStream(zis);
return;
}
}
}
finally
{
} finally {
zis.close();
}
}
public SrtmRaster getRaster()
{
public SrtmRaster getRaster() {
return raster;
}
private String secondToken( String s )
{
private String secondToken(String s) {
StringTokenizer tk = new StringTokenizer(s, " ");
tk.nextToken();
return tk.nextToken();
}
public void readFromStream( InputStream is ) throws Exception
{
public void readFromStream(InputStream is) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
int linenr = 0;
for ( ;; )
{
for (; ; ) {
linenr++;
if ( linenr <= 6 )
{
if (linenr <= 6) {
String line = br.readLine();
if (linenr == 1)
raster.ncols = Integer.parseInt(secondToken(line));
@ -82,45 +70,35 @@ public class SrtmData
raster.yllcorner = Double.parseDouble(secondToken(line));
else if (linenr == 5)
raster.cellsize = Double.parseDouble(secondToken(line));
else if ( linenr == 6 )
{
else if (linenr == 6) {
// nodata ignored here ( < -250 assumed nodata... )
// raster.noDataValue = Short.parseShort( secondToken( line ) );
raster.eval_array = new short[raster.ncols * raster.nrows];
}
}
else
{
} else {
int row = 0;
int col = 0;
int n = 0;
boolean negative = false;
for ( ;; )
{
for (; ; ) {
int c = br.read();
if (c < 0)
break;
if ( c == ' ' )
{
if (c == ' ') {
if (negative)
n = -n;
short val = n < -250 ? Short.MIN_VALUE : (short) (n);
raster.eval_array[row * raster.ncols + col] = val;
if ( ++col == raster.ncols )
{
if (++col == raster.ncols) {
col = 0;
++row;
}
n = 0;
negative = false;
}
else if ( c >= '0' && c <= '9' )
{
} else if (c >= '0' && c <= '9') {
n = 10 * n + (c - '0');
}
else if ( c == '-' )
{
} else if (c == '-') {
negative = true;
}
}
@ -130,16 +108,13 @@ public class SrtmData
br.close();
}
public static void main( String[] args ) throws Exception
{
public static void main(String[] args) throws Exception {
String fromDir = args[0];
String toDir = args[1];
File[] files = new File(fromDir).listFiles();
for( File f : files )
{
if ( !f.getName().endsWith( ".zip" ) )
{
for (File f : files) {
if (!f.getName().endsWith(".zip")) {
continue;
}
System.out.println("*** reading: " + f);
@ -171,21 +146,17 @@ public class SrtmData
String s1 = raster.toString();
String s2 = raster2.toString();
if ( !s1.equals( s2 ) )
{
if (!s1.equals(s2)) {
throw new IllegalArgumentException("missmatch: " + s1 + "<--->" + s2);
}
int cols = raster.ncols;
int rows = raster.nrows;
for( int c = 0; c < cols; c++ )
{
for( int r = 0; r < rows; r++ )
{
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
int idx = r * cols + c;
if ( raster.eval_array[idx] != raster2.eval_array[idx] )
{
if (raster.eval_array[idx] != raster2.eval_array[idx]) {
throw new IllegalArgumentException("missmatch: at " + c + "," + r + ": " + raster.eval_array[idx] + "<--->" + raster2.eval_array[idx]);
}
}

View File

@ -7,8 +7,7 @@ import btools.util.ReducedMedianFilter;
*
* @author ab
*/
public class SrtmRaster
{
public class SrtmRaster {
public int ncols;
public int nrows;
public boolean halfcol;
@ -22,13 +21,11 @@ public class SrtmRaster
private boolean missingData = false;
public short getElevation( int ilon, int ilat )
{
public short getElevation(int ilon, int ilat) {
double lon = ilon / 1000000. - 180.;
double lat = ilat / 1000000. - 90.;
if ( usingWeights )
{
if (usingWeights) {
return getElevationFromShiftWeights(lon, lat);
}
@ -54,15 +51,13 @@ public class SrtmRaster
return missingData ? Short.MIN_VALUE : (short) (eval * 4);
}
private short get( int r, int c )
{
private short get(int r, int c) {
short e = eval_array[(nrows - 1 - r) * ncols + c];
if (e == Short.MIN_VALUE) missingData = true;
return e;
}
private short getElevationFromShiftWeights( double lon, double lat )
{
private short getElevationFromShiftWeights(double lon, double lat) {
// calc lat-idx and -weight
double alat = lat < 0. ? -lat : lat;
alat /= 5.;
@ -111,10 +106,8 @@ public class SrtmRaster
private ReducedMedianFilter rmf = new ReducedMedianFilter(256);
private double getElevation( Weights w, int row, int col )
{
if ( missingData )
{
private double getElevation(Weights w, int row, int col) {
if (missingData) {
return 0.;
}
int nx = w.nx;
@ -126,10 +119,8 @@ public class SrtmRaster
rmf.reset();
for( int ix = 0; ix < nx; ix ++ )
{
for( int iy = 0; iy < ny; iy ++ )
{
for (int ix = 0; ix < nx; ix++) {
for (int iy = 0; iy < ny; iy++) {
short val = get(row + iy - my, col + ix - mx);
rmf.addSample(w.getWeight(ix, iy), val);
}
@ -138,51 +129,42 @@ public class SrtmRaster
}
private static class Weights
{
private static class Weights {
int nx;
int ny;
double[] weights;
long total = 0;
Weights( int nx, int ny )
{
Weights(int nx, int ny) {
this.nx = nx;
this.ny = ny;
weights = new double[nx * ny];
}
void inc( int ix, int iy )
{
void inc(int ix, int iy) {
weights[iy * nx + ix] += 1.;
total++;
}
void normalize( boolean verbose )
{
for( int iy =0; iy < ny; iy++ )
{
void normalize(boolean verbose) {
for (int iy = 0; iy < ny; iy++) {
StringBuilder sb = verbose ? new StringBuilder() : null;
for( int ix =0; ix < nx; ix++ )
{
for (int ix = 0; ix < nx; ix++) {
weights[iy * nx + ix] /= total;
if ( sb != null )
{
if (sb != null) {
int iweight = (int) (1000 * weights[iy * nx + ix] + 0.5);
String sval = " " + iweight;
sb.append(sval.substring(sval.length() - 4));
}
}
if ( sb != null )
{
if (sb != null) {
System.out.println(sb);
System.out.println();
}
}
}
double getWeight( int ix, int iy )
{
double getWeight(int ix, int iy) {
return weights[iy * nx + ix];
}
}
@ -193,17 +175,14 @@ public class SrtmRaster
private static double filterCenterFraction = 0.2;
private static double filterDiscRadius = 4.999; // in pixels
static
{
static {
String sRadius = System.getProperty("filterDiscRadius");
if ( sRadius != null && sRadius.length() > 0 )
{
if (sRadius != null && sRadius.length() > 0) {
filterDiscRadius = Integer.parseInt(sRadius);
System.out.println("using filterDiscRadius = " + filterDiscRadius);
}
String sFraction = System.getProperty("filterCenterFraction");
if ( sFraction != null && sFraction.length() > 0 )
{
if (sFraction != null && sFraction.length() > 0) {
filterCenterFraction = Integer.parseInt(sFraction) / 100.;
System.out.println("using filterCenterFraction = " + filterCenterFraction);
}
@ -213,21 +192,18 @@ public class SrtmRaster
// calculate interpolation weights from the overlap of a probe disc of given radius at given latitude
// ( latIndex = 0 -> 0 deg, latIndex = 16 -> 80 degree)
private static Weights[][] getWeights( int latIndex )
{
private static Weights[][] getWeights(int latIndex) {
int idx = latIndex < 16 ? latIndex : 16;
Weights[][] res = allShiftWeights[idx];
if ( res == null )
{
if (res == null) {
res = calcWeights(idx);
allShiftWeights[idx] = res;
}
return res;
}
private static Weights[][] calcWeights( int latIndex )
{
private static Weights[][] calcWeights(int latIndex) {
double coslat = Math.cos(latIndex * 5. / 57.3);
// radius in pixel units
@ -248,13 +224,11 @@ public class SrtmRaster
Weights[][] shiftWeights = new Weights[gridSteps + 1][];
// loop the intergrid-position
for( int gx=0; gx<=gridSteps; gx++ )
{
for (int gx = 0; gx <= gridSteps; gx++) {
shiftWeights[gx] = new Weights[gridSteps + 1];
double x0 = mx + ((double) gx) / gridSteps;
for( int gy=0; gy<=gridSteps; gy++ )
{
for (int gy = 0; gy <= gridSteps; gy++) {
double y0 = my + ((double) gy) / gridSteps;
// create the weight-matrix
@ -263,16 +237,13 @@ public class SrtmRaster
double sampleStep = 0.001;
for( double x = -1. + sampleStep/2.; x < 1.; x += sampleStep )
{
for (double x = -1. + sampleStep / 2.; x < 1.; x += sampleStep) {
double mx2 = 1. - x * x;
int x_idx = (int) (x0 + x * rx);
for( double y = -1. + sampleStep/2.; y < 1.; y += sampleStep )
{
if ( y*y > mx2 )
{
for (double y = -1. + sampleStep / 2.; y < 1.; y += sampleStep) {
if (y * y > mx2) {
continue;
}
// we are in the ellipse, see what pixel we are on
@ -287,8 +258,7 @@ public class SrtmRaster
}
@Override
public String toString()
{
public String toString() {
return ncols + "," + nrows + "," + halfcol + "," + xllcorner + "," + yllcorner + "," + cellsize + "," + noDataValue + "," + usingWeights;
}
}

View File

@ -7,21 +7,18 @@ import btools.util.TinyDenseLongMap;
/**
* WayCutter does 2 step in map-processing:
*
* <p>
* - cut the way file into 45*30 - pieces
* - enrich ways with relation information
*
* @author ab
*/
public class WayCutter extends MapCreatorBase
{
public class WayCutter extends MapCreatorBase {
private DenseLongMap tileIndexMap;
public static void main(String[] args) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** WayCutter: Soft-Cut way-data into tiles");
if (args.length != 3)
{
if (args.length != 3) {
System.out.println("usage: java WayCutter <node-tiles-in> <way-file-in> <way-tiles-out>");
return;
@ -29,8 +26,7 @@ public class WayCutter extends MapCreatorBase
new WayCutter().process(new File(args[0]), new File(args[1]), new File(args[2]));
}
public void process( File nodeTilesIn, File wayFileIn, File wayTilesOut ) throws Exception
{
public void process(File nodeTilesIn, File wayFileIn, File wayTilesOut) throws Exception {
init(wayTilesOut);
new NodeIterator(this, false).processDir(nodeTilesIn, ".tlf");
@ -40,46 +36,38 @@ public class WayCutter extends MapCreatorBase
finish();
}
public void init( File wayTilesOut ) throws Exception
{
public void init(File wayTilesOut) throws Exception {
this.outTileDir = wayTilesOut;
// *** read all nodes into tileIndexMap
tileIndexMap = Boolean.getBoolean("useDenseMaps") ? new DenseLongMap() : new TinyDenseLongMap();
}
public void finish() throws Exception
{
public void finish() throws Exception {
closeTileOutStreams();
}
@Override
public void nextNode( NodeData n ) throws Exception
{
public void nextNode(NodeData n) throws Exception {
tileIndexMap.put(n.nid, getTileIndex(n.ilon, n.ilat));
}
@Override
public void nextWay( WayData data ) throws Exception
{
public void nextWay(WayData data) throws Exception {
long waytileset = 0;
int nnodes = data.nodes.size();
// determine the tile-index for each node
for (int i=0; i<nnodes; i++ )
{
for (int i = 0; i < nnodes; i++) {
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
if ( tileIndex != -1 )
{
if (tileIndex != -1) {
waytileset |= (1L << tileIndex);
}
}
// now write way to all tiles hit
for( int tileIndex=0; tileIndex<54; tileIndex++ )
{
if ( ( waytileset & ( 1L << tileIndex ) ) == 0 )
{
for (int tileIndex = 0; tileIndex < 54; tileIndex++) {
if ((waytileset & (1L << tileIndex)) == 0) {
continue;
}
data.writeTo(getOutStreamForTile(tileIndex));
@ -87,21 +75,19 @@ public class WayCutter extends MapCreatorBase
}
public int getTileIndexForNid( long nid )
{
public int getTileIndexForNid(long nid) {
return tileIndexMap.getInt(nid);
}
private int getTileIndex( int ilon, int ilat )
{
private int getTileIndex(int ilon, int ilat) {
int lon = ilon / 45000000;
int lat = ilat / 30000000;
if ( lon < 0 || lon > 7 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
if (lon < 0 || lon > 7 || lat < 0 || lat > 5)
throw new IllegalArgumentException("illegal pos: " + ilon + "," + ilat);
return lon * 6 + lat;
}
public String getNameForTile( int tileIndex )
{
public String getNameForTile(int tileIndex) {
int lon = (tileIndex / 6) * 45 - 180;
int lat = (tileIndex % 6) * 30 - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;

View File

@ -12,14 +12,13 @@ import btools.util.TinyDenseLongMap;
/**
* WayCutter5 does 2 step in map-processing:
*
* <p>
* - cut the 45*30 way files into 5*5 pieces
* - create a file containing all border node ids
*
* @author ab
*/
public class WayCutter5 extends MapCreatorBase
{
public class WayCutter5 extends MapCreatorBase {
private DataOutputStream borderNidsOutStream;
private DenseLongMap tileIndexMap;
private File nodeTilesIn;
@ -31,19 +30,16 @@ public class WayCutter5 extends MapCreatorBase
public NodeCutter nodeCutter;
public RestrictionCutter5 restrictionCutter5;
public static void main(String[] args) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** WayCutter5: Soft-Cut way-data into tiles");
if (args.length != 4)
{
if (args.length != 4) {
System.out.println("usage: java WayCutter5 <node-tiles-in> <way-tiles-in> <way-tiles-out> <border-nids-out>");
return;
}
new WayCutter5().process(new File(args[0]), new File(args[1]), new File(args[2]), new File(args[3]));
}
public void process( File nodeTilesIn, File wayTilesIn, File wayTilesOut, File borderNidsOut ) throws Exception
{
public void process(File nodeTilesIn, File wayTilesIn, File wayTilesOut, File borderNidsOut) throws Exception {
this.nodeTilesIn = nodeTilesIn;
this.outTileDir = wayTilesOut;
@ -55,8 +51,7 @@ public class WayCutter5 extends MapCreatorBase
}
@Override
public boolean wayFileStart( File wayfile ) throws Exception
{
public boolean wayFileStart(File wayfile) throws Exception {
// read corresponding node-file into tileIndexMap
String name = wayfile.getName();
String nodefilename = name.substring(0, name.length() - 3) + "ntl";
@ -66,33 +61,26 @@ public class WayCutter5 extends MapCreatorBase
lonoffset = -1;
latoffset = -1;
if ( nodeCutter != null )
{
if (nodeCutter != null) {
nodeCutter.nodeFileStart(null);
}
new NodeIterator(this, nodeCutter != null).processFile(nodefile);
if ( restrictionCutter5 != null )
{
if (restrictionCutter5 != null) {
String resfilename = name.substring(0, name.length() - 3) + "rtl";
File resfile = new File("restrictions", resfilename);
if ( resfile.exists() )
{
if (resfile.exists()) {
// read restrictions for nodes in nodesMap
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(resfile)));
int ntr = 0;
try
{
for(;;)
{
try {
for (; ; ) {
RestrictionData res = new RestrictionData(di);
restrictionCutter5.nextRestriction(res);
ntr++;
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
di.close();
}
System.out.println("read " + ntr + " turn-restrictions");
@ -102,17 +90,13 @@ public class WayCutter5 extends MapCreatorBase
}
@Override
public void nextNode( NodeData n ) throws Exception
{
if ( nodeFilter != null )
{
if ( !nodeFilter.isRelevant( n ) )
{
public void nextNode(NodeData n) throws Exception {
if (nodeFilter != null) {
if (!nodeFilter.isRelevant(n)) {
return;
}
}
if ( nodeCutter != null )
{
if (nodeCutter != null) {
nodeCutter.nextNode(n);
}
@ -120,46 +104,37 @@ public class WayCutter5 extends MapCreatorBase
}
@Override
public void nextWay( WayData data ) throws Exception
{
public void nextWay(WayData data) throws Exception {
long waytileset = 0;
int nnodes = data.nodes.size();
int[] tiForNode = new int[nnodes];
// determine the tile-index for each node
for (int i=0; i<nnodes; i++ )
{
for (int i = 0; i < nnodes; i++) {
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
if ( tileIndex != -1 )
{
if (tileIndex != -1) {
waytileset |= (1L << tileIndex);
}
tiForNode[i] = tileIndex;
}
if ( relMerger != null )
{
if (relMerger != null) {
relMerger.nextWay(data);
}
// now write way to all tiles hit
for( int tileIndex=0; tileIndex<54; tileIndex++ )
{
if ( ( waytileset & ( 1L << tileIndex ) ) == 0 )
{
for (int tileIndex = 0; tileIndex < 54; tileIndex++) {
if ((waytileset & (1L << tileIndex)) == 0) {
continue;
}
data.writeTo(getOutStreamForTile(tileIndex));
}
// and write edge nodes to the border-nid file
for( int i=0; i < nnodes; i++ )
{
for (int i = 0; i < nnodes; i++) {
int ti = tiForNode[i];
if ( ti != -1 )
{
if ( ( i > 0 && tiForNode[i-1] != ti ) || (i+1 < nnodes && tiForNode[i+1] != ti ) )
{
if (ti != -1) {
if ((i > 0 && tiForNode[i - 1] != ti) || (i + 1 < nnodes && tiForNode[i + 1] != ti)) {
writeId(borderNidsOutStream, data.nodes.get(i));
}
}
@ -167,26 +142,21 @@ public class WayCutter5 extends MapCreatorBase
}
@Override
public void wayFileEnd( File wayFile ) throws Exception
{
public void wayFileEnd(File wayFile) throws Exception {
closeTileOutStreams();
if ( nodeCutter != null )
{
if (nodeCutter != null) {
nodeCutter.nodeFileEnd(null);
}
if ( restrictionCutter5 != null )
{
if (restrictionCutter5 != null) {
restrictionCutter5.finish();
}
}
public int getTileIndexForNid( long nid )
{
public int getTileIndexForNid(long nid) {
return tileIndexMap.getInt(nid);
}
private int getTileIndex( int ilon, int ilat )
{
private int getTileIndex(int ilon, int ilat) {
int lonoff = (ilon / 45000000) * 45;
int latoff = (ilat / 30000000) * 30;
if (lonoffset == -1) lonoffset = lonoff;
@ -196,13 +166,13 @@ public class WayCutter5 extends MapCreatorBase
int lon = (ilon / 5000000) % 9;
int lat = (ilat / 5000000) % 6;
if ( lon < 0 || lon > 8 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
if (lon < 0 || lon > 8 || lat < 0 || lat > 5)
throw new IllegalArgumentException("illegal pos: " + ilon + "," + ilat);
return lon * 6 + lat;
}
protected String getNameForTile( int tileIndex )
{
protected String getNameForTile(int tileIndex) {
int lon = (tileIndex / 6) * 5 + lonoffset - 180;
int lat = (tileIndex % 6) * 5 + latoffset - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;

View File

@ -10,44 +10,40 @@ import btools.util.LongList;
*
* @author ab
*/
public class WayData extends MapCreatorBase
{
public class WayData extends MapCreatorBase {
public long wid;
public byte[] description;
public LongList nodes;
public WayData( long id )
{
public WayData(long id) {
wid = id;
nodes = new LongList(16);
}
public WayData( long id, LongList nodes )
{
public WayData(long id, LongList nodes) {
wid = id;
this.nodes = nodes;
}
public WayData( DataInputStream di ) throws Exception
{
public WayData(DataInputStream di) throws Exception {
nodes = new LongList(16);
wid = readId(di);
int dlen = di.readByte(); description = new byte[dlen]; di.readFully( description );
for (;;)
{
int dlen = di.readByte();
description = new byte[dlen];
di.readFully(description);
for (; ; ) {
long nid = readId(di);
if (nid == -1) break;
nodes.add(nid);
}
}
public void writeTo( DataOutputStream dos ) throws Exception
{
public void writeTo(DataOutputStream dos) throws Exception {
writeId(dos, wid);
dos.writeByte( description.length ); dos.write( description );
dos.writeByte(description.length);
dos.write(description);
int size = nodes.size();
for( int i=0; i < size; i++ )
{
for (int i = 0; i < size; i++) {
writeId(dos, nodes.get(i));
}
writeId(dos, -1); // stopbyte

View File

@ -12,68 +12,54 @@ import java.io.FileInputStream;
*
* @author ab
*/
public class WayIterator extends MapCreatorBase
{
public class WayIterator extends MapCreatorBase {
private WayListener listener;
private boolean delete;
private boolean descendingSize;
public WayIterator( WayListener wayListener, boolean deleteAfterReading )
{
public WayIterator(WayListener wayListener, boolean deleteAfterReading) {
listener = wayListener;
delete = deleteAfterReading;
}
public WayIterator( WayListener wayListener, boolean deleteAfterReading, boolean descendingSize )
{
public WayIterator(WayListener wayListener, boolean deleteAfterReading, boolean descendingSize) {
this(wayListener, deleteAfterReading);
this.descendingSize = descendingSize;
}
public void processDir( File indir, String inSuffix ) throws Exception
{
if ( !indir.isDirectory() )
{
public void processDir(File indir, String inSuffix) throws Exception {
if (!indir.isDirectory()) {
throw new IllegalArgumentException("not a directory: " + indir);
}
File[] af = sortBySizeAsc(indir.listFiles());
for( int i=0; i<af.length; i++ )
{
for (int i = 0; i < af.length; i++) {
File wayfile = descendingSize ? af[af.length - 1 - i] : af[i];
if ( wayfile.getName().endsWith( inSuffix ) )
{
if (wayfile.getName().endsWith(inSuffix)) {
processFile(wayfile);
}
}
}
public void processFile(File wayfile) throws Exception
{
public void processFile(File wayfile) throws Exception {
System.out.println("*** WayIterator reading: " + wayfile);
if ( !listener.wayFileStart( wayfile ) )
{
if (!listener.wayFileStart(wayfile)) {
return;
}
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(wayfile)));
try
{
for(;;)
{
try {
for (; ; ) {
WayData w = new WayData(di);
listener.nextWay(w);
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
di.close();
}
listener.wayFileEnd(wayfile);
if ( delete && "true".equals( System.getProperty( "deletetmpfiles" ) ))
{
if (delete && "true".equals(System.getProperty("deletetmpfiles"))) {
wayfile.delete();
}
}

View File

@ -32,8 +32,7 @@ import btools.util.LazyArrayOfLists;
*
* @author ab
*/
public class WayLinker extends MapCreatorBase implements Runnable
{
public class WayLinker extends MapCreatorBase implements Runnable {
private File nodeTilesIn;
private File wayTilesIn;
private File trafficTilesIn;
@ -70,43 +69,33 @@ public class WayLinker extends MapCreatorBase implements Runnable
private boolean isSlave;
private ThreadController tc;
public static final class ThreadController
{
public static final class ThreadController {
long maxFileSize = 0L;
long currentSlaveSize;
long currentMasterSize = 2000000000L;
synchronized boolean setCurrentMasterSize( long size )
{
try
{
if ( size <= currentSlaveSize )
{
synchronized boolean setCurrentMasterSize(long size) {
try {
if (size <= currentSlaveSize) {
maxFileSize = Long.MAX_VALUE;
return false;
}
currentMasterSize = size;
if ( maxFileSize == 0L )
{
if (maxFileSize == 0L) {
maxFileSize = size;
}
return true;
}
finally
{
} finally {
notify();
}
}
synchronized boolean setCurrentSlaveSize( long size ) throws Exception
{
if ( size >= currentMasterSize )
{
synchronized boolean setCurrentSlaveSize(long size) throws Exception {
if (size >= currentMasterSize) {
return false;
}
while ( size + currentMasterSize + 50000000L > maxFileSize )
{
while (size + currentMasterSize + 50000000L > maxFileSize) {
System.out.println("****** slave thread waiting for permission to process file of size " + size
+ " currentMaster=" + currentMasterSize + " maxFileSize=" + maxFileSize);
wait(10000);
@ -117,20 +106,16 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
private void reset()
{
private void reset() {
minLon = -1;
minLat = -1;
nodesMap = new CompactLongMap<OsmNodeP>();
borderSet = new CompactLongSet();
}
public static void main( String[] args ) throws Exception
{
public static void main(String[] args) throws Exception {
System.out.println("*** WayLinker: Format a region of an OSM map for routing");
if ( args.length != 8 )
{
if (args.length != 8) {
System.out
.println("usage: java WayLinker <node-tiles-in> <way-tiles-in> <bordernodes> <restrictions> <lookup-file> <profile-file> <data-tiles-out> <data-tiles-suffix> ");
return;
@ -144,8 +129,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
public void process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
String dataTilesSuffix ) throws Exception
{
String dataTilesSuffix) throws Exception {
WayLinker master = new WayLinker();
WayLinker slave = new WayLinker();
slave.isSlave = true;
@ -167,8 +151,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
private void _process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
String dataTilesSuffix ) throws Exception
{
String dataTilesSuffix) throws Exception {
this.nodeTilesIn = nodeTilesIn;
this.wayTilesIn = wayTilesIn;
this.trafficTilesIn = new File("../traffic");
@ -197,30 +180,22 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
@Override
public void run()
{
try
{
public void run() {
try {
// then process all segments
new WayIterator(this, true, !isSlave).processDir(wayTilesIn, ".wt5");
}
catch( Exception e )
{
} catch (Exception e) {
System.out.println("******* thread (slave=" + isSlave + ") got Exception: " + e);
throw new RuntimeException(e);
}
finally
{
if (!isSlave)
{
} finally {
if (!isSlave) {
tc.setCurrentMasterSize(0L);
}
}
}
@Override
public boolean wayFileStart( File wayfile ) throws Exception
{
public boolean wayFileStart(File wayfile) throws Exception {
// master/slave logic:
// total memory size should stay below a maximum
@ -230,31 +205,22 @@ public class WayLinker extends MapCreatorBase implements Runnable
System.out.println("**** wayFileStart() for isSlave=" + isSlave + " size=" + filesize);
if ( isSlave )
{
if ( !tc.setCurrentSlaveSize( filesize ) )
{
if (isSlave) {
if (!tc.setCurrentSlaveSize(filesize)) {
return false;
}
} else {
if (!tc.setCurrentMasterSize(filesize)) {
return false;
}
}
else
{
if ( !tc.setCurrentMasterSize( filesize ) )
{
return false;
}
}
File trafficFile = fileFromTemplate(wayfile, trafficTilesIn, "trf");
// process corresponding node-file, if any
File nodeFile = fileFromTemplate(wayfile, nodeTilesIn, "u5d");
if ( nodeFile.exists() )
{
if (nodeFile.exists()) {
reset();
// read the border file
@ -272,20 +238,15 @@ public class WayLinker extends MapCreatorBase implements Runnable
File restrictionFile = fileFromTemplate(wayfile, new File(nodeTilesIn.getParentFile(), "restrictions55"), "rt5");
// read restrictions for nodes in nodesMap
if ( restrictionFile.exists() )
{
if (restrictionFile.exists()) {
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(restrictionFile)));
int ntr = 0;
try
{
for(;;)
{
try {
for (; ; ) {
RestrictionData res = new RestrictionData(di);
OsmNodeP n = nodesMap.get(res.viaNid);
if ( n != null )
{
if ( ! ( n instanceof OsmNodePT ) )
{
if (n != null) {
if (!(n instanceof OsmNodePT)) {
n = new OsmNodePT(n);
nodesMap.put(res.viaNid, n);
}
@ -297,9 +258,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
ntr++;
}
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
di.close();
}
System.out.println("read " + ntr + " turn-restrictions");
@ -309,8 +268,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
// read a traffic-file, if any
if ( trafficFile.exists() )
{
if (trafficFile.exists()) {
trafficMap = new OsmTrafficMap(expctxWay);
trafficMap.loadAll(trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false);
}
@ -318,20 +276,17 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
@Override
public void nextNode( NodeData data ) throws Exception
{
public void nextNode(NodeData data) throws Exception {
OsmNodeP n = data.description == null ? new OsmNodeP() : new OsmNodePT(data.description);
n.ilon = data.ilon;
n.ilat = data.ilat;
n.selev = data.selev;
if ( readingBorder || ( !borderSet.contains( data.nid ) ) )
{
if (readingBorder || (!borderSet.contains(data.nid))) {
nodesMap.fastPut(data.nid, n);
}
if ( readingBorder )
{
if (readingBorder) {
n.bits |= OsmNodeP.BORDER_BIT;
borderSet.fastAdd(data.nid);
return;
@ -354,39 +309,30 @@ public class WayLinker extends MapCreatorBase implements Runnable
// starts or ends at it's via node. However, we allow
// ways not ending at the via node, and in this case we take
// the leg according to the mapped direction
private void checkRestriction( OsmNodeP n1, OsmNodeP n2, WayData w )
{
private void checkRestriction(OsmNodeP n1, OsmNodeP n2, WayData w) {
checkRestriction(n1, n2, w, true);
checkRestriction(n2, n1, w, false);
}
private void checkRestriction( OsmNodeP n1, OsmNodeP n2, WayData w, boolean checkFrom )
{
private void checkRestriction(OsmNodeP n1, OsmNodeP n2, WayData w, boolean checkFrom) {
RestrictionData r = n2.getFirstRestriction();
while ( r != null )
{
if ( r.fromWid == w.wid )
{
if ( r.fromLon == 0 || checkFrom )
{
while (r != null) {
if (r.fromWid == w.wid) {
if (r.fromLon == 0 || checkFrom) {
r.fromLon = n1.ilon;
r.fromLat = n1.ilat;
n1.bits |= OsmNodeP.DP_SURVIVOR_BIT;
if ( !isEndNode( n2, w ) )
{
if (!isEndNode(n2, w)) {
r.badWayMatch = true;
}
}
}
if ( r.toWid == w.wid )
{
if ( r.toLon == 0 || !checkFrom )
{
if (r.toWid == w.wid) {
if (r.toLon == 0 || !checkFrom) {
r.toLon = n1.ilon;
r.toLat = n1.ilat;
n1.bits |= OsmNodeP.DP_SURVIVOR_BIT;
if ( !isEndNode( n2, w ) )
{
if (!isEndNode(n2, w)) {
r.badWayMatch = true;
}
}
@ -395,14 +341,12 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
}
private boolean isEndNode( OsmNodeP n, WayData w )
{
private boolean isEndNode(OsmNodeP n, WayData w) {
return n == nodesMap.get(w.nodes.get(0)) || n == nodesMap.get(w.nodes.get(w.nodes.size() - 1));
}
@Override
public void nextWay( WayData way ) throws Exception
{
public void nextWay(WayData way) throws Exception {
byte[] description = abUnifier.unify(way.description);
// filter according to profile
@ -422,28 +366,24 @@ public class WayLinker extends MapCreatorBase implements Runnable
OsmNodeP n1 = null;
OsmNodeP n2 = null;
for ( int i = 0; i < way.nodes.size(); i++ )
{
for (int i = 0; i < way.nodes.size(); i++) {
long nid = way.nodes.get(i);
n1 = n2;
n2 = nodesMap.get(nid);
if ( n1 != null && n2 != null && n1 != n2 )
{
if (n1 != null && n2 != null && n1 != n2) {
checkRestriction(n1, n2, way);
OsmLinkP link = n2.createLink(n1);
link.descriptionBitmap = description;
if ( n1.ilon / cellsize != n2.ilon / cellsize || n1.ilat / cellsize != n2.ilat / cellsize )
{
if (n1.ilon / cellsize != n2.ilon / cellsize || n1.ilat / cellsize != n2.ilat / cellsize) {
n2.incWayCount(); // force first node after cell-change to be a
// network node
}
}
if ( n2 != null )
{
if (n2 != null) {
n2.bits |= wayBits;
n2.incWayCount();
}
@ -451,8 +391,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
@Override
public void wayFileEnd( File wayfile ) throws Exception
{
public void wayFileEnd(File wayfile) throws Exception {
int ncaches = divisor * divisor;
int indexsize = ncaches * 4;
@ -466,8 +405,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
int maxLat = minLat + 5000000;
// cleanup duplicate targets
for ( OsmNodeP n : nodesList )
{
for (OsmNodeP n : nodesList) {
if (n == null || n.getFirstLink() == null || n.isTransferNode())
continue;
n.checkDuplicateTargets();
@ -480,8 +418,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
// sort the nodes into segments
LazyArrayOfLists<OsmNodeP> seglists = new LazyArrayOfLists<OsmNodeP>(nLonSegs * nLatSegs);
for ( OsmNodeP n : nodesList )
{
for (OsmNodeP n : nodesList) {
if (n == null || n.getFirstLink() == null || n.isTransferNode())
continue;
if (n.ilon < minLon || n.ilon >= maxLon || n.ilat < minLat || n.ilat >= maxLat)
@ -503,26 +440,21 @@ public class WayLinker extends MapCreatorBase implements Runnable
int[] fileHeaderCrcs = new int[25];
// write 5*5 index dummy
for ( int i55 = 0; i55 < 25; i55++ )
{
for (int i55 = 0; i55 < 25; i55++) {
os.writeLong(0);
}
long filepos = 200L;
// sort further in 1/divisor-degree squares
for ( int lonIdx = 0; lonIdx < nLonSegs; lonIdx++ )
{
for ( int latIdx = 0; latIdx < nLatSegs; latIdx++ )
{
for (int lonIdx = 0; lonIdx < nLonSegs; lonIdx++) {
for (int latIdx = 0; latIdx < nLatSegs; latIdx++) {
int tileIndex = lonIdx * nLatSegs + latIdx;
if ( seglists.getSize( tileIndex ) > 0 )
{
if (seglists.getSize(tileIndex) > 0) {
List<OsmNodeP> nlist = seglists.getList(tileIndex);
LazyArrayOfLists<OsmNodeP> subs = new LazyArrayOfLists<OsmNodeP>(ncaches);
byte[][] subByteArrays = new byte[ncaches][];
for ( int ni = 0; ni < nlist.size(); ni++ )
{
for (int ni = 0; ni < nlist.size(); ni++) {
OsmNodeP n = nlist.get(ni);
int subLonIdx = (n.ilon - minLon) / cellsize - divisor * lonIdx;
int subLatIdx = (n.ilat - minLat) / cellsize - divisor * latIdx;
@ -533,12 +465,10 @@ public class WayLinker extends MapCreatorBase implements Runnable
int[] posIdx = new int[ncaches];
int pos = indexsize;
for ( int si = 0; si < ncaches; si++ )
{
for (int si = 0; si < ncaches; si++) {
List<OsmNodeP> subList = subs.getList(si);
int size = subList.size();
if ( size > 0 )
{
if (size > 0) {
OsmNodeP n0 = subList.get(0);
int lonIdxDiv = n0.ilon / cellsize;
int latIdxDiv = n0.ilat / cellsize;
@ -546,46 +476,38 @@ public class WayLinker extends MapCreatorBase implements Runnable
// sort via treemap
TreeMap<Integer, OsmNodeP> sortedList = new TreeMap<Integer, OsmNodeP>();
for ( OsmNodeP n : subList )
{
for (OsmNodeP n : subList) {
long longId = n.getIdFromPos();
int shrinkid = mc.shrinkId(longId);
if ( mc.expandId( shrinkid ) != longId )
{
if (mc.expandId(shrinkid) != longId) {
throw new IllegalArgumentException("inconstistent shrinking: " + longId);
}
sortedList.put(Integer.valueOf(shrinkid), n);
}
for ( OsmNodeP n : sortedList.values() )
{
for (OsmNodeP n : sortedList.values()) {
n.writeNodeData(mc, trafficMap);
}
if ( mc.getSize() > 0 )
{
if (mc.getSize() > 0) {
byte[] subBytes;
for ( ;; )
{
for (; ; ) {
int len = mc.encodeMicroCache(abBuf1);
subBytes = new byte[len];
System.arraycopy(abBuf1, 0, subBytes, 0, len);
if ( skipEncodingCheck )
{
if (skipEncodingCheck) {
break;
}
// cross-check the encoding: re-instantiate the cache
MicroCache mc2 = new MicroCache2(new StatCoderContext(subBytes), new DataBuffers(null), lonIdxDiv, latIdxDiv, divisor, null, null);
// ..and check if still the same
String diffMessage = mc.compareWith(mc2);
if ( diffMessage != null )
{
if (diffMessage != null) {
if (MicroCache.debug)
throw new RuntimeException("encoding crosscheck failed: " + diffMessage);
else
MicroCache.debug = true;
}
else
} else
break;
}
pos += subBytes.length + 4; // reserve 4 bytes for crc
@ -598,11 +520,9 @@ public class WayLinker extends MapCreatorBase implements Runnable
byte[] abSubIndex = compileSubFileIndex(posIdx);
fileHeaderCrcs[tileIndex] = Crc32.crc(abSubIndex, 0, abSubIndex.length);
os.write(abSubIndex, 0, abSubIndex.length);
for ( int si = 0; si < ncaches; si++ )
{
for (int si = 0; si < ncaches; si++) {
byte[] ab = subByteArrays[si];
if ( ab != null )
{
if (ab != null) {
os.write(ab);
os.writeInt(Crc32.crc(ab, 0, ab.length) ^ microCacheEncoding);
}
@ -618,8 +538,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
// write extra data: timestamp + index-checksums
os.writeLong(creationTimeStamp);
os.writeInt(Crc32.crc(abFileIndex, 0, abFileIndex.length) ^ microCacheEncoding);
for ( int i55 = 0; i55 < 25; i55++ )
{
for (int i55 = 0; i55 < 25; i55++) {
os.writeInt(fileHeaderCrcs[i55]);
}
@ -630,20 +549,17 @@ public class WayLinker extends MapCreatorBase implements Runnable
ra.write(abFileIndex, 0, abFileIndex.length);
ra.close();
}
if ( trafficMap != null )
{
if (trafficMap != null) {
trafficMap.finish();
trafficMap = null;
}
System.out.println("**** codec stats: *******\n" + StatCoderContext.getBitReport());
}
private byte[] compileFileIndex( long[] fileIndex, short lookupVersion, short lookupMinorVersion ) throws Exception
{
private byte[] compileFileIndex(long[] fileIndex, short lookupVersion, short lookupMinorVersion) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
for ( int i55 = 0; i55 < 25; i55++ )
{
for (int i55 = 0; i55 < 25; i55++) {
long versionPrefix = i55 == 1 ? lookupMinorVersion : lookupVersion;
versionPrefix <<= 48;
dos.writeLong(fileIndex[i55] | versionPrefix);
@ -652,12 +568,10 @@ public class WayLinker extends MapCreatorBase implements Runnable
return bos.toByteArray();
}
private byte[] compileSubFileIndex( int[] posIdx ) throws Exception
{
private byte[] compileSubFileIndex(int[] posIdx) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
for ( int si = 0; si < posIdx.length; si++ )
{
for (int si = 0; si < posIdx.length; si++) {
dos.writeInt(posIdx[si]);
}
dos.close();

View File

@ -7,8 +7,7 @@ import java.io.File;
*
* @author ab
*/
public interface WayListener
{
public interface WayListener {
boolean wayFileStart(File wayfile) throws Exception;
void nextWay(WayData data) throws Exception;

View File

@ -5,14 +5,13 @@ import java.util.HashMap;
import org.junit.Assert;
import org.junit.Test;
import java.net.URL;
import java.io.File;
public class MapcreatorTest
{
public class MapcreatorTest {
@Test
public void mapcreatorTest() throws Exception
{
public void mapcreatorTest() throws Exception {
URL mapurl = this.getClass().getResource("/dreieich.osm.gz");
Assert.assertTrue("test-osm-map dreieich.osm not found", mapurl != null);
File mapFile = new File(mapurl.getFile());

View File

@ -14,14 +14,12 @@ 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 )
{
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);
@ -41,18 +39,14 @@ public final class DirectWeaver extends ByteDataWriter
bc.decodeSortedArray(faid, 0, size, 29, 0);
OsmNode[] nodes = new OsmNode[size];
for( int n = 0; n<size; n++ )
{
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 )
{
if (node == null) {
node = new OsmNode(ilon, ilat);
}
else
{
} else {
node.visitID = 1;
hollowNodes.remove(node);
}
@ -72,8 +66,7 @@ public final class DirectWeaver extends ByteDataWriter
// future escapes (turn restrictions?)
short trExceptions = 0;
for(;;)
{
for (; ; ) {
int featureId = bc.decodeVarBits();
if (featureId == 0) break;
int bitsize = bc.decodeNoisyNumber(5);
@ -81,8 +74,7 @@ public final class DirectWeaver extends ByteDataWriter
if (featureId == 2) // exceptions to turn-restriction
{
trExceptions = (short) bc.decodeBounded(1023);
}
else if ( featureId == 1 ) // turn-restriction
} else if (featureId == 1) // turn-restriction
{
TurnRestriction tr = new TurnRestriction();
tr.exceptions = trExceptions;
@ -93,9 +85,7 @@ public final class DirectWeaver extends ByteDataWriter
tr.toLon = ilon + bc.decodeNoisyDiff(10);
tr.toLat = ilat + bc.decodeNoisyDiff(10);
node.addTurnRestriction(tr);
}
else
{
} else {
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
}
}
@ -106,8 +96,7 @@ public final class DirectWeaver extends ByteDataWriter
node.nodeDescription = nodeTags == null ? null : nodeTags.data; // TODO: unified?
int links = bc.decodeNoisyNumber(1);
for( int li=0; li<links; li++ )
{
for (int li = 0; li < links; li++) {
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
int dlon_remaining;
@ -118,9 +107,7 @@ public final class DirectWeaver extends ByteDataWriter
{
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();
@ -136,41 +123,36 @@ public final class DirectWeaver extends ByteDataWriter
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++ )
{
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 )
{
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 ( 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);
}
@ -179,15 +161,13 @@ public final class DirectWeaver extends ByteDataWriter
{
OsmNode node2 = nodes[nodeIdx];
OsmLink link = node.isLinkUnused() ? node : (node2.isLinkUnused() ? node2 : null);
if ( link == null )
{
if (link == null) {
link = new OsmLink();
}
link.descriptionBitmap = wayTags.data;
link.geometry = geometry;
node.addLink(link, isReverse, node2);
}
else // weave external link
} else // weave external link
{
node.addLink(linklon, linklat, wayTags.data, geometry, hollowNodes, isReverse);
node.visitID = 1;
@ -203,23 +183,19 @@ public final class DirectWeaver extends ByteDataWriter
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++ )
{
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 )
{
for (int bm = 1; bm < 0x8000; bm <<= 1) {
if ((id32 & 1) != 0) dlon |= bm;
if ((id32 & 2) != 0) dlat |= bm;
id32 >>= 2;
@ -227,8 +203,7 @@ public final class DirectWeaver extends ByteDataWriter
return ((long) dlon) << 32 | dlat;
}
public long expandId( int id32 )
{
public long expandId(int id32) {
return id64Base + id32_00[id32 & 1023] + id32_10[(id32 >> 10) & 1023] + id32_20[(id32 >> 20) & 1023];
}
}

View File

@ -8,8 +8,7 @@ package btools.mapaccess;
import btools.util.ByteDataReader;
public final class GeometryDecoder
{
public final class GeometryDecoder {
private ByteDataReader r = new ByteDataReader(null);
private OsmTransferNode[] cachedNodes;
private int nCachedNodes = 128;
@ -19,20 +18,16 @@ 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 ) )
{
public OsmTransferNode decodeGeometry(byte[] geometry, OsmNode sourceNode, OsmNode targetNode, boolean reverseLink) {
if ((lastGeometry == geometry) && (lastReverse == reverseLink)) {
return firstTransferNode;
}
@ -44,8 +39,7 @@ public final class GeometryDecoder
int olat = startnode.ilat;
int oselev = startnode.selev;
int idx = 0;
while ( r.hasMoreData() )
{
while (r.hasMoreData()) {
OsmTransferNode trans = idx < nCachedNodes ? cachedNodes[idx++] : new OsmTransferNode();
trans.ilon = olon + r.readVarLengthSigned();
trans.ilat = olat + r.readVarLengthSigned();
@ -57,16 +51,11 @@ public final class GeometryDecoder
{
trans.next = firstTransferNode;
firstTransferNode = trans;
}
else
{
} else {
trans.next = null;
if ( lastTransferNode == null )
{
if (lastTransferNode == null) {
firstTransferNode = trans;
}
else
{
} else {
lastTransferNode.next = trans;
}
lastTransferNode = trans;

View File

@ -11,8 +11,7 @@ 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;
@ -22,8 +21,7 @@ public final class MatchedWaypoint
public boolean hasUpdate;
public void writeToStream( DataOutput dos ) throws IOException
{
public void writeToStream(DataOutput dos) throws IOException {
dos.writeInt(node1.ilat);
dos.writeInt(node1.ilon);
dos.writeInt(node2.ilat);
@ -35,8 +33,7 @@ public final class MatchedWaypoint
dos.writeDouble(radius);
}
public static MatchedWaypoint readFromStream( DataInput dis ) throws IOException
{
public static MatchedWaypoint readFromStream(DataInput dis) throws IOException {
MatchedWaypoint mwp = new MatchedWaypoint();
mwp.node1 = new OsmNode();
mwp.node2 = new OsmNode();

View File

@ -15,8 +15,7 @@ import btools.codec.MicroCache;
import btools.codec.WaypointMatcher;
import btools.expressions.BExpressionContextWay;
public final class NodesCache
{
public final class NodesCache {
private File segmentDir;
private File secondarySegmentsDir = null;
@ -51,13 +50,11 @@ public final class NodesCache
private boolean directWeaving = !Boolean.getBoolean("disableDirectWeaving");
public String formatStatus()
{
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();
@ -68,8 +65,7 @@ public final class NodesCache
this.forceSecondaryData = forceSecondaryData;
this.detailed = detailed;
if ( ctxWay != null )
{
if (ctxWay != null) {
ctxWay.setDecodeForbidden(detailed);
}
@ -79,33 +75,25 @@ public final class NodesCache
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 )
{
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
{
} else {
fileCache = new HashMap<String, PhysicalFile>(4);
fileRows = new OsmFile[180][];
dataBuffers = new DataBuffers();
@ -114,14 +102,11 @@ public final class NodesCache
ghostSum = cacheSum;
}
public void clean( boolean all )
{
for ( OsmFile[] fileRow : fileRows )
{
public void clean(boolean all) {
for (OsmFile[] fileRow : fileRows) {
if (fileRow == null)
continue;
for ( OsmFile osmf : fileRow )
{
for (OsmFile osmf : fileRow) {
osmf.clean(all);
}
}
@ -129,74 +114,56 @@ public final class NodesCache
// 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 )
{
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 )
{
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,32 +171,24 @@ public final class NodesCache
}
currentFileName = osmf.filename;
if ( !osmf.hasData() )
{
if (!osmf.hasData()) {
return null;
}
MicroCache segment = osmf.getMicroCache(ilon, ilat);
if ( segment == null )
{
if (segment == null) {
checkEnableCacheCleaning();
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)
{
} catch (Exception e) {
throw new RuntimeException("error reading datafile " + currentFileName + ": " + e, e);
}
}
@ -241,24 +200,20 @@ public final class NodesCache
*
* @return true if successfull, false if node is still hollow
*/
public boolean obtainNonHollowNode( OsmNode node )
{
public boolean obtainNonHollowNode(OsmNode node) {
if (!node.isHollow())
return true;
MicroCache segment = getSegmentFor(node.ilon, node.ilat);
if ( segment == null )
{
if (segment == null) {
return false;
}
if ( !node.isHollow() )
{
if (!node.isHollow()) {
return true; // direct weaving...
}
long id = node.getIdFromPos();
if ( segment.getAndClear( id ) )
{
if (segment.getAndClear(id)) {
node.parseNodeBody(segment, nodesMap, expCtxWay);
}
@ -271,14 +226,11 @@ public final class NodesCache
}
/**
* 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 ) )
{
public void expandHollowLinkTargets(OsmNode n) {
for (OsmLink link = n.firstlink; link != null; link = link.getNext(n)) {
obtainNonHollowNode(link.getTarget(n));
}
}
@ -286,12 +238,9 @@ public final class NodesCache
/**
* 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,85 +249,70 @@ 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);
n.setHollow();
nodesMap.put(n);
if ( !obtainNonHollowNode( n ) )
{
if (!obtainNonHollowNode(n)) {
return null;
}
expandHollowLinkTargets(n);
return n;
}
public OsmNode getGraphNode( OsmNode template )
{
public OsmNode getGraphNode(OsmNode template) {
OsmNode graphNode = new OsmNode(template.ilon, template.ilat);
graphNode.setHollow();
OsmNode existing = nodesMap.put(graphNode);
if ( existing == null )
{
if (existing == null) {
return graphNode;
}
nodesMap.put(existing);
return existing;
}
public void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs )
{
public void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs) {
waypointMatcher = new WaypointMatcherImpl(unmatchedWaypoints, maxDistance, islandNodePairs);
for( MatchedWaypoint mwp : unmatchedWaypoints )
{
for (MatchedWaypoint mwp : unmatchedWaypoints) {
preloadPosition(mwp.waypoint);
}
if ( first_file_access_failed )
{
if (first_file_access_failed) {
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
}
for( MatchedWaypoint mwp : unmatchedWaypoints )
{
if ( mwp.crosspoint == null )
{
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 )
{
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 )
{
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;
@ -392,27 +326,21 @@ public final class NodesCache
currentFileName = filenameBase + ".rd5";
PhysicalFile ra = null;
if ( !fileCache.containsKey( filenameBase ) )
{
if (!fileCache.containsKey(filenameBase)) {
File f = null;
if ( !forceSecondaryData )
{
if (!forceSecondaryData) {
File primary = new File(segmentDir, filenameBase + ".rd5");
if ( primary .exists() )
{
if (primary.exists()) {
f = primary;
}
}
if ( f == null )
{
if (f == null) {
File secondary = new File(secondarySegmentsDir, filenameBase + ".rd5");
if ( secondary.exists() )
{
if (secondary.exists()) {
f = secondary;
}
}
if ( f != null )
{
if (f != null) {
currentFileName = f.getName();
ra = new PhysicalFile(f, dataBuffers, lookupVersion, lookupMinorVersion);
}
@ -421,8 +349,7 @@ public final class NodesCache
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
{
public void close() {
for (PhysicalFile f : fileCache.values()) {
try {
if (f != null)
f.ra.close();
}
catch (IOException ioe)
{
} catch (IOException ioe) {
// ignore
}
}

View File

@ -6,8 +6,7 @@
package btools.mapaccess;
final class NodesList
{
final class NodesList {
public OsmNode node;
public NodesList next;
}

View File

@ -17,8 +17,7 @@ import btools.codec.WaypointMatcher;
import btools.util.ByteDataReader;
import btools.util.Crc32;
final class OsmFile
{
final class OsmFile {
private RandomAccessFile is = null;
private long fileOffset;
@ -35,16 +34,14 @@ final class OsmFile
private int ncaches;
private int indexsize;
public OsmFile( PhysicalFile rafile, int lonDegree, int latDegree, DataBuffers dataBuffers ) throws IOException
{
public OsmFile(PhysicalFile rafile, int lonDegree, int latDegree, DataBuffers dataBuffers) throws IOException {
this.lonDegree = lonDegree;
this.latDegree = latDegree;
int lonMod5 = lonDegree % 5;
int latMod5 = latDegree % 5;
int tileIndex = lonMod5 * 5 + latMod5;
if ( rafile != null )
{
if (rafile != null) {
divisor = rafile.divisor;
cellsize = 1000000 / divisor;
@ -65,30 +62,25 @@ final class OsmFile
is.seek(fileOffset);
is.readFully(iobuffer, 0, indexsize);
if ( rafile.fileHeaderCrcs != null )
{
if (rafile.fileHeaderCrcs != null) {
int headerCrc = Crc32.crc(iobuffer, 0, indexsize);
if ( rafile.fileHeaderCrcs[tileIndex] != headerCrc )
{
if (rafile.fileHeaderCrcs[tileIndex] != headerCrc) {
throw new IOException("sub index checksum error");
}
}
ByteDataReader dis = new ByteDataReader(iobuffer);
for ( int i = 0; i < ncaches; i++ )
{
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);
@ -96,8 +88,7 @@ final class OsmFile
}
public MicroCache createMicroCache(int ilon, int ilat, DataBuffers dataBuffers, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes)
throws Exception
{
throws Exception {
int lonIdx = ilon / cellsize;
int latIdx = ilat / cellsize;
MicroCache segment = createMicroCache(lonIdx, latIdx, dataBuffers, wayValidator, waypointMatcher, true, hollowNodes);
@ -106,21 +97,17 @@ final class OsmFile
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
{
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 )
{
if (size > 0) {
is.seek(fileOffset + startPos);
if ( size <= iobuffer.length )
{
if (size <= iobuffer.length) {
is.readFully(iobuffer, 0, size);
}
}
@ -128,52 +115,40 @@ final class OsmFile
}
public MicroCache createMicroCache(int lonIdx, int latIdx, DataBuffers dataBuffers, TagValueValidator wayValidator,
WaypointMatcher waypointMatcher, boolean reallyDecode, OsmNodesMap hollowNodes ) throws IOException
{
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);
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);
}
StatCoderContext bc = new StatCoderContext(ab);
try
{
if ( !reallyDecode )
{
try {
if (!reallyDecode) {
return null;
}
if ( hollowNodes == null )
{
if (hollowNodes == null) {
return new MicroCache2(bc, dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher);
}
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 )
{
if (readBytes != asize - 4) {
int crcData = Crc32.crc(ab, 0, asize - 4);
int crcFooter = new ByteDataReader(ab, asize - 4).readInt();
if ( crcData == crcFooter )
{
if (crcData == crcFooter) {
throw new IOException("old, unsupported data-format");
}
else if ( ( crcData ^ 2 ) != crcFooter )
{
} else if ((crcData ^ 2) != crcFooter) {
throw new IOException("checkum error");
}
}
@ -181,72 +156,58 @@ final class OsmFile
}
// 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)
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)
continue;
if ( !mc.ghost )
{
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)
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)
continue;
if ( all || !mc.virgin )
{
if (all || !mc.virgin) {
microCaches[i] = null;
}
}

View File

@ -6,9 +6,7 @@
package btools.mapaccess;
public class OsmLink
{
public class OsmLink {
/**
* The description bitmap contains the waytags (valid for both directions)
*/
@ -30,12 +28,10 @@ public class OsmLink
private OsmLinkHolder reverselinkholder = null;
private OsmLinkHolder firstlinkholder = null;
protected OsmLink()
{
protected OsmLink() {
}
public OsmLink( OsmNode source, OsmNode target )
{
public OsmLink(OsmNode source, OsmNode target) {
n1 = source;
n2 = target;
}
@ -43,8 +39,7 @@ public class OsmLink
/**
* Get the relevant target-node for the given source
*/
public final OsmNode getTarget( OsmNode source )
{
public final OsmNode getTarget(OsmNode source) {
return n2 != source && n2 != null ? n2 : n1;
/* if ( n2 != null && n2 != source )
{
@ -64,8 +59,7 @@ public class OsmLink
/**
* Get the relevant next-pointer for the given source
*/
public final OsmLink getNext( OsmNode source )
{
public final OsmLink getNext(OsmNode source) {
return n2 != source && n2 != null ? next : previous;
/* if ( n2 != null && n2 != source )
{
@ -84,69 +78,49 @@ public class OsmLink
/**
* Reset this link for the given direction
*/
protected final OsmLink clear( OsmNode source )
{
protected final OsmLink clear(OsmNode source) {
OsmLink n;
if ( n2 != null && n2 != source )
{
if (n2 != null && n2 != source) {
n = next;
next = null;
n2 = null;
firstlinkholder = null;
}
else if ( n1 != null && n1 != source )
{
} else if (n1 != null && n1 != source) {
n = previous;
previous = null;
n1 = null;
reverselinkholder = null;
}
else
{
} else {
throw new IllegalArgumentException("internal error: setNext: unknown source");
}
if ( n1 == null && n2 == null )
{
if (n1 == null && n2 == null) {
descriptionBitmap = null;
geometry = null;
}
return n;
}
public final void setFirstLinkHolder( OsmLinkHolder holder, OsmNode source )
{
if ( n2 != null && n2 != source )
{
public final void setFirstLinkHolder(OsmLinkHolder holder, OsmNode source) {
if (n2 != null && n2 != source) {
firstlinkholder = holder;
}
else if ( n1 != null && n1 != source )
{
} else if (n1 != null && n1 != source) {
reverselinkholder = holder;
}
else
{
} else {
throw new IllegalArgumentException("internal error: setFirstLinkHolder: unknown source");
}
}
public final OsmLinkHolder getFirstLinkHolder( OsmNode source )
{
if ( n2 != null && n2 != source )
{
public final OsmLinkHolder getFirstLinkHolder(OsmNode source) {
if (n2 != null && n2 != source) {
return firstlinkholder;
}
else if ( n1 != null && n1 != source )
{
} else if (n1 != null && n1 != source) {
return reverselinkholder;
}
else
{
} else {
throw new IllegalArgumentException("internal error: getFirstLinkHolder: unknown source");
}
}
public final boolean isReverse( OsmNode source )
{
public final boolean isReverse(OsmNode source) {
return n1 != source && n1 != null;
/* if ( n2 != null && n2 != source )
{
@ -162,20 +136,19 @@ public class OsmLink
} */
}
public final boolean isBidirectional()
{
public final boolean isBidirectional() {
return n1 != null && n2 != null;
}
public final boolean isLinkUnused()
{
public final boolean isLinkUnused() {
return n1 == null && n2 == null;
}
public final void addLinkHolder( OsmLinkHolder holder, OsmNode source )
{
public final void addLinkHolder(OsmLinkHolder holder, OsmNode source) {
OsmLinkHolder firstHolder = getFirstLinkHolder(source);
if ( firstHolder != null ) { holder.setNextForLink( firstHolder ); }
if (firstHolder != null) {
holder.setNextForLink(firstHolder);
}
setFirstLinkHolder(holder, source);
}

View File

@ -5,8 +5,7 @@
*/
package btools.mapaccess;
public interface OsmLinkHolder
{
public interface OsmLinkHolder {
void setNextForLink(OsmLinkHolder holder);
OsmLinkHolder getNextForLink();

View File

@ -11,8 +11,7 @@ import btools.util.ByteArrayUnifier;
import btools.util.CheapRuler;
import btools.util.IByteArrayUnifier;
public class OsmNode extends OsmLink implements OsmPos
{
public class OsmNode extends OsmLink implements OsmPos {
/**
* The latitude
*/
@ -37,8 +36,7 @@ public class OsmNode extends OsmLink implements OsmPos
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 )
{
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 )
{
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,33 +99,26 @@ public class OsmNode extends OsmLink implements OsmPos
}
}
public final int calcDistance( OsmPos p )
{
public final int calcDistance(OsmPos p) {
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
}
public String toString()
{
public String toString() {
return "n_" + (ilon - 180000000) + "_" + (ilat - 90000000);
}
public final void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay )
{
if ( mc instanceof MicroCache2 )
{
public final void parseNodeBody(MicroCache mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay) {
if (mc instanceof MicroCache2) {
parseNodeBody2((MicroCache2) mc, hollowNodes, expCtxWay);
}
else
} 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();
@ -154,8 +133,7 @@ public class OsmNode extends OsmLink implements OsmPos
int nodeDescSize = mc.readVarLengthUnsigned();
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();
@ -164,8 +142,7 @@ public class OsmNode extends OsmLink implements OsmPos
boolean isReverse = (sizecode & 1) != 0;
byte[] description = null;
int descSize = sizecode >> 1;
if ( descSize > 0 )
{
if (descSize > 0) {
description = mc.readUnified(descSize, expCtxWay);
}
byte[] geometry = mc.readDataUntil(endPointer);
@ -175,10 +152,8 @@ public class OsmNode extends OsmLink implements OsmPos
hollowNodes.remove(this);
}
public void addLink( int linklon, int linklat, byte[] description, byte[] geometry, OsmNodesMap hollowNodes, boolean isReverse )
{
if ( linklon == ilon && linklat == ilat )
{
public void addLink(int linklon, int linklat, byte[] description, byte[] geometry, OsmNodesMap hollowNodes, boolean isReverse) {
if (linklon == ilon && linklat == ilat) {
return; // skip self-ref
}
@ -186,14 +161,11 @@ public class OsmNode extends OsmLink implements OsmPos
OsmLink link = null;
// ...in our known links
for ( OsmLink l = firstlink; l != null; l = l.getNext( this ) )
{
for (OsmLink l = firstlink; l != null; l = l.getNext(this)) {
OsmNode t = l.getTarget(this);
if ( t.ilon == linklon && t.ilat == linklat )
{
if (t.ilon == linklon && t.ilat == linklat) {
tn = t;
if ( isReverse || ( l.descriptionBitmap == null && !l.isReverse( this ) ) )
{
if (isReverse || (l.descriptionBitmap == null && !l.isReverse(this))) {
link = l; // the correct one that needs our data
break;
}
@ -210,47 +182,37 @@ public class OsmNode extends OsmLink implements OsmPos
addLink(link = tn, isReverse, tn); // technical inheritance: link instance in node
}
}
if ( link == null )
{
if (link == null) {
addLink(link = new OsmLink(), isReverse, tn);
}
if ( !isReverse )
{
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()
{
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 )
{
while (l != null) {
OsmNode target = l.getTarget(this);
OsmLink nextLink = l.getNext(this);
if ( !target.isHollow() )
{
if (!target.isHollow()) {
unlinkLink(l);
if ( !l.isLinkUnused() )
{
if (!l.isLinkUnused()) {
target.unlinkLink(l);
}
}
@ -259,41 +221,32 @@ public class OsmNode extends OsmLink implements OsmPos
}
}
public final void unlinkLink( OsmLink link )
{
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
{
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
{
} else {
throw new IllegalArgumentException("unlinkLink: unknown source");
}
}
@ -301,14 +254,12 @@ public class OsmNode extends OsmLink implements OsmPos
@Override
public final boolean equals( Object o )
{
public final boolean equals(Object o) {
return ((OsmNode) o).ilon == ilon && ((OsmNode) o).ilat == ilat;
}
@Override
public final int hashCode()
{
public final int hashCode() {
return ilon + ilat;
}
}

View File

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

View File

@ -11,8 +11,7 @@ import java.util.HashMap;
import btools.util.ByteArrayUnifier;
import btools.util.SortedHeap;
public final class OsmNodesMap
{
public final class OsmNodesMap {
private HashMap<OsmNode, OsmNode> hmap = new HashMap<OsmNode, OsmNode>(4096);
private ByteArrayUnifier abUnifier = new ByteArrayUnifier(16384, false);
@ -34,46 +33,33 @@ public final class OsmNodesMap
public int cleanupMode = 0;
public void cleanupAndCount( OsmNode[] nodes )
{
if ( cleanupMode == 0 )
{
public void cleanupAndCount(OsmNode[] nodes) {
if (cleanupMode == 0) {
justCount(nodes);
}
else
{
} else {
cleanupPeninsulas(nodes);
}
}
private void justCount( OsmNode[] nodes )
{
for( int i=0; i<nodes.length; i++ )
{
private void justCount(OsmNode[] nodes) {
for (int i = 0; i < nodes.length; i++) {
OsmNode n = nodes[i];
if ( n.firstlink != null )
{
if (n.firstlink != null) {
nodesCreated++;
}
}
}
private void cleanupPeninsulas( OsmNode[] nodes )
{
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
{
if (n.firstlink != null) {
if (n.visitID == 1) {
try {
minVisitIdInSubtree(null, n);
}
catch( StackOverflowError soe )
{
} catch (StackOverflowError soe) {
// System.out.println( "+++++++++++++++ StackOverflowError ++++++++++++++++" );
}
}
@ -81,16 +67,14 @@ public final class OsmNodesMap
}
}
private int minVisitIdInSubtree( OsmNode source, OsmNode n )
{
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 )
{
for (OsmLink l = n.firstlink; l != null; l = nextLink) {
nextLink = l.getNext(n);
OsmNode t = l.getTarget(n);
@ -98,12 +82,9 @@ public final class OsmNodesMap
if (t.isHollow()) continue;
int minIdSub = t.visitID;
if ( minIdSub == 1 )
{
if (minIdSub == 1) {
minIdSub = baseID;
}
else if ( minIdSub == 0 )
{
} else if (minIdSub == 0) {
int nodesCreatedUntilHere = nodesCreated;
minIdSub = minVisitIdInSubtree(n, t);
if (minIdSub > n.visitID) // peninsula ?
@ -112,13 +93,9 @@ public final class OsmNodesMap
n.unlinkLink(l);
t.unlinkLink(l);
}
}
else if ( minIdSub < baseID )
{
} else if (minIdSub < baseID) {
continue;
}
else if ( cleanupMode == 2 )
{
} else if (cleanupMode == 2) {
minIdSub = baseID; // in tree-mode, hitting anything is like a gateway
}
if (minIdSub < minId) minId = minIdSub;
@ -127,23 +104,18 @@ public final class OsmNodesMap
}
public boolean isInMemoryBounds( int npaths, boolean extend )
{
public boolean isInMemoryBounds(int npaths, boolean extend) {
// long total = nodesCreated * 76L + linksCreated * 48L;
long total = nodesCreated * 95L + npaths * 200L;
if ( extend )
{
if (extend) {
total += 100000;
// when extending, try to have 1 MB space
long delta = total + 1900000 - currentmaxmem;
if ( delta > 0 )
{
if (delta > 0) {
currentmaxmem += delta;
if ( currentmaxmem > maxmem )
{
if (currentmaxmem > maxmem) {
currentmaxmem = maxmem;
}
}
@ -151,8 +123,7 @@ public final class OsmNodesMap
return total <= currentmaxmem;
}
private void addActiveNode( ArrayList<OsmNode> nodes2check, OsmNode n )
{
private void addActiveNode(ArrayList<OsmNode> nodes2check, OsmNode n) {
n.visitID = lastVisitID;
nodesCreated++;
nodes2check.add(n);
@ -160,45 +131,35 @@ public final class OsmNodesMap
// is there an escape from this node
// to a hollow node (or destination node) ?
public boolean canEscape( OsmNode n0 )
{
public boolean canEscape(OsmNode n0) {
boolean sawLowIDs = false;
lastVisitID++;
nodes2check.clear();
nodes2check.add(n0);
while ( !nodes2check.isEmpty() )
{
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
if ( n.visitID < baseID )
{
if (n.visitID < baseID) {
n.visitID = lastVisitID;
nodesCreated++;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
nodes2check.add(t);
}
}
else if ( n.visitID < lastVisitID )
{
} else if (n.visitID < lastVisitID) {
sawLowIDs = true;
}
}
if ( sawLowIDs )
{
if (sawLowIDs) {
return true;
}
nodes2check.add(n0);
while ( !nodes2check.isEmpty() )
{
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
if ( n.visitID == lastVisitID )
{
if (n.visitID == lastVisitID) {
n.visitID = lastVisitID;
nodesCreated--;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
nodes2check.add(t);
}
@ -211,71 +172,60 @@ public final class OsmNodesMap
private ArrayList<OsmNode> nodes2check;
public void clearTemp()
{
public void clearTemp() {
nodes2check = null;
}
public void collectOutreachers()
{
public void collectOutreachers() {
nodes2check = new ArrayList<OsmNode>(nodesCreated);
nodesCreated = 0;
for( OsmNode n : hmap.values() )
{
for (OsmNode n : hmap.values()) {
addActiveNode(nodes2check, n);
}
lastVisitID++;
baseID = lastVisitID;
while ( !nodes2check.isEmpty() )
{
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
n.visitID = lastVisitID;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
if ( t.visitID != lastVisitID )
{
if (t.visitID != lastVisitID) {
addActiveNode(nodes2check, t);
}
}
if ( destination != null && currentMaxCost < 1000000000 )
{
if (destination != null && currentMaxCost < 1000000000) {
int distance = n.calcDistance(destination);
if ( distance > currentMaxCost - currentPathCost + 100 )
{
if (distance > currentMaxCost - currentPathCost + 100) {
n.vanish();
}
}
if ( n.firstlink == null )
{
if (n.firstlink == null) {
nodesCreated--;
}
}
}
public ByteArrayUnifier getByteArrayUnifier()
{
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 )
{
public OsmNode get(int ilon, int ilat) {
testKey.ilon = ilon;
testKey.ilat = ilat;
return hmap.get(testKey);
}
public void remove( OsmNode node )
{
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);
@ -284,37 +234,32 @@ public final class OsmNodesMap
/**
* Put a node into the map
*
* @return the previous node if that id existed, else null
*/
public OsmNode put( OsmNode node )
{
public OsmNode put(OsmNode node) {
return hmap.put(node, node);
}
// ********************** test cleanup **********************
private static void addLinks( OsmNode[] nodes, int idx, boolean isBorder, int[] links )
{
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 )
{
for (int i : links) {
OsmNode t = nodes[i];
OsmLink link = n.isLinkUnused() ? n : (t.isLinkUnused() ? t : null);
if ( link == null )
{
if (link == null) {
link = new OsmLink();
}
n.addLink(link, false, t);
}
}
public static void main( String[] args )
{
public static void main(String[] args) {
OsmNode[] nodes = new OsmNode[12];
for( int i=0; i<nodes.length; i++ )
{
for (int i = 0; i < nodes.length; i++) {
nodes[i] = new OsmNode((i + 1000) * 1000, (i + 1000) * 1000);
}

View File

@ -6,8 +6,7 @@
package btools.mapaccess;
public interface OsmPos
{
public interface OsmPos {
public int getILat();
public int getILon();

View File

@ -6,10 +6,7 @@
package btools.mapaccess;
public final class OsmTransferNode
{
public final class OsmTransferNode {
public OsmTransferNode next;
public int ilon;

View File

@ -14,8 +14,7 @@ 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;
@ -27,8 +26,7 @@ final public class PhysicalFile
public int divisor = 80;
public static void main( String[] args )
{
public static void main(String[] args) {
MicroCache.debug = true;
try {
@ -45,11 +43,9 @@ 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);
int div = pf.divisor;
@ -64,35 +60,27 @@ final public class PhysicalFile
osmf.createMicroCache(lonDegree * div + lonIdx, latDegree * div + latIdx, dataBuffers, null, null, MicroCache.debug, null);
}
}
}
finally
{
} finally {
if (pf != null)
try
{
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++ )
{
for (int i = 0; i < 25; i++) {
long lv = dis.readLong();
short readVersion = (short) (lv >> 48);
if ( i == 0 && lookupVersion != -1 && readVersion != lookupVersion )
{
if (i == 0 && lookupVersion != -1 && readVersion != lookupVersion) {
throw new IOException("lookup version mismatch (old rd5?) lookups.dat="
+ lookupVersion + " " + f.getAbsolutePath() + "=" + readVersion);
}
@ -118,21 +106,15 @@ final public class PhysicalFile
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
{
} else {
throw new IOException("top index checksum error");
}
fileHeaderCrcs = new int[25];
for( int i=0; i<25; i++ )
{
for (int i = 0; i < 25; i++) {
fileHeaderCrcs[i] = dis.readInt();
}
}

View File

@ -13,38 +13,31 @@ import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
final public class Rd5DiffManager
{
public static void main( String[] args ) throws Exception
{
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
{
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() )
{
if (!fo.isFile()) {
continue;
}
@ -70,23 +63,18 @@ final public class Rd5DiffManager
// ... and add that to old diff files
File specificOldDiffs = new File(oldDiffDir, basename);
if ( specificOldDiffs.isDirectory() )
{
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() )
{
if (!updatedDiff.exists()) {
Rd5DiffTool.addDeltas(od, diffFile, updatedDiff);
updatedDiff.setLastModified(od.lastModified());
}
@ -95,8 +83,7 @@ final public class Rd5DiffManager
}
}
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));
@ -122,8 +109,7 @@ final public class Rd5DiffManager
}
}
private static char hexChar( int v )
{
private static char hexChar(int v) {
return (char) (v > 9 ? 'a' + (v - 10) : '0' + v);
}
}

View File

@ -22,29 +22,20 @@ 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 )
{
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" ) )
{
if (args[1].endsWith(".df5")) {
if (args[0].endsWith(".df5")) {
addDeltas(new File(args[0]), new File(args[1]), new File(args[2]));
}
else
{
} else {
recoverFromDelta(new File(args[0]), new File(args[1]), new File(args[2]), new Rd5DiffTool() /*, new File( args[3] ) */);
}
}
else
{
} else {
diff2files(new File(args[0]), new File(args[1]), new File(args[2]));
}
}
@ -55,69 +46,55 @@ final public class Rd5DiffTool implements ProgressListener
}
@Override
public boolean isCanceled()
{
public boolean isCanceled() {
return false;
}
private static long[] readFileIndex( DataInputStream dis, DataOutputStream dos ) throws IOException
{
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 )
{
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 )
{
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 )
{
if (size == 0) {
return null;
}
if ( deltaMode )
{
if (deltaMode) {
size = dis.readInt();
}
byte[] ab = new byte[size];
@ -125,10 +102,8 @@ final public class Rd5DiffTool implements ProgressListener
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);
@ -139,8 +114,7 @@ final public class Rd5DiffTool implements ProgressListener
* 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];
@ -160,28 +134,23 @@ final public class Rd5DiffTool implements ProgressListener
long t0 = System.currentTimeMillis();
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
for ( int subFileIdx = 0; subFileIdx < 25; 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;
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
{
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 ) )
{
if (Arrays.equals(ab1, ab2)) {
mc = MicroCache.emptyCache(); // empty diff
}
else // calc diff of the 2 tiles
} else // calc diff of the 2 tiles
{
MicroCache mc1 = createMicroCache(ab1, dataBuffers);
MicroCache mc2 = createMicroCache(ab2, dataBuffers);
@ -190,8 +159,7 @@ final public class Rd5DiffTool implements ProgressListener
}
int len = mcOut.writeMC(mc);
if ( len > 0 )
{
if (len > 0) {
bytesDiff += len;
nodesDiff += mc.getSize();
diffedTiles++;
@ -238,58 +206,40 @@ final public class Rd5DiffTool implements ProgressListener
}
// write any remaining data to the output file
for(;;)
{
for (; ; ) {
int len = dis2.read(abBuf1);
if (len < 0)
{
if (len < 0) {
break;
}
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
{
} 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 )
{
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;
}
@ -313,13 +263,11 @@ final public class Rd5DiffTool implements ProgressListener
int lastPct = -1;
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
MCInputStream mcIn = new MCInputStream(dis2, dataBuffers);
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
{
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
@ -330,17 +278,14 @@ final public class Rd5DiffTool implements ProgressListener
// int[] posIdxCmp = hasDataCmp ? readPosIndex( disCmp, null ) : null;
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
{
if ( progress.isCanceled() )
{
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 )
{
if (pct != lastPct) {
progress.updateProgress("Applying delta", pct);
lastPct = pct;
}
@ -356,15 +301,12 @@ final public class Rd5DiffTool implements ProgressListener
*/
// no-delta shortcut: just copy base data
if ( mc2.getSize() == 0 )
{
if ( ab1 != null )
{
if (mc2.getSize() == 0) {
if (ab1 != null) {
dos.write(ab1);
}
int newTargetSize = ab1 == null ? 0 : ab1.length;
if ( targetSize != newTargetSize )
{
if (targetSize != newTargetSize) {
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "!=" + newTargetSize);
}
continue;
@ -377,10 +319,8 @@ final public class Rd5DiffTool implements ProgressListener
MicroCache mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
mc.addDelta(mc1, mc2, false);
if ( mc.size() == 0 )
{
if ( targetSize != 0 )
{
if (mc.size() == 0) {
if (targetSize != 0) {
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + ">0");
}
continue;
@ -408,8 +348,7 @@ final public class Rd5DiffTool implements ProgressListener
*/
dos.write(abBuf1, 0, len);
dos.writeInt(Crc32.crc(abBuf1, 0, len) ^ 2);
if ( targetSize != len+4 )
{
if (targetSize != len + 4) {
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "<>" + (len + 4));
}
@ -417,121 +356,86 @@ final public class Rd5DiffTool implements ProgressListener
mcIn.finish();
}
// write any remaining data to the output file
for(;;)
{
for (; ; ) {
int len = dis2.read(abBuf1);
if (len < 0)
{
if (len < 0) {
break;
}
dos.write(abBuf1, 0, len);
}
long t1 = System.currentTimeMillis();
System.out.println("recovering from diffs took " + (t1 - t0) + "ms");
}
finally
{
if ( dis1 != null )
{
try
{
} 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)));
int lastPct = -1;
long sizeTotal = f1.length();
long sizeRead = 0L;
try
{
try {
byte buf[] = new byte[65536];
for (;;)
{
if ( progress.isCanceled() )
{
for (; ; ) {
if (progress.isCanceled()) {
canceled = true;
return;
}
int pct = (int) ((100. * sizeRead) / (sizeTotal + 1) + 0.5);
if ( pct != lastPct )
{
if (pct != lastPct) {
progress.updateProgress("Copying", pct);
lastPct = pct;
}
int len = dis1.read(buf);
if ( len <= 0 )
{
if (len <= 0) {
break;
}
sizeRead += 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];
@ -545,32 +449,26 @@ final public class Rd5DiffTool implements ProgressListener
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);
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
{
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++ )
{
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
MicroCache mc1 = mcIn1.readMC();
MicroCache mc2 = mcIn2.readMC();
MicroCache mc;
if ( mc1.getSize() == 0 && mc2.getSize() == 0 )
{
if (mc1.getSize() == 0 && mc2.getSize() == 0) {
mc = mc1;
}
else
{
} else {
mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
mc.addDelta(mc1, mc2, true);
}
@ -581,56 +479,39 @@ final public class Rd5DiffTool implements ProgressListener
mcOut.finish();
}
// write any remaining data to the output file
for(;;)
{
for (; ; ) {
int len = dis2.read(abBuf1);
if (len < 0)
{
if (len < 0) {
break;
}
dos.write(abBuf1, 0, len);
}
long t1 = System.currentTimeMillis();
System.out.println("adding diffs took " + (t1 - t0) + "ms");
}
finally
{
if ( dis1 != null )
{
try
{
} 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)));
@ -641,17 +522,14 @@ final public class Rd5DiffTool implements ProgressListener
long t0 = System.currentTimeMillis();
try
{
try {
DataBuffers dataBuffers = new DataBuffers();
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
{
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
int[] posIdx1 = hasData1 ? readPosIndex(dis1, dos) : null;
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
{
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
if (ab1 == null) continue;
@ -665,67 +543,50 @@ final public class Rd5DiffTool implements ProgressListener
}
}
// write any remaining data to the output file
for(;;)
{
for (; ; ) {
int len = dis1.read(abBuf1);
if (len < 0)
{
if (len < 0) {
break;
}
dos.write(abBuf1, 0, len);
}
long t1 = System.currentTimeMillis();
System.out.println("re-encoding took " + (t1 - t0) + "ms");
}
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) {
}
}
}
}
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);
skips = 0;
int len = mc.encodeMicroCache(buffer);
if ( len == 0 )
{
if (len == 0) {
throw new IllegalArgumentException("encoded buffer of non-empty micro-cache cannot be empty");
}
dos.writeInt(len);
@ -733,38 +594,31 @@ final public class Rd5DiffTool implements ProgressListener
return len;
}
public void finish() throws Exception
{
if ( skips > 0 )
{
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);
@ -775,8 +629,7 @@ final public class Rd5DiffTool implements ProgressListener
return mc;
}
public void finish()
{
public void finish() {
skips = -1;
}
}

View File

@ -7,38 +7,31 @@ package btools.mapaccess;
import java.io.File;
final public class Rd5DiffValidator
{
public static void main( String[] args ) throws Exception
{
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
{
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() )
{
if (!fo.isFile()) {
continue;
}
@ -60,8 +53,7 @@ final public class Rd5DiffValidator
Rd5DiffTool.recoverFromDelta(fo, diffFile, fcmp, new Rd5DiffTool());
String md5Cmp = Rd5DiffManager.getMD5(fcmp);
if ( !md5Cmp.equals( md5New ) )
{
if (!md5Cmp.equals(md5New)) {
throw new RuntimeException("**************** md5 mismatch!! *****************");
}
}

View File

@ -9,51 +9,38 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class StorageConfigHelper
{
public static File getSecondarySegmentDir( File segmentDir )
{
public class StorageConfigHelper {
public static File getSecondarySegmentDir(File segmentDir) {
return getStorageLocation(segmentDir, "secondary_segment_dir=");
}
public static File getAdditionalMaptoolDir( File segmentDir )
{
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
{
try {
br = new BufferedReader(new FileReader(configFile));
for ( ;; )
{
for (; ; ) {
String line = br.readLine();
if (line == null) break;
line = line.trim();
if (line.startsWith("#")) continue;
if ( line.startsWith( tag ) )
{
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;

Some files were not shown because too many files have changed in this diff Show More