Merge pull request #449 from zod/reformat-codebase

Reformat codebase
This commit is contained in:
afischerdev 2022-10-03 17:49:04 +02:00 committed by GitHub
commit 9662e50a43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
164 changed files with 15131 additions and 18545 deletions

View File

@ -7,3 +7,6 @@
# Reformat brouter-routing-app using Android Studio
54d5c5e9439be2c3df4c95b6fc12d33fdcc9b389
# Reformat whole codebase using Android Studio
c15913c1ab9befd8d583d4a7716d5043d2966f64

View File

@ -5,11 +5,10 @@ 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 );
public BitCoderContext bctx1 = new BitCoderContext(tagbuf1);
public byte[] bbuf1 = new byte[65636];
public int[] ibuf1 = new int[4096];
public int[] ibuf2 = new int[2048];
@ -17,17 +16,15 @@ public final class DataBuffers
public int[] alon = new int[2048];
public int[] alat = new int[2048];
public DataBuffers()
{
this( new byte[65636] );
public DataBuffers() {
this(new byte[65636]);
}
/**
* 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,14 +26,11 @@ 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 );
System.arraycopy(a, 0, aa, 0, size);
a = aa;
}
a[size++] = value;
@ -46,16 +40,13 @@ public class IntegerFifo3Pass
/**
* reads from the fifo in pass3 (in pass1/2 returns just 1)
*/
public int getNext()
{
return pass == 3 ? get( pos++ ) : 1;
public int getNext() {
return pass == 3 ? get(pos++) : 1;
}
private int get( int idx )
{
if ( idx >= size )
{
throw new IndexOutOfBoundsException( "list size=" + size + " idx=" + idx );
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,16 +11,15 @@ 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 )
{
ia = defaultbuffer == null ? new int[nlists*4] : defaultbuffer;
public LinkedListContainer(int nlists, int[] defaultbuffer) {
ia = defaultbuffer == null ? new int[nlists * 4] : defaultbuffer;
startpointer = new int[nlists];
}
@ -31,14 +29,12 @@ 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 ];
startpointer[ listNr ] = size;
ia[size++] = startpointer[listNr];
startpointer[listNr] = size;
ia[size++] = data;
}
@ -48,13 +44,11 @@ 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 )
{
lp = ia[ lp-1 ];
int lp = listpointer = startpointer[listNr];
while (lp != 0) {
lp = ia[lp - 1];
cnt++;
}
return cnt;
@ -67,21 +61,18 @@ public class LinkedListContainer
* @return the data element
* @throws IllegalArgumentException if no more element
*/
public int getDataElement()
{
if ( listpointer == 0 )
{
throw new IllegalArgumentException( "no more element!" );
public int getDataElement() {
if (listpointer == 0) {
throw new IllegalArgumentException("no more element!");
}
int data = ia[ listpointer ];
listpointer = ia[ listpointer-1 ];
int data = ia[listpointer];
listpointer = ia[listpointer - 1];
return data;
}
private void resize()
{
int[] ia2 = new int[2*ia.length];
System.arraycopy( ia, 0, ia2, 0, ia.length );
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 )
{
super( ab );
protected MicroCache(byte[] ab) {
super(ab);
}
public final static MicroCache emptyNonVirgin = new MicroCache( null );
public final static MicroCache emptyNonVirgin = new MicroCache(null);
static
{
static {
emptyNonVirgin.virgin = false;
}
public static MicroCache emptyCache()
{
return new MicroCache( null ); // TODO: singleton?
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 );
faid[size] = shrinkId(id);
size++;
}
public final void discardNode()
{
aboffset = startPos( size );
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,38 +89,31 @@ 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 );
int id = shrinkId(id64);
int[] a = faid;
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 )
{
aboffset = startPos( n );
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,43 +121,35 @@ 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 )
{
int start = startPos( i );
if ((pos & 0x80000000) == 0) {
int start = startPos(i);
int end = fapos[i];
int len = end - start;
System.arraycopy( ab, start, nab, nab_off, len );
System.arraycopy(ab, start, nab, nab_off, len);
nfaid[idx] = faid[i];
nab_off += len;
nfapos[idx] = nab_off;
@ -185,17 +161,15 @@ public class MicroCache extends ByteDataWriter
ab = nab;
}
int deleted = delbytes;
init( nsize );
init(nsize);
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,10 +177,9 @@ 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 );
return expandId(id32);
}
/**
@ -214,9 +187,8 @@ public class MicroCache extends ByteDataWriter
*
* @see #shrinkId
*/
public long expandId( int id32 )
{
throw new IllegalArgumentException( "expandId for empty cache" );
public long expandId(int id32) {
throw new IllegalArgumentException("expandId for empty cache");
}
/**
@ -224,29 +196,25 @@ public class MicroCache extends ByteDataWriter
*
* @see #expandId
*/
public int shrinkId( long id64 )
{
throw new IllegalArgumentException( "shrinkId for empty cache" );
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 )
{
throw new IllegalArgumentException( "isInternal for empty cache" );
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 )
{
throw new IllegalArgumentException( "encodeMicroCache for empty cache" );
public int encodeMicroCache(byte[] buffer) {
throw new IllegalArgumentException("encodeMicroCache for empty cache");
}
/**
@ -254,109 +222,86 @@ public class MicroCache extends ByteDataWriter
*
* @return null if equals, else a diff-report
*/
public String compareWith( MicroCache mc )
{
String msg = _compareWith( mc );
if ( msg != null )
{
StringBuilder sb = new StringBuilder( msg );
sb.append( "\nencode cache:\n" ).append( summary() );
sb.append( "\ndecode cache:\n" ).append( mc.summary() );
public String compareWith(MicroCache mc) {
String msg = _compareWith(mc);
if (msg != null) {
StringBuilder sb = new StringBuilder(msg);
sb.append("\nencode cache:\n").append(summary());
sb.append("\ndecode cache:\n").append(mc.summary());
return sb.toString();
}
return null;
}
private String summary()
{
StringBuilder sb = new StringBuilder( "size=" + size + " aboffset=" + aboffset );
for ( int i = 0; i < size; i++ )
{
sb.append( "\nidx=" + i + " faid=" + faid[i] + " fapos=" + fapos[i] );
private String summary() {
StringBuilder sb = new StringBuilder("size=" + size + " aboffset=" + aboffset);
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
{
write(mc2.ab, start2, len2);
} else {
idx1++;
id = id1; // deleted node
}
@ -366,35 +311,31 @@ 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
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 )
{
write( mc2.ab, start2, len2 );
if (keepEmptyNodes || len2 > 0) {
write(mc2.ab, start2, len2);
fapos[size] = aboffset;
faid[size++] = id2;
}
if ( id1 == id2 ) // // id exists in both caches
if (id1 == id2) // // id exists in both caches
{
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;
write( mc1.ab, start1, len1 );
write(mc1.ab, start1, len1);
fapos[size] = aboffset;
faid[size++] = id1;
}

View File

@ -9,78 +9,73 @@ 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 )
{
super( databuffer ); // sets ab=databuffer, aboffset=0
public MicroCache2(int size, byte[] databuffer, int lonIdx, int latIdx, int divisor) {
super(databuffer); // sets ab=databuffer, aboffset=0
faid = new int[size];
fapos = new int[size];
this.size = 0;
cellsize = 1000000 / divisor;
lonBase = lonIdx*cellsize;
latBase = latIdx*cellsize;
lonBase = lonIdx * cellsize;
latBase = latIdx * cellsize;
}
public byte[] readUnified( int len, IByteArrayUnifier u )
{
byte[] b = u.unify( ab, aboffset, len );
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 )
{
super( null );
public MicroCache2(StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher) {
super(null);
cellsize = 1000000 / divisor;
lonBase = lonIdx*cellsize;
latBase = latIdx*cellsize;
lonBase = lonIdx * cellsize;
latBase = latIdx * cellsize;
TagValueCoder wayTagCoder = new TagValueCoder( bc, dataBuffers, wayValidator );
TagValueCoder nodeTagCoder = new TagValueCoder( bc, dataBuffers, null );
NoisyDiffCoder nodeIdxDiff = new NoisyDiffCoder( bc );
NoisyDiffCoder nodeEleDiff = new NoisyDiffCoder( bc );
TagValueCoder wayTagCoder = new TagValueCoder(bc, dataBuffers, wayValidator);
TagValueCoder nodeTagCoder = new TagValueCoder(bc, dataBuffers, null);
NoisyDiffCoder nodeIdxDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder nodeEleDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder extLonDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder extLatDiff = new NoisyDiffCoder(bc);
NoisyDiffCoder transEleDiff = new NoisyDiffCoder( bc );
NoisyDiffCoder transEleDiff = new NoisyDiffCoder(bc);
size = bc.decodeNoisyNumber( 5 );
size = bc.decodeNoisyNumber(5);
faid = size > dataBuffers.ibuf2.length ? new int[size] : dataBuffers.ibuf2;
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 );
bc.decodeSortedArray(faid, 0, size, 29, 0);
for( int n = 0; n<size; n++ )
{
long id64 = expandId( faid[n] );
alon[n] = (int)(id64 >> 32);
alat[n] = (int)(id64 & 0xffffffff);
for (int n = 0; n < size; n++) {
long id64 = expandId(faid[n]);
alon[n] = (int) (id64 >> 32);
alat[n] = (int) (id64 & 0xffffffff);
}
int netdatasize = bc.decodeNoisyNumber( 10 );
int netdatasize = bc.decodeNoisyNumber(10);
ab = netdatasize > dataBuffers.bbuf1.length ? new byte[netdatasize] : dataBuffers.bbuf1;
aboffset = 0;
int[] validBits = new int[(size+31)>>5];
int[] validBits = new int[(size + 31) >> 5];
int finaldatasize = 0;
LinkedListContainer reverseLinks = new LinkedListContainer( size, dataBuffers.ibuf1 );
LinkedListContainer reverseLinks = new LinkedListContainer(size, dataBuffers.ibuf1);
int selev = 0;
for( int n=0; n<size; n++ ) // loop over nodes
for (int n = 0; n < size; n++) // loop over nodes
{
int ilon = alon[n];
int ilat = alat[n];
@ -88,49 +83,44 @@ 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
validBits[n >> 5] |= 1 << n; // mark dummy-node valid
continue; // empty node escape (delta files only)
}
while( featureId != 0 )
{
int bitsize = bc.decodeNoisyNumber( 5 );
while (featureId != 0) {
int bitsize = bc.decodeNoisyNumber(5);
if ( featureId == 2 ) // exceptions to turn-restriction
if (featureId == 2) // exceptions to turn-restriction
{
trExceptions = (short)bc.decodeBounded( 1023 );
}
else if ( featureId == 1 ) // turn-restriction
trExceptions = (short) bc.decodeBounded(1023);
} else if (featureId == 1) // turn-restriction
{
writeBoolean( true );
writeShort( trExceptions ); // exceptions from previous feature
writeBoolean(true);
writeShort(trExceptions); // exceptions from previous feature
trExceptions = 0;
writeBoolean( bc.decodeBit() ); // isPositive
writeInt( ilon + bc.decodeNoisyDiff( 10 ) ); // fromLon
writeInt( ilat + bc.decodeNoisyDiff( 10 ) ); // fromLat
writeInt( ilon + bc.decodeNoisyDiff( 10 ) ); // toLon
writeInt( ilat + bc.decodeNoisyDiff( 10 ) ); // toLat
}
else
{
for( int i=0; i< bitsize; i++ ) bc.decodeBit(); // unknown feature, just skip
writeBoolean(bc.decodeBit()); // isPositive
writeInt(ilon + bc.decodeNoisyDiff(10)); // fromLon
writeInt(ilat + bc.decodeNoisyDiff(10)); // fromLat
writeInt(ilon + bc.decodeNoisyDiff(10)); // toLon
writeInt(ilat + bc.decodeNoisyDiff(10)); // toLat
} else {
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
}
featureId = bc.decodeVarBits();
}
writeBoolean( false );
writeBoolean(false);
selev += nodeEleDiff.decodeSignedValue();
writeShort( (short) selev );
writeShort((short) selev);
TagValueWrapper nodeTags = nodeTagCoder.decodeTagValueSet();
writeVarBytes( nodeTags == null ? null : nodeTags.data );
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++ )
{
int links = bc.decodeNoisyNumber(1);
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();
@ -138,78 +128,72 @@ public final class MicroCache2 extends MicroCache
int dlat_remaining;
boolean isReverse = false;
if ( nodeIdx != n ) // internal (forward-) link
if (nodeIdx != n) // internal (forward-) link
{
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();
writeVarLengthSigned( dlon_remaining );
writeVarLengthSigned( dlat_remaining );
writeVarLengthSigned(dlon_remaining);
writeVarLengthSigned(dlat_remaining);
validBits[ n >> 5 ] |= 1 << n; // mark source-node valid
if ( nodeIdx != n ) // valid internal (forward-) link
validBits[n >> 5] |= 1 << n; // mark source-node valid
if (nodeIdx != n) // valid internal (forward-) link
{
reverseLinks.addDataElement( nodeIdx, n ); // register reverse link
finaldatasize += 1 + aboffset-startPointer; // reserve place for reverse
validBits[ nodeIdx >> 5 ] |= 1 << nodeIdx; // mark target-node valid
reverseLinks.addDataElement(nodeIdx, n); // register reverse link
finaldatasize += 1 + aboffset - startPointer; // reserve place for reverse
validBits[nodeIdx >> 5] |= 1 << nodeIdx; // mark target-node valid
}
writeModeAndDesc( isReverse, wayTags == null ? null : wayTags.data );
writeModeAndDesc(isReverse, wayTags == null ? null : wayTags.data);
}
if ( !isReverse ) // write geometry for forward links only
if (!isReverse) // write geometry for forward links only
{
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
int ilontarget = ilon + dlon_remaining;
int ilattarget = ilat + dlat_remaining;
if ( matcher != null )
{
if ( !matcher.start( ilon, ilat, ilontarget, ilattarget ) )
{
if (matcher != null) {
if (!matcher.start(ilon, ilat, ilontarget, ilattarget)) {
matcher = null;
}
}
int transcount = bc.decodeVarBits();
if ( debug ) System.out.println( "*** decoding geometry with count=" + transcount );
int count = transcount+1;
for( int i=0; i<transcount; i++ )
{
int dlon = bc.decodePredictedValue( dlon_remaining/count );
int dlat = bc.decodePredictedValue( dlat_remaining/count );
if (debug) System.out.println("*** decoding geometry with count=" + transcount);
int count = transcount + 1;
for (int i = 0; i < transcount; i++) {
int dlon = bc.decodePredictedValue(dlon_remaining / count);
int dlat = bc.decodePredictedValue(dlat_remaining / count);
dlon_remaining -= dlon;
dlat_remaining -= dlat;
count--;
int elediff = transEleDiff.decodeSignedValue();
if ( wayTags != null )
{
writeVarLengthSigned( dlon );
writeVarLengthSigned( dlat );
writeVarLengthSigned( elediff );
if (wayTags != null) {
writeVarLengthSigned(dlon);
writeVarLengthSigned(dlat);
writeVarLengthSigned(elediff);
}
if ( matcher != null ) matcher.transferNode( ilontarget - dlon_remaining, ilattarget - dlat_remaining );
if (matcher != null)
matcher.transferNode(ilontarget - dlon_remaining, ilattarget - dlat_remaining);
}
if ( matcher != null ) matcher.end();
if (matcher != null) matcher.end();
}
if ( linkValid )
{
injectSize( sizeoffset );
if (linkValid) {
injectSize(sizeoffset);
}
}
fapos[n] = aboffset;
@ -218,12 +202,10 @@ 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 )
{
finaldatasize += endpos-startpos;
if ((validBits[i >> 5] & (1 << i)) != 0) {
finaldatasize += endpos - startpos;
finalsize++;
}
startpos = endpos;
@ -240,29 +222,26 @@ 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 )
System.out.println( "*** copied " + len + " bytes from " + aboffset + " for node " + n );
System.arraycopy(abOld, startpos, ab, aboffset, len);
if (debug)
System.out.println("*** copied " + len + " bytes from " + aboffset + " for node " + n);
aboffset += len;
int cnt = reverseLinks.initList( n );
if ( debug )
System.out.println( "*** appending " + cnt + " reverse links for node " + n );
int cnt = reverseLinks.initList(n);
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] );
writeVarLengthSigned( alat[nodeIdx] - alat[n] );
writeModeAndDesc( true, null );
injectSize( sizeoffset );
writeVarLengthSigned(alon[nodeIdx] - alon[n]);
writeVarLengthSigned(alat[nodeIdx] - alat[n]);
writeModeAndDesc(true, null);
injectSize(sizeoffset);
}
faid[size] = faidOld[n];
fapos[size] = aboffset;
@ -270,65 +249,59 @@ public final class MicroCache2 extends MicroCache
}
startpos = endpos;
}
init( size );
init(size);
}
@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 )
{
if ( (id32 & 1) != 0 ) dlon |= bm;
if ( (id32 & 2) != 0 ) dlat |= bm;
for (int bm = 1; bm < 0x8000; bm <<= 1) {
if ((id32 & 1) != 0) dlon |= bm;
if ((id32 & 2) != 0) dlat |= bm;
id32 >>= 2;
}
int lon32 = lonBase + dlon;
int lat32 = latBase + dlat;
return ((long)lon32)<<32 | lat32;
return ((long) lon32) << 32 | lat32;
}
@Override
public int shrinkId( long id64 )
{
int lon32 = (int)(id64 >> 32);
int lat32 = (int)(id64 & 0xffffffff);
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;
if ((dlon & bm) != 0) id32 |= 1;
if ((dlat & bm) != 0) id32 |= 2;
}
return id32;
}
@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
{
HashMap<Long,Integer> idMap = new HashMap<Long,Integer>();
for( int n=0; n<size; n++ ) // loop over nodes
{
idMap.put( Long.valueOf( expandId( faid[n] ) ), Integer.valueOf( n ) );
idMap.put(Long.valueOf(expandId(faid[n])), Integer.valueOf(n));
}
IntegerFifo3Pass linkCounts = new IntegerFifo3Pass( 256 );
IntegerFifo3Pass transCounts = new IntegerFifo3Pass( 256 );
IntegerFifo3Pass restrictionBits = new IntegerFifo3Pass( 16 );
IntegerFifo3Pass linkCounts = new IntegerFifo3Pass(256);
IntegerFifo3Pass transCounts = new IntegerFifo3Pass(256);
IntegerFifo3Pass restrictionBits = new IntegerFifo3Pass(16);
TagValueCoder wayTagCoder = new TagValueCoder();
TagValueCoder nodeTagCoder = new TagValueCoder();
@ -340,91 +313,89 @@ public final class MicroCache2 extends MicroCache
int netdatasize = 0;
for(int pass=1;; pass++) // 3 passes: counters, stat-collection, encoding
for (int pass = 1; ; pass++) // 3 passes: counters, stat-collection, encoding
{
boolean dostats = pass == 3;
boolean dodebug = debug && pass == 3;
if ( pass < 3 ) netdatasize = fapos[size-1];
if (pass < 3) netdatasize = fapos[size - 1];
StatCoderContext bc = new StatCoderContext( buffer );
StatCoderContext bc = new StatCoderContext(buffer);
linkCounts.init();
transCounts.init();
restrictionBits.init();
wayTagCoder.encodeDictionary( bc );
if ( dostats ) bc.assignBits( "wayTagDictionary" );
nodeTagCoder.encodeDictionary( bc );
if ( dostats ) bc.assignBits( "nodeTagDictionary" );
nodeIdxDiff.encodeDictionary( bc );
nodeEleDiff.encodeDictionary( bc );
extLonDiff.encodeDictionary( bc );
extLatDiff.encodeDictionary( bc );
transEleDiff.encodeDictionary( bc );
if ( dostats ) bc.assignBits( "noisebits" );
bc.encodeNoisyNumber( size, 5 );
if ( dostats ) bc.assignBits( "nodecount" );
bc.encodeSortedArray( faid, 0, size, 0x20000000, 0 );
if ( dostats ) bc.assignBits( "node-positions" );
bc.encodeNoisyNumber( netdatasize, 10 ); // net-size
if ( dostats ) bc.assignBits( "netdatasize" );
if ( dodebug ) System.out.println( "*** encoding cache of size=" + size );
wayTagCoder.encodeDictionary(bc);
if (dostats) bc.assignBits("wayTagDictionary");
nodeTagCoder.encodeDictionary(bc);
if (dostats) bc.assignBits("nodeTagDictionary");
nodeIdxDiff.encodeDictionary(bc);
nodeEleDiff.encodeDictionary(bc);
extLonDiff.encodeDictionary(bc);
extLatDiff.encodeDictionary(bc);
transEleDiff.encodeDictionary(bc);
if (dostats) bc.assignBits("noisebits");
bc.encodeNoisyNumber(size, 5);
if (dostats) bc.assignBits("nodecount");
bc.encodeSortedArray(faid, 0, size, 0x20000000, 0);
if (dostats) bc.assignBits("node-positions");
bc.encodeNoisyNumber(netdatasize, 10); // net-size
if (dostats) bc.assignBits("netdatasize");
if (dodebug) System.out.println("*** encoding cache of size=" + size);
int lastSelev = 0;
for( int n=0; n<size; n++ ) // loop over nodes
for (int n = 0; n < size; n++) // loop over nodes
{
aboffset = startPos( n );
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);
long id64 = expandId(faid[n]);
int ilon = (int) (id64 >> 32);
int ilat = (int) (id64 & 0xffffffff);
if ( aboffset == aboffsetEnd )
{
bc.encodeVarBits( 13 ); // empty node escape (delta files only)
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 )
{
bc.encodeVarBits( 2 ); // 2 = tr exceptions
bc.encodeNoisyNumber( 10 , 5 ); // bit-count
bc.encodeBounded( 1023 , exceptions & 1023 );
if (exceptions != 0) {
bc.encodeVarBits(2); // 2 = tr exceptions
bc.encodeNoisyNumber(10, 5); // bit-count
bc.encodeBounded(1023, exceptions & 1023);
}
bc.encodeVarBits( 1 ); // 1 = turn restriction
bc.encodeNoisyNumber( restrictionBits.getNext(), 5 ); // bit-count using look-ahead fifo
bc.encodeVarBits(1); // 1 = turn restriction
bc.encodeNoisyNumber(restrictionBits.getNext(), 5); // bit-count using look-ahead fifo
long b0 = bc.getWritingBitPosition();
bc.encodeBit( readBoolean() ); // isPositive
bc.encodeNoisyDiff( readInt() - ilon, 10 ); // fromLon
bc.encodeNoisyDiff( readInt() - ilat, 10 ); // fromLat
bc.encodeNoisyDiff( readInt() - ilon, 10 ); // toLon
bc.encodeNoisyDiff( readInt() - ilat, 10 ); // toLat
restrictionBits.add( (int)( bc.getWritingBitPosition() - b0 ) );
bc.encodeBit(readBoolean()); // isPositive
bc.encodeNoisyDiff(readInt() - ilon, 10); // fromLon
bc.encodeNoisyDiff(readInt() - ilat, 10); // fromLat
bc.encodeNoisyDiff(readInt() - ilon, 10); // toLon
bc.encodeNoisyDiff(readInt() - ilat, 10); // toLat
restrictionBits.add((int) (bc.getWritingBitPosition() - b0));
}
bc.encodeVarBits( 0 ); // end of extra data
bc.encodeVarBits(0); // end of extra data
if ( dostats ) bc.assignBits( "extradata" );
if (dostats) bc.assignBits("extradata");
int selev = readShort();
nodeEleDiff.encodeSignedValue( selev - lastSelev );
if ( dostats ) bc.assignBits( "nodeele" );
nodeEleDiff.encodeSignedValue(selev - lastSelev);
if (dostats) bc.assignBits("nodeele");
lastSelev = selev;
nodeTagCoder.encodeTagValueSet( readVarBytes() );
if ( dostats ) bc.assignBits( "nodeTagIdx" );
nodeTagCoder.encodeTagValueSet(readVarBytes());
if (dostats) bc.assignBits("nodeTagIdx");
int nlinks = linkCounts.getNext();
if ( dodebug ) System.out.println( "*** nlinks=" + nlinks );
bc.encodeNoisyNumber( nlinks, 1 );
if ( dostats ) bc.assignBits( "link-counts" );
if (dodebug) System.out.println("*** nlinks=" + nlinks);
bc.encodeNoisyNumber(nlinks, 1);
if (dostats) bc.assignBits("link-counts");
nlinks = 0;
while( hasMoreData() ) // loop over links
while (hasMoreData()) // loop over links
{
// read link data
int startPointer = aboffset;
@ -434,85 +405,78 @@ public final class MicroCache2 extends MicroCache
int ilatlink = ilat + readVarLengthSigned();
int sizecode = readVarLengthUnsigned();
boolean isReverse = ( sizecode & 1 ) != 0;
boolean isReverse = (sizecode & 1) != 0;
int descSize = sizecode >> 1;
byte[] description = null;
if ( descSize > 0 )
{
if (descSize > 0) {
description = new byte[descSize];
readFully( description );
readFully(description);
}
long link64 = ((long)ilonlink)<<32 | ilatlink;
Integer idx = idMap.get( Long.valueOf( link64 ) );
long link64 = ((long) ilonlink) << 32 | ilatlink;
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 );
netdatasize -= aboffset-startPointer;
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" );
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 {
nodeIdxDiff.encodeSignedValue(0);
bc.encodeBit(isReverse);
extLonDiff.encodeSignedValue(ilonlink - ilon);
extLatDiff.encodeSignedValue(ilatlink - ilat);
if (dostats) bc.assignBits("externalNode");
}
else
{
nodeIdxDiff.encodeSignedValue( 0 );
bc.encodeBit( isReverse );
extLonDiff.encodeSignedValue( ilonlink - ilon );
extLatDiff.encodeSignedValue( ilatlink - ilat );
if ( dostats ) bc.assignBits( "externalNode" );
}
wayTagCoder.encodeTagValueSet( description );
if ( dostats ) bc.assignBits( "wayDescIdx" );
wayTagCoder.encodeTagValueSet(description);
if (dostats) bc.assignBits("wayDescIdx");
if ( !isReverse )
{
byte[] geometry = readDataUntil( endPointer );
if (!isReverse) {
byte[] geometry = readDataUntil(endPointer);
// write transition nodes
int count = transCounts.getNext();
if ( dodebug ) System.out.println( "*** encoding geometry with count=" + count );
bc.encodeVarBits( count++ );
if ( dostats ) bc.assignBits( "transcount" );
if (dodebug) System.out.println("*** encoding geometry with count=" + count);
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() )
{
ByteDataReader r = new ByteDataReader(geometry);
while (r.hasMoreData()) {
transcount++;
int dlon = r.readVarLengthSigned();
int dlat = r.readVarLengthSigned();
bc.encodePredictedValue( dlon, dlon_remaining/count );
bc.encodePredictedValue( dlat, dlat_remaining/count );
bc.encodePredictedValue(dlon, dlon_remaining / count);
bc.encodePredictedValue(dlat, dlat_remaining / count);
dlon_remaining -= dlon;
dlat_remaining -= dlat;
if ( count > 1 ) count--;
if ( dostats ) bc.assignBits( "transpos" );
transEleDiff.encodeSignedValue( r.readVarLengthSigned() );
if ( dostats ) bc.assignBits( "transele" );
if (count > 1) count--;
if (dostats) bc.assignBits("transpos");
transEleDiff.encodeSignedValue(r.readVarLengthSigned());
if (dostats) bc.assignBits("transele");
}
}
transCounts.add( transcount );
transCounts.add(transcount);
}
}
linkCounts.add( nlinks );
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,60 +26,49 @@ 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 )
{
bc.encodeNoisyDiff( value, noisybits );
}
else if ( pass == 2 )
{
count( value < 0 ? -value : value );
public void encodeSignedValue(int value) {
if (pass == 3) {
bc.encodeNoisyDiff(value, noisybits);
} else if (pass == 2) {
count(value < 0 ? -value : value);
}
}
/**
* decodes a signed int
*/
public int decodeSignedValue()
{
return bc.decodeNoisyDiff( noisybits );
public int decodeSignedValue() {
return bc.decodeNoisyDiff(noisybits);
}
/**
* 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++ )
{
if ( freqs[noisybits] < ( tot >> 1 ) )
for (noisybits = 0; noisybits < 14 && tot > 0; noisybits++) {
if (freqs[noisybits] < (tot >> 1))
break;
}
bc.encodeVarBits( noisybits );
bc.encodeVarBits(noisybits);
}
this.bc = bc;
}
private void count( int value )
{
if ( freqs == null )
private void count(int value) {
if (freqs == null)
freqs = new int[14];
int bm = 1;
for ( int i = 0; i < 14; i++ )
{
if ( value < bm )
for (int i = 0; i < 14; i++) {
if (value < bm)
break;
else
freqs[i]++;

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,9 +25,8 @@ public final class StatCoderContext extends BitCoderContext
}
public StatCoderContext( byte[] ab )
{
super( ab );
public StatCoderContext(byte[] ab) {
super(ab);
}
/**
@ -40,18 +35,15 @@ 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 )
{
long[] stats = statsPerName.get(name);
if (stats == null) {
stats = new long[2];
statsPerName.put( name, stats );
statsPerName.put(name, stats);
}
stats[0] += bitpos - lastbitpos;
stats[1] += 1;
@ -63,17 +55,14 @@ 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() )
{
long[] stats = statsPerName.get( name );
sb.append( name + " count=" + stats[1] + " bits=" + stats[0] + "\n" );
for (String name : statsPerName.keySet()) {
long[] stats = statsPerName.get(name);
sb.append(name + " count=" + stats[1] + " bits=" + stats[0] + "\n");
}
statsPerName = null;
return sb.toString();
@ -85,19 +74,16 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #decodeNoisyNumber
*/
public void encodeNoisyNumber( int value, int noisybits )
{
if ( value < 0 )
{
throw new IllegalArgumentException( "encodeVarBits expects positive value" );
public void encodeNoisyNumber(int value, int noisybits) {
if (value < 0) {
throw new IllegalArgumentException("encodeVarBits expects positive value");
}
if ( noisybits > 0 )
{
int mask = 0xffffffff >>> ( 32 - noisybits );
encodeBounded( mask, value & mask );
if (noisybits > 0) {
int mask = 0xffffffff >>> (32 - noisybits);
encodeBounded(mask, value & mask);
value >>= noisybits;
}
encodeVarBits( value );
encodeVarBits(value);
}
/**
@ -106,10 +92,9 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #encodeNoisyNumber
*/
public int decodeNoisyNumber( int noisybits )
{
int value = decodeBits( noisybits );
return value | ( decodeVarBits() << noisybits );
public int decodeNoisyNumber(int noisybits) {
int value = decodeBits(noisybits);
return value | (decodeVarBits() << noisybits);
}
/**
@ -118,19 +103,16 @@ public final class StatCoderContext extends BitCoderContext
*
* @see #decodeNoisyDiff
*/
public void encodeNoisyDiff( int value, int noisybits )
{
if ( noisybits > 0 )
{
value += 1 << ( noisybits - 1 );
int mask = 0xffffffff >>> ( 32 - noisybits );
encodeBounded( mask, value & mask );
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 )
{
encodeBit( value < 0 );
encodeVarBits(value < 0 ? -value : value);
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 )
{
value = decodeBits( noisybits ) - ( 1 << ( noisybits - 1 ) );
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,17 +142,15 @@ 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;
}
encodeNoisyDiff( value - predictor, noisybits );
encodeNoisyDiff(value - predictor, noisybits);
}
/**
@ -183,16 +159,14 @@ 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;
}
return predictor + decodeNoisyDiff( noisybits + noisy_bits[p] );
return predictor + decodeNoisyDiff(noisybits + noisy_bits[p]);
}
/**
@ -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
{
if ( subsize == 1 ) // last-choice shortcut
{
while (nextbit != 0)
{
encodeBit( ( values[offset] & nextbit ) != 0 );
while (nextbit != 0) {
encodeBit((values[offset] & nextbit) != 0);
nextbit >>= 1;
}
}
if ( nextbit == 0 )
{
if (nextbit == 0) {
return;
}
@ -234,71 +200,55 @@ 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;
}
}
int size1 = i - offset;
int size2 = subsize - size1;
encodeBounded( subsize, size1 );
if ( size1 > 0 )
{
encodeSortedArray( values, offset, size1, nextbit >> 1, mask );
encodeBounded(subsize, size1);
if (size1 > 0) {
encodeSortedArray(values, offset, size1, nextbit >> 1, mask);
}
if ( size2 > 0 )
{
encodeSortedArray( values, i, size2, nextbit >> 1, mask );
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 ( subsize == 1 ) // last-choice shortcut
{
if ( nextbitpos >= 0 )
{
value |= decodeBitsReverse( nextbitpos+1 );
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;
}
int size1 = decodeBounded( subsize );
int size1 = decodeBounded(subsize);
int size2 = subsize - size1;
if ( size1 > 0 )
{
decodeSortedArray( values, offset, size1, nextbitpos-1, value );
if (size1 > 0) {
decodeSortedArray(values, offset, size1, nextbitpos - 1, value);
}
if ( size2 > 0 )
{
decodeSortedArray( values, offset + size1, size2, nextbitpos-1, value | (1 << nextbitpos) );
if (size2 > 0) {
decodeSortedArray(values, offset + size1, size2, nextbitpos - 1, value | (1 << nextbitpos));
}
}

View File

@ -8,51 +8,42 @@ 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 )
{
bc.encodeBounded( tvs.range - 1, tvs.code );
}
else if ( pass == 2 )
{
if ( tvs == null )
{
TagValueSet tvs = identityMap.get(tvsProbe);
if (pass == 3) {
bc.encodeBounded(tvs.range - 1, tvs.code);
} else if (pass == 2) {
if (tvs == null) {
tvs = tvsProbe;
nextTagValueSetId++;
identityMap.put( tvs, tvs );
identityMap.put(tvs, tvs);
}
tvs.frequency++;
}
}
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,104 +51,87 @@ 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 );
identityMap.put(dummy, dummy);
}
PriorityQueue<TagValueSet> queue = new PriorityQueue<TagValueSet>(2*identityMap.size(), new TagValueSet.FrequencyComparator());
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();
node.frequency = node.child1.frequency + node.child2.frequency;
queue.add( node );
queue.add(node);
}
TagValueSet root = queue.poll();
root.encode( bc, 1, 0 );
root.encode(bc, 1, 0);
}
this.bc = bc;
}
public TagValueCoder( BitCoderContext bc, DataBuffers buffers, TagValueValidator validator )
{
tree = decodeTree( bc, buffers, 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 );
node.child1 = decodeTree(bc, buffers, validator);
node.child2 = decodeTree(bc, buffers, validator);
return node;
}
byte[] buffer = buffers.tagbuf1;
BitCoderContext ctx = buffers.bctx1;
ctx.reset( buffer );
ctx.reset(buffer);
int inum = 0;
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 )
{
ctx.encodeVarBits( 0 );
if (delta == 0) {
ctx.encodeVarBits(0);
break;
}
inum += delta;
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 );
ctx.encodeVarBits(inum - lastEncodedInum);
ctx.encodeVarBits(data);
lastEncodedInum = inum;
}
}
byte[] res;
int len = ctx.closeAndGetEncodedLength();
if ( validator == null )
{
if (validator == null) {
res = new byte[len];
System.arraycopy( buffer, 0, res, 0, len );
}
else
{
res = validator.unify( buffer, 0, len );
System.arraycopy(buffer, 0, res, 0, len);
} else {
res = validator.unify(buffer, 0, len);
}
int accessType = validator == null ? 2 : validator.accessType( res );
if ( accessType > 0 )
{
int accessType = validator == null ? 2 : validator.accessType(res);
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,66 +154,51 @@ 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 )
{
child1.encode( bc, range << 1, code );
child2.encode( bc, range << 1, code + range );
}
else
{
if ( data == null )
{
bc.encodeVarBits( 0 );
bc.encodeBit(isNode);
if (isNode) {
child1.encode(bc, range << 1, code);
child2.encode(bc, range << 1, code + range);
} else {
if (data == null) {
bc.encodeVarBits(0);
return;
}
BitCoderContext src = new BitCoderContext( data );
for ( ;; )
{
BitCoderContext src = new BitCoderContext(data);
for (; ; ) {
int delta = src.decodeVarBits();
bc.encodeVarBits( delta );
if ( delta == 0 )
{
bc.encodeVarBits(delta);
if (delta == 0) {
break;
}
int data = src.decodeVarBits();
bc.encodeVarBits( data );
bc.encodeVarBits(data);
}
}
}
@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,39 +208,34 @@ 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++ )
{
h = ( h << 8 ) + data[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) {
if ( tvs1.frequency < tvs2.frequency )
if (tvs1.frequency < tvs2.frequency)
return -1;
if ( tvs1.frequency > tvs2.frequency )
if (tvs1.frequency > tvs2.frequency)
return 1;
// to avoid ordering instability, decide on the id if frequency is equal
if ( tvs1.id < tvs2.id )
if (tvs1.id < tvs2.id)
return -1;
if ( tvs1.id > tvs2.id )
if (tvs1.id > tvs2.id)
return 1;
if ( tvs1 != tvs2 )
{
throw new RuntimeException( "identity corruption!" );
if (tvs1 != tvs2) {
throw new RuntimeException("identity corruption!");
}
return 0;
}

View File

@ -1,17 +1,16 @@
package btools.codec;
public interface TagValueValidator
{
public interface TagValueValidator {
/**
* @param tagValueSet the way description to check
* @return 0 = nothing, 1=no matching, 2=normal
*/
public int accessType( byte[] tagValueSet );
public int accessType(byte[] tagValueSet);
public byte[] unify( byte[] tagValueSet, int offset, int len );
public byte[] unify(byte[] tagValueSet, int offset, int len);
public boolean isLookupIdxUsed( int idx );
public boolean isLookupIdxUsed(int idx);
public void setDecodeForbidden( boolean decodeForbidden );
public void setDecodeForbidden(boolean decodeForbidden);
}

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
{
boolean start( int ilonStart, int ilatStart, int ilonTarget, int ilatTarget );
void transferNode( int ilon, int ilat );
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 );
LinkedListContainer llc = new LinkedListContainer(nlists, null);
for ( int ln = 0; ln < nlists; ln++ )
{
for ( int i = 0; i < 10; i++ )
{
llc.addDataElement( ln, ln * 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++ )
{
llc.addDataElement( ln, ln * i );
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++ )
{
int cnt = llc.initList( ln );
Assert.assertTrue( "list size test", cnt == 20 );
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 ) );
Assert.assertTrue("data value test", data == ln * (i % 10));
}
}
try
{
try {
llc.getDataElement();
Assert.fail( "no more elements expected" );
}
catch (IllegalArgumentException e)
{
Assert.fail("no more elements expected");
} catch (IllegalArgumentException e) {
}
}
}

View File

@ -6,100 +6,79 @@ 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++ )
{
ctx.encodeNoisyNumber( i, noisybits );
StatCoderContext ctx = new StatCoderContext(ab);
for (int noisybits = 1; noisybits < 12; noisybits++) {
for (int i = 0; i < 1000; i++) {
ctx.encodeNoisyNumber(i, noisybits);
}
}
ctx.closeAndGetEncodedLength();
ctx = new StatCoderContext( ab );
ctx = new StatCoderContext(ab);
for ( int noisybits = 1; noisybits < 12; noisybits++ )
{
for ( int i = 0; i < 1000; i++ )
{
int value = ctx.decodeNoisyNumber( noisybits );
if ( value != i )
{
Assert.fail( "value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value );
for (int noisybits = 1; noisybits < 12; noisybits++) {
for (int i = 0; i < 1000; i++) {
int value = ctx.decodeNoisyNumber(noisybits);
if (value != i) {
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
}
}
}
}
@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++ )
{
ctx.encodeNoisyDiff( i, noisybits );
StatCoderContext ctx = new StatCoderContext(ab);
for (int noisybits = 0; noisybits < 12; noisybits++) {
for (int i = -1000; i < 1000; i++) {
ctx.encodeNoisyDiff(i, noisybits);
}
}
ctx.closeAndGetEncodedLength();
ctx = new StatCoderContext( ab );
ctx = new StatCoderContext(ab);
for ( int noisybits = 0; noisybits < 12; noisybits++ )
{
for ( int i = -1000; i < 1000; i++ )
{
int value = ctx.decodeNoisyDiff( noisybits );
if ( value != i )
{
Assert.fail( "value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value );
for (int noisybits = 0; noisybits < 12; noisybits++) {
for (int i = -1000; i < 1000; i++) {
int value = ctx.decodeNoisyDiff(noisybits);
if (value != i) {
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
}
}
}
}
@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 )
{
ctx.encodePredictedValue( value, predictor );
StatCoderContext ctx = new StatCoderContext(ab);
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 );
ctx = new StatCoderContext(ab);
for ( int value = -100; value < 100; value += 5 )
{
for ( int predictor = -200; predictor < 200; predictor += 7 )
{
int decodedValue = ctx.decodePredictedValue( predictor );
if ( value != decodedValue )
{
Assert.fail( "value mismatch: value=" + value + " predictor=" + predictor + " decodedValue=" + decodedValue );
for (int value = -100; value < 100; value += 5) {
for (int predictor = -200; predictor < 200; predictor += 7) {
int decodedValue = ctx.decodePredictedValue(predictor);
if (value != decodedValue) {
Assert.fail("value mismatch: value=" + value + " predictor=" + predictor + " decodedValue=" + decodedValue);
}
}
}
}
@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
@ -108,23 +87,21 @@ public class StatCoderContextTest
values[15] = 275384; // force neighbours
values[18] = 275385;
Arrays.sort( values );
Arrays.sort(values);
byte[] ab = new byte[3000000];
StatCoderContext ctx = new StatCoderContext( ab );
ctx.encodeSortedArray( values, 0, size, 0x08000000, 0 );
StatCoderContext ctx = new StatCoderContext(ab);
ctx.encodeSortedArray(values, 0, size, 0x08000000, 0);
ctx.closeAndGetEncodedLength();
ctx = new StatCoderContext( ab );
ctx = new StatCoderContext(ab);
int[] decodedValues = new int[size];
ctx.decodeSortedArray( decodedValues, 0, size, 27, 0 );
ctx.decodeSortedArray(decodedValues, 0, size, 27, 0);
for ( int i = 0; i < size; i++ )
{
if ( values[i] != decodedValues[i] )
{
Assert.fail( "mismatch at i=" + i + " " + 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();
}
@ -47,7 +44,7 @@ final class KinematicModel extends OsmPathModel
protected BExpressionContextWay ctxWay;
protected BExpressionContextNode ctxNode;
protected Map<String,String> params;
protected Map<String, String> params;
private boolean initDone = false;
@ -55,77 +52,67 @@ 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 );
wayIdxMaxspeedExplicit = ctxWay.getOutputVariableIndex( "maxspeed_explicit", false );
wayIdxMinspeed = ctxWay.getOutputVariableIndex( "minspeed", false );
nodeIdxMaxspeed = ctxNode.getOutputVariableIndex( "maxspeed", false );
wayIdxMaxspeed = ctxWay.getOutputVariableIndex("maxspeed", false);
wayIdxMaxspeedExplicit = ctxWay.getOutputVariableIndex("maxspeed_explicit", false);
wayIdxMinspeed = ctxWay.getOutputVariableIndex("minspeed", false);
nodeIdxMaxspeed = ctxNode.getOutputVariableIndex("maxspeed", false);
initDone = true;
}
params = extraParams;
turnAngleDecayTime = getParam( "turnAngleDecayTime", 5.f );
f_roll = getParam( "f_roll", 232.f );
f_air = getParam( "f_air", 0.4f );
f_recup = getParam( "f_recup", 400.f );
p_standby = getParam( "p_standby", 250.f );
outside_temp = getParam( "outside_temp", 20.f );
recup_efficiency = getParam( "recup_efficiency", 0.7f );
totalweight = getParam( "totalweight", 1640.f );
vmax = getParam( "vmax", 80.f ) / 3.6;
leftWaySpeed = getParam( "leftWaySpeed", 12.f ) / 3.6;
rightWaySpeed = getParam( "rightWaySpeed", 12.f ) / 3.6;
turnAngleDecayTime = getParam("turnAngleDecayTime", 5.f);
f_roll = getParam("f_roll", 232.f);
f_air = getParam("f_air", 0.4f);
f_recup = getParam("f_recup", 400.f);
p_standby = getParam("p_standby", 250.f);
outside_temp = getParam("outside_temp", 20.f);
recup_efficiency = getParam("recup_efficiency", 0.7f);
totalweight = getParam("totalweight", 1640.f);
vmax = getParam("vmax", 80.f) / 3.6;
leftWaySpeed = getParam("leftWaySpeed", 12.f) / 3.6;
rightWaySpeed = getParam("rightWaySpeed", 12.f) / 3.6;
pw = 2. * f_air * vmax * vmax * vmax - p_standby;
cost0 = (pw+p_standby)/vmax + f_roll + f_air*vmax*vmax;
cost0 = (pw + p_standby) / vmax + f_roll + f_air * vmax * vmax;
}
protected float getParam( String name, float defaultValue )
{
String sval = params == null ? null : params.get( name );
if ( sval != null )
{
return Float.parseFloat( sval );
protected float getParam(String name, float defaultValue) {
String sval = params == null ? null : params.get(name);
if (sval != null) {
return Float.parseFloat(sval);
}
float v = ctxWay.getVariableValue( name, defaultValue );
if ( params != null )
{
params.put( name, "" + v );
float v = ctxWay.getVariableValue(name, defaultValue);
if (params != null) {
params.put(name, "" + v);
}
return v;
}
public float getWayMaxspeed()
{
return ctxWay.getBuildInVariable( wayIdxMaxspeed ) / 3.6f;
public float getWayMaxspeed() {
return ctxWay.getBuildInVariable(wayIdxMaxspeed) / 3.6f;
}
public float getWayMaxspeedExplicit()
{
return ctxWay.getBuildInVariable( wayIdxMaxspeedExplicit ) / 3.6f;
public float getWayMaxspeedExplicit() {
return ctxWay.getBuildInVariable(wayIdxMaxspeedExplicit) / 3.6f;
}
public float getWayMinspeed()
{
return ctxWay.getBuildInVariable( wayIdxMinspeed ) / 3.6f;
public float getWayMinspeed() {
return ctxWay.getBuildInVariable(wayIdxMinspeed) / 3.6f;
}
public float getNodeMaxspeed()
{
return ctxNode.getBuildInVariable( nodeIdxMaxspeed ) / 3.6f;
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,23 +123,20 @@ 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;
}
double v = vl*0.8;
double pw2 = pw+p_standby;
double v = vl * 0.8;
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++)
{
double v2 = v*v;
double x = pw2/v+f_air*e*v2 - x0;
double dx = 2.*e*f_air*v - pw2/v2;
v -= x/dx;
double x0 = pw2 / vl + f_air * e * vl * vl + (1. - e) * f_roll;
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;
v -= x / dx;
}
lastEffectiveLimit = vl;
lastBreakingSpeed = v;

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,9 +16,8 @@ final class KinematicPath extends OsmPath
private float floatingAngleRight; // sliding average right bend (degree)
@Override
protected void init( OsmPath orig )
{
KinematicPath origin = (KinematicPath)orig;
protected void init(OsmPath orig) {
KinematicPath origin = (KinematicPath) orig;
ekin = origin.ekin;
totalTime = origin.totalTime;
totalEnergy = origin.totalEnergy;
@ -29,8 +27,7 @@ final class KinematicPath extends OsmPath
}
@Override
protected void resetState()
{
protected void resetState() {
ekin = 0.;
totalTime = 0.;
totalEnergy = 0.;
@ -39,117 +36,105 @@ 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 )
{
KinematicModel km = (KinematicModel)rc.pm;
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 )
{
extraTime = 0.5 * (1. - cosangle ) * 40.; // 40 seconds turn penalty
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
if (km.turnAngleDecayTime != 0.) // process turn-angle slowdown
{
if ( angle < 0 ) floatingAngleLeft -= (float)angle;
else floatingAngleRight += (float)angle;
float aa = Math.max( floatingAngleLeft, floatingAngleRight );
if (angle < 0) floatingAngleLeft -= (float) angle;
else floatingAngleRight += (float) angle;
float aa = Math.max(floatingAngleLeft, floatingAngleRight);
double curveSpeed = aa > 10. ? 200. / aa : 20.;
double distanceTime = dist / curveSpeed;
double decayFactor = FastMath.exp( - distanceTime / km.turnAngleDecayTime );
floatingAngleLeft = (float)( floatingAngleLeft * decayFactor );
floatingAngleRight = (float)( floatingAngleRight * decayFactor );
double decayFactor = FastMath.exp(-distanceTime / km.turnAngleDecayTime);
floatingAngleLeft = (float) (floatingAngleLeft * decayFactor);
floatingAngleRight = (float) (floatingAngleRight * decayFactor);
if ( curveSpeed < 20. )
{
if (curveSpeed < 20.) {
turnspeed = curveSpeed;
}
}
if ( nsection == 0 ) // process slowdown by crossing geometry
if (nsection == 0) // process slowdown by crossing geometry
{
double junctionspeed = 999.; // just high
int classifiermask = (int)rc.expctxWay.getClassifierMask();
int classifiermask = (int) rc.expctxWay.getClassifierMask();
// penalty for equal priority crossing
boolean hasLeftWay = false;
boolean hasRightWay = false;
boolean hasResidential = false;
for( OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next )
{
KinematicPrePath pp = (KinematicPrePath)prePath;
for (OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next) {
KinematicPrePath pp = (KinematicPrePath) prePath;
if ( ( (pp.classifiermask ^ classifiermask) & 8 ) != 0 ) // exactly one is linktype
if (((pp.classifiermask ^ classifiermask) & 8) != 0) // exactly one is linktype
{
continue;
}
if ( ( pp.classifiermask & 32 ) != 0 ) // touching a residential?
if ((pp.classifiermask & 32) != 0) // touching a residential?
{
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;
if (diff < -40. && diff > -140.) hasLeftWay = true;
if (diff > 40. && diff < 140.) hasRightWay = true;
}
}
double residentialSpeed = 13.;
if ( hasLeftWay && junctionspeed > km.leftWaySpeed ) junctionspeed = km.leftWaySpeed;
if ( hasRightWay && junctionspeed > km.rightWaySpeed ) junctionspeed = km.rightWaySpeed;
if ( hasResidential && junctionspeed > residentialSpeed ) junctionspeed = residentialSpeed;
if (hasLeftWay && junctionspeed > km.leftWaySpeed) junctionspeed = km.leftWaySpeed;
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 )
{
message.vnode0 = (int) ( junctionspeed * 3.6 + 0.5 );
if (message != null) {
message.vnode0 = (int) (junctionspeed * 3.6 + 0.5);
}
}
cutEkin( km.totalweight, turnspeed ); // apply turnspeed
cutEkin(km.totalweight, turnspeed); // apply turnspeed
}
// linear temperature correction
double tcorr = (20.-km.outside_temp)*0.0035;
double tcorr = (20. - km.outside_temp) * 0.0035;
// air_pressure down 1mb/8m
double ecorr = 0.0001375 * (elevation - 100.);
double f_air = km.f_air * ( 1. + tcorr - ecorr );
double f_air = km.f_air * (1. + tcorr - ecorr);
double distanceCost = evolveDistance( km, dist, delta_h, f_air );
double distanceCost = evolveDistance(km, dist, delta_h, f_air);
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 );
message.vmin = (int) ( km.getWayMinspeed() * 3.6 + 0.5 );
message.extraTime = (int)(extraTime*1000);
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);
message.vmin = (int) (km.getWayMinspeed() * 3.6 + 0.5);
message.extraTime = (int) (extraTime * 1000);
}
cost += extraTime * km.pw / km.cost0;
@ -159,147 +144,129 @@ 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. )
{
double emax = 0.5 * km.totalweight * effectiveSpeedLimit * effectiveSpeedLimit;
if (emax <= 0.) {
return -1.;
}
double vb = km.getBreakingSpeed( effectiveSpeedLimit );
double elow = 0.5*km.totalweight*vb*vb;
double vb = km.getBreakingSpeed(effectiveSpeedLimit);
double elow = 0.5 * km.totalweight * vb * vb;
double elapsedTime = 0.;
double dissipatedEnergy = 0.;
double v = Math.sqrt( 2. * ekin / km.totalweight );
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;
double f = km.f_roll + f_air*v*v + fh;
double f_recup = Math.max( 0., fast ? -f : (slow ? km.f_recup :0 ) -fh ); // additional recup for slow part
double f = km.f_roll + f_air * v * v + fh;
double f_recup = Math.max(0., fast ? -f : (slow ? km.f_recup : 0) - fh); // additional recup for slow part
f += f_recup;
double delta_ekin;
double timeStep;
double x;
if ( fast )
{
if (fast) {
x = d;
delta_ekin = x*f;
timeStep = x/v;
delta_ekin = x * f;
timeStep = x / v;
ekin = etarget;
}
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 )
{
} 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) {
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)
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 );
double v2 = Math.sqrt(2. * ekin / km.totalweight);
double a = f / km.totalweight; // TODO: average force?
timeStep = (v2-v)/a;
timeStep = (v2 - v) / a;
v = v2;
}
d -= x;
elapsedTime += timeStep;
// dissipated energy does not contain elevation and efficient recup
dissipatedEnergy += delta_ekin - x*(fh + f_recup*km.recup_efficiency);
dissipatedEnergy += delta_ekin - x * (fh + f_recup * km.recup_efficiency);
// correction: inefficient recup going into heating is half efficient
double ieRecup = x*f_recup*(1.-km.recup_efficiency);
double eaux = timeStep*km.p_standby;
dissipatedEnergy -= Math.max( ieRecup, eaux ) * 0.5;
double ieRecup = x * f_recup * (1. - km.recup_efficiency);
double eaux = timeStep * km.p_standby;
dissipatedEnergy -= Math.max(ieRecup, eaux) * 0.5;
}
dissipatedEnergy += elapsedTime * km.p_standby;
totalTime += elapsedTime;
totalEnergy += dissipatedEnergy + dist*fh;
totalEnergy += dissipatedEnergy + dist * fh;
return (km.pw * elapsedTime + dissipatedEnergy)/km.cost0; // =cost
return (km.pw * elapsedTime + dissipatedEnergy) / km.cost0; // =cost
}
@Override
protected double processTargetNode( RoutingContext rc )
{
KinematicModel km = (KinematicModel)rc.pm;
protected double processTargetNode(RoutingContext rc) {
KinematicModel km = (KinematicModel) rc.pm;
// finally add node-costs for target node
if ( targetNode.nodeDescription != null )
{
rc.expctxNode.evaluate( false , targetNode.nodeDescription );
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
cutEkin(km.totalweight, km.getNodeMaxspeed()); // apply node maxspeed
if ( message != null )
{
message.linknodecost += (int)initialcost;
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription( false, targetNode.nodeDescription );
if (message != null) {
message.linknodecost += (int) initialcost;
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(false, targetNode.nodeDescription);
message.vnode1 = (int) ( km.getNodeMaxspeed() * 3.6 + 0.5 );
message.vnode1 = (int) (km.getNodeMaxspeed() * 3.6 + 0.5);
}
return initialcost;
}
return 0.;
}
private void cutEkin( double weight, double speed )
{
double e = 0.5*weight*speed*speed;
if ( ekin > e ) ekin = e;
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 )
{
KinematicPath p = (KinematicPath)path;
public boolean definitlyWorseThan(OsmPath path, RoutingContext rc) {
KinematicPath p = (KinematicPath) path;
int c = p.cost;
return cost > c + 100;
}
@Override
public double getTotalTime()
{
public double getTotalTime() {
return totalTime;
}
@Override
public double getTotalEnergy()
{
public double getTotalEnergy() {
return totalEnergy;
}
}

View File

@ -8,16 +8,14 @@ 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 );
if (description == null) throw new IllegalArgumentException("null description for: " + link);
// extract the 3 positions of the first section
int lon0 = origin.originLon;
@ -27,32 +25,29 @@ final class KinematicPrePath extends OsmPrePath
int lon1 = p1.getILon();
int lat1 = p1.getILat();
boolean isReverse = link.isReverse( sourceNode );
boolean isReverse = link.isReverse(sourceNode);
// evaluate the way tags
rc.expctxWay.evaluate( rc.inverseDirection ^ isReverse, description );
rc.expctxWay.evaluate(rc.inverseDirection ^ isReverse, description);
OsmTransferNode transferNode = link.geometry == null ? null
: rc.geometryDecoder.decodeGeometry( link.geometry, p1, targetNode, isReverse );
: rc.geometryDecoder.decodeGeometry(link.geometry, p1, targetNode, isReverse);
int lon2;
int lat2;
if ( transferNode == null )
{
if (transferNode == null) {
lon2 = targetNode.ilon;
lat2 = targetNode.ilat;
}
else
{
} else {
lon2 = transferNode.ilon;
lat2 = transferNode.ilat;
}
int dist = rc.calcDistance( lon1, lat1, lon2, lat2 );
int dist = rc.calcDistance(lon1, lat1, lon2, lat2);
angle = rc.anglemeter.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
priorityclassifier = (int)rc.expctxWay.getPriorityClassifier();
classifiermask = (int)rc.expctxWay.getClassifierMask();
angle = rc.anglemeter.calcAngle(lon0, lat0, lon1, lat1, lon2, lat2);
priorityclassifier = (int) rc.expctxWay.getPriorityClassifier();
classifiermask = (int) rc.expctxWay.getClassifierMask();
}
}

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,17 +35,15 @@ final class MessageData implements Cloneable
int vnode1 = 999;
int extraTime = 0;
String toMessage()
{
if ( wayKeyValues == null )
{
String toMessage() {
if (wayKeyValues == null) {
return null;
}
int iCost = (int)(costfactor*1000 + 0.5f);
return (lon-180000000) + "\t"
+ (lat-90000000) + "\t"
+ ele/4 + "\t"
int iCost = (int) (costfactor * 1000 + 0.5f);
return (lon - 180000000) + "\t"
+ (lat - 90000000) + "\t"
+ ele / 4 + "\t"
+ linkdist + "\t"
+ iCost + "\t"
+ linkelevationcost
@ -55,66 +51,54 @@ final class MessageData implements Cloneable
+ "\t" + linknodecost
+ "\t" + linkinitcost
+ "\t" + wayKeyValues
+ "\t" + ( nodeKeyValues == null ? "" : nodeKeyValues )
+ "\t" + ((int)time)
+ "\t" + ((int)energy);
+ "\t" + (nodeKeyValues == null ? "" : nodeKeyValues)
+ "\t" + ((int) time)
+ "\t" + ((int) energy);
}
void add( MessageData d )
{
void add(MessageData d) {
linkdist += d.linkdist;
linkelevationcost += d.linkelevationcost;
linkturncost += d.linkturncost;
linknodecost += d.linknodecost;
linkinitcost+= d.linkinitcost;
linkinitcost += d.linkinitcost;
}
MessageData copy()
{
try
{
return (MessageData)clone();
}
catch( CloneNotSupportedException e )
{
throw new RuntimeException( e );
MessageData copy() {
try {
return (MessageData) clone();
} 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()
{
return ( classifiermask & 1 ) != 0;
public boolean isBadOneway() {
return (classifiermask & 1) != 0;
}
public boolean isGoodOneway()
{
return ( classifiermask & 2 ) != 0;
public boolean isGoodOneway() {
return (classifiermask & 2) != 0;
}
public boolean isRoundabout()
{
return ( classifiermask & 4 ) != 0;
public boolean isRoundabout() {
return (classifiermask & 4) != 0;
}
public boolean isLinktType()
{
return ( classifiermask & 8 ) != 0;
public boolean isLinktType() {
return (classifiermask & 8) != 0;
}
public boolean isGoodForCars()
{
return ( classifiermask & 16 ) != 0;
public boolean isGoodForCars() {
return (classifiermask & 16) != 0;
}
}

View File

@ -8,26 +8,22 @@ 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)
{
super( n.ilon, n.ilat );
public OsmNodeNamed(OsmNode n) {
super(n.ilon, n.ilat);
}
@Override
public String toString()
{
if ( Double.isNaN(nogoWeight ) ) {
public String toString() {
if (Double.isNaN(nogoWeight)) {
return ilon + "," + ilat + "," + name;
} else {
return ilon + "," + ilat + "," + name + "," + nogoWeight;
@ -35,7 +31,7 @@ public class OsmNodeNamed extends OsmNode
}
public double distanceWithinRadius(int lon1, int lat1, int lon2, int lat2, double totalSegmentLength) {
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1 + lat2) >> 1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lat1 + lat2) >> 1);
boolean isFirstPointWithinCircle = CheapRuler.distance(lon1, lat1, ilon, ilat) < radius;
boolean isLastPointWithinCircle = CheapRuler.distance(lon2, lat2, ilon, ilat) < radius;
@ -70,9 +66,9 @@ public class OsmNodeNamed extends OsmNode
double initialToCenter = CheapRuler.distance(ilon, ilat, lon1, lat1);
// Half length of the segment within the circle
double halfDistanceWithin = Math.sqrt(
radius*radius - (
initialToCenter*initialToCenter -
initialToProject*initialToProject
radius * radius - (
initialToCenter * initialToCenter -
initialToProject * initialToProject
)
);
// Last point is within the circle
@ -82,20 +78,19 @@ 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 ) );
int idx2 = s.indexOf( ',', idx1+1 );
n.ilat = Integer.parseInt( s.substring( idx1+1, idx2 ) );
int idx3 = s.indexOf( ',', idx2+1 );
if ( idx3 == -1) {
n.name = s.substring( idx2 + 1 );
int idx1 = s.indexOf(',');
n.ilon = Integer.parseInt(s.substring(0, idx1));
int idx2 = s.indexOf(',', idx1 + 1);
n.ilat = Integer.parseInt(s.substring(idx1 + 1, idx2));
int idx3 = s.indexOf(',', idx2 + 1);
if (idx3 == -1) {
n.name = s.substring(idx2 + 1);
n.nogoWeight = Double.NaN;
} else {
n.name = s.substring( idx2+1, idx3 );
n.nogoWeight = Double.parseDouble( s.substring( idx3 + 1 ) );
n.name = s.substring(idx2 + 1, idx3);
n.nogoWeight = Double.parseDouble(s.substring(idx3 + 1));
}
n.isNogo = true;
return n;

View File

@ -5,8 +5,7 @@
http://geomalgorithms.com/a03-_inclusion.html
cn_PnPoly, wn_PnPoly, inSegment, intersect2D_2Segments
**********************************************************************************************/
**********************************************************************************************/
package btools.router;
import java.util.ArrayList;
@ -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,44 +48,38 @@ 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;
}
}
int cx = (cxmax+cxmin) / 2; // center of circle
int cy = (cymax+cymin) / 2;
int cx = (cxmax + cxmin) / 2; // center of circle
int cy = (cymax + cymin) / 2;
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( cy ); // conversion-factors at the center of circle
double[] lonlat2m = CheapRuler.getLonLatToMeterScales(cy); // conversion-factors at the center of circle
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
@ -100,48 +88,43 @@ 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()
// it's crucial to use the factors of the center!
final double x1 = (cx - p.x) * dlon2m;
final double y1 = (cy - p.y) * dlat2m;
final double dist = Math.sqrt( x1*x1 + y1*y1 );
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);
final Point p = points.get(i_max); // calculate new radius to just include this point
cx += (int)(dd * (p.x - cx) + 0.5); // shift center toward point
cy += (int)(dd * (p.y - cy) + 0.5);
cx += (int) (dd * (p.x - cx) + 0.5); // shift center toward point
cy += (int) (dd * (p.y - cy) + 0.5);
// get new factors at shifted centerpoint
lonlat2m = CheapRuler.getLonLatToMeterScales( cy );
lonlat2m = CheapRuler.getLonLatToMeterScales(cy);
dlon2m = lonlat2m[0];
dlat2m = lonlat2m[1];
final double x1 = (cx - p.x) * dlon2m;
final double y1 = (cy - p.y) * dlat2m;
dmax = rad = Math.sqrt( x1*x1 + y1*y1 );
dmax = rad = Math.sqrt(x1 * x1 + y1 * y1);
i_max = -1;
}
while (true);
@ -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)
{
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++)
{
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++) {
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 )
{
int i_last = points.size()-1;
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,37 +177,35 @@ public class OsmNogoPolygon extends OsmNodeNamed
return false;
}
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;
final double v12y = p1y-p0y;
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;
final double v12y = p1y - p0y;
if ( v10x == 0 ) // P0->P1 vertical?
if (v10x == 0) // P0->P1 vertical?
{
if ( v10y == 0 ) // P0 == P1?
if (v10y == 0) // P0 == P1?
{
return true;
}
if ( v12x != 0 ) // P1->P2 not vertical?
if (v12x != 0) // P1->P2 not vertical?
{
return false;
}
return ( v12y / v10y ) >= 1; // P1->P2 at least as long as P1->P0?
return (v12y / v10y) >= 1; // P1->P2 at least as long as P1->P0?
}
if ( v10y == 0 ) // P0->P1 horizontal?
if (v10y == 0) // P0->P1 horizontal?
{
if ( v12y != 0 ) // P1->P2 not horizontal?
if (v12y != 0) // P1->P2 not horizontal?
{
return false;
}
// if ( P10x == 0 ) // P0 == P1? already tested
return ( v12x / v10x ) >= 1; // P1->P2 at least as long as P1->P0?
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,12 +225,11 @@ 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
final int i_last = points.size()-1;
final int i_last = points.size() - 1;
final Point p0 = points.get(isClosed ? i_last : 0);
long p0x = p0.x; // need to use long to avoid overflow in products
long p0y = p0.y;
@ -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.
*/
@ -312,12 +282,11 @@ public class OsmNogoPolygon extends OsmNodeNamed
double distance = 0.;
// Extremities of the segments
final Point p1 = new Point (lon1, lat1);
final Point p2 = new Point (lon2, lat2);
final Point p1 = new Point(lon1, lat1);
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,28 +461,24 @@ 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;
}
if (t0 > t1) // must have t0 smaller than t1
{
final double t=t0; // swap if not
t0=t1;
t1=t;
final double t = t0; // swap if not
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
t1 = t1>1? 1 : t1; // clip to max 1
t0 = t0 < 0 ? 0 : t0; // clip to min 0
t1 = t1 > 1 ? 1 : t1; // clip to max 1
return (t0 == t1) ? 1 : 2; // return 1 if intersect is a point
}

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,90 +56,74 @@ 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 )
{
return (bitfield & mask ) != 0;
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()
{
return !getBit( HAD_DESTINATION_START_BIT ) && getBit( IS_ON_DESTINATION_BIT );
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 )
{
throw new RuntimeException( ioe );
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
public void registerUpTree()
{
if ( originElement instanceof OsmPathElementWithTraffic )
{
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)originElement;
public void registerUpTree() {
if (originElement instanceof OsmPathElementWithTraffic) {
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) originElement;
ot.register();
ot.addTraffic( traffic );
ot.addTraffic(traffic);
}
}
public void init( OsmLink link )
{
public void init(OsmLink link) {
this.link = link;
targetNode = link.getTarget( null );
targetNode = link.getTarget(null);
selev = targetNode.getSElev();
originLon = -1;
originLat = -1;
}
public void init( OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc )
{
if ( origin.myElement == null )
{
origin.myElement = OsmPathElement.create( origin, rc.countTraffic );
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;
this.link = link;
this.sourceNode = origin.targetNode;
this.targetNode = link.getTarget( sourceNode );
this.targetNode = link.getTarget(sourceNode);
this.cost = origin.cost;
this.lastClassifier = origin.lastClassifier;
this.lastInitialCost = origin.lastInitialCost;
this.bitfield = origin.bitfield;
init( origin );
addAddionalPenalty(refTrack, detailMode, origin, link, rc );
init(origin);
addAddionalPenalty(refTrack, detailMode, origin, link, rc);
}
protected abstract void init( OsmPath orig );
protected abstract void init(OsmPath orig);
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
}
@ -160,34 +143,31 @@ abstract class OsmPath implements OsmLinkHolder
message = detailMode ? new MessageData() : null;
boolean isReverse = link.isReverse( sourceNode );
boolean isReverse = link.isReverse(sourceNode);
// evaluate the way tags
rc.expctxWay.evaluate( rc.inverseDirection ^ isReverse, description );
rc.expctxWay.evaluate(rc.inverseDirection ^ isReverse, description);
// calculate the costfactor inputs
float costfactor = rc.expctxWay.getCostfactor();
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
int lastpriorityclassifier = priorityclassifier;
priorityclassifier = (int)rc.expctxWay.getPriorityClassifier();
priorityclassifier = (int) rc.expctxWay.getPriorityClassifier();
// *** add initial cost if the classifier changed
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 )
{
int iicost = (int) initialcost;
if (message != null) {
message.linkinitcost += iicost;
}
cost += iicost;
@ -196,38 +176,30 @@ abstract class OsmPath implements OsmLinkHolder
lastInitialCost = newInitialCost;
// *** destination logic: no destination access in between
int classifiermask = (int)rc.expctxWay.getClassifierMask();
int classifiermask = (int) rc.expctxWay.getClassifierMask();
boolean newDestination = (classifiermask & 64) != 0;
boolean oldDestination = getBit( IS_ON_DESTINATION_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 ) )
{
setBit( CAN_LEAVE_DESTINATION_BIT, false );
}
else
{
boolean oldDestination = getBit(IS_ON_DESTINATION_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)) {
setBit(CAN_LEAVE_DESTINATION_BIT, false);
} else {
cost = -1;
return;
}
}
}
setBit( IS_ON_DESTINATION_BIT, newDestination );
setBit(IS_ON_DESTINATION_BIT, newDestination);
OsmTransferNode transferNode = link.geometry == null ? null
: rc.geometryDecoder.decodeGeometry( link.geometry, sourceNode, targetNode, isReverse );
: 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,36 +221,29 @@ 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 ( 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 ) )
{
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)) {
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();
}
int dist = rc.calcDistance( lon1, lat1, lon2, lat2 );
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
{
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
} else {
// we just start here, reset everything
cost = 0;
resetState();
@ -289,138 +251,111 @@ abstract class OsmPath implements OsmLinkHolder
lat0 = -1;
isStartpoint = true;
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
{
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 {
originElement = null; // prevent duplicate point
}
}
if ( rc.checkPendingEndpoint() )
{
dist = rc.calcDistance( rc.ilonshortest, rc.ilatshortest, lon2, lat2 );
if ( rc.shortestmatch )
{
if (rc.checkPendingEndpoint()) {
dist = rc.calcDistance(rc.ilonshortest, rc.ilatshortest, lon2, lat2);
if (rc.shortestmatch) {
stopAtEndpoint = true;
ele2 = interpolateEle( ele1, ele2, rc.wayfraction );
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
}
}
}
}
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
{
lon0 = lon1 - (lon2-lon1);
lat0 = lat1 - (lat2-lat1);
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 {
lon0 = lon1 - (lon2 - lon1);
lat0 = lat1 - (lat2 - lat1);
}
}
double angle = rc.anglemeter.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
double angle = rc.anglemeter.calcAngle(lon0, lat0, lon1, lat1, lon2, lat2);
double cosangle = rc.anglemeter.getCosAngle();
// *** elevation stuff
double delta_h = 0.;
if ( ele2 == Short.MIN_VALUE ) ele2 = ele1;
if ( ele1 != Short.MIN_VALUE )
{
delta_h = (ele2 - ele1)/4.;
if ( rc.inverseDirection )
{
if (ele2 == Short.MIN_VALUE) ele2 = ele1;
if (ele1 != Short.MIN_VALUE) {
delta_h = (ele2 - ele1) / 4.;
if (rc.inverseDirection) {
delta_h = -delta_h;
}
}
double elevation = ele2 == Short.MIN_VALUE ? 100. : ele2 / 4.;
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. )
{
double sectionCost = processWaySection(rc, dist, delta_h, elevation, angle, cosangle, isStartpoint, nsection, lastpriorityclassifier);
if ((sectionCost < 0. || costfactor > 9998. && !detailMode) || sectionCost + cost >= 2000000000.) {
cost = -1;
return;
}
if ( isTrafficBackbone )
{
if (isTrafficBackbone) {
sectionCost = 0.;
}
cost += (int)sectionCost;
cost += (int) sectionCost;
// calculate traffic
if ( rc.countTraffic )
{
int minDist = (int)rc.trafficSourceMinDist;
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);
traffic += dist * rc.expctxWay.getTrafficSourceDensity() * Math.pow(cost2 / 10000.f, rc.trafficSourceExponent);
}
// compute kinematic
computeKinematic( rc, dist, delta_h, detailMode );
computeKinematic(rc, dist, delta_h, detailMode);
if ( message != null )
{
message.turnangle = (float)angle;
message.time = (float)getTotalTime();
message.energy = (float)getTotalEnergy();
if (message != null) {
message.turnangle = (float) angle;
message.time = (float) getTotalTime();
message.energy = (float) getTotalEnergy();
message.priorityclassifier = priorityclassifier;
message.classifiermask = classifiermask;
message.lon = lon2;
message.lat = lat2;
message.ele = ele2;
message.wayKeyValues = rc.expctxWay.getKeyValueDescription( isReverse, description );
message.wayKeyValues = rc.expctxWay.getKeyValueDescription(isReverse, description);
}
if ( stopAtEndpoint )
{
if ( recordTransferNodes )
{
originElement = OsmPathElement.create( rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic );
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,11 +364,10 @@ abstract class OsmPath implements OsmLinkHolder
}
transferNode = transferNode.next;
if ( recordTransferNodes )
{
originElement = OsmPathElement.create( lon2, lat2, ele2, originElement, rc.countTraffic );
if (recordTransferNodes) {
originElement = OsmPathElement.create(lon2, lat2, ele2, originElement, rc.countTraffic);
originElement.cost = cost;
originElement.addTraffic( traffic );
originElement.addTraffic(traffic);
traffic = 0;
}
lon0 = lon1;
@ -444,81 +378,67 @@ 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. )
{
double targetCost = processTargetNode(rc);
if (targetCost < 0. || targetCost + cost >= 2000000000.) {
cost = -1;
return;
}
cost += (int)targetCost;
cost += (int) targetCost;
}
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 );
return (short) (e1 * (1. - fraction) + e2 * fraction);
}
protected abstract double processWaySection( RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier );
protected abstract double processWaySection(RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier);
protected abstract double processTargetNode( RoutingContext rc );
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 int elevationCorrection(RoutingContext rc);
public abstract boolean definitlyWorseThan( OsmPath p, 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,76 +24,62 @@ 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()
{
return ((long)ilon)<<32 | ilat;
public final long getIdFromPos() {
return ((long) ilon) << 32 | ilat;
}
public final int calcDistance( OsmPos p )
{
return (int)(CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0 );
public final int calcDistance(OsmPos p) {
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
}
public 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 );
OsmPathElement pe = create(n.getILon(), n.getILat(), path.selev, path.originElement, countTraffic);
pe.cost = path.cost;
pe.message = path.message;
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
{
dos.writeInt( ilat );
dos.writeInt( ilon );
dos.writeShort( selev );
dos.writeInt( cost );
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,19 +9,15 @@ 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 )
{
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)origin;
public void register() {
if (registerCount++ == 0) {
if (origin instanceof OsmPathElementWithTraffic) {
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
ot.register();
ot.farTraffic += farTraffic;
ot.nearTraffic += nearTraffic;
@ -32,40 +28,34 @@ public final class OsmPathElementWithTraffic extends OsmPathElement
}
@Override
public void addTraffic( float traffic )
{
public void addTraffic(float traffic) {
this.farTraffic += traffic;
this.nearTraffic += traffic;
}
// unregister from origin if our registercount is 0, else do nothing
public static double maxtraffic = 0.;
public static double maxtraffic = 0.;
public boolean unregister( RoutingContext rc ) throws IOException
{
if ( --registerCount == 0 )
{
if ( origin instanceof OsmPathElementWithTraffic )
{
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)origin;
public boolean unregister(RoutingContext rc) throws IOException {
if (--registerCount == 0) {
if (origin instanceof OsmPathElementWithTraffic) {
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
int costdelta = cost-ot.cost;
ot.farTraffic += farTraffic*Math.exp(-costdelta/rc.farTrafficDecayLength);
ot.nearTraffic += nearTraffic*Math.exp(-costdelta/rc.nearTrafficDecayLength);
int costdelta = cost - ot.cost;
ot.farTraffic += farTraffic * Math.exp(-costdelta / rc.farTrafficDecayLength);
ot.nearTraffic += nearTraffic * Math.exp(-costdelta / rc.nearTrafficDecayLength);
if ( costdelta > 0 && farTraffic > maxtraffic ) maxtraffic = farTraffic;
if (costdelta > 0 && farTraffic > maxtraffic) maxtraffic = farTraffic;
int t2 = cost == ot.cost ? -1 : (int)(rc.farTrafficWeight*farTraffic + rc.nearTrafficWeight*nearTraffic);
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 )
{
rc.trafficOutputStream.writeLong( getIdFromPos());
rc.trafficOutputStream.writeLong( ot.getIdFromPos());
rc.trafficOutputStream.writeInt( t2 );
if (rc.trafficOutputStream != null) {
rc.trafficOutputStream.writeLong(getIdFromPos());
rc.trafficOutputStream.writeLong(ot.getIdFromPos());
rc.trafficOutputStream.writeInt(t2);
}
}
farTraffic = 0;

View File

@ -11,11 +11,10 @@ import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
abstract class OsmPathModel
{
abstract class OsmPathModel {
public abstract OsmPrePath createPrePath();
public abstract OsmPath createPath();
public abstract void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String,String> keyValues );
public abstract void init(BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String, String> keyValues);
}

View File

@ -9,21 +9,19 @@ 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 );
initPrePath(origin, rc );
this.targetNode = link.getTarget(sourceNode);
initPrePath(origin, rc);
}
protected abstract void initPrePath(OsmPath origin, RoutingContext rc );
protected abstract void initPrePath(OsmPath origin, RoutingContext rc);
}

File diff suppressed because it is too large Load Diff

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;
@ -25,38 +24,31 @@ public final class ProfileCache
private long lastUseTime;
private static ProfileCache[] apc = new ProfileCache[1];
private static boolean debug = Boolean.getBoolean( "debugProfileCache" );
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 )
{
String profileBaseDir = System.getProperty( "profileBaseDir" );
public static synchronized boolean parseProfile(RoutingContext rc) {
String profileBaseDir = System.getProperty("profileBaseDir");
File profileDir;
File profileFile;
if ( profileBaseDir == null )
{
profileDir = new File( rc.localFunction ).getParentFile();
profileFile = new File( rc.localFunction ) ;
}
else
{
profileDir = new File( profileBaseDir );
profileFile = new File( profileDir, rc.localFunction + ".brf" ) ;
if (profileBaseDir == null) {
profileDir = new File(rc.localFunction).getParentFile();
profileFile = new File(rc.localFunction);
} else {
profileDir = new File(profileBaseDir);
profileFile = new File(profileDir, rc.localFunction + ".brf");
}
rc.profileTimestamp = profileFile.lastModified() + rc.getKeyValueChecksum()<<24;
File lookupFile = new File( profileDir, "lookups.dat" );
rc.profileTimestamp = profileFile.lastModified() + rc.getKeyValueChecksum() << 24;
File lookupFile = new File(profileDir, "lookups.dat");
// invalidate cache at lookup-table update
if ( !(lookupFile.equals( lastLookupFile ) && lookupFile.lastModified() == lastLookupTimestamp ) )
{
if ( lastLookupFile != null )
{
System.out.println( "******** invalidating profile-cache after lookup-file update ******** " );
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];
lastLookupFile = lookupFile;
@ -64,19 +56,15 @@ public final class ProfileCache
}
ProfileCache lru = null;
int unusedSlot =-1;
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,48 +75,43 @@ 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;
}
}
BExpressionMetaData meta = new BExpressionMetaData();
rc.expctxWay = new BExpressionContextWay( rc.memoryclass * 512, meta );
rc.expctxNode = new BExpressionContextNode( 0, meta );
rc.expctxNode.setForeignContext( rc.expctxWay );
rc.expctxWay = new BExpressionContextWay(rc.memoryclass * 512, meta);
rc.expctxNode = new BExpressionContextNode(0, meta);
rc.expctxNode.setForeignContext(rc.expctxWay);
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
meta.readMetaData(new File(profileDir, "lookups.dat"));
rc.expctxWay.parseFile( profileFile, "global" );
rc.expctxNode.parseFile( profileFile, "global" );
rc.expctxWay.parseFile(profileFile, "global");
rc.expctxNode.parseFile(profileFile, "global");
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,30 +20,28 @@ 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;
public Map<String,String> keyValues;
public Map<String, String> keyValues;
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 );
if ( idx >= 0 ) name = name.substring( idx+1 );
if (name.endsWith(".brf")) name = name.substring(0, localFunction.length() - 4);
int idx = name.lastIndexOf(File.separatorChar);
if (idx >= 0) name = name.substring(idx + 1);
return name;
}
@ -81,129 +79,117 @@ 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
{
Class clazz = Class.forName( className );
} else {
try {
Class clazz = Class.forName(className);
pm = (OsmPathModel) clazz.newInstance();
}
catch( Exception e )
{
throw new RuntimeException( "Cannot create path-model: " + e );
} catch (Exception e) {
throw new RuntimeException("Cannot create path-model: " + e);
}
}
initModel();
}
public void initModel()
{
pm.init( expctxWay, expctxNode, keyValues );
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) {
// add parameter to context
for (Map.Entry<String, String> e : keyValues.entrySet()) {
float f = Float.parseFloat(e.getValue());
expctxWay.setVariableValue(e.getKey(), f, false );
expctxNode.setVariableValue(e.getKey(), f, false );
expctxWay.setVariableValue(e.getKey(), f, false);
expctxNode.setVariableValue(e.getKey(), f, false);
}
}
setModel( expctxGlobal._modelClass );
setModel(expctxGlobal._modelClass);
downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost", 0.f );
downhillcutoff = (int)(expctxGlobal.getVariableValue( "downhillcutoff", 0.f )*10000);
uphillcostdiv = (int)expctxGlobal.getVariableValue( "uphillcost", 0.f );
uphillcutoff = (int)(expctxGlobal.getVariableValue( "uphillcutoff", 0.f )*10000);
if ( downhillcostdiv != 0 ) downhillcostdiv = 1000000/downhillcostdiv;
if ( uphillcostdiv != 0 ) uphillcostdiv = 1000000/uphillcostdiv;
carMode = 0.f != expctxGlobal.getVariableValue( "validForCars", 0.f );
bikeMode = 0.f != expctxGlobal.getVariableValue( "validForBikes", 0.f );
footMode = 0.f != expctxGlobal.getVariableValue( "validForFoot", 0.f );
downhillcostdiv = (int) expctxGlobal.getVariableValue("downhillcost", 0.f);
downhillcutoff = (int) (expctxGlobal.getVariableValue("downhillcutoff", 0.f) * 10000);
uphillcostdiv = (int) expctxGlobal.getVariableValue("uphillcost", 0.f);
uphillcutoff = (int) (expctxGlobal.getVariableValue("uphillcutoff", 0.f) * 10000);
if (downhillcostdiv != 0) downhillcostdiv = 1000000 / downhillcostdiv;
if (uphillcostdiv != 0) uphillcostdiv = 1000000 / uphillcostdiv;
carMode = 0.f != expctxGlobal.getVariableValue("validForCars", 0.f);
bikeMode = 0.f != expctxGlobal.getVariableValue("validForBikes", 0.f);
footMode = 0.f != expctxGlobal.getVariableValue("validForFoot", 0.f);
waypointCatchingRange = expctxGlobal.getVariableValue( "waypointCatchingRange", 250.f );
waypointCatchingRange = expctxGlobal.getVariableValue("waypointCatchingRange", 250.f);
// turn-restrictions not used per default for foot profiles
considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue( "considerTurnRestrictions", footMode ? 0.f : 1.f );
considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue("considerTurnRestrictions", footMode ? 0.f : 1.f);
// process tags not used in the profile (to have them in the data-tab)
processUnusedTags = 0.f != expctxGlobal.getVariableValue( "processUnusedTags", 0.f );
processUnusedTags = 0.f != expctxGlobal.getVariableValue("processUnusedTags", 0.f);
forceSecondaryData = 0.f != expctxGlobal.getVariableValue( "forceSecondaryData", 0.f );
pass1coefficient = expctxGlobal.getVariableValue( "pass1coefficient", 1.5f );
pass2coefficient = expctxGlobal.getVariableValue( "pass2coefficient", 0.f );
elevationpenaltybuffer = (int)(expctxGlobal.getVariableValue( "elevationpenaltybuffer", 5.f )*1000000);
elevationmaxbuffer = (int)(expctxGlobal.getVariableValue( "elevationmaxbuffer", 10.f )*1000000);
elevationbufferreduce = (int)(expctxGlobal.getVariableValue( "elevationbufferreduce", 0.f )*10000);
forceSecondaryData = 0.f != expctxGlobal.getVariableValue("forceSecondaryData", 0.f);
pass1coefficient = expctxGlobal.getVariableValue("pass1coefficient", 1.5f);
pass2coefficient = expctxGlobal.getVariableValue("pass2coefficient", 0.f);
elevationpenaltybuffer = (int) (expctxGlobal.getVariableValue("elevationpenaltybuffer", 5.f) * 1000000);
elevationmaxbuffer = (int) (expctxGlobal.getVariableValue("elevationmaxbuffer", 10.f) * 1000000);
elevationbufferreduce = (int) (expctxGlobal.getVariableValue("elevationbufferreduce", 0.f) * 10000);
cost1speed = expctxGlobal.getVariableValue( "cost1speed", 22.f );
additionalcostfactor = expctxGlobal.getVariableValue( "additionalcostfactor", 1.5f );
changetime = expctxGlobal.getVariableValue( "changetime", 180.f );
buffertime = expctxGlobal.getVariableValue( "buffertime", 120.f );
waittimeadjustment = expctxGlobal.getVariableValue( "waittimeadjustment", 0.9f );
inittimeadjustment = expctxGlobal.getVariableValue( "inittimeadjustment", 0.2f );
starttimeoffset = expctxGlobal.getVariableValue( "starttimeoffset", 0.f );
transitonly = expctxGlobal.getVariableValue( "transitonly", 0.f ) != 0.f;
cost1speed = expctxGlobal.getVariableValue("cost1speed", 22.f);
additionalcostfactor = expctxGlobal.getVariableValue("additionalcostfactor", 1.5f);
changetime = expctxGlobal.getVariableValue("changetime", 180.f);
buffertime = expctxGlobal.getVariableValue("buffertime", 120.f);
waittimeadjustment = expctxGlobal.getVariableValue("waittimeadjustment", 0.9f);
inittimeadjustment = expctxGlobal.getVariableValue("inittimeadjustment", 0.2f);
starttimeoffset = expctxGlobal.getVariableValue("starttimeoffset", 0.f);
transitonly = expctxGlobal.getVariableValue("transitonly", 0.f) != 0.f;
farTrafficWeight = expctxGlobal.getVariableValue( "farTrafficWeight", 2.f );
nearTrafficWeight = expctxGlobal.getVariableValue( "nearTrafficWeight", 2.f );
farTrafficDecayLength = expctxGlobal.getVariableValue( "farTrafficDecayLength", 30000.f );
nearTrafficDecayLength = expctxGlobal.getVariableValue( "nearTrafficDecayLength", 3000.f );
trafficDirectionFactor = expctxGlobal.getVariableValue( "trafficDirectionFactor", 0.9f );
trafficSourceExponent = expctxGlobal.getVariableValue( "trafficSourceExponent", -0.7f );
trafficSourceMinDist = expctxGlobal.getVariableValue( "trafficSourceMinDist", 3000.f );
farTrafficWeight = expctxGlobal.getVariableValue("farTrafficWeight", 2.f);
nearTrafficWeight = expctxGlobal.getVariableValue("nearTrafficWeight", 2.f);
farTrafficDecayLength = expctxGlobal.getVariableValue("farTrafficDecayLength", 30000.f);
nearTrafficDecayLength = expctxGlobal.getVariableValue("nearTrafficDecayLength", 3000.f);
trafficDirectionFactor = expctxGlobal.getVariableValue("trafficDirectionFactor", 0.9f);
trafficSourceExponent = expctxGlobal.getVariableValue("trafficSourceExponent", -0.7f);
trafficSourceMinDist = expctxGlobal.getVariableValue("trafficSourceMinDist", 3000.f);
showspeed = 0.f != expctxGlobal.getVariableValue( "showspeed", 0.f );
showSpeedProfile = 0.f != expctxGlobal.getVariableValue( "showSpeedProfile", 0.f );
inverseRouting = 0.f != expctxGlobal.getVariableValue( "inverseRouting", 0.f );
showspeed = 0.f != expctxGlobal.getVariableValue("showspeed", 0.f);
showSpeedProfile = 0.f != expctxGlobal.getVariableValue("showSpeedProfile", 0.f);
inverseRouting = 0.f != expctxGlobal.getVariableValue("inverseRouting", 0.f);
int tiMode = (int)expctxGlobal.getVariableValue( "turnInstructionMode", 0.f );
if ( tiMode != 1 ) // automatic selection from coordinate source
int tiMode = (int) expctxGlobal.getVariableValue("turnInstructionMode", 0.f);
if (tiMode != 1) // automatic selection from coordinate source
{
turnInstructionMode = tiMode;
}
turnInstructionCatchingRange = expctxGlobal.getVariableValue( "turnInstructionCatchingRange", 40.f );
turnInstructionRoundabouts = expctxGlobal.getVariableValue( "turnInstructionRoundabouts", 1.f ) != 0.f;
turnInstructionCatchingRange = expctxGlobal.getVariableValue("turnInstructionCatchingRange", 40.f);
turnInstructionRoundabouts = expctxGlobal.getVariableValue("turnInstructionRoundabouts", 1.f) != 0.f;
// Speed computation model (for bikes)
// Total mass (biker + bike + luggages or hiker), in kg
totalMass = expctxGlobal.getVariableValue( "totalMass", 90.f );
totalMass = expctxGlobal.getVariableValue("totalMass", 90.f);
// Max speed (before braking), in km/h in profile and m/s in code
if (footMode) {
maxSpeed = expctxGlobal.getVariableValue( "maxSpeed", 6.f ) / 3.6;
maxSpeed = expctxGlobal.getVariableValue("maxSpeed", 6.f) / 3.6;
} else {
maxSpeed = expctxGlobal.getVariableValue( "maxSpeed", 45.f ) / 3.6;
maxSpeed = expctxGlobal.getVariableValue("maxSpeed", 45.f) / 3.6;
}
// Equivalent surface for wind, S * C_x, F = -1/2 * S * C_x * v^2 = - S_C_x * v^2
S_C_x = expctxGlobal.getVariableValue( "S_C_x", 0.5f * 0.45f );
S_C_x = expctxGlobal.getVariableValue("S_C_x", 0.5f * 0.45f);
// Default resistance of the road, F = - m * g * C_r (for good quality road)
defaultC_r = expctxGlobal.getVariableValue( "C_r", 0.01f );
defaultC_r = expctxGlobal.getVariableValue("C_r", 0.01f);
// Constant power of the biker (in W)
bikerPower = expctxGlobal.getVariableValue( "bikerPower", 100.f );
bikerPower = expctxGlobal.getVariableValue("bikerPower", 100.f);
}
public List<OsmNodeNamed> poipoints;
@ -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 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,46 +274,38 @@ 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;
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 )
{
if ( wp.calcDistance( nogo ) < nogo.radius
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).isClosed
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
: ((OsmNogoPolygon) nogo).isOnPolyline(wp.ilon, wp.ilat)))) {
goodGuy = false;
}
}
if ( goodGuy ) nogos.add( nogo );
if (goodGuy) nogos.add(nogo);
}
nogopoints = nogos.isEmpty() ? null : nogos;
}
public boolean allInOneNogo( List<OsmNode> waypoints )
{
if ( nogopoints == null ) return false;
public boolean allInOneNogo(List<OsmNode> waypoints) {
if (nogopoints == null) return false;
boolean allInTotal = false;
for( OsmNodeNamed nogo : nogopoints )
{
boolean allIn = Double.isNaN( nogo.nogoWeight );
for( OsmNode wp : waypoints )
{
int dist = wp.calcDistance( nogo );
if ( dist < nogo.radius
for (OsmNodeNamed nogo : nogopoints) {
boolean allIn = Double.isNaN(nogo.nogoWeight);
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).isClosed
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
: ((OsmNogoPolygon) nogo).isOnPolyline(wp.ilon, wp.ilat)))) {
continue;
}
allIn = false;
@ -341,93 +315,84 @@ 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;
// 10 is an arbitrary constant to get sub-integer precision in the checksum
cs[2] += (long) ( nogo.radius*10.);
cs[2] += (long) (nogo.radius * 10.);
}
return cs;
}
public void setWaypoint( OsmNodeNamed wp, boolean endpoint )
{
setWaypoint( wp, null, 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 );
if ( keepnogopoints != null ) nogopoints.addAll( keepnogopoints );
nogopoints.add(wp);
if (keepnogopoints != null) nogopoints.addAll(keepnogopoints);
isEndpoint = endpoint;
this.pendingEndpoint = pendingEndpoint;
}
public boolean checkPendingEndpoint()
{
if ( pendingEndpoint != null )
{
public boolean checkPendingEndpoint() {
if (pendingEndpoint != null) {
isEndpoint = true;
nogopoints.set( 0, pendingEndpoint );
nogopoints.set(0, pendingEndpoint);
pendingEndpoint = null;
return true;
}
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 )
{
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1+lat2) >> 1 );
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];
double dx = (lon2 - lon1 ) * dlon2m;
double dy = (lat2 - lat1 ) * dlat2m;
double d = Math.sqrt( dy*dy + dx*dx );
double dx = (lon2 - lon1) * dlon2m;
double dy = (lat2 - lat1) * dlat2m;
double d = Math.sqrt(dy * dy + dx * dx);
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;
double x2 = (lon2 - nogo.ilon) * dlon2m;
double y2 = (lat2 - nogo.ilat) * dlat2m;
double r12 = x1*x1 + y1*y1;
double r22 = x2*x2 + y2*y2;
double radius = Math.abs( r12 < r22 ? y1*dx - x1*dy : y2*dx - x2*dy ) / d;
double r12 = x1 * x1 + y1 * y1;
double r22 = x2 * x2 + y2 * y2;
double radius = Math.abs(r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy) / d;
if ( radius < nogo.radius ) // 20m
if (radius < nogo.radius) // 20m
{
double s1 = x1*dx + y1*dy;
double s2 = x2*dx + y2*dy;
double s1 = x1 * dx + y1 * dy;
double s2 = x2 * dx + y2 * dy;
if ( s1 < 0. ) { s1 = -s1; s2 = -s2; }
if ( s2 > 0. )
{
radius = Math.sqrt( s1 < s2 ? r12 : r22 );
if ( radius > nogo.radius ) continue;
if (s1 < 0.) {
s1 = -s1;
s2 = -s2;
}
if ( nogo.isNogo )
{
if (s2 > 0.) {
radius = Math.sqrt(s1 < s2 ? r12 : r22);
if (radius > nogo.radius) continue;
}
if (nogo.isNogo) {
if (!(nogo instanceof OsmNogoPolygon)) { // nogo is a circle
if (Double.isNaN(nogo.nogoWeight)) {
// default nogo behaviour (ignore completely)
@ -436,46 +401,37 @@ 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)) {
// default nogo behaviour (ignore completely)
nogoCost = -1;
} else {
if (((OsmNogoPolygon)nogo).isClosed) {
if (((OsmNogoPolygon) nogo).isClosed) {
// compute distance within the polygon
nogoCost = ((OsmNogoPolygon)nogo).distanceWithinPolygon(lon1, lat1, lon2, lat2) * nogo.nogoWeight;
nogoCost = ((OsmNogoPolygon) nogo).distanceWithinPolygon(lon1, lat1, lon2, lat2) * nogo.nogoWeight;
} else {
// for a polyline, just add a constant penalty
nogoCost = nogo.nogoWeight;
}
}
}
}
else
{
} else {
shortestmatch = true;
nogo.radius = radius; // shortest distance to way
// calculate remaining distance
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 )
{
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) {
wayfraction = 0.;
ilonshortest = lon2;
ilatshortest = lat2;
}
else
{
} else {
wayfraction = 1.;
ilonshortest = lon1;
ilatshortest = lat1;
@ -485,51 +441,44 @@ 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;
}
dx = (lon2 - lon1 ) * dlon2m;
dy = (lat2 - lat1 ) * dlat2m;
d = Math.sqrt( dy*dy + dx*dx );
dx = (lon2 - lon1) * dlon2m;
dy = (lat2 - lat1) * dlat2m;
d = Math.sqrt(dy * dy + dx * dx);
}
}
}
}
return (int)(d + 1.0 );
return (int) (d + 1.0);
}
public OsmPathModel pm;
public OsmPrePath createPrePath( OsmPath origin, OsmLink link )
{
public OsmPrePath createPrePath(OsmPath origin, OsmLink link) {
OsmPrePath p = pm.createPrePath();
if ( p != null )
{
p.init( origin, link, this );
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 );
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 );
p.init(origin, link, refTrack, detailMode, this);
return p;
}

File diff suppressed because it is too large Load Diff

View File

@ -9,40 +9,32 @@ 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 )
{
return hasAnyDatafiles( secondary );
File secondary = StorageConfigHelper.getSecondarySegmentDir(segmentDir);
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 )
{
if ( fileName.endsWith( ".rd5" ) ) return true;
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,15 +27,14 @@ 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;
p = new OsmNode( n.ilon, n.ilat );
p = new OsmNode(n.ilon, n.ilat);
int lon = (n.ilon / 5000000 ) * 5000000;
int lat = (n.ilat / 5000000 ) * 5000000;
int lon = (n.ilon / 5000000) * 5000000;
int lat = (n.ilat / 5000000) * 5000000;
minlon0 = lon - 5000000;
minlat0 = lat - 5000000;
@ -49,12 +47,11 @@ public final class SearchBoundary
maxlat = lat + 6000000;
}
public static String getFileName( OsmNode n )
{
int lon = (n.ilon / 5000000 ) * 5000000;
int lat = (n.ilat / 5000000 ) * 5000000;
public static String getFileName(OsmNode n) {
int lon = (n.ilon / 5000000) * 5000000;
int lat = (n.ilat / 5000000) * 5000000;
int dlon = lon / 1000000 -180;
int dlon = lon / 1000000 - 180;
int dlat = lat / 1000000 - 90;
String slon = dlon < 0 ? "W" + (-dlon) : "E" + dlon;
@ -62,28 +59,28 @@ public final class SearchBoundary
return slon + "_" + slat + ".trf";
}
public boolean isInBoundary( OsmNode n, int cost )
{
if ( radius > 0 )
{
return n.calcDistance( p ) < radius;
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,9 +22,8 @@ final class StdPath extends OsmPath
private static final double GRAVITY = 9.81; // in meters per second^(-2)
@Override
public void init( OsmPath orig )
{
StdPath origin = (StdPath)orig;
public void init(OsmPath orig) {
StdPath origin = (StdPath) orig;
this.ehbd = origin.ehbd;
this.ehbu = origin.ehbu;
this.totalTime = origin.totalTime;
@ -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();
@ -54,14 +50,13 @@ final class StdPath extends OsmPath
cfup = cfup == 0.f ? cf : cfup;
cfdown = cfdown == 0.f ? cf : cfdown;
int dist = (int)distance; // legacy arithmetics needs int
int dist = (int) distance; // legacy arithmetics needs int
// penalty for turning angle
int turncost = (int)((1.-cosangle) * turncostbase + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty
if ( message != null )
{
int turncost = (int) ((1. - cosangle) * turncostbase + 0.2); // e.g. turncost=90 -> 90 degree = 90m penalty
if (message != null) {
message.linkturncost += turncost;
message.turnangle = (float)angle;
message.turnangle = (float) angle;
}
double sectionCost = turncost;
@ -70,81 +65,66 @@ final class StdPath extends OsmPath
// only the part of the descend that does not fit into the elevation-hysteresis-buffers
// leads to an immediate penalty
int delta_h_micros = (int)(1000000. * delta_h);
int delta_h_micros = (int) (1000000. * delta_h);
ehbd += -delta_h_micros - dist * rc.downhillcutoff;
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 )
{
downweight = ((float)excess)/reduce;
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 )
{
int elevationCost = reduce/rc.downhillcostdiv;
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 )
{
upweight = ((float)excess)/reduce;
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 )
{
int elevationCost = reduce/rc.uphillcostdiv;
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;
float costfactor = cfup * upweight + cf * (1.f - upweight - downweight) + cfdown * downweight;
if ( message != null )
{
if (message != null) {
message.costfactor = costfactor;
}
@ -154,22 +134,18 @@ 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 );
rc.expctxNode.evaluate(nodeAccessGranted, targetNode.nodeDescription);
float initialcost = rc.expctxNode.getInitialcost();
if ( initialcost >= 1000000. )
{
if (initialcost >= 1000000.) {
return -1.;
}
if ( message != null )
{
message.linknodecost += (int)initialcost;
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription );
if (message != null) {
message.linknodecost += (int) initialcost;
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(nodeAccessGranted, targetNode.nodeDescription);
}
return initialcost;
}
@ -177,118 +153,96 @@ final class StdPath extends OsmPath
}
@Override
public int elevationCorrection( RoutingContext rc )
{
return ( rc.downhillcostdiv > 0 ? ehbd/rc.downhillcostdiv : 0 )
+ ( rc.uphillcostdiv > 0 ? ehbu/rc.uphillcostdiv : 0 );
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 )
{
StdPath p = (StdPath)path;
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 (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;
if (delta > 0) c += delta / rc.uphillcostdiv;
}
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. );
float new_elevation_buffer = (float)( (elevation_buffer+shift) * decayFactor - shift);
double incline = ( elevation_buffer - new_elevation_buffer ) / dist;
double decayFactor = FastMath.exp(-dist / 100.);
float new_elevation_buffer = (float) ((elevation_buffer + shift) * decayFactor - shift);
double incline = (elevation_buffer - new_elevation_buffer) / dist;
elevation_buffer = new_elevation_buffer;
return incline;
}
@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;
}
// compute incline
elevation_buffer += delta_h;
double incline = calcIncline( dist );
double incline = calcIncline(dist);
double wayMaxspeed;
wayMaxspeed = rc.expctxWay.getMaxspeed() / 3.6f;
if (wayMaxspeed == 0)
{
if (wayMaxspeed == 0) {
wayMaxspeed = rc.maxSpeed;
}
wayMaxspeed = Math.min(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 )
{
double f_roll = rc.totalMass * GRAVITY * (rc.defaultC_r + incline);
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)
{
speed = solveCubic( rc.S_C_x, f_roll, rc.bikerPower );
speed = (speed * FastMath.exp(-3.5 * Math.abs(incline + 0.05))) / 3.6;
} 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;
}
float dt = (float) ( dist / speed );
float dt = (float) (dist / speed);
totalTime += dt;
// 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. )
{
double energy = dist * (rc.S_C_x * speed * speed + f_roll);
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++ )
{
double y = ( a * v * v + c ) * v - d;
if ( y < .1 )
{
if ( findingStartvalue )
{
for (int i = 0; i < 10; i++) {
double y = (a * v * v + c) * v - d;
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,50 +16,44 @@ public class SuspectInfo
public int prio;
public int triggers;
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 )
{
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) {
info = new SuspectInfo();
map.put( iD, info );
map.put(iD, info);
}
info.prio = Math.max( info.prio, prio );
info.prio = Math.max(info.prio, prio);
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 );
old.prio = Math.max(old.prio, prio);
old.triggers |= trigger;
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 );
addText( sb, "node-block" , triggers, TRIGGER_NODE_BLOCK );
addText( sb, "bad-access" , triggers, TRIGGER_BAD_ACCESS );
addText( sb, "unkown-access", triggers, TRIGGER_UNK_ACCESS );
addText( sb, "sharp-exit" , triggers, TRIGGER_SHARP_EXIT );
addText( sb, "sharp-entry" , triggers, TRIGGER_SHARP_ENTRY );
addText( sb, "sharp-link" , triggers, TRIGGER_SHARP_LINK );
addText( sb, "bad-tr" , triggers, TRIGGER_BAD_TR );
addText(sb, "dead-end", triggers, TRIGGER_DEAD_END);
addText(sb, "dead-start", triggers, TRIGGER_DEAD_START);
addText(sb, "node-block", triggers, TRIGGER_NODE_BLOCK);
addText(sb, "bad-access", triggers, TRIGGER_BAD_ACCESS);
addText(sb, "unkown-access", triggers, TRIGGER_UNK_ACCESS);
addText(sb, "sharp-exit", triggers, TRIGGER_SHARP_EXIT);
addText(sb, "sharp-entry", triggers, TRIGGER_SHARP_ENTRY);
addText(sb, "sharp-link", triggers, TRIGGER_SHARP_LINK);
addText(sb, "bad-tr", triggers, TRIGGER_BAD_TR);
return sb.toString();
}
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 );
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,269 +45,281 @@ 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 );
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;
}
}
}
float cmdAngle= angle;
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. )
{
if ( cmd != KR ) // don't overwrite KR with TSLL
} else if (cmdAngle < -21.) {
if (cmd != KR) // don't overwrite KR with TSLL
{
cmd = TSLL;
}
}
else if ( cmdAngle < 21. )
{
if ( cmd != KR && cmd != KL ) // don't overwrite KL/KR hints!
} else if (cmdAngle < 21.) {
if (cmd != KR && cmd != KL) // don't overwrite KL/KR hints!
{
cmd = C;
}
}
else if ( cmdAngle < 45. )
{
if ( cmd != KL ) // don't overwrite KL with TSLR
} 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 )
{
sb.append( " " );
appendTurnGeometry( sb, badWay );
sb.append(' ').append((int) oldPrio);
appendTurnGeometry(sb, goodWay);
if (badWays != null) {
for (MessageData badWay : badWays) {
sb.append(" ");
appendTurnGeometry(sb, badWay);
}
}
return sb.toString();
}
private void appendTurnGeometry( StringBuilder sb, MessageData msg )
{
sb.append( "(" ).append( (int)(msg.turnangle+0.5) ).append( ")" ).append( (int)(msg.priorityclassifier) );
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 )
{
transportMode = isCar ? "car" : ( isBike ? "bike" : "foot" );
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 )
{
VoiceHint input = inputs.get( offset-- );
if ( input.turnAngleConsumed )
{
while (offset >= 0 && distance < catchingRange) {
VoiceHint input = inputs.get(offset--);
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,54 +50,46 @@ 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++ )
{
VoiceHint input = inputs.get( hintIdx );
for (int hintIdx = 0; hintIdx < inputs.size(); hintIdx++) {
VoiceHint input = inputs.get(hintIdx);
float turnAngle = input.goodWay.turnangle;
distance += input.goodWay.linkdist;
int currentPrio = input.goodWay.getPrio();
int oldPrio = input.oldWay.getPrio();
int minPrio = Math.min( oldPrio, currentPrio );
int minPrio = Math.min(oldPrio, currentPrio);
boolean isLink2Highway = input.oldWay.isLinktType() && !input.goodWay.isLinktType();
if ( input.oldWay.isRoundabout() )
{
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange( inputs, hintIdx );
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 )
{
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange( inputs, hintIdx );
if (roundaboutExit > 0) {
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
input.angle = roundAboutTurnAngle;
input.distanceToNext = distance;
input.roundaboutExit = turnAngle < 0 ? -roundaboutExit : roundaboutExit;
distance = 0.;
results.add( input );
results.add(input);
roundAboutTurnAngle = 0.f;
roundaboutExit = 0;
continue;
@ -114,91 +101,77 @@ 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 )
{
minAbsAngeRaw = Math.abs( badTurn );
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;
}
}
}
boolean hasSomethingMoreStraight = Math.abs( turnAngle ) - minAbsAngeRaw > 20.;
boolean hasSomethingMoreStraight = Math.abs(turnAngle) - minAbsAngeRaw > 20.;
// unconditional triggers are all junctions with
// - higher detour prios than the minimum route prio (except link->highway junctions)
// - or candidate detours with higher prio then the route exit leg
boolean unconditionalTrigger = hasSomethingMoreStraight || ( maxPrioAll > minPrio && !isLink2Highway ) || ( maxPrioCandidates > currentPrio );
boolean unconditionalTrigger = hasSomethingMoreStraight || (maxPrioAll > minPrio && !isLink2Highway) || (maxPrioCandidates > currentPrio);
// conditional triggers (=real turning angle required) are junctions
// 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;
}
input.angle = sumNonConsumedWithinCatchingRange( inputs, hintIdx );
input.angle = sumNonConsumedWithinCatchingRange(inputs, hintIdx);
input.distanceToNext = distance;
distance = 0.;
results.add( input );
results.add(input);
}
if ( results.size() > 0 && distance < catchingRange )
{
results.get( results.size()-1 ).angle += sumNonConsumedWithinCatchingRange( inputs, hintIdx );
if (results.size() > 0 && distance < catchingRange) {
results.get(results.size() - 1).angle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
}
}
@ -207,25 +180,21 @@ 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 )
{
VoiceHint h2 = results.get(i-1);
while (dist < catchingRange && i > 0) {
VoiceHint h2 = results.get(i - 1);
dist = h2.distanceToNext;
hint.distanceToNext+= dist;
hint.distanceToNext += dist;
hint.angle += h2.angle;
i--;
if ( h2.isRoundabout() ) // if we hit a roundabout, use that as the trigger
if (h2.isRoundabout()) // if we hit a roundabout, use that as the trigger
{
h2.angle = hint.angle;
hint = h2;
@ -233,12 +202,11 @@ public final class VoiceHintProcessor
}
}
if ( !explicitRoundabouts )
{
if (!explicitRoundabouts) {
hint.roundaboutExit = 0; // use an angular hint instead
}
hint.calcCommand();
results2.add( hint );
results2.add(hint);
}
}
return results2;

View File

@ -12,11 +12,11 @@ import btools.util.CheapRuler;
public class OsmNodeNamedTest {
static int toOsmLon(double lon) {
return (int)( ( lon + 180. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
return (int) ((lon + 180.) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
}
static int toOsmLat(double lat) {
return (int)( ( lat + 90. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
return (int) ((lat + 90.) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
}
@Test

View File

@ -1,6 +1,6 @@
/**********************************************************************************************
Copyright (C) 2018 Norbert Truchsess norbert.truchsess@t-online.de
**********************************************************************************************/
**********************************************************************************************/
package btools.router;
import static org.junit.Assert.assertEquals;
@ -22,26 +22,26 @@ public class OsmNogoPolygonTest {
static OsmNogoPolygon polygon;
static OsmNogoPolygon polyline;
static final double[] lons = { 1.0, 1.0, 0.5, 0.5, 1.0, 1.0, -1.1, -1.0 };
static final double[] lats = { -1.0, -0.1, -0.1, 0.1, 0.1, 1.0, 1.1, -1.0 };
static final double[] lons = {1.0, 1.0, 0.5, 0.5, 1.0, 1.0, -1.1, -1.0};
static final double[] lats = {-1.0, -0.1, -0.1, 0.1, 0.1, 1.0, 1.1, -1.0};
static int toOsmLon(double lon, int offset_x) {
return (int)( ( lon + 180. ) *1000000. + 0.5)+offset_x; // see ServerHandler.readPosition()
return (int) ((lon + 180.) * 1000000. + 0.5) + offset_x; // see ServerHandler.readPosition()
}
static int toOsmLat(double lat, int offset_y) {
return (int)( ( lat + 90. ) *1000000. + 0.5)+offset_y;
return (int) ((lat + 90.) * 1000000. + 0.5) + offset_y;
}
@BeforeClass
public static void setUp() throws Exception {
polygon = new OsmNogoPolygon(true);
for (int i = 0; i<lons.length; i++) {
polygon.addVertex(toOsmLon(lons[i], OFFSET_X),toOsmLat(lats[i], OFFSET_Y));
for (int i = 0; i < lons.length; i++) {
polygon.addVertex(toOsmLon(lons[i], OFFSET_X), toOsmLat(lats[i], OFFSET_Y));
}
polyline = new OsmNogoPolygon(false);
for (int i = 0; i<lons.length; i++) {
polyline.addVertex(toOsmLon(lons[i], OFFSET_X),toOsmLat(lats[i], OFFSET_Y));
for (int i = 0; i < lons.length; i++) {
polyline.addVertex(toOsmLon(lons[i], OFFSET_X), toOsmLat(lats[i], OFFSET_Y));
}
}
@ -51,91 +51,91 @@ public class OsmNogoPolygonTest {
@Test
public void testCalcBoundingCircle() {
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( polygon.ilat );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales(polygon.ilat);
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
polygon.calcBoundingCircle();
double r = polygon.radius;
for (int i=0; i<lons.length; i++) {
for (int i = 0; i < lons.length; i++) {
double dpx = (toOsmLon(lons[i], OFFSET_X) - polygon.ilon) * dlon2m;
double dpy = (toOsmLat(lats[i], OFFSET_Y) - polygon.ilat) * dlat2m;
double r1 = Math.sqrt(dpx * dpx + dpy * dpy);
double diff = r-r1;
assertTrue("i: "+i+" r("+r+") >= r1("+r1+")", diff >= 0);
double diff = r - r1;
assertTrue("i: " + i + " r(" + r + ") >= r1(" + r1 + ")", diff >= 0);
}
polyline.calcBoundingCircle();
r = polyline.radius;
for (int i=0; i<lons.length; i++) {
for (int i = 0; i < lons.length; i++) {
double dpx = (toOsmLon(lons[i], OFFSET_X) - polyline.ilon) * dlon2m;
double dpy = (toOsmLat(lats[i], OFFSET_Y) - polyline.ilat) * dlat2m;
double r1 = Math.sqrt(dpx * dpx + dpy * dpy);
double diff = r-r1;
assertTrue("i: "+i+" r("+r+") >= r1("+r1+")", diff >= 0);
double diff = r - r1;
assertTrue("i: " + i + " r(" + r + ") >= r1(" + r1 + ")", diff >= 0);
}
}
@Test
public void testIsWithin() {
double[] plons = { 0.0, 0.5, 1.0, -1.5, -0.5, 1.0, 1.0, 0.5, 0.5, 0.5, };
double[] plats = { 0.0, 1.5, 0.0, 0.5, -1.5, -1.0, -0.1, -0.1, 0.0, 0.1, };
boolean[] within = { true, false, false, false, false, true, true, true, true, true, };
double[] plons = {0.0, 0.5, 1.0, -1.5, -0.5, 1.0, 1.0, 0.5, 0.5, 0.5,};
double[] plats = {0.0, 1.5, 0.0, 0.5, -1.5, -1.0, -0.1, -0.1, 0.0, 0.1,};
boolean[] within = {true, false, false, false, false, true, true, true, true, true,};
for (int i=0; i<plons.length; i++) {
assertEquals("("+plons[i]+","+plats[i]+")",within[i],polygon.isWithin(toOsmLon(plons[i], OFFSET_X), toOsmLat(plats[i], OFFSET_Y)));
for (int i = 0; i < plons.length; i++) {
assertEquals("(" + plons[i] + "," + plats[i] + ")", within[i], polygon.isWithin(toOsmLon(plons[i], OFFSET_X), toOsmLat(plats[i], OFFSET_Y)));
}
}
@Test
public void testIntersectsPolygon() {
double[] p0lons = { 0.0, 1.0, -0.5, 0.5, 0.7, 0.7, 0.7, -1.5, -1.5, 0.0 };
double[] p0lats = { 0.0, 0.0, 0.5, 0.5, 0.5, 0.05, 0.05, -1.5, 0.2, 0.0 };
double[] p1lons = { 0.0, 1.0, 0.5, 1.0, 0.7, 0.7, 0.7, -0.5, -0.2, 0.5 };
double[] p1lats = { 0.0, 0.0, 0.5, 0.5, -0.5, -0.5, -0.05, -0.5, 1.5, -1.5 };
boolean[] within = { false, false, false, true, true, true, false, true, true, true };
double[] p0lons = {0.0, 1.0, -0.5, 0.5, 0.7, 0.7, 0.7, -1.5, -1.5, 0.0};
double[] p0lats = {0.0, 0.0, 0.5, 0.5, 0.5, 0.05, 0.05, -1.5, 0.2, 0.0};
double[] p1lons = {0.0, 1.0, 0.5, 1.0, 0.7, 0.7, 0.7, -0.5, -0.2, 0.5};
double[] p1lats = {0.0, 0.0, 0.5, 0.5, -0.5, -0.5, -0.05, -0.5, 1.5, -1.5};
boolean[] within = {false, false, false, true, true, true, false, true, true, true};
for (int i=0; i<p0lons.length; i++) {
assertEquals("("+p0lons[i]+","+p0lats[i]+")-("+p1lons[i]+","+p1lats[i]+")",within[i],polygon.intersects(toOsmLon(p0lons[i], OFFSET_X), toOsmLat(p0lats[i], OFFSET_Y), toOsmLon(p1lons[i], OFFSET_X), toOsmLat(p1lats[i], OFFSET_Y)));
for (int i = 0; i < p0lons.length; i++) {
assertEquals("(" + p0lons[i] + "," + p0lats[i] + ")-(" + p1lons[i] + "," + p1lats[i] + ")", within[i], polygon.intersects(toOsmLon(p0lons[i], OFFSET_X), toOsmLat(p0lats[i], OFFSET_Y), toOsmLon(p1lons[i], OFFSET_X), toOsmLat(p1lats[i], OFFSET_Y)));
}
}
@Test
public void testIntersectsPolyline() {
double[] p0lons = { 0.0, 1.0, -0.5, 0.5, 0.7, 0.7, 0.7, -1.5, -1.5, 0.0 };
double[] p0lats = { 0.0, 0.0, 0.5, 0.5, 0.5, 0.05, 0.05, -1.5, 0.2, 0.0 };
double[] p1lons = { 0.0, 1.0, 0.5, 1.0, 0.7, 0.7, 0.7, -0.5, -0.2, 0.5 };
double[] p1lats = { 0.0, 0.0, 0.5, 0.5, -0.5, -0.5, -0.05, -0.5, 1.5, -1.5 };
boolean[] within = { false, false, false, true, true, true, false, true, true, false };
double[] p0lons = {0.0, 1.0, -0.5, 0.5, 0.7, 0.7, 0.7, -1.5, -1.5, 0.0};
double[] p0lats = {0.0, 0.0, 0.5, 0.5, 0.5, 0.05, 0.05, -1.5, 0.2, 0.0};
double[] p1lons = {0.0, 1.0, 0.5, 1.0, 0.7, 0.7, 0.7, -0.5, -0.2, 0.5};
double[] p1lats = {0.0, 0.0, 0.5, 0.5, -0.5, -0.5, -0.05, -0.5, 1.5, -1.5};
boolean[] within = {false, false, false, true, true, true, false, true, true, false};
for (int i=0; i<p0lons.length; i++) {
assertEquals("("+p0lons[i]+","+p0lats[i]+")-("+p1lons[i]+","+p1lats[i]+")",within[i],polyline.intersects(toOsmLon(p0lons[i], OFFSET_X), toOsmLat(p0lats[i], OFFSET_Y), toOsmLon(p1lons[i], OFFSET_X), toOsmLat(p1lats[i], OFFSET_Y)));
for (int i = 0; i < p0lons.length; i++) {
assertEquals("(" + p0lons[i] + "," + p0lats[i] + ")-(" + p1lons[i] + "," + p1lats[i] + ")", within[i], polyline.intersects(toOsmLon(p0lons[i], OFFSET_X), toOsmLat(p0lats[i], OFFSET_Y), toOsmLon(p1lons[i], OFFSET_X), toOsmLat(p1lats[i], OFFSET_Y)));
}
}
@Test
public void testBelongsToLine() {
assertTrue(OsmNogoPolygon.isOnLine(10,10, 10,10, 10,20));
assertTrue(OsmNogoPolygon.isOnLine(10,10, 10,10, 20,10));
assertTrue(OsmNogoPolygon.isOnLine(10,10, 20,10, 10,10));
assertTrue(OsmNogoPolygon.isOnLine(10,10, 10,20, 10,10));
assertTrue(OsmNogoPolygon.isOnLine(10,15, 10,10, 10,20));
assertTrue(OsmNogoPolygon.isOnLine(15,10, 10,10, 20,10));
assertTrue(OsmNogoPolygon.isOnLine(10,10, 10,10, 20,30));
assertTrue(OsmNogoPolygon.isOnLine(20,30, 10,10, 20,30));
assertTrue(OsmNogoPolygon.isOnLine(15,20, 10,10, 20,30));
assertFalse(OsmNogoPolygon.isOnLine(11,11, 10,10, 10,20));
assertFalse(OsmNogoPolygon.isOnLine(11,11, 10,10, 20,10));
assertFalse(OsmNogoPolygon.isOnLine(15,21, 10,10, 20,30));
assertFalse(OsmNogoPolygon.isOnLine(15,19, 10,10, 20,30));
assertFalse(OsmNogoPolygon.isOnLine(0,-10, 10,10, 20,30));
assertFalse(OsmNogoPolygon.isOnLine(30,50, 10,10, 20,30));
assertTrue(OsmNogoPolygon.isOnLine(10, 10, 10, 10, 10, 20));
assertTrue(OsmNogoPolygon.isOnLine(10, 10, 10, 10, 20, 10));
assertTrue(OsmNogoPolygon.isOnLine(10, 10, 20, 10, 10, 10));
assertTrue(OsmNogoPolygon.isOnLine(10, 10, 10, 20, 10, 10));
assertTrue(OsmNogoPolygon.isOnLine(10, 15, 10, 10, 10, 20));
assertTrue(OsmNogoPolygon.isOnLine(15, 10, 10, 10, 20, 10));
assertTrue(OsmNogoPolygon.isOnLine(10, 10, 10, 10, 20, 30));
assertTrue(OsmNogoPolygon.isOnLine(20, 30, 10, 10, 20, 30));
assertTrue(OsmNogoPolygon.isOnLine(15, 20, 10, 10, 20, 30));
assertFalse(OsmNogoPolygon.isOnLine(11, 11, 10, 10, 10, 20));
assertFalse(OsmNogoPolygon.isOnLine(11, 11, 10, 10, 20, 10));
assertFalse(OsmNogoPolygon.isOnLine(15, 21, 10, 10, 20, 30));
assertFalse(OsmNogoPolygon.isOnLine(15, 19, 10, 10, 20, 30));
assertFalse(OsmNogoPolygon.isOnLine(0, -10, 10, 10, 20, 30));
assertFalse(OsmNogoPolygon.isOnLine(30, 50, 10, 10, 20, 30));
}
@Test
public void testDistanceWithinPolygon() {
// Testing polygon
final double[] lons = { 2.333523, 2.333432, 2.333833, 2.333983, 2.334815, 2.334766 };
final double[] lats = { 48.823778, 48.824091, 48.82389, 48.824165, 48.824232, 48.82384 };
final double[] lons = {2.333523, 2.333432, 2.333833, 2.333983, 2.334815, 2.334766};
final double[] lats = {48.823778, 48.824091, 48.82389, 48.824165, 48.824232, 48.82384};
OsmNogoPolygon polygon = new OsmNogoPolygon(true);
for (int i = 0; i < lons.length; i++) {
polygon.addVertex(toOsmLon(lons[i], 0), toOsmLat(lats[i], 0));

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,36 +36,29 @@ final class BExpression
private int[] lookupValueIdxArray;
// Parse the expression and all subexpression
public static BExpression parse( BExpressionContext ctx, int level ) throws Exception
{
return parse( ctx, level, null );
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 ( level == 0 ) return null;
else throw new IllegalArgumentException( "unexpected end of file" );
if (operator == null) {
if (level == 0) return null;
else throw new IllegalArgumentException("unexpected end of file");
}
if ( level == 0 )
{
if ( !"assign".equals( operator ) )
{
throw new IllegalArgumentException( "operator " + operator + " is invalid on toplevel (only 'assign' allowed)" );
if (level == 0) {
if (!"assign".equals(operator)) {
throw new IllegalArgumentException("operator " + operator + " is invalid on toplevel (only 'assign' allowed)");
}
}
@ -74,113 +66,77 @@ 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 ( level > 0 ) throw new IllegalArgumentException( "assign operator within expression" );
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 );
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 (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);
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)) {
exp.typ = NOT_EXP;
}
else
{
} else {
nops = 0; // check elemantary expressions
int idx = operator.indexOf( '=' );
if ( idx >= 0 )
{
int idx = operator.indexOf('=');
if (idx >= 0) {
exp.typ = LOOKUP_EXP;
String name = operator.substring( 0, idx );
String values = operator.substring( idx+1 );
String name = operator.substring(0, idx);
String values = operator.substring(idx + 1);
exp.lookupNameIdx = ctx.getLookupNameIdx( name );
if ( exp.lookupNameIdx < 0 )
{
throw new IllegalArgumentException( "unknown lookup name: " + name );
exp.lookupNameIdx = ctx.getLookupNameIdx(name);
if (exp.lookupNameIdx < 0) {
throw new IllegalArgumentException("unknown lookup name: " + name);
}
ctx.markLookupIdxUsed( exp.lookupNameIdx );
StringTokenizer tk = new StringTokenizer( values, "|" );
ctx.markLookupIdxUsed(exp.lookupNameIdx);
StringTokenizer tk = new StringTokenizer(values, "|");
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 )
{
throw new IllegalArgumentException( "unknown lookup value: " + value );
exp.lookupValueIdxArray[ti] = ctx.getLookupValueIdx(exp.lookupNameIdx, value);
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
@ -191,110 +147,109 @@ final class BExpression
if (operator.startsWith("v:")) {
String name = operator.substring(2);
exp.typ = VARIABLE_GET_EXP;
exp.lookupNameIdx = ctx.getLookupNameIdx( name );
exp.lookupNameIdx = ctx.getLookupNameIdx(name);
} else {
String context = operator.substring( 0, idx );
String varname = operator.substring( idx+1 );
String context = operator.substring(0, idx);
String varname = operator.substring(idx + 1);
exp.typ = FOREIGN_VARIABLE_EXP;
exp.variableIdx = ctx.getForeignVariableIdx( context, varname );
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
{
exp.numberValue = Float.parseFloat( operator );
} else {
try {
exp.numberValue = Float.parseFloat(operator);
exp.typ = NUMBER_EXP;
}
catch( NumberFormatException nfe )
{
throw new IllegalArgumentException( "unknown expression: " + operator );
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("unknown expression: " + operator);
}
}
}
}
}
// parse operands
if ( nops > 0 )
{
exp.op1 = BExpression.parse( ctx, level+1, exp.typ == ASSIGN_EXP ? "=" : null );
if (nops > 0) {
exp.op1 = BExpression.parse(ctx, level + 1, exp.typ == ASSIGN_EXP ? "=" : null);
}
if ( nops > 1 )
{
if ( ifThenElse ) checkExpectedToken( ctx, "then" );
exp.op2 = BExpression.parse( ctx, level+1, null );
if (nops > 1) {
if (ifThenElse) checkExpectedToken(ctx, "then");
exp.op2 = BExpression.parse(ctx, level + 1, null);
}
if ( nops > 2 )
{
if ( ifThenElse ) checkExpectedToken( ctx, "else" );
exp.op3 = BExpression.parse( ctx, level+1, null );
if (nops > 2) {
if (ifThenElse) checkExpectedToken(ctx, "else");
exp.op3 = BExpression.parse(ctx, level + 1, null);
}
if ( brackets )
{
checkExpectedToken( ctx, ")" );
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 ) )
{
throw new IllegalArgumentException( "unexpected token: " + token + ", expected: " + expected );
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

@ -7,23 +7,21 @@
package btools.expressions;
public final class BExpressionContextNode extends BExpressionContext
{
public final class BExpressionContextNode extends BExpressionContext {
private static String[] buildInVariables =
{ "initialcost" };
{"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 )
{
super( "node", 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 )
{
super( "node", hashSize, meta );
public BExpressionContextNode(int hashSize, BExpressionMetaData meta) {
super("node", hashSize, meta);
}
}

View File

@ -8,34 +8,66 @@ 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" };
{"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 )
{
super( "way", 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 )
{
super( "way", hashSize, meta );
public BExpressionContextWay(int hashSize, BExpressionMetaData meta) {
super("way", hashSize, meta);
}
@Override
public int accessType( byte[] description )
{
evaluate( false, 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 )
{
this.decodeForbidden= 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,53 +11,43 @@ 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 )
{
if ( aliases == null ) aliases = new ArrayList<String>();
aliases.add( 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 )
{
String v = (String)o;
return value.equals( v );
public boolean equals(Object o) {
if (o instanceof String) {
String v = (String) o;
return value.equals(v);
}
if ( o instanceof BExpressionLookupValue )
{
BExpressionLookupValue v = (BExpressionLookupValue)o;
if (o instanceof BExpressionLookupValue) {
BExpressionLookupValue v = (BExpressionLookupValue) o;
return value.equals( v.value );
return value.equals(v.value);
}
return false;
}
public boolean matches( String s )
{
if ( value.equals( s ) ) return true;
if ( aliases != null )
{
for( String alias : aliases )
{
if ( alias.equals( s ) ) return true;
public boolean matches(String s) {
if (value.equals(s)) return true;
if (aliases != null) {
for (String alias : aliases) {
if (alias.equals(s)) return true;
}
}
return false;

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:";
@ -31,59 +30,49 @@ public final class BExpressionMetaData
public short lookupVersion = -1;
public short lookupMinorVersion = -1;
private HashMap<String,BExpressionContext> listeners = new HashMap<String,BExpressionContext>();
private HashMap<String, BExpressionContext> listeners = new HashMap<String, BExpressionContext>();
public void registerListener( String context, BExpressionContext ctx )
{
listeners.put( context, ctx );
public void registerListener(String context, BExpressionContext ctx) {
listeners.put(context, ctx);
}
public void readMetaData( File lookupsFile )
{
try
{
BufferedReader br = new BufferedReader( new FileReader( lookupsFile ) );
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;
if (line == null) break;
line = line.trim();
if ( line.length() == 0 || line.startsWith( "#" ) ) continue;
if ( line.startsWith( CONTEXT_TAG ) )
{
ctx = listeners.get( line.substring( CONTEXT_TAG.length() ) );
if (line.length() == 0 || line.startsWith("#")) continue;
if (line.startsWith(CONTEXT_TAG)) {
ctx = listeners.get(line.substring(CONTEXT_TAG.length()));
continue;
}
if ( line.startsWith( VERSION_TAG ) )
{
lookupVersion = Short.parseShort( line.substring( VERSION_TAG.length() ) );
if (line.startsWith(VERSION_TAG)) {
lookupVersion = Short.parseShort(line.substring(VERSION_TAG.length()));
continue;
}
if ( line.startsWith( MINOR_VERSION_TAG ) )
{
lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) );
if (line.startsWith(MINOR_VERSION_TAG)) {
lookupMinorVersion = Short.parseShort(line.substring(MINOR_VERSION_TAG.length()));
continue;
}
if ( line.startsWith( VARLENGTH_TAG ) ) // tag removed...
if (line.startsWith(VARLENGTH_TAG)) // tag removed...
{
continue;
}
if ( ctx != null ) ctx.parseMetaLine( line );
if (ctx != null) ctx.parseMetaLine(line);
}
br.close();
for( BExpressionContext c : listeners.values() )
{
for (BExpressionContext c : listeners.values()) {
c.finishMetaParsing();
}
}
catch( Exception e )
{
throw new RuntimeException( e );
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -4,29 +4,24 @@ 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 );
return Arrays.equals(ab, n.ab);
}
}

View File

@ -3,45 +3,40 @@ 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 )
{
System.out.println( "usage: java ProfileComparator <lookup-file> <profile1> <profile2> <nsamples>" );
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;
}
File lookupFile = new File( args[0] );
File profile1File = new File( args[1] );
File profile2File = new File( args[2] );
int nsamples = Integer.parseInt( args[3] );
testContext( lookupFile, profile1File, profile2File, nsamples, false );
testContext( lookupFile, profile1File, profile2File, nsamples, true );
File lookupFile = new File(args[0]);
File profile1File = new File(args[1]);
File profile2File = new File(args[2]);
int nsamples = Integer.parseInt(args[3]);
testContext(lookupFile, profile1File, profile2File, nsamples, false);
testContext(lookupFile, profile1File, profile2File, nsamples, true);
}
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();
BExpressionContext expctx1 = nodeContext ? new BExpressionContextNode( meta1 ) : new BExpressionContextWay( meta1 );
BExpressionContext expctx2 = nodeContext ? new BExpressionContextNode( meta2 ) : new BExpressionContextWay( meta2 );
meta1.readMetaData( lookupFile );
meta2.readMetaData( lookupFile );
expctx1.parseFile( profile1File, "global" );
expctx2.parseFile( profile2File, "global" );
BExpressionContext expctx1 = nodeContext ? new BExpressionContextNode(meta1) : new BExpressionContextWay(meta1);
BExpressionContext expctx2 = nodeContext ? new BExpressionContextNode(meta2) : new BExpressionContextWay(meta2);
meta1.readMetaData(lookupFile);
meta2.readMetaData(lookupFile);
expctx1.parseFile(profile1File, "global");
expctx2.parseFile(profile2File, "global");
Random rnd = new Random();
for( int i=0; i<nsamples; i++ )
{
int[] data = expctx1.generateRandomValues( rnd );
expctx1.evaluate( data );
expctx2.evaluate( data );
for (int i = 0; i < nsamples; i++) {
int[] data = expctx1.generateRandomValues(rnd);
expctx1.evaluate(data);
expctx2.evaluate(data);
expctx1.assertAllVariablesEqual( expctx2 );
expctx1.assertAllVariablesEqual(expctx2);
}
}
}

View File

@ -4,24 +4,20 @@ 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 );
return Arrays.equals(vars, n.vars);
}
}

View File

@ -7,24 +7,22 @@ import java.net.URL;
import org.junit.Assert;
import org.junit.Test;
public class EncodeDecodeTest
{
public class EncodeDecodeTest {
@Test
public void encodeDecodeTest()
{
URL testpurl = this.getClass().getResource( "/dummy.txt" );
public void encodeDecodeTest() {
URL testpurl = this.getClass().getResource("/dummy.txt");
File workingDir = new File(testpurl.getFile()).getParentFile();
File profileDir = new File( workingDir, "/../../../../misc/profiles2" );
File profileDir = new File(workingDir, "/../../../../misc/profiles2");
//File lookupFile = new File( profileDir, "lookups.dat" );
// add a test lookup
URL testlookup = this.getClass().getResource( "/lookups_test.dat" );
File lookupFile = new File( testlookup.getPath() );
URL testlookup = this.getClass().getResource("/lookups_test.dat");
File lookupFile = new File(testlookup.getPath());
// read lookup.dat + trekking.brf
BExpressionMetaData meta = new BExpressionMetaData();
BExpressionContextWay expctxWay = new BExpressionContextWay( meta );
meta.readMetaData( lookupFile );
expctxWay.parseFile( new File( profileDir, "trekking.brf" ), "global" );
BExpressionContextWay expctxWay = new BExpressionContextWay(meta);
meta.readMetaData(lookupFile);
expctxWay.parseFile(new File(profileDir, "trekking.brf"), "global");
String[] tags = {
"highway=residential",
@ -38,23 +36,23 @@ public class EncodeDecodeTest
// encode the tags into 64 bit description word
int[] lookupData = expctxWay.createNewLookupData();
for( String arg: tags )
{
int idx = arg.indexOf( '=' );
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 );
for (String arg : tags) {
int idx = arg.indexOf('=');
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);
expctxWay.addLookupValue( key, value, lookupData );
expctxWay.addLookupValue(key, value, lookupData);
}
byte[] description = expctxWay.encode(lookupData);
// calculate the cost factor from that description
expctxWay.evaluate( true, description ); // true = "reversedirection=yes" (not encoded in description anymore)
expctxWay.evaluate(true, description); // true = "reversedirection=yes" (not encoded in description anymore)
System.out.println( "description: " + expctxWay.getKeyValueDescription(true, description) );
System.out.println("description: " + expctxWay.getKeyValueDescription(true, description));
float costfactor = expctxWay.getCostfactor();
Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 );
Assert.assertTrue("costfactor mismatch", Math.abs(costfactor - 5.15) < 0.00001);
}
}

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,78 +20,63 @@ public class ConvertLidarTile
static short[] imagePixels;
private static void readHgtZip( String filename, int rowOffset, int colOffset ) throws Exception
{
ZipInputStream zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( filename ) ) );
try
{
for ( ;; )
{
private static void readHgtZip(String filename, int rowOffset, int colOffset) throws Exception {
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(filename)));
try {
for (; ; ) {
ZipEntry ze = zis.getNextEntry();
if ( ze.getName().endsWith( ".hgt" ) )
{
readHgtFromStream( zis, rowOffset, colOffset );
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
{
DataInputStream dis = new DataInputStream( new BufferedInputStream( is ) );
for ( int ir = 0; ir < 1201; ir++ )
{
private static void readHgtFromStream(InputStream is, int rowOffset, int colOffset)
throws Exception {
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
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!
int i0 = dis.read();
if ( i0 == -1 || i1 == -1 )
throw new RuntimeException( "unexcepted end of file reading hgt entry!" );
if (i0 == -1 || i1 == -1)
throw new RuntimeException("unexcepted end of file reading hgt entry!");
short val = (short) ( ( i1 << 8 ) | i0 );
short val = (short) ((i1 << 8) | i0);
if ( val == NODATA2 )
{
if (val == NODATA2) {
val = NODATA;
}
setPixel( row, col, val );
setPixel(row, col, val);
}
}
}
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,34 +85,27 @@ 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;
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 )
{
System.out.println( "exist: " + filename );
readHgtZip( filename, rowOffset, colOffset );
}
else
{
System.out.println( "none : " + filename );
String filename = inputDir + "/" + formatLat(latDegree) + formatLon(lonDegree) + ".zip";
File f = new File(filename);
if (f.exists() && f.length() > 0) {
System.out.println("exist: " + filename);
readHgtZip(filename, rowOffset, colOffset);
} else {
System.out.println("none : " + filename);
}
}
}
@ -142,79 +119,71 @@ public class ConvertLidarTile
raster.halfcol = halfCol5;
raster.noDataValue = NODATA;
raster.cellsize = 1 / 1200.;
raster.xllcorner = lonDegreeStart - ( 0.5 + extraBorder ) * raster.cellsize;
raster.yllcorner = latDegreeStart - ( 0.5 + extraBorder ) * raster.cellsize;
raster.xllcorner = lonDegreeStart - (0.5 + extraBorder) * raster.cellsize;
raster.yllcorner = latDegreeStart - (0.5 + extraBorder) * raster.cellsize;
raster.eval_array = imagePixels;
// encode the raster
OutputStream os = new BufferedOutputStream( new FileOutputStream( outputFile ) );
new RasterCoder().encodeRaster( raster, os );
OutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
new RasterCoder().encodeRaster(raster, os);
os.close();
// decode the raster
InputStream is = new BufferedInputStream( new FileInputStream( outputFile ) );
SrtmRaster raster2 = new RasterCoder().decodeRaster( is );
InputStream is = new BufferedInputStream(new FileInputStream(outputFile));
SrtmRaster raster2 = new RasterCoder().decodeRaster(is);
is.close();
short[] pix2 = raster2.eval_array;
if ( pix2.length != imagePixels.length )
throw new RuntimeException( "length mismatch!" );
if (pix2.length != imagePixels.length)
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] )
{
throw new RuntimeException( "content mismatch: p2=" + p2 + " p1=" + imagePixels[idx] );
if (p2 != imagePixels[idx]) {
throw new RuntimeException("content mismatch: p2=" + p2 + " p1=" + imagePixels[idx]);
}
}
}
}
private static String formatLon( int lon )
{
if ( lon >= 180 )
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";
}
String n = "000" + lon;
return s + n.substring( n.length() - 3 );
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";
}
String n = "00" + lat;
return s + n.substring( n.length() - 2 );
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";
String filename30 = filename90.substring(0, filename90.length() - 3) + "bef";
int srtmLonIdx = Integer.parseInt( filename90.substring( 5, 7 ).toLowerCase() );
int srtmLatIdx = Integer.parseInt( filename90.substring( 8, 10 ).toLowerCase() );
int srtmLonIdx = Integer.parseInt(filename90.substring(5, 7).toLowerCase());
int srtmLatIdx = Integer.parseInt(filename90.substring(8, 10).toLowerCase());
int ilon_base = ( srtmLonIdx - 1 ) * 5 - 180;
int ilon_base = (srtmLonIdx - 1) * 5 - 180;
int ilat_base = 150 - srtmLatIdx * 5 - 90;
doConvert( args[1], ilon_base, ilat_base, filename30 );
doConvert(args[1], ilon_base, ilat_base, filename30);
}
}

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,44 +15,33 @@ public class ConvertSrtmTile
public static int[] diffs = new int[100];
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 ( ;; )
{
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 (; ; ) {
ZipEntry ze = zis.getNextEntry();
if ( ze.getName().endsWith( ".bil" ) )
{
readBilFromStream( zis, rowOffset, colOffset, halfCols );
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
{
DataInputStream dis = new DataInputStream( new BufferedInputStream( is ) );
for ( int ir = 0; ir < 3601; ir++ )
{
private static void readBilFromStream(InputStream is, int rowOffset, int colOffset, boolean halfCols)
throws Exception {
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
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 )
{
setPixel( row, col, SKIPDATA );
if ((ic % 2) == 1 && halfCols) {
if (getPixel(row, col) == NODATA) {
setPixel(row, col, SKIPDATA);
}
continue;
}
@ -61,42 +49,36 @@ public class ConvertSrtmTile
int i0 = dis.read();
int i1 = dis.read();
if ( i0 == -1 || i1 == -1 )
throw new RuntimeException( "unexcepted end of file reading bil entry!" );
if (i0 == -1 || i1 == -1)
throw new RuntimeException("unexcepted end of file reading bil entry!");
short val = (short) ( ( i1 << 8 ) | i0 );
short val = (short) ((i1 << 8) | i0);
if ( val == NODATA2 )
{
if (val == NODATA2) {
val = NODATA;
}
setPixel( row, col, val );
setPixel(row, col, val);
}
}
}
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,95 +89,74 @@ 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;
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 )
{
System.out.println( "exist: " + filename );
String filename = inputDir + "/" + formatLat(latDegree) + "_" + formatLon(lonDegree) + "_1arc_v3_bil.zip";
File f = new File(filename);
if (f.exists() && f.length() > 0) {
System.out.println("exist: " + filename);
boolean halfCol = latDegree >= 50 || latDegree < -50;
readBilZip( filename, rowOffset, colOffset, halfCol );
}
else
{
System.out.println( "none : " + filename );
readBilZip(filename, rowOffset, colOffset, halfCol);
} else {
System.out.println("none : " + filename);
}
}
}
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;
}
}
@ -210,102 +171,90 @@ public class ConvertSrtmTile
raster.halfcol = halfCol5;
raster.noDataValue = NODATA;
raster.cellsize = 1 / 3600.;
raster.xllcorner = lonDegreeStart - ( 0.5 + extraBorder ) * raster.cellsize;
raster.yllcorner = latDegreeStart - ( 0.5 + extraBorder ) * raster.cellsize;
raster.xllcorner = lonDegreeStart - (0.5 + extraBorder) * raster.cellsize;
raster.yllcorner = latDegreeStart - (0.5 + extraBorder) * raster.cellsize;
raster.eval_array = imagePixels;
// encode the raster
OutputStream os = new BufferedOutputStream( new FileOutputStream( outputFile ) );
new RasterCoder().encodeRaster( raster, os );
OutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
new RasterCoder().encodeRaster(raster, os);
os.close();
// decode the raster
InputStream is = new BufferedInputStream( new FileInputStream( outputFile ) );
SrtmRaster raster2 = new RasterCoder().decodeRaster( is );
InputStream is = new BufferedInputStream(new FileInputStream(outputFile));
SrtmRaster raster2 = new RasterCoder().decodeRaster(is);
is.close();
short[] pix2 = raster2.eval_array;
if ( pix2.length != imagePixels.length )
throw new RuntimeException( "length mismatch!" );
if (pix2.length != imagePixels.length)
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] )
{
throw new RuntimeException( "content mismatch!" );
if (p2 != imagePixels[idx]) {
throw new RuntimeException("content mismatch!");
}
}
}
for(int i=1; i<100;i++) System.out.println( "diff[" + (i-50) + "] = " + diffs[i] );
System.out.println( "datacells=" + datacells + " mismatch%=" + (100.*mismatches)/datacells );
btools.util.MixCoderDataOutputStream.stats();
for (int i = 1; i < 100; i++) System.out.println("diff[" + (i - 50) + "] = " + diffs[i]);
System.out.println("datacells=" + datacells + " mismatch%=" + (100. * mismatches) / datacells);
btools.util.MixCoderDataOutputStream.stats();
// test( raster );
// raster.calcWeights( 50. );
// test( raster );
// 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. );
int ival = (int) (raster.getElevation(lon, lat) / 4.);
String sval = " " + ival;
sb.append( sval.substring( sval.length() - 4 ) );
sb.append(sval.substring(sval.length() - 4));
}
System.out.println( sb );
System.out.println(sb);
System.out.println();
}
}
private static String formatLon( int lon )
{
if ( lon >= 180 )
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";
}
String n = "000" + lon;
return s + n.substring( n.length() - 3 );
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";
}
String n = "00" + lat;
return s + n.substring( n.length() - 2 );
return s + n.substring(n.length() - 2);
}
}

View File

@ -4,54 +4,47 @@ 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
{
BufferedReader br = new BufferedReader( new FileReader( args[0] ) );
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 )
{
int idx1 = line.indexOf("srtm_");
if (idx1 < 0) {
continue;
}
String filename90 = line.substring( idx1 );
String filename30 = filename90.substring( 0, filename90.length() - 3 ) + "bef";
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;
}
// int srtmLonIdx = (ilon+5000000)/5000000; -> ilon = (srtmLonIdx-1)*5
// int srtmLatIdx = (154999999-ilat)/5000000; -> ilat = 155 - srtmLatIdx*5
int srtmLonIdx = Integer.parseInt( filename90.substring( 5, 7 ).toLowerCase() );
int srtmLatIdx = Integer.parseInt( filename90.substring( 8, 10 ).toLowerCase() );
int srtmLonIdx = Integer.parseInt(filename90.substring(5, 7).toLowerCase());
int srtmLatIdx = Integer.parseInt(filename90.substring(8, 10).toLowerCase());
int ilon_base = ( srtmLonIdx - 1 ) * 5 - 180;
int ilon_base = (srtmLonIdx - 1) * 5 - 180;
int ilat_base = 150 - srtmLatIdx * 5 - 90;
SrtmRaster raster90 = null;
File file90 = new File( new File( args[1] ), filename90 );
if ( file90.exists() )
{
System.out.println( "reading " + file90 );
raster90 = new SrtmData( file90 ).getRaster();
File file90 = new File(new File(args[1]), filename90);
if (file90.exists()) {
System.out.println("reading " + file90);
raster90 = new SrtmData(file90).getRaster();
}
ConvertSrtmTile.doConvert( args[2], args[3], ilon_base, ilat_base, filename30, raster90 );
ConvertSrtmTile.doConvert(args[2], args[3], ilon_base, ilat_base, filename30, raster90);
}
br.close();
}

View File

@ -9,76 +9,63 @@ 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 )
{
int last = nodes.size() - 1;
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 )
{
doDPFilter( nodes, first, last );
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 );
OsmNodeP p2 = nodes.get( last );
OsmNodeP p1 = nodes.get(first);
OsmNodeP p2 = nodes.get(last);
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (p1.ilat+p2.ilat) >> 1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((p1.ilat + p2.ilat) >> 1);
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
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++ )
{
OsmNodeP p = nodes.get( i );
for (int i = first + 1; i < last; i++) {
OsmNodeP p = nodes.get(i);
double t = 0.;
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 );
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 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 )
{
doDPFilter( nodes, first, index );
if (index >= 0) {
if (index - first > 1) {
doDPFilter(nodes, first, index);
}
if ( maxSqDist >= dp_sql_threshold )
{
nodes.get( index ).bits |= OsmNodeP.DP_SURVIVOR_BIT;
if (maxSqDist >= dp_sql_threshold) {
nodes.get(index).bits |= OsmNodeP.DP_SURVIVOR_BIT;
}
if ( last - index > 1 )
{
doDPFilter( nodes, index, last );
if (last - index > 1) {
doDPFilter(nodes, index, last);
}
}
}

View File

@ -17,71 +17,59 @@ 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;
protected HashMap<String, String> tags;
public void putTag( String key, String value )
{
if ( tags == null ) tags = new HashMap<String,String>();
tags.put( key, 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 )
{
return tags == null ? null : tags.get( 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;
if (offset == 32) return -1;
long i = is.readInt();
i = i << 5;
return i | offset;
}
protected static void writeId( DataOutputStream o, long id ) throws IOException
{
if ( id == -1 )
{
o.writeByte( 32 );
protected static void writeId(DataOutputStream o, long id) throws IOException {
if (id == -1) {
o.writeByte(32);
return;
}
int offset = (int)( id & 0x1f );
int i = (int)( id >> 5 );
o.writeByte( offset );
o.writeInt( i );
int offset = (int) (id & 0x1f);
int i = (int) (id >> 5);
o.writeByte(offset);
o.writeInt(i);
}
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 i = 0; i < n; i++) sizes[i] = files[i].length();
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,51 +80,41 @@ 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 );
filename = filename.substring(0, filename.length() - 3) + suffix;
return new File(dir, filename);
}
protected DataInputStream createInStream( File inFile ) throws IOException
{
return new DataInputStream( new BufferedInputStream ( new FileInputStream( inFile ) ) );
protected DataInputStream createInStream(File inFile) throws IOException {
return new DataInputStream(new BufferedInputStream(new FileInputStream(inFile)));
}
protected DiffCoderDataOutputStream createOutStream( File outFile ) throws IOException
{
return new DiffCoderDataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
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 )
{
tileOutStreams[tileIndex] = createOutStream( new File( outTileDir, getNameForTile( tileIndex ) ) );
if (tileOutStreams[tileIndex] == null) {
tileOutStreams[tileIndex] = createOutStream(new File(outTileDir, getNameForTile(tileIndex)));
}
return tileOutStreams[tileIndex];
}
protected String getNameForTile( int tileIndex )
{
throw new IllegalArgumentException( "getNameForTile not implemented" );
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++ )
{
if ( tileOutStreams[tileIndex] != null ) tileOutStreams[tileIndex].close();
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,78 +4,69 @@ 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)
{
System.out.println("usage: java NodeCutter <node-tiles-in> <node-tiles-out>" );
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] ) );
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
{
init( nodeTilesOut );
public void process(File nodeTilesIn, File nodeTilesOut) throws Exception {
init(nodeTilesOut);
new NodeIterator( this, true ).processDir( nodeTilesIn, ".tlf" );
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
{
n.writeTo( getOutStreamForTile( getTileIndex( n.ilon, n.ilat ) ) );
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 )
{
int lonoff = (ilon / 45000000 ) * 45;
int latoff = (ilat / 30000000 ) * 30;
if ( lonoffset == -1 ) lonoffset = lonoff;
if ( latoffset == -1 ) latoffset = latoff;
if ( lonoff != lonoffset || latoff != latoffset )
throw new IllegalArgumentException( "inconsistent node: " + ilon + " " + ilat );
private int getTileIndex(int ilon, int ilat) {
int lonoff = (ilon / 45000000) * 45;
int latoff = (ilat / 30000000) * 30;
if (lonoffset == -1) lonoffset = lonoff;
if (latoffset == -1) latoffset = latoff;
if (lonoff != lonoffset || latoff != latoffset)
throw new IllegalArgumentException("inconsistent node: " + ilon + " " + ilat);
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 );
return lon*6 + lat;
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 )
{
int lon = (tileIndex / 6 ) * 5 + lonoffset - 180;
int lat = (tileIndex % 6 ) * 5 + latoffset - 90;
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;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".n5d";

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);
ilat = (int) ((lat + 90.) * 1000000. + 0.5);
ilon = (int) ((lon + 180.) * 1000000. + 0.5);
}
public NodeData( DiffCoderDataInputStream dis ) throws Exception
{
nid = dis.readDiffed( 0 );
ilon = (int)dis.readDiffed( 1 );
ilat = (int)dis.readDiffed( 2 );
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 & 2 ) != 0 ) selev = dis.readShort();
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
{
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 & 2 ) != 0 ) dos.writeShort( selev );
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 & 2) != 0) dos.writeShort(selev);
}
}

View File

@ -10,83 +10,71 @@ 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)
{
System.out.println("usage: java NodeFilter <node-tiles-in> <way-file-in> <node-tiles-out>" );
if (args.length != 3) {
System.out.println("usage: java NodeFilter <node-tiles-in> <way-file-in> <node-tiles-out>");
return;
}
new NodeFilter().process( new File( args[0] ), new File( args[1] ), new File( args[2] ) );
new NodeFilter().process(new File(args[0]), new File(args[1]), new File(args[2]));
}
public void init() throws Exception
{
nodebitmap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap( 512 ) : new TinyDenseLongMap();
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;
// read the wayfile into a bitmap of used nodes
new WayIterator( this, false ).processFile( wayFileIn );
new WayIterator(this, false).processFile(wayFileIn);
// finally filter all node files
new NodeIterator( this, true ).processDir( nodeTilesIn, ".tls" );
new NodeIterator(this, true).processDir(nodeTilesIn, ".tls");
}
@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++ )
{
nodebitmap.put( data.nodes.get(i), 0 );
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 ) ) );
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 ) )
{
n.writeTo( nodesOutStream );
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
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() )
{
throw new IllegalArgumentException( "not a directory: " + indir );
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++ )
{
File[] af = sortBySizeAsc(indir.listFiles());
for (int i = 0; i < af.length; i++) {
File nodefile = af[i];
if ( nodefile.getName().endsWith( inSuffix ) )
{
processFile( nodefile );
if (nodefile.getName().endsWith(inSuffix)) {
processFile(nodefile);
}
}
}
public void processFile(File nodefile) throws Exception
{
System.out.println( "*** NodeIterator reading: " + nodefile );
public void processFile(File nodefile) throws Exception {
System.out.println("*** NodeIterator reading: " + nodefile);
listener.nodeFileStart( nodefile );
listener.nodeFileStart(nodefile);
DiffCoderDataInputStream di = new DiffCoderDataInputStream( new BufferedInputStream ( new FileInputStream( nodefile ) ) );
try
{
for(;;)
{
NodeData n = new NodeData( di );
listener.nextNode( n );
DiffCoderDataInputStream di = new DiffCoderDataInputStream(new BufferedInputStream(new FileInputStream(nodefile)));
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" ) ))
{
listener.nodeFileEnd(nodefile);
if (delete && "true".equals(System.getProperty("deletetmpfiles"))) {
nodefile.delete();
}
}

View File

@ -7,11 +7,10 @@ import java.io.File;
*
* @author ab
*/
public interface NodeListener
{
void nodeFileStart( File nodefile ) throws Exception;
public interface NodeListener {
void nodeFileStart(File nodefile) throws Exception;
void nextNode( NodeData data ) throws Exception;
void nextNode(NodeData data) throws Exception;
void nodeFileEnd( File nodefile ) throws Exception;
void nodeFileEnd(File nodefile) 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,24 +33,22 @@ 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;
}
new OsmCutter().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] )
, args.length > 6 ? new File( args[6] ) : null
new File(args[0])
, new File(args[1])
, new File(args[2])
, new File(args[3])
, new File(args[4])
, new File(args[5])
, args.length > 6 ? new File(args[6]) : null
);
}
@ -61,50 +58,46 @@ 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() )
{
throw new IllegalArgumentException( "lookup-file: " + lookupFile + " does not exist" );
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");
}
BExpressionMetaData meta = new BExpressionMetaData();
_expctxWay = new BExpressionContextWay( meta );
_expctxNode = new BExpressionContextNode( meta );
meta.readMetaData( lookupFile );
_expctxWay.parseFile( profileFile, "global" );
_expctxWay = new BExpressionContextWay(meta);
_expctxNode = new BExpressionContextNode(meta);
meta.readMetaData(lookupFile);
_expctxWay.parseFile(profileFile, "global");
// _expctxWayStat = new BExpressionContextWay( null );
// _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 )
{
restrictionsDos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( resFile ) ) );
wayDos = wayFile == null ? null : new DataOutputStream(new BufferedOutputStream(new FileOutputStream(wayFile)));
cyclewayDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(relFile)));
if (resFile != null) {
restrictionsDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(resFile)));
}
// read the osm map into memory
long t0 = System.currentTimeMillis();
new OsmParser().readMap( mapFile, this, this, this );
new OsmParser().readMap(mapFile, this, this, this);
long t1 = System.currentTimeMillis();
System.out.println( "parsing time (ms) =" + (t1-t0) );
System.out.println("parsing time (ms) =" + (t1 - t0));
// close all files
closeTileOutStreams();
if ( wayDos != null )
{
if (wayDos != null) {
wayDos.close();
}
cyclewayDos.close();
if ( restrictionsDos != null )
{
if (restrictionsDos != null) {
restrictionsDos.close();
}
@ -113,177 +106,151 @@ public class OsmCutter extends MapCreatorBase
// System.out.println( "-------- node-statistics -------- " );
// _expctxNodeStat.dumpStatistics();
System.out.println( statsLine() );
System.out.println(statsLine());
}
private void checkStats()
{
if ( (++recordCnt % 100000) == 0 ) System.out.println( statsLine() );
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() )
{
_expctxNode.addLookupValue( e.getKey(), e.getValue(), lookupData );
for (Map.Entry<String, String> e : n.getTagsOrNull().entrySet()) {
_expctxNode.addLookupValue(e.getKey(), e.getValue(), lookupData);
// _expctxNodeStat.addLookupValue( key, value, null );
}
n.description = _expctxNode.encode(lookupData);
}
// write node to file
int tileIndex = getTileIndex( n.ilon, n.ilat );
if ( tileIndex >= 0 )
{
n.writeTo( getOutStreamForTile( tileIndex ) );
if ( wayCutter != null )
{
wayCutter.nextNode( n );
int tileIndex = getTileIndex(n.ilon, n.ilat);
if (tileIndex >= 0) {
n.writeTo(getOutStreamForTile(tileIndex));
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:" ) )
{
concrete = value.substring( "concrete:".length() );
if (value.startsWith("concrete:")) {
concrete = value.substring("concrete:".length());
}
}
}
if ( concrete != null )
{
map.put( "concrete", concrete );
if (concrete != null) {
map.put("concrete", concrete);
}
}
@Override
public void nextWay( WayData w ) throws Exception
{
public void nextWay(WayData w) throws Exception {
waysParsed++;
checkStats();
// encode tags
if ( w.getTagsOrNull() == null ) return;
if (w.getTagsOrNull() == null) return;
generatePseudoTags( w.getTagsOrNull() );
generatePseudoTags(w.getTagsOrNull());
int[] lookupData = _expctxWay.createNewLookupData();
for( String key : w.getTagsOrNull().keySet() )
{
String value = w.getTag( key );
_expctxWay.addLookupValue( key, value.replace( ' ', '_' ), lookupData );
for (String key : w.getTagsOrNull().keySet()) {
String value = w.getTag(key);
_expctxWay.addLookupValue(key, value.replace(' ', '_'), lookupData);
// _expctxWayStat.addLookupValue( key, value, null );
}
w.description = _expctxWay.encode(lookupData);
if ( w.description == null ) return;
if (w.description == null) return;
// filter according to profile
_expctxWay.evaluate( false, w.description );
_expctxWay.evaluate(false, w.description);
boolean ok = _expctxWay.getCostfactor() < 10000.;
_expctxWay.evaluate( true, w.description );
_expctxWay.evaluate(true, w.description);
ok |= _expctxWay.getCostfactor() < 10000.;
if ( !ok ) return;
if (!ok) return;
if ( wayDos != null )
{
w.writeTo( wayDos );
if (wayDos != null) {
w.writeTo(wayDos);
}
if ( wayCutter != null )
{
wayCutter.nextWay( w );
if (wayCutter != null) {
wayCutter.nextWay(w);
}
if ( nodeFilter != null )
{
nodeFilter.nextWay( w );
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" );
String route = r.getTag("route");
// filter out non-cycle relations
if ( route == null )
{
if (route == null) {
return;
}
String network = r.getTag( "network" );
if ( network == null ) network = "";
String state = r.getTag( "state" );
if ( state == null ) state = "";
writeId( cyclewayDos, r.rid );
cyclewayDos.writeUTF( route );
cyclewayDos.writeUTF( network );
cyclewayDos.writeUTF( state );
for ( int i=0; i<r.ways.size();i++ )
{
String network = r.getTag("network");
if (network == null) network = "";
String state = r.getTag("state");
if (state == null) state = "";
writeId(cyclewayDos, r.rid);
cyclewayDos.writeUTF(route);
cyclewayDos.writeUTF(network);
cyclewayDos.writeUTF(state);
for (int i = 0; i < r.ways.size(); i++) {
long wid = r.ways.get(i);
writeId( cyclewayDos, wid );
writeId(cyclewayDos, wid);
}
writeId( cyclewayDos, -1 );
writeId(cyclewayDos, -1);
}
@Override
public void nextRestriction( RelationData r, long fromWid, long toWid, long viaNid ) throws Exception
{
String type = r.getTag( "type" );
if ( type == null || !"restriction".equals( type ) )
{
public void nextRestriction(RelationData r, long fromWid, long toWid, long viaNid) throws Exception {
String type = r.getTag("type");
if (type == null || !"restriction".equals(type)) {
return;
}
short exceptions = 0;
String except = r.getTag( "except" );
if ( except != null )
{
exceptions |= toBit( "bicycle" , 0, except );
exceptions |= toBit( "motorcar" , 1, except );
exceptions |= toBit( "agricultural" , 2, except );
exceptions |= toBit( "forestry" , 2, except );
exceptions |= toBit( "psv" , 3, except );
exceptions |= toBit( "hgv" , 4, except );
String except = r.getTag("except");
if (except != null) {
exceptions |= toBit("bicycle", 0, except);
exceptions |= toBit("motorcar", 1, except);
exceptions |= toBit("agricultural", 2, except);
exceptions |= toBit("forestry", 2, except);
exceptions |= toBit("psv", 3, except);
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 );
String restriction = r.getTag(restrictionKey);
RestrictionData res = new RestrictionData();
res.restrictionKey = restrictionKey;
@ -293,38 +260,32 @@ public class OsmCutter extends MapCreatorBase
res.toWid = toWid;
res.viaNid = viaNid;
if ( restrictionsDos != null )
{
res.writeTo( restrictionsDos );
if (restrictionsDos != null) {
res.writeTo(restrictionsDos);
}
if ( restrictionCutter != null )
{
restrictionCutter.nextRestriction( res );
if (restrictionCutter != null) {
restrictionCutter.nextRestriction(res);
}
}
}
private static short toBit( String tag, int bitpos, String s )
{
return (short) ( s.indexOf( tag ) < 0 ? 0 : 1 << bitpos );
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 )
{
System.out.println( "warning: ignoring illegal pos: " + ilon + "," + ilat );
if (lon < 0 || lon > 7 || lat < 0 || lat > 5) {
System.out.println("warning: ignoring illegal pos: " + ilon + "," + ilat);
return -1;
}
return lon*6 + lat;
return lon * 6 + lat;
}
protected String getNameForTile( int tileIndex )
{
int lon = (tileIndex / 6 ) * 45 - 180;
int lat = (tileIndex % 6 ) * 30 - 90;
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;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".ntl";

View File

@ -9,55 +9,51 @@ 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 );
System.out.println("or : " + common + " <inputfile> " );
System.out.println("usage: bzip2 -dc <map> | " + common);
System.out.println("or : " + common + " <inputfile> ");
return;
}
doCut(
new File( args[0] )
, new File( args[1] )
, new File( args[2] )
, new File( args[3] )
, new File( args[4] )
, new File( args[5] )
, new File( args[6] )
, new File( args[7] )
, new File( args[8] )
, new File( args[9] )
, new File( args[10] )
, args.length > 11 ? new File( args[11] ) : null
new File(args[0])
, new File(args[1])
, new File(args[2])
, new File(args[3])
, new File(args[4])
, new File(args[5])
, new File(args[6])
, new File(args[7])
, new File(args[8])
, new File(args[9])
, new File(args[10])
, args.length > 11 ? new File(args[11]) : null
);
}
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();
// ... inject WayCutter
cutter.wayCutter = new WayCutter();
cutter.wayCutter.init( wayDir );
cutter.wayCutter.init(wayDir);
// ... inject RestrictionCutter
cutter.restrictionCutter = new RestrictionCutter();
cutter.restrictionCutter.init( new File( nodeDir.getParentFile(), "restrictions" ), cutter.wayCutter );
cutter.restrictionCutter.init(new File(nodeDir.getParentFile(), "restrictions"), cutter.wayCutter);
// ... inject NodeFilter
NodeFilter nodeFilter = new NodeFilter();
nodeFilter.init();
cutter.nodeFilter = nodeFilter;
cutter.process( lookupFile, nodeDir, null, relFile, null, profileAll, mapFile );
cutter.process(lookupFile, nodeDir, null, relFile, null, profileAll, mapFile);
cutter.wayCutter.finish();
cutter.restrictionCutter.finish();
cutter = null;
@ -67,20 +63,20 @@ public class OsmFastCutter extends MapCreatorBase
//... inject RelationMerger
wayCut5.relMerger = new RelationMerger();
wayCut5.relMerger.init( relFile, lookupFile, profileReport, profileCheck );
wayCut5.relMerger.init(relFile, lookupFile, profileReport, profileCheck);
// ... inject RestrictionCutter5
wayCut5.restrictionCutter5 = new RestrictionCutter5();
wayCut5.restrictionCutter5.init( new File( nodeDir.getParentFile(), "restrictions55" ), wayCut5 );
wayCut5.restrictionCutter5.init(new File(nodeDir.getParentFile(), "restrictions55"), wayCut5);
//... inject NodeFilter
wayCut5.nodeFilter = nodeFilter;
// ... inject NodeCutter
wayCut5.nodeCutter = new NodeCutter();
wayCut5.nodeCutter.init( node55Dir );
wayCut5.nodeCutter.init(node55Dir);
wayCut5.process( nodeDir, wayDir, way55Dir, borderFile );
wayCut5.process(nodeDir, wayDir, way55Dir, borderFile);
}
}

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,94 +23,67 @@ 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
{
throw new IllegalArgumentException( "internal error: setNext: unknown source" );
} else {
throw new IllegalArgumentException("internal error: setNext: unknown source");
}
}
/**
* 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
{
throw new IllegalArgumentException( "internal error: gextNext: unknown source" );
} else {
throw new IllegalArgumentException("internal error: gextNext: unknown source");
}
}
/**
* 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
{
throw new IllegalArgumentException( "internal error: getTarget: unknown source" );
} else {
throw new IllegalArgumentException("internal error: getTarget: unknown source");
}
}
/**
* 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
{
throw new IllegalArgumentException( "internal error: isReverse: unknown source" );
} 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,311 +39,261 @@ 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;
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;
source.addLink( this );
source.addLink(this);
return this;
}
OsmLinkP link = new OsmLinkP( source, this );
addLink( link );
source.addLink( link );
OsmLinkP link = new OsmLinkP(source, this);
addLink(link);
source.addLink(link);
return link;
}
// memory-squeezing-hack: OsmLinkP's "previous" also used as firstlink..
public void addLink( OsmLinkP link )
{
link.setNext( previous, this );
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 )
{
valid = writeNodeData2( (MicroCache2) mc, trafficMap );
}
else
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
if ( valid )
{
mc.finishNode( getIdFromPos() );
}
else
{
if (mc instanceof MicroCache2) {
valid = writeNodeData2((MicroCache2) mc, trafficMap);
} else
throw new IllegalArgumentException("unknown cache version: " + mc.getClass());
if (valid) {
mc.finishNode(getIdFromPos());
} else {
mc.discardNode();
}
}
public void checkDuplicateTargets()
{
HashMap<OsmNodeP,OsmLinkP> targets = new HashMap<OsmNodeP,OsmLinkP>();
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)
{
target = link.getTarget( origin );
if ( !target.isTransferNode() )
{
while (link != null) {
target = link.getTarget(origin);
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 ) )
{
if ( link.getTarget( target ) != origin )
for (link = target.getFirstLink(); link != null; link = link.getNext(target)) {
if (link.getTarget(target) != origin)
break;
}
origin = target;
}
if ( link == null ) continue;
OsmLinkP oldLink = targets.put( target, link0 );
if ( oldLink != null )
{
unifyLink( oldLink );
unifyLink( link0 );
if (link == null) continue;
OsmLinkP oldLink = targets.put(target, link0);
if (oldLink != null) {
unifyLink(oldLink);
unifyLink(link0);
}
}
}
private void unifyLink( OsmLinkP link )
{
if ( link.isReverse( this ) ) return;
OsmNodeP target = link.getTarget( this );
if ( target.isTransferNode() )
{
private void unifyLink(OsmLinkP link) {
if (link.isReverse(this)) return;
OsmNodeP target = link.getTarget(this);
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 )
{
mc.writeBoolean( true ); // restriction follows
mc.writeShort( r.exceptions );
mc.writeBoolean( r.isPositive() );
mc.writeInt( r.fromLon );
mc.writeInt( r.fromLat );
mc.writeInt( r.toLon );
mc.writeInt( r.toLat );
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());
mc.writeInt(r.fromLon);
mc.writeInt(r.fromLat);
mc.writeInt(r.toLon);
mc.writeInt(r.toLat);
}
r = r.next;
}
mc.writeBoolean( false ); // end restritions
mc.writeBoolean(false); // end restritions
mc.writeShort( getSElev() );
mc.writeVarBytes( getNodeDecsription() );
mc.writeShort(getSElev());
mc.writeVarBytes(getNodeDecsription());
// 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;
ArrayList<OsmNodeP> linkNodes = new ArrayList<OsmNodeP>();
linkNodes.add( this );
linkNodes.add(this);
// first pass just to see if that link is consistent
while (link != null)
{
target = link.getTarget( origin );
linkNodes.add( target );
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 ) )
{
if ( link.getTarget( target ) != origin )
for (link = target.getFirstLink(); link != null; link = link.getNext(target)) {
if (link.getTarget(target) != origin)
break;
}
if ( link != null && link.descriptionBitmap != link0.descriptionBitmap )
{
throw new IllegalArgumentException( "assertion failed: description change along transfer nodes" );
if (link != null && link.descriptionBitmap != link0.descriptionBitmap) {
throw new IllegalArgumentException("assertion failed: description change along transfer nodes");
}
origin = target;
}
if ( link == null )
if (link == null)
continue; // dead end
if ( target == this )
if (target == this)
continue; // self-ref
hasLinks = true;
// internal reverse links later
boolean isReverse = link0.isReverse( this );
if ( isReverse )
{
if ( mc.isInternal( target.ilon, target.ilat ) )
{
internalReverse.add( target );
boolean isReverse = link0.isReverse(this);
if (isReverse) {
if (mc.isInternal(target.ilon, target.ilat)) {
internalReverse.add(target);
continue;
}
}
// add traffic simulation, if present
byte[] description = link0.descriptionBitmap;
if ( trafficMap != null )
{
description = trafficMap.addTrafficClass( linkNodes, description );
if (trafficMap != null) {
description = trafficMap.addTrafficClass(linkNodes, description);
}
// write link data
int sizeoffset = mc.writeSizePlaceHolder();
mc.writeVarLengthSigned( target.ilon - ilon );
mc.writeVarLengthSigned( target.ilat - ilat );
mc.writeModeAndDesc( isReverse, description );
if ( !isReverse && linkNodes.size() > 2 ) // write geometry for forward links only
mc.writeVarLengthSigned(target.ilon - ilon);
mc.writeVarLengthSigned(target.ilat - ilat);
mc.writeModeAndDesc(isReverse, description);
if (!isReverse && linkNodes.size() > 2) // write geometry for forward links only
{
DPFilter.doDPFilter( linkNodes );
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 )
{
mc.writeVarLengthSigned( tranferNode.ilon - origin.ilon );
mc.writeVarLengthSigned( tranferNode.ilat - origin.ilat );
mc.writeVarLengthSigned( tranferNode.getSElev() - origin.getSElev() );
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());
origin = tranferNode;
}
}
}
mc.injectSize( sizeoffset );
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++ )
{
int id32 = mc.shrinkId( internalReverse.get( i ).getIdFromPos() );
if ( id32 > max32 )
{
for (int i = 0; i < internalReverse.size(); i++) {
int id32 = mc.shrinkId(internalReverse.get(i).getIdFromPos());
if (id32 > max32) {
max32 = id32;
nextIdx = i;
}
}
}
OsmNodeP target = internalReverse.remove( nextIdx );
OsmNodeP target = internalReverse.remove(nextIdx);
int sizeoffset = mc.writeSizePlaceHolder();
mc.writeVarLengthSigned( target.ilon - ilon );
mc.writeVarLengthSigned( target.ilat - ilat );
mc.writeModeAndDesc( true, null );
mc.injectSize( sizeoffset );
mc.writeVarLengthSigned(target.ilon - ilon);
mc.writeVarLengthSigned(target.ilat - ilat);
mc.writeModeAndDesc(true, null);
mc.injectSize(sizeoffset);
}
return hasLinks;
}
public String toString2()
{
return ( ilon - 180000000 ) + "_" + ( ilat - 90000000 ) + "_" + ( selev / 4 );
public String toString2() {
return (ilon - 180000000) + "_" + (ilat - 90000000) + "_" + (selev / 4);
}
public long getIdFromPos()
{
return ( (long) ilon ) << 32 | ilat;
public long getIdFromPos() {
return ((long) ilon) << 32 | ilat;
}
public boolean isBorderNode()
{
return ( bits & BORDER_BIT ) != 0;
public boolean isBorderNode() {
return (bits & BORDER_BIT) != 0;
}
public boolean hasTraffic()
{
return ( bits & TRAFFIC_BIT ) != 0;
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()
{
return ( bits & BORDER_BIT ) == 0 && ( bits & MULTI_WAY_BIT ) == 0 && _linkCnt() == 2;
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,225 +11,189 @@ import java.util.zip.GZIPInputStream;
*
* @author ab
*/
public class OsmParser extends MapCreatorBase
{
public class OsmParser extends MapCreatorBase {
private BufferedReader _br;
private NodeListener nListener;
private WayListener wListener;
private RelationListener rListener;
public void readMap( File mapFile,
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" ) )
{
_br = new BufferedReader(new InputStreamReader( new GZIPInputStream( new FileInputStream( mapFile ) ) ) );
}
else
{
_br = new BufferedReader(new InputStreamReader( new FileInputStream( mapFile ) ) );
} else {
if (mapFile.getName().endsWith(".gz")) {
_br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(mapFile))));
} else {
_br = new BufferedReader(new InputStreamReader(new FileInputStream(mapFile)));
}
}
for(;;)
{
for (; ; ) {
String line = _br.readLine();
if ( line == null ) break;
if (line == null) break;
if ( checkNode( line ) ) continue;
if ( checkWay( line ) ) continue;
if ( checkRelation( line ) ) continue;
if ( checkChangeset( line ) ) continue;
if (checkNode(line)) continue;
if (checkWay(line)) continue;
if (checkRelation(line)) continue;
if (checkChangeset(line)) continue;
}
if ( mapFile != null )
{
if (mapFile != null) {
_br.close();
}
}
private boolean checkNode( String line ) throws Exception
{
int idx0 = line.indexOf( "<node id=\"" );
if ( idx0 < 0 ) return false;
private boolean checkNode(String line) throws Exception {
int idx0 = line.indexOf("<node id=\"");
if (idx0 < 0) return false;
idx0 += 10;
int idx1 = line.indexOf( '"', idx0 );
int idx1 = line.indexOf('"', idx0);
long nodeId = Long.parseLong( line.substring( idx0, idx1 ) );
long nodeId = Long.parseLong(line.substring(idx0, idx1));
int idx2 = line.indexOf( " lat=\"" );
if ( idx2 < 0 ) return false;
int idx2 = line.indexOf(" lat=\"");
if (idx2 < 0) return false;
idx2 += 6;
int idx3 = line.indexOf( '"', idx2 );
double lat = Double.parseDouble( line.substring( idx2, idx3 ) );
int idx4 = line.indexOf( " lon=\"" );
if ( idx4 < 0 ) return false;
int idx3 = line.indexOf('"', idx2);
double lat = Double.parseDouble(line.substring(idx2, idx3));
int idx4 = line.indexOf(" lon=\"");
if (idx4 < 0) return false;
idx4 += 6;
int idx5 = line.indexOf( '"', idx4 );
double lon = Double.parseDouble( line.substring( idx4, idx5 ) );
int idx5 = line.indexOf('"', idx4);
double lon = Double.parseDouble(line.substring(idx4, idx5));
NodeData n = new NodeData( nodeId, lon, lat );
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;
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 )
{
int ri2 = l2.indexOf('"', i2);
String key = l2.substring(i2, ri2);
i2 = l2.indexOf(" v=\"", ri2);
if (i2 >= 0) {
i2 += 4;
int ri3 = l2.indexOf( '"', i2 );
String value = l2.substring( i2, ri3 );
int ri3 = l2.indexOf('"', i2);
String value = l2.substring(i2, ri3);
n.putTag( key, value );
n.putTag(key, value);
}
}
else if ( l2.indexOf( "</node>" ) >= 0 )
{ // end-tag
} else if (l2.indexOf("</node>") >= 0) { // end-tag
break;
}
}
}
nListener.nextNode( n );
nListener.nextNode(n);
return true;
}
private boolean checkWay( String line ) throws Exception
{
int idx0 = line.indexOf( "<way id=\"" );
if ( idx0 < 0 ) return false;
private boolean checkWay(String line) throws Exception {
int idx0 = line.indexOf("<way id=\"");
if (idx0 < 0) return false;
idx0 += 9;
int idx1 = line.indexOf( '"', idx0 );
long id = Long.parseLong( line.substring( idx0, idx1 ) );
int idx1 = line.indexOf('"', idx0);
long id = Long.parseLong(line.substring(idx0, idx1));
WayData w = new WayData( id );
WayData w = new WayData(id);
// read the nodes
for(;;)
{
for (; ; ) {
String l2 = _br.readLine();
if ( l2 == null ) return false;
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
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
i2 += 8;
int ri2 = l2.indexOf( '"', i2 );
String key = l2.substring( i2, ri2 );
i2 = l2.indexOf( " v=\"", ri2 );
if ( i2 >= 0 )
{
int ri2 = l2.indexOf('"', i2);
String key = l2.substring(i2, ri2);
i2 = l2.indexOf(" v=\"", ri2);
if (i2 >= 0) {
i2 += 4;
int ri3 = l2.indexOf( '"', i2 );
String value = l2.substring( i2, ri3 );
w.putTag( key, value );
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;
}
}
wListener.nextWay( w );
wListener.nextWay(w);
return true;
}
private boolean checkChangeset( String line ) throws Exception
{
int idx0 = line.indexOf( "<changeset id=\"" );
if ( idx0 < 0 ) return false;
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;
if (l2.indexOf("</changeset>") >= 0 || ++loopcheck > 10000) break;
}
}
return true;
}
private boolean checkRelation( String line ) throws Exception
{
int idx0 = line.indexOf( "<relation id=\"" );
if ( idx0 < 0 ) return false;
private boolean checkRelation(String line) throws Exception {
int idx0 = line.indexOf("<relation id=\"");
if (idx0 < 0) return false;
idx0 += 14;
int idx1 = line.indexOf( '"', idx0 );
long rid = Long.parseLong( line.substring( idx0, idx1 ) );
int idx1 = line.indexOf('"', idx0);
long rid = Long.parseLong(line.substring(idx0, idx1));
RelationData r = new RelationData( rid );
RelationData r = new RelationData(rid);
// read the nodes
for(;;)
{
for (; ; ) {
String l2 = _br.readLine();
if ( l2 == null ) return false;
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
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
i2 += 8;
int ri2 = l2.indexOf( '"', i2 );
String key = l2.substring( i2, ri2 );
i2 = l2.indexOf( " v=\"", ri2 );
if ( i2 >= 0 )
{
int ri2 = l2.indexOf('"', i2);
String key = l2.substring(i2, ri2);
i2 = l2.indexOf(" v=\"", ri2);
if (i2 >= 0) {
i2 += 4;
int ri3 = l2.indexOf( '"', i2 );
String value = l2.substring( i2, ri3 );
r.putTag( key, value );
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;
}
}
rListener.nextRelation( r );
rListener.nextRelation(r);
return true;
}

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" );
debug = Boolean.getBoolean("debugTrafficMap");
}
public static class OsmTrafficElement
{
public static class OsmTrafficElement {
public long node2;
public int traffic;
public OsmTrafficElement next;
@ -57,155 +54,129 @@ 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
{
load( file, minLon, minLat, maxLon, maxLat, includeMotorways );
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() )
{
oldTrafficClasses = new OsmTrafficMap( null );
oldTrafficFile = new File(file.getParentFile(), file.getName() + "_old");
if (oldTrafficFile.exists()) {
oldTrafficClasses = new OsmTrafficMap(null);
oldTrafficClasses.doNotAdd = true;
oldTrafficClasses.load( oldTrafficFile, minLon, minLat, maxLon, maxLat, false );
oldTrafficClasses.load(oldTrafficFile, minLon, minLat, maxLon, maxLat, false);
}
// check for old traffic data
newTrafficFile = new File( file.getParentFile(), file.getName() + "_new" );
newTrafficDos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( newTrafficFile ) ) );
newTrafficFile = new File(file.getParentFile(), file.getName() + "_new");
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();
newTrafficFile.renameTo( oldTrafficFile );
System.out.println( "TrafficMap: changes total=" + totalChanges + " supressed=" + supressedChanges );
newTrafficFile.renameTo(oldTrafficFile);
System.out.println("TrafficMap: changes total=" + totalChanges + " supressed=" + supressedChanges);
}
}
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;
this.maxLat = maxLat;
int trafficElements = 0;
DataInputStream is = new DataInputStream( new BufferedInputStream( new FileInputStream( file ) ) );
try
{
for(;;)
{
DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
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 );
map = new FrozenLongMap<OsmTrafficElement>(map);
System.out.println("read traffic-elements: " + trafficElements);
}
public boolean addElement( long n1, long n2, int traffic )
{
OsmTrafficElement e = getElement( n1, n2 );
if ( e == null )
{
public boolean addElement(long n1, long n2, int traffic) {
OsmTrafficElement e = getElement(n1, n2);
if (e == null) {
e = new OsmTrafficElement();
e.node2 = n2;
e.traffic = traffic;
OsmTrafficElement e0 = map.get( n1 );
if ( e0 != null )
{
while( e0.next != null )
{
OsmTrafficElement e0 = map.get(n1);
if (e0 != null) {
while (e0.next != null) {
e0 = e0.next;
}
e0.next = e;
}
else
{
map.fastPut( n1, e );
} else {
map.fastPut(n1, e);
}
return true;
}
if ( doNotAdd )
{
e.traffic = Math.max( e.traffic, traffic );
}
else
{
if (doNotAdd) {
e.traffic = Math.max(e.traffic, traffic);
} else {
e.traffic = e.traffic == -1 || traffic == -1 ? -1 : e.traffic + traffic;
}
return false;
}
private boolean isInsideBounds( long id )
{
int ilon = (int)(id >> 32);
int ilat = (int)(id & 0xffffffff);
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 );
OsmTrafficElement e = getElement(n1, n2);
return e == null ? 0 : e.traffic;
}
public int getTrafficClassForTraffic( int traffic )
{
if ( traffic < 0 ) return -1;
if ( traffic < 40000 ) return 0;
if ( traffic < 80000 ) return 2;
if ( traffic < 160000 ) return 3;
if ( traffic < 320000 ) return 4;
if ( traffic < 640000 ) return 5;
if ( traffic <1280000 ) return 6;
public int getTrafficClassForTraffic(int traffic) {
if (traffic < 0) return -1;
if (traffic < 40000) return 0;
if (traffic < 80000) return 2;
if (traffic < 160000) return 3;
if (traffic < 320000) return 4;
if (traffic < 640000) return 5;
if (traffic < 1280000) return 6;
return 7;
}
private int getTraffic( long n1, long n2 )
{
OsmTrafficElement e1 = getElement( n1, 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 );
OsmTrafficElement e2 = getElement(n2, n1);
int traffic2 = e2 == null ? 0 : e2.traffic;
return traffic1 == -1 || traffic2 == -1 ? -1 : traffic1 > traffic2 ? traffic1 : traffic2;
}
public void freeze()
{
public void freeze() {
}
private OsmTrafficElement getElement( long n1, long n2 )
{
OsmTrafficElement e = map.get( n1 );
while( e != null )
{
if ( e.node2 == n2 )
{
private OsmTrafficElement getElement(long n1, long n2) {
OsmTrafficElement e = map.get(n1);
while (e != null) {
if (e.node2 == n2) {
return e;
}
e = e.next;
@ -213,68 +184,59 @@ public class OsmTrafficMap
return null;
}
public OsmTrafficElement getElement( long n )
{
return map.get( 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() );
double dist = CheapRuler.distance( n1.ilon, n1.ilat, n2.ilon, n2.ilat );
OsmNodeP n2 = linkNodes.get(i + 1);
int traffic = getTraffic(n1.getIdFromPos(), n2.getIdFromPos());
double dist = CheapRuler.distance(n1.ilon, n1.ilat, n2.ilon, n2.ilat);
distance += dist;
sum += dist*traffic;
sum += dist * traffic;
}
if ( distance == 0. )
{
if (distance == 0.) {
return description;
}
int traffic = (int)(sum/distance + 0.5);
int traffic = (int) (sum / distance + 0.5);
long id0 = linkNodes.get(0).getIdFromPos();
long id1 = linkNodes.get(linkNodes.size()-1).getIdFromPos();
long id1 = linkNodes.get(linkNodes.size() - 1).getIdFromPos();
int trafficClass = getTrafficClassForTraffic( traffic );
int trafficClass = getTrafficClassForTraffic(traffic);
// delta suppression: keep old traffic classes within some buffer range
if ( oldTrafficClasses != null )
{
int oldTrafficClass = oldTrafficClasses.getTrafficClass( id0, id1 );
if ( oldTrafficClass != trafficClass )
{
if (oldTrafficClasses != null) {
int oldTrafficClass = oldTrafficClasses.getTrafficClass(id0, id1);
if (oldTrafficClass != trafficClass) {
totalChanges++;
boolean supressChange =
oldTrafficClass == getTrafficClassForTraffic( (int)(traffic*1.3) )
|| oldTrafficClass == getTrafficClassForTraffic( (int)(traffic*0.77) );
oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 1.3))
|| oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 0.77));
if ( debug )
{
System.out.println( "traffic class change " + oldTrafficClass + "->" + trafficClass + " supress=" + supressChange );
if (debug) {
System.out.println("traffic class change " + oldTrafficClass + "->" + trafficClass + " supress=" + supressChange);
}
if ( supressChange )
{
if (supressChange) {
trafficClass = oldTrafficClass;
supressedChanges++;
}
}
}
if ( trafficClass > 0 )
{
newTrafficDos.writeLong( id0 );
newTrafficDos.writeLong( id1 );
newTrafficDos.writeInt( trafficClass );
if (trafficClass > 0) {
newTrafficDos.writeLong(id0);
newTrafficDos.writeLong(id1);
newTrafficDos.writeInt(trafficClass);
expctxWay.decode( description );
expctxWay.addLookupValue( "estimated_traffic_class", trafficClass + 1 );
expctxWay.decode(description);
expctxWay.addLookupValue("estimated_traffic_class", trafficClass + 1);
return expctxWay.encode();
}
return description;

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,140 +34,116 @@ public class PosUnifier extends MapCreatorBase
private CompactLongSet borderNids;
public static void main( String[] args ) throws Exception
{
System.out.println( "*** PosUnifier: Unify position values and enhance elevation" );
if ( args.length != 5 )
{
System.out.println( "usage: java PosUnifier <node-tiles-in> <node-tiles-out> <bordernids-in> <bordernodes-out> <srtm-data-dir>" );
public static void main(String[] args) throws Exception {
System.out.println("*** PosUnifier: Unify position values and enhance elevation");
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] );
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 );
DataInputStream dis = createInStream(bordernidsinfile);
borderNids = new CompactLongSet();
try
{
for ( ;; )
{
long nid = readId( dis );
if ( !borderNids.contains( nid ) )
borderNids.fastAdd( nid );
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 );
borderNids = new FrozenLongSet(borderNids);
// process all files
borderNodesOut = createOutStream( bordernodesoutfile );
new NodeIterator( this, true ).processDir( nodeTilesIn, ".n5d" );
borderNodesOut = createOutStream(bordernodesoutfile);
new NodeIterator(this, true).processDir(nodeTilesIn, ".n5d");
borderNodesOut.close();
}
@Override
public void nodeFileStart( File nodefile ) throws Exception
{
public void nodeFileStart(File nodefile) throws Exception {
resetSrtm();
nodesOutStream = createOutStream( fileFromTemplate( nodefile, nodeTilesOut, "u5d" ) );
nodesOutStream = createOutStream(fileFromTemplate(nodefile, nodeTilesOut, "u5d"));
positionSets = new CompactLongSet[2500];
}
@Override
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 );
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 );
findUniquePos(n);
n.writeTo( nodesOutStream );
if ( borderNids.contains( n.nid ) )
{
n.writeTo( borderNodesOut );
n.writeTo(nodesOutStream);
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 )
{
int slot = ((lon%5000000)/100000)*50 + ((lat%5000000)/100000);
long id = ( (long) lon ) << 32 | 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 ) )
{
set.fastAdd( id );
if (!set.contains(id)) {
set.fastAdd(id);
return true;
}
return false;
}
private void findUniquePos( NodeData n )
{
if ( !checkAdd( n.ilon, n.ilat ) )
{
_findUniquePos( n );
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;
}
}
}
System.out.println( "*** WARNING: cannot unify position for: " + n.ilon + " " + n.ilat );
System.out.println("*** WARNING: cannot unify position for: " + n.ilon + " " + n.ilat);
}
/**
* 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
{
int srtmLonIdx = ( ilon + 5000000 ) / 5000000;
int srtmLatIdx = ( 654999999 - ilat ) / 5000000 - 100; // ugly negative rounding...
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;
@ -176,50 +151,40 @@ public class PosUnifier extends MapCreatorBase
String slonidx = "0" + srtmLonIdx;
String slatidx = "0" + srtmLatIdx;
String filename = "srtm_" + slonidx.substring( slonidx.length()-2 ) + "_" + slatidx.substring( slatidx.length()-2 );
String filename = "srtm_" + slonidx.substring(slonidx.length() - 2) + "_" + slatidx.substring(slatidx.length() - 2);
lastSrtmRaster = srtmmap.get( 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() )
{
System.out.println( "*** reading: " + f );
try
{
InputStream isc = new BufferedInputStream( new FileInputStream( f ) );
lastSrtmRaster = new RasterCoder().decodeRaster( isc );
lastSrtmRaster = srtmmap.get(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()) {
System.out.println("*** reading: " + f);
try {
InputStream isc = new BufferedInputStream(new FileInputStream(f));
lastSrtmRaster = new RasterCoder().decodeRaster(isc);
isc.close();
} catch (Exception e) {
System.out.println("**** ERROR reading " + f + " ****");
}
catch (Exception e)
{
System.out.println( "**** ERROR reading " + f + " ****" );
}
srtmmap.put( filename, lastSrtmRaster );
srtmmap.put(filename, lastSrtmRaster);
return lastSrtmRaster;
}
f = new File( new File( srtmdir ), filename + ".zip" );
System.out.println( "reading: " + f + " ilon=" + ilon + " ilat=" + ilat );
if ( f.exists() )
{
try
{
lastSrtmRaster = new SrtmData( f ).getRaster();
}
catch (Exception e)
{
System.out.println( "**** ERROR reading " + f + " ****" );
f = new File(new File(srtmdir), filename + ".zip");
System.out.println("reading: " + f + " ilon=" + ilon + " ilat=" + ilat);
if (f.exists()) {
try {
lastSrtmRaster = new SrtmData(f).getRaster();
} catch (Exception e) {
System.out.println("**** ERROR reading " + f + " ****");
}
}
srtmmap.put( filename, lastSrtmRaster );
srtmmap.put(filename, lastSrtmRaster);
}
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();
@ -50,74 +48,61 @@ public class RasterCoder
raster.usingWeights = raster.ncols > 6001;
long t1 = System.currentTimeMillis();
System.out.println("finished decoding in " + (t1 - t0) + " ms ncols=" + raster.ncols + " nrows=" + raster.nrows );
System.out.println("finished decoding in " + (t1 - t0) + " ms ncols=" + raster.ncols + " nrows=" + raster.nrows);
return raster;
}
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;
}
// remap nodata
int code = val == Short.MIN_VALUE ? -1 : ( val < 0 ? val-1 : val );
mco.writeMixed( code );
int code = val == Short.MIN_VALUE ? -1 : (val < 0 ? val - 1 : val);
mco.writeMixed(code);
}
}
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 )
{
int v30 = code == -1 ? Short.MIN_VALUE : (code < 0 ? code + 1 : code);
if (raster.usingWeights && v30 > -32766) {
v30 *= 2;
}
pixels[row * ncols + col] = (short) ( v30 );
pixels[row * ncols + col] = (short) (v30);
}
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];
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 )
{
v30 = (short)((l+r)/2);
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 );
ways = new LongList(16);
}
public RelationData( long id, LongList ways )
{
public RelationData(long id, LongList ways) {
rid = id;
this.ways = ways;
}

View File

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

View File

@ -13,14 +13,13 @@ import btools.util.FrozenLongSet;
/**
* RelationMerger does 1 step in map processing:
*
* <p>
* - enrich ways with relation information
*
* @author ab
*/
public class RelationMerger extends MapCreatorBase
{
private HashMap<String,CompactLongSet> routesets;
public class RelationMerger extends MapCreatorBase {
private HashMap<String, CompactLongSet> routesets;
private CompactLongSet routesetall;
private BExpressionContextWay expctxReport;
private BExpressionContextWay expctxCheck;
@ -28,137 +27,117 @@ public class RelationMerger extends MapCreatorBase
private DataOutputStream wayOutStream;
public static void main(String[] args) throws Exception
{
System.out.println("*** RelationMerger: merge relations into ways" );
if (args.length != 6)
{
System.out.println("usage: java RelationMerger <way-file-in> <way-file-out> <relation-file> <lookup-file> <report-profile> <check-profile>" );
public static void main(String[] args) throws Exception {
System.out.println("*** RelationMerger: merge relations into ways");
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;
}
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] ) );
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 );
metaReport.readMetaData( lookupFile );
expctxReport = new BExpressionContextWay(metaReport);
metaReport.readMetaData(lookupFile);
BExpressionMetaData metaCheck = new BExpressionMetaData();
expctxCheck = new BExpressionContextWay( metaCheck );
metaCheck.readMetaData( lookupFile );
expctxCheck = new BExpressionContextWay(metaCheck);
metaCheck.readMetaData(lookupFile);
expctxReport.parseFile( reportProfile, "global" );
expctxCheck.parseFile( checkProfile, "global" );
expctxReport.parseFile(reportProfile, "global");
expctxCheck.parseFile(checkProfile, "global");
// expctxStat = new BExpressionContext("way");
// *** read the relation file into sets for each processed tag
routesets = new HashMap<String,CompactLongSet>();
routesets = new HashMap<String, CompactLongSet>();
routesetall = new CompactLongSet();
DataInputStream dis = createInStream( relationFileIn );
try
{
for(;;)
{
long rid = readId( dis );
DataInputStream dis = createInStream(relationFileIn);
try {
for (; ; ) {
long rid = readId(dis);
String route = dis.readUTF();
String network = dis.readUTF();
String state = dis.readUTF();
int value = "proposed".equals( state ) ? 3 : 2; // 2=yes, 3=proposed
int value = "proposed".equals(state) ? 3 : 2; // 2=yes, 3=proposed
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 )
{
routeset = routesets.get(key);
if (routeset == null) {
routeset = new CompactLongSet();
routesets.put( key, routeset );
routesets.put(key, routeset);
}
}
for(;;)
{
long wid = readId( dis );
if ( wid == -1 ) break;
for (; ; ) {
long wid = readId(dis);
if (wid == -1) break;
// expctxStat.addLookupValue( tagname, "yes", null );
if ( routeset != null && !routeset.contains( wid ) )
{
routeset.add( wid );
routesetall.add( 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() )
{
CompactLongSet routeset = new FrozenLongSet( routesets.get( key ) );
routesets.put( key, routeset );
System.out.println( "marked " + routeset.size() + " routes for key: " + key );
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
{
init( relationFileIn, lookupFile, reportProfile, checkProfile );
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
wayOutStream = createOutStream( wayFileOut );
new WayIterator( this, true ).processFile( wayFileIn );
wayOutStream = createOutStream(wayFileOut);
new WayIterator(this, true).processFile(wayFileIn);
wayOutStream.close();
// System.out.println( "-------- route-statistics -------- " );
// expctxStat.dumpStatistics();
}
@Override
public void nextWay( WayData data ) throws Exception
{
// propagate the route-bits
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 )
{
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 )
{
expctxReport.decode( data.description );
for( String key : routesets.keySet() )
{
CompactLongSet routeset = routesets.get( key );
if ( routeset.contains( data.wid ) )
{
int sepIdx = key.lastIndexOf( '_' );
String tagname = key.substring( 0, sepIdx );
int val = Integer.valueOf( key.substring( sepIdx+1 ) );
expctxReport.addSmallestLookupValue( tagname, val );
@Override
public void nextWay(WayData data) throws Exception {
// propagate the route-bits
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) {
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) {
expctxReport.decode(data.description);
for (String key : routesets.keySet()) {
CompactLongSet routeset = routesets.get(key);
if (routeset.contains(data.wid)) {
int sepIdx = key.lastIndexOf('_');
String tagname = key.substring(0, sepIdx);
int val = Integer.valueOf(key.substring(sepIdx + 1));
expctxReport.addSmallestLookupValue(tagname, val);
}
}
data.description = expctxReport.encode();
}
}
if ( wayOutStream != null )
{
data.writeTo( wayOutStream );
if (wayOutStream != null) {
data.writeTo(wayOutStream);
}
}

View File

@ -10,63 +10,52 @@ 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)
{
System.out.println("usage: java WayCutter <relation-file>" );
if (args.length != 1) {
System.out.println("usage: java WayCutter <relation-file>");
return;
}
new RelationStatistics().process( new File( args[0] ) );
new RelationStatistics().process(new File(args[0]));
}
public void process( File relationFileIn ) throws Exception
{
HashMap<String,long[]> relstats = new HashMap<String,long[]>();
public void process(File relationFileIn) throws Exception {
HashMap<String, long[]> relstats = new HashMap<String, long[]>();
DataInputStream dis = createInStream( relationFileIn );
try
{
for(;;)
{
long rid = readId( dis );
DataInputStream dis = createInStream(relationFileIn);
try {
for (; ; ) {
long rid = readId(dis);
String network = dis.readUTF();
int waycount = 0;
for(;;)
{
long wid = readId( dis );
if ( wid == -1 ) break;
for (; ; ) {
long wid = readId(dis);
if (wid == -1) break;
waycount++;
}
long[] stat = relstats.get( network );
if ( stat == null )
{
long[] stat = relstats.get(network);
if (stat == null) {
stat = new long[2];
relstats.put( network, stat );
relstats.put(network, stat);
}
stat[0]++;
stat[1] += waycount;
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
dis.close();
}
for( String network : relstats.keySet() )
{
long[] stat = relstats.get( network );
System.out.println( "network: " + network + " has " + stat[0] + " relations with " + stat[1] + " ways" );
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,41 +4,35 @@ 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
{
int tileIndex = wayCutter.getTileIndexForNid( data.viaNid );
if ( tileIndex != -1 )
{
data.writeTo( getOutStreamForTile( tileIndex ) );
public void nextRestriction(RestrictionData data) throws Exception {
int tileIndex = wayCutter.getTileIndexForNid(data.viaNid);
if (tileIndex != -1) {
data.writeTo(getOutStreamForTile(tileIndex));
}
}
protected String getNameForTile( int tileIndex )
{
String name = wayCutter.getNameForTile( tileIndex );
return name.substring( 0, name.length()-3 ) + "rtl";
protected String getNameForTile(int tileIndex) {
String name = wayCutter.getNameForTile(tileIndex);
return name.substring(0, name.length() - 3) + "rtl";
}
}

View File

@ -4,40 +4,34 @@ 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
{
int tileIndex = wayCutter5.getTileIndexForNid( data.viaNid );
if ( tileIndex != -1 )
{
data.writeTo( getOutStreamForTile( tileIndex ) );
public void nextRestriction(RestrictionData data) throws Exception {
int tileIndex = wayCutter5.getTileIndexForNid(data.viaNid);
if (tileIndex != -1) {
data.writeTo(getOutStreamForTile(tileIndex));
}
}
protected String getNameForTile( int tileIndex )
{
String name = wayCutter5.getNameForTile( tileIndex );
return name.substring( 0, name.length()-3 ) + "rt5";
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;
@ -36,119 +35,93 @@ public class RestrictionData extends MapCreatorBase
public boolean badWayMatch;
private static HashMap<String,String> names = new HashMap<>();
private static HashMap<String, String> names = new HashMap<>();
private static TreeSet<Long> badTRs = new TreeSet<>();
public RestrictionData()
{
public RestrictionData() {
}
public boolean isPositive()
{
return restriction.startsWith( "only_" );
public boolean isPositive() {
return restriction.startsWith("only_");
}
public boolean isValid()
{
boolean valid = fromLon != 0 && toLon != 0 && ( restriction.startsWith( "only_" ) || restriction.startsWith( "no_" ) );
if ( (!valid) || badWayMatch || !(checkGeometry()) )
{
synchronized( badTRs )
{
badTRs.add( ( (long) viaLon ) << 32 | viaLat );
public boolean isValid() {
boolean valid = fromLon != 0 && toLon != 0 && (restriction.startsWith("only_") || restriction.startsWith("no_"));
if ((!valid) || badWayMatch || !(checkGeometry())) {
synchronized (badTRs) {
badTRs.add(((long) viaLon) << 32 | viaLat);
}
}
return valid && "restriction".equals( restrictionKey );
return valid && "restriction".equals(restrictionKey);
}
private boolean checkGeometry()
{
double a = (new CheapAngleMeter()).calcAngle( fromLon, fromLat, viaLon, viaLat, toLon, toLat );
private boolean checkGeometry() {
double a = (new CheapAngleMeter()).calcAngle(fromLon, fromLat, viaLon, viaLat, toLon, toLat);
String t;
if ( restriction.startsWith( "only_" ) )
{
t = restriction.substring( "only_".length() );
}
else if ( restriction.startsWith( "no_" ) )
{
t = restriction.substring( "no_".length() );
}
else throw new RuntimeException( "ups" );
if (restriction.startsWith("only_")) {
t = restriction.substring("only_".length());
} else if (restriction.startsWith("no_")) {
t = restriction.substring("no_".length());
} else throw new RuntimeException("ups");
if ( restrictionKey.endsWith( ":conditional" ) )
{
int idx = t.indexOf( '@' );
if ( idx >= 0 )
{
t = t.substring(0, idx ).trim();
if (restrictionKey.endsWith(":conditional")) {
int idx = t.indexOf('@');
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 ) )
{
return a < - 95. || a > 95.;
if ("u_turn".equals(t)) {
return a < -95. || a > 95.;
}
return "entry".equals( t ) || "exit".equals( t );
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 )
{
names.put( name, name );
if (n == null) {
names.put(name, name);
n = name;
}
return n;
}
}
public static void dumpBadTRs()
{
try( BufferedWriter bw = new BufferedWriter( new FileWriter( "badtrs.txt" ) ) )
{
for( Long id : badTRs )
{
bw.write( "" + id + " 26\n" );
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 )
{
throw new RuntimeException( ioe );
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
public RestrictionData( DataInputStream di ) throws Exception
{
restrictionKey = unifyName( di.readUTF() );
restriction = unifyName( di.readUTF() );
public RestrictionData(DataInputStream di) throws Exception {
restrictionKey = unifyName(di.readUTF());
restriction = unifyName(di.readUTF());
exceptions = di.readShort();
fromWid = readId( di );
toWid = readId( di );
viaNid = readId( di );
fromWid = readId(di);
toWid = readId(di);
viaNid = readId(di);
}
public void writeTo( DataOutputStream dos ) throws Exception
{
dos.writeUTF( restrictionKey );
dos.writeUTF( restriction );
dos.writeShort( exceptions );
writeId( dos, fromWid );
writeId( dos, toWid );
writeId( dos, viaNid );
public void writeTo(DataOutputStream dos) throws Exception {
dos.writeUTF(restrictionKey);
dos.writeUTF(restriction);
dos.writeShort(exceptions);
writeId(dos, fromWid);
writeId(dos, toWid);
writeId(dos, viaNid);
}
}

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,104 +23,82 @@ 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 ( ;; )
{
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
try {
for (; ; ) {
ZipEntry ze = zis.getNextEntry();
if ( ze.getName().endsWith( ".asc" ) )
{
readFromStream( zis );
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 )
{
StringTokenizer tk = new StringTokenizer( s, " " );
private String secondToken(String s) {
StringTokenizer tk = new StringTokenizer(s, " ");
tk.nextToken();
return tk.nextToken();
}
public void readFromStream( InputStream is ) throws Exception
{
BufferedReader br = new BufferedReader( new InputStreamReader( is ) );
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 ) );
else if ( linenr == 2 )
raster.nrows = Integer.parseInt( secondToken( line ) );
else if ( linenr == 3 )
raster.xllcorner = Double.parseDouble( secondToken( line ) );
else if ( linenr == 4 )
raster.yllcorner = Double.parseDouble( secondToken( line ) );
else if ( linenr == 5 )
raster.cellsize = Double.parseDouble( secondToken( line ) );
else if ( linenr == 6 )
{
if (linenr == 1)
raster.ncols = Integer.parseInt(secondToken(line));
else if (linenr == 2)
raster.nrows = Integer.parseInt(secondToken(line));
else if (linenr == 3)
raster.xllcorner = Double.parseDouble(secondToken(line));
else if (linenr == 4)
raster.yllcorner = Double.parseDouble(secondToken(line));
else if (linenr == 5)
raster.cellsize = Double.parseDouble(secondToken(line));
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 )
if (c < 0)
break;
if ( c == ' ' )
{
if ( negative )
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' )
{
n = 10 * n + ( c - '0' );
}
else if ( c == '-' )
{
} else if (c >= '0' && c <= '9') {
n = 10 * n + (c - '0');
} else if (c == '-') {
negative = true;
}
}
@ -130,63 +108,56 @@ 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" ) )
{
File[] files = new File(fromDir).listFiles();
for (File f : files) {
if (!f.getName().endsWith(".zip")) {
continue;
}
System.out.println( "*** reading: " + f );
System.out.println("*** reading: " + f);
long t0 = System.currentTimeMillis();
SrtmRaster raster = new SrtmData( f ).getRaster();
SrtmRaster raster = new SrtmData(f).getRaster();
long t1 = System.currentTimeMillis();
String name = f.getName();
long zipTime = t1-t0;
long zipTime = t1 - t0;
File fbef = new File( new File( toDir ), name.substring( 0, name.length()-3 ) + "bef" );
System.out.println( "recoding: " + f + " to " + fbef );
OutputStream osbef = new BufferedOutputStream( new FileOutputStream( fbef ) );
new RasterCoder().encodeRaster( raster, osbef );
File fbef = new File(new File(toDir), name.substring(0, name.length() - 3) + "bef");
System.out.println("recoding: " + f + " to " + fbef);
OutputStream osbef = new BufferedOutputStream(new FileOutputStream(fbef));
new RasterCoder().encodeRaster(raster, osbef);
osbef.close();
System.out.println( "*** re-reading: " + fbef );
System.out.println("*** re-reading: " + fbef);
long t2 = System.currentTimeMillis();
InputStream isc = new BufferedInputStream( new FileInputStream( fbef ) );
SrtmRaster raster2 = new RasterCoder().decodeRaster( isc );
InputStream isc = new BufferedInputStream(new FileInputStream(fbef));
SrtmRaster raster2 = new RasterCoder().decodeRaster(isc);
isc.close();
long t3 = System.currentTimeMillis();
long befTime = t3-t2;
long befTime = t3 - t2;
System.out.println( "*** zip-time: " + zipTime + "*** bef-time: " + befTime );
System.out.println("*** zip-time: " + zipTime + "*** bef-time: " + befTime);
String s1 = raster.toString();
String s2 = raster2.toString();
if ( !s1.equals( s2 ) )
{
throw new IllegalArgumentException( "missmatch: " + s1 + "<--->" + 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] )
{
throw new IllegalArgumentException( "missmatch: at " + c + "," + r + ": " + 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,99 +21,93 @@ 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 )
{
return getElevationFromShiftWeights( lon, lat );
if (usingWeights) {
return getElevationFromShiftWeights(lon, lat);
}
// no weights calculated, use 2d linear interpolation
double dcol = (lon - xllcorner)/cellsize -0.5;
double drow = (lat - yllcorner)/cellsize -0.5;
int row = (int)drow;
int col = (int)dcol;
if ( col < 0 ) col = 0;
if ( col >= ncols-1 ) col = ncols - 2;
if ( row < 0 ) row = 0;
if ( row >= nrows-1 ) row = nrows - 2;
double wrow = drow-row;
double wcol = dcol-col;
double dcol = (lon - xllcorner) / cellsize - 0.5;
double drow = (lat - yllcorner) / cellsize - 0.5;
int row = (int) drow;
int col = (int) dcol;
if (col < 0) col = 0;
if (col >= ncols - 1) col = ncols - 2;
if (row < 0) row = 0;
if (row >= nrows - 1) row = nrows - 2;
double wrow = drow - row;
double wcol = dcol - col;
missingData = false;
// System.out.println( "wrow=" + wrow + " wcol=" + wcol + " row=" + row + " col=" + col );
double eval = (1.-wrow)*(1.-wcol)*get(row ,col )
+ ( wrow)*(1.-wcol)*get(row+1,col )
+ (1.-wrow)*( wcol)*get(row ,col+1)
+ ( wrow)*( wcol)*get(row+1,col+1);
double eval = (1. - wrow) * (1. - wcol) * get(row, col)
+ (wrow) * (1. - wcol) * get(row + 1, col)
+ (1. - wrow) * (wcol) * get(row, col + 1)
+ (wrow) * (wcol) * get(row + 1, col + 1);
// System.out.println( "eval=" + eval );
return missingData ? Short.MIN_VALUE : (short)(eval*4);
return missingData ? Short.MIN_VALUE : (short) (eval * 4);
}
private short get( int r, int c )
{
short e = eval_array[ (nrows-1-r)*ncols + c ];
if ( e == Short.MIN_VALUE ) missingData = true;
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;
double alat = lat < 0. ? -lat : lat;
alat /= 5.;
int latIdx = (int)alat;
int latIdx = (int) alat;
double wlat = alat - latIdx;
double dcol = (lon - xllcorner)/cellsize;
double drow = (lat - yllcorner)/cellsize;
int row = (int)drow;
int col = (int)dcol;
double dcol = (lon - xllcorner) / cellsize;
double drow = (lat - yllcorner) / cellsize;
int row = (int) drow;
int col = (int) dcol;
double dgx = (dcol-col)*gridSteps;
double dgy = (drow-row)*gridSteps;
double dgx = (dcol - col) * gridSteps;
double dgy = (drow - row) * gridSteps;
// System.out.println( "wrow=" + wrow + " wcol=" + wcol + " row=" + row + " col=" + col );
int gx = (int)(dgx);
int gy = (int)(dgy);
int gx = (int) (dgx);
int gy = (int) (dgy);
double wx = dgx-gx;
double wy = dgy-gy;
double wx = dgx - gx;
double wy = dgy - gy;
double w00 = (1.-wx)*(1.-wy);
double w01 = (1.-wx)*( wy);
double w10 = ( wx)*(1.-wy);
double w11 = ( wx)*( wy);
double w00 = (1. - wx) * (1. - wy);
double w01 = (1. - wx) * (wy);
double w10 = (wx) * (1. - wy);
double w11 = (wx) * (wy);
Weights[][] w0 = getWeights( latIdx );
Weights[][] w1 = getWeights( latIdx+1 );
Weights[][] w0 = getWeights(latIdx);
Weights[][] w1 = getWeights(latIdx + 1);
missingData = false;
double m0 = w00*getElevation( w0[gx ][gy ], row, col )
+ w01*getElevation( w0[gx ][gy+1], row, col )
+ w10*getElevation( w0[gx+1][gy ], row, col )
+ w11*getElevation( w0[gx+1][gy+1], row, col );
double m1 = w00*getElevation( w1[gx ][gy ], row, col )
+ w01*getElevation( w1[gx ][gy+1], row, col )
+ w10*getElevation( w1[gx+1][gy ], row, col )
+ w11*getElevation( w1[gx+1][gy+1], row, col );
double m0 = w00 * getElevation(w0[gx][gy], row, col)
+ w01 * getElevation(w0[gx][gy + 1], row, col)
+ w10 * getElevation(w0[gx + 1][gy], row, col)
+ w11 * getElevation(w0[gx + 1][gy + 1], row, col);
double m1 = w00 * getElevation(w1[gx][gy], row, col)
+ w01 * getElevation(w1[gx][gy + 1], row, col)
+ w10 * getElevation(w1[gx + 1][gy], row, col)
+ w11 * getElevation(w1[gx + 1][gy + 1], row, col);
if ( missingData ) return Short.MIN_VALUE;
double m = (1.-wlat) * m0 + wlat * m1;
return (short)(m * 2);
if (missingData) return Short.MIN_VALUE;
double m = (1. - wlat) * m0 + wlat * m1;
return (short) (m * 2);
}
private ReducedMedianFilter rmf = new ReducedMedianFilter( 256 );
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,64 +119,53 @@ public class SrtmRaster
rmf.reset();
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 );
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);
}
}
return missingData ? 0. : rmf.calcEdgeReducedMedian( filterCenterFraction );
return missingData ? 0. : rmf.calcEdgeReducedMedian(filterCenterFraction);
}
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];
weights = new double[nx * ny];
}
void inc( int ix, int iy )
{
weights[ iy*nx + ix ] += 1.;
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++ )
{
weights[ iy*nx + ix ] /= total;
if ( sb != null )
{
int iweight = (int)(1000*weights[ iy*nx + ix ] + 0.5 );
for (int ix = 0; ix < nx; ix++) {
weights[iy * nx + ix] /= total;
if (sb != null) {
int iweight = (int) (1000 * weights[iy * nx + ix] + 0.5);
String sval = " " + iweight;
sb.append( sval.substring( sval.length() - 4 ) );
sb.append(sval.substring(sval.length() - 4));
}
}
if ( sb != null )
{
System.out.println( sb );
if (sb != null) {
System.out.println(sb);
System.out.println();
}
}
}
double getWeight( int ix, int iy )
{
return weights[ iy*nx + ix ];
double getWeight(int ix, int iy) {
return weights[iy * nx + ix];
}
}
@ -193,19 +175,16 @@ public class SrtmRaster
private static double filterCenterFraction = 0.2;
private static double filterDiscRadius = 4.999; // in pixels
static
{
String sRadius = System.getProperty( "filterDiscRadius" );
if ( sRadius != null && sRadius.length() > 0 )
{
filterDiscRadius = Integer.parseInt( sRadius );
System.out.println( "using filterDiscRadius = " + filterDiscRadius );
static {
String sRadius = System.getProperty("filterDiscRadius");
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 )
{
filterCenterFraction = Integer.parseInt( sFraction ) / 100.;
System.out.println( "using filterCenterFraction = " + filterCenterFraction );
String sFraction = System.getProperty("filterCenterFraction");
if (sFraction != null && sFraction.length() > 0) {
filterCenterFraction = Integer.parseInt(sFraction) / 100.;
System.out.println("using filterCenterFraction = " + filterCenterFraction);
}
}
@ -213,82 +192,73 @@ 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 )
{
res = calcWeights( idx );
if (res == null) {
res = calcWeights(idx);
allShiftWeights[idx] = res;
}
return res;
}
private static Weights[][] calcWeights( int latIndex )
{
double coslat = Math.cos( latIndex * 5. / 57.3 );
private static Weights[][] calcWeights(int latIndex) {
double coslat = Math.cos(latIndex * 5. / 57.3);
// radius in pixel units
double ry = filterDiscRadius;
double rx = ry / coslat;
// gridsize is 2*radius + 1 cell
int nx = ((int)rx) *2 + 3;
int ny = ((int)ry) *2 + 3;
int nx = ((int) rx) * 2 + 3;
int ny = ((int) ry) * 2 + 3;
System.out.println( "nx="+ nx + " ny=" + ny );
System.out.println("nx=" + nx + " ny=" + ny);
int mx = nx / 2; // mean pixels
int my = ny / 2;
// create a matrix for the relative intergrid-position
Weights[][] shiftWeights = new Weights[gridSteps+1][];
Weights[][] shiftWeights = new Weights[gridSteps + 1][];
// loop the intergrid-position
for( int gx=0; gx<=gridSteps; gx++ )
{
shiftWeights[gx] = new Weights[gridSteps+1];
double x0 = mx + ( (double)gx ) / gridSteps;
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++ )
{
double y0 = my + ( (double)gy ) / gridSteps;
for (int gy = 0; gy <= gridSteps; gy++) {
double y0 = my + ((double) gy) / gridSteps;
// create the weight-matrix
Weights weights = new Weights( nx, ny );
Weights weights = new Weights(nx, ny);
shiftWeights[gx][gy] = weights;
double sampleStep = 0.001;
for( double x = -1. + sampleStep/2.; x < 1.; x += sampleStep )
{
double mx2 = 1. - x*x;
for (double x = -1. + sampleStep / 2.; x < 1.; x += sampleStep) {
double mx2 = 1. - x * x;
int x_idx = (int)(x0 + x*rx);
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
int y_idx = (int)(y0 + y*ry);
weights.inc( x_idx, y_idx );
int y_idx = (int) (y0 + y * ry);
weights.inc(x_idx, y_idx);
}
}
weights.normalize( true );
weights.normalize(true);
}
}
return shiftWeights;
}
@Override
public String toString()
{
public String toString() {
return ncols + "," + nrows + "," + halfcol + "," + xllcorner + "," + yllcorner + "," + cellsize + "," + noDataValue + "," + usingWeights;
}
}

View File

@ -7,103 +7,89 @@ 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)
{
System.out.println("usage: java WayCutter <node-tiles-in> <way-file-in> <way-tiles-out>" );
if (args.length != 3) {
System.out.println("usage: java WayCutter <node-tiles-in> <way-file-in> <way-tiles-out>");
return;
}
new WayCutter().process( new File( args[0] ), new File( args[1] ), new File( args[2] ) );
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
{
init( wayTilesOut );
public void process(File nodeTilesIn, File wayFileIn, File wayTilesOut) throws Exception {
init(wayTilesOut);
new NodeIterator( this, false ).processDir( nodeTilesIn, ".tlf" );
new NodeIterator(this, false).processDir(nodeTilesIn, ".tlf");
// *** finally process the way-file, cutting into pieces
new WayIterator( this, true ).processFile( wayFileIn );
new WayIterator(this, true).processFile(wayFileIn);
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();
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
{
tileIndexMap.put( n.nid, getTileIndex( n.ilon, n.ilat ) );
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++ )
{
int tileIndex = tileIndexMap.getInt( data.nodes.get(i) );
if ( tileIndex != -1 )
{
waytileset |= ( 1L << tileIndex );
for (int i = 0; i < nnodes; i++) {
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
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 ) );
data.writeTo(getOutStreamForTile(tileIndex));
}
}
public int getTileIndexForNid( long nid )
{
return tileIndexMap.getInt( 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 );
return lon*6 + lat;
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 )
{
int lon = (tileIndex / 6 ) * 45 - 180;
int lat = (tileIndex % 6 ) * 30 - 90;
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;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".wtl";

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,180 +30,151 @@ 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)
{
System.out.println("usage: java WayCutter5 <node-tiles-in> <way-tiles-in> <way-tiles-out> <border-nids-out>" );
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] ) );
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;
borderNidsOutStream = createOutStream( borderNidsOut );
borderNidsOutStream = createOutStream(borderNidsOut);
new WayIterator( this, true ).processDir( wayTilesIn, ".wtl" );
new WayIterator(this, true).processDir(wayTilesIn, ".wtl");
borderNidsOutStream.close();
}
@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";
File nodefile = new File( nodeTilesIn, nodefilename );
String nodefilename = name.substring(0, name.length() - 3) + "ntl";
File nodefile = new File(nodeTilesIn, nodefilename);
tileIndexMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap() : new TinyDenseLongMap();
tileIndexMap = Boolean.getBoolean("useDenseMaps") ? new DenseLongMap() : new TinyDenseLongMap();
lonoffset = -1;
latoffset = -1;
if ( nodeCutter != null )
{
nodeCutter.nodeFileStart( null );
if (nodeCutter != null) {
nodeCutter.nodeFileStart(null);
}
new NodeIterator( this, nodeCutter != null ).processFile( nodefile );
new NodeIterator(this, nodeCutter != null).processFile(nodefile);
if ( restrictionCutter5 != null )
{
String resfilename = name.substring( 0, name.length()-3 ) + "rtl";
File resfile = new File( "restrictions", resfilename );
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 ) ) );
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(resfile)));
int ntr = 0;
try
{
for(;;)
{
RestrictionData res = new RestrictionData( di );
restrictionCutter5.nextRestriction( res );
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" );
System.out.println("read " + ntr + " turn-restrictions");
}
}
return true;
}
@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 )
{
nodeCutter.nextNode( n );
if (nodeCutter != null) {
nodeCutter.nextNode(n);
}
tileIndexMap.put( n.nid, getTileIndex( n.ilon, n.ilat ) );
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();
int[] tiForNode = new int[nnodes];
// determine the tile-index for each node
for (int i=0; i<nnodes; i++ )
{
int tileIndex = tileIndexMap.getInt( data.nodes.get(i) );
if ( tileIndex != -1 )
{
waytileset |= ( 1L << tileIndex );
for (int i = 0; i < nnodes; i++) {
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
if (tileIndex != -1) {
waytileset |= (1L << tileIndex);
}
tiForNode[i] = tileIndex;
}
if ( relMerger != null )
{
relMerger.nextWay( data );
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 ) );
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 ) )
{
writeId( borderNidsOutStream, data.nodes.get(i) );
if (ti != -1) {
if ((i > 0 && tiForNode[i - 1] != ti) || (i + 1 < nnodes && tiForNode[i + 1] != ti)) {
writeId(borderNidsOutStream, data.nodes.get(i));
}
}
}
}
@Override
public void wayFileEnd( File wayFile ) throws Exception
{
public void wayFileEnd(File wayFile) throws Exception {
closeTileOutStreams();
if ( nodeCutter != null )
{
nodeCutter.nodeFileEnd( null );
if (nodeCutter != null) {
nodeCutter.nodeFileEnd(null);
}
if ( restrictionCutter5 != null )
{
if (restrictionCutter5 != null) {
restrictionCutter5.finish();
}
}
public int getTileIndexForNid( long nid )
{
return tileIndexMap.getInt( nid );
public int getTileIndexForNid(long nid) {
return tileIndexMap.getInt(nid);
}
private int getTileIndex( int ilon, int ilat )
{
int lonoff = (ilon / 45000000 ) * 45;
int latoff = (ilat / 30000000 ) * 30;
if ( lonoffset == -1 ) lonoffset = lonoff;
if ( latoffset == -1 ) latoffset = latoff;
if ( lonoff != lonoffset || latoff != latoffset )
throw new IllegalArgumentException( "inconsistent node: " + ilon + " " + ilat );
private int getTileIndex(int ilon, int ilat) {
int lonoff = (ilon / 45000000) * 45;
int latoff = (ilat / 30000000) * 30;
if (lonoffset == -1) lonoffset = lonoff;
if (latoffset == -1) latoffset = latoff;
if (lonoff != lonoffset || latoff != latoffset)
throw new IllegalArgumentException("inconsistent node: " + ilon + " " + ilat);
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 );
return lon*6 + lat;
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 )
{
int lon = (tileIndex / 6 ) * 5 + lonoffset - 180;
int lat = (tileIndex % 6 ) * 5 + latoffset - 90;
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;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".wt5";

View File

@ -10,46 +10,42 @@ 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 );
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
{
nodes = new LongList( 16 );
wid = readId( di) ;
int dlen = di.readByte(); description = new byte[dlen]; di.readFully( description );
for (;;)
{
long nid = readId( di );
if ( nid == -1 ) break;
nodes.add( nid );
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 (; ; ) {
long nid = readId(di);
if (nid == -1) break;
nodes.add(nid);
}
}
public void writeTo( DataOutputStream dos ) throws Exception
{
writeId( dos, wid );
dos.writeByte( description.length ); dos.write( description );
public void writeTo(DataOutputStream dos) throws Exception {
writeId(dos, wid);
dos.writeByte(description.length);
dos.write(description);
int size = nodes.size();
for( int i=0; i < size; i++ )
{
writeId( dos, nodes.get( i ) );
for (int i = 0; i < size; i++) {
writeId(dos, nodes.get(i));
}
writeId( dos, -1 ); // stopbyte
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 )
{
this( wayListener, deleteAfterReading );
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() )
{
throw new IllegalArgumentException( "not a directory: " + indir );
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++ )
{
File wayfile = descendingSize ? af[af.length -1 - i] : af[i];
if ( wayfile.getName().endsWith( inSuffix ) )
{
processFile( wayfile );
File[] af = sortBySizeAsc(indir.listFiles());
for (int i = 0; i < af.length; i++) {
File wayfile = descendingSize ? af[af.length - 1 - i] : af[i];
if (wayfile.getName().endsWith(inSuffix)) {
processFile(wayfile);
}
}
}
public void processFile(File wayfile) throws Exception
{
System.out.println( "*** WayIterator reading: " + wayfile );
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(;;)
{
WayData w = new WayData( di );
listener.nextWay( w );
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(wayfile)));
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" ) ))
{
listener.wayFileEnd(wayfile);
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,46 +69,36 @@ 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 )
{
System.out.println( "****** slave thread waiting for permission to process file of size " + size
+ " currentMaster=" + currentMasterSize + " maxFileSize=" + maxFileSize );
wait( 10000 );
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);
}
currentSlaveSize = size;
return true;
@ -117,35 +106,30 @@ 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
{
System.out.println( "*** WayLinker: Format a region of an OSM map for routing" );
if ( args.length != 8 )
{
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) {
System.out
.println( "usage: java WayLinker <node-tiles-in> <way-tiles-in> <bordernodes> <restrictions> <lookup-file> <profile-file> <data-tiles-out> <data-tiles-suffix> " );
.println("usage: java WayLinker <node-tiles-in> <way-tiles-in> <bordernodes> <restrictions> <lookup-file> <profile-file> <data-tiles-out> <data-tiles-suffix> ");
return;
}
new WayLinker().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] ), new File(
args[6] ), args[7] );
new WayLinker().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]), new File(
args[6]), args[7]);
System.out.println( "dumping bad TRs" );
System.out.println("dumping bad TRs");
RestrictionData.dumpBadTRs();
}
public void process( File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
String dataTilesSuffix ) throws Exception
{
public void process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
String dataTilesSuffix) throws Exception {
WayLinker master = new WayLinker();
WayLinker slave = new WayLinker();
slave.isSlave = true;
@ -155,23 +139,22 @@ public class WayLinker extends MapCreatorBase implements Runnable
slave.tc = tc;
master.tc = tc;
master._process( nodeTilesIn, wayTilesIn, borderFileIn, restrictionsFileIn, lookupFile, profileFile, dataTilesOut, dataTilesSuffix );
slave._process( nodeTilesIn, wayTilesIn, borderFileIn, restrictionsFileIn, lookupFile, profileFile, dataTilesOut, dataTilesSuffix );
master._process(nodeTilesIn, wayTilesIn, borderFileIn, restrictionsFileIn, lookupFile, profileFile, dataTilesOut, dataTilesSuffix);
slave._process(nodeTilesIn, wayTilesIn, borderFileIn, restrictionsFileIn, lookupFile, profileFile, dataTilesOut, dataTilesSuffix);
Thread m = new Thread( master );
Thread s = new Thread( slave );
Thread m = new Thread(master);
Thread s = new Thread(slave);
m.start();
s.start();
m.join();
s.join();
}
private void _process( File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
String dataTilesSuffix ) throws Exception
{
private void _process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
String dataTilesSuffix) throws Exception {
this.nodeTilesIn = nodeTilesIn;
this.wayTilesIn = wayTilesIn;
this.trafficTilesIn = new File( "../traffic" );
this.trafficTilesIn = new File("../traffic");
this.dataTilesOut = dataTilesOut;
this.borderFileIn = borderFileIn;
this.restrictionsFileIn = restrictionsFileIn;
@ -180,47 +163,39 @@ public class WayLinker extends MapCreatorBase implements Runnable
BExpressionMetaData meta = new BExpressionMetaData();
// read lookup + profile for lookup-version + access-filter
expctxWay = new BExpressionContextWay( meta );
meta.readMetaData( lookupFile );
expctxWay = new BExpressionContextWay(meta);
meta.readMetaData(lookupFile);
lookupVersion = meta.lookupVersion;
lookupMinorVersion = meta.lookupMinorVersion;
expctxWay.parseFile( profileFile, "global" );
expctxWay.parseFile(profileFile, "global");
creationTimeStamp = System.currentTimeMillis();
abUnifier = new ByteArrayUnifier( 16384, false );
abUnifier = new ByteArrayUnifier(16384, false);
skipEncodingCheck = Boolean.getBoolean( "skipEncodingCheck" );
skipEncodingCheck = Boolean.getBoolean("skipEncodingCheck");
}
@Override
public void run()
{
try
{
public void run() {
try {
// then process all segments
new WayIterator( this, true, !isSlave ).processDir( wayTilesIn, ".wt5" );
}
catch( Exception e )
{
System.out.println( "******* thread (slave=" + isSlave + ") got Exception: " + e );
throw new RuntimeException( e );
}
finally
{
if (!isSlave)
{
tc.setCurrentMasterSize( 0L );
new WayIterator(this, true, !isSlave).processDir(wayTilesIn, ".wt5");
} catch (Exception e) {
System.out.println("******* thread (slave=" + isSlave + ") got Exception: " + e);
throw new RuntimeException(e);
} 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
@ -228,66 +203,52 @@ public class WayLinker extends MapCreatorBase implements Runnable
long filesize = wayfile.length();
System.out.println( "**** wayFileStart() for isSlave=" + isSlave + " size=" + filesize );
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 ) )
{
} else {
if (!tc.setCurrentMasterSize(filesize)) {
return false;
}
}
File trafficFile = fileFromTemplate( wayfile, trafficTilesIn, "trf" );
File trafficFile = fileFromTemplate(wayfile, trafficTilesIn, "trf");
// process corresponding node-file, if any
File nodeFile = fileFromTemplate( wayfile, nodeTilesIn, "u5d" );
if ( nodeFile.exists() )
{
File nodeFile = fileFromTemplate(wayfile, nodeTilesIn, "u5d");
if (nodeFile.exists()) {
reset();
// read the border file
readingBorder = true;
new NodeIterator( this, false ).processFile( borderFileIn );
borderSet = new FrozenLongSet( borderSet );
new NodeIterator(this, false).processFile(borderFileIn);
borderSet = new FrozenLongSet(borderSet);
// read this tile's nodes
readingBorder = false;
new NodeIterator( this, true ).processFile( nodeFile );
new NodeIterator(this, true).processFile(nodeFile);
// freeze the nodes-map
FrozenLongMap<OsmNodeP> nodesMapFrozen = new FrozenLongMap<OsmNodeP>( nodesMap );
FrozenLongMap<OsmNodeP> nodesMapFrozen = new FrozenLongMap<OsmNodeP>(nodesMap);
nodesMap = nodesMapFrozen;
File restrictionFile = fileFromTemplate( wayfile, new File( nodeTilesIn.getParentFile(), "restrictions55" ), "rt5" );
File restrictionFile = fileFromTemplate(wayfile, new File(nodeTilesIn.getParentFile(), "restrictions55"), "rt5");
// read restrictions for nodes in nodesMap
if ( restrictionFile.exists() )
{
DataInputStream di = new DataInputStream( new BufferedInputStream ( new FileInputStream( restrictionFile ) ) );
if (restrictionFile.exists()) {
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(restrictionFile)));
int ntr = 0;
try
{
for(;;)
{
RestrictionData res = new RestrictionData( di );
OsmNodeP n = nodesMap.get( res.viaNid );
if ( n != null )
{
if ( ! ( n instanceof OsmNodePT ) )
{
n = new OsmNodePT( n );
nodesMap.put( res.viaNid, n );
try {
for (; ; ) {
RestrictionData res = new RestrictionData(di);
OsmNodeP n = nodesMap.get(res.viaNid);
if (n != null) {
if (!(n instanceof OsmNodePT)) {
n = new OsmNodePT(n);
nodesMap.put(res.viaNid, n);
}
OsmNodePT nt = (OsmNodePT) n;
res.viaLon = nt.ilon;
@ -297,55 +258,49 @@ public class WayLinker extends MapCreatorBase implements Runnable
ntr++;
}
}
}
catch( EOFException eof )
{
} catch (EOFException eof) {
di.close();
}
System.out.println( "read " + ntr + " turn-restrictions" );
System.out.println("read " + ntr + " turn-restrictions");
}
nodesList = nodesMapFrozen.getValueList();
}
// read a traffic-file, if any
if ( trafficFile.exists() )
{
trafficMap = new OsmTrafficMap( expctxWay );
trafficMap.loadAll( trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false );
if (trafficFile.exists()) {
trafficMap = new OsmTrafficMap(expctxWay);
trafficMap.loadAll(trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false);
}
return true;
}
@Override
public void nextNode( NodeData data ) throws Exception
{
OsmNodeP n = data.description == null ? new OsmNodeP() : new OsmNodePT( data.description );
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 ) ) )
{
nodesMap.fastPut( data.nid, n );
if (readingBorder || (!borderSet.contains(data.nid))) {
nodesMap.fastPut(data.nid, n);
}
if ( readingBorder )
{
if (readingBorder) {
n.bits |= OsmNodeP.BORDER_BIT;
borderSet.fastAdd( data.nid );
borderSet.fastAdd(data.nid);
return;
}
// remember the segment coords
int min_lon = ( n.ilon / 5000000 ) * 5000000;
int min_lat = ( n.ilat / 5000000 ) * 5000000;
if ( minLon == -1 )
int min_lon = (n.ilon / 5000000) * 5000000;
int min_lat = (n.ilat / 5000000) * 5000000;
if (minLon == -1)
minLon = min_lon;
if ( minLat == -1 )
if (minLat == -1)
minLat = min_lat;
if ( minLat != min_lat || minLon != min_lon )
throw new IllegalArgumentException( "inconsistent node: " + n.ilon + " " + n.ilat );
if (minLat != min_lat || minLon != min_lon)
throw new IllegalArgumentException("inconsistent node: " + n.ilon + " " + n.ilat);
}
// check if one of the nodes has a turn-restriction with
@ -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 )
{
checkRestriction( n1, n2, w, true );
checkRestriction( n2, n1, w, false );
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,55 +341,49 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
}
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 ) );
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
{
byte[] description = abUnifier.unify( way.description );
public void nextWay(WayData way) throws Exception {
byte[] description = abUnifier.unify(way.description);
// filter according to profile
expctxWay.evaluate( false, description );
expctxWay.evaluate(false, description);
boolean ok = expctxWay.getCostfactor() < 10000.;
expctxWay.evaluate( true, description );
expctxWay.evaluate(true, description);
ok |= expctxWay.getCostfactor() < 10000.;
if ( !ok )
if (!ok)
return;
byte wayBits = 0;
expctxWay.decode( description );
if ( !expctxWay.getBooleanLookupValue( "bridge" ) )
expctxWay.decode(description);
if (!expctxWay.getBooleanLookupValue("bridge"))
wayBits |= OsmNodeP.NO_BRIDGE_BIT;
if ( !expctxWay.getBooleanLookupValue( "tunnel" ) )
if (!expctxWay.getBooleanLookupValue("tunnel"))
wayBits |= OsmNodeP.NO_TUNNEL_BIT;
OsmNodeP n1 = null;
OsmNodeP n2 = null;
for ( int i = 0; i < way.nodes.size(); i++ )
{
long nid = way.nodes.get( i );
for (int i = 0; i < way.nodes.size(); i++) {
long nid = way.nodes.get(i);
n1 = n2;
n2 = nodesMap.get( nid );
n2 = nodesMap.get(nid);
if ( n1 != null && n2 != null && n1 != n2 )
{
checkRestriction( n1, n2, way );
if (n1 != null && n2 != null && n1 != n2) {
checkRestriction(n1, n2, way);
OsmLinkP link = n2.createLink( n1 );
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,126 +405,109 @@ public class WayLinker extends MapCreatorBase implements Runnable
int maxLat = minLat + 5000000;
// cleanup duplicate targets
for ( OsmNodeP n : nodesList )
{
if ( n == null || n.getFirstLink() == null || n.isTransferNode() )
for (OsmNodeP n : nodesList) {
if (n == null || n.getFirstLink() == null || n.isTransferNode())
continue;
n.checkDuplicateTargets();
}
// write segment data to individual files
{
int nLonSegs = ( maxLon - minLon ) / 1000000;
int nLatSegs = ( maxLat - minLat ) / 1000000;
int nLonSegs = (maxLon - minLon) / 1000000;
int nLatSegs = (maxLat - minLat) / 1000000;
// sort the nodes into segments
LazyArrayOfLists<OsmNodeP> seglists = new LazyArrayOfLists<OsmNodeP>( nLonSegs * nLatSegs );
for ( OsmNodeP n : nodesList )
{
if ( n == null || n.getFirstLink() == null || n.isTransferNode() )
LazyArrayOfLists<OsmNodeP> seglists = new LazyArrayOfLists<OsmNodeP>(nLonSegs * nLatSegs);
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 )
if (n.ilon < minLon || n.ilon >= maxLon || n.ilat < minLat || n.ilat >= maxLat)
continue;
int lonIdx = ( n.ilon - minLon ) / 1000000;
int latIdx = ( n.ilat - minLat ) / 1000000;
int lonIdx = (n.ilon - minLon) / 1000000;
int latIdx = (n.ilat - minLat) / 1000000;
int tileIndex = lonIdx * nLatSegs + latIdx;
seglists.getList( tileIndex ).add( n );
seglists.getList(tileIndex).add(n);
}
nodesList = null;
seglists.trimAll();
// open the output file
File outfile = fileFromTemplate( wayfile, dataTilesOut, dataTilesSuffix );
DataOutputStream os = createOutStream( outfile );
File outfile = fileFromTemplate(wayfile, dataTilesOut, dataTilesSuffix);
DataOutputStream os = createOutStream(outfile);
long[] fileIndex = new long[25];
int[] fileHeaderCrcs = new int[25];
// write 5*5 index dummy
for ( int i55 = 0; i55 < 25; i55++ )
{
os.writeLong( 0 );
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 )
{
List<OsmNodeP> nlist = seglists.getList( tileIndex );
if (seglists.getSize(tileIndex) > 0) {
List<OsmNodeP> nlist = seglists.getList(tileIndex);
LazyArrayOfLists<OsmNodeP> subs = new LazyArrayOfLists<OsmNodeP>( ncaches );
LazyArrayOfLists<OsmNodeP> subs = new LazyArrayOfLists<OsmNodeP>(ncaches);
byte[][] subByteArrays = new byte[ncaches][];
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;
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;
int si = subLatIdx * divisor + subLonIdx;
subs.getList( si ).add( n );
subs.getList(si).add(n);
}
subs.trimAll();
int[] posIdx = new int[ncaches];
int pos = indexsize;
for ( int si = 0; si < ncaches; si++ )
{
List<OsmNodeP> subList = subs.getList( si );
for (int si = 0; si < ncaches; si++) {
List<OsmNodeP> subList = subs.getList(si);
int size = subList.size();
if ( size > 0 )
{
OsmNodeP n0 = subList.get( 0 );
if (size > 0) {
OsmNodeP n0 = subList.get(0);
int lonIdxDiv = n0.ilon / cellsize;
int latIdxDiv = n0.ilat / cellsize;
MicroCache mc = new MicroCache2( size, abBuf2, lonIdxDiv, latIdxDiv, divisor );
MicroCache mc = new MicroCache2(size, abBuf2, lonIdxDiv, latIdxDiv, divisor);
// 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 )
{
throw new IllegalArgumentException( "inconstistent shrinking: " + longId );
int shrinkid = mc.shrinkId(longId);
if (mc.expandId(shrinkid) != longId) {
throw new IllegalArgumentException("inconstistent shrinking: " + longId);
}
sortedList.put( Integer.valueOf( shrinkid ), n );
sortedList.put(Integer.valueOf(shrinkid), n);
}
for ( OsmNodeP n : sortedList.values() )
{
n.writeNodeData( mc, trafficMap );
for (OsmNodeP n : sortedList.values()) {
n.writeNodeData(mc, trafficMap);
}
if ( mc.getSize() > 0 )
{
if (mc.getSize() > 0) {
byte[] subBytes;
for ( ;; )
{
int len = mc.encodeMicroCache( abBuf1 );
for (; ; ) {
int len = mc.encodeMicroCache(abBuf1);
subBytes = new byte[len];
System.arraycopy( abBuf1, 0, subBytes, 0, 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 );
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 ( MicroCache.debug )
throw new RuntimeException( "encoding crosscheck failed: " + diffMessage );
String diffMessage = mc.compareWith(mc2);
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
@ -595,16 +517,14 @@ public class WayLinker extends MapCreatorBase implements Runnable
posIdx[si] = pos;
}
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++ )
{
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++) {
byte[] ab = subByteArrays[si];
if ( ab != null )
{
os.write( ab );
os.writeInt( Crc32.crc( ab, 0, ab.length ) ^ microCacheEncoding );
if (ab != null) {
os.write(ab);
os.writeInt(Crc32.crc(ab, 0, ab.length) ^ microCacheEncoding);
}
}
filepos += pos;
@ -613,52 +533,46 @@ public class WayLinker extends MapCreatorBase implements Runnable
}
}
byte[] abFileIndex = compileFileIndex( fileIndex, lookupVersion, lookupMinorVersion );
byte[] abFileIndex = compileFileIndex(fileIndex, lookupVersion, lookupMinorVersion);
// 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++ )
{
os.writeInt( fileHeaderCrcs[i55] );
os.writeLong(creationTimeStamp);
os.writeInt(Crc32.crc(abFileIndex, 0, abFileIndex.length) ^ microCacheEncoding);
for (int i55 = 0; i55 < 25; i55++) {
os.writeInt(fileHeaderCrcs[i55]);
}
os.close();
// re-open random-access to write file-index
RandomAccessFile ra = new RandomAccessFile( outfile, "rw" );
ra.write( abFileIndex, 0, abFileIndex.length );
RandomAccessFile ra = new RandomAccessFile(outfile, "rw");
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() );
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++ )
{
DataOutputStream dos = new DataOutputStream(bos);
for (int i55 = 0; i55 < 25; i55++) {
long versionPrefix = i55 == 1 ? lookupMinorVersion : lookupVersion;
versionPrefix <<= 48;
dos.writeLong( fileIndex[i55] | versionPrefix );
dos.writeLong(fileIndex[i55] | versionPrefix);
}
dos.close();
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++ )
{
dos.writeInt( posIdx[si] );
DataOutputStream dos = new DataOutputStream(bos);
for (int si = 0; si < posIdx.length; si++) {
dos.writeInt(posIdx[si]);
}
dos.close();
return bos.toByteArray();

View File

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

View File

@ -5,50 +5,49 @@ 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
{
URL mapurl = this.getClass().getResource( "/dreieich.osm.gz" );
Assert.assertTrue( "test-osm-map dreieich.osm not found", mapurl != null );
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());
File workingDir = mapFile.getParentFile();
File profileDir = new File( workingDir, "/../../../../misc/profiles2" );
File tmpdir = new File( workingDir, "tmp" );
File profileDir = new File(workingDir, "/../../../../misc/profiles2");
File tmpdir = new File(workingDir, "tmp");
tmpdir.mkdir();
File nodes = new File( tmpdir, "nodetiles" );
File nodes = new File(tmpdir, "nodetiles");
nodes.mkdir();
File ways = new File( tmpdir, "waytiles" );
File ways = new File(tmpdir, "waytiles");
ways.mkdir();
File nodes55 = new File( tmpdir, "nodes55" );
File nodes55 = new File(tmpdir, "nodes55");
nodes55.mkdir();
File ways55 = new File( tmpdir, "waytiles55" );
File ways55 = new File(tmpdir, "waytiles55");
ways55.mkdir();
File lookupFile = new File( profileDir, "lookups.dat" );
File relFile = new File( tmpdir, "cycleways.dat" );
File resFile = new File( tmpdir, "restrictions.dat" );
File profileAll = new File( profileDir, "all.brf" );
File profileReport = new File( profileDir, "trekking.brf" );
File profileCheck = new File( profileDir, "softaccess.brf" );
File borderFile = new File( tmpdir, "bordernids.dat" );
File lookupFile = new File(profileDir, "lookups.dat");
File relFile = new File(tmpdir, "cycleways.dat");
File resFile = new File(tmpdir, "restrictions.dat");
File profileAll = new File(profileDir, "all.brf");
File profileReport = new File(profileDir, "trekking.brf");
File profileCheck = new File(profileDir, "softaccess.brf");
File borderFile = new File(tmpdir, "bordernids.dat");
new OsmFastCutter().doCut( lookupFile, nodes, ways, nodes55, ways55, borderFile, relFile, resFile, profileAll, profileReport, profileCheck, mapFile );
new OsmFastCutter().doCut(lookupFile, nodes, ways, nodes55, ways55, borderFile, relFile, resFile, profileAll, profileReport, profileCheck, mapFile);
// run PosUnifier
File unodes55 = new File( tmpdir, "unodes55" );
File bordernodes = new File( tmpdir, "bordernodes.dat" );
File unodes55 = new File(tmpdir, "unodes55");
File bordernodes = new File(tmpdir, "bordernodes.dat");
unodes55.mkdir();
new PosUnifier().process( nodes55, unodes55, borderFile, bordernodes, "/private-backup/srtm" );
new PosUnifier().process(nodes55, unodes55, borderFile, bordernodes, "/private-backup/srtm");
// run WayLinker
File segments = new File( tmpdir, "segments" );
File segments = new File(tmpdir, "segments");
segments.mkdir();
new WayLinker().process( unodes55, ways55, bordernodes, resFile, lookupFile, profileAll, segments, "rd5" );
new WayLinker().process(unodes55, ways55, bordernodes, resFile, lookupFile, profileAll, segments, "rd5");
}
}

View File

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

View File

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

View File

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

View File

@ -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 {
throw new IllegalArgumentException("internal error: setNext: unknown source");
}
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
{
throw new IllegalArgumentException( "internal error: setFirstLinkHolder: unknown source" );
} 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
{
throw new IllegalArgumentException( "internal error: getFirstLinkHolder: unknown source" );
} 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,21 +136,20 @@ 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 )
{
OsmLinkHolder firstHolder = getFirstLinkHolder( source );
if ( firstHolder != null ) { holder.setNextForLink( firstHolder ); }
setFirstLinkHolder( holder, source );
public final void addLinkHolder(OsmLinkHolder holder, OsmNode source) {
OsmLinkHolder firstHolder = getFirstLinkHolder(source);
if (firstHolder != null) {
holder.setNextForLink(firstHolder);
}
setFirstLinkHolder(holder, source);
}
}

View File

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

View File

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

View File

@ -11,11 +11,10 @@ import java.util.HashMap;
import btools.util.ByteArrayUnifier;
import btools.util.SortedHeap;
public final class OsmNodesMap
{
private HashMap<OsmNode,OsmNode> hmap = new HashMap<OsmNode,OsmNode>(4096);
public final class OsmNodesMap {
private HashMap<OsmNode, OsmNode> hmap = new HashMap<OsmNode, OsmNode>(4096);
private ByteArrayUnifier abUnifier = new ByteArrayUnifier( 16384, false );
private ByteArrayUnifier abUnifier = new ByteArrayUnifier(16384, false);
private OsmNode testKey = new OsmNode();
@ -34,46 +33,33 @@ public final class OsmNodesMap
public int cleanupMode = 0;
public void cleanupAndCount( OsmNode[] nodes )
{
if ( cleanupMode == 0 )
{
justCount( nodes );
}
else
{
cleanupPeninsulas( nodes );
public void cleanupAndCount(OsmNode[] nodes) {
if (cleanupMode == 0) {
justCount(nodes);
} else {
cleanupPeninsulas(nodes);
}
}
private void justCount( OsmNode[] nodes )
{
for( int i=0; i<nodes.length; i++ )
{
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
for (int i = 0; i < nodes.length; i++) // loop over nodes again just for housekeeping
{
OsmNode n = nodes[i];
if ( n.firstlink != null )
{
if ( n.visitID == 1 )
{
try
{
minVisitIdInSubtree( null, n );
}
catch( StackOverflowError soe )
{
if (n.firstlink != null) {
if (n.visitID == 1) {
try {
minVisitIdInSubtree(null, n);
} catch (StackOverflowError soe) {
// System.out.println( "+++++++++++++++ StackOverflowError ++++++++++++++++" );
}
}
@ -81,69 +67,55 @@ public final class OsmNodesMap
}
}
private int minVisitIdInSubtree( OsmNode source, OsmNode n )
{
if ( n.visitID == 1 ) n.visitID = baseID; // border node
private int minVisitIdInSubtree(OsmNode source, OsmNode n) {
if (n.visitID == 1) n.visitID = baseID; // border node
else n.visitID = lastVisitID++;
int minId = n.visitID;
nodesCreated++;
OsmLink nextLink = null;
for( OsmLink l = n.firstlink; l != null; l = nextLink )
{
nextLink = l.getNext( n );
for (OsmLink l = n.firstlink; l != null; l = nextLink) {
nextLink = l.getNext(n);
OsmNode t = l.getTarget( n );
if ( t == source ) continue;
if ( t.isHollow() ) continue;
OsmNode t = l.getTarget(n);
if (t == source) continue;
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 ?
minIdSub = minVisitIdInSubtree(n, t);
if (minIdSub > n.visitID) // peninsula ?
{
nodesCreated = nodesCreatedUntilHere;
n.unlinkLink( l );
t.unlinkLink( l );
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;
if (minIdSub < minId) minId = minIdSub;
}
return minId;
}
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,56 +123,45 @@ 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 );
nodes2check.add(n);
}
// 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() )
{
OsmNode n = nodes2check.remove( nodes2check.size()-1 );
if ( n.visitID < baseID )
{
nodes2check.add(n0);
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
if (n.visitID < baseID) {
n.visitID = lastVisitID;
nodesCreated++;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
OsmNode t = l.getTarget( n );
nodes2check.add( t );
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() )
{
OsmNode n = nodes2check.remove( nodes2check.size()-1 );
if ( n.visitID == lastVisitID )
{
nodes2check.add(n0);
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
if (n.visitID == lastVisitID) {
n.visitID = lastVisitID;
nodesCreated--;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
OsmNode t = l.getTarget( n );
nodes2check.add( t );
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
nodes2check.add(t);
}
n.vanish();
}
@ -211,137 +172,121 @@ 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() )
{
addActiveNode( nodes2check, n );
nodesCreated = 0;
for (OsmNode n : hmap.values()) {
addActiveNode(nodes2check, n);
}
lastVisitID++;
baseID = lastVisitID;
while ( !nodes2check.isEmpty() )
{
OsmNode n = nodes2check.remove( nodes2check.size()-1 );
while (!nodes2check.isEmpty()) {
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
n.visitID = lastVisitID;
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
{
OsmNode t = l.getTarget( n );
if ( t.visitID != lastVisitID )
{
addActiveNode( nodes2check, t );
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
OsmNode t = l.getTarget(n);
if (t.visitID != lastVisitID) {
addActiveNode(nodes2check, t);
}
}
if ( destination != null && currentMaxCost < 1000000000 )
{
int distance = n.calcDistance( destination );
if ( distance > currentMaxCost - currentPathCost + 100 )
{
if (destination != null && currentMaxCost < 1000000000) {
int distance = n.calcDistance(destination);
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 );
return hmap.get(testKey);
}
public void remove( OsmNode node )
{
if ( node != endNode1 && node != endNode2 ) // keep endnodes in hollow-map even when loaded
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 );
hmap.remove(node);
}
}
/**
* Put a node into the map
*
* @return the previous node if that id existed, else null
*/
public OsmNode put( OsmNode node )
{
return hmap.put( node, node );
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 )
{
n.selev = (short) idx;
for (int i : links) {
OsmNode t = nodes[i];
OsmLink link = n.isLinkUnused() ? n : ( t.isLinkUnused() ? t : null );
if ( link == null )
{
OsmLink link = n.isLinkUnused() ? n : (t.isLinkUnused() ? t : null);
if (link == null) {
link = new OsmLink();
}
n.addLink( link, false, t );
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++ )
{
nodes[i]= new OsmNode( (i+1000)*1000,(i+1000)*1000 );
for (int i = 0; i < nodes.length; i++) {
nodes[i] = new OsmNode((i + 1000) * 1000, (i + 1000) * 1000);
}
addLinks( nodes, 0, true , new int[]{1,5} ); // 0
addLinks( nodes, 1, true , new int[]{} ); // 1
addLinks( nodes, 2, false, new int[]{3,4} ); // 2
addLinks( nodes, 3, false, new int[]{4} ); // 3
addLinks( nodes, 4, false, new int[]{} ); // 4
addLinks( nodes, 5, true , new int[]{6,9} ); // 5
addLinks( nodes, 6, false, new int[]{7,8} ); // 6
addLinks( nodes, 7, false, new int[]{} ); // 7
addLinks( nodes, 8, false, new int[]{} ); // 8
addLinks( nodes, 9, false, new int[]{10,11} ); // 9
addLinks( nodes, 10, false, new int[]{11} ); // 10
addLinks( nodes, 11, false, new int[]{} ); // 11
addLinks(nodes, 0, true, new int[]{1, 5}); // 0
addLinks(nodes, 1, true, new int[]{}); // 1
addLinks(nodes, 2, false, new int[]{3, 4}); // 2
addLinks(nodes, 3, false, new int[]{4}); // 3
addLinks(nodes, 4, false, new int[]{}); // 4
addLinks(nodes, 5, true, new int[]{6, 9}); // 5
addLinks(nodes, 6, false, new int[]{7, 8}); // 6
addLinks(nodes, 7, false, new int[]{}); // 7
addLinks(nodes, 8, false, new int[]{}); // 8
addLinks(nodes, 9, false, new int[]{10, 11}); // 9
addLinks(nodes, 10, false, new int[]{11}); // 10
addLinks(nodes, 11, false, new int[]{}); // 11
OsmNodesMap nm = new OsmNodesMap();
nm.cleanupMode = 2;
nm.cleanupAndCount( nodes );
nm.cleanupAndCount(nodes);
System.out.println( "nodesCreated=" + nm.nodesCreated );
nm.cleanupAndCount( nodes );
System.out.println("nodesCreated=" + nm.nodesCreated);
nm.cleanupAndCount(nodes);
System.out.println( "nodesCreated=" + nm.nodesCreated );
System.out.println("nodesCreated=" + nm.nodesCreated);
}

View File

@ -6,8 +6,7 @@
package btools.mapaccess;
public interface OsmPos
{
public interface OsmPos {
public int getILat();
public int getILon();
@ -16,7 +15,7 @@ public interface OsmPos
public double getElev();
public int calcDistance( OsmPos p );
public int calcDistance(OsmPos p);
public long getIdFromPos();

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

View File

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

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