Reformat whole codebase using Android Studio
This commit is contained in:
parent
d5322667d5
commit
c15913c1ab
@ -5,8 +5,7 @@ import btools.util.BitCoderContext;
|
|||||||
/**
|
/**
|
||||||
* Container for some re-usable databuffers for the decoder
|
* Container for some re-usable databuffers for the decoder
|
||||||
*/
|
*/
|
||||||
public final class DataBuffers
|
public final class DataBuffers {
|
||||||
{
|
|
||||||
public byte[] iobuffer;
|
public byte[] iobuffer;
|
||||||
public byte[] tagbuf1 = new byte[256];
|
public byte[] tagbuf1 = new byte[256];
|
||||||
public BitCoderContext bctx1 = new BitCoderContext(tagbuf1);
|
public BitCoderContext bctx1 = new BitCoderContext(tagbuf1);
|
||||||
@ -17,8 +16,7 @@ public final class DataBuffers
|
|||||||
public int[] alon = new int[2048];
|
public int[] alon = new int[2048];
|
||||||
public int[] alat = new int[2048];
|
public int[] alat = new int[2048];
|
||||||
|
|
||||||
public DataBuffers()
|
public DataBuffers() {
|
||||||
{
|
|
||||||
this(new byte[65636]);
|
this(new byte[65636]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,8 +24,7 @@ public final class DataBuffers
|
|||||||
* construct a set of databuffers except
|
* construct a set of databuffers except
|
||||||
* for 'iobuffer', where the given array is used
|
* for 'iobuffer', where the given array is used
|
||||||
*/
|
*/
|
||||||
public DataBuffers( byte[] iobuffer )
|
public DataBuffers(byte[] iobuffer) {
|
||||||
{
|
|
||||||
this.iobuffer = iobuffer;
|
this.iobuffer = iobuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,16 +3,14 @@ package btools.codec;
|
|||||||
/**
|
/**
|
||||||
* Special integer fifo suitable for 3-pass encoding
|
* Special integer fifo suitable for 3-pass encoding
|
||||||
*/
|
*/
|
||||||
public class IntegerFifo3Pass
|
public class IntegerFifo3Pass {
|
||||||
{
|
|
||||||
private int[] a;
|
private int[] a;
|
||||||
private int size;
|
private int size;
|
||||||
private int pos;
|
private int pos;
|
||||||
|
|
||||||
private int pass;
|
private int pass;
|
||||||
|
|
||||||
public IntegerFifo3Pass( int capacity )
|
public IntegerFifo3Pass(int capacity) {
|
||||||
{
|
|
||||||
a = capacity < 4 ? new int[4] : new 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
|
* Starts a new encoding pass and resets the reading pointer
|
||||||
* from the stats collected in pass2 and writes that to the given context
|
* from the stats collected in pass2 and writes that to the given context
|
||||||
*/
|
*/
|
||||||
public void init()
|
public void init() {
|
||||||
{
|
|
||||||
pass++;
|
pass++;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
@ -29,12 +26,9 @@ public class IntegerFifo3Pass
|
|||||||
/**
|
/**
|
||||||
* writes to the fifo in pass2
|
* writes to the fifo in pass2
|
||||||
*/
|
*/
|
||||||
public void add( int value )
|
public void add(int value) {
|
||||||
{
|
if (pass == 2) {
|
||||||
if ( pass == 2 )
|
if (size == a.length) {
|
||||||
{
|
|
||||||
if ( size == a.length )
|
|
||||||
{
|
|
||||||
int[] aa = new int[2 * size];
|
int[] aa = new int[2 * size];
|
||||||
System.arraycopy(a, 0, aa, 0, size);
|
System.arraycopy(a, 0, aa, 0, size);
|
||||||
a = aa;
|
a = aa;
|
||||||
@ -46,15 +40,12 @@ public class IntegerFifo3Pass
|
|||||||
/**
|
/**
|
||||||
* reads from the fifo in pass3 (in pass1/2 returns just 1)
|
* reads from the fifo in pass3 (in pass1/2 returns just 1)
|
||||||
*/
|
*/
|
||||||
public int getNext()
|
public int getNext() {
|
||||||
{
|
|
||||||
return pass == 3 ? get(pos++) : 1;
|
return pass == 3 ? get(pos++) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int get( int idx )
|
private int get(int idx) {
|
||||||
{
|
if (idx >= size) {
|
||||||
if ( idx >= size )
|
|
||||||
{
|
|
||||||
throw new IndexOutOfBoundsException("list size=" + size + " idx=" + idx);
|
throw new IndexOutOfBoundsException("list size=" + size + " idx=" + idx);
|
||||||
}
|
}
|
||||||
return a[idx];
|
return a[idx];
|
||||||
|
|||||||
@ -3,8 +3,7 @@ package btools.codec;
|
|||||||
/**
|
/**
|
||||||
* Simple container for a list of lists of integers
|
* Simple container for a list of lists of integers
|
||||||
*/
|
*/
|
||||||
public class LinkedListContainer
|
public class LinkedListContainer {
|
||||||
{
|
|
||||||
private int[] ia; // prev, data, prev, data, ...
|
private int[] ia; // prev, data, prev, data, ...
|
||||||
private int size;
|
private int size;
|
||||||
private int[] startpointer; // 0=void, odd=head-data-cell
|
private int[] startpointer; // 0=void, odd=head-data-cell
|
||||||
@ -12,15 +11,14 @@ public class LinkedListContainer
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a container for the given number of lists
|
* Construct a container for the given number of lists
|
||||||
*
|
* <p>
|
||||||
* If no default-buffer is given, an int[nlists*4] is constructed,
|
* If no default-buffer is given, an int[nlists*4] is constructed,
|
||||||
* able to hold 2 entries per list on average
|
* able to hold 2 entries per list on average
|
||||||
*
|
*
|
||||||
* @param nlists the number of lists
|
* @param nlists the number of lists
|
||||||
* @param defaultbuffer an optional data array for re-use (gets replaced if too small)
|
* @param defaultbuffer an optional data array for re-use (gets replaced if too small)
|
||||||
*/
|
*/
|
||||||
public LinkedListContainer( int nlists, int[] defaultbuffer )
|
public LinkedListContainer(int nlists, int[] defaultbuffer) {
|
||||||
{
|
|
||||||
ia = defaultbuffer == null ? new int[nlists * 4] : defaultbuffer;
|
ia = defaultbuffer == null ? new int[nlists * 4] : defaultbuffer;
|
||||||
startpointer = new int[nlists];
|
startpointer = new int[nlists];
|
||||||
}
|
}
|
||||||
@ -31,10 +29,8 @@ public class LinkedListContainer
|
|||||||
* @param listNr the list to add the data to
|
* @param listNr the list to add the data to
|
||||||
* @param data the data value
|
* @param data the data value
|
||||||
*/
|
*/
|
||||||
public void addDataElement( int listNr, int data )
|
public void addDataElement(int listNr, int data) {
|
||||||
{
|
if (size + 2 > ia.length) {
|
||||||
if ( size + 2 > ia.length )
|
|
||||||
{
|
|
||||||
resize();
|
resize();
|
||||||
}
|
}
|
||||||
ia[size++] = startpointer[listNr];
|
ia[size++] = startpointer[listNr];
|
||||||
@ -48,12 +44,10 @@ public class LinkedListContainer
|
|||||||
* @param listNr the list to initialize
|
* @param listNr the list to initialize
|
||||||
* @return the number of entries in that list
|
* @return the number of entries in that list
|
||||||
*/
|
*/
|
||||||
public int initList( int listNr )
|
public int initList(int listNr) {
|
||||||
{
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
int lp = listpointer = startpointer[listNr];
|
int lp = listpointer = startpointer[listNr];
|
||||||
while( lp != 0 )
|
while (lp != 0) {
|
||||||
{
|
|
||||||
lp = ia[lp - 1];
|
lp = ia[lp - 1];
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
@ -67,10 +61,8 @@ public class LinkedListContainer
|
|||||||
* @return the data element
|
* @return the data element
|
||||||
* @throws IllegalArgumentException if no more element
|
* @throws IllegalArgumentException if no more element
|
||||||
*/
|
*/
|
||||||
public int getDataElement()
|
public int getDataElement() {
|
||||||
{
|
if (listpointer == 0) {
|
||||||
if ( listpointer == 0 )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("no more element!");
|
throw new IllegalArgumentException("no more element!");
|
||||||
}
|
}
|
||||||
int data = ia[listpointer];
|
int data = ia[listpointer];
|
||||||
@ -78,8 +70,7 @@ public class LinkedListContainer
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resize()
|
private void resize() {
|
||||||
{
|
|
||||||
int[] ia2 = new int[2 * ia.length];
|
int[] ia2 = new int[2 * ia.length];
|
||||||
System.arraycopy(ia, 0, ia2, 0, ia.length);
|
System.arraycopy(ia, 0, ia2, 0, ia.length);
|
||||||
ia = ia2;
|
ia = ia2;
|
||||||
|
|||||||
@ -5,21 +5,20 @@ import btools.util.ByteDataWriter;
|
|||||||
/**
|
/**
|
||||||
* a micro-cache is a data cache for an area of some square kilometers or some
|
* a micro-cache is a data cache for an area of some square kilometers or some
|
||||||
* hundreds or thousands nodes
|
* hundreds or thousands nodes
|
||||||
*
|
* <p>
|
||||||
* This is the basic io-unit: always a full microcache is loaded from the
|
* 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
|
* data-file if a node is requested at a position not yet covered by the caches
|
||||||
* already loaded
|
* already loaded
|
||||||
*
|
* <p>
|
||||||
* The nodes are represented in a compact way (typical 20-50 bytes per node),
|
* 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
|
* 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.
|
* supported to remove the nodes already consumed from the cache.
|
||||||
*
|
* <p>
|
||||||
* The cache-internal data representation is different from that in the
|
* The cache-internal data representation is different from that in the
|
||||||
* data-files, where a cache is encoded as a whole, allowing more
|
* data-files, where a cache is encoded as a whole, allowing more
|
||||||
* redundancy-removal for a more compact encoding
|
* redundancy-removal for a more compact encoding
|
||||||
*/
|
*/
|
||||||
public class MicroCache extends ByteDataWriter
|
public class MicroCache extends ByteDataWriter {
|
||||||
{
|
|
||||||
protected int[] faid;
|
protected int[] faid;
|
||||||
protected int[] fapos;
|
protected int[] fapos;
|
||||||
protected int size = 0;
|
protected int size = 0;
|
||||||
@ -35,25 +34,21 @@ public class MicroCache extends ByteDataWriter
|
|||||||
|
|
||||||
public static boolean debug = false;
|
public static boolean debug = false;
|
||||||
|
|
||||||
protected MicroCache( byte[] ab )
|
protected MicroCache(byte[] ab) {
|
||||||
{
|
|
||||||
super(ab);
|
super(ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static MicroCache emptyNonVirgin = new MicroCache(null);
|
public final static MicroCache emptyNonVirgin = new MicroCache(null);
|
||||||
|
|
||||||
static
|
static {
|
||||||
{
|
|
||||||
emptyNonVirgin.virgin = false;
|
emptyNonVirgin.virgin = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MicroCache emptyCache()
|
public static MicroCache emptyCache() {
|
||||||
{
|
|
||||||
return new MicroCache(null); // TODO: singleton?
|
return new MicroCache(null); // TODO: singleton?
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void init( int size )
|
protected void init(int size) {
|
||||||
{
|
|
||||||
this.size = size;
|
this.size = size;
|
||||||
delcount = 0;
|
delcount = 0;
|
||||||
delbytes = 0;
|
delbytes = 0;
|
||||||
@ -62,35 +57,31 @@ public class MicroCache extends ByteDataWriter
|
|||||||
p2size >>= 1;
|
p2size >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void finishNode( long id )
|
public final void finishNode(long id) {
|
||||||
{
|
|
||||||
fapos[size] = aboffset;
|
fapos[size] = aboffset;
|
||||||
faid[size] = shrinkId(id);
|
faid[size] = shrinkId(id);
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void discardNode()
|
public final void discardNode() {
|
||||||
{
|
|
||||||
aboffset = startPos(size);
|
aboffset = startPos(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getSize()
|
public final int getSize() {
|
||||||
{
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getDataSize()
|
public final int getDataSize() {
|
||||||
{
|
|
||||||
return ab == null ? 0 : ab.length;
|
return ab == null ? 0 : ab.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the internal reader (aboffset, aboffsetEnd) to the body data for the given id
|
* 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
|
* 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),
|
* (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.
|
* 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
|
* Current implementation always returns false for not-found, however, for
|
||||||
* regression testing, at least for the case that is most likely a bug
|
* regression testing, at least for the case that is most likely a bug
|
||||||
* (node found but marked as deleted = ready for garbage collection
|
* (node found but marked as deleted = ready for garbage collection
|
||||||
@ -98,10 +89,8 @@ public class MicroCache extends ByteDataWriter
|
|||||||
*
|
*
|
||||||
* @return true if id was found
|
* @return true if id was found
|
||||||
*/
|
*/
|
||||||
public final boolean getAndClear( long id64 )
|
public final boolean getAndClear(long id64) {
|
||||||
{
|
if (size == 0) {
|
||||||
if ( size == 0 )
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int id = shrinkId(id64);
|
int id = shrinkId(id64);
|
||||||
@ -109,27 +98,22 @@ public class MicroCache extends ByteDataWriter
|
|||||||
int offset = p2size;
|
int offset = p2size;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
while (offset > 0)
|
while (offset > 0) {
|
||||||
{
|
|
||||||
int nn = n + offset;
|
int nn = n + offset;
|
||||||
if ( nn < size && a[nn] <= id )
|
if (nn < size && a[nn] <= id) {
|
||||||
{
|
|
||||||
n = nn;
|
n = nn;
|
||||||
}
|
}
|
||||||
offset >>= 1;
|
offset >>= 1;
|
||||||
}
|
}
|
||||||
if ( a[n] == id )
|
if (a[n] == id) {
|
||||||
{
|
if ((fapos[n] & 0x80000000) == 0) {
|
||||||
if ( ( fapos[n] & 0x80000000 ) == 0 )
|
|
||||||
{
|
|
||||||
aboffset = startPos(n);
|
aboffset = startPos(n);
|
||||||
aboffsetEnd = fapos[n];
|
aboffsetEnd = fapos[n];
|
||||||
fapos[n] |= 0x80000000; // mark deleted
|
fapos[n] |= 0x80000000; // mark deleted
|
||||||
delbytes += aboffsetEnd - aboffset;
|
delbytes += aboffsetEnd - aboffset;
|
||||||
delcount++;
|
delcount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
} else // .. marked as deleted
|
||||||
else // .. marked as deleted
|
|
||||||
{
|
{
|
||||||
// throw new RuntimeException( "MicroCache: node already consumed: id=" + id );
|
// throw new RuntimeException( "MicroCache: node already consumed: id=" + id );
|
||||||
}
|
}
|
||||||
@ -137,39 +121,31 @@ public class MicroCache extends ByteDataWriter
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final int startPos( int n )
|
protected final int startPos(int n) {
|
||||||
{
|
|
||||||
return n > 0 ? fapos[n - 1] & 0x7fffffff : 0;
|
return n > 0 ? fapos[n - 1] & 0x7fffffff : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int collect( int threshold )
|
public final int collect(int threshold) {
|
||||||
{
|
if (delcount <= threshold) {
|
||||||
if ( delcount <= threshold )
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virgin = false;
|
virgin = false;
|
||||||
|
|
||||||
int nsize = size - delcount;
|
int nsize = size - delcount;
|
||||||
if ( nsize == 0 )
|
if (nsize == 0) {
|
||||||
{
|
|
||||||
faid = null;
|
faid = null;
|
||||||
fapos = null;
|
fapos = null;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
int[] nfaid = new int[nsize];
|
int[] nfaid = new int[nsize];
|
||||||
int[] nfapos = new int[nsize];
|
int[] nfapos = new int[nsize];
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
byte[] nab = new byte[ab.length - delbytes];
|
byte[] nab = new byte[ab.length - delbytes];
|
||||||
int nab_off = 0;
|
int nab_off = 0;
|
||||||
for ( int i = 0; i < size; i++ )
|
for (int i = 0; i < size; i++) {
|
||||||
{
|
|
||||||
int pos = fapos[i];
|
int pos = fapos[i];
|
||||||
if ( ( pos & 0x80000000 ) == 0 )
|
if ((pos & 0x80000000) == 0) {
|
||||||
{
|
|
||||||
int start = startPos(i);
|
int start = startPos(i);
|
||||||
int end = fapos[i];
|
int end = fapos[i];
|
||||||
int len = end - start;
|
int len = end - start;
|
||||||
@ -189,13 +165,11 @@ public class MicroCache extends ByteDataWriter
|
|||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void unGhost()
|
public final void unGhost() {
|
||||||
{
|
|
||||||
ghost = false;
|
ghost = false;
|
||||||
delcount = 0;
|
delcount = 0;
|
||||||
delbytes = 0;
|
delbytes = 0;
|
||||||
for ( int i = 0; i < size; i++ )
|
for (int i = 0; i < size; i++) {
|
||||||
{
|
|
||||||
fapos[i] &= 0x7fffffff; // clear deleted flags
|
fapos[i] &= 0x7fffffff; // clear deleted flags
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,8 +177,7 @@ public class MicroCache extends ByteDataWriter
|
|||||||
/**
|
/**
|
||||||
* @return the 64-bit global id for the given cache-position
|
* @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];
|
int id32 = faid[i];
|
||||||
return expandId(id32);
|
return expandId(id32);
|
||||||
}
|
}
|
||||||
@ -214,8 +187,7 @@ public class MicroCache extends ByteDataWriter
|
|||||||
*
|
*
|
||||||
* @see #shrinkId
|
* @see #shrinkId
|
||||||
*/
|
*/
|
||||||
public long expandId( int id32 )
|
public long expandId(int id32) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("expandId for empty cache");
|
throw new IllegalArgumentException("expandId for empty cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,28 +196,24 @@ public class MicroCache extends ByteDataWriter
|
|||||||
*
|
*
|
||||||
* @see #expandId
|
* @see #expandId
|
||||||
*/
|
*/
|
||||||
public int shrinkId( long id64 )
|
public int shrinkId(long id64) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("shrinkId for empty cache");
|
throw new IllegalArgumentException("shrinkId for empty cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the given lon/lat position is internal for that micro-cache
|
* @return true if the given lon/lat position is internal for that micro-cache
|
||||||
*/
|
*/
|
||||||
public boolean isInternal( int ilon, int ilat )
|
public boolean isInternal(int ilon, int ilat) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("isInternal for empty cache");
|
throw new IllegalArgumentException("isInternal for empty cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (stasticially) encode the micro-cache into the format used in the datafiles
|
* (stasticially) encode the micro-cache into the format used in the datafiles
|
||||||
*
|
*
|
||||||
* @param buffer
|
* @param buffer byte array to encode into (considered big enough)
|
||||||
* byte array to encode into (considered big enough)
|
|
||||||
* @return the size of the encoded data
|
* @return the size of the encoded data
|
||||||
*/
|
*/
|
||||||
public int encodeMicroCache( byte[] buffer )
|
public int encodeMicroCache(byte[] buffer) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("encodeMicroCache for empty cache");
|
throw new IllegalArgumentException("encodeMicroCache for empty cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,11 +222,9 @@ public class MicroCache extends ByteDataWriter
|
|||||||
*
|
*
|
||||||
* @return null if equals, else a diff-report
|
* @return null if equals, else a diff-report
|
||||||
*/
|
*/
|
||||||
public String compareWith( MicroCache mc )
|
public String compareWith(MicroCache mc) {
|
||||||
{
|
|
||||||
String msg = _compareWith(mc);
|
String msg = _compareWith(mc);
|
||||||
if ( msg != null )
|
if (msg != null) {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder(msg);
|
StringBuilder sb = new StringBuilder(msg);
|
||||||
sb.append("\nencode cache:\n").append(summary());
|
sb.append("\nencode cache:\n").append(summary());
|
||||||
sb.append("\ndecode cache:\n").append(mc.summary());
|
sb.append("\ndecode cache:\n").append(mc.summary());
|
||||||
@ -267,96 +233,75 @@ public class MicroCache extends ByteDataWriter
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String summary()
|
private String summary() {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder("size=" + size + " aboffset=" + aboffset);
|
StringBuilder sb = new StringBuilder("size=" + size + " aboffset=" + aboffset);
|
||||||
for ( int i = 0; i < size; i++ )
|
for (int i = 0; i < size; i++) {
|
||||||
{
|
|
||||||
sb.append("\nidx=" + i + " faid=" + faid[i] + " fapos=" + fapos[i]);
|
sb.append("\nidx=" + i + " faid=" + faid[i] + " fapos=" + fapos[i]);
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String _compareWith( MicroCache mc )
|
private String _compareWith(MicroCache mc) {
|
||||||
{
|
if (size != mc.size) {
|
||||||
if ( size != mc.size )
|
|
||||||
{
|
|
||||||
return "size missmatch: " + size + "->" + mc.size;
|
return "size missmatch: " + size + "->" + mc.size;
|
||||||
}
|
}
|
||||||
for ( int i = 0; i < size; i++ )
|
for (int i = 0; i < size; i++) {
|
||||||
{
|
if (faid[i] != mc.faid[i]) {
|
||||||
if ( faid[i] != mc.faid[i] )
|
|
||||||
{
|
|
||||||
return "faid missmatch at index " + i + ":" + 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 start = i > 0 ? fapos[i - 1] : 0;
|
||||||
int end = fapos[i] < mc.fapos[i] ? fapos[i] : mc.fapos[i];
|
int end = fapos[i] < mc.fapos[i] ? fapos[i] : mc.fapos[i];
|
||||||
int len = end - start;
|
int len = end - start;
|
||||||
for ( int offset = 0; offset < len; offset++ )
|
for (int offset = 0; offset < len; offset++) {
|
||||||
{
|
if (mc.ab.length <= start + offset) {
|
||||||
if ( mc.ab.length <= start + offset )
|
|
||||||
{
|
|
||||||
return "data buffer too small";
|
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;
|
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];
|
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 "datasize missmatch: " + aboffset + "->" + mc.aboffset;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void calcDelta( MicroCache mc1, MicroCache mc2 )
|
public void calcDelta(MicroCache mc1, MicroCache mc2) {
|
||||||
{
|
|
||||||
int idx1 = 0;
|
int idx1 = 0;
|
||||||
int idx2 = 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 id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
|
||||||
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
|
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
|
||||||
int id;
|
int id;
|
||||||
if ( id1 >= id2 )
|
if (id1 >= id2) {
|
||||||
{
|
|
||||||
id = id2;
|
id = id2;
|
||||||
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
|
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
|
||||||
int len2 = mc2.fapos[idx2++] - start2;
|
int len2 = mc2.fapos[idx2++] - start2;
|
||||||
|
|
||||||
if ( id1 == id2 )
|
if (id1 == id2) {
|
||||||
{
|
|
||||||
// id exists in both caches, compare data
|
// id exists in both caches, compare data
|
||||||
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
||||||
int len1 = mc1.fapos[idx1++] - start1;
|
int len1 = mc1.fapos[idx1++] - start1;
|
||||||
if ( len1 == len2 )
|
if (len1 == len2) {
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while( i<len1 )
|
while (i < len1) {
|
||||||
{
|
if (mc1.ab[start1 + i] != mc2.ab[start2 + i]) {
|
||||||
if ( mc1.ab[start1+i] != mc2.ab[start2+i] )
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if ( i == len1 )
|
if (i == len1) {
|
||||||
{
|
|
||||||
continue; // same data -> do nothing
|
continue; // same data -> do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write(mc2.ab, start2, len2);
|
write(mc2.ab, start2, len2);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
idx1++;
|
idx1++;
|
||||||
id = id1; // deleted node
|
id = id1; // deleted node
|
||||||
}
|
}
|
||||||
@ -366,21 +311,18 @@ public class MicroCache extends ByteDataWriter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDelta( MicroCache mc1, MicroCache mc2, boolean keepEmptyNodes )
|
public void addDelta(MicroCache mc1, MicroCache mc2, boolean keepEmptyNodes) {
|
||||||
{
|
|
||||||
int idx1 = 0;
|
int idx1 = 0;
|
||||||
int idx2 = 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 id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
|
||||||
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : 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 start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
|
||||||
int len2 = mc2.fapos[idx2++] - start2;
|
int len2 = mc2.fapos[idx2++] - start2;
|
||||||
if ( keepEmptyNodes || len2 > 0 )
|
if (keepEmptyNodes || len2 > 0) {
|
||||||
{
|
|
||||||
write(mc2.ab, start2, len2);
|
write(mc2.ab, start2, len2);
|
||||||
fapos[size] = aboffset;
|
fapos[size] = aboffset;
|
||||||
faid[size++] = id2;
|
faid[size++] = id2;
|
||||||
@ -389,8 +331,7 @@ public class MicroCache extends ByteDataWriter
|
|||||||
{
|
{
|
||||||
idx1++;
|
idx1++;
|
||||||
}
|
}
|
||||||
}
|
} else // use data from base file
|
||||||
else // use data from base file
|
|
||||||
{
|
{
|
||||||
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
||||||
int len1 = mc1.fapos[idx1++] - start1;
|
int len1 = mc1.fapos[idx1++] - start1;
|
||||||
|
|||||||
@ -9,14 +9,12 @@ import btools.util.IByteArrayUnifier;
|
|||||||
* MicroCache2 is the new format that uses statistical encoding and
|
* MicroCache2 is the new format that uses statistical encoding and
|
||||||
* is able to do access filtering and waypoint matching during encoding
|
* 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 lonBase;
|
||||||
private int latBase;
|
private int latBase;
|
||||||
private int cellsize;
|
private int cellsize;
|
||||||
|
|
||||||
public MicroCache2( int size, byte[] databuffer, int lonIdx, int latIdx, int divisor )
|
public MicroCache2(int size, byte[] databuffer, int lonIdx, int latIdx, int divisor) {
|
||||||
{
|
|
||||||
super(databuffer); // sets ab=databuffer, aboffset=0
|
super(databuffer); // sets ab=databuffer, aboffset=0
|
||||||
|
|
||||||
faid = new int[size];
|
faid = new int[size];
|
||||||
@ -27,15 +25,13 @@ public final class MicroCache2 extends MicroCache
|
|||||||
latBase = latIdx * cellsize;
|
latBase = latIdx * cellsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] readUnified( int len, IByteArrayUnifier u )
|
public byte[] readUnified(int len, IByteArrayUnifier u) {
|
||||||
{
|
|
||||||
byte[] b = u.unify(ab, aboffset, len);
|
byte[] b = u.unify(ab, aboffset, len);
|
||||||
aboffset += len;
|
aboffset += len;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MicroCache2( StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher )
|
public MicroCache2(StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher) {
|
||||||
{
|
|
||||||
super(null);
|
super(null);
|
||||||
cellsize = 1000000 / divisor;
|
cellsize = 1000000 / divisor;
|
||||||
lonBase = lonIdx * cellsize;
|
lonBase = lonIdx * cellsize;
|
||||||
@ -54,16 +50,15 @@ public final class MicroCache2 extends MicroCache
|
|||||||
fapos = size > dataBuffers.ibuf3.length ? new int[size] : dataBuffers.ibuf3;
|
fapos = size > dataBuffers.ibuf3.length ? new int[size] : dataBuffers.ibuf3;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int[] alon = size > dataBuffers.alon.length ? new int[size] : dataBuffers.alon;
|
int[] alon = size > dataBuffers.alon.length ? new int[size] : dataBuffers.alon;
|
||||||
int[] alat = size > dataBuffers.alat.length ? new int[size] : dataBuffers.alat;
|
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++ )
|
for (int n = 0; n < size; n++) {
|
||||||
{
|
|
||||||
long id64 = expandId(faid[n]);
|
long id64 = expandId(faid[n]);
|
||||||
alon[n] = (int) (id64 >> 32);
|
alon[n] = (int) (id64 >> 32);
|
||||||
alat[n] = (int) (id64 & 0xffffffff);
|
alat[n] = (int) (id64 & 0xffffffff);
|
||||||
@ -88,21 +83,18 @@ public final class MicroCache2 extends MicroCache
|
|||||||
// future escapes (turn restrictions?)
|
// future escapes (turn restrictions?)
|
||||||
short trExceptions = 0;
|
short trExceptions = 0;
|
||||||
int featureId = bc.decodeVarBits();
|
int featureId = bc.decodeVarBits();
|
||||||
if ( featureId == 13 )
|
if (featureId == 13) {
|
||||||
{
|
|
||||||
fapos[n] = aboffset;
|
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)
|
continue; // empty node escape (delta files only)
|
||||||
}
|
}
|
||||||
while( featureId != 0 )
|
while (featureId != 0) {
|
||||||
{
|
|
||||||
int bitsize = bc.decodeNoisyNumber(5);
|
int bitsize = bc.decodeNoisyNumber(5);
|
||||||
|
|
||||||
if (featureId == 2) // exceptions to turn-restriction
|
if (featureId == 2) // exceptions to turn-restriction
|
||||||
{
|
{
|
||||||
trExceptions = (short) bc.decodeBounded(1023);
|
trExceptions = (short) bc.decodeBounded(1023);
|
||||||
}
|
} else if (featureId == 1) // turn-restriction
|
||||||
else if ( featureId == 1 ) // turn-restriction
|
|
||||||
{
|
{
|
||||||
writeBoolean(true);
|
writeBoolean(true);
|
||||||
writeShort(trExceptions); // exceptions from previous feature
|
writeShort(trExceptions); // exceptions from previous feature
|
||||||
@ -113,9 +105,7 @@ public final class MicroCache2 extends MicroCache
|
|||||||
writeInt(ilat + bc.decodeNoisyDiff(10)); // fromLat
|
writeInt(ilat + bc.decodeNoisyDiff(10)); // fromLat
|
||||||
writeInt(ilon + bc.decodeNoisyDiff(10)); // toLon
|
writeInt(ilon + bc.decodeNoisyDiff(10)); // toLon
|
||||||
writeInt(ilat + bc.decodeNoisyDiff(10)); // toLat
|
writeInt(ilat + bc.decodeNoisyDiff(10)); // toLat
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
|
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
|
||||||
}
|
}
|
||||||
featureId = bc.decodeVarBits();
|
featureId = bc.decodeVarBits();
|
||||||
@ -128,9 +118,9 @@ public final class MicroCache2 extends MicroCache
|
|||||||
writeVarBytes(nodeTags == null ? null : nodeTags.data);
|
writeVarBytes(nodeTags == null ? null : nodeTags.data);
|
||||||
|
|
||||||
int links = bc.decodeNoisyNumber(1);
|
int links = bc.decodeNoisyNumber(1);
|
||||||
if ( debug ) System.out.println( "*** decoding node " + ilon + "/" + ilat + " with links=" + links );
|
if (debug)
|
||||||
for( int li=0; li<links; li++ )
|
System.out.println("*** decoding node " + ilon + "/" + ilat + " with links=" + links);
|
||||||
{
|
for (int li = 0; li < links; li++) {
|
||||||
int sizeoffset = 0;
|
int sizeoffset = 0;
|
||||||
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
|
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
|
||||||
|
|
||||||
@ -142,20 +132,18 @@ public final class MicroCache2 extends MicroCache
|
|||||||
{
|
{
|
||||||
dlon_remaining = alon[nodeIdx] - ilon;
|
dlon_remaining = alon[nodeIdx] - ilon;
|
||||||
dlat_remaining = alat[nodeIdx] - ilat;
|
dlat_remaining = alat[nodeIdx] - ilat;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
isReverse = bc.decodeBit();
|
isReverse = bc.decodeBit();
|
||||||
dlon_remaining = extLonDiff.decodeSignedValue();
|
dlon_remaining = extLonDiff.decodeSignedValue();
|
||||||
dlat_remaining = extLatDiff.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();
|
TagValueWrapper wayTags = wayTagCoder.decodeTagValueSet();
|
||||||
|
|
||||||
boolean linkValid = wayTags != null || wayValidator == null;
|
boolean linkValid = wayTags != null || wayValidator == null;
|
||||||
if ( linkValid )
|
if (linkValid) {
|
||||||
{
|
|
||||||
int startPointer = aboffset;
|
int startPointer = aboffset;
|
||||||
sizeoffset = writeSizePlaceHolder();
|
sizeoffset = writeSizePlaceHolder();
|
||||||
|
|
||||||
@ -177,10 +165,8 @@ public final class MicroCache2 extends MicroCache
|
|||||||
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
||||||
int ilontarget = ilon + dlon_remaining;
|
int ilontarget = ilon + dlon_remaining;
|
||||||
int ilattarget = ilat + dlat_remaining;
|
int ilattarget = ilat + dlat_remaining;
|
||||||
if ( matcher != null )
|
if (matcher != null) {
|
||||||
{
|
if (!matcher.start(ilon, ilat, ilontarget, ilattarget)) {
|
||||||
if ( !matcher.start( ilon, ilat, ilontarget, ilattarget ) )
|
|
||||||
{
|
|
||||||
matcher = null;
|
matcher = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,27 +174,25 @@ public final class MicroCache2 extends MicroCache
|
|||||||
int transcount = bc.decodeVarBits();
|
int transcount = bc.decodeVarBits();
|
||||||
if (debug) System.out.println("*** decoding geometry with count=" + transcount);
|
if (debug) System.out.println("*** decoding geometry with count=" + transcount);
|
||||||
int count = transcount + 1;
|
int count = transcount + 1;
|
||||||
for( int i=0; i<transcount; i++ )
|
for (int i = 0; i < transcount; i++) {
|
||||||
{
|
|
||||||
int dlon = bc.decodePredictedValue(dlon_remaining / count);
|
int dlon = bc.decodePredictedValue(dlon_remaining / count);
|
||||||
int dlat = bc.decodePredictedValue(dlat_remaining / count);
|
int dlat = bc.decodePredictedValue(dlat_remaining / count);
|
||||||
dlon_remaining -= dlon;
|
dlon_remaining -= dlon;
|
||||||
dlat_remaining -= dlat;
|
dlat_remaining -= dlat;
|
||||||
count--;
|
count--;
|
||||||
int elediff = transEleDiff.decodeSignedValue();
|
int elediff = transEleDiff.decodeSignedValue();
|
||||||
if ( wayTags != null )
|
if (wayTags != null) {
|
||||||
{
|
|
||||||
writeVarLengthSigned(dlon);
|
writeVarLengthSigned(dlon);
|
||||||
writeVarLengthSigned(dlat);
|
writeVarLengthSigned(dlat);
|
||||||
writeVarLengthSigned(elediff);
|
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 )
|
if (linkValid) {
|
||||||
{
|
|
||||||
injectSize(sizeoffset);
|
injectSize(sizeoffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,11 +202,9 @@ public final class MicroCache2 extends MicroCache
|
|||||||
// calculate final data size
|
// calculate final data size
|
||||||
int finalsize = 0;
|
int finalsize = 0;
|
||||||
int startpos = 0;
|
int startpos = 0;
|
||||||
for( int i=0; i<size; i++ )
|
for (int i = 0; i < size; i++) {
|
||||||
{
|
|
||||||
int endpos = fapos[i];
|
int endpos = fapos[i];
|
||||||
if ( ( validBits[ i >> 5 ] & (1 << i ) ) != 0 )
|
if ((validBits[i >> 5] & (1 << i)) != 0) {
|
||||||
{
|
|
||||||
finaldatasize += endpos - startpos;
|
finaldatasize += endpos - startpos;
|
||||||
finalsize++;
|
finalsize++;
|
||||||
}
|
}
|
||||||
@ -240,11 +222,9 @@ public final class MicroCache2 extends MicroCache
|
|||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
startpos = 0;
|
startpos = 0;
|
||||||
for ( int n = 0; n < sizeOld; n++ )
|
for (int n = 0; n < sizeOld; n++) {
|
||||||
{
|
|
||||||
int endpos = faposOld[n];
|
int endpos = faposOld[n];
|
||||||
if ( ( validBits[ n >> 5 ] & (1 << n ) ) != 0 )
|
if ((validBits[n >> 5] & (1 << n)) != 0) {
|
||||||
{
|
|
||||||
int len = endpos - startpos;
|
int len = endpos - startpos;
|
||||||
System.arraycopy(abOld, startpos, ab, aboffset, len);
|
System.arraycopy(abOld, startpos, ab, aboffset, len);
|
||||||
if (debug)
|
if (debug)
|
||||||
@ -255,8 +235,7 @@ public final class MicroCache2 extends MicroCache
|
|||||||
if (debug)
|
if (debug)
|
||||||
System.out.println("*** appending " + cnt + " reverse links for node " + n);
|
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 nodeIdx = reverseLinks.getDataElement();
|
||||||
int sizeoffset = writeSizePlaceHolder();
|
int sizeoffset = writeSizePlaceHolder();
|
||||||
writeVarLengthSigned(alon[nodeIdx] - alon[n]);
|
writeVarLengthSigned(alon[nodeIdx] - alon[n]);
|
||||||
@ -274,13 +253,11 @@ public final class MicroCache2 extends MicroCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long expandId( int id32 )
|
public long expandId(int id32) {
|
||||||
{
|
|
||||||
int dlon = 0;
|
int dlon = 0;
|
||||||
int dlat = 0;
|
int dlat = 0;
|
||||||
|
|
||||||
for( int bm = 1; bm < 0x8000; bm <<= 1 )
|
for (int bm = 1; bm < 0x8000; bm <<= 1) {
|
||||||
{
|
|
||||||
if ((id32 & 1) != 0) dlon |= bm;
|
if ((id32 & 1) != 0) dlon |= bm;
|
||||||
if ((id32 & 2) != 0) dlat |= bm;
|
if ((id32 & 2) != 0) dlat |= bm;
|
||||||
id32 >>= 2;
|
id32 >>= 2;
|
||||||
@ -293,16 +270,14 @@ public final class MicroCache2 extends MicroCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int shrinkId( long id64 )
|
public int shrinkId(long id64) {
|
||||||
{
|
|
||||||
int lon32 = (int) (id64 >> 32);
|
int lon32 = (int) (id64 >> 32);
|
||||||
int lat32 = (int) (id64 & 0xffffffff);
|
int lat32 = (int) (id64 & 0xffffffff);
|
||||||
int dlon = lon32 - lonBase;
|
int dlon = lon32 - lonBase;
|
||||||
int dlat = lat32 - latBase;
|
int dlat = lat32 - latBase;
|
||||||
int id32 = 0;
|
int id32 = 0;
|
||||||
|
|
||||||
for( int bm = 0x4000; bm > 0; bm >>= 1 )
|
for (int bm = 0x4000; bm > 0; bm >>= 1) {
|
||||||
{
|
|
||||||
id32 <<= 2;
|
id32 <<= 2;
|
||||||
if ((dlon & bm) != 0) id32 |= 1;
|
if ((dlon & bm) != 0) id32 |= 1;
|
||||||
if ((dlat & bm) != 0) id32 |= 2;
|
if ((dlat & bm) != 0) id32 |= 2;
|
||||||
@ -311,15 +286,13 @@ public final class MicroCache2 extends MicroCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInternal( int ilon, int ilat )
|
public boolean isInternal(int ilon, int ilat) {
|
||||||
{
|
|
||||||
return ilon >= lonBase && ilon < lonBase + cellsize
|
return ilon >= lonBase && ilon < lonBase + cellsize
|
||||||
&& ilat >= latBase && ilat < latBase + cellsize;
|
&& ilat >= latBase && ilat < latBase + cellsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int encodeMicroCache( byte[] buffer )
|
public int encodeMicroCache(byte[] buffer) {
|
||||||
{
|
|
||||||
HashMap<Long, Integer> idMap = new HashMap<Long, Integer>();
|
HashMap<Long, Integer> idMap = new HashMap<Long, Integer>();
|
||||||
for (int n = 0; n < size; n++) // loop over nodes
|
for (int n = 0; n < size; n++) // loop over nodes
|
||||||
{
|
{
|
||||||
@ -376,24 +349,22 @@ public final class MicroCache2 extends MicroCache
|
|||||||
{
|
{
|
||||||
aboffset = startPos(n);
|
aboffset = startPos(n);
|
||||||
aboffsetEnd = fapos[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]);
|
long id64 = expandId(faid[n]);
|
||||||
int ilon = (int) (id64 >> 32);
|
int ilon = (int) (id64 >> 32);
|
||||||
int ilat = (int) (id64 & 0xffffffff);
|
int ilat = (int) (id64 & 0xffffffff);
|
||||||
|
|
||||||
if ( aboffset == aboffsetEnd )
|
if (aboffset == aboffsetEnd) {
|
||||||
{
|
|
||||||
bc.encodeVarBits(13); // empty node escape (delta files only)
|
bc.encodeVarBits(13); // empty node escape (delta files only)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write turn restrictions
|
// write turn restrictions
|
||||||
while( readBoolean() )
|
while (readBoolean()) {
|
||||||
{
|
|
||||||
short exceptions = readShort(); // except bikes, psv, ...
|
short exceptions = readShort(); // except bikes, psv, ...
|
||||||
if ( exceptions != 0 )
|
if (exceptions != 0) {
|
||||||
{
|
|
||||||
bc.encodeVarBits(2); // 2 = tr exceptions
|
bc.encodeVarBits(2); // 2 = tr exceptions
|
||||||
bc.encodeNoisyNumber(10, 5); // bit-count
|
bc.encodeNoisyNumber(10, 5); // bit-count
|
||||||
bc.encodeBounded(1023, exceptions & 1023);
|
bc.encodeBounded(1023, exceptions & 1023);
|
||||||
@ -437,8 +408,7 @@ public final class MicroCache2 extends MicroCache
|
|||||||
boolean isReverse = (sizecode & 1) != 0;
|
boolean isReverse = (sizecode & 1) != 0;
|
||||||
int descSize = sizecode >> 1;
|
int descSize = sizecode >> 1;
|
||||||
byte[] description = null;
|
byte[] description = null;
|
||||||
if ( descSize > 0 )
|
if (descSize > 0) {
|
||||||
{
|
|
||||||
description = new byte[descSize];
|
description = new byte[descSize];
|
||||||
readFully(description);
|
readFully(description);
|
||||||
}
|
}
|
||||||
@ -447,25 +417,23 @@ public final class MicroCache2 extends MicroCache
|
|||||||
Integer idx = idMap.get(Long.valueOf(link64));
|
Integer idx = idMap.get(Long.valueOf(link64));
|
||||||
boolean isInternal = idx != null;
|
boolean isInternal = idx != null;
|
||||||
|
|
||||||
if ( isReverse && isInternal )
|
if (isReverse && isInternal) {
|
||||||
{
|
if (dodebug)
|
||||||
if ( dodebug ) System.out.println( "*** NOT encoding link reverse=" + isReverse + " internal=" + isInternal );
|
System.out.println("*** NOT encoding link reverse=" + isReverse + " internal=" + isInternal);
|
||||||
netdatasize -= aboffset - startPointer;
|
netdatasize -= aboffset - startPointer;
|
||||||
continue; // do not encode internal reverse links
|
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++;
|
nlinks++;
|
||||||
|
|
||||||
if ( isInternal )
|
if (isInternal) {
|
||||||
{
|
|
||||||
int nodeIdx = idx.intValue();
|
int nodeIdx = idx.intValue();
|
||||||
if (dodebug) System.out.println("*** target nodeIdx=" + nodeIdx);
|
if (dodebug) System.out.println("*** target nodeIdx=" + nodeIdx);
|
||||||
if (nodeIdx == n) throw new RuntimeException("ups: self ref?");
|
if (nodeIdx == n) throw new RuntimeException("ups: self ref?");
|
||||||
nodeIdxDiff.encodeSignedValue(nodeIdx - n);
|
nodeIdxDiff.encodeSignedValue(nodeIdx - n);
|
||||||
if (dostats) bc.assignBits("nodeIdx");
|
if (dostats) bc.assignBits("nodeIdx");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nodeIdxDiff.encodeSignedValue(0);
|
nodeIdxDiff.encodeSignedValue(0);
|
||||||
bc.encodeBit(isReverse);
|
bc.encodeBit(isReverse);
|
||||||
extLonDiff.encodeSignedValue(ilonlink - ilon);
|
extLonDiff.encodeSignedValue(ilonlink - ilon);
|
||||||
@ -475,8 +443,7 @@ public final class MicroCache2 extends MicroCache
|
|||||||
wayTagCoder.encodeTagValueSet(description);
|
wayTagCoder.encodeTagValueSet(description);
|
||||||
if (dostats) bc.assignBits("wayDescIdx");
|
if (dostats) bc.assignBits("wayDescIdx");
|
||||||
|
|
||||||
if ( !isReverse )
|
if (!isReverse) {
|
||||||
{
|
|
||||||
byte[] geometry = readDataUntil(endPointer);
|
byte[] geometry = readDataUntil(endPointer);
|
||||||
// write transition nodes
|
// write transition nodes
|
||||||
int count = transCounts.getNext();
|
int count = transCounts.getNext();
|
||||||
@ -484,14 +451,12 @@ public final class MicroCache2 extends MicroCache
|
|||||||
bc.encodeVarBits(count++);
|
bc.encodeVarBits(count++);
|
||||||
if (dostats) bc.assignBits("transcount");
|
if (dostats) bc.assignBits("transcount");
|
||||||
int transcount = 0;
|
int transcount = 0;
|
||||||
if ( geometry != null )
|
if (geometry != null) {
|
||||||
{
|
|
||||||
int dlon_remaining = ilonlink - ilon;
|
int dlon_remaining = ilonlink - ilon;
|
||||||
int dlat_remaining = ilatlink - ilat;
|
int dlat_remaining = ilatlink - ilat;
|
||||||
|
|
||||||
ByteDataReader r = new ByteDataReader(geometry);
|
ByteDataReader r = new ByteDataReader(geometry);
|
||||||
while ( r.hasMoreData() )
|
while (r.hasMoreData()) {
|
||||||
{
|
|
||||||
transcount++;
|
transcount++;
|
||||||
|
|
||||||
int dlon = r.readVarLengthSigned();
|
int dlon = r.readVarLengthSigned();
|
||||||
@ -511,8 +476,7 @@ public final class MicroCache2 extends MicroCache
|
|||||||
}
|
}
|
||||||
linkCounts.add(nlinks);
|
linkCounts.add(nlinks);
|
||||||
}
|
}
|
||||||
if ( pass == 3 )
|
if (pass == 3) {
|
||||||
{
|
|
||||||
return bc.closeAndGetEncodedLength();
|
return bc.closeAndGetEncodedLength();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,11 @@ package btools.codec;
|
|||||||
* Encoder/Decoder for signed integers that automatically detects the typical
|
* Encoder/Decoder for signed integers that automatically detects the typical
|
||||||
* range of these numbers to determine a noisy-bit count as a very simple
|
* range of these numbers to determine a noisy-bit count as a very simple
|
||||||
* dictionary
|
* dictionary
|
||||||
*
|
* <p>
|
||||||
* Adapted for 3-pass encoding (counters -> statistics -> encoding )
|
* Adapted for 3-pass encoding (counters -> statistics -> encoding )
|
||||||
* but doesn't do anything at pass1
|
* but doesn't do anything at pass1
|
||||||
*/
|
*/
|
||||||
public final class NoisyDiffCoder
|
public final class NoisyDiffCoder {
|
||||||
{
|
|
||||||
private int tot;
|
private int tot;
|
||||||
private int[] freqs;
|
private int[] freqs;
|
||||||
private int noisybits;
|
private int noisybits;
|
||||||
@ -19,8 +18,7 @@ public final class NoisyDiffCoder
|
|||||||
/**
|
/**
|
||||||
* Create a decoder and read the noisy-bit count from the gibe context
|
* Create a decoder and read the noisy-bit count from the gibe context
|
||||||
*/
|
*/
|
||||||
public NoisyDiffCoder( StatCoderContext bc )
|
public NoisyDiffCoder(StatCoderContext bc) {
|
||||||
{
|
|
||||||
noisybits = bc.decodeVarBits();
|
noisybits = bc.decodeVarBits();
|
||||||
this.bc = bc;
|
this.bc = bc;
|
||||||
}
|
}
|
||||||
@ -28,21 +26,16 @@ public final class NoisyDiffCoder
|
|||||||
/**
|
/**
|
||||||
* Create an encoder for 3-pass-encoding
|
* Create an encoder for 3-pass-encoding
|
||||||
*/
|
*/
|
||||||
public NoisyDiffCoder()
|
public NoisyDiffCoder() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* encodes a signed int (pass3 only, stats collection in pass2)
|
* encodes a signed int (pass3 only, stats collection in pass2)
|
||||||
*/
|
*/
|
||||||
public void encodeSignedValue( int value )
|
public void encodeSignedValue(int value) {
|
||||||
{
|
if (pass == 3) {
|
||||||
if ( pass == 3 )
|
|
||||||
{
|
|
||||||
bc.encodeNoisyDiff(value, noisybits);
|
bc.encodeNoisyDiff(value, noisybits);
|
||||||
}
|
} else if (pass == 2) {
|
||||||
else if ( pass == 2 )
|
|
||||||
{
|
|
||||||
count(value < 0 ? -value : value);
|
count(value < 0 ? -value : value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,8 +43,7 @@ public final class NoisyDiffCoder
|
|||||||
/**
|
/**
|
||||||
* decodes a signed int
|
* decodes a signed int
|
||||||
*/
|
*/
|
||||||
public int decodeSignedValue()
|
public int decodeSignedValue() {
|
||||||
{
|
|
||||||
return bc.decodeNoisyDiff(noisybits);
|
return bc.decodeNoisyDiff(noisybits);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,13 +51,10 @@ public final class NoisyDiffCoder
|
|||||||
* Starts a new encoding pass and (in pass3) calculates the noisy-bit count
|
* 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
|
* from the stats collected in pass2 and writes that to the given context
|
||||||
*/
|
*/
|
||||||
public void encodeDictionary( StatCoderContext bc )
|
public void encodeDictionary(StatCoderContext bc) {
|
||||||
{
|
if (++pass == 3) {
|
||||||
if ( ++pass == 3 )
|
|
||||||
{
|
|
||||||
// how many noisy bits?
|
// how many noisy bits?
|
||||||
for ( noisybits = 0; noisybits < 14 && tot > 0; noisybits++ )
|
for (noisybits = 0; noisybits < 14 && tot > 0; noisybits++) {
|
||||||
{
|
|
||||||
if (freqs[noisybits] < (tot >> 1))
|
if (freqs[noisybits] < (tot >> 1))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -74,13 +63,11 @@ public final class NoisyDiffCoder
|
|||||||
this.bc = bc;
|
this.bc = bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void count( int value )
|
private void count(int value) {
|
||||||
{
|
|
||||||
if (freqs == null)
|
if (freqs == null)
|
||||||
freqs = new int[14];
|
freqs = new int[14];
|
||||||
int bm = 1;
|
int bm = 1;
|
||||||
for ( int i = 0; i < 14; i++ )
|
for (int i = 0; i < 14; i++) {
|
||||||
{
|
|
||||||
if (value < bm)
|
if (value < bm)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
|
|||||||
@ -4,23 +4,19 @@ import java.util.TreeMap;
|
|||||||
|
|
||||||
import btools.util.BitCoderContext;
|
import btools.util.BitCoderContext;
|
||||||
|
|
||||||
public final class StatCoderContext extends BitCoderContext
|
public final class StatCoderContext extends BitCoderContext {
|
||||||
{
|
|
||||||
private static TreeMap<String, long[]> statsPerName;
|
private static TreeMap<String, long[]> statsPerName;
|
||||||
private long lastbitpos = 0;
|
private long lastbitpos = 0;
|
||||||
|
|
||||||
|
|
||||||
private static final int[] noisy_bits = new int[1024];
|
private static final int[] noisy_bits = new int[1024];
|
||||||
|
|
||||||
static
|
static {
|
||||||
{
|
|
||||||
// noisybits lookup
|
// noisybits lookup
|
||||||
for( int i=0; i<1024; i++ )
|
for (int i = 0; i < 1024; i++) {
|
||||||
{
|
|
||||||
int p = i;
|
int p = i;
|
||||||
int noisybits = 0;
|
int noisybits = 0;
|
||||||
while (p > 2)
|
while (p > 2) {
|
||||||
{
|
|
||||||
noisybits++;
|
noisybits++;
|
||||||
p >>= 1;
|
p >>= 1;
|
||||||
}
|
}
|
||||||
@ -29,8 +25,7 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public StatCoderContext( byte[] ab )
|
public StatCoderContext(byte[] ab) {
|
||||||
{
|
|
||||||
super(ab);
|
super(ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,16 +35,13 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #getBitReport
|
* @see #getBitReport
|
||||||
*/
|
*/
|
||||||
public void assignBits( String name )
|
public void assignBits(String name) {
|
||||||
{
|
|
||||||
long bitpos = getWritingBitPosition();
|
long bitpos = getWritingBitPosition();
|
||||||
if ( statsPerName == null )
|
if (statsPerName == null) {
|
||||||
{
|
|
||||||
statsPerName = new TreeMap<String, long[]>();
|
statsPerName = new TreeMap<String, long[]>();
|
||||||
}
|
}
|
||||||
long[] stats = statsPerName.get(name);
|
long[] stats = statsPerName.get(name);
|
||||||
if ( stats == null )
|
if (stats == null) {
|
||||||
{
|
|
||||||
stats = new long[2];
|
stats = new long[2];
|
||||||
statsPerName.put(name, stats);
|
statsPerName.put(name, stats);
|
||||||
}
|
}
|
||||||
@ -63,15 +55,12 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #assignBits
|
* @see #assignBits
|
||||||
*/
|
*/
|
||||||
public static String getBitReport()
|
public static String getBitReport() {
|
||||||
{
|
if (statsPerName == null) {
|
||||||
if ( statsPerName == null )
|
|
||||||
{
|
|
||||||
return "<empty bit report>";
|
return "<empty bit report>";
|
||||||
}
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for ( String name : statsPerName.keySet() )
|
for (String name : statsPerName.keySet()) {
|
||||||
{
|
|
||||||
long[] stats = statsPerName.get(name);
|
long[] stats = statsPerName.get(name);
|
||||||
sb.append(name + " count=" + stats[1] + " bits=" + stats[0] + "\n");
|
sb.append(name + " count=" + stats[1] + " bits=" + stats[0] + "\n");
|
||||||
}
|
}
|
||||||
@ -85,14 +74,11 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #decodeNoisyNumber
|
* @see #decodeNoisyNumber
|
||||||
*/
|
*/
|
||||||
public void encodeNoisyNumber( int value, int noisybits )
|
public void encodeNoisyNumber(int value, int noisybits) {
|
||||||
{
|
if (value < 0) {
|
||||||
if ( value < 0 )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("encodeVarBits expects positive value");
|
throw new IllegalArgumentException("encodeVarBits expects positive value");
|
||||||
}
|
}
|
||||||
if ( noisybits > 0 )
|
if (noisybits > 0) {
|
||||||
{
|
|
||||||
int mask = 0xffffffff >>> (32 - noisybits);
|
int mask = 0xffffffff >>> (32 - noisybits);
|
||||||
encodeBounded(mask, value & mask);
|
encodeBounded(mask, value & mask);
|
||||||
value >>= noisybits;
|
value >>= noisybits;
|
||||||
@ -106,8 +92,7 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #encodeNoisyNumber
|
* @see #encodeNoisyNumber
|
||||||
*/
|
*/
|
||||||
public int decodeNoisyNumber( int noisybits )
|
public int decodeNoisyNumber(int noisybits) {
|
||||||
{
|
|
||||||
int value = decodeBits(noisybits);
|
int value = decodeBits(noisybits);
|
||||||
return value | (decodeVarBits() << noisybits);
|
return value | (decodeVarBits() << noisybits);
|
||||||
}
|
}
|
||||||
@ -118,18 +103,15 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #decodeNoisyDiff
|
* @see #decodeNoisyDiff
|
||||||
*/
|
*/
|
||||||
public void encodeNoisyDiff( int value, int noisybits )
|
public void encodeNoisyDiff(int value, int noisybits) {
|
||||||
{
|
if (noisybits > 0) {
|
||||||
if ( noisybits > 0 )
|
|
||||||
{
|
|
||||||
value += 1 << (noisybits - 1);
|
value += 1 << (noisybits - 1);
|
||||||
int mask = 0xffffffff >>> (32 - noisybits);
|
int mask = 0xffffffff >>> (32 - noisybits);
|
||||||
encodeBounded(mask, value & mask);
|
encodeBounded(mask, value & mask);
|
||||||
value >>= noisybits;
|
value >>= noisybits;
|
||||||
}
|
}
|
||||||
encodeVarBits(value < 0 ? -value : value);
|
encodeVarBits(value < 0 ? -value : value);
|
||||||
if ( value != 0 )
|
if (value != 0) {
|
||||||
{
|
|
||||||
encodeBit(value < 0);
|
encodeBit(value < 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,18 +122,14 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #encodeNoisyDiff
|
* @see #encodeNoisyDiff
|
||||||
*/
|
*/
|
||||||
public int decodeNoisyDiff( int noisybits )
|
public int decodeNoisyDiff(int noisybits) {
|
||||||
{
|
|
||||||
int value = 0;
|
int value = 0;
|
||||||
if ( noisybits > 0 )
|
if (noisybits > 0) {
|
||||||
{
|
|
||||||
value = decodeBits(noisybits) - (1 << (noisybits - 1));
|
value = decodeBits(noisybits) - (1 << (noisybits - 1));
|
||||||
}
|
}
|
||||||
int val2 = decodeVarBits() << noisybits;
|
int val2 = decodeVarBits() << noisybits;
|
||||||
if ( val2 != 0 )
|
if (val2 != 0) {
|
||||||
{
|
if (decodeBit()) {
|
||||||
if ( decodeBit() )
|
|
||||||
{
|
|
||||||
val2 = -val2;
|
val2 = -val2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,13 +142,11 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #decodePredictedValue
|
* @see #decodePredictedValue
|
||||||
*/
|
*/
|
||||||
public void encodePredictedValue( int value, int predictor )
|
public void encodePredictedValue(int value, int predictor) {
|
||||||
{
|
|
||||||
int p = predictor < 0 ? -predictor : predictor;
|
int p = predictor < 0 ? -predictor : predictor;
|
||||||
int noisybits = 0;
|
int noisybits = 0;
|
||||||
|
|
||||||
while (p > 2)
|
while (p > 2) {
|
||||||
{
|
|
||||||
noisybits++;
|
noisybits++;
|
||||||
p >>= 1;
|
p >>= 1;
|
||||||
}
|
}
|
||||||
@ -183,12 +159,10 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
*
|
*
|
||||||
* @see #encodePredictedValue
|
* @see #encodePredictedValue
|
||||||
*/
|
*/
|
||||||
public int decodePredictedValue( int predictor )
|
public int decodePredictedValue(int predictor) {
|
||||||
{
|
|
||||||
int p = predictor < 0 ? -predictor : predictor;
|
int p = predictor < 0 ? -predictor : predictor;
|
||||||
int noisybits = 0;
|
int noisybits = 0;
|
||||||
while (p > 1023)
|
while (p > 1023) {
|
||||||
{
|
|
||||||
noisybits++;
|
noisybits++;
|
||||||
p >>= 1;
|
p >>= 1;
|
||||||
}
|
}
|
||||||
@ -202,29 +176,21 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
* bits per value that only depends on the typical distance between subsequent
|
* bits per value that only depends on the typical distance between subsequent
|
||||||
* values and also benefits
|
* values and also benefits
|
||||||
*
|
*
|
||||||
* @param values
|
* @param values the array to encode
|
||||||
* the array to encode
|
* @param offset position in this array where to start
|
||||||
* @param offset
|
* @param subsize number of values to encode
|
||||||
* position in this array where to start
|
* @param nextbit bitmask with the most significant bit set to 1
|
||||||
* @param subsize
|
* @param mask should be 0
|
||||||
* 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)
|
while (nextbit != 0) {
|
||||||
{
|
|
||||||
encodeBit((values[offset] & nextbit) != 0);
|
encodeBit((values[offset] & nextbit) != 0);
|
||||||
nextbit >>= 1;
|
nextbit >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( nextbit == 0 )
|
if (nextbit == 0) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,10 +200,8 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
// count 0-bit-fraction
|
// count 0-bit-fraction
|
||||||
int i = offset;
|
int i = offset;
|
||||||
int end = subsize + offset;
|
int end = subsize + offset;
|
||||||
for ( ; i < end; i++ )
|
for (; i < end; i++) {
|
||||||
{
|
if ((values[i] & mask) != data) {
|
||||||
if ( ( values[i] & mask ) != data )
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,45 +209,33 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
int size2 = subsize - size1;
|
int size2 = subsize - size1;
|
||||||
|
|
||||||
encodeBounded(subsize, size1);
|
encodeBounded(subsize, size1);
|
||||||
if ( size1 > 0 )
|
if (size1 > 0) {
|
||||||
{
|
|
||||||
encodeSortedArray(values, offset, size1, nextbit >> 1, mask);
|
encodeSortedArray(values, offset, size1, nextbit >> 1, mask);
|
||||||
}
|
}
|
||||||
if ( size2 > 0 )
|
if (size2 > 0) {
|
||||||
{
|
|
||||||
encodeSortedArray(values, i, size2, nextbit >> 1, mask);
|
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
|
* @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 )
|
if (nextbitpos >= 0) {
|
||||||
{
|
|
||||||
value |= decodeBitsReverse(nextbitpos + 1);
|
value |= decodeBitsReverse(nextbitpos + 1);
|
||||||
}
|
}
|
||||||
values[offset] = value;
|
values[offset] = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( nextbitpos < 0 )
|
if (nextbitpos < 0) {
|
||||||
{
|
while (subsize-- > 0) {
|
||||||
while (subsize-- > 0)
|
|
||||||
{
|
|
||||||
values[offset++] = value;
|
values[offset++] = value;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -292,12 +244,10 @@ public final class StatCoderContext extends BitCoderContext
|
|||||||
int size1 = decodeBounded(subsize);
|
int size1 = decodeBounded(subsize);
|
||||||
int size2 = subsize - size1;
|
int size2 = subsize - size1;
|
||||||
|
|
||||||
if ( size1 > 0 )
|
if (size1 > 0) {
|
||||||
{
|
|
||||||
decodeSortedArray(values, offset, size1, nextbitpos - 1, value);
|
decodeSortedArray(values, offset, size1, nextbitpos - 1, value);
|
||||||
}
|
}
|
||||||
if ( size2 > 0 )
|
if (size2 > 0) {
|
||||||
{
|
|
||||||
decodeSortedArray(values, offset + size1, size2, nextbitpos - 1, value | (1 << nextbitpos));
|
decodeSortedArray(values, offset + size1, size2, nextbitpos - 1, value | (1 << nextbitpos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,38 +8,31 @@ import btools.util.BitCoderContext;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Encoder/Decoder for way-/node-descriptions
|
* Encoder/Decoder for way-/node-descriptions
|
||||||
*
|
* <p>
|
||||||
* It detects identical descriptions and sorts them
|
* It detects identical descriptions and sorts them
|
||||||
* into a huffman-tree according to their frequencies
|
* into a huffman-tree according to their frequencies
|
||||||
*
|
* <p>
|
||||||
* Adapted for 3-pass encoding (counters -> statistics -> encoding )
|
* Adapted for 3-pass encoding (counters -> statistics -> encoding )
|
||||||
* but doesn't do anything at pass1
|
* but doesn't do anything at pass1
|
||||||
*/
|
*/
|
||||||
public final class TagValueCoder
|
public final class TagValueCoder {
|
||||||
{
|
|
||||||
private HashMap<TagValueSet, TagValueSet> identityMap;
|
private HashMap<TagValueSet, TagValueSet> identityMap;
|
||||||
private Object tree;
|
private Object tree;
|
||||||
private BitCoderContext bc;
|
private BitCoderContext bc;
|
||||||
private int pass;
|
private int pass;
|
||||||
private int nextTagValueSetId;
|
private int nextTagValueSetId;
|
||||||
|
|
||||||
public void encodeTagValueSet( byte[] data )
|
public void encodeTagValueSet(byte[] data) {
|
||||||
{
|
if (pass == 1) {
|
||||||
if ( pass == 1 )
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TagValueSet tvsProbe = new TagValueSet(nextTagValueSetId);
|
TagValueSet tvsProbe = new TagValueSet(nextTagValueSetId);
|
||||||
tvsProbe.data = data;
|
tvsProbe.data = data;
|
||||||
TagValueSet tvs = identityMap.get(tvsProbe);
|
TagValueSet tvs = identityMap.get(tvsProbe);
|
||||||
if ( pass == 3 )
|
if (pass == 3) {
|
||||||
{
|
|
||||||
bc.encodeBounded(tvs.range - 1, tvs.code);
|
bc.encodeBounded(tvs.range - 1, tvs.code);
|
||||||
}
|
} else if (pass == 2) {
|
||||||
else if ( pass == 2 )
|
if (tvs == null) {
|
||||||
{
|
|
||||||
if ( tvs == null )
|
|
||||||
{
|
|
||||||
tvs = tvsProbe;
|
tvs = tvsProbe;
|
||||||
nextTagValueSetId++;
|
nextTagValueSetId++;
|
||||||
identityMap.put(tvs, tvs);
|
identityMap.put(tvs, tvs);
|
||||||
@ -48,11 +41,9 @@ public final class TagValueCoder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagValueWrapper decodeTagValueSet()
|
public TagValueWrapper decodeTagValueSet() {
|
||||||
{
|
|
||||||
Object node = tree;
|
Object node = tree;
|
||||||
while (node instanceof TreeNode)
|
while (node instanceof TreeNode) {
|
||||||
{
|
|
||||||
TreeNode tn = (TreeNode) node;
|
TreeNode tn = (TreeNode) node;
|
||||||
boolean nextBit = bc.decodeBit();
|
boolean nextBit = bc.decodeBit();
|
||||||
node = nextBit ? tn.child2 : tn.child1;
|
node = nextBit ? tn.child2 : tn.child1;
|
||||||
@ -60,19 +51,15 @@ public final class TagValueCoder
|
|||||||
return (TagValueWrapper) node;
|
return (TagValueWrapper) node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void encodeDictionary( BitCoderContext bc )
|
public void encodeDictionary(BitCoderContext bc) {
|
||||||
{
|
if (++pass == 3) {
|
||||||
if ( ++pass == 3 )
|
if (identityMap.size() == 0) {
|
||||||
{
|
|
||||||
if ( identityMap.size() == 0 )
|
|
||||||
{
|
|
||||||
TagValueSet dummy = new TagValueSet(nextTagValueSetId++);
|
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());
|
queue.addAll(identityMap.values());
|
||||||
while (queue.size() > 1)
|
while (queue.size() > 1) {
|
||||||
{
|
|
||||||
TagValueSet node = new TagValueSet(nextTagValueSetId++);
|
TagValueSet node = new TagValueSet(nextTagValueSetId++);
|
||||||
node.child1 = queue.poll();
|
node.child1 = queue.poll();
|
||||||
node.child2 = queue.poll();
|
node.child2 = queue.poll();
|
||||||
@ -85,22 +72,18 @@ public final class TagValueCoder
|
|||||||
this.bc = bc;
|
this.bc = bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagValueCoder( BitCoderContext bc, DataBuffers buffers, TagValueValidator validator )
|
public TagValueCoder(BitCoderContext bc, DataBuffers buffers, TagValueValidator validator) {
|
||||||
{
|
|
||||||
tree = decodeTree(bc, buffers, validator);
|
tree = decodeTree(bc, buffers, validator);
|
||||||
this.bc = bc;
|
this.bc = bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagValueCoder()
|
public TagValueCoder() {
|
||||||
{
|
|
||||||
identityMap = new HashMap<TagValueSet, TagValueSet>();
|
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();
|
boolean isNode = bc.decodeBit();
|
||||||
if ( isNode )
|
if (isNode) {
|
||||||
{
|
|
||||||
TreeNode node = new TreeNode();
|
TreeNode node = new TreeNode();
|
||||||
node.child1 = decodeTree(bc, buffers, validator);
|
node.child1 = decodeTree(bc, buffers, validator);
|
||||||
node.child2 = decodeTree(bc, buffers, validator);
|
node.child2 = decodeTree(bc, buffers, validator);
|
||||||
@ -115,18 +98,14 @@ public final class TagValueCoder
|
|||||||
int lastEncodedInum = 0;
|
int lastEncodedInum = 0;
|
||||||
|
|
||||||
boolean hasdata = false;
|
boolean hasdata = false;
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
int delta = bc.decodeVarBits();
|
int delta = bc.decodeVarBits();
|
||||||
if ( !hasdata )
|
if (!hasdata) {
|
||||||
{
|
if (delta == 0) {
|
||||||
if ( delta == 0 )
|
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( delta == 0 )
|
if (delta == 0) {
|
||||||
{
|
|
||||||
ctx.encodeVarBits(0);
|
ctx.encodeVarBits(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -134,8 +113,7 @@ public final class TagValueCoder
|
|||||||
|
|
||||||
int data = bc.decodeVarBits();
|
int data = bc.decodeVarBits();
|
||||||
|
|
||||||
if ( validator == null || validator.isLookupIdxUsed( inum ) )
|
if (validator == null || validator.isLookupIdxUsed(inum)) {
|
||||||
{
|
|
||||||
hasdata = true;
|
hasdata = true;
|
||||||
ctx.encodeVarBits(inum - lastEncodedInum);
|
ctx.encodeVarBits(inum - lastEncodedInum);
|
||||||
ctx.encodeVarBits(data);
|
ctx.encodeVarBits(data);
|
||||||
@ -145,19 +123,15 @@ public final class TagValueCoder
|
|||||||
|
|
||||||
byte[] res;
|
byte[] res;
|
||||||
int len = ctx.closeAndGetEncodedLength();
|
int len = ctx.closeAndGetEncodedLength();
|
||||||
if ( validator == null )
|
if (validator == null) {
|
||||||
{
|
|
||||||
res = new byte[len];
|
res = new byte[len];
|
||||||
System.arraycopy(buffer, 0, res, 0, len);
|
System.arraycopy(buffer, 0, res, 0, len);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
res = validator.unify(buffer, 0, len);
|
res = validator.unify(buffer, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int accessType = validator == null ? 2 : validator.accessType(res);
|
int accessType = validator == null ? 2 : validator.accessType(res);
|
||||||
if ( accessType > 0 )
|
if (accessType > 0) {
|
||||||
{
|
|
||||||
TagValueWrapper w = new TagValueWrapper();
|
TagValueWrapper w = new TagValueWrapper();
|
||||||
w.data = res;
|
w.data = res;
|
||||||
w.accessType = accessType;
|
w.accessType = accessType;
|
||||||
@ -166,14 +140,12 @@ public final class TagValueCoder
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class TreeNode
|
public static final class TreeNode {
|
||||||
{
|
|
||||||
public Object child1;
|
public Object child1;
|
||||||
public Object child2;
|
public Object child2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class TagValueSet
|
public static final class TagValueSet {
|
||||||
{
|
|
||||||
public byte[] data;
|
public byte[] data;
|
||||||
public int frequency;
|
public int frequency;
|
||||||
public int code;
|
public int code;
|
||||||
@ -182,36 +154,28 @@ public final class TagValueCoder
|
|||||||
public TagValueSet child2;
|
public TagValueSet child2;
|
||||||
private int id; // serial number to make the comparator well defined in case of equal frequencies
|
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;
|
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.range = range;
|
||||||
this.code = code;
|
this.code = code;
|
||||||
boolean isNode = child1 != null;
|
boolean isNode = child1 != null;
|
||||||
bc.encodeBit(isNode);
|
bc.encodeBit(isNode);
|
||||||
if ( isNode )
|
if (isNode) {
|
||||||
{
|
|
||||||
child1.encode(bc, range << 1, code);
|
child1.encode(bc, range << 1, code);
|
||||||
child2.encode(bc, range << 1, code + range);
|
child2.encode(bc, range << 1, code + range);
|
||||||
}
|
} else {
|
||||||
else
|
if (data == null) {
|
||||||
{
|
|
||||||
if ( data == null )
|
|
||||||
{
|
|
||||||
bc.encodeVarBits(0);
|
bc.encodeVarBits(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BitCoderContext src = new BitCoderContext(data);
|
BitCoderContext src = new BitCoderContext(data);
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
int delta = src.decodeVarBits();
|
int delta = src.decodeVarBits();
|
||||||
bc.encodeVarBits(delta);
|
bc.encodeVarBits(delta);
|
||||||
if ( delta == 0 )
|
if (delta == 0) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int data = src.decodeVarBits();
|
int data = src.decodeVarBits();
|
||||||
@ -221,27 +185,20 @@ public final class TagValueCoder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals( Object o )
|
public boolean equals(Object o) {
|
||||||
{
|
if (o instanceof TagValueSet) {
|
||||||
if ( o instanceof TagValueSet )
|
|
||||||
{
|
|
||||||
TagValueSet tvs = (TagValueSet) o;
|
TagValueSet tvs = (TagValueSet) o;
|
||||||
if ( data == null )
|
if (data == null) {
|
||||||
{
|
|
||||||
return tvs.data == null;
|
return tvs.data == null;
|
||||||
}
|
}
|
||||||
if ( tvs.data == null )
|
if (tvs.data == null) {
|
||||||
{
|
|
||||||
return data == null;
|
return data == null;
|
||||||
}
|
}
|
||||||
if ( data.length != tvs.data.length )
|
if (data.length != tvs.data.length) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for ( int i = 0; i < data.length; i++ )
|
for (int i = 0; i < data.length; i++) {
|
||||||
{
|
if (data[i] != tvs.data[i]) {
|
||||||
if ( data[i] != tvs.data[i] )
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,22 +208,18 @@ public final class TagValueCoder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode() {
|
||||||
{
|
if (data == null) {
|
||||||
if ( data == null )
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int h = 17;
|
int h = 17;
|
||||||
for ( int i = 0; i < data.length; i++ )
|
for (int i = 0; i < data.length; i++) {
|
||||||
{
|
|
||||||
h = (h << 8) + data[i];
|
h = (h << 8) + data[i];
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FrequencyComparator implements Comparator<TagValueSet>
|
public static class FrequencyComparator implements Comparator<TagValueSet> {
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(TagValueSet tvs1, TagValueSet tvs2) {
|
public int compare(TagValueSet tvs1, TagValueSet tvs2) {
|
||||||
@ -281,8 +234,7 @@ public final class TagValueCoder
|
|||||||
if (tvs1.id > tvs2.id)
|
if (tvs1.id > tvs2.id)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ( tvs1 != tvs2 )
|
if (tvs1 != tvs2) {
|
||||||
{
|
|
||||||
throw new RuntimeException("identity corruption!");
|
throw new RuntimeException("identity corruption!");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
package btools.codec;
|
package btools.codec;
|
||||||
|
|
||||||
|
|
||||||
public interface TagValueValidator
|
public interface TagValueValidator {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* @param tagValueSet the way description to check
|
* @param tagValueSet the way description to check
|
||||||
* @return 0 = nothing, 1=no matching, 2=normal
|
* @return 0 = nothing, 1=no matching, 2=normal
|
||||||
|
|||||||
@ -5,8 +5,7 @@ package btools.codec;
|
|||||||
* TagValueWrapper wrapps a description bitmap
|
* TagValueWrapper wrapps a description bitmap
|
||||||
* to add the access-type
|
* to add the access-type
|
||||||
*/
|
*/
|
||||||
public final class TagValueWrapper
|
public final class TagValueWrapper {
|
||||||
{
|
|
||||||
public byte[] data;
|
public byte[] data;
|
||||||
public int accessType;
|
public int accessType;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,10 @@ package btools.codec;
|
|||||||
* from the decoder to find the closest
|
* from the decoder to find the closest
|
||||||
* matches to the waypoints
|
* matches to the waypoints
|
||||||
*/
|
*/
|
||||||
public interface WaypointMatcher
|
public interface WaypointMatcher {
|
||||||
{
|
|
||||||
boolean start(int ilonStart, int ilatStart, int ilonTarget, int ilatTarget);
|
boolean start(int ilonStart, int ilatStart, int ilonTarget, int ilatTarget);
|
||||||
|
|
||||||
void transferNode(int ilon, int ilat);
|
void transferNode(int ilon, int ilat);
|
||||||
|
|
||||||
void end();
|
void end();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,50 +3,39 @@ package btools.codec;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class LinkedListContainerTest
|
public class LinkedListContainerTest {
|
||||||
{
|
|
||||||
@Test
|
@Test
|
||||||
public void linkedListTest1()
|
public void linkedListTest1() {
|
||||||
{
|
|
||||||
int nlists = 553;
|
int nlists = 553;
|
||||||
|
|
||||||
LinkedListContainer llc = new LinkedListContainer(nlists, null);
|
LinkedListContainer llc = new LinkedListContainer(nlists, null);
|
||||||
|
|
||||||
for ( int ln = 0; ln < nlists; ln++ )
|
for (int ln = 0; ln < nlists; ln++) {
|
||||||
{
|
for (int i = 0; i < 10; i++) {
|
||||||
for ( int i = 0; i < 10; i++ )
|
|
||||||
{
|
|
||||||
llc.addDataElement(ln, ln * i);
|
llc.addDataElement(ln, ln * i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < 10; i++ )
|
for (int i = 0; i < 10; i++) {
|
||||||
{
|
for (int ln = 0; ln < nlists; ln++) {
|
||||||
for ( int ln = 0; ln < nlists; ln++ )
|
|
||||||
{
|
|
||||||
llc.addDataElement(ln, ln * i);
|
llc.addDataElement(ln, ln * i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int ln = 0; ln < nlists; ln++ )
|
for (int ln = 0; ln < nlists; ln++) {
|
||||||
{
|
|
||||||
int cnt = llc.initList(ln);
|
int cnt = llc.initList(ln);
|
||||||
Assert.assertTrue("list size test", cnt == 20);
|
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();
|
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();
|
llc.getDataElement();
|
||||||
Assert.fail("no more elements expected");
|
Assert.fail("no more elements expected");
|
||||||
}
|
} catch (IllegalArgumentException e) {
|
||||||
catch (IllegalArgumentException e)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,30 +6,23 @@ import java.util.Random;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class StatCoderContextTest
|
public class StatCoderContextTest {
|
||||||
{
|
|
||||||
@Test
|
@Test
|
||||||
public void noisyVarBitsEncodeDecodeTest()
|
public void noisyVarBitsEncodeDecodeTest() {
|
||||||
{
|
|
||||||
byte[] ab = new byte[40000];
|
byte[] ab = new byte[40000];
|
||||||
StatCoderContext ctx = new StatCoderContext(ab);
|
StatCoderContext ctx = new StatCoderContext(ab);
|
||||||
for ( int noisybits = 1; noisybits < 12; noisybits++ )
|
for (int noisybits = 1; noisybits < 12; noisybits++) {
|
||||||
{
|
for (int i = 0; i < 1000; i++) {
|
||||||
for ( int i = 0; i < 1000; i++ )
|
|
||||||
{
|
|
||||||
ctx.encodeNoisyNumber(i, noisybits);
|
ctx.encodeNoisyNumber(i, noisybits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.closeAndGetEncodedLength();
|
ctx.closeAndGetEncodedLength();
|
||||||
ctx = new StatCoderContext(ab);
|
ctx = new StatCoderContext(ab);
|
||||||
|
|
||||||
for ( int noisybits = 1; noisybits < 12; noisybits++ )
|
for (int noisybits = 1; noisybits < 12; noisybits++) {
|
||||||
{
|
for (int i = 0; i < 1000; i++) {
|
||||||
for ( int i = 0; i < 1000; i++ )
|
|
||||||
{
|
|
||||||
int value = ctx.decodeNoisyNumber(noisybits);
|
int value = ctx.decodeNoisyNumber(noisybits);
|
||||||
if ( value != i )
|
if (value != i) {
|
||||||
{
|
|
||||||
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
|
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,27 +30,21 @@ public class StatCoderContextTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noisySignedVarBitsEncodeDecodeTest()
|
public void noisySignedVarBitsEncodeDecodeTest() {
|
||||||
{
|
|
||||||
byte[] ab = new byte[80000];
|
byte[] ab = new byte[80000];
|
||||||
StatCoderContext ctx = new StatCoderContext(ab);
|
StatCoderContext ctx = new StatCoderContext(ab);
|
||||||
for ( int noisybits = 0; noisybits < 12; noisybits++ )
|
for (int noisybits = 0; noisybits < 12; noisybits++) {
|
||||||
{
|
for (int i = -1000; i < 1000; i++) {
|
||||||
for ( int i = -1000; i < 1000; i++ )
|
|
||||||
{
|
|
||||||
ctx.encodeNoisyDiff(i, noisybits);
|
ctx.encodeNoisyDiff(i, noisybits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.closeAndGetEncodedLength();
|
ctx.closeAndGetEncodedLength();
|
||||||
ctx = new StatCoderContext(ab);
|
ctx = new StatCoderContext(ab);
|
||||||
|
|
||||||
for ( int noisybits = 0; noisybits < 12; noisybits++ )
|
for (int noisybits = 0; noisybits < 12; noisybits++) {
|
||||||
{
|
for (int i = -1000; i < 1000; i++) {
|
||||||
for ( int i = -1000; i < 1000; i++ )
|
|
||||||
{
|
|
||||||
int value = ctx.decodeNoisyDiff(noisybits);
|
int value = ctx.decodeNoisyDiff(noisybits);
|
||||||
if ( value != i )
|
if (value != i) {
|
||||||
{
|
|
||||||
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
|
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,27 +52,21 @@ public class StatCoderContextTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void predictedValueEncodeDecodeTest()
|
public void predictedValueEncodeDecodeTest() {
|
||||||
{
|
|
||||||
byte[] ab = new byte[80000];
|
byte[] ab = new byte[80000];
|
||||||
StatCoderContext ctx = new StatCoderContext(ab);
|
StatCoderContext ctx = new StatCoderContext(ab);
|
||||||
for ( int value = -100; value < 100; value += 5 )
|
for (int value = -100; value < 100; value += 5) {
|
||||||
{
|
for (int predictor = -200; predictor < 200; predictor += 7) {
|
||||||
for ( int predictor = -200; predictor < 200; predictor += 7 )
|
|
||||||
{
|
|
||||||
ctx.encodePredictedValue(value, predictor);
|
ctx.encodePredictedValue(value, predictor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.closeAndGetEncodedLength();
|
ctx.closeAndGetEncodedLength();
|
||||||
ctx = new StatCoderContext(ab);
|
ctx = new StatCoderContext(ab);
|
||||||
|
|
||||||
for ( int value = -100; value < 100; value += 5 )
|
for (int value = -100; value < 100; value += 5) {
|
||||||
{
|
for (int predictor = -200; predictor < 200; predictor += 7) {
|
||||||
for ( int predictor = -200; predictor < 200; predictor += 7 )
|
|
||||||
{
|
|
||||||
int decodedValue = ctx.decodePredictedValue(predictor);
|
int decodedValue = ctx.decodePredictedValue(predictor);
|
||||||
if ( value != decodedValue )
|
if (value != decodedValue) {
|
||||||
{
|
|
||||||
Assert.fail("value mismatch: value=" + value + " predictor=" + predictor + " decodedValue=" + decodedValue);
|
Assert.fail("value mismatch: value=" + value + " predictor=" + predictor + " decodedValue=" + decodedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,13 +74,11 @@ public class StatCoderContextTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sortedArrayEncodeDecodeTest()
|
public void sortedArrayEncodeDecodeTest() {
|
||||||
{
|
|
||||||
Random rand = new Random();
|
Random rand = new Random();
|
||||||
int size = 1000000;
|
int size = 1000000;
|
||||||
int[] values = new int[size];
|
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[i] = rand.nextInt() & 0x0fffffff;
|
||||||
}
|
}
|
||||||
values[5] = 175384; // force collision
|
values[5] = 175384; // force collision
|
||||||
@ -120,10 +99,8 @@ public class StatCoderContextTest
|
|||||||
int[] decodedValues = new int[size];
|
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++ )
|
for (int i = 0; i < size; i++) {
|
||||||
{
|
if (values[i] != decodedValues[i]) {
|
||||||
if ( values[i] != decodedValues[i] )
|
|
||||||
{
|
|
||||||
Assert.fail("mismatch at i=" + i + " " + values[i] + "<>" + decodedValues[i]);
|
Assert.fail("mismatch at i=" + i + " " + values[i] + "<>" + decodedValues[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,15 +11,12 @@ import btools.expressions.BExpressionContextNode;
|
|||||||
import btools.expressions.BExpressionContextWay;
|
import btools.expressions.BExpressionContextWay;
|
||||||
|
|
||||||
|
|
||||||
final class KinematicModel extends OsmPathModel
|
final class KinematicModel extends OsmPathModel {
|
||||||
{
|
public OsmPrePath createPrePath() {
|
||||||
public OsmPrePath createPrePath()
|
|
||||||
{
|
|
||||||
return new KinematicPrePath();
|
return new KinematicPrePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmPath createPath()
|
public OsmPath createPath() {
|
||||||
{
|
|
||||||
return new KinematicPath();
|
return new KinematicPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +52,8 @@ final class KinematicModel extends OsmPathModel
|
|||||||
private double lastBreakingSpeed;
|
private double lastBreakingSpeed;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String,String> extraParams )
|
public void init(BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map<String, String> extraParams) {
|
||||||
{
|
if (!initDone) {
|
||||||
if ( !initDone )
|
|
||||||
{
|
|
||||||
ctxWay = expctxWay;
|
ctxWay = expctxWay;
|
||||||
ctxNode = expctxNode;
|
ctxNode = expctxNode;
|
||||||
wayIdxMaxspeed = ctxWay.getOutputVariableIndex("maxspeed", false);
|
wayIdxMaxspeed = ctxWay.getOutputVariableIndex("maxspeed", false);
|
||||||
@ -86,46 +81,38 @@ final class KinematicModel extends OsmPathModel
|
|||||||
cost0 = (pw + p_standby) / vmax + f_roll + f_air * vmax * vmax;
|
cost0 = (pw + p_standby) / vmax + f_roll + f_air * vmax * vmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getParam( String name, float defaultValue )
|
protected float getParam(String name, float defaultValue) {
|
||||||
{
|
|
||||||
String sval = params == null ? null : params.get(name);
|
String sval = params == null ? null : params.get(name);
|
||||||
if ( sval != null )
|
if (sval != null) {
|
||||||
{
|
|
||||||
return Float.parseFloat(sval);
|
return Float.parseFloat(sval);
|
||||||
}
|
}
|
||||||
float v = ctxWay.getVariableValue(name, defaultValue);
|
float v = ctxWay.getVariableValue(name, defaultValue);
|
||||||
if ( params != null )
|
if (params != null) {
|
||||||
{
|
|
||||||
params.put(name, "" + v);
|
params.put(name, "" + v);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getWayMaxspeed()
|
public float getWayMaxspeed() {
|
||||||
{
|
|
||||||
return ctxWay.getBuildInVariable(wayIdxMaxspeed) / 3.6f;
|
return ctxWay.getBuildInVariable(wayIdxMaxspeed) / 3.6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getWayMaxspeedExplicit()
|
public float getWayMaxspeedExplicit() {
|
||||||
{
|
|
||||||
return ctxWay.getBuildInVariable(wayIdxMaxspeedExplicit) / 3.6f;
|
return ctxWay.getBuildInVariable(wayIdxMaxspeedExplicit) / 3.6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getWayMinspeed()
|
public float getWayMinspeed() {
|
||||||
{
|
|
||||||
return ctxWay.getBuildInVariable(wayIdxMinspeed) / 3.6f;
|
return ctxWay.getBuildInVariable(wayIdxMinspeed) / 3.6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getNodeMaxspeed()
|
public float getNodeMaxspeed() {
|
||||||
{
|
|
||||||
return ctxNode.getBuildInVariable(nodeIdxMaxspeed) / 3.6f;
|
return ctxNode.getBuildInVariable(nodeIdxMaxspeed) / 3.6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the effective speed limit from the way-limit and vmax/vmin
|
* get the effective speed limit from the way-limit and vmax/vmin
|
||||||
*/
|
*/
|
||||||
public double getEffectiveSpeedLimit( )
|
public double getEffectiveSpeedLimit() {
|
||||||
{
|
|
||||||
// performance related inline coding
|
// performance related inline coding
|
||||||
double minspeed = getWayMinspeed();
|
double minspeed = getWayMinspeed();
|
||||||
double espeed = minspeed > vmax ? minspeed : vmax;
|
double espeed = minspeed > vmax ? minspeed : vmax;
|
||||||
@ -136,10 +123,8 @@ final class KinematicModel extends OsmPathModel
|
|||||||
/**
|
/**
|
||||||
* get the breaking speed for current balance-power (pw) and effective speed limit (vl)
|
* get the breaking speed for current balance-power (pw) and effective speed limit (vl)
|
||||||
*/
|
*/
|
||||||
public double getBreakingSpeed( double vl )
|
public double getBreakingSpeed(double vl) {
|
||||||
{
|
if (vl == lastEffectiveLimit) {
|
||||||
if ( vl == lastEffectiveLimit )
|
|
||||||
{
|
|
||||||
return lastBreakingSpeed;
|
return lastBreakingSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,8 +132,7 @@ final class KinematicModel extends OsmPathModel
|
|||||||
double pw2 = pw + p_standby;
|
double pw2 = pw + p_standby;
|
||||||
double e = recup_efficiency;
|
double e = recup_efficiency;
|
||||||
double x0 = pw2 / vl + f_air * e * vl * vl + (1. - e) * f_roll;
|
double x0 = pw2 / vl + f_air * e * vl * vl + (1. - e) * f_roll;
|
||||||
for(int i=0;i<5;i++)
|
for (int i = 0; i < 5; i++) {
|
||||||
{
|
|
||||||
double v2 = v * v;
|
double v2 = v * v;
|
||||||
double x = pw2 / v + f_air * e * v2 - x0;
|
double x = pw2 / v + f_air * e * v2 - x0;
|
||||||
double dx = 2. * e * f_air * v - pw2 / v2;
|
double dx = 2. * e * f_air * v - pw2 / v2;
|
||||||
|
|||||||
@ -8,8 +8,7 @@ package btools.router;
|
|||||||
import btools.util.FastMath;
|
import btools.util.FastMath;
|
||||||
|
|
||||||
|
|
||||||
final class KinematicPath extends OsmPath
|
final class KinematicPath extends OsmPath {
|
||||||
{
|
|
||||||
private double ekin; // kinetic energy (Joule)
|
private double ekin; // kinetic energy (Joule)
|
||||||
private double totalTime; // travel time (seconds)
|
private double totalTime; // travel time (seconds)
|
||||||
private double totalEnergy; // total route energy (Joule)
|
private double totalEnergy; // total route energy (Joule)
|
||||||
@ -17,8 +16,7 @@ final class KinematicPath extends OsmPath
|
|||||||
private float floatingAngleRight; // sliding average right bend (degree)
|
private float floatingAngleRight; // sliding average right bend (degree)
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init( OsmPath orig )
|
protected void init(OsmPath orig) {
|
||||||
{
|
|
||||||
KinematicPath origin = (KinematicPath) orig;
|
KinematicPath origin = (KinematicPath) orig;
|
||||||
ekin = origin.ekin;
|
ekin = origin.ekin;
|
||||||
totalTime = origin.totalTime;
|
totalTime = origin.totalTime;
|
||||||
@ -29,8 +27,7 @@ final class KinematicPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void resetState()
|
protected void resetState() {
|
||||||
{
|
|
||||||
ekin = 0.;
|
ekin = 0.;
|
||||||
totalTime = 0.;
|
totalTime = 0.;
|
||||||
totalEnergy = 0.;
|
totalEnergy = 0.;
|
||||||
@ -39,23 +36,18 @@ final class KinematicPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected double processWaySection( RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier )
|
protected double processWaySection(RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier) {
|
||||||
{
|
|
||||||
KinematicModel km = (KinematicModel) rc.pm;
|
KinematicModel km = (KinematicModel) rc.pm;
|
||||||
|
|
||||||
double cost = 0.;
|
double cost = 0.;
|
||||||
double extraTime = 0.;
|
double extraTime = 0.;
|
||||||
|
|
||||||
if ( isStartpoint )
|
if (isStartpoint) {
|
||||||
{
|
|
||||||
// for forward direction, we start with target speed
|
// for forward direction, we start with target speed
|
||||||
if ( !rc.inverseDirection )
|
if (!rc.inverseDirection) {
|
||||||
{
|
|
||||||
extraTime = 0.5 * (1. - cosangle) * 40.; // 40 seconds turn penalty
|
extraTime = 0.5 * (1. - cosangle) * 40.; // 40 seconds turn penalty
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
double turnspeed = 999.; // just high
|
double turnspeed = 999.; // just high
|
||||||
|
|
||||||
if (km.turnAngleDecayTime != 0.) // process turn-angle slowdown
|
if (km.turnAngleDecayTime != 0.) // process turn-angle slowdown
|
||||||
@ -70,8 +62,7 @@ final class KinematicPath extends OsmPath
|
|||||||
floatingAngleLeft = (float) (floatingAngleLeft * decayFactor);
|
floatingAngleLeft = (float) (floatingAngleLeft * decayFactor);
|
||||||
floatingAngleRight = (float) (floatingAngleRight * decayFactor);
|
floatingAngleRight = (float) (floatingAngleRight * decayFactor);
|
||||||
|
|
||||||
if ( curveSpeed < 20. )
|
if (curveSpeed < 20.) {
|
||||||
{
|
|
||||||
turnspeed = curveSpeed;
|
turnspeed = curveSpeed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,8 +77,7 @@ final class KinematicPath extends OsmPath
|
|||||||
boolean hasLeftWay = false;
|
boolean hasLeftWay = false;
|
||||||
boolean hasRightWay = false;
|
boolean hasRightWay = false;
|
||||||
boolean hasResidential = false;
|
boolean hasResidential = false;
|
||||||
for( OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next )
|
for (OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next) {
|
||||||
{
|
|
||||||
KinematicPrePath pp = (KinematicPrePath) prePath;
|
KinematicPrePath pp = (KinematicPrePath) prePath;
|
||||||
|
|
||||||
if (((pp.classifiermask ^ classifiermask) & 8) != 0) // exactly one is linktype
|
if (((pp.classifiermask ^ classifiermask) & 8) != 0) // exactly one is linktype
|
||||||
@ -100,8 +90,7 @@ final class KinematicPath extends OsmPath
|
|||||||
hasResidential = true;
|
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;
|
double diff = pp.angle - angle;
|
||||||
if (diff < -40. && diff > -140.) hasLeftWay = true;
|
if (diff < -40. && diff > -140.) hasLeftWay = true;
|
||||||
if (diff > 40. && diff < 140.) hasRightWay = true;
|
if (diff > 40. && diff < 140.) hasRightWay = true;
|
||||||
@ -113,20 +102,17 @@ final class KinematicPath extends OsmPath
|
|||||||
if (hasRightWay && junctionspeed > km.rightWaySpeed) junctionspeed = km.rightWaySpeed;
|
if (hasRightWay && junctionspeed > km.rightWaySpeed) junctionspeed = km.rightWaySpeed;
|
||||||
if (hasResidential && junctionspeed > residentialSpeed) junctionspeed = residentialSpeed;
|
if (hasResidential && junctionspeed > residentialSpeed) junctionspeed = residentialSpeed;
|
||||||
|
|
||||||
if ( (lastpriorityclassifier < 20) ^ (priorityclassifier < 20) )
|
if ((lastpriorityclassifier < 20) ^ (priorityclassifier < 20)) {
|
||||||
{
|
|
||||||
extraTime += 10.;
|
extraTime += 10.;
|
||||||
junctionspeed = 0; // full stop for entering or leaving road network
|
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
|
extraTime += 2.; // two seconds for entering a link-type
|
||||||
}
|
}
|
||||||
turnspeed = turnspeed > junctionspeed ? junctionspeed : turnspeed;
|
turnspeed = turnspeed > junctionspeed ? junctionspeed : turnspeed;
|
||||||
|
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.vnode0 = (int) (junctionspeed * 3.6 + 0.5);
|
message.vnode0 = (int) (junctionspeed * 3.6 + 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,8 +129,7 @@ final class KinematicPath extends OsmPath
|
|||||||
|
|
||||||
double distanceCost = evolveDistance(km, dist, delta_h, f_air);
|
double distanceCost = evolveDistance(km, dist, delta_h, f_air);
|
||||||
|
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.costfactor = (float) (distanceCost / dist);
|
message.costfactor = (float) (distanceCost / dist);
|
||||||
message.vmax = (int) (km.getWayMaxspeed() * 3.6 + 0.5);
|
message.vmax = (int) (km.getWayMaxspeed() * 3.6 + 0.5);
|
||||||
message.vmaxExplicit = (int) (km.getWayMaxspeedExplicit() * 3.6 + 0.5);
|
message.vmaxExplicit = (int) (km.getWayMaxspeedExplicit() * 3.6 + 0.5);
|
||||||
@ -159,15 +144,13 @@ final class KinematicPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected double evolveDistance( KinematicModel km, double dist, double delta_h, double f_air )
|
protected double evolveDistance(KinematicModel km, double dist, double delta_h, double f_air) {
|
||||||
{
|
|
||||||
// elevation force
|
// elevation force
|
||||||
double fh = delta_h * km.totalweight * 9.81 / dist;
|
double fh = delta_h * km.totalweight * 9.81 / dist;
|
||||||
|
|
||||||
double effectiveSpeedLimit = km.getEffectiveSpeedLimit();
|
double effectiveSpeedLimit = km.getEffectiveSpeedLimit();
|
||||||
double emax = 0.5 * km.totalweight * effectiveSpeedLimit * effectiveSpeedLimit;
|
double emax = 0.5 * km.totalweight * effectiveSpeedLimit * effectiveSpeedLimit;
|
||||||
if ( emax <= 0. )
|
if (emax <= 0.) {
|
||||||
{
|
|
||||||
return -1.;
|
return -1.;
|
||||||
}
|
}
|
||||||
double vb = km.getBreakingSpeed(effectiveSpeedLimit);
|
double vb = km.getBreakingSpeed(effectiveSpeedLimit);
|
||||||
@ -178,8 +161,7 @@ final class KinematicPath extends OsmPath
|
|||||||
|
|
||||||
double v = Math.sqrt(2. * ekin / km.totalweight);
|
double v = Math.sqrt(2. * ekin / km.totalweight);
|
||||||
double d = dist;
|
double d = dist;
|
||||||
while( d > 0. )
|
while (d > 0.) {
|
||||||
{
|
|
||||||
boolean slow = ekin < elow;
|
boolean slow = ekin < elow;
|
||||||
boolean fast = ekin >= emax;
|
boolean fast = ekin >= emax;
|
||||||
double etarget = slow ? elow : emax;
|
double etarget = slow ? elow : emax;
|
||||||
@ -190,30 +172,24 @@ final class KinematicPath extends OsmPath
|
|||||||
double delta_ekin;
|
double delta_ekin;
|
||||||
double timeStep;
|
double timeStep;
|
||||||
double x;
|
double x;
|
||||||
if ( fast )
|
if (fast) {
|
||||||
{
|
|
||||||
x = d;
|
x = d;
|
||||||
delta_ekin = x * f;
|
delta_ekin = x * f;
|
||||||
timeStep = x / v;
|
timeStep = x / v;
|
||||||
ekin = etarget;
|
ekin = etarget;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
delta_ekin = etarget - ekin;
|
delta_ekin = etarget - ekin;
|
||||||
double b = 2. * f_air / km.totalweight;
|
double b = 2. * f_air / km.totalweight;
|
||||||
double x0 = delta_ekin / f;
|
double x0 = delta_ekin / f;
|
||||||
double x0b = x0 * b;
|
double x0b = x0 * b;
|
||||||
x = x0 * (1. - x0b * (0.5 + x0b * (0.333333333 - x0b * 0.25))); // = ln( delta_ekin*b/f + 1.) / 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);
|
double maxstep = Math.min(50., d);
|
||||||
if ( x >= maxstep )
|
if (x >= maxstep) {
|
||||||
{
|
|
||||||
x = maxstep;
|
x = maxstep;
|
||||||
double xb = x * b;
|
double xb = x * b;
|
||||||
delta_ekin = x * f * (1. + xb * (0.5 + xb * (0.166666667 + xb * 0.0416666667))); // = f/b* exp(xb-1)
|
delta_ekin = x * f * (1. + xb * (0.5 + xb * (0.166666667 + xb * 0.0416666667))); // = f/b* exp(xb-1)
|
||||||
ekin += delta_ekin;
|
ekin += delta_ekin;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ekin = etarget;
|
ekin = etarget;
|
||||||
}
|
}
|
||||||
double v2 = Math.sqrt(2. * ekin / km.totalweight);
|
double v2 = Math.sqrt(2. * ekin / km.totalweight);
|
||||||
@ -242,23 +218,19 @@ final class KinematicPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected double processTargetNode( RoutingContext rc )
|
protected double processTargetNode(RoutingContext rc) {
|
||||||
{
|
|
||||||
KinematicModel km = (KinematicModel) rc.pm;
|
KinematicModel km = (KinematicModel) rc.pm;
|
||||||
|
|
||||||
// finally add node-costs for target node
|
// finally add node-costs for target node
|
||||||
if ( targetNode.nodeDescription != null )
|
if (targetNode.nodeDescription != null) {
|
||||||
{
|
|
||||||
rc.expctxNode.evaluate(false, targetNode.nodeDescription);
|
rc.expctxNode.evaluate(false, targetNode.nodeDescription);
|
||||||
float initialcost = rc.expctxNode.getInitialcost();
|
float initialcost = rc.expctxNode.getInitialcost();
|
||||||
if ( initialcost >= 1000000. )
|
if (initialcost >= 1000000.) {
|
||||||
{
|
|
||||||
return -1.;
|
return -1.;
|
||||||
}
|
}
|
||||||
cutEkin(km.totalweight, km.getNodeMaxspeed()); // apply node maxspeed
|
cutEkin(km.totalweight, km.getNodeMaxspeed()); // apply node maxspeed
|
||||||
|
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.linknodecost += (int) initialcost;
|
message.linknodecost += (int) initialcost;
|
||||||
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(false, targetNode.nodeDescription);
|
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(false, targetNode.nodeDescription);
|
||||||
|
|
||||||
@ -269,22 +241,19 @@ final class KinematicPath extends OsmPath
|
|||||||
return 0.;
|
return 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cutEkin( double weight, double speed )
|
private void cutEkin(double weight, double speed) {
|
||||||
{
|
|
||||||
double e = 0.5 * weight * speed * speed;
|
double e = 0.5 * weight * speed * speed;
|
||||||
if (ekin > e) ekin = e;
|
if (ekin > e) ekin = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int elevationCorrection( RoutingContext rc )
|
public int elevationCorrection(RoutingContext rc) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean definitlyWorseThan( OsmPath path, RoutingContext rc )
|
public boolean definitlyWorseThan(OsmPath path, RoutingContext rc) {
|
||||||
{
|
|
||||||
KinematicPath p = (KinematicPath) path;
|
KinematicPath p = (KinematicPath) path;
|
||||||
|
|
||||||
int c = p.cost;
|
int c = p.cost;
|
||||||
@ -292,14 +261,12 @@ final class KinematicPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getTotalTime()
|
public double getTotalTime() {
|
||||||
{
|
|
||||||
return totalTime;
|
return totalTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getTotalEnergy()
|
public double getTotalEnergy() {
|
||||||
{
|
|
||||||
return totalEnergy;
|
return totalEnergy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,14 +8,12 @@ package btools.router;
|
|||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
import btools.mapaccess.OsmTransferNode;
|
import btools.mapaccess.OsmTransferNode;
|
||||||
|
|
||||||
final class KinematicPrePath extends OsmPrePath
|
final class KinematicPrePath extends OsmPrePath {
|
||||||
{
|
|
||||||
public double angle;
|
public double angle;
|
||||||
public int priorityclassifier;
|
public int priorityclassifier;
|
||||||
public int classifiermask;
|
public int classifiermask;
|
||||||
|
|
||||||
protected void initPrePath(OsmPath origin, RoutingContext rc )
|
protected void initPrePath(OsmPath origin, RoutingContext rc) {
|
||||||
{
|
|
||||||
byte[] description = link.descriptionBitmap;
|
byte[] description = link.descriptionBitmap;
|
||||||
if (description == null) throw new IllegalArgumentException("null description for: " + link);
|
if (description == null) throw new IllegalArgumentException("null description for: " + link);
|
||||||
|
|
||||||
@ -38,13 +36,10 @@ final class KinematicPrePath extends OsmPrePath
|
|||||||
int lon2;
|
int lon2;
|
||||||
int lat2;
|
int lat2;
|
||||||
|
|
||||||
if ( transferNode == null )
|
if (transferNode == null) {
|
||||||
{
|
|
||||||
lon2 = targetNode.ilon;
|
lon2 = targetNode.ilon;
|
||||||
lat2 = targetNode.ilat;
|
lat2 = targetNode.ilat;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
lon2 = transferNode.ilon;
|
lon2 = transferNode.ilon;
|
||||||
lat2 = transferNode.ilat;
|
lat2 = transferNode.ilat;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,9 +6,7 @@
|
|||||||
package btools.router;
|
package btools.router;
|
||||||
|
|
||||||
|
|
||||||
|
final class MessageData implements Cloneable {
|
||||||
final class MessageData implements Cloneable
|
|
||||||
{
|
|
||||||
int linkdist = 0;
|
int linkdist = 0;
|
||||||
int linkelevationcost = 0;
|
int linkelevationcost = 0;
|
||||||
int linkturncost = 0;
|
int linkturncost = 0;
|
||||||
@ -37,10 +35,8 @@ final class MessageData implements Cloneable
|
|||||||
int vnode1 = 999;
|
int vnode1 = 999;
|
||||||
int extraTime = 0;
|
int extraTime = 0;
|
||||||
|
|
||||||
String toMessage()
|
String toMessage() {
|
||||||
{
|
if (wayKeyValues == null) {
|
||||||
if ( wayKeyValues == null )
|
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +56,7 @@ final class MessageData implements Cloneable
|
|||||||
+ "\t" + ((int) energy);
|
+ "\t" + ((int) energy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add( MessageData d )
|
void add(MessageData d) {
|
||||||
{
|
|
||||||
linkdist += d.linkdist;
|
linkdist += d.linkdist;
|
||||||
linkelevationcost += d.linkelevationcost;
|
linkelevationcost += d.linkelevationcost;
|
||||||
linkturncost += d.linkturncost;
|
linkturncost += d.linkturncost;
|
||||||
@ -69,51 +64,40 @@ final class MessageData implements Cloneable
|
|||||||
linkinitcost += d.linkinitcost;
|
linkinitcost += d.linkinitcost;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageData copy()
|
MessageData copy() {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
return (MessageData) clone();
|
return (MessageData) clone();
|
||||||
}
|
} catch (CloneNotSupportedException e) {
|
||||||
catch( CloneNotSupportedException e )
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString() {
|
||||||
{
|
|
||||||
return "dist=" + linkdist + " prio=" + priorityclassifier + " turn=" + turnangle;
|
return "dist=" + linkdist + " prio=" + priorityclassifier + " turn=" + turnangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPrio()
|
public int getPrio() {
|
||||||
{
|
|
||||||
return priorityclassifier;
|
return priorityclassifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBadOneway()
|
public boolean isBadOneway() {
|
||||||
{
|
|
||||||
return (classifiermask & 1) != 0;
|
return (classifiermask & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGoodOneway()
|
public boolean isGoodOneway() {
|
||||||
{
|
|
||||||
return (classifiermask & 2) != 0;
|
return (classifiermask & 2) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRoundabout()
|
public boolean isRoundabout() {
|
||||||
{
|
|
||||||
return (classifiermask & 4) != 0;
|
return (classifiermask & 4) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLinktType()
|
public boolean isLinktType() {
|
||||||
{
|
|
||||||
return (classifiermask & 8) != 0;
|
return (classifiermask & 8) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGoodForCars()
|
public boolean isGoodForCars() {
|
||||||
{
|
|
||||||
return (classifiermask & 16) != 0;
|
return (classifiermask & 16) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,25 +8,21 @@ package btools.router;
|
|||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
import btools.util.CheapRuler;
|
import btools.util.CheapRuler;
|
||||||
|
|
||||||
public class OsmNodeNamed extends OsmNode
|
public class OsmNodeNamed extends OsmNode {
|
||||||
{
|
|
||||||
public String name;
|
public String name;
|
||||||
public double radius; // radius of nogopoint (in meters)
|
public double radius; // radius of nogopoint (in meters)
|
||||||
public double nogoWeight; // weight for nogopoint
|
public double nogoWeight; // weight for nogopoint
|
||||||
public boolean isNogo = false;
|
public boolean isNogo = false;
|
||||||
|
|
||||||
public OsmNodeNamed()
|
public OsmNodeNamed() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNodeNamed( OsmNode n)
|
public OsmNodeNamed(OsmNode n) {
|
||||||
{
|
|
||||||
super(n.ilon, n.ilat);
|
super(n.ilon, n.ilat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString() {
|
||||||
{
|
|
||||||
if (Double.isNaN(nogoWeight)) {
|
if (Double.isNaN(nogoWeight)) {
|
||||||
return ilon + "," + ilat + "," + name;
|
return ilon + "," + ilat + "," + name;
|
||||||
} else {
|
} else {
|
||||||
@ -82,8 +78,7 @@ public class OsmNodeNamed extends OsmNode
|
|||||||
return 2 * halfDistanceWithin;
|
return 2 * halfDistanceWithin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OsmNodeNamed decodeNogo( String s )
|
public static OsmNodeNamed decodeNogo(String s) {
|
||||||
{
|
|
||||||
OsmNodeNamed n = new OsmNodeNamed();
|
OsmNodeNamed n = new OsmNodeNamed();
|
||||||
int idx1 = s.indexOf(',');
|
int idx1 = s.indexOf(',');
|
||||||
n.ilon = Integer.parseInt(s.substring(0, idx1));
|
n.ilon = Integer.parseInt(s.substring(0, idx1));
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
http://geomalgorithms.com/a03-_inclusion.html
|
http://geomalgorithms.com/a03-_inclusion.html
|
||||||
|
|
||||||
cn_PnPoly, wn_PnPoly, inSegment, intersect2D_2Segments
|
cn_PnPoly, wn_PnPoly, inSegment, intersect2D_2Segments
|
||||||
|
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
package btools.router;
|
package btools.router;
|
||||||
|
|
||||||
@ -14,15 +13,12 @@ import java.util.List;
|
|||||||
|
|
||||||
import btools.util.CheapRuler;
|
import btools.util.CheapRuler;
|
||||||
|
|
||||||
public class OsmNogoPolygon extends OsmNodeNamed
|
public class OsmNogoPolygon extends OsmNodeNamed {
|
||||||
{
|
public final static class Point {
|
||||||
public final static class Point
|
|
||||||
{
|
|
||||||
public final int y;
|
public final int y;
|
||||||
public final int x;
|
public final int x;
|
||||||
|
|
||||||
Point(final int lon, final int lat)
|
Point(final int lon, final int lat) {
|
||||||
{
|
|
||||||
x = lon;
|
x = lon;
|
||||||
y = lat;
|
y = lat;
|
||||||
}
|
}
|
||||||
@ -32,15 +28,13 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
|
|
||||||
public final boolean isClosed;
|
public final boolean isClosed;
|
||||||
|
|
||||||
public OsmNogoPolygon(boolean closed)
|
public OsmNogoPolygon(boolean closed) {
|
||||||
{
|
|
||||||
this.isClosed = closed;
|
this.isClosed = closed;
|
||||||
this.isNogo = true;
|
this.isNogo = true;
|
||||||
this.name = "";
|
this.name = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addVertex(int lon, int lat)
|
public final void addVertex(int lon, int lat) {
|
||||||
{
|
|
||||||
points.add(new Point(lon, lat));
|
points.add(new Point(lon, lat));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,36 +48,30 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
* with each iteration.
|
* with each iteration.
|
||||||
* This is done to ensure the calculated radius being used
|
* This is done to ensure the calculated radius being used
|
||||||
* in RoutingContext.calcDistance will actually contain the whole polygon.
|
* in RoutingContext.calcDistance will actually contain the whole polygon.
|
||||||
*
|
* <p>
|
||||||
* For reasonable distributed vertices the implemented algorithm runs in O(n*ln(n)).
|
* 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
|
* 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
|
* overall usage of cpu is neglegible in comparism to the cpu-usage of the
|
||||||
* actual routing algoritm.
|
* actual routing algoritm.
|
||||||
*/
|
*/
|
||||||
public void calcBoundingCircle()
|
public void calcBoundingCircle() {
|
||||||
{
|
|
||||||
int cxmin, cxmax, cymin, cymax;
|
int cxmin, cxmax, cymin, cymax;
|
||||||
cxmin = cymin = Integer.MAX_VALUE;
|
cxmin = cymin = Integer.MAX_VALUE;
|
||||||
cxmax = cymax = Integer.MIN_VALUE;
|
cxmax = cymax = Integer.MIN_VALUE;
|
||||||
|
|
||||||
// first calculate a starting center point as center of boundingbox
|
// 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);
|
final Point p = points.get(i);
|
||||||
if (p.x < cxmin)
|
if (p.x < cxmin) {
|
||||||
{
|
|
||||||
cxmin = p.x;
|
cxmin = p.x;
|
||||||
}
|
}
|
||||||
if (p.x > cxmax)
|
if (p.x > cxmax) {
|
||||||
{
|
|
||||||
cxmax = p.x;
|
cxmax = p.x;
|
||||||
}
|
}
|
||||||
if (p.y < cymin)
|
if (p.y < cymin) {
|
||||||
{
|
|
||||||
cymin = p.y;
|
cymin = p.y;
|
||||||
}
|
}
|
||||||
if (p.y > cymax)
|
if (p.y > cymax) {
|
||||||
{
|
|
||||||
cymax = p.y;
|
cymax = p.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,11 +88,9 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
double dmax = 0; // length of vector from center to point
|
double dmax = 0; // length of vector from center to point
|
||||||
int i_max = -1;
|
int i_max = -1;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
// now identify the point outside of the circle that has the greatest distance
|
// 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);
|
final Point p = points.get(i);
|
||||||
|
|
||||||
// to get precisely the same results as in RoutingContext.calcDistance()
|
// to get precisely the same results as in RoutingContext.calcDistance()
|
||||||
@ -113,19 +99,16 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
final double y1 = (cy - p.y) * dlat2m;
|
final double 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;
|
continue;
|
||||||
}
|
}
|
||||||
if (dist > dmax)
|
if (dist > dmax) {
|
||||||
{
|
|
||||||
// new maximum distance found
|
// new maximum distance found
|
||||||
dmax = dist;
|
dmax = dist;
|
||||||
i_max = i;
|
i_max = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i_max < 0)
|
if (i_max < 0) {
|
||||||
{
|
|
||||||
break; // leave loop when no point outside the circle is found any more.
|
break; // leave loop when no point outside the circle is found any more.
|
||||||
}
|
}
|
||||||
final double dd = 0.5 * (1 - rad / dmax);
|
final double dd = 0.5 * (1 - rad / dmax);
|
||||||
@ -165,18 +148,15 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
* @param lat1 latitude of start point
|
* @param lat1 latitude of start point
|
||||||
* @return true if segment or any of it's points are 'inside' of polygon
|
* @return true if segment or any of it's points are 'inside' of polygon
|
||||||
*/
|
*/
|
||||||
public boolean intersects(int lon0, int lat0, int lon1, int lat1)
|
public boolean intersects(int lon0, int lat0, int lon1, int lat1) {
|
||||||
{
|
|
||||||
final Point p0 = new Point(lon0, lat0);
|
final Point p0 = new Point(lon0, lat0);
|
||||||
final Point p1 = new Point(lon1, lat1);
|
final Point p1 = new Point(lon1, lat1);
|
||||||
int i_last = points.size() - 1;
|
int i_last = points.size() - 1;
|
||||||
Point p2 = points.get(isClosed ? i_last : 0);
|
Point p2 = points.get(isClosed ? i_last : 0);
|
||||||
for (int i = isClosed ? 0 : 1 ; i <= i_last; i++)
|
for (int i = isClosed ? 0 : 1; i <= i_last; i++) {
|
||||||
{
|
|
||||||
Point p3 = points.get(i);
|
Point p3 = points.get(i);
|
||||||
// does it intersect with at least one of the polygon's segments?
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
p2 = p3;
|
p2 = p3;
|
||||||
@ -184,15 +164,12 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnPolyline( long px, long py )
|
public boolean isOnPolyline(long px, long py) {
|
||||||
{
|
|
||||||
int i_last = points.size() - 1;
|
int i_last = points.size() - 1;
|
||||||
Point p1 = points.get(0);
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
p1 = p2;
|
p1 = p2;
|
||||||
@ -200,8 +177,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isOnLine( long px, long py, long p0x, long p0y, long p1x, long p1y )
|
public static boolean isOnLine(long px, long py, long p0x, long p0y, long p1x, long p1y) {
|
||||||
{
|
|
||||||
final double v10x = px - p0x;
|
final double v10x = px - p0x;
|
||||||
final double v10y = py - p0y;
|
final double v10y = py - p0y;
|
||||||
final double v12x = p1x - p0x;
|
final double v12x = p1x - p0x;
|
||||||
@ -229,8 +205,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
return (v12x / v10x) >= 1; // P1->P2 at least as long as P1->P0?
|
return (v12x / v10x) >= 1; // P1->P2 at least as long as P1->P0?
|
||||||
}
|
}
|
||||||
final double kx = v12x / v10x;
|
final double kx = v12x / v10x;
|
||||||
if ( kx < 1 )
|
if (kx < 1) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return kx == v12y / v10y;
|
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
|
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
|
resulting from its use. Users of this code must verify correctness for
|
||||||
their application. */
|
their application. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* winding number test for a point in a polygon
|
* winding number test for a point in a polygon
|
||||||
*
|
*
|
||||||
@ -249,8 +225,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
* @param py latitude of the point to check
|
* @param py latitude of the point to check
|
||||||
* @return a boolean whether the point is within the polygon or not.
|
* @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
|
int wn = 0; // the winding number counter
|
||||||
|
|
||||||
// loop through all edges of the polygon
|
// loop through all edges of the polygon
|
||||||
@ -266,8 +241,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
final long p1x = p1.x;
|
final long p1x = p1.x;
|
||||||
final long p1y = p1.y;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,18 +249,15 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
{
|
{
|
||||||
if (p1y > py) // an upward crossing
|
if (p1y > py) // an upward crossing
|
||||||
{ // p left of edge
|
{ // 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
|
++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
|
if (p1y <= py) // a downward crossing
|
||||||
{ // p right of edge
|
{ // 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
|
--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 lat1 Integer latitude of the first point of the segment.
|
||||||
* @param lon2 Integer longitude of the last 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.
|
* @param lat2 Integer latitude of the last point of the segment.
|
||||||
*
|
|
||||||
* @return The length, in meters, of the portion of the segment which is
|
* @return The length, in meters, of the portion of the segment which is
|
||||||
* included in the polygon.
|
* included in the polygon.
|
||||||
*/
|
*/
|
||||||
@ -316,8 +286,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
final Point p2 = new Point(lon2, lat2);
|
final Point p2 = new Point(lon2, lat2);
|
||||||
|
|
||||||
Point previousIntersectionOnSegment = null;
|
Point previousIntersectionOnSegment = null;
|
||||||
if (isWithin(lon1, lat1))
|
if (isWithin(lon1, lat1)) {
|
||||||
{
|
|
||||||
// Start point of the segment is within the polygon, this is the first
|
// Start point of the segment is within the polygon, this is the first
|
||||||
// "intersection".
|
// "intersection".
|
||||||
previousIntersectionOnSegment = p1;
|
previousIntersectionOnSegment = p1;
|
||||||
@ -325,14 +294,12 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
|
|
||||||
// Loop over edges of the polygon to find intersections
|
// Loop over edges of the polygon to find intersections
|
||||||
int i_last = points.size() - 1;
|
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 edgePoint1 = points.get(j);
|
||||||
Point edgePoint2 = points.get(i);
|
Point edgePoint2 = points.get(i);
|
||||||
int intersectsEdge = intersect2D_2Segments(p1, p2, edgePoint1, edgePoint2);
|
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
|
// Intersects with a (closed) polygon edge on a single point
|
||||||
// Distance is zero when crossing a polyline.
|
// Distance is zero when crossing a polyline.
|
||||||
// Let's find this intersection point
|
// Let's find this intersection point
|
||||||
@ -363,8 +330,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
previousIntersectionOnSegment = intersection;
|
previousIntersectionOnSegment = intersection;
|
||||||
}
|
} else if (intersectsEdge == 2) {
|
||||||
else if (intersectsEdge == 2) {
|
|
||||||
// Segment and edge overlaps
|
// Segment and edge overlaps
|
||||||
// FIXME: Could probably be done in a smarter way
|
// FIXME: Could probably be done in a smarter way
|
||||||
distance += Math.min(
|
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
|
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
|
resulting from its use. Users of this code must verify correctness for
|
||||||
their application. */
|
their application. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inSegment(): determine if a point is inside a segment
|
* inSegment(): determine if a point is inside a segment
|
||||||
*
|
*
|
||||||
@ -410,35 +377,29 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
* @return 1 = P is inside S
|
* @return 1 = P is inside S
|
||||||
* 0 = P is not 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 sp0x = seg_p0.x;
|
||||||
final int sp1x = seg_p1.x;
|
final int sp1x = seg_p1.x;
|
||||||
|
|
||||||
if (sp0x != sp1x) // S is not vertical
|
if (sp0x != sp1x) // S is not vertical
|
||||||
{
|
{
|
||||||
final int px = p.x;
|
final int px = p.x;
|
||||||
if (sp0x <= px && px <= sp1x)
|
if (sp0x <= px && px <= sp1x) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (sp0x >= px && px >= sp1x)
|
if (sp0x >= px && px >= sp1x) {
|
||||||
{
|
|
||||||
return true;
|
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 sp0y = seg_p0.y;
|
||||||
final int sp1y = seg_p1.y;
|
final int sp1y = seg_p1.y;
|
||||||
final int py = p.y;
|
final int py = p.y;
|
||||||
|
|
||||||
if (sp0y <= py && py <= sp1y)
|
if (sp0y <= py && py <= sp1y) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (sp0y >= py && py >= sp1y)
|
if (sp0y >= py && py >= sp1y) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,8 +412,10 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
this code, and cannot be held liable for any real or imagined damage
|
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
|
resulting from its use. Users of this code must verify correctness for
|
||||||
their application. */
|
their application. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* intersect2D_2Segments(): find the 2D intersection of 2 finite segments
|
* intersect2D_2Segments(): find the 2D intersection of 2 finite segments
|
||||||
|
*
|
||||||
* @param s1p0 start point of segment 1
|
* @param s1p0 start point of segment 1
|
||||||
* @param s1p1 end point of segment 1
|
* @param s1p1 end point of segment 1
|
||||||
* @param s2p0 start point of segment 2
|
* @param s2p0 start point of segment 2
|
||||||
@ -461,8 +424,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
* 1=intersect in unique point I0
|
* 1=intersect in unique point I0
|
||||||
* 2=overlap in segment from I0 to I1
|
* 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 ux = s1p1.x - s1p0.x; // vector u = S1P1-S1P0 (segment 1)
|
||||||
final long uy = s1p1.y - s1p0.y;
|
final long uy = s1p1.y - s1p0.y;
|
||||||
final long vx = s2p1.x - s2p0.x; // vector v = S2P1-S2P0 (segment 2)
|
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)
|
// test if they are parallel (includes either being a point)
|
||||||
if (d == 0) // S1 and S2 are parallel
|
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
|
return 0; // they are NOT collinear
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,13 +461,10 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
double t0, t1; // endpoints of S1 in eqn for S2
|
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 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;
|
final int w2y = s1p1.y - s2p0.y;
|
||||||
if (vx != 0)
|
if (vx != 0) {
|
||||||
{
|
|
||||||
t0 = wx / vx;
|
t0 = wx / vx;
|
||||||
t1 = w2x / vx;
|
t1 = w2x / vx;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
t0 = wy / vy;
|
t0 = wy / vy;
|
||||||
t1 = w2y / vy;
|
t1 = w2y / vy;
|
||||||
}
|
}
|
||||||
@ -516,8 +474,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
|
|||||||
t0 = t1;
|
t0 = t1;
|
||||||
t1 = t;
|
t1 = t;
|
||||||
}
|
}
|
||||||
if (t0 > 1 || t1 < 0)
|
if (t0 > 1 || t1 < 0) {
|
||||||
{
|
|
||||||
return 0; // NO overlap
|
return 0; // NO overlap
|
||||||
}
|
}
|
||||||
t0 = t0 < 0 ? 0 : t0; // clip to min 0
|
t0 = t0 < 0 ? 0 : t0; // clip to min 0
|
||||||
|
|||||||
@ -14,8 +14,7 @@ import btools.mapaccess.OsmTransferNode;
|
|||||||
import btools.mapaccess.TurnRestriction;
|
import btools.mapaccess.TurnRestriction;
|
||||||
import btools.util.CheapRuler;
|
import btools.util.CheapRuler;
|
||||||
|
|
||||||
abstract class OsmPath implements OsmLinkHolder
|
abstract class OsmPath implements OsmLinkHolder {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* The cost of that path (a modified distance)
|
* The cost of that path (a modified distance)
|
||||||
*/
|
*/
|
||||||
@ -57,54 +56,42 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
private static final int HAD_DESTINATION_START_BIT = 8;
|
private static final int HAD_DESTINATION_START_BIT = 8;
|
||||||
protected int bitfield = PATH_START_BIT;
|
protected int bitfield = PATH_START_BIT;
|
||||||
|
|
||||||
private boolean getBit( int mask )
|
private boolean getBit(int mask) {
|
||||||
{
|
|
||||||
return (bitfield & mask) != 0;
|
return (bitfield & mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBit( int mask, boolean bit )
|
private void setBit(int mask, boolean bit) {
|
||||||
{
|
if (getBit(mask) != bit) {
|
||||||
if ( getBit( mask ) != bit )
|
|
||||||
{
|
|
||||||
bitfield ^= mask;
|
bitfield ^= mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean didEnterDestinationArea()
|
public boolean didEnterDestinationArea() {
|
||||||
{
|
|
||||||
return !getBit(HAD_DESTINATION_START_BIT) && getBit(IS_ON_DESTINATION_BIT);
|
return !getBit(HAD_DESTINATION_START_BIT) && getBit(IS_ON_DESTINATION_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageData message;
|
public MessageData message;
|
||||||
|
|
||||||
public void unregisterUpTree( RoutingContext rc )
|
public void unregisterUpTree(RoutingContext rc) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
OsmPathElement pe = originElement;
|
OsmPathElement pe = originElement;
|
||||||
while( pe instanceof OsmPathElementWithTraffic && ((OsmPathElementWithTraffic)pe).unregister(rc) )
|
while (pe instanceof OsmPathElementWithTraffic && ((OsmPathElementWithTraffic) pe).unregister(rc)) {
|
||||||
{
|
|
||||||
pe = pe.origin;
|
pe = pe.origin;
|
||||||
}
|
}
|
||||||
}
|
} catch (IOException ioe) {
|
||||||
catch( IOException ioe )
|
|
||||||
{
|
|
||||||
throw new RuntimeException(ioe);
|
throw new RuntimeException(ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerUpTree()
|
public void registerUpTree() {
|
||||||
{
|
if (originElement instanceof OsmPathElementWithTraffic) {
|
||||||
if ( originElement instanceof OsmPathElementWithTraffic )
|
|
||||||
{
|
|
||||||
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) originElement;
|
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) originElement;
|
||||||
ot.register();
|
ot.register();
|
||||||
ot.addTraffic(traffic);
|
ot.addTraffic(traffic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init( OsmLink link )
|
public void init(OsmLink link) {
|
||||||
{
|
|
||||||
this.link = link;
|
this.link = link;
|
||||||
targetNode = link.getTarget(null);
|
targetNode = link.getTarget(null);
|
||||||
selev = targetNode.getSElev();
|
selev = targetNode.getSElev();
|
||||||
@ -113,10 +100,8 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
originLat = -1;
|
originLat = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init( OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc )
|
public void init(OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc) {
|
||||||
{
|
if (origin.myElement == null) {
|
||||||
if ( origin.myElement == null )
|
|
||||||
{
|
|
||||||
origin.myElement = OsmPathElement.create(origin, rc.countTraffic);
|
origin.myElement = OsmPathElement.create(origin, rc.countTraffic);
|
||||||
}
|
}
|
||||||
this.originElement = origin.myElement;
|
this.originElement = origin.myElement;
|
||||||
@ -136,11 +121,9 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
protected abstract void resetState();
|
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;
|
byte[] description = link.descriptionBitmap;
|
||||||
if ( description == null )
|
if (description == null) {
|
||||||
{
|
|
||||||
return; // could be a beeline path
|
return; // could be a beeline path
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,18 +159,15 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
float newClassifier = rc.expctxWay.getInitialClassifier();
|
float newClassifier = rc.expctxWay.getInitialClassifier();
|
||||||
float newInitialCost = rc.expctxWay.getInitialcost();
|
float newInitialCost = rc.expctxWay.getInitialcost();
|
||||||
float classifierDiff = newClassifier - lastClassifier;
|
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;
|
float initialcost = rc.inverseDirection ? lastInitialCost : newInitialCost;
|
||||||
if ( initialcost >= 1000000. )
|
if (initialcost >= 1000000.) {
|
||||||
{
|
|
||||||
cost = -1;
|
cost = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iicost = (int) initialcost;
|
int iicost = (int) initialcost;
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.linkinitcost += iicost;
|
message.linkinitcost += iicost;
|
||||||
}
|
}
|
||||||
cost += iicost;
|
cost += iicost;
|
||||||
@ -199,22 +179,15 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
int classifiermask = (int) rc.expctxWay.getClassifierMask();
|
int classifiermask = (int) rc.expctxWay.getClassifierMask();
|
||||||
boolean newDestination = (classifiermask & 64) != 0;
|
boolean newDestination = (classifiermask & 64) != 0;
|
||||||
boolean oldDestination = getBit(IS_ON_DESTINATION_BIT);
|
boolean oldDestination = getBit(IS_ON_DESTINATION_BIT);
|
||||||
if ( getBit( PATH_START_BIT ) )
|
if (getBit(PATH_START_BIT)) {
|
||||||
{
|
|
||||||
setBit(PATH_START_BIT, false);
|
setBit(PATH_START_BIT, false);
|
||||||
setBit(CAN_LEAVE_DESTINATION_BIT, newDestination);
|
setBit(CAN_LEAVE_DESTINATION_BIT, newDestination);
|
||||||
setBit(HAD_DESTINATION_START_BIT, newDestination);
|
setBit(HAD_DESTINATION_START_BIT, newDestination);
|
||||||
}
|
} else {
|
||||||
else
|
if (oldDestination && !newDestination) {
|
||||||
{
|
if (getBit(CAN_LEAVE_DESTINATION_BIT)) {
|
||||||
if ( oldDestination && !newDestination )
|
|
||||||
{
|
|
||||||
if ( getBit( CAN_LEAVE_DESTINATION_BIT ) )
|
|
||||||
{
|
|
||||||
setBit(CAN_LEAVE_DESTINATION_BIT, false);
|
setBit(CAN_LEAVE_DESTINATION_BIT, false);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cost = -1;
|
cost = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -226,8 +199,7 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
OsmTransferNode transferNode = link.geometry == null ? null
|
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;
|
originLon = lon1;
|
||||||
originLat = lat1;
|
originLat = lat1;
|
||||||
@ -236,14 +208,11 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
int lat2;
|
int lat2;
|
||||||
short ele2;
|
short ele2;
|
||||||
|
|
||||||
if ( transferNode == null )
|
if (transferNode == null) {
|
||||||
{
|
|
||||||
lon2 = targetNode.ilon;
|
lon2 = targetNode.ilon;
|
||||||
lat2 = targetNode.ilat;
|
lat2 = targetNode.ilat;
|
||||||
ele2 = targetNode.selev;
|
ele2 = targetNode.selev;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
lon2 = transferNode.ilon;
|
lon2 = transferNode.ilon;
|
||||||
lat2 = transferNode.ilat;
|
lat2 = transferNode.ilat;
|
||||||
ele2 = transferNode.selev;
|
ele2 = transferNode.selev;
|
||||||
@ -252,20 +221,17 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
boolean isStartpoint = lon0 == -1 && lat0 == -1;
|
boolean isStartpoint = lon0 == -1 && lat0 == -1;
|
||||||
|
|
||||||
// check turn restrictions (n detail mode (=final pass) no TR to not mess up voice hints)
|
// check turn restrictions (n detail mode (=final pass) no TR to not mess up voice hints)
|
||||||
if ( nsection == 0 && rc.considerTurnRestrictions && !detailMode&& !isStartpoint )
|
if (nsection == 0 && rc.considerTurnRestrictions && !detailMode && !isStartpoint) {
|
||||||
{
|
|
||||||
if (rc.inverseDirection
|
if (rc.inverseDirection
|
||||||
? TurnRestriction.isTurnForbidden(sourceNode.firstRestriction, lon2, lat2, lon0, lat0, rc.bikeMode || rc.footMode, rc.carMode)
|
? TurnRestriction.isTurnForbidden(sourceNode.firstRestriction, lon2, lat2, lon0, lat0, rc.bikeMode || rc.footMode, rc.carMode)
|
||||||
: TurnRestriction.isTurnForbidden( sourceNode.firstRestriction, lon0, lat0, lon2, lat2, rc.bikeMode || rc.footMode, rc.carMode ) )
|
: TurnRestriction.isTurnForbidden(sourceNode.firstRestriction, lon0, lat0, lon2, lat2, rc.bikeMode || rc.footMode, rc.carMode)) {
|
||||||
{
|
|
||||||
cost = -1;
|
cost = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if recording, new MessageData for each section (needed for turn-instructions)
|
// 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;
|
originElement.message = message;
|
||||||
message = new MessageData();
|
message = new MessageData();
|
||||||
}
|
}
|
||||||
@ -273,15 +239,11 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
int dist = rc.calcDistance(lon1, lat1, lon2, lat2);
|
int dist = rc.calcDistance(lon1, lat1, lon2, lat2);
|
||||||
|
|
||||||
boolean stopAtEndpoint = false;
|
boolean stopAtEndpoint = false;
|
||||||
if ( rc.shortestmatch )
|
if (rc.shortestmatch) {
|
||||||
{
|
if (rc.isEndpoint) {
|
||||||
if ( rc.isEndpoint )
|
|
||||||
{
|
|
||||||
stopAtEndpoint = true;
|
stopAtEndpoint = true;
|
||||||
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
|
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// we just start here, reset everything
|
// we just start here, reset everything
|
||||||
cost = 0;
|
cost = 0;
|
||||||
resetState();
|
resetState();
|
||||||
@ -289,24 +251,18 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
lat0 = -1;
|
lat0 = -1;
|
||||||
isStartpoint = true;
|
isStartpoint = true;
|
||||||
|
|
||||||
if ( recordTransferNodes )
|
if (recordTransferNodes) {
|
||||||
{
|
if (rc.wayfraction > 0.) {
|
||||||
if ( rc.wayfraction > 0. )
|
|
||||||
{
|
|
||||||
ele1 = interpolateEle(ele1, ele2, 1. - rc.wayfraction);
|
ele1 = interpolateEle(ele1, ele2, 1. - rc.wayfraction);
|
||||||
originElement = OsmPathElement.create(rc.ilonshortest, rc.ilatshortest, ele1, null, rc.countTraffic);
|
originElement = OsmPathElement.create(rc.ilonshortest, rc.ilatshortest, ele1, null, rc.countTraffic);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
originElement = null; // prevent duplicate point
|
originElement = null; // prevent duplicate point
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( rc.checkPendingEndpoint() )
|
if (rc.checkPendingEndpoint()) {
|
||||||
{
|
|
||||||
dist = rc.calcDistance(rc.ilonshortest, rc.ilatshortest, lon2, lat2);
|
dist = rc.calcDistance(rc.ilonshortest, rc.ilatshortest, lon2, lat2);
|
||||||
if ( rc.shortestmatch )
|
if (rc.shortestmatch) {
|
||||||
{
|
|
||||||
stopAtEndpoint = true;
|
stopAtEndpoint = true;
|
||||||
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
|
ele2 = interpolateEle(ele1, ele2, rc.wayfraction);
|
||||||
}
|
}
|
||||||
@ -314,24 +270,19 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.linkdist += dist;
|
message.linkdist += dist;
|
||||||
}
|
}
|
||||||
linkdisttotal += dist;
|
linkdisttotal += dist;
|
||||||
|
|
||||||
// apply a start-direction if appropriate (by faking the origin position)
|
// apply a start-direction if appropriate (by faking the origin position)
|
||||||
if ( isStartpoint )
|
if (isStartpoint) {
|
||||||
{
|
if (rc.startDirectionValid) {
|
||||||
if ( rc.startDirectionValid )
|
|
||||||
{
|
|
||||||
double dir = rc.startDirection.intValue() * CheapRuler.DEG_TO_RAD;
|
double dir = rc.startDirection.intValue() * CheapRuler.DEG_TO_RAD;
|
||||||
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lon0 + lat1) >> 1);
|
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lon0 + lat1) >> 1);
|
||||||
lon0 = lon1 - (int) (1000. * Math.sin(dir) / lonlat2m[0]);
|
lon0 = lon1 - (int) (1000. * Math.sin(dir) / lonlat2m[0]);
|
||||||
lat0 = lat1 - (int) (1000. * Math.cos(dir) / lonlat2m[1]);
|
lat0 = lat1 - (int) (1000. * Math.cos(dir) / lonlat2m[1]);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
lon0 = lon1 - (lon2 - lon1);
|
lon0 = lon1 - (lon2 - lon1);
|
||||||
lat0 = lat1 - (lat2 - lat1);
|
lat0 = lat1 - (lat2 - lat1);
|
||||||
}
|
}
|
||||||
@ -342,37 +293,30 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
// *** elevation stuff
|
// *** elevation stuff
|
||||||
double delta_h = 0.;
|
double delta_h = 0.;
|
||||||
if (ele2 == Short.MIN_VALUE) ele2 = ele1;
|
if (ele2 == Short.MIN_VALUE) ele2 = ele1;
|
||||||
if ( ele1 != Short.MIN_VALUE )
|
if (ele1 != Short.MIN_VALUE) {
|
||||||
{
|
|
||||||
delta_h = (ele2 - ele1) / 4.;
|
delta_h = (ele2 - ele1) / 4.;
|
||||||
if ( rc.inverseDirection )
|
if (rc.inverseDirection) {
|
||||||
{
|
|
||||||
delta_h = -delta_h;
|
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);
|
double sectionCost = processWaySection(rc, dist, delta_h, elevation, angle, cosangle, isStartpoint, nsection, lastpriorityclassifier);
|
||||||
if ( ( sectionCost < 0. || costfactor > 9998. && !detailMode ) || sectionCost + cost >= 2000000000. )
|
if ((sectionCost < 0. || costfactor > 9998. && !detailMode) || sectionCost + cost >= 2000000000.) {
|
||||||
{
|
|
||||||
cost = -1;
|
cost = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isTrafficBackbone )
|
if (isTrafficBackbone) {
|
||||||
{
|
|
||||||
sectionCost = 0.;
|
sectionCost = 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
cost += (int) sectionCost;
|
cost += (int) sectionCost;
|
||||||
|
|
||||||
// calculate traffic
|
// calculate traffic
|
||||||
if ( rc.countTraffic )
|
if (rc.countTraffic) {
|
||||||
{
|
|
||||||
int minDist = (int) rc.trafficSourceMinDist;
|
int minDist = (int) rc.trafficSourceMinDist;
|
||||||
int cost2 = cost < minDist ? minDist : cost;
|
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);
|
||||||
@ -381,8 +325,7 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
// compute kinematic
|
// compute kinematic
|
||||||
computeKinematic(rc, dist, delta_h, detailMode);
|
computeKinematic(rc, dist, delta_h, detailMode);
|
||||||
|
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.turnangle = (float) angle;
|
message.turnangle = (float) angle;
|
||||||
message.time = (float) getTotalTime();
|
message.time = (float) getTotalTime();
|
||||||
message.energy = (float) getTotalEnergy();
|
message.energy = (float) getTotalEnergy();
|
||||||
@ -394,33 +337,25 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
message.wayKeyValues = rc.expctxWay.getKeyValueDescription(isReverse, description);
|
message.wayKeyValues = rc.expctxWay.getKeyValueDescription(isReverse, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( stopAtEndpoint )
|
if (stopAtEndpoint) {
|
||||||
{
|
if (recordTransferNodes) {
|
||||||
if ( recordTransferNodes )
|
|
||||||
{
|
|
||||||
originElement = OsmPathElement.create(rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic);
|
originElement = OsmPathElement.create(rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic);
|
||||||
originElement.cost = cost;
|
originElement.cost = cost;
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
originElement.message = message;
|
originElement.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( rc.nogoCost < 0)
|
if (rc.nogoCost < 0) {
|
||||||
{
|
|
||||||
cost = -1;
|
cost = -1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cost += rc.nogoCost;
|
cost += rc.nogoCost;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( transferNode == null )
|
if (transferNode == null) {
|
||||||
{
|
|
||||||
// *** penalty for being part of the reference track
|
// *** 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;
|
int reftrackcost = linkdisttotal;
|
||||||
cost += reftrackcost;
|
cost += reftrackcost;
|
||||||
}
|
}
|
||||||
@ -429,8 +364,7 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
}
|
}
|
||||||
transferNode = transferNode.next;
|
transferNode = transferNode.next;
|
||||||
|
|
||||||
if ( recordTransferNodes )
|
if (recordTransferNodes) {
|
||||||
{
|
|
||||||
originElement = OsmPathElement.create(lon2, lat2, ele2, originElement, rc.countTraffic);
|
originElement = OsmPathElement.create(lon2, lat2, ele2, originElement, rc.countTraffic);
|
||||||
originElement.cost = cost;
|
originElement.cost = cost;
|
||||||
originElement.addTraffic(traffic);
|
originElement.addTraffic(traffic);
|
||||||
@ -444,20 +378,16 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for nogo-matches (after the *actual* start of segment)
|
// check for nogo-matches (after the *actual* start of segment)
|
||||||
if ( rc.nogoCost < 0)
|
if (rc.nogoCost < 0) {
|
||||||
{
|
|
||||||
cost = -1;
|
cost = -1;
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cost += rc.nogoCost;
|
cost += rc.nogoCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add target-node costs
|
// add target-node costs
|
||||||
double targetCost = processTargetNode(rc);
|
double targetCost = processTargetNode(rc);
|
||||||
if ( targetCost < 0. || targetCost + cost >= 2000000000. )
|
if (targetCost < 0. || targetCost + cost >= 2000000000.) {
|
||||||
{
|
|
||||||
cost = -1;
|
cost = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -465,10 +395,8 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public short interpolateEle( short e1, short e2, double fraction )
|
public short interpolateEle(short e1, short e2, double fraction) {
|
||||||
{
|
if (e1 == Short.MIN_VALUE || e2 == Short.MIN_VALUE) {
|
||||||
if ( e1 == Short.MIN_VALUE || e2 == Short.MIN_VALUE )
|
|
||||||
{
|
|
||||||
return Short.MIN_VALUE;
|
return Short.MIN_VALUE;
|
||||||
}
|
}
|
||||||
return (short) (e1 * (1. - fraction) + e2 * fraction);
|
return (short) (e1 * (1. - fraction) + e2 * fraction);
|
||||||
@ -478,47 +406,39 @@ abstract class OsmPath implements OsmLinkHolder
|
|||||||
|
|
||||||
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;
|
return sourceNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNode getTargetNode()
|
public OsmNode getTargetNode() {
|
||||||
{
|
|
||||||
return targetNode;
|
return targetNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmLink getLink()
|
public OsmLink getLink() {
|
||||||
{
|
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setNextForLink( OsmLinkHolder holder )
|
public void setNextForLink(OsmLinkHolder holder) {
|
||||||
{
|
|
||||||
nextForLink = holder;
|
nextForLink = holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmLinkHolder getNextForLink()
|
public OsmLinkHolder getNextForLink() {
|
||||||
{
|
|
||||||
return nextForLink;
|
return nextForLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getTotalTime()
|
public double getTotalTime() {
|
||||||
{
|
|
||||||
return 0.;
|
return 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getTotalEnergy()
|
public double getTotalEnergy() {
|
||||||
{
|
|
||||||
return 0.;
|
return 0.;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,8 +14,7 @@ import btools.util.CheapRuler;
|
|||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class OsmPathElement implements OsmPos
|
public class OsmPathElement implements OsmPos {
|
||||||
{
|
|
||||||
private int ilat; // latitude
|
private int ilat; // latitude
|
||||||
private int ilon; // longitude
|
private int ilon; // longitude
|
||||||
private short selev; // longitude
|
private short selev; // longitude
|
||||||
@ -25,67 +24,54 @@ public class OsmPathElement implements OsmPos
|
|||||||
public int cost;
|
public int cost;
|
||||||
|
|
||||||
// interface OsmPos
|
// interface OsmPos
|
||||||
public final int getILat()
|
public final int getILat() {
|
||||||
{
|
|
||||||
return ilat;
|
return ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getILon()
|
public final int getILon() {
|
||||||
{
|
|
||||||
return ilon;
|
return ilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final short getSElev()
|
public final short getSElev() {
|
||||||
{
|
|
||||||
return selev;
|
return selev;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final double getElev()
|
public final double getElev() {
|
||||||
{
|
|
||||||
return selev / 4.;
|
return selev / 4.;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final float getTime()
|
public final float getTime() {
|
||||||
{
|
|
||||||
return message == null ? 0.f : message.time;
|
return message == null ? 0.f : message.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setTime( float t )
|
public final void setTime(float t) {
|
||||||
{
|
if (message != null) {
|
||||||
if ( message != null )
|
|
||||||
{
|
|
||||||
message.time = t;
|
message.time = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final float getEnergy()
|
public final float getEnergy() {
|
||||||
{
|
|
||||||
return message == null ? 0.f : message.energy;
|
return message == null ? 0.f : message.energy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setEnergy( float e )
|
public final void setEnergy(float e) {
|
||||||
{
|
if (message != null) {
|
||||||
if ( message != null )
|
|
||||||
{
|
|
||||||
message.energy = e;
|
message.energy = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final long getIdFromPos()
|
public final long getIdFromPos() {
|
||||||
{
|
|
||||||
return ((long) ilon) << 32 | ilat;
|
return ((long) ilon) << 32 | ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int calcDistance( OsmPos p )
|
public final int calcDistance(OsmPos p) {
|
||||||
{
|
|
||||||
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
|
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmPathElement origin;
|
public OsmPathElement origin;
|
||||||
|
|
||||||
// construct a path element from a path
|
// 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();
|
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.cost = path.cost;
|
||||||
@ -93,8 +79,7 @@ public class OsmPathElement implements OsmPos
|
|||||||
return pe;
|
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();
|
OsmPathElement pe = countTraffic ? new OsmPathElementWithTraffic() : new OsmPathElement();
|
||||||
pe.ilon = ilon;
|
pe.ilon = ilon;
|
||||||
pe.ilat = ilat;
|
pe.ilat = ilat;
|
||||||
@ -103,29 +88,24 @@ public class OsmPathElement implements OsmPos
|
|||||||
return pe;
|
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;
|
return ilon + "_" + ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeToStream( DataOutput dos ) throws IOException
|
public void writeToStream(DataOutput dos) throws IOException {
|
||||||
{
|
|
||||||
dos.writeInt(ilat);
|
dos.writeInt(ilat);
|
||||||
dos.writeInt(ilon);
|
dos.writeInt(ilon);
|
||||||
dos.writeShort(selev);
|
dos.writeShort(selev);
|
||||||
dos.writeInt(cost);
|
dos.writeInt(cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OsmPathElement readFromStream( DataInput dis ) throws IOException
|
public static OsmPathElement readFromStream(DataInput dis) throws IOException {
|
||||||
{
|
|
||||||
OsmPathElement pe = new OsmPathElement();
|
OsmPathElement pe = new OsmPathElement();
|
||||||
pe.ilat = dis.readInt();
|
pe.ilat = dis.readInt();
|
||||||
pe.ilon = dis.readInt();
|
pe.ilon = dis.readInt();
|
||||||
|
|||||||
@ -9,18 +9,14 @@ import java.io.IOException;
|
|||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class OsmPathElementWithTraffic extends OsmPathElement
|
public final class OsmPathElementWithTraffic extends OsmPathElement {
|
||||||
{
|
|
||||||
private int registerCount;
|
private int registerCount;
|
||||||
private float farTraffic;
|
private float farTraffic;
|
||||||
private float nearTraffic;
|
private float nearTraffic;
|
||||||
|
|
||||||
public void register()
|
public void register() {
|
||||||
{
|
if (registerCount++ == 0) {
|
||||||
if ( registerCount++ == 0 )
|
if (origin instanceof OsmPathElementWithTraffic) {
|
||||||
{
|
|
||||||
if ( origin instanceof OsmPathElementWithTraffic )
|
|
||||||
{
|
|
||||||
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
|
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
|
||||||
ot.register();
|
ot.register();
|
||||||
ot.farTraffic += farTraffic;
|
ot.farTraffic += farTraffic;
|
||||||
@ -32,8 +28,7 @@ public final class OsmPathElementWithTraffic extends OsmPathElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTraffic( float traffic )
|
public void addTraffic(float traffic) {
|
||||||
{
|
|
||||||
this.farTraffic += traffic;
|
this.farTraffic += traffic;
|
||||||
this.nearTraffic += traffic;
|
this.nearTraffic += traffic;
|
||||||
}
|
}
|
||||||
@ -42,12 +37,9 @@ public final class OsmPathElementWithTraffic extends OsmPathElement
|
|||||||
|
|
||||||
public static double maxtraffic = 0.;
|
public static double maxtraffic = 0.;
|
||||||
|
|
||||||
public boolean unregister( RoutingContext rc ) throws IOException
|
public boolean unregister(RoutingContext rc) throws IOException {
|
||||||
{
|
if (--registerCount == 0) {
|
||||||
if ( --registerCount == 0 )
|
if (origin instanceof OsmPathElementWithTraffic) {
|
||||||
{
|
|
||||||
if ( origin instanceof OsmPathElementWithTraffic )
|
|
||||||
{
|
|
||||||
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
|
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic) origin;
|
||||||
|
|
||||||
int costdelta = cost - ot.cost;
|
int costdelta = cost - ot.cost;
|
||||||
@ -58,11 +50,9 @@ if ( costdelta > 0 && farTraffic > maxtraffic ) maxtraffic = farTraffic;
|
|||||||
|
|
||||||
int t2 = cost == ot.cost ? -1 : (int) (rc.farTrafficWeight * farTraffic + rc.nearTrafficWeight * nearTraffic);
|
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 );
|
// System.out.println( "unregistered: " + this + " origin=" + ot + " farTraffic =" + farTraffic + " nearTraffic =" + nearTraffic + " cost=" + cost );
|
||||||
if ( rc.trafficOutputStream != null )
|
if (rc.trafficOutputStream != null) {
|
||||||
{
|
|
||||||
rc.trafficOutputStream.writeLong(getIdFromPos());
|
rc.trafficOutputStream.writeLong(getIdFromPos());
|
||||||
rc.trafficOutputStream.writeLong(ot.getIdFromPos());
|
rc.trafficOutputStream.writeLong(ot.getIdFromPos());
|
||||||
rc.trafficOutputStream.writeInt(t2);
|
rc.trafficOutputStream.writeInt(t2);
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import btools.expressions.BExpressionContextNode;
|
|||||||
import btools.expressions.BExpressionContextWay;
|
import btools.expressions.BExpressionContextWay;
|
||||||
|
|
||||||
|
|
||||||
abstract class OsmPathModel
|
abstract class OsmPathModel {
|
||||||
{
|
|
||||||
public abstract OsmPrePath createPrePath();
|
public abstract OsmPrePath createPrePath();
|
||||||
|
|
||||||
public abstract OsmPath createPath();
|
public abstract OsmPath createPath();
|
||||||
|
|||||||
@ -9,16 +9,14 @@ import btools.mapaccess.OsmLink;
|
|||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
import btools.mapaccess.OsmTransferNode;
|
import btools.mapaccess.OsmTransferNode;
|
||||||
|
|
||||||
public abstract class OsmPrePath
|
public abstract class OsmPrePath {
|
||||||
{
|
|
||||||
protected OsmNode sourceNode;
|
protected OsmNode sourceNode;
|
||||||
protected OsmNode targetNode;
|
protected OsmNode targetNode;
|
||||||
protected OsmLink link;
|
protected OsmLink link;
|
||||||
|
|
||||||
public OsmPrePath next;
|
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.link = link;
|
||||||
this.sourceNode = origin.getTargetNode();
|
this.sourceNode = origin.getTargetNode();
|
||||||
this.targetNode = link.getTarget(sourceNode);
|
this.targetNode = link.getTarget(sourceNode);
|
||||||
|
|||||||
@ -31,8 +31,7 @@ import btools.util.CompactLongMap;
|
|||||||
import btools.util.FrozenLongMap;
|
import btools.util.FrozenLongMap;
|
||||||
import btools.util.StringUtils;
|
import btools.util.StringUtils;
|
||||||
|
|
||||||
public final class OsmTrack
|
public final class OsmTrack {
|
||||||
{
|
|
||||||
final public static String version = "1.6.3";
|
final public static String version = "1.6.3";
|
||||||
final public static String versionDate = "21122021";
|
final public static String versionDate = "21122021";
|
||||||
|
|
||||||
@ -49,8 +48,7 @@ public final class OsmTrack
|
|||||||
|
|
||||||
public List<OsmNodeNamed> pois = new ArrayList<OsmNodeNamed>();
|
public List<OsmNodeNamed> pois = new ArrayList<OsmNodeNamed>();
|
||||||
|
|
||||||
private static class OsmPathElementHolder
|
private static class OsmPathElementHolder {
|
||||||
{
|
|
||||||
public OsmPathElement node;
|
public OsmPathElement node;
|
||||||
public OsmPathElementHolder nextHolder;
|
public OsmPathElementHolder nextHolder;
|
||||||
}
|
}
|
||||||
@ -71,108 +69,83 @@ public final class OsmTrack
|
|||||||
protected List<MatchedWaypoint> matchedWaypoints;
|
protected List<MatchedWaypoint> matchedWaypoints;
|
||||||
public boolean exportWaypoints = false;
|
public boolean exportWaypoints = false;
|
||||||
|
|
||||||
public void addNode( OsmPathElement node )
|
public void addNode(OsmPathElement node) {
|
||||||
{
|
|
||||||
nodes.add(0, node);
|
nodes.add(0, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerDetourForId( long id, OsmPathElement detour )
|
public void registerDetourForId(long id, OsmPathElement detour) {
|
||||||
{
|
if (detourMap == null) {
|
||||||
if ( detourMap == null )
|
|
||||||
{
|
|
||||||
detourMap = new CompactLongMap<OsmPathElementHolder>();
|
detourMap = new CompactLongMap<OsmPathElementHolder>();
|
||||||
}
|
}
|
||||||
OsmPathElementHolder nh = new OsmPathElementHolder();
|
OsmPathElementHolder nh = new OsmPathElementHolder();
|
||||||
nh.node = detour;
|
nh.node = detour;
|
||||||
OsmPathElementHolder h = detourMap.get(id);
|
OsmPathElementHolder h = detourMap.get(id);
|
||||||
if ( h != null )
|
if (h != null) {
|
||||||
{
|
while (h.nextHolder != null) {
|
||||||
while ( h.nextHolder != null )
|
|
||||||
{
|
|
||||||
h = h.nextHolder;
|
h = h.nextHolder;
|
||||||
}
|
}
|
||||||
h.nextHolder = nh;
|
h.nextHolder = nh;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
detourMap.fastPut(id, nh);
|
detourMap.fastPut(id, nh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void copyDetours( OsmTrack source )
|
public void copyDetours(OsmTrack source) {
|
||||||
{
|
|
||||||
detourMap = source.detourMap == null ? null : new FrozenLongMap<OsmPathElementHolder>(source.detourMap);
|
detourMap = source.detourMap == null ? null : new FrozenLongMap<OsmPathElementHolder>(source.detourMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildMap()
|
public void buildMap() {
|
||||||
{
|
|
||||||
nodesMap = new CompactLongMap<OsmPathElementHolder>();
|
nodesMap = new CompactLongMap<OsmPathElementHolder>();
|
||||||
for ( OsmPathElement node : nodes )
|
for (OsmPathElement node : nodes) {
|
||||||
{
|
|
||||||
long id = node.getIdFromPos();
|
long id = node.getIdFromPos();
|
||||||
OsmPathElementHolder nh = new OsmPathElementHolder();
|
OsmPathElementHolder nh = new OsmPathElementHolder();
|
||||||
nh.node = node;
|
nh.node = node;
|
||||||
OsmPathElementHolder h = nodesMap.get(id);
|
OsmPathElementHolder h = nodesMap.get(id);
|
||||||
if ( h != null )
|
if (h != null) {
|
||||||
{
|
while (h.nextHolder != null) {
|
||||||
while (h.nextHolder != null)
|
|
||||||
{
|
|
||||||
h = h.nextHolder;
|
h = h.nextHolder;
|
||||||
}
|
}
|
||||||
h.nextHolder = nh;
|
h.nextHolder = nh;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nodesMap.fastPut(id, nh);
|
nodesMap.fastPut(id, nh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodesMap = new FrozenLongMap<OsmPathElementHolder>(nodesMap);
|
nodesMap = new FrozenLongMap<OsmPathElementHolder>(nodesMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<String> aggregateMessages()
|
private ArrayList<String> aggregateMessages() {
|
||||||
{
|
|
||||||
ArrayList<String> res = new ArrayList<String>();
|
ArrayList<String> res = new ArrayList<String>();
|
||||||
MessageData current = null;
|
MessageData current = null;
|
||||||
for ( OsmPathElement n : nodes )
|
for (OsmPathElement n : nodes) {
|
||||||
{
|
if (n.message != null && n.message.wayKeyValues != null) {
|
||||||
if ( n.message != null && n.message.wayKeyValues != null )
|
|
||||||
{
|
|
||||||
MessageData md = n.message.copy();
|
MessageData md = n.message.copy();
|
||||||
if ( current != null )
|
if (current != null) {
|
||||||
{
|
if (current.nodeKeyValues != null || !current.wayKeyValues.equals(md.wayKeyValues)) {
|
||||||
if ( current.nodeKeyValues != null || !current.wayKeyValues.equals( md.wayKeyValues ) )
|
|
||||||
{
|
|
||||||
res.add(current.toMessage());
|
res.add(current.toMessage());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
md.add(current);
|
md.add(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current = md;
|
current = md;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( current != null )
|
if (current != null) {
|
||||||
{
|
|
||||||
res.add(current.toMessage());
|
res.add(current.toMessage());
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<String> aggregateSpeedProfile()
|
private ArrayList<String> aggregateSpeedProfile() {
|
||||||
{
|
|
||||||
ArrayList<String> res = new ArrayList<String>();
|
ArrayList<String> res = new ArrayList<String>();
|
||||||
int vmax = -1;
|
int vmax = -1;
|
||||||
int vmaxe = -1;
|
int vmaxe = -1;
|
||||||
int vmin = -1;
|
int vmin = -1;
|
||||||
int extraTime = 0;
|
int extraTime = 0;
|
||||||
for( int i = nodes.size()-1; i > 0; i-- )
|
for (int i = nodes.size() - 1; i > 0; i--) {
|
||||||
{
|
|
||||||
OsmPathElement n = nodes.get(i);
|
OsmPathElement n = nodes.get(i);
|
||||||
MessageData m = n.message;
|
MessageData m = n.message;
|
||||||
int vnode = getVNode(i);
|
int vnode = getVNode(i);
|
||||||
if ( m != null && ( vmax != m.vmax || vmin != m.vmin || vmaxe != m.vmaxExplicit || vnode < m.vmax || extraTime != m.extraTime ) )
|
if (m != null && (vmax != m.vmax || vmin != m.vmin || vmaxe != m.vmaxExplicit || vnode < m.vmax || extraTime != m.extraTime)) {
|
||||||
{
|
|
||||||
vmax = m.vmax;
|
vmax = m.vmax;
|
||||||
vmin = m.vmin;
|
vmin = m.vmin;
|
||||||
vmaxe = m.vmaxExplicit;
|
vmaxe = m.vmaxExplicit;
|
||||||
@ -187,17 +160,14 @@ public final class OsmTrack
|
|||||||
/**
|
/**
|
||||||
* writes the track in binary-format to a file
|
* writes the track in binary-format to a file
|
||||||
*
|
*
|
||||||
* @param filename
|
* @param filename the filename to write to
|
||||||
* the filename to write to
|
|
||||||
*/
|
*/
|
||||||
public void writeBinary( String filename ) throws Exception
|
public void writeBinary(String filename) throws Exception {
|
||||||
{
|
|
||||||
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
|
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
|
||||||
|
|
||||||
endPoint.writeToStream(dos);
|
endPoint.writeToStream(dos);
|
||||||
dos.writeInt(nodes.size());
|
dos.writeInt(nodes.size());
|
||||||
for ( OsmPathElement node : nodes )
|
for (OsmPathElement node : nodes) {
|
||||||
{
|
|
||||||
node.writeToStream(dos);
|
node.writeToStream(dos);
|
||||||
}
|
}
|
||||||
dos.writeLong(nogoChecksums[0]);
|
dos.writeLong(nogoChecksums[0]);
|
||||||
@ -208,33 +178,26 @@ public final class OsmTrack
|
|||||||
dos.close();
|
dos.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OsmTrack readBinary( String filename, OsmNodeNamed newEp, long[] nogoChecksums, long profileChecksum, StringBuilder debugInfo )
|
public static OsmTrack readBinary(String filename, OsmNodeNamed newEp, long[] nogoChecksums, long profileChecksum, StringBuilder debugInfo) {
|
||||||
{
|
|
||||||
OsmTrack t = null;
|
OsmTrack t = null;
|
||||||
if ( filename != null )
|
if (filename != null) {
|
||||||
{
|
|
||||||
File f = new File(filename);
|
File f = new File(filename);
|
||||||
if ( f.exists() )
|
if (f.exists()) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
|
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
|
||||||
MatchedWaypoint ep = MatchedWaypoint.readFromStream(dis);
|
MatchedWaypoint ep = MatchedWaypoint.readFromStream(dis);
|
||||||
int dlon = ep.waypoint.ilon - newEp.ilon;
|
int dlon = ep.waypoint.ilon - newEp.ilon;
|
||||||
int dlat = ep.waypoint.ilat - newEp.ilat;
|
int dlat = ep.waypoint.ilat - newEp.ilat;
|
||||||
boolean targetMatch = dlon < 20 && dlon > -20 && dlat < 20 && dlat > -20;
|
boolean targetMatch = dlon < 20 && dlon > -20 && dlat < 20 && dlat > -20;
|
||||||
if ( debugInfo != null )
|
if (debugInfo != null) {
|
||||||
{
|
|
||||||
debugInfo.append("target-delta = " + dlon + "/" + dlat + " targetMatch=" + targetMatch);
|
debugInfo.append("target-delta = " + dlon + "/" + dlat + " targetMatch=" + targetMatch);
|
||||||
}
|
}
|
||||||
if ( targetMatch )
|
if (targetMatch) {
|
||||||
{
|
|
||||||
t = new OsmTrack();
|
t = new OsmTrack();
|
||||||
t.endPoint = ep;
|
t.endPoint = ep;
|
||||||
int n = dis.readInt();
|
int n = dis.readInt();
|
||||||
OsmPathElement last_pe = null;
|
OsmPathElement last_pe = null;
|
||||||
for ( int i = 0; i < n; i++ )
|
for (int i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
OsmPathElement pe = OsmPathElement.readFromStream(dis);
|
OsmPathElement pe = OsmPathElement.readFromStream(dis);
|
||||||
pe.origin = last_pe;
|
pe.origin = last_pe;
|
||||||
last_pe = pe;
|
last_pe = pe;
|
||||||
@ -246,39 +209,30 @@ public final class OsmTrack
|
|||||||
// check cheecksums, too
|
// check cheecksums, too
|
||||||
long[] al = new long[3];
|
long[] al = new long[3];
|
||||||
long pchecksum = 0;
|
long pchecksum = 0;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
al[0] = dis.readLong();
|
al[0] = dis.readLong();
|
||||||
al[1] = dis.readLong();
|
al[1] = dis.readLong();
|
||||||
al[2] = dis.readLong();
|
al[2] = dis.readLong();
|
||||||
}
|
} catch (EOFException eof) { /* kind of expected */ }
|
||||||
catch (EOFException eof) { /* kind of expected */ }
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
t.isDirty = dis.readBoolean();
|
t.isDirty = dis.readBoolean();
|
||||||
}
|
} catch (EOFException eof) { /* kind of expected */ }
|
||||||
catch (EOFException eof) { /* kind of expected */ }
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
pchecksum = dis.readLong();
|
pchecksum = dis.readLong();
|
||||||
}
|
} catch (EOFException eof) { /* kind of expected */ }
|
||||||
catch (EOFException eof) { /* kind of expected */ }
|
|
||||||
boolean nogoCheckOk = Math.abs(al[0] - nogoChecksums[0]) <= 20
|
boolean nogoCheckOk = Math.abs(al[0] - nogoChecksums[0]) <= 20
|
||||||
&& Math.abs(al[1] - nogoChecksums[1]) <= 20
|
&& Math.abs(al[1] - nogoChecksums[1]) <= 20
|
||||||
&& Math.abs(al[2] - nogoChecksums[2]) <= 20;
|
&& Math.abs(al[2] - nogoChecksums[2]) <= 20;
|
||||||
boolean profileCheckOk = pchecksum == profileChecksum;
|
boolean profileCheckOk = pchecksum == profileChecksum;
|
||||||
|
|
||||||
if ( debugInfo != null )
|
if (debugInfo != null) {
|
||||||
{
|
|
||||||
debugInfo.append(" nogoCheckOk=" + nogoCheckOk + " profileCheckOk=" + profileCheckOk);
|
debugInfo.append(" nogoCheckOk=" + nogoCheckOk + " profileCheckOk=" + profileCheckOk);
|
||||||
debugInfo.append(" al=" + formatLongs(al) + " nogoChecksums=" + formatLongs(nogoChecksums));
|
debugInfo.append(" al=" + formatLongs(al) + " nogoChecksums=" + formatLongs(nogoChecksums));
|
||||||
}
|
}
|
||||||
if (!(nogoCheckOk && profileCheckOk)) return null;
|
if (!(nogoCheckOk && profileCheckOk)) return null;
|
||||||
}
|
}
|
||||||
dis.close();
|
dis.close();
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Exception reading rawTrack: " + e);
|
throw new RuntimeException("Exception reading rawTrack: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,12 +240,10 @@ public final class OsmTrack
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatLongs( long[] al )
|
private static String formatLongs(long[] al) {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append('{');
|
sb.append('{');
|
||||||
for( long l : al )
|
for (long l : al) {
|
||||||
{
|
|
||||||
sb.append(l);
|
sb.append(l);
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
}
|
}
|
||||||
@ -300,26 +252,21 @@ public final class OsmTrack
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addNodes( OsmTrack t )
|
public void addNodes(OsmTrack t) {
|
||||||
{
|
|
||||||
for (OsmPathElement n : t.nodes)
|
for (OsmPathElement n : t.nodes)
|
||||||
addNode(n);
|
addNode(n);
|
||||||
buildMap();
|
buildMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsNode( OsmPos node )
|
public boolean containsNode(OsmPos node) {
|
||||||
{
|
|
||||||
return nodesMap.contains(node.getIdFromPos());
|
return nodesMap.contains(node.getIdFromPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmPathElement getLink( long n1, long n2 )
|
public OsmPathElement getLink(long n1, long n2) {
|
||||||
{
|
|
||||||
OsmPathElementHolder h = nodesMap.get(n2);
|
OsmPathElementHolder h = nodesMap.get(n2);
|
||||||
while (h != null)
|
while (h != null) {
|
||||||
{
|
|
||||||
OsmPathElement e1 = h.node.origin;
|
OsmPathElement e1 = h.node.origin;
|
||||||
if ( e1 != null && e1.getIdFromPos() == n1 )
|
if (e1 != null && e1.getIdFromPos() == n1) {
|
||||||
{
|
|
||||||
return h.node;
|
return h.node;
|
||||||
}
|
}
|
||||||
h = h.nextHolder;
|
h = h.nextHolder;
|
||||||
@ -327,15 +274,12 @@ public final class OsmTrack
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendTrack( OsmTrack t )
|
public void appendTrack(OsmTrack t) {
|
||||||
{
|
|
||||||
int ourSize = nodes.size();
|
int ourSize = nodes.size();
|
||||||
float t0 = ourSize > 0 ? nodes.get(ourSize - 1).getTime() : 0;
|
float t0 = ourSize > 0 ? nodes.get(ourSize - 1).getTime() : 0;
|
||||||
float e0 = ourSize > 0 ? nodes.get(ourSize - 1).getEnergy() : 0;
|
float e0 = ourSize > 0 ? nodes.get(ourSize - 1).getEnergy() : 0;
|
||||||
for ( int i = 0; i < t.nodes.size(); i++ )
|
for (int i = 0; i < t.nodes.size(); i++) {
|
||||||
{
|
if (i > 0 || ourSize == 0) {
|
||||||
if ( i > 0 || ourSize == 0 )
|
|
||||||
{
|
|
||||||
OsmPathElement e = t.nodes.get(i);
|
OsmPathElement e = t.nodes.get(i);
|
||||||
e.setTime(e.getTime() + t0);
|
e.setTime(e.getTime() + t0);
|
||||||
e.setEnergy(e.getEnergy() + e0);
|
e.setEnergy(e.getEnergy() + e0);
|
||||||
@ -343,19 +287,15 @@ public final class OsmTrack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( t.voiceHints != null )
|
if (t.voiceHints != null) {
|
||||||
{
|
|
||||||
if (ourSize > 0) {
|
if (ourSize > 0) {
|
||||||
for (VoiceHint hint : t.voiceHints.list) {
|
for (VoiceHint hint : t.voiceHints.list) {
|
||||||
hint.indexInTrack = hint.indexInTrack + ourSize - 1;
|
hint.indexInTrack = hint.indexInTrack + ourSize - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( voiceHints == null )
|
if (voiceHints == null) {
|
||||||
{
|
|
||||||
voiceHints = t.voiceHints;
|
voiceHints = t.voiceHints;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
voiceHints.list.addAll(t.voiceHints.list);
|
voiceHints.list.addAll(t.voiceHints.list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -379,39 +319,31 @@ public final class OsmTrack
|
|||||||
/**
|
/**
|
||||||
* writes the track in gpx-format to a file
|
* writes the track in gpx-format to a file
|
||||||
*
|
*
|
||||||
* @param filename
|
* @param filename the filename to write to
|
||||||
* the filename to write to
|
|
||||||
*/
|
*/
|
||||||
public void writeGpx( String filename ) throws Exception
|
public void writeGpx(String filename) throws Exception {
|
||||||
{
|
|
||||||
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
|
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
|
||||||
formatAsGpx(bw);
|
formatAsGpx(bw);
|
||||||
bw.close();
|
bw.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String formatAsGpx()
|
public String formatAsGpx() {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
StringWriter sw = new StringWriter(8192);
|
StringWriter sw = new StringWriter(8192);
|
||||||
BufferedWriter bw = new BufferedWriter(sw);
|
BufferedWriter bw = new BufferedWriter(sw);
|
||||||
formatAsGpx(bw);
|
formatAsGpx(bw);
|
||||||
bw.close();
|
bw.close();
|
||||||
return sw.toString();
|
return sw.toString();
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch( Exception e )
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String formatAsGpx( BufferedWriter sb ) throws IOException
|
public String formatAsGpx(BufferedWriter sb) throws IOException {
|
||||||
{
|
|
||||||
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
|
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
|
||||||
|
|
||||||
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||||
for ( int i = messageList.size() - 1; i >= 0; i-- )
|
for (int i = messageList.size() - 1; i >= 0; i--) {
|
||||||
{
|
|
||||||
String message = messageList.get(i);
|
String message = messageList.get(i);
|
||||||
if (i < messageList.size() - 1)
|
if (i < messageList.size() - 1)
|
||||||
message = "(alt-index " + i + ": " + message + " )";
|
message = "(alt-index " + i + ": " + message + " )";
|
||||||
@ -424,8 +356,7 @@ public final class OsmTrack
|
|||||||
sb.append("<!-- $transport-mode$").append(voiceHints.getTransportMode()).append("$ -->\n");
|
sb.append("<!-- $transport-mode$").append(voiceHints.getTransportMode()).append("$ -->\n");
|
||||||
sb.append("<!-- cmd idx lon lat d2next geometry -->\n");
|
sb.append("<!-- cmd idx lon lat d2next geometry -->\n");
|
||||||
sb.append("<!-- $turn-instruction-start$\n");
|
sb.append("<!-- $turn-instruction-start$\n");
|
||||||
for( VoiceHint hint: voiceHints.list )
|
for (VoiceHint hint : voiceHints.list) {
|
||||||
{
|
|
||||||
sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(), hint.indexInTrack,
|
sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(), hint.indexInTrack,
|
||||||
formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry()));
|
formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry()));
|
||||||
}
|
}
|
||||||
@ -440,12 +371,9 @@ public final class OsmTrack
|
|||||||
}
|
}
|
||||||
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
|
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
|
||||||
|
|
||||||
if ( turnInstructionMode == 3)
|
if (turnInstructionMode == 3) {
|
||||||
{
|
|
||||||
sb.append(" creator=\"OsmAndRouter\" version=\"1.1\">\n");
|
sb.append(" creator=\"OsmAndRouter\" version=\"1.1\">\n");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.append(" creator=\"BRouter-" + version + "\" version=\"1.1\">\n");
|
sb.append(" creator=\"BRouter-" + version + "\" version=\"1.1\">\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,8 +397,7 @@ public final class OsmTrack
|
|||||||
}
|
}
|
||||||
sb.append(" <offset>0</offset>\n </extensions>\n </rtept>\n");
|
sb.append(" <offset>0</offset>\n </extensions>\n </rtept>\n");
|
||||||
|
|
||||||
for( int i = 0 ; i < voiceHints.list.size(); i++ )
|
for (int i = 0; i < voiceHints.list.size(); i++) {
|
||||||
{
|
|
||||||
VoiceHint hint = voiceHints.list.get(i);
|
VoiceHint hint = voiceHints.list.get(i);
|
||||||
sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
|
sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
|
||||||
.append(formatILon(hint.ilon)).append("\">\n")
|
.append(formatILon(hint.ilon)).append("\">\n")
|
||||||
@ -500,8 +427,7 @@ public final class OsmTrack
|
|||||||
{
|
{
|
||||||
float lastRteTime = getVoiceHintTime(0);
|
float lastRteTime = getVoiceHintTime(0);
|
||||||
|
|
||||||
for( int i=0; i<voiceHints.list.size(); i++ )
|
for (int i = 0; i < voiceHints.list.size(); i++) {
|
||||||
{
|
|
||||||
VoiceHint hint = voiceHints.list.get(i);
|
VoiceHint hint = voiceHints.list.get(i);
|
||||||
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
|
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
|
||||||
.append(formatILat(hint.ilat)).append("\">")
|
.append(formatILat(hint.ilat)).append("\">")
|
||||||
@ -523,8 +449,7 @@ public final class OsmTrack
|
|||||||
}
|
}
|
||||||
if (turnInstructionMode == 5) // gpsies style
|
if (turnInstructionMode == 5) // gpsies style
|
||||||
{
|
{
|
||||||
for( VoiceHint hint: voiceHints.list )
|
for (VoiceHint hint : voiceHints.list) {
|
||||||
{
|
|
||||||
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
|
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
|
||||||
.append(formatILat(hint.ilat)).append("\">")
|
.append(formatILat(hint.ilat)).append("\">")
|
||||||
.append("<name>").append(hint.getMessageString()).append("</name>")
|
.append("<name>").append(hint.getMessageString()).append("</name>")
|
||||||
@ -536,8 +461,7 @@ public final class OsmTrack
|
|||||||
|
|
||||||
if (turnInstructionMode == 6) // orux style
|
if (turnInstructionMode == 6) // orux style
|
||||||
{
|
{
|
||||||
for( VoiceHint hint: voiceHints.list )
|
for (VoiceHint hint : voiceHints.list) {
|
||||||
{
|
|
||||||
sb.append(" <wpt lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
|
sb.append(" <wpt lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
|
||||||
.append(formatILon(hint.ilon)).append("\">")
|
.append(formatILon(hint.ilon)).append("\">")
|
||||||
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
|
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
|
||||||
@ -551,8 +475,7 @@ public final class OsmTrack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i=0; i<=pois.size() - 1; i++ )
|
for (int i = 0; i <= pois.size() - 1; i++) {
|
||||||
{
|
|
||||||
OsmNodeNamed poi = pois.get(i);
|
OsmNodeNamed poi = pois.get(i);
|
||||||
sb.append(" <wpt lon=\"").append(formatILon(poi.ilon)).append("\" lat=\"")
|
sb.append(" <wpt lon=\"").append(formatILon(poi.ilon)).append("\" lat=\"")
|
||||||
.append(formatILat(poi.ilat)).append("\">\n")
|
.append(formatILat(poi.ilat)).append("\">\n")
|
||||||
@ -560,23 +483,17 @@ public final class OsmTrack
|
|||||||
.append(" </wpt>\n");
|
.append(" </wpt>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( exportWaypoints )
|
if (exportWaypoints) {
|
||||||
{
|
for (int i = 0; i <= matchedWaypoints.size() - 1; i++) {
|
||||||
for( int i=0; i<=matchedWaypoints.size() - 1; i++ )
|
|
||||||
{
|
|
||||||
MatchedWaypoint wt = matchedWaypoints.get(i);
|
MatchedWaypoint wt = matchedWaypoints.get(i);
|
||||||
sb.append(" <wpt lon=\"").append(formatILon(wt.waypoint.ilon)).append("\" lat=\"")
|
sb.append(" <wpt lon=\"").append(formatILon(wt.waypoint.ilon)).append("\" lat=\"")
|
||||||
.append(formatILat(wt.waypoint.ilat)).append("\">\n")
|
.append(formatILat(wt.waypoint.ilat)).append("\">\n")
|
||||||
.append(" <name>").append(StringUtils.escapeXml10(wt.name)).append("</name>\n");
|
.append(" <name>").append(StringUtils.escapeXml10(wt.name)).append("</name>\n");
|
||||||
if(i == 0)
|
if (i == 0) {
|
||||||
{
|
|
||||||
sb.append(" <type>from</type>\n");
|
sb.append(" <type>from</type>\n");
|
||||||
}
|
} else if (i == matchedWaypoints.size() - 1) {
|
||||||
else if (i == matchedWaypoints.size() - 1)
|
|
||||||
{
|
|
||||||
sb.append(" <type>to</type>\n");
|
sb.append(" <type>to</type>\n");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
sb.append(" <type>via</type>\n");
|
sb.append(" <type>via</type>\n");
|
||||||
}
|
}
|
||||||
sb.append(" </wpt>\n");
|
sb.append(" </wpt>\n");
|
||||||
@ -589,8 +506,7 @@ public final class OsmTrack
|
|||||||
sb.append(" <type>").append(voiceHints.getTransportMode()).append("</type>\n");
|
sb.append(" <type>").append(voiceHints.getTransportMode()).append("</type>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( turnInstructionMode == 2 )
|
if (turnInstructionMode == 2) {
|
||||||
{
|
|
||||||
sb.append(" <extensions>\n");
|
sb.append(" <extensions>\n");
|
||||||
sb.append(" <locus:rteComputeType>").append("" + voiceHints.getLocusRouteType()).append("</locus:rteComputeType>\n");
|
sb.append(" <locus:rteComputeType>").append("" + voiceHints.getLocusRouteType()).append("</locus:rteComputeType>\n");
|
||||||
sb.append(" <locus:rteSimpleRoundabouts>1</locus:rteSimpleRoundabouts>\n");
|
sb.append(" <locus:rteSimpleRoundabouts>1</locus:rteSimpleRoundabouts>\n");
|
||||||
@ -599,16 +515,13 @@ public final class OsmTrack
|
|||||||
|
|
||||||
sb.append(" <trkseg>\n");
|
sb.append(" <trkseg>\n");
|
||||||
|
|
||||||
for ( int idx = 0; idx < nodes.size(); idx++ )
|
for (int idx = 0; idx < nodes.size(); idx++) {
|
||||||
{
|
|
||||||
OsmPathElement n = nodes.get(idx);
|
OsmPathElement n = nodes.get(idx);
|
||||||
String sele = n.getSElev() == Short.MIN_VALUE ? "" : "<ele>" + n.getElev() + "</ele>";
|
String sele = n.getSElev() == Short.MIN_VALUE ? "" : "<ele>" + n.getElev() + "</ele>";
|
||||||
if (turnInstructionMode == 1) // trkpt/sym style
|
if (turnInstructionMode == 1) // trkpt/sym style
|
||||||
{
|
{
|
||||||
for ( VoiceHint hint : voiceHints.list )
|
for (VoiceHint hint : voiceHints.list) {
|
||||||
{
|
if (hint.indexInTrack == idx) {
|
||||||
if ( hint.indexInTrack == idx )
|
|
||||||
{
|
|
||||||
sele += "<sym>" + hint.getCommandString() + "</sym>";
|
sele += "<sym>" + hint.getCommandString() + "</sym>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -624,16 +537,14 @@ public final class OsmTrack
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeKml( String filename ) throws Exception
|
public void writeKml(String filename) throws Exception {
|
||||||
{
|
|
||||||
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
|
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
|
||||||
|
|
||||||
bw.write(formatAsKml());
|
bw.write(formatAsKml());
|
||||||
bw.close();
|
bw.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String formatAsKml()
|
public String formatAsKml() {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder(8192);
|
StringBuilder sb = new StringBuilder(8192);
|
||||||
|
|
||||||
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||||
@ -657,8 +568,7 @@ public final class OsmTrack
|
|||||||
sb.append(" <tessellate>1</tessellate>\n");
|
sb.append(" <tessellate>1</tessellate>\n");
|
||||||
sb.append(" <coordinates>");
|
sb.append(" <coordinates>");
|
||||||
|
|
||||||
for ( OsmPathElement n : nodes )
|
for (OsmPathElement n : nodes) {
|
||||||
{
|
|
||||||
sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
|
sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,8 +576,7 @@ public final class OsmTrack
|
|||||||
sb.append(" </LineString>\n");
|
sb.append(" </LineString>\n");
|
||||||
sb.append(" </Placemark>\n");
|
sb.append(" </Placemark>\n");
|
||||||
sb.append(" </Folder>\n");
|
sb.append(" </Folder>\n");
|
||||||
if ( exportWaypoints || !pois.isEmpty() )
|
if (exportWaypoints || !pois.isEmpty()) {
|
||||||
{
|
|
||||||
if (!pois.isEmpty()) {
|
if (!pois.isEmpty()) {
|
||||||
sb.append(" <Folder>\n");
|
sb.append(" <Folder>\n");
|
||||||
sb.append(" <name>poi</name>\n");
|
sb.append(" <name>poi</name>\n");
|
||||||
@ -678,8 +587,7 @@ public final class OsmTrack
|
|||||||
sb.append(" </Folder>\n");
|
sb.append(" </Folder>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exportWaypoints)
|
if (exportWaypoints) {
|
||||||
{
|
|
||||||
int size = matchedWaypoints.size();
|
int size = matchedWaypoints.size();
|
||||||
createFolder(sb, "start", matchedWaypoints.subList(0, 1));
|
createFolder(sb, "start", matchedWaypoints.subList(0, 1));
|
||||||
if (matchedWaypoints.size() > 2) {
|
if (matchedWaypoints.size() > 2) {
|
||||||
@ -715,8 +623,7 @@ public final class OsmTrack
|
|||||||
|
|
||||||
public List<String> iternity;
|
public List<String> iternity;
|
||||||
|
|
||||||
public void writeJson( String filename ) throws Exception
|
public void writeJson(String filename) throws Exception {
|
||||||
{
|
|
||||||
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
|
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
|
||||||
|
|
||||||
bw.write(formatAsGeoJson());
|
bw.write(formatAsGeoJson());
|
||||||
@ -724,8 +631,7 @@ public final class OsmTrack
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String formatAsGeoJson()
|
public String formatAsGeoJson() {
|
||||||
{
|
|
||||||
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
|
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(8192);
|
StringBuilder sb = new StringBuilder(8192);
|
||||||
@ -744,11 +650,9 @@ public final class OsmTrack
|
|||||||
sb.append(" \"total-time\": \"").append(getTotalSeconds()).append("\",\n");
|
sb.append(" \"total-time\": \"").append(getTotalSeconds()).append("\",\n");
|
||||||
sb.append(" \"total-energy\": \"").append(energy).append("\",\n");
|
sb.append(" \"total-energy\": \"").append(energy).append("\",\n");
|
||||||
sb.append(" \"cost\": \"").append(cost).append("\",\n");
|
sb.append(" \"cost\": \"").append(cost).append("\",\n");
|
||||||
if ( voiceHints != null && !voiceHints.list.isEmpty() )
|
if (voiceHints != null && !voiceHints.list.isEmpty()) {
|
||||||
{
|
|
||||||
sb.append(" \"voicehints\": [\n");
|
sb.append(" \"voicehints\": [\n");
|
||||||
for( VoiceHint hint: voiceHints.list )
|
for (VoiceHint hint : voiceHints.list) {
|
||||||
{
|
|
||||||
sb.append(" [");
|
sb.append(" [");
|
||||||
sb.append(hint.indexInTrack);
|
sb.append(hint.indexInTrack);
|
||||||
sb.append(',').append(hint.getCommand());
|
sb.append(',').append(hint.getCommand());
|
||||||
@ -770,11 +674,9 @@ public final class OsmTrack
|
|||||||
if (showSpeedProfile) // set in profile
|
if (showSpeedProfile) // set in profile
|
||||||
{
|
{
|
||||||
ArrayList<String> sp = aggregateSpeedProfile();
|
ArrayList<String> sp = aggregateSpeedProfile();
|
||||||
if ( sp.size() > 0 )
|
if (sp.size() > 0) {
|
||||||
{
|
|
||||||
sb.append(" \"speedprofile\": [\n");
|
sb.append(" \"speedprofile\": [\n");
|
||||||
for( int i=sp.size()-1; i>=0; i-- )
|
for (int i = sp.size() - 1; i >= 0; i--) {
|
||||||
{
|
|
||||||
sb.append(" [").append(sp.get(i)).append(i > 0 ? "],\n" : "]\n");
|
sb.append(" [").append(sp.get(i)).append(i > 0 ? "],\n" : "]\n");
|
||||||
}
|
}
|
||||||
sb.append(" ],\n");
|
sb.append(" ],\n");
|
||||||
@ -784,8 +686,7 @@ public final class OsmTrack
|
|||||||
{
|
{
|
||||||
sb.append(" \"messages\": [\n");
|
sb.append(" \"messages\": [\n");
|
||||||
sb.append(" [\"").append(MESSAGES_HEADER.replaceAll("\t", "\", \"")).append("\"],\n");
|
sb.append(" [\"").append(MESSAGES_HEADER.replaceAll("\t", "\", \"")).append("\"],\n");
|
||||||
for ( String m : aggregateMessages() )
|
for (String m : aggregateMessages()) {
|
||||||
{
|
|
||||||
sb.append(" [\"").append(m.replaceAll("\t", "\", \"")).append("\"],\n");
|
sb.append(" [\"").append(m.replaceAll("\t", "\", \"")).append("\"],\n");
|
||||||
}
|
}
|
||||||
sb.deleteCharAt(sb.lastIndexOf(","));
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
@ -807,11 +708,9 @@ public final class OsmTrack
|
|||||||
|
|
||||||
sb.append(" },\n");
|
sb.append(" },\n");
|
||||||
|
|
||||||
if ( iternity != null )
|
if (iternity != null) {
|
||||||
{
|
|
||||||
sb.append(" \"iternity\": [\n");
|
sb.append(" \"iternity\": [\n");
|
||||||
for ( String s : iternity )
|
for (String s : iternity) {
|
||||||
{
|
|
||||||
sb.append(" \"").append(s).append("\",\n");
|
sb.append(" \"").append(s).append("\",\n");
|
||||||
}
|
}
|
||||||
sb.deleteCharAt(sb.lastIndexOf(","));
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
@ -822,18 +721,15 @@ public final class OsmTrack
|
|||||||
sb.append(" \"coordinates\": [\n");
|
sb.append(" \"coordinates\": [\n");
|
||||||
|
|
||||||
OsmPathElement nn = null;
|
OsmPathElement nn = null;
|
||||||
for ( OsmPathElement n : nodes )
|
for (OsmPathElement n : nodes) {
|
||||||
{
|
|
||||||
String sele = n.getSElev() == Short.MIN_VALUE ? "" : ", " + n.getElev();
|
String sele = n.getSElev() == Short.MIN_VALUE ? "" : ", " + n.getElev();
|
||||||
if (showspeed) // hack: show speed instead of elevation
|
if (showspeed) // hack: show speed instead of elevation
|
||||||
{
|
{
|
||||||
double speed = 0;
|
double speed = 0;
|
||||||
if ( nn != null )
|
if (nn != null) {
|
||||||
{
|
|
||||||
int dist = n.calcDistance(nn);
|
int dist = n.calcDistance(nn);
|
||||||
float dt = n.getTime() - nn.getTime();
|
float dt = n.getTime() - nn.getTime();
|
||||||
if ( dt != 0.f )
|
if (dt != 0.f) {
|
||||||
{
|
|
||||||
speed = ((3.6f * dist) / dt + 0.5);
|
speed = ((3.6f * dist) / dt + 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -847,11 +743,9 @@ public final class OsmTrack
|
|||||||
|
|
||||||
sb.append(" ]\n");
|
sb.append(" ]\n");
|
||||||
sb.append(" }\n");
|
sb.append(" }\n");
|
||||||
if ( exportWaypoints || !pois.isEmpty())
|
if (exportWaypoints || !pois.isEmpty()) {
|
||||||
{
|
|
||||||
sb.append(" },\n");
|
sb.append(" },\n");
|
||||||
for( int i=0; i<=pois.size() - 1; i++ )
|
for (int i = 0; i <= pois.size() - 1; i++) {
|
||||||
{
|
|
||||||
OsmNodeNamed poi = pois.get(i);
|
OsmNodeNamed poi = pois.get(i);
|
||||||
addFeature(sb, "poi", poi.name, poi.ilat, poi.ilon);
|
addFeature(sb, "poi", poi.name, poi.ilat, poi.ilon);
|
||||||
if (i < matchedWaypoints.size() - 1) {
|
if (i < matchedWaypoints.size() - 1) {
|
||||||
@ -878,8 +772,7 @@ public final class OsmTrack
|
|||||||
sb.append(" \n");
|
sb.append(" \n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
sb.append(" }\n");
|
sb.append(" }\n");
|
||||||
}
|
}
|
||||||
sb.append(" ]\n");
|
sb.append(" ]\n");
|
||||||
@ -905,8 +798,7 @@ public final class OsmTrack
|
|||||||
sb.append(" }");
|
sb.append(" }");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getVNode( int i )
|
private int getVNode(int i) {
|
||||||
{
|
|
||||||
MessageData m1 = i + 1 < nodes.size() ? nodes.get(i + 1).message : null;
|
MessageData m1 = i + 1 < nodes.size() ? nodes.get(i + 1).message : null;
|
||||||
MessageData m0 = i < nodes.size() ? nodes.get(i).message : null;
|
MessageData m0 = i < nodes.size() ? nodes.get(i).message : null;
|
||||||
int vnode0 = m1 == null ? 999 : m1.vnode0;
|
int vnode0 = m1 == null ? 999 : m1.vnode0;
|
||||||
@ -914,19 +806,16 @@ public final class OsmTrack
|
|||||||
return vnode0 < vnode1 ? vnode0 : vnode1;
|
return vnode0 < vnode1 ? vnode0 : vnode1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTotalSeconds()
|
private int getTotalSeconds() {
|
||||||
{
|
|
||||||
float s = nodes.size() < 2 ? 0 : nodes.get(nodes.size() - 1).getTime() - nodes.get(0).getTime();
|
float s = nodes.size() < 2 ? 0 : nodes.get(nodes.size() - 1).getTime() - nodes.get(0).getTime();
|
||||||
return (int) (s + 0.5);
|
return (int) (s + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFormattedTime()
|
public String getFormattedTime() {
|
||||||
{
|
|
||||||
return format1(getTotalSeconds() / 60.) + "m";
|
return format1(getTotalSeconds() / 60.) + "m";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFormattedTime2()
|
public String getFormattedTime2() {
|
||||||
{
|
|
||||||
int seconds = (int) (getTotalSeconds() + 0.5);
|
int seconds = (int) (getTotalSeconds() + 0.5);
|
||||||
int hours = seconds / 3600;
|
int hours = seconds / 3600;
|
||||||
int minutes = (seconds - hours * 3600) / 60;
|
int minutes = (seconds - hours * 3600) / 60;
|
||||||
@ -941,30 +830,25 @@ public final class OsmTrack
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFormattedEnergy()
|
public String getFormattedEnergy() {
|
||||||
{
|
|
||||||
return format1(energy / 3600000.) + "kwh";
|
return format1(energy / 3600000.) + "kwh";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatILon( int ilon )
|
private static String formatILon(int ilon) {
|
||||||
{
|
|
||||||
return formatPos(ilon - 180000000);
|
return formatPos(ilon - 180000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatILat( int ilat )
|
private static String formatILat(int ilat) {
|
||||||
{
|
|
||||||
return formatPos(ilat - 90000000);
|
return formatPos(ilat - 90000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatPos( int p )
|
private static String formatPos(int p) {
|
||||||
{
|
|
||||||
boolean negative = p < 0;
|
boolean negative = p < 0;
|
||||||
if (negative)
|
if (negative)
|
||||||
p = -p;
|
p = -p;
|
||||||
char[] ac = new char[12];
|
char[] ac = new char[12];
|
||||||
int i = 11;
|
int i = 11;
|
||||||
while (p != 0 || i > 3)
|
while (p != 0 || i > 3) {
|
||||||
{
|
|
||||||
ac[i--] = (char) ('0' + (p % 10));
|
ac[i--] = (char) ('0' + (p % 10));
|
||||||
p /= 10;
|
p /= 10;
|
||||||
if (i == 5)
|
if (i == 5)
|
||||||
@ -975,59 +859,48 @@ public final class OsmTrack
|
|||||||
return new String(ac, i + 1, 11 - i);
|
return new String(ac, i + 1, 11 - i);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String format1( double n )
|
private String format1(double n) {
|
||||||
{
|
|
||||||
String s = "" + (long) (n * 10 + 0.5);
|
String s = "" + (long) (n * 10 + 0.5);
|
||||||
int len = s.length();
|
int len = s.length();
|
||||||
return s.substring(0, len - 1) + "." + s.charAt(len - 1);
|
return s.substring(0, len - 1) + "." + s.charAt(len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpMessages( String filename, RoutingContext rc ) throws Exception
|
public void dumpMessages(String filename, RoutingContext rc) throws Exception {
|
||||||
{
|
|
||||||
BufferedWriter bw = filename == null ? null : new BufferedWriter(new FileWriter(filename));
|
BufferedWriter bw = filename == null ? null : new BufferedWriter(new FileWriter(filename));
|
||||||
writeMessages(bw, rc);
|
writeMessages(bw, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeMessages( BufferedWriter bw, RoutingContext rc ) throws Exception
|
public void writeMessages(BufferedWriter bw, RoutingContext rc) throws Exception {
|
||||||
{
|
|
||||||
dumpLine(bw, MESSAGES_HEADER);
|
dumpLine(bw, MESSAGES_HEADER);
|
||||||
for ( String m : aggregateMessages() )
|
for (String m : aggregateMessages()) {
|
||||||
{
|
|
||||||
dumpLine(bw, m);
|
dumpLine(bw, m);
|
||||||
}
|
}
|
||||||
if (bw != null)
|
if (bw != null)
|
||||||
bw.close();
|
bw.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpLine( BufferedWriter bw, String s ) throws Exception
|
private void dumpLine(BufferedWriter bw, String s) throws Exception {
|
||||||
{
|
if (bw == null) {
|
||||||
if ( bw == null )
|
|
||||||
{
|
|
||||||
System.out.println(s);
|
System.out.println(s);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
bw.write(s);
|
bw.write(s);
|
||||||
bw.write("\n");
|
bw.write("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readGpx( String filename ) throws Exception
|
public void readGpx(String filename) throws Exception {
|
||||||
{
|
|
||||||
File f = new File(filename);
|
File f = new File(filename);
|
||||||
if (!f.exists())
|
if (!f.exists())
|
||||||
return;
|
return;
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
|
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
|
||||||
|
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
String line = br.readLine();
|
String line = br.readLine();
|
||||||
if (line == null)
|
if (line == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
int idx0 = line.indexOf("<trkpt lon=\"");
|
int idx0 = line.indexOf("<trkpt lon=\"");
|
||||||
if ( idx0 >= 0 )
|
if (idx0 >= 0) {
|
||||||
{
|
|
||||||
idx0 += 12;
|
idx0 += 12;
|
||||||
int idx1 = line.indexOf('"', idx0);
|
int idx1 = line.indexOf('"', idx0);
|
||||||
int ilon = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 180.) * 1000000. + 0.5);
|
int ilon = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 180.) * 1000000. + 0.5);
|
||||||
@ -1043,12 +916,10 @@ public final class OsmTrack
|
|||||||
br.close();
|
br.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equalsTrack( OsmTrack t )
|
public boolean equalsTrack(OsmTrack t) {
|
||||||
{
|
|
||||||
if (nodes.size() != t.nodes.size())
|
if (nodes.size() != t.nodes.size())
|
||||||
return false;
|
return false;
|
||||||
for ( int i = 0; i < nodes.size(); i++ )
|
for (int i = 0; i < nodes.size(); i++) {
|
||||||
{
|
|
||||||
OsmPathElement e1 = nodes.get(i);
|
OsmPathElement e1 = nodes.get(i);
|
||||||
OsmPathElement e2 = t.nodes.get(i);
|
OsmPathElement e2 = t.nodes.get(i);
|
||||||
if (e1.getILon() != e2.getILon() || e1.getILat() != e2.getILat())
|
if (e1.getILon() != e2.getILon() || e1.getILat() != e2.getILat())
|
||||||
@ -1057,28 +928,23 @@ public final class OsmTrack
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepareSpeedProfile( RoutingContext rc )
|
public void prepareSpeedProfile(RoutingContext rc) {
|
||||||
{
|
|
||||||
// sendSpeedProfile = rc.keyValues != null && rc.keyValues.containsKey( "vmax" );
|
// sendSpeedProfile = rc.keyValues != null && rc.keyValues.containsKey( "vmax" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processVoiceHints( RoutingContext rc )
|
public void processVoiceHints(RoutingContext rc) {
|
||||||
{
|
|
||||||
voiceHints = new VoiceHintList();
|
voiceHints = new VoiceHintList();
|
||||||
voiceHints.setTransportMode(rc.carMode, rc.bikeMode);
|
voiceHints.setTransportMode(rc.carMode, rc.bikeMode);
|
||||||
voiceHints.turnInstructionMode = rc.turnInstructionMode;
|
voiceHints.turnInstructionMode = rc.turnInstructionMode;
|
||||||
|
|
||||||
if ( detourMap == null )
|
if (detourMap == null) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int nodeNr = nodes.size() - 1;
|
int nodeNr = nodes.size() - 1;
|
||||||
OsmPathElement node = nodes.get(nodeNr);
|
OsmPathElement node = nodes.get(nodeNr);
|
||||||
List<VoiceHint> inputs = new ArrayList<VoiceHint>();
|
List<VoiceHint> inputs = new ArrayList<VoiceHint>();
|
||||||
while (node != null)
|
while (node != null) {
|
||||||
{
|
if (node.origin != null) {
|
||||||
if ( node.origin != null )
|
|
||||||
{
|
|
||||||
VoiceHint input = new VoiceHint();
|
VoiceHint input = new VoiceHint();
|
||||||
inputs.add(input);
|
inputs.add(input);
|
||||||
input.ilat = node.origin.getILat();
|
input.ilat = node.origin.getILat();
|
||||||
@ -1089,11 +955,9 @@ public final class OsmTrack
|
|||||||
input.oldWay = node.origin.message == null ? node.message : node.origin.message;
|
input.oldWay = node.origin.message == null ? node.message : node.origin.message;
|
||||||
|
|
||||||
OsmPathElementHolder detours = detourMap.get(node.origin.getIdFromPos());
|
OsmPathElementHolder detours = detourMap.get(node.origin.getIdFromPos());
|
||||||
if ( detours != null )
|
if (detours != null) {
|
||||||
{
|
|
||||||
OsmPathElementHolder h = detours;
|
OsmPathElementHolder h = detours;
|
||||||
while (h != null)
|
while (h != null) {
|
||||||
{
|
|
||||||
OsmPathElement e = h.node;
|
OsmPathElement e = h.node;
|
||||||
input.addBadWay(startSection(e, node.origin));
|
input.addBadWay(startSection(e, node.origin));
|
||||||
h = h.nextHolder;
|
h = h.nextHolder;
|
||||||
@ -1105,43 +969,34 @@ public final class OsmTrack
|
|||||||
|
|
||||||
VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts);
|
VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts);
|
||||||
List<VoiceHint> results = vproc.process(inputs);
|
List<VoiceHint> results = vproc.process(inputs);
|
||||||
for( VoiceHint hint : results )
|
for (VoiceHint hint : results) {
|
||||||
{
|
|
||||||
voiceHints.list.add(hint);
|
voiceHints.list.add(hint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getVoiceHintTime( int i )
|
private float getVoiceHintTime(int i) {
|
||||||
{
|
if (voiceHints.list.isEmpty()) {
|
||||||
if ( voiceHints.list.isEmpty() )
|
|
||||||
{
|
|
||||||
return 0f;
|
return 0f;
|
||||||
}
|
}
|
||||||
if ( i < voiceHints.list.size() )
|
if (i < voiceHints.list.size()) {
|
||||||
{
|
|
||||||
return voiceHints.list.get(i).getTime();
|
return voiceHints.list.get(i).getTime();
|
||||||
}
|
}
|
||||||
if ( nodes.isEmpty() )
|
if (nodes.isEmpty()) {
|
||||||
{
|
|
||||||
return 0f;
|
return 0f;
|
||||||
}
|
}
|
||||||
return nodes.get(nodes.size() - 1).getTime();
|
return nodes.get(nodes.size() - 1).getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private MessageData startSection( OsmPathElement element, OsmPathElement root )
|
private MessageData startSection(OsmPathElement element, OsmPathElement root) {
|
||||||
{
|
|
||||||
OsmPathElement e = element;
|
OsmPathElement e = element;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while( e != null && e.origin != null )
|
while (e != null && e.origin != null) {
|
||||||
{
|
if (e.origin.getILat() == root.getILat() && e.origin.getILon() == root.getILon()) {
|
||||||
if ( e.origin.getILat() == root.getILat() && e.origin.getILon() == root.getILon() )
|
|
||||||
{
|
|
||||||
return e.message;
|
return e.message;
|
||||||
}
|
}
|
||||||
e = e.origin;
|
e = e.origin;
|
||||||
if ( cnt++ == 1000000 )
|
if (cnt++ == 1000000) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("ups: " + root + "->" + element);
|
throw new IllegalArgumentException("ups: " + root + "->" + element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import btools.expressions.BExpressionContextNode;
|
|||||||
import btools.expressions.BExpressionContextWay;
|
import btools.expressions.BExpressionContextWay;
|
||||||
import btools.expressions.BExpressionMetaData;
|
import btools.expressions.BExpressionMetaData;
|
||||||
|
|
||||||
public final class ProfileCache
|
public final class ProfileCache {
|
||||||
{
|
|
||||||
|
|
||||||
private static File lastLookupFile;
|
private static File lastLookupFile;
|
||||||
private static long lastLookupTimestamp;
|
private static long lastLookupTimestamp;
|
||||||
@ -27,23 +26,18 @@ public final class ProfileCache
|
|||||||
private static ProfileCache[] apc = new ProfileCache[1];
|
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];
|
apc = new ProfileCache[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized boolean parseProfile( RoutingContext rc )
|
public static synchronized boolean parseProfile(RoutingContext rc) {
|
||||||
{
|
|
||||||
String profileBaseDir = System.getProperty("profileBaseDir");
|
String profileBaseDir = System.getProperty("profileBaseDir");
|
||||||
File profileDir;
|
File profileDir;
|
||||||
File profileFile;
|
File profileFile;
|
||||||
if ( profileBaseDir == null )
|
if (profileBaseDir == null) {
|
||||||
{
|
|
||||||
profileDir = new File(rc.localFunction).getParentFile();
|
profileDir = new File(rc.localFunction).getParentFile();
|
||||||
profileFile = new File(rc.localFunction);
|
profileFile = new File(rc.localFunction);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
profileDir = new File(profileBaseDir);
|
profileDir = new File(profileBaseDir);
|
||||||
profileFile = new File(profileDir, rc.localFunction + ".brf");
|
profileFile = new File(profileDir, rc.localFunction + ".brf");
|
||||||
}
|
}
|
||||||
@ -52,10 +46,8 @@ public final class ProfileCache
|
|||||||
File lookupFile = new File(profileDir, "lookups.dat");
|
File lookupFile = new File(profileDir, "lookups.dat");
|
||||||
|
|
||||||
// invalidate cache at lookup-table update
|
// invalidate cache at lookup-table update
|
||||||
if ( !(lookupFile.equals( lastLookupFile ) && lookupFile.lastModified() == lastLookupTimestamp ) )
|
if (!(lookupFile.equals(lastLookupFile) && lookupFile.lastModified() == lastLookupTimestamp)) {
|
||||||
{
|
if (lastLookupFile != null) {
|
||||||
if ( lastLookupFile != null )
|
|
||||||
{
|
|
||||||
System.out.println("******** invalidating profile-cache after lookup-file update ******** ");
|
System.out.println("******** invalidating profile-cache after lookup-file update ******** ");
|
||||||
}
|
}
|
||||||
apc = new ProfileCache[apc.length];
|
apc = new ProfileCache[apc.length];
|
||||||
@ -67,16 +59,12 @@ public final class ProfileCache
|
|||||||
int unusedSlot = -1;
|
int unusedSlot = -1;
|
||||||
|
|
||||||
// check for re-use
|
// check for re-use
|
||||||
for( int i=0; i<apc.length; i++)
|
for (int i = 0; i < apc.length; i++) {
|
||||||
{
|
|
||||||
ProfileCache pc = apc[i];
|
ProfileCache pc = apc[i];
|
||||||
|
|
||||||
if ( pc != null )
|
if (pc != null) {
|
||||||
{
|
if ((!pc.profilesBusy) && profileFile.equals(pc.lastProfileFile)) {
|
||||||
if ( (!pc.profilesBusy) && profileFile.equals( pc.lastProfileFile ) )
|
if (rc.profileTimestamp == pc.lastProfileTimestamp) {
|
||||||
{
|
|
||||||
if ( rc.profileTimestamp == pc.lastProfileTimestamp )
|
|
||||||
{
|
|
||||||
rc.expctxWay = pc.expctxWay;
|
rc.expctxWay = pc.expctxWay;
|
||||||
rc.expctxNode = pc.expctxNode;
|
rc.expctxNode = pc.expctxNode;
|
||||||
rc.readGlobalConfig();
|
rc.readGlobalConfig();
|
||||||
@ -87,13 +75,10 @@ public final class ProfileCache
|
|||||||
unusedSlot = -1;
|
unusedSlot = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( lru == null || lru.lastUseTime > pc.lastUseTime )
|
if (lru == null || lru.lastUseTime > pc.lastUseTime) {
|
||||||
{
|
|
||||||
lru = pc;
|
lru = pc;
|
||||||
}
|
}
|
||||||
}
|
} else if (unusedSlot < 0) {
|
||||||
else if ( unusedSlot < 0 )
|
|
||||||
{
|
|
||||||
unusedSlot = i;
|
unusedSlot = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,24 +96,22 @@ public final class ProfileCache
|
|||||||
|
|
||||||
rc.readGlobalConfig();
|
rc.readGlobalConfig();
|
||||||
|
|
||||||
if ( rc.processUnusedTags )
|
if (rc.processUnusedTags) {
|
||||||
{
|
|
||||||
rc.expctxWay.setAllTagsUsed();
|
rc.expctxWay.setAllTagsUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( lru == null || unusedSlot >= 0 )
|
if (lru == null || unusedSlot >= 0) {
|
||||||
{
|
|
||||||
lru = new ProfileCache();
|
lru = new ProfileCache();
|
||||||
if ( unusedSlot >= 0 )
|
if (unusedSlot >= 0) {
|
||||||
{
|
|
||||||
apc[unusedSlot] = lru;
|
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 (lru.lastProfileFile != null) {
|
||||||
{
|
if (debug)
|
||||||
if ( debug ) System.out.println( "******* replacing profile of age " + ((System.currentTimeMillis()-lru.lastUseTime)/1000L) + " sec " + lru.lastProfileFile + "->" + profileFile );
|
System.out.println("******* replacing profile of age " + ((System.currentTimeMillis() - lru.lastUseTime) / 1000L) + " sec " + lru.lastProfileFile + "->" + profileFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
lru.lastProfileTimestamp = rc.profileTimestamp;
|
lru.lastProfileTimestamp = rc.profileTimestamp;
|
||||||
@ -140,17 +123,13 @@ public final class ProfileCache
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void releaseProfile( RoutingContext rc )
|
public static synchronized void releaseProfile(RoutingContext rc) {
|
||||||
{
|
for (int i = 0; i < apc.length; i++) {
|
||||||
for( int i=0; i<apc.length; i++)
|
|
||||||
{
|
|
||||||
ProfileCache pc = apc[i];
|
ProfileCache pc = apc[i];
|
||||||
|
|
||||||
if ( pc != null )
|
if (pc != null) {
|
||||||
{
|
|
||||||
// only the thread that holds the cached instance can release it
|
// 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;
|
pc.profilesBusy = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,16 +20,15 @@ import btools.mapaccess.OsmNode;
|
|||||||
import btools.util.CheapAngleMeter;
|
import btools.util.CheapAngleMeter;
|
||||||
import btools.util.CheapRuler;
|
import btools.util.CheapRuler;
|
||||||
|
|
||||||
public final class RoutingContext
|
public final class RoutingContext {
|
||||||
{
|
public void setAlternativeIdx(int idx) {
|
||||||
public void setAlternativeIdx(int idx )
|
|
||||||
{
|
|
||||||
alternativeIdx = 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);
|
return alternativeIdx < min ? min : (alternativeIdx > max ? max : alternativeIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int alternativeIdx = 0;
|
public int alternativeIdx = 0;
|
||||||
public String localFunction;
|
public String localFunction;
|
||||||
public long profileTimestamp;
|
public long profileTimestamp;
|
||||||
@ -38,8 +37,7 @@ public final class RoutingContext
|
|||||||
|
|
||||||
public String rawTrackPath;
|
public String rawTrackPath;
|
||||||
|
|
||||||
public String getProfileName()
|
public String getProfileName() {
|
||||||
{
|
|
||||||
String name = localFunction == null ? "unknown" : localFunction;
|
String name = localFunction == null ? "unknown" : localFunction;
|
||||||
if (name.endsWith(".brf")) name = name.substring(0, localFunction.length() - 4);
|
if (name.endsWith(".brf")) name = name.substring(0, localFunction.length() - 4);
|
||||||
int idx = name.lastIndexOf(File.separatorChar);
|
int idx = name.lastIndexOf(File.separatorChar);
|
||||||
@ -81,47 +79,35 @@ public final class RoutingContext
|
|||||||
|
|
||||||
public double waypointCatchingRange;
|
public double waypointCatchingRange;
|
||||||
|
|
||||||
private void setModel( String className )
|
private void setModel(String className) {
|
||||||
{
|
if (className == null) {
|
||||||
if ( className == null )
|
|
||||||
{
|
|
||||||
pm = new StdModel();
|
pm = new StdModel();
|
||||||
}
|
} else {
|
||||||
else
|
try {
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Class clazz = Class.forName(className);
|
Class clazz = Class.forName(className);
|
||||||
pm = (OsmPathModel) clazz.newInstance();
|
pm = (OsmPathModel) clazz.newInstance();
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch( Exception e )
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Cannot create path-model: " + e);
|
throw new RuntimeException("Cannot create path-model: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initModel();
|
initModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initModel()
|
public void initModel() {
|
||||||
{
|
|
||||||
pm.init(expctxWay, expctxNode, keyValues);
|
pm.init(expctxWay, expctxNode, keyValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getKeyValueChecksum()
|
public long getKeyValueChecksum() {
|
||||||
{
|
|
||||||
long s = 0L;
|
long s = 0L;
|
||||||
if ( keyValues != null )
|
if (keyValues != null) {
|
||||||
{
|
for (Map.Entry<String, String> e : keyValues.entrySet()) {
|
||||||
for( Map.Entry<String,String> e : keyValues.entrySet() )
|
|
||||||
{
|
|
||||||
s += e.getKey().hashCode() + e.getValue().hashCode();
|
s += e.getKey().hashCode() + e.getValue().hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readGlobalConfig()
|
public void readGlobalConfig() {
|
||||||
{
|
|
||||||
BExpressionContext expctxGlobal = expctxWay; // just one of them...
|
BExpressionContext expctxGlobal = expctxWay; // just one of them...
|
||||||
|
|
||||||
if (keyValues != null) {
|
if (keyValues != null) {
|
||||||
@ -256,22 +242,19 @@ public final class RoutingContext
|
|||||||
public double defaultC_r;
|
public double defaultC_r;
|
||||||
public double bikerPower;
|
public double bikerPower;
|
||||||
|
|
||||||
public static void prepareNogoPoints( List<OsmNodeNamed> nogos )
|
public static void prepareNogoPoints(List<OsmNodeNamed> nogos) {
|
||||||
{
|
for (OsmNodeNamed nogo : nogos) {
|
||||||
for( OsmNodeNamed nogo : nogos )
|
if (nogo instanceof OsmNogoPolygon) {
|
||||||
{
|
|
||||||
if (nogo instanceof OsmNogoPolygon)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String s = nogo.name;
|
String s = nogo.name;
|
||||||
int idx = s.indexOf(' ');
|
int idx = s.indexOf(' ');
|
||||||
if (idx > 0) s = s.substring(0, idx);
|
if (idx > 0) s = s.substring(0, idx);
|
||||||
int ir = 20; // default radius
|
int ir = 20; // default radius
|
||||||
if ( s.length() > 4 )
|
if (s.length() > 4) {
|
||||||
{
|
try {
|
||||||
try { ir = Integer.parseInt( s.substring( 4 ) ); }
|
ir = Integer.parseInt(s.substring(4));
|
||||||
catch( Exception e ) { /* ignore */ }
|
} catch (Exception e) { /* ignore */ }
|
||||||
}
|
}
|
||||||
// Radius of the nogo point in meters
|
// Radius of the nogo point in meters
|
||||||
nogo.radius = ir;
|
nogo.radius = ir;
|
||||||
@ -281,8 +264,7 @@ public final class RoutingContext
|
|||||||
/**
|
/**
|
||||||
* restore the full nogolist previously saved by cleanNogoList
|
* restore the full nogolist previously saved by cleanNogoList
|
||||||
*/
|
*/
|
||||||
public void restoreNogoList()
|
public void restoreNogoList() {
|
||||||
{
|
|
||||||
nogopoints = nogopoints_all;
|
nogopoints = nogopoints_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,22 +274,18 @@ public final class RoutingContext
|
|||||||
*
|
*
|
||||||
* @return true if all wayoints are all in the same (full-weigth) nogo area (triggering bee-line-mode)
|
* @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;
|
nogopoints_all = nogopoints;
|
||||||
if (nogopoints == null) return;
|
if (nogopoints == null) return;
|
||||||
List<OsmNodeNamed> nogos = new ArrayList<OsmNodeNamed>();
|
List<OsmNodeNamed> nogos = new ArrayList<OsmNodeNamed>();
|
||||||
for( OsmNodeNamed nogo : nogopoints )
|
for (OsmNodeNamed nogo : nogopoints) {
|
||||||
{
|
|
||||||
boolean goodGuy = true;
|
boolean goodGuy = true;
|
||||||
for( OsmNode wp : waypoints )
|
for (OsmNode wp : waypoints) {
|
||||||
{
|
|
||||||
if (wp.calcDistance(nogo) < nogo.radius
|
if (wp.calcDistance(nogo) < nogo.radius
|
||||||
&& (!(nogo instanceof OsmNogoPolygon)
|
&& (!(nogo instanceof OsmNogoPolygon)
|
||||||
|| (((OsmNogoPolygon) nogo).isClosed
|
|| (((OsmNogoPolygon) nogo).isClosed
|
||||||
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
|
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
|
||||||
: ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat))))
|
: ((OsmNogoPolygon) nogo).isOnPolyline(wp.ilon, wp.ilat)))) {
|
||||||
{
|
|
||||||
goodGuy = false;
|
goodGuy = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,22 +294,18 @@ public final class RoutingContext
|
|||||||
nogopoints = nogos.isEmpty() ? null : nogos;
|
nogopoints = nogos.isEmpty() ? null : nogos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allInOneNogo( List<OsmNode> waypoints )
|
public boolean allInOneNogo(List<OsmNode> waypoints) {
|
||||||
{
|
|
||||||
if (nogopoints == null) return false;
|
if (nogopoints == null) return false;
|
||||||
boolean allInTotal = false;
|
boolean allInTotal = false;
|
||||||
for( OsmNodeNamed nogo : nogopoints )
|
for (OsmNodeNamed nogo : nogopoints) {
|
||||||
{
|
|
||||||
boolean allIn = Double.isNaN(nogo.nogoWeight);
|
boolean allIn = Double.isNaN(nogo.nogoWeight);
|
||||||
for( OsmNode wp : waypoints )
|
for (OsmNode wp : waypoints) {
|
||||||
{
|
|
||||||
int dist = wp.calcDistance(nogo);
|
int dist = wp.calcDistance(nogo);
|
||||||
if (dist < nogo.radius
|
if (dist < nogo.radius
|
||||||
&& (!(nogo instanceof OsmNogoPolygon)
|
&& (!(nogo instanceof OsmNogoPolygon)
|
||||||
|| (((OsmNogoPolygon) nogo).isClosed
|
|| (((OsmNogoPolygon) nogo).isClosed
|
||||||
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
|
? ((OsmNogoPolygon) nogo).isWithin(wp.ilon, wp.ilat)
|
||||||
: ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat))))
|
: ((OsmNogoPolygon) nogo).isOnPolyline(wp.ilon, wp.ilat)))) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
allIn = false;
|
allIn = false;
|
||||||
@ -341,12 +315,10 @@ public final class RoutingContext
|
|||||||
return allInTotal;
|
return allInTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long[] getNogoChecksums()
|
public long[] getNogoChecksums() {
|
||||||
{
|
|
||||||
long[] cs = new long[3];
|
long[] cs = new long[3];
|
||||||
int n = nogopoints == null ? 0 : nogopoints.size();
|
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);
|
OsmNodeNamed nogo = nogopoints.get(i);
|
||||||
cs[0] += nogo.ilon;
|
cs[0] += nogo.ilon;
|
||||||
cs[1] += nogo.ilat;
|
cs[1] += nogo.ilat;
|
||||||
@ -356,13 +328,11 @@ public final class RoutingContext
|
|||||||
return cs;
|
return cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWaypoint( OsmNodeNamed wp, boolean endpoint )
|
public void setWaypoint(OsmNodeNamed wp, boolean endpoint) {
|
||||||
{
|
|
||||||
setWaypoint(wp, null, 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;
|
keepnogopoints = nogopoints;
|
||||||
nogopoints = new ArrayList<OsmNodeNamed>();
|
nogopoints = new ArrayList<OsmNodeNamed>();
|
||||||
nogopoints.add(wp);
|
nogopoints.add(wp);
|
||||||
@ -371,10 +341,8 @@ public final class RoutingContext
|
|||||||
this.pendingEndpoint = pendingEndpoint;
|
this.pendingEndpoint = pendingEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkPendingEndpoint()
|
public boolean checkPendingEndpoint() {
|
||||||
{
|
if (pendingEndpoint != null) {
|
||||||
if ( pendingEndpoint != null )
|
|
||||||
{
|
|
||||||
isEndpoint = true;
|
isEndpoint = true;
|
||||||
nogopoints.set(0, pendingEndpoint);
|
nogopoints.set(0, pendingEndpoint);
|
||||||
pendingEndpoint = null;
|
pendingEndpoint = null;
|
||||||
@ -383,15 +351,13 @@ public final class RoutingContext
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unsetWaypoint()
|
public void unsetWaypoint() {
|
||||||
{
|
|
||||||
nogopoints = keepnogopoints;
|
nogopoints = keepnogopoints;
|
||||||
pendingEndpoint = null;
|
pendingEndpoint = null;
|
||||||
isEndpoint = false;
|
isEndpoint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int calcDistance( int lon1, int lat1, int lon2, int lat2 )
|
public int calcDistance(int lon1, int lat1, int lon2, int lat2) {
|
||||||
{
|
|
||||||
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lat1 + lat2) >> 1);
|
double[] lonlat2m = CheapRuler.getLonLatToMeterScales((lat1 + lat2) >> 1);
|
||||||
double dlon2m = lonlat2m[0];
|
double dlon2m = lonlat2m[0];
|
||||||
double dlat2m = lonlat2m[1];
|
double dlat2m = lonlat2m[1];
|
||||||
@ -401,10 +367,8 @@ public final class RoutingContext
|
|||||||
|
|
||||||
shortestmatch = false;
|
shortestmatch = false;
|
||||||
|
|
||||||
if ( nogopoints != null && !nogopoints.isEmpty() && d > 0. )
|
if (nogopoints != null && !nogopoints.isEmpty() && d > 0.) {
|
||||||
{
|
for (int ngidx = 0; ngidx < nogopoints.size(); ngidx++) {
|
||||||
for( int ngidx = 0; ngidx < nogopoints.size(); ngidx++ )
|
|
||||||
{
|
|
||||||
OsmNodeNamed nogo = nogopoints.get(ngidx);
|
OsmNodeNamed nogo = nogopoints.get(ngidx);
|
||||||
double x1 = (lon1 - nogo.ilon) * dlon2m;
|
double x1 = (lon1 - nogo.ilon) * dlon2m;
|
||||||
double y1 = (lat1 - nogo.ilat) * dlat2m;
|
double y1 = (lat1 - nogo.ilat) * dlat2m;
|
||||||
@ -420,14 +384,15 @@ public final class RoutingContext
|
|||||||
double s2 = x2 * dx + y2 * dy;
|
double s2 = x2 * dx + y2 * dy;
|
||||||
|
|
||||||
|
|
||||||
if ( s1 < 0. ) { s1 = -s1; s2 = -s2; }
|
if (s1 < 0.) {
|
||||||
if ( s2 > 0. )
|
s1 = -s1;
|
||||||
{
|
s2 = -s2;
|
||||||
|
}
|
||||||
|
if (s2 > 0.) {
|
||||||
radius = Math.sqrt(s1 < s2 ? r12 : r22);
|
radius = Math.sqrt(s1 < s2 ? r12 : r22);
|
||||||
if (radius > nogo.radius) continue;
|
if (radius > nogo.radius) continue;
|
||||||
}
|
}
|
||||||
if ( nogo.isNogo )
|
if (nogo.isNogo) {
|
||||||
{
|
|
||||||
if (!(nogo instanceof OsmNogoPolygon)) { // nogo is a circle
|
if (!(nogo instanceof OsmNogoPolygon)) { // nogo is a circle
|
||||||
if (Double.isNaN(nogo.nogoWeight)) {
|
if (Double.isNaN(nogo.nogoWeight)) {
|
||||||
// default nogo behaviour (ignore completely)
|
// default nogo behaviour (ignore completely)
|
||||||
@ -436,9 +401,7 @@ public final class RoutingContext
|
|||||||
// nogo weight, compute distance within the circle
|
// nogo weight, compute distance within the circle
|
||||||
nogoCost = nogo.distanceWithinRadius(lon1, lat1, lon2, lat2, d) * nogo.nogoWeight;
|
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
|
// nogo is a polyline/polygon, we have to check there is indeed
|
||||||
// an intersection in this case (radius check is not enough).
|
// an intersection in this case (radius check is not enough).
|
||||||
if (Double.isNaN(nogo.nogoWeight)) {
|
if (Double.isNaN(nogo.nogoWeight)) {
|
||||||
@ -454,28 +417,21 @@ public final class RoutingContext
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
shortestmatch = true;
|
shortestmatch = true;
|
||||||
nogo.radius = radius; // shortest distance to way
|
nogo.radius = radius; // shortest distance to way
|
||||||
// calculate remaining distance
|
// calculate remaining distance
|
||||||
if ( s2 < 0. )
|
if (s2 < 0.) {
|
||||||
{
|
|
||||||
wayfraction = -s2 / (d * d);
|
wayfraction = -s2 / (d * d);
|
||||||
double xm = x2 - wayfraction * dx;
|
double xm = x2 - wayfraction * dx;
|
||||||
double ym = y2 - wayfraction * dy;
|
double ym = y2 - wayfraction * dy;
|
||||||
ilonshortest = (int) (xm / dlon2m + nogo.ilon);
|
ilonshortest = (int) (xm / dlon2m + nogo.ilon);
|
||||||
ilatshortest = (int) (ym / dlat2m + nogo.ilat);
|
ilatshortest = (int) (ym / dlat2m + nogo.ilat);
|
||||||
}
|
} else if (s1 > s2) {
|
||||||
else if ( s1 > s2 )
|
|
||||||
{
|
|
||||||
wayfraction = 0.;
|
wayfraction = 0.;
|
||||||
ilonshortest = lon2;
|
ilonshortest = lon2;
|
||||||
ilatshortest = lat2;
|
ilatshortest = lat2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
wayfraction = 1.;
|
wayfraction = 1.;
|
||||||
ilonshortest = lon1;
|
ilonshortest = lon1;
|
||||||
ilatshortest = lat1;
|
ilatshortest = lat1;
|
||||||
@ -485,14 +441,11 @@ public final class RoutingContext
|
|||||||
// *after* the shortest distance point. In case of a shortest-match
|
// *after* the shortest distance point. In case of a shortest-match
|
||||||
// we use the reduced way segment for nogo-matching, in order not
|
// 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
|
// to cut our escape-way if we placed a nogo just in front of where we are
|
||||||
if ( isEndpoint )
|
if (isEndpoint) {
|
||||||
{
|
|
||||||
wayfraction = 1. - wayfraction;
|
wayfraction = 1. - wayfraction;
|
||||||
lon2 = ilonshortest;
|
lon2 = ilonshortest;
|
||||||
lat2 = ilatshortest;
|
lat2 = ilatshortest;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nogoCost = 0.;
|
nogoCost = 0.;
|
||||||
lon1 = ilonshortest;
|
lon1 = ilonshortest;
|
||||||
lat1 = ilatshortest;
|
lat1 = ilatshortest;
|
||||||
@ -509,25 +462,21 @@ public final class RoutingContext
|
|||||||
|
|
||||||
public OsmPathModel pm;
|
public OsmPathModel pm;
|
||||||
|
|
||||||
public OsmPrePath createPrePath( OsmPath origin, OsmLink link )
|
public OsmPrePath createPrePath(OsmPath origin, OsmLink link) {
|
||||||
{
|
|
||||||
OsmPrePath p = pm.createPrePath();
|
OsmPrePath p = pm.createPrePath();
|
||||||
if ( p != null )
|
if (p != null) {
|
||||||
{
|
|
||||||
p.init(origin, link, this);
|
p.init(origin, link, this);
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmPath createPath( OsmLink link )
|
public OsmPath createPath(OsmLink link) {
|
||||||
{
|
|
||||||
OsmPath p = pm.createPath();
|
OsmPath p = pm.createPath();
|
||||||
p.init(link);
|
p.init(link);
|
||||||
return p;
|
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();
|
OsmPath p = pm.createPath();
|
||||||
p.init(origin, link, refTrack, detailMode, this);
|
p.init(origin, link, refTrack, detailMode, this);
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -9,39 +9,31 @@ import java.io.File;
|
|||||||
|
|
||||||
import btools.mapaccess.StorageConfigHelper;
|
import btools.mapaccess.StorageConfigHelper;
|
||||||
|
|
||||||
public final class RoutingHelper
|
public final class RoutingHelper {
|
||||||
{
|
public static File getAdditionalMaptoolDir(File segmentDir) {
|
||||||
public static File getAdditionalMaptoolDir( File segmentDir )
|
|
||||||
{
|
|
||||||
return StorageConfigHelper.getAdditionalMaptoolDir(segmentDir);
|
return StorageConfigHelper.getAdditionalMaptoolDir(segmentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getSecondarySegmentDir( File segmentDir )
|
public static File getSecondarySegmentDir(File segmentDir) {
|
||||||
{
|
|
||||||
return StorageConfigHelper.getSecondarySegmentDir(segmentDir);
|
return StorageConfigHelper.getSecondarySegmentDir(segmentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean hasDirectoryAnyDatafiles( File segmentDir )
|
public static boolean hasDirectoryAnyDatafiles(File segmentDir) {
|
||||||
{
|
if (hasAnyDatafiles(segmentDir)) {
|
||||||
if ( hasAnyDatafiles( segmentDir ) )
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// check secondary, too
|
// check secondary, too
|
||||||
File secondary = StorageConfigHelper.getSecondarySegmentDir(segmentDir);
|
File secondary = StorageConfigHelper.getSecondarySegmentDir(segmentDir);
|
||||||
if ( secondary != null )
|
if (secondary != null) {
|
||||||
{
|
|
||||||
return hasAnyDatafiles(secondary);
|
return hasAnyDatafiles(secondary);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasAnyDatafiles( File dir )
|
private static boolean hasAnyDatafiles(File dir) {
|
||||||
{
|
|
||||||
String[] fileNames = dir.list();
|
String[] fileNames = dir.list();
|
||||||
for( String fileName : fileNames )
|
for (String fileName : fileNames) {
|
||||||
{
|
|
||||||
if (fileName.endsWith(".rd5")) return true;
|
if (fileName.endsWith(".rd5")) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
package btools.router;
|
package btools.router;
|
||||||
|
|
||||||
public class RoutingIslandException extends RuntimeException
|
public class RoutingIslandException extends RuntimeException {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,7 @@ package btools.router;
|
|||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
|
|
||||||
|
|
||||||
public final class SearchBoundary
|
public final class SearchBoundary {
|
||||||
{
|
|
||||||
|
|
||||||
private int minlon0;
|
private int minlon0;
|
||||||
private int minlat0;
|
private int minlat0;
|
||||||
@ -28,8 +27,7 @@ public final class SearchBoundary
|
|||||||
/**
|
/**
|
||||||
* @param radius Search radius in meters.
|
* @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.radius = radius;
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
|
|
||||||
@ -49,8 +47,7 @@ public final class SearchBoundary
|
|||||||
maxlat = lat + 6000000;
|
maxlat = lat + 6000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFileName( OsmNode n )
|
public static String getFileName(OsmNode n) {
|
||||||
{
|
|
||||||
int lon = (n.ilon / 5000000) * 5000000;
|
int lon = (n.ilon / 5000000) * 5000000;
|
||||||
int lat = (n.ilat / 5000000) * 5000000;
|
int lat = (n.ilat / 5000000) * 5000000;
|
||||||
|
|
||||||
@ -62,28 +59,28 @@ public final class SearchBoundary
|
|||||||
return slon + "_" + slat + ".trf";
|
return slon + "_" + slat + ".trf";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInBoundary( OsmNode n, int cost )
|
public boolean isInBoundary(OsmNode n, int cost) {
|
||||||
{
|
if (radius > 0) {
|
||||||
if ( radius > 0 )
|
|
||||||
{
|
|
||||||
return n.calcDistance(p) < radius;
|
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 > minlon0 && n.ilon < maxlon0 && n.ilat > minlat0 && n.ilat < maxlat0;
|
||||||
}
|
}
|
||||||
return n.ilon > minlon && n.ilon < maxlon && n.ilat > minlat && n.ilat < maxlat;
|
return n.ilon > minlon && n.ilon < maxlon && n.ilat > minlat && n.ilat < maxlat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBoundaryDistance( OsmNode n )
|
public int getBoundaryDistance(OsmNode n) {
|
||||||
{
|
switch (direction) {
|
||||||
switch( direction )
|
case 0:
|
||||||
{
|
return n.calcDistance(new OsmNode(n.ilon, minlat));
|
||||||
case 0: return n.calcDistance( new OsmNode( n.ilon, minlat ) );
|
case 1:
|
||||||
case 1: return n.calcDistance( new OsmNode( minlon, n.ilat ) );
|
return n.calcDistance(new OsmNode(minlon, n.ilat));
|
||||||
case 2: return n.calcDistance( new OsmNode( n.ilon, maxlat ) );
|
case 2:
|
||||||
case 3: return n.calcDistance( new OsmNode( maxlon, n.ilat ) );
|
return n.calcDistance(new OsmNode(n.ilon, maxlat));
|
||||||
default: throw new IllegalArgumentException( "undefined direction: "+ direction );
|
case 3:
|
||||||
|
return n.calcDistance(new OsmNode(maxlon, n.ilat));
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("undefined direction: " + direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,15 +12,12 @@ import btools.expressions.BExpressionContextNode;
|
|||||||
import btools.expressions.BExpressionContextWay;
|
import btools.expressions.BExpressionContextWay;
|
||||||
|
|
||||||
|
|
||||||
final class StdModel extends OsmPathModel
|
final class StdModel extends OsmPathModel {
|
||||||
{
|
public OsmPrePath createPrePath() {
|
||||||
public OsmPrePath createPrePath()
|
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmPath createPath()
|
public OsmPath createPath() {
|
||||||
{
|
|
||||||
return new StdPath();
|
return new StdPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,8 +26,7 @@ final class StdModel extends OsmPathModel
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@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;
|
ctxWay = expctxWay;
|
||||||
ctxNode = expctxNode;
|
ctxNode = expctxNode;
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,7 @@ package btools.router;
|
|||||||
|
|
||||||
import btools.util.FastMath;
|
import btools.util.FastMath;
|
||||||
|
|
||||||
final class StdPath extends OsmPath
|
final class StdPath extends OsmPath {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* The elevation-hysteresis-buffer (0-10 m)
|
* The elevation-hysteresis-buffer (0-10 m)
|
||||||
*/
|
*/
|
||||||
@ -23,8 +22,7 @@ final class StdPath extends OsmPath
|
|||||||
private static final double GRAVITY = 9.81; // in meters per second^(-2)
|
private static final double GRAVITY = 9.81; // in meters per second^(-2)
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init( OsmPath orig )
|
public void init(OsmPath orig) {
|
||||||
{
|
|
||||||
StdPath origin = (StdPath) orig;
|
StdPath origin = (StdPath) orig;
|
||||||
this.ehbd = origin.ehbd;
|
this.ehbd = origin.ehbd;
|
||||||
this.ehbu = origin.ehbu;
|
this.ehbu = origin.ehbu;
|
||||||
@ -34,8 +32,7 @@ final class StdPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void resetState()
|
protected void resetState() {
|
||||||
{
|
|
||||||
ehbd = 0;
|
ehbd = 0;
|
||||||
ehbu = 0;
|
ehbu = 0;
|
||||||
totalTime = 0.f;
|
totalTime = 0.f;
|
||||||
@ -44,8 +41,7 @@ final class StdPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
// calculate the costfactor inputs
|
||||||
float turncostbase = rc.expctxWay.getTurncost();
|
float turncostbase = rc.expctxWay.getTurncost();
|
||||||
float cfup = rc.expctxWay.getUphillCostfactor();
|
float cfup = rc.expctxWay.getUphillCostfactor();
|
||||||
@ -58,8 +54,7 @@ final class StdPath extends OsmPath
|
|||||||
|
|
||||||
// penalty for turning angle
|
// penalty for turning angle
|
||||||
int turncost = (int) ((1. - cosangle) * turncostbase + 0.2); // e.g. turncost=90 -> 90 degree = 90m penalty
|
int turncost = (int) ((1. - cosangle) * turncostbase + 0.2); // e.g. turncost=90 -> 90 degree = 90m penalty
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.linkturncost += turncost;
|
message.linkturncost += turncost;
|
||||||
message.turnangle = (float) angle;
|
message.turnangle = (float) angle;
|
||||||
}
|
}
|
||||||
@ -75,76 +70,61 @@ final class StdPath extends OsmPath
|
|||||||
ehbu += delta_h_micros - dist * rc.uphillcutoff;
|
ehbu += delta_h_micros - dist * rc.uphillcutoff;
|
||||||
|
|
||||||
float downweight = 0.f;
|
float downweight = 0.f;
|
||||||
if ( ehbd > rc.elevationpenaltybuffer )
|
if (ehbd > rc.elevationpenaltybuffer) {
|
||||||
{
|
|
||||||
downweight = 1.f;
|
downweight = 1.f;
|
||||||
|
|
||||||
int excess = ehbd - rc.elevationpenaltybuffer;
|
int excess = ehbd - rc.elevationpenaltybuffer;
|
||||||
int reduce = dist * rc.elevationbufferreduce;
|
int reduce = dist * rc.elevationbufferreduce;
|
||||||
if ( reduce > excess )
|
if (reduce > excess) {
|
||||||
{
|
|
||||||
downweight = ((float) excess) / reduce;
|
downweight = ((float) excess) / reduce;
|
||||||
reduce = excess;
|
reduce = excess;
|
||||||
}
|
}
|
||||||
excess = ehbd - rc.elevationmaxbuffer;
|
excess = ehbd - rc.elevationmaxbuffer;
|
||||||
if ( reduce < excess )
|
if (reduce < excess) {
|
||||||
{
|
|
||||||
reduce = excess;
|
reduce = excess;
|
||||||
}
|
}
|
||||||
ehbd -= reduce;
|
ehbd -= reduce;
|
||||||
if ( rc.downhillcostdiv > 0 )
|
if (rc.downhillcostdiv > 0) {
|
||||||
{
|
|
||||||
int elevationCost = reduce / rc.downhillcostdiv;
|
int elevationCost = reduce / rc.downhillcostdiv;
|
||||||
sectionCost += elevationCost;
|
sectionCost += elevationCost;
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.linkelevationcost += elevationCost;
|
message.linkelevationcost += elevationCost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (ehbd < 0) {
|
||||||
else if ( ehbd < 0 )
|
|
||||||
{
|
|
||||||
ehbd = 0;
|
ehbd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float upweight = 0.f;
|
float upweight = 0.f;
|
||||||
if ( ehbu > rc.elevationpenaltybuffer )
|
if (ehbu > rc.elevationpenaltybuffer) {
|
||||||
{
|
|
||||||
upweight = 1.f;
|
upweight = 1.f;
|
||||||
|
|
||||||
int excess = ehbu - rc.elevationpenaltybuffer;
|
int excess = ehbu - rc.elevationpenaltybuffer;
|
||||||
int reduce = dist * rc.elevationbufferreduce;
|
int reduce = dist * rc.elevationbufferreduce;
|
||||||
if ( reduce > excess )
|
if (reduce > excess) {
|
||||||
{
|
|
||||||
upweight = ((float) excess) / reduce;
|
upweight = ((float) excess) / reduce;
|
||||||
reduce = excess;
|
reduce = excess;
|
||||||
}
|
}
|
||||||
excess = ehbu - rc.elevationmaxbuffer;
|
excess = ehbu - rc.elevationmaxbuffer;
|
||||||
if ( reduce < excess )
|
if (reduce < excess) {
|
||||||
{
|
|
||||||
reduce = excess;
|
reduce = excess;
|
||||||
}
|
}
|
||||||
ehbu -= reduce;
|
ehbu -= reduce;
|
||||||
if ( rc.uphillcostdiv > 0 )
|
if (rc.uphillcostdiv > 0) {
|
||||||
{
|
|
||||||
int elevationCost = reduce / rc.uphillcostdiv;
|
int elevationCost = reduce / rc.uphillcostdiv;
|
||||||
sectionCost += elevationCost;
|
sectionCost += elevationCost;
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.linkelevationcost += elevationCost;
|
message.linkelevationcost += elevationCost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (ehbu < 0) {
|
||||||
else if ( ehbu < 0 )
|
|
||||||
{
|
|
||||||
ehbu = 0;
|
ehbu = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the effective costfactor (slope dependent)
|
// 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;
|
message.costfactor = costfactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,20 +134,16 @@ final class StdPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected double processTargetNode( RoutingContext rc )
|
protected double processTargetNode(RoutingContext rc) {
|
||||||
{
|
|
||||||
// finally add node-costs for target node
|
// finally add node-costs for target node
|
||||||
if ( targetNode.nodeDescription != null )
|
if (targetNode.nodeDescription != null) {
|
||||||
{
|
|
||||||
boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.;
|
boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.;
|
||||||
rc.expctxNode.evaluate(nodeAccessGranted, targetNode.nodeDescription);
|
rc.expctxNode.evaluate(nodeAccessGranted, targetNode.nodeDescription);
|
||||||
float initialcost = rc.expctxNode.getInitialcost();
|
float initialcost = rc.expctxNode.getInitialcost();
|
||||||
if ( initialcost >= 1000000. )
|
if (initialcost >= 1000000.) {
|
||||||
{
|
|
||||||
return -1.;
|
return -1.;
|
||||||
}
|
}
|
||||||
if ( message != null )
|
if (message != null) {
|
||||||
{
|
|
||||||
message.linknodecost += (int) initialcost;
|
message.linknodecost += (int) initialcost;
|
||||||
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(nodeAccessGranted, targetNode.nodeDescription);
|
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription(nodeAccessGranted, targetNode.nodeDescription);
|
||||||
}
|
}
|
||||||
@ -177,25 +153,21 @@ final class StdPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int elevationCorrection( RoutingContext rc )
|
public int elevationCorrection(RoutingContext rc) {
|
||||||
{
|
|
||||||
return (rc.downhillcostdiv > 0 ? ehbd / rc.downhillcostdiv : 0)
|
return (rc.downhillcostdiv > 0 ? ehbd / rc.downhillcostdiv : 0)
|
||||||
+ (rc.uphillcostdiv > 0 ? ehbu / rc.uphillcostdiv : 0);
|
+ (rc.uphillcostdiv > 0 ? ehbu / rc.uphillcostdiv : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean definitlyWorseThan( OsmPath path, RoutingContext rc )
|
public boolean definitlyWorseThan(OsmPath path, RoutingContext rc) {
|
||||||
{
|
|
||||||
StdPath p = (StdPath) path;
|
StdPath p = (StdPath) path;
|
||||||
|
|
||||||
int c = p.cost;
|
int c = p.cost;
|
||||||
if ( rc.downhillcostdiv > 0 )
|
if (rc.downhillcostdiv > 0) {
|
||||||
{
|
|
||||||
int delta = p.ehbd - ehbd;
|
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;
|
int delta = p.ehbu - ehbu;
|
||||||
if (delta > 0) c += delta / rc.uphillcostdiv;
|
if (delta > 0) c += delta / rc.uphillcostdiv;
|
||||||
}
|
}
|
||||||
@ -203,20 +175,14 @@ final class StdPath extends OsmPath
|
|||||||
return cost > c;
|
return cost > c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double calcIncline( double dist )
|
private double calcIncline(double dist) {
|
||||||
{
|
|
||||||
double min_delta = 3.;
|
double min_delta = 3.;
|
||||||
double shift;
|
double shift;
|
||||||
if ( elevation_buffer > min_delta )
|
if (elevation_buffer > min_delta) {
|
||||||
{
|
|
||||||
shift = -min_delta;
|
shift = -min_delta;
|
||||||
}
|
} else if (elevation_buffer < min_delta) {
|
||||||
else if ( elevation_buffer < min_delta )
|
|
||||||
{
|
|
||||||
shift = -min_delta;
|
shift = -min_delta;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0.;
|
return 0.;
|
||||||
}
|
}
|
||||||
double decayFactor = FastMath.exp(-dist / 100.);
|
double decayFactor = FastMath.exp(-dist / 100.);
|
||||||
@ -227,10 +193,8 @@ final class StdPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void computeKinematic( RoutingContext rc, double dist, double delta_h, boolean detailMode )
|
protected void computeKinematic(RoutingContext rc, double dist, double delta_h, boolean detailMode) {
|
||||||
{
|
if (!detailMode) {
|
||||||
if ( !detailMode )
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,26 +205,21 @@ final class StdPath extends OsmPath
|
|||||||
double wayMaxspeed;
|
double wayMaxspeed;
|
||||||
|
|
||||||
wayMaxspeed = rc.expctxWay.getMaxspeed() / 3.6f;
|
wayMaxspeed = rc.expctxWay.getMaxspeed() / 3.6f;
|
||||||
if (wayMaxspeed == 0)
|
if (wayMaxspeed == 0) {
|
||||||
{
|
|
||||||
wayMaxspeed = rc.maxSpeed;
|
wayMaxspeed = rc.maxSpeed;
|
||||||
}
|
}
|
||||||
wayMaxspeed = Math.min(wayMaxspeed, rc.maxSpeed);
|
wayMaxspeed = Math.min(wayMaxspeed, rc.maxSpeed);
|
||||||
|
|
||||||
double speed; // Travel speed
|
double speed; // Travel speed
|
||||||
double f_roll = rc.totalMass * GRAVITY * (rc.defaultC_r + incline);
|
double f_roll = rc.totalMass * GRAVITY * (rc.defaultC_r + incline);
|
||||||
if (rc.footMode || rc.expctxWay.getCostfactor() > 4.9 )
|
if (rc.footMode || rc.expctxWay.getCostfactor() > 4.9) {
|
||||||
{
|
|
||||||
// Use Tobler's hiking function for walking sections
|
// Use Tobler's hiking function for walking sections
|
||||||
speed = rc.maxSpeed * 3.6;
|
speed = rc.maxSpeed * 3.6;
|
||||||
speed = (speed * FastMath.exp(-3.5 * Math.abs(incline + 0.05))) / 3.6;
|
speed = (speed * FastMath.exp(-3.5 * Math.abs(incline + 0.05))) / 3.6;
|
||||||
}
|
} else if (rc.bikeMode) {
|
||||||
else if (rc.bikeMode)
|
|
||||||
{
|
|
||||||
speed = solveCubic(rc.S_C_x, f_roll, rc.bikerPower);
|
speed = solveCubic(rc.S_C_x, f_roll, rc.bikerPower);
|
||||||
speed = Math.min(speed, wayMaxspeed);
|
speed = Math.min(speed, wayMaxspeed);
|
||||||
}
|
} else // all other
|
||||||
else // all other
|
|
||||||
{
|
{
|
||||||
speed = wayMaxspeed;
|
speed = wayMaxspeed;
|
||||||
}
|
}
|
||||||
@ -269,26 +228,21 @@ final class StdPath extends OsmPath
|
|||||||
// Calc energy assuming biking (no good model yet for hiking)
|
// Calc energy assuming biking (no good model yet for hiking)
|
||||||
// (Count only positive, negative would mean breaking to enforce maxspeed)
|
// (Count only positive, negative would mean breaking to enforce maxspeed)
|
||||||
double energy = dist * (rc.S_C_x * speed * speed + f_roll);
|
double energy = dist * (rc.S_C_x * speed * speed + f_roll);
|
||||||
if ( energy > 0. )
|
if (energy > 0.) {
|
||||||
{
|
|
||||||
totalEnergy += energy;
|
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
|
// Solves a * v^3 + c * v = d with a Newton method
|
||||||
// to get the speed v for the section.
|
// to get the speed v for the section.
|
||||||
|
|
||||||
double v = 8.;
|
double v = 8.;
|
||||||
boolean findingStartvalue = true;
|
boolean findingStartvalue = true;
|
||||||
for ( int i = 0; i < 10; i++ )
|
for (int i = 0; i < 10; i++) {
|
||||||
{
|
|
||||||
double y = (a * v * v + c) * v - d;
|
double y = (a * v * v + c) * v - d;
|
||||||
if ( y < .1 )
|
if (y < .1) {
|
||||||
{
|
if (findingStartvalue) {
|
||||||
if ( findingStartvalue )
|
|
||||||
{
|
|
||||||
v *= 2.;
|
v *= 2.;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -302,14 +256,12 @@ final class StdPath extends OsmPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getTotalTime()
|
public double getTotalTime() {
|
||||||
{
|
|
||||||
return totalTime;
|
return totalTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getTotalEnergy()
|
public double getTotalEnergy() {
|
||||||
{
|
|
||||||
return totalEnergy;
|
return totalEnergy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,7 @@ package btools.router;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SuspectInfo
|
public class SuspectInfo {
|
||||||
{
|
|
||||||
public static final int TRIGGER_DEAD_END = 1;
|
public static final int TRIGGER_DEAD_END = 1;
|
||||||
public static final int TRIGGER_DEAD_START = 2;
|
public static final int TRIGGER_DEAD_START = 2;
|
||||||
public static final int TRIGGER_NODE_BLOCK = 4;
|
public static final int TRIGGER_NODE_BLOCK = 4;
|
||||||
@ -17,12 +16,10 @@ public class SuspectInfo
|
|||||||
public int prio;
|
public int prio;
|
||||||
public int triggers;
|
public int triggers;
|
||||||
|
|
||||||
public static void addSuspect( Map<Long,SuspectInfo> map, long id, int prio, int trigger )
|
public static void addSuspect(Map<Long, SuspectInfo> map, long id, int prio, int trigger) {
|
||||||
{
|
|
||||||
Long iD = Long.valueOf(id);
|
Long iD = Long.valueOf(id);
|
||||||
SuspectInfo info = map.get(iD);
|
SuspectInfo info = map.get(iD);
|
||||||
if ( info == null )
|
if (info == null) {
|
||||||
{
|
|
||||||
info = new SuspectInfo();
|
info = new SuspectInfo();
|
||||||
map.put(iD, info);
|
map.put(iD, info);
|
||||||
}
|
}
|
||||||
@ -30,10 +27,8 @@ public class SuspectInfo
|
|||||||
info.triggers |= trigger;
|
info.triggers |= trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SuspectInfo addTrigger( SuspectInfo old, int prio, int trigger )
|
public static SuspectInfo addTrigger(SuspectInfo old, int prio, int trigger) {
|
||||||
{
|
if (old == null) {
|
||||||
if ( old == null )
|
|
||||||
{
|
|
||||||
old = new SuspectInfo();
|
old = new SuspectInfo();
|
||||||
}
|
}
|
||||||
old.prio = Math.max(old.prio, prio);
|
old.prio = Math.max(old.prio, prio);
|
||||||
@ -41,8 +36,7 @@ public class SuspectInfo
|
|||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getTriggerText( int triggers )
|
public static String getTriggerText(int triggers) {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
addText(sb, "dead-end", triggers, TRIGGER_DEAD_END);
|
addText(sb, "dead-end", triggers, TRIGGER_DEAD_END);
|
||||||
addText(sb, "dead-start", triggers, TRIGGER_DEAD_START);
|
addText(sb, "dead-start", triggers, TRIGGER_DEAD_START);
|
||||||
@ -56,8 +50,7 @@ public class SuspectInfo
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addText( StringBuilder sb, String text, int mask, int bit )
|
private static void addText(StringBuilder sb, String text, int mask, int bit) {
|
||||||
{
|
|
||||||
if ((bit & mask) == 0) return;
|
if ((bit & mask) == 0) return;
|
||||||
if (sb.length() > 0) sb.append(",");
|
if (sb.length() > 0) sb.append(",");
|
||||||
sb.append(text);
|
sb.append(text);
|
||||||
|
|||||||
@ -9,8 +9,7 @@ package btools.router;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class VoiceHint
|
public class VoiceHint {
|
||||||
{
|
|
||||||
static final int C = 1; // continue (go straight)
|
static final int C = 1; // continue (go straight)
|
||||||
static final int TL = 2; // turn left
|
static final int TL = 2; // turn left
|
||||||
static final int TSLL = 3; // turn slightly left
|
static final int TSLL = 3; // turn slightly left
|
||||||
@ -36,8 +35,7 @@ public class VoiceHint
|
|||||||
double distanceToNext;
|
double distanceToNext;
|
||||||
int indexInTrack;
|
int indexInTrack;
|
||||||
|
|
||||||
public float getTime()
|
public float getTime() {
|
||||||
{
|
|
||||||
return oldWay == null ? 0.f : oldWay.time;
|
return oldWay == null ? 0.f : oldWay.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,157 +45,205 @@ public class VoiceHint
|
|||||||
|
|
||||||
int roundaboutExit;
|
int roundaboutExit;
|
||||||
|
|
||||||
boolean isRoundabout()
|
boolean isRoundabout() {
|
||||||
{
|
|
||||||
return roundaboutExit != 0;
|
return roundaboutExit != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBadWay( MessageData badWay )
|
public void addBadWay(MessageData badWay) {
|
||||||
{
|
if (badWay == null) {
|
||||||
if ( badWay == null )
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( badWays == null )
|
if (badWays == null) {
|
||||||
{
|
|
||||||
badWays = new ArrayList<MessageData>();
|
badWays = new ArrayList<MessageData>();
|
||||||
}
|
}
|
||||||
badWays.add(badWay);
|
badWays.add(badWay);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCommand()
|
public int getCommand() {
|
||||||
{
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExitNumber()
|
public int getExitNumber() {
|
||||||
{
|
|
||||||
return roundaboutExit;
|
return roundaboutExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCommandString()
|
public String getCommandString() {
|
||||||
{
|
switch (cmd) {
|
||||||
switch ( cmd )
|
case TU:
|
||||||
{
|
return "TU";
|
||||||
case TU : return "TU";
|
case TSHL:
|
||||||
case TSHL : return "TSHL";
|
return "TSHL";
|
||||||
case TL : return "TL";
|
case TL:
|
||||||
case TSLL : return "TSLL";
|
return "TL";
|
||||||
case KL : return "KL";
|
case TSLL:
|
||||||
case C : return "C";
|
return "TSLL";
|
||||||
case KR : return "KR";
|
case KL:
|
||||||
case TSLR : return "TSLR";
|
return "KL";
|
||||||
case TR : return "TR";
|
case C:
|
||||||
case TSHR : return "TSHR";
|
return "C";
|
||||||
case TRU : return "TRU";
|
case KR:
|
||||||
case RNDB : return "RNDB" + roundaboutExit;
|
return "KR";
|
||||||
case RNLB : return "RNLB" + (-roundaboutExit);
|
case TSLR:
|
||||||
default : throw new IllegalArgumentException( "unknown command: " + cmd );
|
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()
|
public String getSymbolString() {
|
||||||
{
|
switch (cmd) {
|
||||||
switch ( cmd )
|
case TU:
|
||||||
{
|
return "TU";
|
||||||
case TU : return "TU";
|
case TSHL:
|
||||||
case TSHL : return "TSHL";
|
return "TSHL";
|
||||||
case TL : return "Left";
|
case TL:
|
||||||
case TSLL : return "TSLL";
|
return "Left";
|
||||||
case KL : return "TSLL"; // ?
|
case TSLL:
|
||||||
case C : return "Straight";
|
return "TSLL";
|
||||||
case KR : return "TSLR"; // ?
|
case KL:
|
||||||
case TSLR : return "TSLR";
|
return "TSLL"; // ?
|
||||||
case TR : return "Right";
|
case C:
|
||||||
case TSHR : return "TSHR";
|
return "Straight";
|
||||||
case TRU : return "TU";
|
case KR:
|
||||||
case RNDB : return "RNDB" + roundaboutExit;
|
return "TSLR"; // ?
|
||||||
case RNLB : return "RNLB" + (-roundaboutExit);
|
case TSLR:
|
||||||
default : throw new IllegalArgumentException( "unknown command: " + cmd );
|
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()
|
public String getMessageString() {
|
||||||
{
|
switch (cmd) {
|
||||||
switch ( cmd )
|
case TU:
|
||||||
{
|
return "u-turn";
|
||||||
case TU : return "u-turn";
|
case TSHL:
|
||||||
case TSHL : return "sharp left";
|
return "sharp left";
|
||||||
case TL : return "left";
|
case TL:
|
||||||
case TSLL : return "slight left";
|
return "left";
|
||||||
case KL : return "keep left";
|
case TSLL:
|
||||||
case C : return "straight";
|
return "slight left";
|
||||||
case KR : return "keep right";
|
case KL:
|
||||||
case TSLR : return "slight right";
|
return "keep left";
|
||||||
case TR : return "right";
|
case C:
|
||||||
case TSHR : return "sharp right";
|
return "straight";
|
||||||
case TRU : return "u-turn";
|
case KR:
|
||||||
case RNDB : return "Take exit " + roundaboutExit;
|
return "keep right";
|
||||||
case RNLB : return "Take exit " + (-roundaboutExit);
|
case TSLR:
|
||||||
default : throw new IllegalArgumentException( "unknown command: " + cmd );
|
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()
|
public int getLocusAction() {
|
||||||
{
|
switch (cmd) {
|
||||||
switch ( cmd )
|
case TU:
|
||||||
{
|
return 13;
|
||||||
case TU : return 13;
|
case TSHL:
|
||||||
case TSHL : return 5;
|
return 5;
|
||||||
case TL : return 4;
|
case TL:
|
||||||
case TSLL : return 3;
|
return 4;
|
||||||
case KL : return 9; // ?
|
case TSLL:
|
||||||
case C : return 1;
|
return 3;
|
||||||
case KR : return 10; // ?
|
case KL:
|
||||||
case TSLR : return 6;
|
return 9; // ?
|
||||||
case TR : return 7;
|
case C:
|
||||||
case TSHR : return 8;
|
return 1;
|
||||||
case TRU : return 14;
|
case KR:
|
||||||
case RNDB : return 26 + roundaboutExit;
|
return 10; // ?
|
||||||
case RNLB : return 26 - roundaboutExit;
|
case TSLR:
|
||||||
default : throw new IllegalArgumentException( "unknown command: " + cmd );
|
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()
|
public int getOruxAction() {
|
||||||
{
|
switch (cmd) {
|
||||||
switch ( cmd )
|
case TU:
|
||||||
{
|
return 1003;
|
||||||
case TU : return 1003;
|
case TSHL:
|
||||||
case TSHL : return 1019;
|
return 1019;
|
||||||
case TL : return 1000;
|
case TL:
|
||||||
case TSLL : return 1017;
|
return 1000;
|
||||||
case KL : return 1015; // ?
|
case TSLL:
|
||||||
case C : return 1002;
|
return 1017;
|
||||||
case KR : return 1014; // ?
|
case KL:
|
||||||
case TSLR : return 1016;
|
return 1015; // ?
|
||||||
case TR : return 1001;
|
case C:
|
||||||
case TSHR : return 1018;
|
return 1002;
|
||||||
case TRU : return 1003;
|
case KR:
|
||||||
case RNDB : return 1008 + roundaboutExit;
|
return 1014; // ?
|
||||||
case RNLB : return 1008 + roundaboutExit;
|
case TSLR:
|
||||||
default : throw new IllegalArgumentException( "unknown command: " + cmd );
|
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 lowerBadWayAngle = -181;
|
||||||
float higherBadWayAngle = 181;
|
float higherBadWayAngle = 181;
|
||||||
if ( badWays != null )
|
if (badWays != null) {
|
||||||
{
|
for (MessageData badWay : badWays) {
|
||||||
for ( MessageData badWay : badWays )
|
if (badWay.isBadOneway()) {
|
||||||
{
|
|
||||||
if ( badWay.isBadOneway() )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( lowerBadWayAngle < badWay.turnangle && badWay.turnangle < goodWay.turnangle )
|
if (lowerBadWayAngle < badWay.turnangle && badWay.turnangle < goodWay.turnangle) {
|
||||||
{
|
|
||||||
lowerBadWayAngle = badWay.turnangle;
|
lowerBadWayAngle = badWay.turnangle;
|
||||||
}
|
}
|
||||||
if ( higherBadWayAngle > badWay.turnangle && badWay.turnangle > goodWay.turnangle )
|
if (higherBadWayAngle > badWay.turnangle && badWay.turnangle > goodWay.turnangle) {
|
||||||
{
|
|
||||||
higherBadWayAngle = badWay.turnangle;
|
higherBadWayAngle = badWay.turnangle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,100 +252,65 @@ public class VoiceHint
|
|||||||
float cmdAngle = angle;
|
float cmdAngle = angle;
|
||||||
|
|
||||||
// fall back to local angle if otherwise inconsistent
|
// fall back to local angle if otherwise inconsistent
|
||||||
if ( lowerBadWayAngle > angle || higherBadWayAngle < angle )
|
if (lowerBadWayAngle > angle || higherBadWayAngle < angle) {
|
||||||
{
|
|
||||||
cmdAngle = goodWay.turnangle;
|
cmdAngle = goodWay.turnangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roundaboutExit > 0)
|
if (roundaboutExit > 0) {
|
||||||
{
|
|
||||||
cmd = RNDB;
|
cmd = RNDB;
|
||||||
}
|
} else if (roundaboutExit < 0) {
|
||||||
else if (roundaboutExit < 0)
|
|
||||||
{
|
|
||||||
cmd = RNLB;
|
cmd = RNLB;
|
||||||
}
|
} else if (cmdAngle < -159.) {
|
||||||
else if ( cmdAngle < -159. )
|
|
||||||
{
|
|
||||||
cmd = TU;
|
cmd = TU;
|
||||||
}
|
} else if (cmdAngle < -135.) {
|
||||||
else if ( cmdAngle < -135. )
|
|
||||||
{
|
|
||||||
cmd = TSHL;
|
cmd = TSHL;
|
||||||
}
|
} else if (cmdAngle < -45.) {
|
||||||
else if ( cmdAngle < -45. )
|
|
||||||
{
|
|
||||||
// a TL can be pushed in either direction by a close-by alternative
|
// 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;
|
cmd = TSHL;
|
||||||
}
|
} else if (lowerBadWayAngle > -180. && lowerBadWayAngle < -90. && higherBadWayAngle > 0.) {
|
||||||
else if ( lowerBadWayAngle > -180. && lowerBadWayAngle < -90. && higherBadWayAngle > 0. )
|
|
||||||
{
|
|
||||||
cmd = TSLL;
|
cmd = TSLL;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd = TL;
|
cmd = TL;
|
||||||
}
|
}
|
||||||
}
|
} else if (cmdAngle < -21.) {
|
||||||
else if ( cmdAngle < -21. )
|
|
||||||
{
|
|
||||||
if (cmd != KR) // don't overwrite KR with TSLL
|
if (cmd != KR) // don't overwrite KR with TSLL
|
||||||
{
|
{
|
||||||
cmd = TSLL;
|
cmd = TSLL;
|
||||||
}
|
}
|
||||||
}
|
} else if (cmdAngle < 21.) {
|
||||||
else if ( cmdAngle < 21. )
|
|
||||||
{
|
|
||||||
if (cmd != KR && cmd != KL) // don't overwrite KL/KR hints!
|
if (cmd != KR && cmd != KL) // don't overwrite KL/KR hints!
|
||||||
{
|
{
|
||||||
cmd = C;
|
cmd = C;
|
||||||
}
|
}
|
||||||
}
|
} else if (cmdAngle < 45.) {
|
||||||
else if ( cmdAngle < 45. )
|
|
||||||
{
|
|
||||||
if (cmd != KL) // don't overwrite KL with TSLR
|
if (cmd != KL) // don't overwrite KL with TSLR
|
||||||
{
|
{
|
||||||
cmd = TSLR;
|
cmd = TSLR;
|
||||||
}
|
}
|
||||||
}
|
} else if (cmdAngle < 135.) {
|
||||||
else if ( cmdAngle < 135. )
|
|
||||||
{
|
|
||||||
// a TR can be pushed in either direction by a close-by alternative
|
// 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;
|
cmd = TSLR;
|
||||||
}
|
} else if (lowerBadWayAngle > 15. && lowerBadWayAngle < 90. && higherBadWayAngle > 180.) {
|
||||||
else if ( lowerBadWayAngle > 15. && lowerBadWayAngle < 90. && higherBadWayAngle > 180. )
|
|
||||||
{
|
|
||||||
cmd = TSHR;
|
cmd = TSHR;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd = TR;
|
cmd = TR;
|
||||||
}
|
}
|
||||||
}
|
} else if (cmdAngle < 159.) {
|
||||||
else if ( cmdAngle < 159. )
|
|
||||||
{
|
|
||||||
cmd = TSHR;
|
cmd = TSHR;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd = TRU;
|
cmd = TRU;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String formatGeometry()
|
public String formatGeometry() {
|
||||||
{
|
|
||||||
float oldPrio = oldWay == null ? 0.f : oldWay.priorityclassifier;
|
float oldPrio = oldWay == null ? 0.f : oldWay.priorityclassifier;
|
||||||
StringBuilder sb = new StringBuilder(30);
|
StringBuilder sb = new StringBuilder(30);
|
||||||
sb.append(' ').append((int) oldPrio);
|
sb.append(' ').append((int) oldPrio);
|
||||||
appendTurnGeometry(sb, goodWay);
|
appendTurnGeometry(sb, goodWay);
|
||||||
if ( badWays != null )
|
if (badWays != null) {
|
||||||
{
|
for (MessageData badWay : badWays) {
|
||||||
for ( MessageData badWay : badWays )
|
|
||||||
{
|
|
||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
appendTurnGeometry(sb, badWay);
|
appendTurnGeometry(sb, badWay);
|
||||||
}
|
}
|
||||||
@ -307,8 +318,7 @@ public class VoiceHint
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendTurnGeometry( StringBuilder sb, MessageData msg )
|
private void appendTurnGeometry(StringBuilder sb, MessageData msg) {
|
||||||
{
|
|
||||||
sb.append("(").append((int) (msg.turnangle + 0.5)).append(")").append((int) (msg.priorityclassifier));
|
sb.append("(").append((int) (msg.turnangle + 0.5)).append(")").append((int) (msg.priorityclassifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,30 +9,24 @@ package btools.router;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class VoiceHintList
|
public class VoiceHintList {
|
||||||
{
|
|
||||||
private String transportMode;
|
private String transportMode;
|
||||||
int turnInstructionMode;
|
int turnInstructionMode;
|
||||||
ArrayList<VoiceHint> list = new ArrayList<VoiceHint>();
|
ArrayList<VoiceHint> list = new ArrayList<VoiceHint>();
|
||||||
|
|
||||||
public void setTransportMode( boolean isCar, boolean isBike )
|
public void setTransportMode(boolean isCar, boolean isBike) {
|
||||||
{
|
|
||||||
transportMode = isCar ? "car" : (isBike ? "bike" : "foot");
|
transportMode = isCar ? "car" : (isBike ? "bike" : "foot");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTransportMode()
|
public String getTransportMode() {
|
||||||
{
|
|
||||||
return transportMode;
|
return transportMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLocusRouteType()
|
public int getLocusRouteType() {
|
||||||
{
|
if ("car".equals(transportMode)) {
|
||||||
if ( "car".equals( transportMode ) )
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ( "bike".equals( transportMode ) )
|
if ("bike".equals(transportMode)) {
|
||||||
{
|
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
return 3; // foot
|
return 3; // foot
|
||||||
|
|||||||
@ -8,26 +8,21 @@ package btools.router;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class VoiceHintProcessor
|
public final class VoiceHintProcessor {
|
||||||
{
|
|
||||||
private double catchingRange; // range to catch angles and merge turns
|
private double catchingRange; // range to catch angles and merge turns
|
||||||
private boolean explicitRoundabouts;
|
private boolean explicitRoundabouts;
|
||||||
|
|
||||||
public VoiceHintProcessor( double catchingRange, boolean explicitRoundabouts )
|
public VoiceHintProcessor(double catchingRange, boolean explicitRoundabouts) {
|
||||||
{
|
|
||||||
this.catchingRange = catchingRange;
|
this.catchingRange = catchingRange;
|
||||||
this.explicitRoundabouts = explicitRoundabouts;
|
this.explicitRoundabouts = explicitRoundabouts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float sumNonConsumedWithinCatchingRange( List<VoiceHint> inputs, int offset )
|
private float sumNonConsumedWithinCatchingRange(List<VoiceHint> inputs, int offset) {
|
||||||
{
|
|
||||||
double distance = 0.;
|
double distance = 0.;
|
||||||
float angle = 0.f;
|
float angle = 0.f;
|
||||||
while( offset >= 0 && distance < catchingRange )
|
while (offset >= 0 && distance < catchingRange) {
|
||||||
{
|
|
||||||
VoiceHint input = inputs.get(offset--);
|
VoiceHint input = inputs.get(offset--);
|
||||||
if ( input.turnAngleConsumed )
|
if (input.turnAngleConsumed) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
angle += input.goodWay.turnangle;
|
angle += input.goodWay.turnangle;
|
||||||
@ -44,10 +39,10 @@ public final class VoiceHintProcessor
|
|||||||
* order (from target to start), but output is
|
* order (from target to start), but output is
|
||||||
* returned in travel-direction and only for
|
* returned in travel-direction and only for
|
||||||
* those nodes that trigger a voice hint.
|
* those nodes that trigger a voice hint.
|
||||||
*
|
* <p>
|
||||||
* Input objects are expected for every segment
|
* Input objects are expected for every segment
|
||||||
* of the track, also for those without a junction
|
* of the track, also for those without a junction
|
||||||
*
|
* <p>
|
||||||
* VoiceHint objects in the output list are enriched
|
* VoiceHint objects in the output list are enriched
|
||||||
* by the voice-command, the total angle and the distance
|
* by the voice-command, the total angle and the distance
|
||||||
* to the next hint
|
* to the next hint
|
||||||
@ -55,16 +50,14 @@ public final class VoiceHintProcessor
|
|||||||
* @param inputs tracknodes, un reverse order
|
* @param inputs tracknodes, un reverse order
|
||||||
* @return voice hints, in forward 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>();
|
List<VoiceHint> results = new ArrayList<VoiceHint>();
|
||||||
double distance = 0.;
|
double distance = 0.;
|
||||||
float roundAboutTurnAngle = 0.f; // sums up angles in roundabout
|
float roundAboutTurnAngle = 0.f; // sums up angles in roundabout
|
||||||
|
|
||||||
int roundaboutExit = 0;
|
int roundaboutExit = 0;
|
||||||
|
|
||||||
for ( int hintIdx = 0; hintIdx < inputs.size(); hintIdx++ )
|
for (int hintIdx = 0; hintIdx < inputs.size(); hintIdx++) {
|
||||||
{
|
|
||||||
VoiceHint input = inputs.get(hintIdx);
|
VoiceHint input = inputs.get(hintIdx);
|
||||||
|
|
||||||
float turnAngle = input.goodWay.turnangle;
|
float turnAngle = input.goodWay.turnangle;
|
||||||
@ -75,28 +68,22 @@ public final class VoiceHintProcessor
|
|||||||
|
|
||||||
boolean isLink2Highway = input.oldWay.isLinktType() && !input.goodWay.isLinktType();
|
boolean isLink2Highway = input.oldWay.isLinktType() && !input.goodWay.isLinktType();
|
||||||
|
|
||||||
if ( input.oldWay.isRoundabout() )
|
if (input.oldWay.isRoundabout()) {
|
||||||
{
|
|
||||||
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
|
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
|
||||||
boolean isExit = roundaboutExit == 0; // exit point is always exit
|
boolean isExit = roundaboutExit == 0; // exit point is always exit
|
||||||
if ( input.badWays != null )
|
if (input.badWays != null) {
|
||||||
{
|
for (MessageData badWay : input.badWays) {
|
||||||
for ( MessageData badWay : input.badWays )
|
if (!badWay.isBadOneway() && badWay.isGoodForCars() && Math.abs(badWay.turnangle) < 120.) {
|
||||||
{
|
|
||||||
if ( !badWay.isBadOneway() && badWay.isGoodForCars() && Math.abs( badWay.turnangle ) < 120. )
|
|
||||||
{
|
|
||||||
isExit = true;
|
isExit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( isExit )
|
if (isExit) {
|
||||||
{
|
|
||||||
roundaboutExit++;
|
roundaboutExit++;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( roundaboutExit > 0 )
|
if (roundaboutExit > 0) {
|
||||||
{
|
|
||||||
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
|
roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
|
||||||
input.angle = roundAboutTurnAngle;
|
input.angle = roundAboutTurnAngle;
|
||||||
input.distanceToNext = distance;
|
input.distanceToNext = distance;
|
||||||
@ -114,50 +101,40 @@ public final class VoiceHintProcessor
|
|||||||
float minAngle = 180.f;
|
float minAngle = 180.f;
|
||||||
float minAbsAngeRaw = 180.f;
|
float minAbsAngeRaw = 180.f;
|
||||||
|
|
||||||
if ( input.badWays != null )
|
if (input.badWays != null) {
|
||||||
{
|
for (MessageData badWay : input.badWays) {
|
||||||
for ( MessageData badWay : input.badWays )
|
|
||||||
{
|
|
||||||
int badPrio = badWay.getPrio();
|
int badPrio = badWay.getPrio();
|
||||||
float badTurn = badWay.turnangle;
|
float badTurn = badWay.turnangle;
|
||||||
|
|
||||||
boolean isHighway2Link = !input.oldWay.isLinktType() && badWay.isLinktType();
|
boolean isHighway2Link = !input.oldWay.isLinktType() && badWay.isLinktType();
|
||||||
|
|
||||||
if ( badPrio > maxPrioAll && !isHighway2Link )
|
if (badPrio > maxPrioAll && !isHighway2Link) {
|
||||||
{
|
|
||||||
maxPrioAll = badPrio;
|
maxPrioAll = badPrio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( badWay.costfactor < 20.f && Math.abs( badTurn ) < minAbsAngeRaw )
|
if (badWay.costfactor < 20.f && Math.abs(badTurn) < minAbsAngeRaw) {
|
||||||
{
|
|
||||||
minAbsAngeRaw = Math.abs(badTurn);
|
minAbsAngeRaw = Math.abs(badTurn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( badPrio < minPrio )
|
if (badPrio < minPrio) {
|
||||||
{
|
|
||||||
continue; // ignore low prio ways
|
continue; // ignore low prio ways
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( badWay.isBadOneway() )
|
if (badWay.isBadOneway()) {
|
||||||
{
|
|
||||||
continue; // ignore wrong oneways
|
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
|
continue; // ways from the back should not trigger a slight turn
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( badPrio > maxPrioCandidates )
|
if (badPrio > maxPrioCandidates) {
|
||||||
{
|
|
||||||
maxPrioCandidates = badPrio;
|
maxPrioCandidates = badPrio;
|
||||||
}
|
}
|
||||||
if ( badTurn > maxAngle )
|
if (badTurn > maxAngle) {
|
||||||
{
|
|
||||||
maxAngle = badTurn;
|
maxAngle = badTurn;
|
||||||
}
|
}
|
||||||
if ( badTurn < minAngle )
|
if (badTurn < minAngle) {
|
||||||
{
|
|
||||||
minAngle = badTurn;
|
minAngle = badTurn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,20 +151,17 @@ public final class VoiceHintProcessor
|
|||||||
// with candidate detours equal in priority than the route exit leg
|
// with candidate detours equal in priority than the route exit leg
|
||||||
boolean conditionalTrigger = maxPrioCandidates >= minPrio;
|
boolean conditionalTrigger = maxPrioCandidates >= minPrio;
|
||||||
|
|
||||||
if ( unconditionalTrigger || conditionalTrigger )
|
if (unconditionalTrigger || conditionalTrigger) {
|
||||||
{
|
|
||||||
input.angle = turnAngle;
|
input.angle = turnAngle;
|
||||||
input.calcCommand();
|
input.calcCommand();
|
||||||
boolean isStraight = input.cmd == VoiceHint.C;
|
boolean isStraight = input.cmd == VoiceHint.C;
|
||||||
input.needsRealTurn = (!unconditionalTrigger) && isStraight;
|
input.needsRealTurn = (!unconditionalTrigger) && isStraight;
|
||||||
|
|
||||||
// check for KR/KL
|
// 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;
|
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.cmd = VoiceHint.KL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,8 +170,7 @@ public final class VoiceHintProcessor
|
|||||||
distance = 0.;
|
distance = 0.;
|
||||||
results.add(input);
|
results.add(input);
|
||||||
}
|
}
|
||||||
if ( results.size() > 0 && distance < catchingRange )
|
if (results.size() > 0 && distance < catchingRange) {
|
||||||
{
|
|
||||||
results.get(results.size() - 1).angle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
|
results.get(results.size() - 1).angle += sumNonConsumedWithinCatchingRange(inputs, hintIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,19 +180,15 @@ public final class VoiceHintProcessor
|
|||||||
|
|
||||||
List<VoiceHint> results2 = new ArrayList<VoiceHint>();
|
List<VoiceHint> results2 = new ArrayList<VoiceHint>();
|
||||||
int i = results.size();
|
int i = results.size();
|
||||||
while( i > 0 )
|
while (i > 0) {
|
||||||
{
|
|
||||||
VoiceHint hint = results.get(--i);
|
VoiceHint hint = results.get(--i);
|
||||||
if ( hint.cmd == 0 )
|
if (hint.cmd == 0) {
|
||||||
{
|
|
||||||
hint.calcCommand();
|
hint.calcCommand();
|
||||||
}
|
}
|
||||||
if ( ! ( hint.needsRealTurn && hint.cmd == VoiceHint.C ) )
|
if (!(hint.needsRealTurn && hint.cmd == VoiceHint.C)) {
|
||||||
{
|
|
||||||
double dist = hint.distanceToNext;
|
double dist = hint.distanceToNext;
|
||||||
// sum up other hints within the catching range (e.g. 40m)
|
// sum up other hints within the catching range (e.g. 40m)
|
||||||
while( dist < catchingRange && i > 0 )
|
while (dist < catchingRange && i > 0) {
|
||||||
{
|
|
||||||
VoiceHint h2 = results.get(i - 1);
|
VoiceHint h2 = results.get(i - 1);
|
||||||
dist = h2.distanceToNext;
|
dist = h2.distanceToNext;
|
||||||
hint.distanceToNext += dist;
|
hint.distanceToNext += dist;
|
||||||
@ -233,8 +202,7 @@ public final class VoiceHintProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !explicitRoundabouts )
|
if (!explicitRoundabouts) {
|
||||||
{
|
|
||||||
hint.roundaboutExit = 0; // use an angular hint instead
|
hint.roundaboutExit = 0; // use an angular hint instead
|
||||||
}
|
}
|
||||||
hint.calcCommand();
|
hint.calcCommand();
|
||||||
|
|||||||
@ -2,8 +2,7 @@ package btools.expressions;
|
|||||||
|
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
final class BExpression
|
final class BExpression {
|
||||||
{
|
|
||||||
private static final int OR_EXP = 10;
|
private static final int OR_EXP = 10;
|
||||||
private static final int AND_EXP = 11;
|
private static final int AND_EXP = 11;
|
||||||
private static final int NOT_EXP = 12;
|
private static final int NOT_EXP = 12;
|
||||||
@ -37,35 +36,28 @@ final class BExpression
|
|||||||
private int[] lookupValueIdxArray;
|
private int[] lookupValueIdxArray;
|
||||||
|
|
||||||
// Parse the expression and all subexpression
|
// Parse the expression and all subexpression
|
||||||
public static BExpression parse( BExpressionContext ctx, int level ) throws Exception
|
public static BExpression parse(BExpressionContext ctx, int level) throws Exception {
|
||||||
{
|
|
||||||
return parse(ctx, level, null);
|
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;
|
boolean brackets = false;
|
||||||
String operator = ctx.parseToken();
|
String operator = ctx.parseToken();
|
||||||
if ( optionalToken != null && optionalToken.equals( operator ) )
|
if (optionalToken != null && optionalToken.equals(operator)) {
|
||||||
{
|
|
||||||
operator = ctx.parseToken();
|
operator = ctx.parseToken();
|
||||||
}
|
}
|
||||||
if ( "(".equals( operator ) )
|
if ("(".equals(operator)) {
|
||||||
{
|
|
||||||
brackets = true;
|
brackets = true;
|
||||||
operator = ctx.parseToken();
|
operator = ctx.parseToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( operator == null )
|
if (operator == null) {
|
||||||
{
|
|
||||||
if (level == 0) return null;
|
if (level == 0) return null;
|
||||||
else throw new IllegalArgumentException("unexpected end of file");
|
else throw new IllegalArgumentException("unexpected end of file");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( level == 0 )
|
if (level == 0) {
|
||||||
{
|
if (!"assign".equals(operator)) {
|
||||||
if ( !"assign".equals( operator ) )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("operator " + operator + " is invalid on toplevel (only 'assign' allowed)");
|
throw new IllegalArgumentException("operator " + operator + " is invalid on toplevel (only 'assign' allowed)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,94 +66,62 @@ final class BExpression
|
|||||||
int nops = 3;
|
int nops = 3;
|
||||||
boolean ifThenElse = false;
|
boolean ifThenElse = false;
|
||||||
|
|
||||||
if ( "switch".equals( operator ) )
|
if ("switch".equals(operator)) {
|
||||||
{
|
|
||||||
exp.typ = SWITCH_EXP;
|
exp.typ = SWITCH_EXP;
|
||||||
}
|
} else if ("if".equals(operator)) {
|
||||||
else if ( "if".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = SWITCH_EXP;
|
exp.typ = SWITCH_EXP;
|
||||||
ifThenElse = true;
|
ifThenElse = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nops = 2; // check binary expressions
|
nops = 2; // check binary expressions
|
||||||
|
|
||||||
if ( "or".equals( operator ) )
|
if ("or".equals(operator)) {
|
||||||
{
|
|
||||||
exp.typ = OR_EXP;
|
exp.typ = OR_EXP;
|
||||||
}
|
} else if ("and".equals(operator)) {
|
||||||
else if ( "and".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = AND_EXP;
|
exp.typ = AND_EXP;
|
||||||
}
|
} else if ("multiply".equals(operator)) {
|
||||||
else if ( "multiply".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = MULTIPLY_EXP;
|
exp.typ = MULTIPLY_EXP;
|
||||||
}
|
} else if ("add".equals(operator)) {
|
||||||
else if ( "add".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = ADD_EXP;
|
exp.typ = ADD_EXP;
|
||||||
}
|
} else if ("max".equals(operator)) {
|
||||||
else if ( "max".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = MAX_EXP;
|
exp.typ = MAX_EXP;
|
||||||
}
|
} else if ("min".equals(operator)) {
|
||||||
else if ( "min".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = MIN_EXP;
|
exp.typ = MIN_EXP;
|
||||||
}
|
} else if ("equal".equals(operator)) {
|
||||||
else if ( "equal".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = EQUAL_EXP;
|
exp.typ = EQUAL_EXP;
|
||||||
}
|
} else if ("greater".equals(operator)) {
|
||||||
else if ( "greater".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = GREATER_EXP;
|
exp.typ = GREATER_EXP;
|
||||||
}
|
} else if ("sub".equals(operator)) {
|
||||||
else if ( "sub".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = SUB_EXP;
|
exp.typ = SUB_EXP;
|
||||||
}
|
} else if ("lesser".equals(operator)) {
|
||||||
else if ( "lesser".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = LESSER_EXP;
|
exp.typ = LESSER_EXP;
|
||||||
}
|
} else if ("xor".equals(operator)) {
|
||||||
else if ( "xor".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = XOR_EXP;
|
exp.typ = XOR_EXP;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nops = 1; // check unary expressions
|
nops = 1; // check unary expressions
|
||||||
if ( "assign".equals( operator ) )
|
if ("assign".equals(operator)) {
|
||||||
{
|
|
||||||
if (level > 0) throw new IllegalArgumentException("assign operator within expression");
|
if (level > 0) throw new IllegalArgumentException("assign operator within expression");
|
||||||
exp.typ = ASSIGN_EXP;
|
exp.typ = ASSIGN_EXP;
|
||||||
String variable = ctx.parseToken();
|
String variable = ctx.parseToken();
|
||||||
if (variable == null) throw new IllegalArgumentException("unexpected end of file");
|
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)
|
||||||
if ( variable.indexOf( ':' ) >= 0 ) throw new IllegalArgumentException( "cannot assign context-prefixed variable: " + variable );
|
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);
|
exp.variableIdx = ctx.getVariableIdx(variable, true);
|
||||||
if ( exp.variableIdx < ctx.getMinWriteIdx() ) throw new IllegalArgumentException( "cannot assign to readonly variable " + variable );
|
if (exp.variableIdx < ctx.getMinWriteIdx())
|
||||||
}
|
throw new IllegalArgumentException("cannot assign to readonly variable " + variable);
|
||||||
else if ( "not".equals( operator ) )
|
} else if ("not".equals(operator)) {
|
||||||
{
|
|
||||||
exp.typ = NOT_EXP;
|
exp.typ = NOT_EXP;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nops = 0; // check elemantary expressions
|
nops = 0; // check elemantary expressions
|
||||||
int idx = operator.indexOf('=');
|
int idx = operator.indexOf('=');
|
||||||
if ( idx >= 0 )
|
if (idx >= 0) {
|
||||||
{
|
|
||||||
exp.typ = LOOKUP_EXP;
|
exp.typ = LOOKUP_EXP;
|
||||||
String name = operator.substring(0, idx);
|
String name = operator.substring(0, idx);
|
||||||
String values = operator.substring(idx + 1);
|
String values = operator.substring(idx + 1);
|
||||||
|
|
||||||
exp.lookupNameIdx = ctx.getLookupNameIdx(name);
|
exp.lookupNameIdx = ctx.getLookupNameIdx(name);
|
||||||
if ( exp.lookupNameIdx < 0 )
|
if (exp.lookupNameIdx < 0) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unknown lookup name: " + name);
|
throw new IllegalArgumentException("unknown lookup name: " + name);
|
||||||
}
|
}
|
||||||
ctx.markLookupIdxUsed(exp.lookupNameIdx);
|
ctx.markLookupIdxUsed(exp.lookupNameIdx);
|
||||||
@ -169,18 +129,14 @@ final class BExpression
|
|||||||
int nt = tk.countTokens();
|
int nt = tk.countTokens();
|
||||||
int nt2 = nt == 0 ? 1 : nt;
|
int nt2 = nt == 0 ? 1 : nt;
|
||||||
exp.lookupValueIdxArray = new int[nt2];
|
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() : "";
|
String value = ti < nt ? tk.nextToken() : "";
|
||||||
exp.lookupValueIdxArray[ti] = ctx.getLookupValueIdx(exp.lookupNameIdx, value);
|
exp.lookupValueIdxArray[ti] = ctx.getLookupValueIdx(exp.lookupNameIdx, value);
|
||||||
if ( exp.lookupValueIdxArray[ti] < 0 )
|
if (exp.lookupValueIdxArray[ti] < 0) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unknown lookup value: " + value);
|
throw new IllegalArgumentException("unknown lookup value: " + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if ((idx = operator.indexOf(':')) >= 0) {
|
||||||
else if ( ( idx = operator.indexOf( ':' ) ) >= 0 )
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
use of variable values
|
use of variable values
|
||||||
assign no_height
|
assign no_height
|
||||||
@ -198,31 +154,20 @@ final class BExpression
|
|||||||
exp.typ = FOREIGN_VARIABLE_EXP;
|
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.typ = VARIABLE_EXP;
|
||||||
exp.variableIdx = idx;
|
exp.variableIdx = idx;
|
||||||
}
|
} else if ("true".equals(operator)) {
|
||||||
else if ( "true".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.numberValue = 1.f;
|
exp.numberValue = 1.f;
|
||||||
exp.typ = NUMBER_EXP;
|
exp.typ = NUMBER_EXP;
|
||||||
}
|
} else if ("false".equals(operator)) {
|
||||||
else if ( "false".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.numberValue = 0.f;
|
exp.numberValue = 0.f;
|
||||||
exp.typ = NUMBER_EXP;
|
exp.typ = NUMBER_EXP;
|
||||||
}
|
} else {
|
||||||
else
|
try {
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
exp.numberValue = Float.parseFloat(operator);
|
exp.numberValue = Float.parseFloat(operator);
|
||||||
exp.typ = NUMBER_EXP;
|
exp.typ = NUMBER_EXP;
|
||||||
}
|
} catch (NumberFormatException nfe) {
|
||||||
catch( NumberFormatException nfe )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unknown expression: " + operator);
|
throw new IllegalArgumentException("unknown expression: " + operator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,71 +175,81 @@ final class BExpression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// parse operands
|
// parse operands
|
||||||
if ( nops > 0 )
|
if (nops > 0) {
|
||||||
{
|
|
||||||
exp.op1 = BExpression.parse(ctx, level + 1, exp.typ == ASSIGN_EXP ? "=" : null);
|
exp.op1 = BExpression.parse(ctx, level + 1, exp.typ == ASSIGN_EXP ? "=" : null);
|
||||||
}
|
}
|
||||||
if ( nops > 1 )
|
if (nops > 1) {
|
||||||
{
|
|
||||||
if (ifThenElse) checkExpectedToken(ctx, "then");
|
if (ifThenElse) checkExpectedToken(ctx, "then");
|
||||||
exp.op2 = BExpression.parse(ctx, level + 1, null);
|
exp.op2 = BExpression.parse(ctx, level + 1, null);
|
||||||
}
|
}
|
||||||
if ( nops > 2 )
|
if (nops > 2) {
|
||||||
{
|
|
||||||
if (ifThenElse) checkExpectedToken(ctx, "else");
|
if (ifThenElse) checkExpectedToken(ctx, "else");
|
||||||
exp.op3 = BExpression.parse(ctx, level + 1, null);
|
exp.op3 = BExpression.parse(ctx, level + 1, null);
|
||||||
}
|
}
|
||||||
if ( brackets )
|
if (brackets) {
|
||||||
{
|
|
||||||
checkExpectedToken(ctx, ")");
|
checkExpectedToken(ctx, ")");
|
||||||
}
|
}
|
||||||
return exp;
|
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();
|
String token = ctx.parseToken();
|
||||||
if ( ! expected.equals( token ) )
|
if (!expected.equals(token)) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unexpected token: " + token + ", expected: " + expected);
|
throw new IllegalArgumentException("unexpected token: " + token + ", expected: " + expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the expression
|
// Evaluate the expression
|
||||||
public float evaluate( BExpressionContext ctx )
|
public float evaluate(BExpressionContext ctx) {
|
||||||
{
|
switch (typ) {
|
||||||
switch( typ )
|
case OR_EXP:
|
||||||
{
|
return op1.evaluate(ctx) != 0.f ? 1.f : (op2.evaluate(ctx) != 0.f ? 1.f : 0.f);
|
||||||
case OR_EXP: return op1.evaluate(ctx) != 0.f ? 1.f : ( op2.evaluate(ctx) != 0.f ? 1.f : 0.f );
|
case XOR_EXP:
|
||||||
case XOR_EXP: return ( (op1.evaluate(ctx) != 0.f) ^ ( op2.evaluate(ctx) != 0.f ) ? 1.f : 0.f );
|
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 AND_EXP:
|
||||||
case ADD_EXP: return op1.evaluate(ctx) + op2.evaluate(ctx);
|
return op1.evaluate(ctx) != 0.f ? (op2.evaluate(ctx) != 0.f ? 1.f : 0.f) : 0.f;
|
||||||
case SUB_EXP: return op1.evaluate(ctx) - op2.evaluate(ctx);
|
case ADD_EXP:
|
||||||
case MULTIPLY_EXP: return op1.evaluate(ctx) * op2.evaluate(ctx);
|
return op1.evaluate(ctx) + op2.evaluate(ctx);
|
||||||
case MAX_EXP: return max( op1.evaluate(ctx), op2.evaluate(ctx) );
|
case SUB_EXP:
|
||||||
case MIN_EXP: return min( op1.evaluate(ctx), op2.evaluate(ctx) );
|
return op1.evaluate(ctx) - op2.evaluate(ctx);
|
||||||
case EQUAL_EXP: return op1.evaluate(ctx) == op2.evaluate(ctx) ? 1.f : 0.f;
|
case MULTIPLY_EXP:
|
||||||
case GREATER_EXP: return op1.evaluate(ctx) > op2.evaluate(ctx) ? 1.f : 0.f;
|
return op1.evaluate(ctx) * op2.evaluate(ctx);
|
||||||
case LESSER_EXP: return op1.evaluate(ctx) < op2.evaluate(ctx) ? 1.f : 0.f;
|
case MAX_EXP:
|
||||||
case SWITCH_EXP: return op1.evaluate(ctx) != 0.f ? op2.evaluate(ctx) : op3.evaluate(ctx);
|
return max(op1.evaluate(ctx), op2.evaluate(ctx));
|
||||||
case ASSIGN_EXP: return ctx.assign( variableIdx, op1.evaluate(ctx) );
|
case MIN_EXP:
|
||||||
case LOOKUP_EXP: return ctx.getLookupMatch( lookupNameIdx, lookupValueIdxArray );
|
return min(op1.evaluate(ctx), op2.evaluate(ctx));
|
||||||
case NUMBER_EXP: return numberValue;
|
case EQUAL_EXP:
|
||||||
case VARIABLE_EXP: return ctx.getVariableValue( variableIdx );
|
return op1.evaluate(ctx) == op2.evaluate(ctx) ? 1.f : 0.f;
|
||||||
case FOREIGN_VARIABLE_EXP: return ctx.getForeignVariableValue( variableIdx );
|
case GREATER_EXP:
|
||||||
case VARIABLE_GET_EXP: return ctx.getLookupValue(lookupNameIdx);
|
return op1.evaluate(ctx) > op2.evaluate(ctx) ? 1.f : 0.f;
|
||||||
case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f;
|
case LESSER_EXP:
|
||||||
default: throw new IllegalArgumentException( "unknown op-code: " + typ );
|
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;
|
return v1 > v2 ? v1 : v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float min( float v1, float v2 )
|
private float min(float v1, float v2) {
|
||||||
{
|
|
||||||
return v1 < v2 ? v1 : v2;
|
return v1 < v2 ? v1 : v2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,8 +25,7 @@ import btools.util.IByteArrayUnifier;
|
|||||||
import btools.util.LruMap;
|
import btools.util.LruMap;
|
||||||
|
|
||||||
|
|
||||||
public abstract class BExpressionContext implements IByteArrayUnifier
|
public abstract class BExpressionContext implements IByteArrayUnifier {
|
||||||
{
|
|
||||||
private static final String CONTEXT_TAG = "---context:";
|
private static final String CONTEXT_TAG = "---context:";
|
||||||
private static final String MODEL_TAG = "---model:";
|
private static final String MODEL_TAG = "---model:";
|
||||||
|
|
||||||
@ -76,15 +75,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
|
|
||||||
private BExpressionContext foreignContext;
|
private BExpressionContext foreignContext;
|
||||||
|
|
||||||
protected void setInverseVars()
|
protected void setInverseVars() {
|
||||||
{
|
|
||||||
currentVarOffset = nBuildInVars;
|
currentVarOffset = nBuildInVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract String[] getBuildInVariableNames();
|
abstract String[] getBuildInVariableNames();
|
||||||
|
|
||||||
public final float getBuildInVariable( int idx )
|
public final float getBuildInVariable(int idx) {
|
||||||
{
|
|
||||||
return currentVars[idx + currentVarOffset];
|
return currentVars[idx + currentVarOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,8 +90,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
public BExpressionMetaData meta;
|
public BExpressionMetaData meta;
|
||||||
private boolean lookupDataValid = false;
|
private boolean lookupDataValid = false;
|
||||||
|
|
||||||
protected BExpressionContext( String context, BExpressionMetaData meta )
|
protected BExpressionContext(String context, BExpressionMetaData meta) {
|
||||||
{
|
|
||||||
this(context, 4096, meta);
|
this(context, 4096, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +100,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
* @param context global, way or node - context of that instance
|
* @param context global, way or node - context of that instance
|
||||||
* @param hashSize size of hashmap for result caching
|
* @param hashSize size of hashmap for result caching
|
||||||
*/
|
*/
|
||||||
protected BExpressionContext( String context, int hashSize, BExpressionMetaData meta )
|
protected BExpressionContext(String context, int hashSize, BExpressionMetaData meta) {
|
||||||
{
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
|
|
||||||
@ -114,8 +109,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
if (Boolean.getBoolean("disableExpressionCache")) hashSize = 1;
|
if (Boolean.getBoolean("disableExpressionCache")) hashSize = 1;
|
||||||
|
|
||||||
// create the expression cache
|
// create the expression cache
|
||||||
if ( hashSize > 0 )
|
if (hashSize > 0) {
|
||||||
{
|
|
||||||
cache = new LruMap(4 * hashSize, hashSize);
|
cache = new LruMap(4 * hashSize, hashSize);
|
||||||
resultVarCache = new LruMap(4096, 4096);
|
resultVarCache = new LruMap(4096, 4096);
|
||||||
}
|
}
|
||||||
@ -124,14 +118,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
/**
|
/**
|
||||||
* encode internal lookup data to a byte array
|
* encode internal lookup data to a byte array
|
||||||
*/
|
*/
|
||||||
public byte[] encode()
|
public byte[] encode() {
|
||||||
{
|
if (!lookupDataValid)
|
||||||
if ( !lookupDataValid ) throw new IllegalArgumentException( "internal error: encoding undefined data?" );
|
throw new IllegalArgumentException("internal error: encoding undefined data?");
|
||||||
return encode(lookupData);
|
return encode(lookupData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] encode( int[] ld )
|
public byte[] encode(int[] ld) {
|
||||||
{
|
|
||||||
BitCoderContext ctx = ctxEndode;
|
BitCoderContext ctx = ctxEndode;
|
||||||
ctx.reset();
|
ctx.reset();
|
||||||
|
|
||||||
@ -144,8 +137,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
for (int inum = 1; inum < lookupValues.size(); inum++) // loop over lookup names
|
for (int inum = 1; inum < lookupValues.size(); inum++) // loop over lookup names
|
||||||
{
|
{
|
||||||
int d = ld[inum];
|
int d = ld[inum];
|
||||||
if ( d == 0 )
|
if (d == 0) {
|
||||||
{
|
|
||||||
skippedTags++;
|
skippedTags++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -172,7 +164,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
decode(ld2, false, ab);
|
decode(ld2, false, ab);
|
||||||
for (int inum = 1; inum < lookupValues.size(); inum++) // loop over lookup names (except reverse dir)
|
for (int inum = 1; inum < lookupValues.size(); inum++) // loop over lookup names (except reverse dir)
|
||||||
{
|
{
|
||||||
if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab) );
|
if (ld2[inum] != ld[inum])
|
||||||
|
throw new RuntimeException("assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ab;
|
return ab;
|
||||||
@ -182,19 +175,16 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
/**
|
/**
|
||||||
* decode byte array to internal lookup data
|
* decode byte array to internal lookup data
|
||||||
*/
|
*/
|
||||||
public void decode( byte[] ab )
|
public void decode(byte[] ab) {
|
||||||
{
|
|
||||||
decode(lookupData, false, ab);
|
decode(lookupData, false, ab);
|
||||||
lookupDataValid = true;
|
lookupDataValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* decode a byte-array into a lookup data array
|
* decode a byte-array into a lookup data array
|
||||||
*/
|
*/
|
||||||
private void decode( int[] ld, boolean inverseDirection, byte[] ab )
|
private void decode(int[] ld, boolean inverseDirection, byte[] ab) {
|
||||||
{
|
|
||||||
BitCoderContext ctx = ctxDecode;
|
BitCoderContext ctx = ctxDecode;
|
||||||
ctx.reset(ab);
|
ctx.reset(ab);
|
||||||
|
|
||||||
@ -203,8 +193,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
|
|
||||||
// all others are generic
|
// all others are generic
|
||||||
int inum = 1;
|
int inum = 1;
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
int delta = ctx.decodeVarBits();
|
int delta = ctx.decodeVarBits();
|
||||||
if (delta == 0) break;
|
if (delta == 0) break;
|
||||||
if (inum + delta > ld.length) break; // higher minor version is o.k.
|
if (inum + delta > ld.length) break; // higher minor version is o.k.
|
||||||
@ -220,8 +209,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
while (inum < ld.length) ld[inum++] = 0;
|
while (inum < ld.length) ld[inum++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKeyValueDescription( boolean inverseDirection, byte[] ab )
|
public String getKeyValueDescription(boolean inverseDirection, byte[] ab) {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder(200);
|
StringBuilder sb = new StringBuilder(200);
|
||||||
decode(lookupData, inverseDirection, ab);
|
decode(lookupData, inverseDirection, ab);
|
||||||
for (int inum = 0; inum < lookupValues.size(); inum++) // loop over lookup names
|
for (int inum = 0; inum < lookupValues.size(); inum++) // loop over lookup names
|
||||||
@ -229,8 +217,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
BExpressionLookupValue[] va = lookupValues.get(inum);
|
BExpressionLookupValue[] va = lookupValues.get(inum);
|
||||||
int val = lookupData[inum];
|
int val = lookupData[inum];
|
||||||
String value = (val >= 1000) ? Float.toString((val - 1000) / 100f) : va[val].toString();
|
String value = (val >= 1000) ? Float.toString((val - 1000) / 100f) : va[val].toString();
|
||||||
if ( value != null && value.length() > 0 )
|
if (value != null && value.length() > 0) {
|
||||||
{
|
|
||||||
if (sb.length() > 0) sb.append(' ');
|
if (sb.length() > 0) sb.append(' ');
|
||||||
sb.append(lookupNames.get(inum) + "=" + value);
|
sb.append(lookupNames.get(inum) + "=" + value);
|
||||||
}
|
}
|
||||||
@ -238,8 +225,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getKeyValueList( boolean inverseDirection, byte[] ab )
|
public List<String> getKeyValueList(boolean inverseDirection, byte[] ab) {
|
||||||
{
|
|
||||||
ArrayList<String> res = new ArrayList<String>();
|
ArrayList<String> res = new ArrayList<String>();
|
||||||
decode(lookupData, inverseDirection, ab);
|
decode(lookupData, inverseDirection, ab);
|
||||||
for (int inum = 0; inum < lookupValues.size(); inum++) // loop over lookup names
|
for (int inum = 0; inum < lookupValues.size(); inum++) // loop over lookup names
|
||||||
@ -248,8 +234,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
int val = lookupData[inum];
|
int val = lookupData[inum];
|
||||||
// no negative values
|
// no negative values
|
||||||
String value = (val >= 1000) ? Float.toString((val - 1000) / 100f) : va[val].toString();
|
String value = (val >= 1000) ? Float.toString((val - 1000) / 100f) : va[val].toString();
|
||||||
if ( value != null && value.length() > 0 )
|
if (value != null && value.length() > 0) {
|
||||||
{
|
|
||||||
res.add(lookupNames.get(inum));
|
res.add(lookupNames.get(inum));
|
||||||
res.add(value);
|
res.add(value);
|
||||||
}
|
}
|
||||||
@ -261,7 +246,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
int res = -1;
|
int res = -1;
|
||||||
try {
|
try {
|
||||||
res = lookupNumbers.get(name).intValue();
|
res = lookupNumbers.get(name).intValue();
|
||||||
} catch (Exception e ) {}
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,8 +271,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
private int parsedLines = 0;
|
private int parsedLines = 0;
|
||||||
private boolean fixTagsWritten = false;
|
private boolean fixTagsWritten = false;
|
||||||
|
|
||||||
public void parseMetaLine( String line )
|
public void parseMetaLine(String line) {
|
||||||
{
|
|
||||||
parsedLines++;
|
parsedLines++;
|
||||||
StringTokenizer tk = new StringTokenizer(line, " ");
|
StringTokenizer tk = new StringTokenizer(line, " ");
|
||||||
String name = tk.nextToken();
|
String name = tk.nextToken();
|
||||||
@ -294,8 +279,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
int idx = name.indexOf(';');
|
int idx = name.indexOf(';');
|
||||||
if (idx >= 0) name = name.substring(0, idx);
|
if (idx >= 0) name = name.substring(0, idx);
|
||||||
|
|
||||||
if ( !fixTagsWritten )
|
if (!fixTagsWritten) {
|
||||||
{
|
|
||||||
fixTagsWritten = true;
|
fixTagsWritten = true;
|
||||||
if ("way".equals(context)) addLookupValue("reversedirection", "yes", null);
|
if ("way".equals(context)) addLookupValue("reversedirection", "yes", null);
|
||||||
else if ("node".equals(context)) addLookupValue("nodeaccessgranted", "yes", null);
|
else if ("node".equals(context)) addLookupValue("nodeaccessgranted", "yes", null);
|
||||||
@ -308,10 +292,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
while (newValue != null && tk.hasMoreTokens()) newValue.addAlias(tk.nextToken());
|
while (newValue != null && tk.hasMoreTokens()) newValue.addAlias(tk.nextToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finishMetaParsing()
|
public void finishMetaParsing() {
|
||||||
{
|
if (parsedLines == 0 && !"global".equals(context)) {
|
||||||
if ( parsedLines == 0 && !"global".equals(context) )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("lookup table does not contain data for context " + context + " (old version?)");
|
throw new IllegalArgumentException("lookup table does not contain data for context " + context + " (old version?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,17 +303,14 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
lookupIdxUsed = new boolean[lookupValues.size()];
|
lookupIdxUsed = new boolean[lookupValues.size()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void evaluate( int[] lookupData2 )
|
public final void evaluate(int[] lookupData2) {
|
||||||
{
|
|
||||||
lookupData = lookupData2;
|
lookupData = lookupData2;
|
||||||
evaluate();
|
evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evaluate()
|
private void evaluate() {
|
||||||
{
|
|
||||||
int n = expressionList.size();
|
int n = expressionList.size();
|
||||||
for( int expidx = 0; expidx < n; expidx++ )
|
for (int expidx = 0; expidx < n; expidx++) {
|
||||||
{
|
|
||||||
expressionList.get(expidx).evaluate(this);
|
expressionList.get(expidx).evaluate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,35 +319,28 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
private long requests2;
|
private long requests2;
|
||||||
private long cachemisses;
|
private long cachemisses;
|
||||||
|
|
||||||
public String cacheStats()
|
public String cacheStats() {
|
||||||
{
|
|
||||||
return "requests=" + requests + " requests2=" + requests2 + " cachemisses=" + cachemisses;
|
return "requests=" + requests + " requests2=" + requests2 + " cachemisses=" + cachemisses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CacheNode lastCacheNode = new CacheNode();
|
private CacheNode lastCacheNode = new CacheNode();
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
public final byte[] unify( byte[] ab, int offset, int len )
|
public final byte[] unify(byte[] ab, int offset, int len) {
|
||||||
{
|
|
||||||
probeCacheNode.ab = null; // crc based cache lookup only
|
probeCacheNode.ab = null; // crc based cache lookup only
|
||||||
probeCacheNode.hash = Crc32.crc(ab, offset, len);
|
probeCacheNode.hash = Crc32.crc(ab, offset, len);
|
||||||
|
|
||||||
CacheNode cn = (CacheNode) cache.get(probeCacheNode);
|
CacheNode cn = (CacheNode) cache.get(probeCacheNode);
|
||||||
if ( cn != null )
|
if (cn != null) {
|
||||||
{
|
|
||||||
byte[] cab = cn.ab;
|
byte[] cab = cn.ab;
|
||||||
if ( cab.length == len )
|
if (cab.length == len) {
|
||||||
{
|
for (int i = 0; i < len; i++) {
|
||||||
for( int i=0; i<len; i++ )
|
if (cab[i] != ab[i + offset]) {
|
||||||
{
|
|
||||||
if ( cab[i] != ab[i+offset] )
|
|
||||||
{
|
|
||||||
cn = null;
|
cn = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( cn != null )
|
if (cn != null) {
|
||||||
{
|
|
||||||
lastCacheNode = cn;
|
lastCacheNode = cn;
|
||||||
return cn.ab;
|
return cn.ab;
|
||||||
}
|
}
|
||||||
@ -380,16 +352,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final void evaluate( boolean inverseDirection, byte[] ab )
|
public final void evaluate(boolean inverseDirection, byte[] ab) {
|
||||||
{
|
|
||||||
requests++;
|
requests++;
|
||||||
lookupDataValid = false; // this is an assertion for a nasty pifall
|
lookupDataValid = false; // this is an assertion for a nasty pifall
|
||||||
|
|
||||||
if ( cache == null )
|
if (cache == null) {
|
||||||
{
|
|
||||||
decode(lookupData, inverseDirection, ab);
|
decode(lookupData, inverseDirection, ab);
|
||||||
if ( currentVars == null || currentVars.length != nBuildInVars )
|
if (currentVars == null || currentVars.length != nBuildInVars) {
|
||||||
{
|
|
||||||
currentVars = new float[nBuildInVars];
|
currentVars = new float[nBuildInVars];
|
||||||
}
|
}
|
||||||
evaluateInto(currentVars, 0);
|
evaluateInto(currentVars, 0);
|
||||||
@ -398,32 +367,26 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
CacheNode cn;
|
CacheNode cn;
|
||||||
if ( lastCacheNode.ab == ab )
|
if (lastCacheNode.ab == ab) {
|
||||||
{
|
|
||||||
cn = lastCacheNode;
|
cn = lastCacheNode;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
probeCacheNode.ab = ab;
|
probeCacheNode.ab = ab;
|
||||||
probeCacheNode.hash = Crc32.crc(ab, 0, ab.length);
|
probeCacheNode.hash = Crc32.crc(ab, 0, ab.length);
|
||||||
cn = (CacheNode) cache.get(probeCacheNode);
|
cn = (CacheNode) cache.get(probeCacheNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cn == null )
|
if (cn == null) {
|
||||||
{
|
|
||||||
cachemisses++;
|
cachemisses++;
|
||||||
|
|
||||||
cn = (CacheNode) cache.removeLru();
|
cn = (CacheNode) cache.removeLru();
|
||||||
if ( cn == null )
|
if (cn == null) {
|
||||||
{
|
|
||||||
cn = new CacheNode();
|
cn = new CacheNode();
|
||||||
}
|
}
|
||||||
cn.hash = probeCacheNode.hash;
|
cn.hash = probeCacheNode.hash;
|
||||||
cn.ab = ab;
|
cn.ab = ab;
|
||||||
cache.put(cn);
|
cache.put(cn);
|
||||||
|
|
||||||
if ( probeVarSet.vars == null )
|
if (probeVarSet.vars == null) {
|
||||||
{
|
|
||||||
probeVarSet.vars = new float[2 * nBuildInVars];
|
probeVarSet.vars = new float[2 * nBuildInVars];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,11 +402,9 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
|
|
||||||
// unify the result variable set
|
// unify the result variable set
|
||||||
VarWrapper vw = (VarWrapper) resultVarCache.get(probeVarSet);
|
VarWrapper vw = (VarWrapper) resultVarCache.get(probeVarSet);
|
||||||
if ( vw == null )
|
if (vw == null) {
|
||||||
{
|
|
||||||
vw = (VarWrapper) resultVarCache.removeLru();
|
vw = (VarWrapper) resultVarCache.removeLru();
|
||||||
if ( vw == null )
|
if (vw == null) {
|
||||||
{
|
|
||||||
vw = new VarWrapper();
|
vw = new VarWrapper();
|
||||||
}
|
}
|
||||||
vw.hash = probeVarSet.hash;
|
vw.hash = probeVarSet.hash;
|
||||||
@ -452,9 +413,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
resultVarCache.put(vw);
|
resultVarCache.put(vw);
|
||||||
}
|
}
|
||||||
cn.vars = vw.vars;
|
cn.vars = vw.vars;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ab == cn.ab) requests2++;
|
if (ab == cn.ab) requests2++;
|
||||||
|
|
||||||
cache.touch(cn);
|
cache.touch(cn);
|
||||||
@ -464,36 +423,30 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
currentVarOffset = inverseDirection ? nBuildInVars : 0;
|
currentVarOffset = inverseDirection ? nBuildInVars : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evaluateInto( float[] vars, int offset )
|
private void evaluateInto(float[] vars, int offset) {
|
||||||
{
|
|
||||||
evaluate();
|
evaluate();
|
||||||
for ( int vi = 0; vi < nBuildInVars; vi++ )
|
for (int vi = 0; vi < nBuildInVars; vi++) {
|
||||||
{
|
|
||||||
int idx = buildInVariableIdx[vi];
|
int idx = buildInVariableIdx[vi];
|
||||||
vars[vi + offset] = idx == -1 ? 0.f : variableData[idx];
|
vars[vi + offset] = idx == -1 ? 0.f : variableData[idx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void dumpStatistics()
|
public void dumpStatistics() {
|
||||||
{
|
|
||||||
TreeMap<String, String> counts = new TreeMap<String, String>();
|
TreeMap<String, String> counts = new TreeMap<String, String>();
|
||||||
// first count
|
// first count
|
||||||
for( String name: lookupNumbers.keySet() )
|
for (String name : lookupNumbers.keySet()) {
|
||||||
{
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
int inum = lookupNumbers.get(name).intValue();
|
int inum = lookupNumbers.get(name).intValue();
|
||||||
int[] histo = lookupHistograms.get(inum);
|
int[] histo = lookupHistograms.get(inum);
|
||||||
// if ( histo.length == 500 ) continue;
|
// if ( histo.length == 500 ) continue;
|
||||||
for( int i=2; i<histo.length; i++ )
|
for (int i = 2; i < histo.length; i++) {
|
||||||
{
|
|
||||||
cnt += histo[i];
|
cnt += histo[i];
|
||||||
}
|
}
|
||||||
counts.put("" + (1000000000 + cnt) + "_" + name, name);
|
counts.put("" + (1000000000 + cnt) + "_" + name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
while( counts.size() > 0 )
|
while (counts.size() > 0) {
|
||||||
{
|
|
||||||
String key = counts.lastEntry().getKey();
|
String key = counts.lastEntry().getKey();
|
||||||
String name = counts.get(key);
|
String name = counts.get(key);
|
||||||
counts.remove(key);
|
counts.remove(key);
|
||||||
@ -502,15 +455,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
int[] histo = lookupHistograms.get(inum);
|
int[] histo = lookupHistograms.get(inum);
|
||||||
if (values.length == 1000) continue;
|
if (values.length == 1000) continue;
|
||||||
String[] svalues = new String[values.length];
|
String[] svalues = new String[values.length];
|
||||||
for( int i=0; i<values.length; i++ )
|
for (int i = 0; i < values.length; i++) {
|
||||||
{
|
|
||||||
String scnt = "0000000000" + histo[i];
|
String scnt = "0000000000" + histo[i];
|
||||||
scnt = scnt.substring(scnt.length() - 10);
|
scnt = scnt.substring(scnt.length() - 10);
|
||||||
svalues[i] = scnt + " " + values[i].toString();
|
svalues[i] = scnt + " " + values[i].toString();
|
||||||
}
|
}
|
||||||
Arrays.sort(svalues);
|
Arrays.sort(svalues);
|
||||||
for( int i=svalues.length-1; i>=0; i-- )
|
for (int i = svalues.length - 1; i >= 0; i--) {
|
||||||
{
|
|
||||||
System.out.println(name + ";" + svalues[i]);
|
System.out.println(name + ";" + svalues[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -519,10 +470,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
/**
|
/**
|
||||||
* @return a new lookupData array, or null if no metadata defined
|
* @return a new lookupData array, or null if no metadata defined
|
||||||
*/
|
*/
|
||||||
public int[] createNewLookupData()
|
public int[] createNewLookupData() {
|
||||||
{
|
if (lookupDataFrozen) {
|
||||||
if ( lookupDataFrozen )
|
|
||||||
{
|
|
||||||
return new int[lookupValues.size()];
|
return new int[lookupValues.size()];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -531,12 +480,10 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
/**
|
/**
|
||||||
* generate random values for regression testing
|
* generate random values for regression testing
|
||||||
*/
|
*/
|
||||||
public int[] generateRandomValues( Random rnd )
|
public int[] generateRandomValues(Random rnd) {
|
||||||
{
|
|
||||||
int[] data = createNewLookupData();
|
int[] data = createNewLookupData();
|
||||||
data[0] = 2 * rnd.nextInt(2); // reverse-direction = 0 or 2
|
data[0] = 2 * rnd.nextInt(2); // reverse-direction = 0 or 2
|
||||||
for( int inum = 1; inum < data.length; inum++ )
|
for (int inum = 1; inum < data.length; inum++) {
|
||||||
{
|
|
||||||
int nvalues = lookupValues.get(inum).length;
|
int nvalues = lookupValues.get(inum).length;
|
||||||
data[inum] = 0;
|
data[inum] = 0;
|
||||||
if (inum > 1 && rnd.nextInt(10) > 0) continue; // tags other than highway only 10%
|
if (inum > 1 && rnd.nextInt(10) > 0) continue; // tags other than highway only 10%
|
||||||
@ -546,27 +493,21 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertAllVariablesEqual( BExpressionContext other )
|
public void assertAllVariablesEqual(BExpressionContext other) {
|
||||||
{
|
|
||||||
int nv = variableData.length;
|
int nv = variableData.length;
|
||||||
int nv2 = other.variableData.length;
|
int nv2 = other.variableData.length;
|
||||||
if (nv != nv2) throw new RuntimeException("mismatch in variable-count: " + nv + "<->" + nv2);
|
if (nv != nv2) throw new RuntimeException("mismatch in variable-count: " + nv + "<->" + nv2);
|
||||||
for( int i=0; i<nv; i++ )
|
for (int i = 0; i < nv; i++) {
|
||||||
{
|
if (variableData[i] != other.variableData[i]) {
|
||||||
if ( variableData[i] != other.variableData[i] )
|
|
||||||
{
|
|
||||||
throw new RuntimeException("mismatch in variable " + variableName(i) + " " + variableData[i] + "<->" + other.variableData[i]
|
throw new RuntimeException("mismatch in variable " + variableName(i) + " " + variableData[i] + "<->" + other.variableData[i]
|
||||||
+ "\ntags = " + getKeyValueDescription(false, encode()));
|
+ "\ntags = " + getKeyValueDescription(false, encode()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String variableName( int idx )
|
public String variableName(int idx) {
|
||||||
{
|
for (Map.Entry<String, Integer> e : variableNumbers.entrySet()) {
|
||||||
for( Map.Entry<String,Integer> e : variableNumbers.entrySet() )
|
if (e.getValue().intValue() == idx) {
|
||||||
{
|
|
||||||
if ( e.getValue().intValue() == idx )
|
|
||||||
{
|
|
||||||
return e.getKey();
|
return e.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -581,14 +522,11 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
*
|
*
|
||||||
* @return a newly created value element, if any, to optionally add aliases
|
* @return a newly created value element, if any, to optionally add aliases
|
||||||
*/
|
*/
|
||||||
public BExpressionLookupValue addLookupValue( String name, String value, int[] lookupData2 )
|
public BExpressionLookupValue addLookupValue(String name, String value, int[] lookupData2) {
|
||||||
{
|
|
||||||
BExpressionLookupValue newValue = null;
|
BExpressionLookupValue newValue = null;
|
||||||
Integer num = lookupNumbers.get(name);
|
Integer num = lookupNumbers.get(name);
|
||||||
if ( num == null )
|
if (num == null) {
|
||||||
{
|
if (lookupData2 != null) {
|
||||||
if ( lookupData2 != null )
|
|
||||||
{
|
|
||||||
// do not create unknown name for external data array
|
// do not create unknown name for external data array
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
@ -611,16 +549,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
int[] histo = lookupHistograms.get(inum);
|
int[] histo = lookupHistograms.get(inum);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
boolean bFoundAsterix = false;
|
boolean bFoundAsterix = false;
|
||||||
for( ; i<values.length; i++ )
|
for (; i < values.length; i++) {
|
||||||
{
|
|
||||||
BExpressionLookupValue v = values[i];
|
BExpressionLookupValue v = values[i];
|
||||||
if (v.equals("*")) bFoundAsterix = true;
|
if (v.equals("*")) bFoundAsterix = true;
|
||||||
if (v.matches(value)) break;
|
if (v.matches(value)) break;
|
||||||
}
|
}
|
||||||
if ( i == values.length )
|
if (i == values.length) {
|
||||||
{
|
if (lookupData2 != null) {
|
||||||
if ( lookupData2 != null )
|
|
||||||
{
|
|
||||||
// do not create unknown value for external data array,
|
// do not create unknown value for external data array,
|
||||||
// record as 'unknown' instead
|
// record as 'unknown' instead
|
||||||
lookupData2[inum] = 1; // 1 == unknown
|
lookupData2[inum] = 1; // 1 == unknown
|
||||||
@ -666,58 +601,48 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
foot += inch / 12f;
|
foot += inch / 12f;
|
||||||
}
|
}
|
||||||
value = String.format(Locale.US, "%3.1f", foot * 0.3048f);
|
value = String.format(Locale.US, "%3.1f", foot * 0.3048f);
|
||||||
}
|
} else if (value.contains("in") || value.contains("\"")) {
|
||||||
else if (value.contains("in") || value.contains("\"")) {
|
|
||||||
float inch = 0f;
|
float inch = 0f;
|
||||||
if (value.indexOf("in") > 0) value = value.substring(0, value.indexOf("in"));
|
if (value.indexOf("in") > 0) value = value.substring(0, value.indexOf("in"));
|
||||||
if (value.indexOf("\"") > 0) value = value.substring(0, value.indexOf("\""));
|
if (value.indexOf("\"") > 0) value = value.substring(0, value.indexOf("\""));
|
||||||
inch = Float.parseFloat(value.trim());
|
inch = Float.parseFloat(value.trim());
|
||||||
value = String.format(Locale.US, "%3.1f", inch * 0.0254f);
|
value = String.format(Locale.US, "%3.1f", inch * 0.0254f);
|
||||||
}
|
} else if (value.toLowerCase().contains("feet") || value.toLowerCase().contains("foot")) {
|
||||||
else if (value.toLowerCase().contains("feet") || value.toLowerCase().contains("foot")) {
|
|
||||||
float feet = 0f;
|
float feet = 0f;
|
||||||
String s = value.substring(0, value.toLowerCase().indexOf("f"));
|
String s = value.substring(0, value.toLowerCase().indexOf("f"));
|
||||||
feet = Float.parseFloat(s.trim());
|
feet = Float.parseFloat(s.trim());
|
||||||
value = String.format(Locale.US, "%3.1f", feet * 0.3048f);
|
value = String.format(Locale.US, "%3.1f", feet * 0.3048f);
|
||||||
}
|
} else if (value.toLowerCase().contains("fathom") || value.toLowerCase().contains("fm")) {
|
||||||
else if (value.toLowerCase().contains("fathom") || value.toLowerCase().contains("fm")) {
|
|
||||||
float fathom = 0f;
|
float fathom = 0f;
|
||||||
String s = value.substring(0, value.toLowerCase().indexOf("f"));
|
String s = value.substring(0, value.toLowerCase().indexOf("f"));
|
||||||
fathom = Float.parseFloat(s.trim());
|
fathom = Float.parseFloat(s.trim());
|
||||||
value = String.format(Locale.US, "%3.1f", fathom * 1.8288f);
|
value = String.format(Locale.US, "%3.1f", fathom * 1.8288f);
|
||||||
}
|
} else if (value.contains("cm")) {
|
||||||
else if (value.contains("cm")) {
|
|
||||||
String[] sa = value.trim().split("cm");
|
String[] sa = value.trim().split("cm");
|
||||||
if (sa.length == 1) value = sa[0].trim();
|
if (sa.length == 1) value = sa[0].trim();
|
||||||
float cm = Float.parseFloat(value.trim());
|
float cm = Float.parseFloat(value.trim());
|
||||||
value = String.format(Locale.US, "%3.1f", cm * 100f);
|
value = String.format(Locale.US, "%3.1f", cm * 100f);
|
||||||
}
|
} else if (value.toLowerCase().contains("meter")) {
|
||||||
else if (value.toLowerCase().contains("meter")) {
|
|
||||||
String s = value.substring(0, value.toLowerCase().indexOf("m"));
|
String s = value.substring(0, value.toLowerCase().indexOf("m"));
|
||||||
value = s.trim();
|
value = s.trim();
|
||||||
}
|
} else if (value.toLowerCase().contains("mph")) {
|
||||||
else if (value.toLowerCase().contains("mph")) {
|
|
||||||
value = value.replace("_", "");
|
value = value.replace("_", "");
|
||||||
String[] sa = value.trim().toLowerCase().split("mph");
|
String[] sa = value.trim().toLowerCase().split("mph");
|
||||||
if (sa.length >= 1) value = sa[0].trim();
|
if (sa.length >= 1) value = sa[0].trim();
|
||||||
float mph = Float.parseFloat(value.trim());
|
float mph = Float.parseFloat(value.trim());
|
||||||
value = String.format(Locale.US, "%3.1f", mph * 1.609344f);
|
value = String.format(Locale.US, "%3.1f", mph * 1.609344f);
|
||||||
}
|
} else if (value.toLowerCase().contains("knot")) {
|
||||||
else if (value.toLowerCase().contains("knot")) {
|
|
||||||
String[] sa = value.trim().toLowerCase().split("knot");
|
String[] sa = value.trim().toLowerCase().split("knot");
|
||||||
if (sa.length >= 1) value = sa[0].trim();
|
if (sa.length >= 1) value = sa[0].trim();
|
||||||
float nm = Float.parseFloat(value.trim());
|
float nm = Float.parseFloat(value.trim());
|
||||||
value = String.format(Locale.US, "%3.1f", nm * 1.852f);
|
value = String.format(Locale.US, "%3.1f", nm * 1.852f);
|
||||||
}
|
} else if (value.contains("kmh") || value.contains("km/h") || value.contains("kph")) {
|
||||||
else if (value.contains("kmh") || value.contains("km/h") || value.contains("kph")) {
|
|
||||||
String[] sa = value.trim().split("k");
|
String[] sa = value.trim().split("k");
|
||||||
if (sa.length == 1) value = sa[0].trim();
|
if (sa.length == 1) value = sa[0].trim();
|
||||||
}
|
} else if (value.contains("m")) {
|
||||||
else if (value.contains("m")) {
|
|
||||||
String s = value.substring(0, value.toLowerCase().indexOf("m"));
|
String s = value.substring(0, value.toLowerCase().indexOf("m"));
|
||||||
value = s.trim();
|
value = s.trim();
|
||||||
}
|
} else if (value.contains("(")) {
|
||||||
else if (value.contains("(")) {
|
|
||||||
String s = value.substring(0, value.toLowerCase().indexOf("("));
|
String s = value.substring(0, value.toLowerCase().indexOf("("));
|
||||||
value = s.trim();
|
value = s.trim();
|
||||||
}
|
}
|
||||||
@ -734,12 +659,10 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( i == 499 )
|
if (i == 499) {
|
||||||
{
|
|
||||||
// System.out.println( "value limit reached for: " + name );
|
// System.out.println( "value limit reached for: " + name );
|
||||||
}
|
}
|
||||||
if ( i == 500 )
|
if (i == 500) {
|
||||||
{
|
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
// unknown value, create
|
// unknown value, create
|
||||||
@ -767,18 +690,17 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
* add a value-index to to internal array
|
* add a value-index to to internal array
|
||||||
* value-index means 0=unknown, 1=other, 2=value-x, ...
|
* value-index means 0=unknown, 1=other, 2=value-x, ...
|
||||||
*/
|
*/
|
||||||
public void addLookupValue( String name, int valueIndex )
|
public void addLookupValue(String name, int valueIndex) {
|
||||||
{
|
|
||||||
Integer num = lookupNumbers.get(name);
|
Integer num = lookupNumbers.get(name);
|
||||||
if ( num == null )
|
if (num == null) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for that value
|
// look for that value
|
||||||
int inum = num.intValue();
|
int inum = num.intValue();
|
||||||
int nvalues = lookupValues.get(inum).length;
|
int nvalues = lookupValues.get(inum).length;
|
||||||
if ( valueIndex < 0 || valueIndex >= nvalues ) throw new IllegalArgumentException( "value index out of range for name " + name + ": " + valueIndex );
|
if (valueIndex < 0 || valueIndex >= nvalues)
|
||||||
|
throw new IllegalArgumentException("value index out of range for name " + name + ": " + valueIndex);
|
||||||
lookupData[inum] = valueIndex;
|
lookupData[inum] = valueIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,11 +711,9 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
* add a 2=yes if the provided value is out of range
|
* add a 2=yes if the provided value is out of range
|
||||||
* value-index means here 0=unknown, 1=other, 2=yes, 3=proposed
|
* value-index means here 0=unknown, 1=other, 2=yes, 3=proposed
|
||||||
*/
|
*/
|
||||||
public void addSmallestLookupValue( String name, int valueIndex )
|
public void addSmallestLookupValue(String name, int valueIndex) {
|
||||||
{
|
|
||||||
Integer num = lookupNumbers.get(name);
|
Integer num = lookupNumbers.get(name);
|
||||||
if ( num == null )
|
if (num == null) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,42 +721,33 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
int inum = num.intValue();
|
int inum = num.intValue();
|
||||||
int nvalues = lookupValues.get(inum).length;
|
int nvalues = lookupValues.get(inum).length;
|
||||||
int oldValueIndex = lookupData[inum];
|
int oldValueIndex = lookupData[inum];
|
||||||
if ( oldValueIndex > 1 && oldValueIndex < valueIndex )
|
if (oldValueIndex > 1 && oldValueIndex < valueIndex) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( valueIndex >= nvalues )
|
if (valueIndex >= nvalues) {
|
||||||
{
|
|
||||||
valueIndex = nvalues - 1;
|
valueIndex = nvalues - 1;
|
||||||
}
|
}
|
||||||
if ( valueIndex < 0 ) throw new IllegalArgumentException( "value index out of range for name " + name + ": " + valueIndex );
|
if (valueIndex < 0)
|
||||||
|
throw new IllegalArgumentException("value index out of range for name " + name + ": " + valueIndex);
|
||||||
lookupData[inum] = valueIndex;
|
lookupData[inum] = valueIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBooleanLookupValue( String name )
|
public boolean getBooleanLookupValue(String name) {
|
||||||
{
|
|
||||||
Integer num = lookupNumbers.get(name);
|
Integer num = lookupNumbers.get(name);
|
||||||
return num != null && lookupData[num.intValue()] == 2;
|
return num != null && lookupData[num.intValue()] == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOutputVariableIndex( String name, boolean mustExist )
|
public int getOutputVariableIndex(String name, boolean mustExist) {
|
||||||
{
|
|
||||||
int idx = getVariableIdx(name, false);
|
int idx = getVariableIdx(name, false);
|
||||||
if ( idx < 0 )
|
if (idx < 0) {
|
||||||
{
|
if (mustExist) {
|
||||||
if ( mustExist )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unknown variable: " + name);
|
throw new IllegalArgumentException("unknown variable: " + name);
|
||||||
}
|
}
|
||||||
}
|
} else if (idx < minWriteIdx) {
|
||||||
else if ( idx < minWriteIdx )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("bad access to global variable: " + name);
|
throw new IllegalArgumentException("bad access to global variable: " + name);
|
||||||
}
|
}
|
||||||
for( int i=0; i<nBuildInVars; i++ )
|
for (int i = 0; i < nBuildInVars; i++) {
|
||||||
{
|
if (buildInVariableIdx[i] == idx) {
|
||||||
if ( buildInVariableIdx[i] == idx )
|
|
||||||
{
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -847,35 +758,27 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
return nBuildInVars++;
|
return nBuildInVars++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setForeignContext( BExpressionContext foreignContext )
|
public void setForeignContext(BExpressionContext foreignContext) {
|
||||||
{
|
|
||||||
this.foreignContext = foreignContext;
|
this.foreignContext = foreignContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getForeignVariableValue( int foreignIndex )
|
public float getForeignVariableValue(int foreignIndex) {
|
||||||
{
|
|
||||||
return foreignContext.getBuildInVariable(foreignIndex);
|
return foreignContext.getBuildInVariable(foreignIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getForeignVariableIdx( String context, String name )
|
public int getForeignVariableIdx(String context, String name) {
|
||||||
{
|
if (foreignContext == null || !context.equals(foreignContext.context)) {
|
||||||
if ( foreignContext == null || !context.equals( foreignContext.context ) )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unknown foreign context: " + context);
|
throw new IllegalArgumentException("unknown foreign context: " + context);
|
||||||
}
|
}
|
||||||
return foreignContext.getOutputVariableIndex(name, true);
|
return foreignContext.getOutputVariableIndex(name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parseFile( File file, String readOnlyContext )
|
public void parseFile(File file, String readOnlyContext) {
|
||||||
{
|
if (!file.exists()) {
|
||||||
if ( !file.exists() )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("profile " + file + " does not exist");
|
throw new IllegalArgumentException("profile " + file + " does not exist");
|
||||||
}
|
}
|
||||||
try
|
try {
|
||||||
{
|
if (readOnlyContext != null) {
|
||||||
if ( readOnlyContext != null )
|
|
||||||
{
|
|
||||||
linenr = 1;
|
linenr = 1;
|
||||||
String realContext = context;
|
String realContext = context;
|
||||||
context = readOnlyContext;
|
context = readOnlyContext;
|
||||||
@ -893,40 +796,32 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
String[] varNames = getBuildInVariableNames();
|
String[] varNames = getBuildInVariableNames();
|
||||||
nBuildInVars = varNames.length;
|
nBuildInVars = varNames.length;
|
||||||
buildInVariableIdx = new int[nBuildInVars];
|
buildInVariableIdx = new int[nBuildInVars];
|
||||||
for( int vi=0; vi<varNames.length; vi++ )
|
for (int vi = 0; vi < varNames.length; vi++) {
|
||||||
{
|
|
||||||
buildInVariableIdx[vi] = getVariableIdx(varNames[vi], false);
|
buildInVariableIdx[vi] = getVariableIdx(varNames[vi], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] readOnlyData = variableData;
|
float[] readOnlyData = variableData;
|
||||||
variableData = new float[variableNumbers.size()];
|
variableData = new float[variableNumbers.size()];
|
||||||
for( int i=0; i<minWriteIdx; i++ )
|
for (int i = 0; i < minWriteIdx; i++) {
|
||||||
{
|
|
||||||
variableData[i] = readOnlyData[i];
|
variableData[i] = readOnlyData[i];
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch( Exception e )
|
if (e instanceof IllegalArgumentException) {
|
||||||
{
|
|
||||||
if ( e instanceof IllegalArgumentException )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("ParseException " + file + " at line " + linenr + ": " + e.getMessage());
|
throw new IllegalArgumentException("ParseException " + file + " at line " + linenr + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
if ( expressionList.size() == 0 )
|
if (expressionList.size() == 0) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException(file.getAbsolutePath()
|
throw new IllegalArgumentException(file.getAbsolutePath()
|
||||||
+ " does not contain expressions for context " + context + " (old version?)");
|
+ " does not contain expressions for context " + context + " (old version?)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BExpression> _parseFile( File file ) throws Exception
|
private List<BExpression> _parseFile(File file) throws Exception {
|
||||||
{
|
|
||||||
_br = new BufferedReader(new FileReader(file));
|
_br = new BufferedReader(new FileReader(file));
|
||||||
_readerDone = false;
|
_readerDone = false;
|
||||||
List<BExpression> result = new ArrayList<BExpression>();
|
List<BExpression> result = new ArrayList<BExpression>();
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
BExpression exp = BExpression.parse(this, 0);
|
BExpression exp = BExpression.parse(this, 0);
|
||||||
if (exp == null) break;
|
if (exp == null) break;
|
||||||
result.add(exp);
|
result.add(exp);
|
||||||
@ -938,124 +833,95 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
|
|
||||||
public void setVariableValue(String name, float value, boolean create) {
|
public void setVariableValue(String name, float value, boolean create) {
|
||||||
Integer num = variableNumbers.get(name);
|
Integer num = variableNumbers.get(name);
|
||||||
if ( num != null )
|
if (num != null) {
|
||||||
{
|
|
||||||
variableData[num.intValue()] = value;
|
variableData[num.intValue()] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getVariableValue( String name, float defaultValue )
|
public float getVariableValue(String name, float defaultValue) {
|
||||||
{
|
|
||||||
Integer num = variableNumbers.get(name);
|
Integer num = variableNumbers.get(name);
|
||||||
return num == null ? defaultValue : getVariableValue(num.intValue());
|
return num == null ? defaultValue : getVariableValue(num.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
float getVariableValue( int variableIdx )
|
float getVariableValue(int variableIdx) {
|
||||||
{
|
|
||||||
return variableData[variableIdx];
|
return variableData[variableIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
int getVariableIdx( String name, boolean create )
|
int getVariableIdx(String name, boolean create) {
|
||||||
{
|
|
||||||
Integer num = variableNumbers.get(name);
|
Integer num = variableNumbers.get(name);
|
||||||
if ( num == null )
|
if (num == null) {
|
||||||
{
|
if (create) {
|
||||||
if ( create )
|
|
||||||
{
|
|
||||||
num = new Integer(variableNumbers.size());
|
num = new Integer(variableNumbers.size());
|
||||||
variableNumbers.put(name, num);
|
variableNumbers.put(name, num);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return num.intValue();
|
return num.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getMinWriteIdx()
|
int getMinWriteIdx() {
|
||||||
{
|
|
||||||
return minWriteIdx;
|
return minWriteIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getLookupMatch( int nameIdx, int[] valueIdxArray )
|
float getLookupMatch(int nameIdx, int[] valueIdxArray) {
|
||||||
{
|
for (int i = 0; i < valueIdxArray.length; i++) {
|
||||||
for( int i=0; i<valueIdxArray.length; i++ )
|
if (lookupData[nameIdx] == valueIdxArray[i]) {
|
||||||
{
|
|
||||||
if ( lookupData[nameIdx] == valueIdxArray[i] )
|
|
||||||
{
|
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLookupNameIdx( String name )
|
public int getLookupNameIdx(String name) {
|
||||||
{
|
|
||||||
Integer num = lookupNumbers.get(name);
|
Integer num = lookupNumbers.get(name);
|
||||||
return num == null ? -1 : num.intValue();
|
return num == null ? -1 : num.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void markLookupIdxUsed( int idx )
|
public final void markLookupIdxUsed(int idx) {
|
||||||
{
|
|
||||||
lookupIdxUsed[idx] = true;
|
lookupIdxUsed[idx] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isLookupIdxUsed( int idx )
|
public final boolean isLookupIdxUsed(int idx) {
|
||||||
{
|
|
||||||
return idx < lookupIdxUsed.length ? lookupIdxUsed[idx] : false;
|
return idx < lookupIdxUsed.length ? lookupIdxUsed[idx] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setAllTagsUsed()
|
public final void setAllTagsUsed() {
|
||||||
{
|
for (int i = 0; i < lookupIdxUsed.length; i++) {
|
||||||
for( int i=0; i<lookupIdxUsed.length; i++ )
|
|
||||||
{
|
|
||||||
lookupIdxUsed[i] = true;
|
lookupIdxUsed[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getLookupValueIdx( int nameIdx, String value )
|
int getLookupValueIdx(int nameIdx, String value) {
|
||||||
{
|
|
||||||
BExpressionLookupValue[] values = lookupValues.get(nameIdx);
|
BExpressionLookupValue[] values = lookupValues.get(nameIdx);
|
||||||
for( int i=0; i< values.length; i++ )
|
for (int i = 0; i < values.length; i++) {
|
||||||
{
|
|
||||||
if (values[i].equals(value)) return i;
|
if (values[i].equals(value)) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String parseToken() throws Exception
|
String parseToken() throws Exception {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
String token = _parseToken();
|
String token = _parseToken();
|
||||||
if (token == null) return null;
|
if (token == null) return null;
|
||||||
if ( token.startsWith( CONTEXT_TAG ) )
|
if (token.startsWith(CONTEXT_TAG)) {
|
||||||
{
|
|
||||||
_inOurContext = token.substring(CONTEXT_TAG.length()).equals(context);
|
_inOurContext = token.substring(CONTEXT_TAG.length()).equals(context);
|
||||||
}
|
} else if (token.startsWith(MODEL_TAG)) {
|
||||||
else if ( token.startsWith( MODEL_TAG ) )
|
|
||||||
{
|
|
||||||
_modelClass = token.substring(MODEL_TAG.length()).trim();
|
_modelClass = token.substring(MODEL_TAG.length()).trim();
|
||||||
}
|
} else if (_inOurContext) {
|
||||||
else if ( _inOurContext )
|
|
||||||
{
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String _parseToken() throws Exception
|
private String _parseToken() throws Exception {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder(32);
|
StringBuilder sb = new StringBuilder(32);
|
||||||
boolean inComment = false;
|
boolean inComment = false;
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
int ic = _readerDone ? -1 : _br.read();
|
int ic = _readerDone ? -1 : _br.read();
|
||||||
if ( ic < 0 )
|
if (ic < 0) {
|
||||||
{
|
|
||||||
if (sb.length() == 0) return null;
|
if (sb.length() == 0) return null;
|
||||||
_readerDone = true;
|
_readerDone = true;
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@ -1063,13 +929,11 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
char c = (char) ic;
|
char c = (char) ic;
|
||||||
if (c == '\n') linenr++;
|
if (c == '\n') linenr++;
|
||||||
|
|
||||||
if ( inComment )
|
if (inComment) {
|
||||||
{
|
|
||||||
if (c == '\r' || c == '\n') inComment = false;
|
if (c == '\r' || c == '\n') inComment = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( Character.isWhitespace( c ) )
|
if (Character.isWhitespace(c)) {
|
||||||
{
|
|
||||||
if (sb.length() > 0) return sb.toString();
|
if (sb.length() > 0) return sb.toString();
|
||||||
else continue;
|
else continue;
|
||||||
}
|
}
|
||||||
@ -1078,8 +942,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float assign( int variableIdx, float value )
|
float assign(int variableIdx, float value) {
|
||||||
{
|
|
||||||
variableData[variableIdx] = value;
|
variableData[variableIdx] = value;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,22 +7,20 @@
|
|||||||
package btools.expressions;
|
package btools.expressions;
|
||||||
|
|
||||||
|
|
||||||
|
public final class BExpressionContextNode extends BExpressionContext {
|
||||||
public final class BExpressionContextNode extends BExpressionContext
|
|
||||||
{
|
|
||||||
private static String[] buildInVariables =
|
private static String[] buildInVariables =
|
||||||
{"initialcost"};
|
{"initialcost"};
|
||||||
|
|
||||||
protected String[] getBuildInVariableNames()
|
protected String[] getBuildInVariableNames() {
|
||||||
{
|
|
||||||
return buildInVariables;
|
return buildInVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getInitialcost() { return getBuildInVariable(0); }
|
public float getInitialcost() {
|
||||||
|
return getBuildInVariable(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public BExpressionContextNode( BExpressionMetaData meta )
|
public BExpressionContextNode(BExpressionMetaData meta) {
|
||||||
{
|
|
||||||
super("node", meta);
|
super("node", meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,8 +29,7 @@ public final class BExpressionContextNode extends BExpressionContext
|
|||||||
*
|
*
|
||||||
* @param hashSize size of hashmap for result caching
|
* @param hashSize size of hashmap for result caching
|
||||||
*/
|
*/
|
||||||
public BExpressionContextNode( int hashSize, BExpressionMetaData meta )
|
public BExpressionContextNode(int hashSize, BExpressionMetaData meta) {
|
||||||
{
|
|
||||||
super("node", hashSize, meta);
|
super("node", hashSize, meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,33 +8,65 @@ package btools.expressions;
|
|||||||
|
|
||||||
import btools.codec.TagValueValidator;
|
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 boolean decodeForbidden = true;
|
||||||
|
|
||||||
private static String[] buildInVariables =
|
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;
|
return buildInVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getCostfactor() { return getBuildInVariable(0); }
|
public float getCostfactor() {
|
||||||
public float getTurncost() { return getBuildInVariable(1); }
|
return getBuildInVariable(0);
|
||||||
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 )
|
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);
|
super("way", meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,22 +75,18 @@ public final class BExpressionContextWay extends BExpressionContext implements T
|
|||||||
*
|
*
|
||||||
* @param hashSize size of hashmap for result caching
|
* @param hashSize size of hashmap for result caching
|
||||||
*/
|
*/
|
||||||
public BExpressionContextWay( int hashSize, BExpressionMetaData meta )
|
public BExpressionContextWay(int hashSize, BExpressionMetaData meta) {
|
||||||
{
|
|
||||||
super("way", hashSize, meta);
|
super("way", hashSize, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int accessType( byte[] description )
|
public int accessType(byte[] description) {
|
||||||
{
|
|
||||||
evaluate(false, description);
|
evaluate(false, description);
|
||||||
float minCostFactor = getCostfactor();
|
float minCostFactor = getCostfactor();
|
||||||
if ( minCostFactor >= 9999.f )
|
if (minCostFactor >= 9999.f) {
|
||||||
{
|
|
||||||
setInverseVars();
|
setInverseVars();
|
||||||
float reverseCostFactor = getCostfactor();
|
float reverseCostFactor = getCostfactor();
|
||||||
if ( reverseCostFactor < minCostFactor )
|
if (reverseCostFactor < minCostFactor) {
|
||||||
{
|
|
||||||
minCostFactor = reverseCostFactor;
|
minCostFactor = reverseCostFactor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,8 +94,7 @@ public final class BExpressionContextWay extends BExpressionContext implements T
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDecodeForbidden( boolean decodeForbidden )
|
public void setDecodeForbidden(boolean decodeForbidden) {
|
||||||
{
|
|
||||||
this.decodeForbidden = decodeForbidden;
|
this.decodeForbidden = decodeForbidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* A lookup value with optional aliases
|
* A lookup value with optional aliases
|
||||||
*
|
* <p>
|
||||||
* toString just gives the primary value,
|
* toString just gives the primary value,
|
||||||
* equals just compares against primary value
|
* equals just compares against primary value
|
||||||
* matches() also compares aliases
|
* matches() also compares aliases
|
||||||
@ -11,38 +11,31 @@ package btools.expressions;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
final class BExpressionLookupValue
|
final class BExpressionLookupValue {
|
||||||
{
|
|
||||||
String value;
|
String value;
|
||||||
ArrayList<String> aliases;
|
ArrayList<String> aliases;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString() {
|
||||||
{
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BExpressionLookupValue( String value )
|
public BExpressionLookupValue(String value) {
|
||||||
{
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAlias( String alias )
|
public void addAlias(String alias) {
|
||||||
{
|
|
||||||
if (aliases == null) aliases = new ArrayList<String>();
|
if (aliases == null) aliases = new ArrayList<String>();
|
||||||
aliases.add(alias);
|
aliases.add(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals( Object o )
|
public boolean equals(Object o) {
|
||||||
{
|
if (o instanceof String) {
|
||||||
if ( o instanceof String )
|
|
||||||
{
|
|
||||||
String v = (String) o;
|
String v = (String) o;
|
||||||
return value.equals(v);
|
return value.equals(v);
|
||||||
}
|
}
|
||||||
if ( o instanceof BExpressionLookupValue )
|
if (o instanceof BExpressionLookupValue) {
|
||||||
{
|
|
||||||
BExpressionLookupValue v = (BExpressionLookupValue) o;
|
BExpressionLookupValue v = (BExpressionLookupValue) o;
|
||||||
|
|
||||||
return value.equals(v.value);
|
return value.equals(v.value);
|
||||||
@ -50,13 +43,10 @@ final class BExpressionLookupValue
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches( String s )
|
public boolean matches(String s) {
|
||||||
{
|
|
||||||
if (value.equals(s)) return true;
|
if (value.equals(s)) return true;
|
||||||
if ( aliases != null )
|
if (aliases != null) {
|
||||||
{
|
for (String alias : aliases) {
|
||||||
for( String alias : aliases )
|
|
||||||
{
|
|
||||||
if (alias.equals(s)) return true;
|
if (alias.equals(s)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,8 +21,7 @@ import btools.util.BitCoderContext;
|
|||||||
import btools.util.Crc32;
|
import btools.util.Crc32;
|
||||||
|
|
||||||
|
|
||||||
public final class BExpressionMetaData
|
public final class BExpressionMetaData {
|
||||||
{
|
|
||||||
private static final String CONTEXT_TAG = "---context:";
|
private static final String CONTEXT_TAG = "---context:";
|
||||||
private static final String VERSION_TAG = "---lookupversion:";
|
private static final String VERSION_TAG = "---lookupversion:";
|
||||||
private static final String MINOR_VERSION_TAG = "---minorversion:";
|
private static final String MINOR_VERSION_TAG = "---minorversion:";
|
||||||
@ -33,37 +32,30 @@ public final class BExpressionMetaData
|
|||||||
|
|
||||||
private HashMap<String, BExpressionContext> listeners = new HashMap<String, BExpressionContext>();
|
private HashMap<String, BExpressionContext> listeners = new HashMap<String, BExpressionContext>();
|
||||||
|
|
||||||
public void registerListener( String context, BExpressionContext ctx )
|
public void registerListener(String context, BExpressionContext ctx) {
|
||||||
{
|
|
||||||
listeners.put(context, ctx);
|
listeners.put(context, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readMetaData( File lookupsFile )
|
public void readMetaData(File lookupsFile) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
BufferedReader br = new BufferedReader(new FileReader(lookupsFile));
|
BufferedReader br = new BufferedReader(new FileReader(lookupsFile));
|
||||||
|
|
||||||
BExpressionContext ctx = null;
|
BExpressionContext ctx = null;
|
||||||
|
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
String line = br.readLine();
|
String line = br.readLine();
|
||||||
if (line == null) break;
|
if (line == null) break;
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
if (line.length() == 0 || line.startsWith("#")) continue;
|
if (line.length() == 0 || line.startsWith("#")) continue;
|
||||||
if ( line.startsWith( CONTEXT_TAG ) )
|
if (line.startsWith(CONTEXT_TAG)) {
|
||||||
{
|
|
||||||
ctx = listeners.get(line.substring(CONTEXT_TAG.length()));
|
ctx = listeners.get(line.substring(CONTEXT_TAG.length()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( line.startsWith( VERSION_TAG ) )
|
if (line.startsWith(VERSION_TAG)) {
|
||||||
{
|
|
||||||
lookupVersion = Short.parseShort(line.substring(VERSION_TAG.length()));
|
lookupVersion = Short.parseShort(line.substring(VERSION_TAG.length()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( line.startsWith( MINOR_VERSION_TAG ) )
|
if (line.startsWith(MINOR_VERSION_TAG)) {
|
||||||
{
|
|
||||||
lookupMinorVersion = Short.parseShort(line.substring(MINOR_VERSION_TAG.length()));
|
lookupMinorVersion = Short.parseShort(line.substring(MINOR_VERSION_TAG.length()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -75,14 +67,11 @@ public final class BExpressionMetaData
|
|||||||
}
|
}
|
||||||
br.close();
|
br.close();
|
||||||
|
|
||||||
for( BExpressionContext c : listeners.values() )
|
for (BExpressionContext c : listeners.values()) {
|
||||||
{
|
|
||||||
c.finishMetaParsing();
|
c.finishMetaParsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch( Exception e )
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,27 +4,22 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
import btools.util.LruMapNode;
|
import btools.util.LruMapNode;
|
||||||
|
|
||||||
public final class CacheNode extends LruMapNode
|
public final class CacheNode extends LruMapNode {
|
||||||
{
|
|
||||||
byte[] ab;
|
byte[] ab;
|
||||||
float[] vars;
|
float[] vars;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode() {
|
||||||
{
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals( Object o )
|
public boolean equals(Object o) {
|
||||||
{
|
|
||||||
CacheNode n = (CacheNode) o;
|
CacheNode n = (CacheNode) o;
|
||||||
if ( hash != n.hash )
|
if (hash != n.hash) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( ab == null )
|
if (ab == null) {
|
||||||
{
|
|
||||||
return true; // hack: null = crc match only
|
return true; // hack: null = crc match only
|
||||||
}
|
}
|
||||||
return Arrays.equals(ab, n.ab);
|
return Arrays.equals(ab, n.ab);
|
||||||
|
|||||||
@ -3,12 +3,9 @@ package btools.expressions;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public final class ProfileComparator
|
public final class ProfileComparator {
|
||||||
{
|
public static void main(String[] args) {
|
||||||
public static void main( String[] args )
|
if (args.length != 4) {
|
||||||
{
|
|
||||||
if ( args.length != 4 )
|
|
||||||
{
|
|
||||||
System.out.println("usage: java ProfileComparator <lookup-file> <profile1> <profile2> <nsamples>");
|
System.out.println("usage: java ProfileComparator <lookup-file> <profile1> <profile2> <nsamples>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -22,8 +19,7 @@ public final class ProfileComparator
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testContext( File lookupFile, File profile1File, File profile2File, int nsamples, boolean nodeContext )
|
private static void testContext(File lookupFile, File profile1File, File profile2File, int nsamples, boolean nodeContext) {
|
||||||
{
|
|
||||||
// read lookup.dat + profiles
|
// read lookup.dat + profiles
|
||||||
BExpressionMetaData meta1 = new BExpressionMetaData();
|
BExpressionMetaData meta1 = new BExpressionMetaData();
|
||||||
BExpressionMetaData meta2 = new BExpressionMetaData();
|
BExpressionMetaData meta2 = new BExpressionMetaData();
|
||||||
@ -35,8 +31,7 @@ public final class ProfileComparator
|
|||||||
expctx2.parseFile(profile2File, "global");
|
expctx2.parseFile(profile2File, "global");
|
||||||
|
|
||||||
Random rnd = new Random();
|
Random rnd = new Random();
|
||||||
for( int i=0; i<nsamples; i++ )
|
for (int i = 0; i < nsamples; i++) {
|
||||||
{
|
|
||||||
int[] data = expctx1.generateRandomValues(rnd);
|
int[] data = expctx1.generateRandomValues(rnd);
|
||||||
expctx1.evaluate(data);
|
expctx1.evaluate(data);
|
||||||
expctx2.evaluate(data);
|
expctx2.evaluate(data);
|
||||||
|
|||||||
@ -4,22 +4,18 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
import btools.util.LruMapNode;
|
import btools.util.LruMapNode;
|
||||||
|
|
||||||
public final class VarWrapper extends LruMapNode
|
public final class VarWrapper extends LruMapNode {
|
||||||
{
|
|
||||||
float[] vars;
|
float[] vars;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode() {
|
||||||
{
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals( Object o )
|
public boolean equals(Object o) {
|
||||||
{
|
|
||||||
VarWrapper n = (VarWrapper) o;
|
VarWrapper n = (VarWrapper) o;
|
||||||
if ( hash != n.hash )
|
if (hash != n.hash) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Arrays.equals(vars, n.vars);
|
return Arrays.equals(vars, n.vars);
|
||||||
|
|||||||
@ -7,11 +7,9 @@ import java.net.URL;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class EncodeDecodeTest
|
public class EncodeDecodeTest {
|
||||||
{
|
|
||||||
@Test
|
@Test
|
||||||
public void encodeDecodeTest()
|
public void encodeDecodeTest() {
|
||||||
{
|
|
||||||
URL testpurl = this.getClass().getResource("/dummy.txt");
|
URL testpurl = this.getClass().getResource("/dummy.txt");
|
||||||
File workingDir = new File(testpurl.getFile()).getParentFile();
|
File workingDir = new File(testpurl.getFile()).getParentFile();
|
||||||
File profileDir = new File(workingDir, "/../../../../misc/profiles2");
|
File profileDir = new File(workingDir, "/../../../../misc/profiles2");
|
||||||
@ -38,10 +36,10 @@ public class EncodeDecodeTest
|
|||||||
|
|
||||||
// encode the tags into 64 bit description word
|
// encode the tags into 64 bit description word
|
||||||
int[] lookupData = expctxWay.createNewLookupData();
|
int[] lookupData = expctxWay.createNewLookupData();
|
||||||
for( String arg: tags )
|
for (String arg : tags) {
|
||||||
{
|
|
||||||
int idx = arg.indexOf('=');
|
int idx = arg.indexOf('=');
|
||||||
if ( idx < 0 ) throw new IllegalArgumentException( "bad argument (should be <tag>=<value>): " + arg );
|
if (idx < 0)
|
||||||
|
throw new IllegalArgumentException("bad argument (should be <tag>=<value>): " + arg);
|
||||||
String key = arg.substring(0, idx);
|
String key = arg.substring(0, idx);
|
||||||
String value = arg.substring(idx + 1);
|
String value = arg.substring(idx + 1);
|
||||||
|
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import java.io.OutputStream;
|
|||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
public class ConvertLidarTile
|
public class ConvertLidarTile {
|
||||||
{
|
|
||||||
public static int NROWS;
|
public static int NROWS;
|
||||||
public static int NCOLS;
|
public static int NCOLS;
|
||||||
|
|
||||||
@ -21,37 +20,28 @@ public class ConvertLidarTile
|
|||||||
|
|
||||||
static short[] imagePixels;
|
static short[] imagePixels;
|
||||||
|
|
||||||
private static void readHgtZip( String filename, int rowOffset, int colOffset ) throws Exception
|
private static void readHgtZip(String filename, int rowOffset, int colOffset) throws Exception {
|
||||||
{
|
|
||||||
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(filename)));
|
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(filename)));
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
ZipEntry ze = zis.getNextEntry();
|
ZipEntry ze = zis.getNextEntry();
|
||||||
if ( ze.getName().endsWith( ".hgt" ) )
|
if (ze.getName().endsWith(".hgt")) {
|
||||||
{
|
|
||||||
readHgtFromStream(zis, rowOffset, colOffset);
|
readHgtFromStream(zis, rowOffset, colOffset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
zis.close();
|
zis.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void readHgtFromStream(InputStream is, int rowOffset, int colOffset)
|
private static void readHgtFromStream(InputStream is, int rowOffset, int colOffset)
|
||||||
throws Exception
|
throws Exception {
|
||||||
{
|
|
||||||
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
|
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
|
||||||
for ( int ir = 0; ir < 1201; ir++ )
|
for (int ir = 0; ir < 1201; ir++) {
|
||||||
{
|
|
||||||
int row = rowOffset + ir;
|
int row = rowOffset + ir;
|
||||||
|
|
||||||
for ( int ic = 0; ic < 1201; ic++ )
|
for (int ic = 0; ic < 1201; ic++) {
|
||||||
{
|
|
||||||
int col = colOffset + ic;
|
int col = colOffset + ic;
|
||||||
|
|
||||||
int i1 = dis.read(); // msb first!
|
int i1 = dis.read(); // msb first!
|
||||||
@ -62,8 +52,7 @@ public class ConvertLidarTile
|
|||||||
|
|
||||||
short val = (short) ((i1 << 8) | i0);
|
short val = (short) ((i1 << 8) | i0);
|
||||||
|
|
||||||
if ( val == NODATA2 )
|
if (val == NODATA2) {
|
||||||
{
|
|
||||||
val = NODATA;
|
val = NODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,26 +62,21 @@ public class ConvertLidarTile
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void setPixel( int row, int col, short val )
|
private static void setPixel(int row, int col, short val) {
|
||||||
{
|
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
|
||||||
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
|
|
||||||
{
|
|
||||||
imagePixels[row * NCOLS + col] = val;
|
imagePixels[row * NCOLS + col] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static short getPixel( int row, int col )
|
private static short getPixel(int row, int col) {
|
||||||
{
|
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
|
||||||
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
|
|
||||||
{
|
|
||||||
return imagePixels[row * NCOLS + col];
|
return imagePixels[row * NCOLS + col];
|
||||||
}
|
}
|
||||||
return NODATA;
|
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;
|
int extraBorder = 0;
|
||||||
|
|
||||||
NROWS = 5 * 1200 + 1 + 2 * extraBorder;
|
NROWS = 5 * 1200 + 1 + 2 * extraBorder;
|
||||||
@ -101,33 +85,26 @@ public class ConvertLidarTile
|
|||||||
imagePixels = new short[NROWS * NCOLS]; // 650 MB !
|
imagePixels = new short[NROWS * NCOLS]; // 650 MB !
|
||||||
|
|
||||||
// prefill as NODATA
|
// prefill as NODATA
|
||||||
for ( int row = 0; row < NROWS; row++ )
|
for (int row = 0; row < NROWS; row++) {
|
||||||
{
|
for (int col = 0; col < NCOLS; col++) {
|
||||||
for ( int col = 0; col < NCOLS; col++ )
|
|
||||||
{
|
|
||||||
imagePixels[row * NCOLS + col] = NODATA;
|
imagePixels[row * NCOLS + col] = NODATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int latIdx = -1; latIdx <= 5; latIdx++ )
|
for (int latIdx = -1; latIdx <= 5; latIdx++) {
|
||||||
{
|
|
||||||
int latDegree = latDegreeStart + 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 lonDegree = lonDegreeStart + lonIdx;
|
||||||
int colOffset = extraBorder + lonIdx * 1200;
|
int colOffset = extraBorder + lonIdx * 1200;
|
||||||
|
|
||||||
String filename = inputDir + "/" + formatLat(latDegree) + formatLon(lonDegree) + ".zip";
|
String filename = inputDir + "/" + formatLat(latDegree) + formatLon(lonDegree) + ".zip";
|
||||||
File f = new File(filename);
|
File f = new File(filename);
|
||||||
if ( f.exists() && f.length() > 0 )
|
if (f.exists() && f.length() > 0) {
|
||||||
{
|
|
||||||
System.out.println("exist: " + filename);
|
System.out.println("exist: " + filename);
|
||||||
readHgtZip(filename, rowOffset, colOffset);
|
readHgtZip(filename, rowOffset, colOffset);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
System.out.println("none : " + filename);
|
System.out.println("none : " + filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,29 +138,24 @@ public class ConvertLidarTile
|
|||||||
throw new RuntimeException("length mismatch!");
|
throw new RuntimeException("length mismatch!");
|
||||||
|
|
||||||
// compare decoding result
|
// compare decoding result
|
||||||
for ( int row = 0; row < NROWS; row++ )
|
for (int row = 0; row < NROWS; row++) {
|
||||||
{
|
|
||||||
int colstep = halfCol5 ? 2 : 1;
|
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;
|
int idx = row * NCOLS + col;
|
||||||
short p2 = pix2[idx];
|
short p2 = pix2[idx];
|
||||||
if ( p2 != imagePixels[idx] )
|
if (p2 != imagePixels[idx]) {
|
||||||
{
|
|
||||||
throw new RuntimeException("content mismatch: p2=" + p2 + " p1=" + imagePixels[idx]);
|
throw new RuntimeException("content mismatch: p2=" + p2 + " p1=" + imagePixels[idx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatLon( int lon )
|
private static String formatLon(int lon) {
|
||||||
{
|
|
||||||
if (lon >= 180)
|
if (lon >= 180)
|
||||||
lon -= 180; // TODO: w180 oder E180 ?
|
lon -= 180; // TODO: w180 oder E180 ?
|
||||||
|
|
||||||
String s = "E";
|
String s = "E";
|
||||||
if ( lon < 0 )
|
if (lon < 0) {
|
||||||
{
|
|
||||||
lon = -lon;
|
lon = -lon;
|
||||||
s = "E";
|
s = "E";
|
||||||
}
|
}
|
||||||
@ -191,11 +163,9 @@ public class ConvertLidarTile
|
|||||||
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";
|
String s = "N";
|
||||||
if ( lat < 0 )
|
if (lat < 0) {
|
||||||
{
|
|
||||||
lat = -lat;
|
lat = -lat;
|
||||||
s = "S";
|
s = "S";
|
||||||
}
|
}
|
||||||
@ -203,8 +173,7 @@ public class ConvertLidarTile
|
|||||||
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 filename90 = args[0];
|
||||||
String filename30 = filename90.substring(0, filename90.length() - 3) + "bef";
|
String filename30 = filename90.substring(0, filename90.length() - 3) + "bef";
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,7 @@ package btools.mapcreator;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.zip.*;
|
import java.util.zip.*;
|
||||||
|
|
||||||
public class ConvertSrtmTile
|
public class ConvertSrtmTile {
|
||||||
{
|
|
||||||
public static int NROWS;
|
public static int NROWS;
|
||||||
public static int NCOLS;
|
public static int NCOLS;
|
||||||
|
|
||||||
@ -16,43 +15,32 @@ public class ConvertSrtmTile
|
|||||||
|
|
||||||
public static int[] diffs = new int[100];
|
public static int[] diffs = new int[100];
|
||||||
|
|
||||||
private static void readBilZip( String filename, int rowOffset, int colOffset, boolean halfCols ) throws Exception
|
private static void readBilZip(String filename, int rowOffset, int colOffset, boolean halfCols) throws Exception {
|
||||||
{
|
|
||||||
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(filename)));
|
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(filename)));
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
ZipEntry ze = zis.getNextEntry();
|
ZipEntry ze = zis.getNextEntry();
|
||||||
if ( ze.getName().endsWith( ".bil" ) )
|
if (ze.getName().endsWith(".bil")) {
|
||||||
{
|
|
||||||
readBilFromStream(zis, rowOffset, colOffset, halfCols);
|
readBilFromStream(zis, rowOffset, colOffset, halfCols);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
zis.close();
|
zis.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void readBilFromStream(InputStream is, int rowOffset, int colOffset, boolean halfCols)
|
private static void readBilFromStream(InputStream is, int rowOffset, int colOffset, boolean halfCols)
|
||||||
throws Exception
|
throws Exception {
|
||||||
{
|
|
||||||
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
|
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
|
||||||
for ( int ir = 0; ir < 3601; ir++ )
|
for (int ir = 0; ir < 3601; ir++) {
|
||||||
{
|
|
||||||
int row = rowOffset + ir;
|
int row = rowOffset + ir;
|
||||||
|
|
||||||
for ( int ic = 0; ic < 3601; ic++ )
|
for (int ic = 0; ic < 3601; ic++) {
|
||||||
{
|
|
||||||
int col = colOffset + ic;
|
int col = colOffset + ic;
|
||||||
|
|
||||||
if ( ( ic % 2 ) == 1 && halfCols )
|
if ((ic % 2) == 1 && halfCols) {
|
||||||
{
|
if (getPixel(row, col) == NODATA) {
|
||||||
if ( getPixel( row, col ) == NODATA )
|
|
||||||
{
|
|
||||||
setPixel(row, col, SKIPDATA);
|
setPixel(row, col, SKIPDATA);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -66,8 +54,7 @@ public class ConvertSrtmTile
|
|||||||
|
|
||||||
short val = (short) ((i1 << 8) | i0);
|
short val = (short) ((i1 << 8) | i0);
|
||||||
|
|
||||||
if ( val == NODATA2 )
|
if (val == NODATA2) {
|
||||||
{
|
|
||||||
val = NODATA;
|
val = NODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,26 +64,21 @@ public class ConvertSrtmTile
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void setPixel( int row, int col, short val )
|
private static void setPixel(int row, int col, short val) {
|
||||||
{
|
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
|
||||||
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
|
|
||||||
{
|
|
||||||
imagePixels[row * NCOLS + col] = val;
|
imagePixels[row * NCOLS + col] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static short getPixel( int row, int col )
|
private static short getPixel(int row, int col) {
|
||||||
{
|
if (row >= 0 && row < NROWS && col >= 0 && col < NCOLS) {
|
||||||
if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS )
|
|
||||||
{
|
|
||||||
return imagePixels[row * NCOLS + col];
|
return imagePixels[row * NCOLS + col];
|
||||||
}
|
}
|
||||||
return NODATA;
|
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 extraBorder = 10;
|
||||||
int datacells = 0;
|
int datacells = 0;
|
||||||
int mismatches = 0;
|
int mismatches = 0;
|
||||||
@ -107,34 +89,27 @@ public class ConvertSrtmTile
|
|||||||
imagePixels = new short[NROWS * NCOLS]; // 650 MB !
|
imagePixels = new short[NROWS * NCOLS]; // 650 MB !
|
||||||
|
|
||||||
// prefill as NODATA
|
// prefill as NODATA
|
||||||
for ( int row = 0; row < NROWS; row++ )
|
for (int row = 0; row < NROWS; row++) {
|
||||||
{
|
for (int col = 0; col < NCOLS; col++) {
|
||||||
for ( int col = 0; col < NCOLS; col++ )
|
|
||||||
{
|
|
||||||
imagePixels[row * NCOLS + col] = NODATA;
|
imagePixels[row * NCOLS + col] = NODATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int latIdx = -1; latIdx <= 5; latIdx++ )
|
for (int latIdx = -1; latIdx <= 5; latIdx++) {
|
||||||
{
|
|
||||||
int latDegree = latDegreeStart + 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 lonDegree = lonDegreeStart + lonIdx;
|
||||||
int colOffset = extraBorder + lonIdx * 3600;
|
int colOffset = extraBorder + lonIdx * 3600;
|
||||||
|
|
||||||
String filename = inputDir + "/" + formatLat(latDegree) + "_" + formatLon(lonDegree) + "_1arc_v3_bil.zip";
|
String filename = inputDir + "/" + formatLat(latDegree) + "_" + formatLon(lonDegree) + "_1arc_v3_bil.zip";
|
||||||
File f = new File(filename);
|
File f = new File(filename);
|
||||||
if ( f.exists() && f.length() > 0 )
|
if (f.exists() && f.length() > 0) {
|
||||||
{
|
|
||||||
System.out.println("exist: " + filename);
|
System.out.println("exist: " + filename);
|
||||||
boolean halfCol = latDegree >= 50 || latDegree < -50;
|
boolean halfCol = latDegree >= 50 || latDegree < -50;
|
||||||
readBilZip(filename, rowOffset, colOffset, halfCol);
|
readBilZip(filename, rowOffset, colOffset, halfCol);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
System.out.println("none : " + filename);
|
System.out.println("none : " + filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,60 +117,46 @@ public class ConvertSrtmTile
|
|||||||
|
|
||||||
boolean halfCol5 = latDegreeStart >= 50 || latDegreeStart < -50;
|
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
|
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
|
int ccol = 3 * col90 + extraBorder; // center col of 3x3
|
||||||
|
|
||||||
// evaluate 3x3 area
|
// 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];
|
short v90 = raster90.eval_array[row90 * 6001 + col90];
|
||||||
|
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
int nodatas = 0;
|
int nodatas = 0;
|
||||||
int datas = 0;
|
int datas = 0;
|
||||||
int colstep = halfCol5 ? 2 : 1;
|
int colstep = halfCol5 ? 2 : 1;
|
||||||
for ( int row = crow - 1; row <= crow + 1; row++ )
|
for (int row = crow - 1; row <= crow + 1; row++) {
|
||||||
{
|
for (int col = ccol - colstep; col <= ccol + colstep; col += colstep) {
|
||||||
for ( int col = ccol - colstep; col <= ccol + colstep; col += colstep )
|
|
||||||
{
|
|
||||||
short v30 = imagePixels[row * NCOLS + col];
|
short v30 = imagePixels[row * NCOLS + col];
|
||||||
if ( v30 == NODATA )
|
if (v30 == NODATA) {
|
||||||
{
|
|
||||||
nodatas++;
|
nodatas++;
|
||||||
}
|
} else if (v30 != SKIPDATA) {
|
||||||
else if ( v30 != SKIPDATA )
|
|
||||||
{
|
|
||||||
sum += v30;
|
sum += v30;
|
||||||
datas++;
|
datas++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean doReplace = nodatas > 0 || v90 == NODATA || datas < 7;
|
boolean doReplace = nodatas > 0 || v90 == NODATA || datas < 7;
|
||||||
if ( !doReplace )
|
if (!doReplace) {
|
||||||
{
|
|
||||||
datacells++;
|
datacells++;
|
||||||
int diff = sum - datas * v90;
|
int diff = sum - datas * v90;
|
||||||
if ( diff < -4 || diff > 4 )
|
if (diff < -4 || diff > 4) {
|
||||||
{
|
|
||||||
doReplace = true;
|
doReplace = true;
|
||||||
mismatches++;
|
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]++;
|
diffs[diff + 50]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( doReplace )
|
if (doReplace) {
|
||||||
{
|
for (int row = crow - 1; row <= crow + 1; row++) {
|
||||||
for ( int row = crow - 1; row <= crow + 1; row++ )
|
for (int col = ccol - colstep; col <= ccol + colstep; col += colstep) {
|
||||||
{
|
|
||||||
for ( int col = ccol - colstep; col <= ccol + colstep; col += colstep )
|
|
||||||
{
|
|
||||||
imagePixels[row * NCOLS + col] = v90;
|
imagePixels[row * NCOLS + col] = v90;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,23 +190,18 @@ public class ConvertSrtmTile
|
|||||||
throw new RuntimeException("length mismatch!");
|
throw new RuntimeException("length mismatch!");
|
||||||
|
|
||||||
// compare decoding result
|
// compare decoding result
|
||||||
for ( int row = 0; row < NROWS; row++ )
|
for (int row = 0; row < NROWS; row++) {
|
||||||
{
|
|
||||||
int colstep = halfCol5 ? 2 : 1;
|
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;
|
int idx = row * NCOLS + col;
|
||||||
if ( imagePixels[idx] == SKIPDATA )
|
if (imagePixels[idx] == SKIPDATA) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
short p2 = pix2[idx];
|
short p2 = pix2[idx];
|
||||||
if ( p2 > SKIPDATA )
|
if (p2 > SKIPDATA) {
|
||||||
{
|
|
||||||
p2 /= 2;
|
p2 /= 2;
|
||||||
}
|
}
|
||||||
if ( p2 != imagePixels[idx] )
|
if (p2 != imagePixels[idx]) {
|
||||||
{
|
|
||||||
throw new RuntimeException("content mismatch!");
|
throw new RuntimeException("content mismatch!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,16 +216,13 @@ btools.util.MixCoderDataOutputStream.stats();
|
|||||||
// 39828330 &lon=3115280&layer=OpenStreetMap
|
// 39828330 &lon=3115280&layer=OpenStreetMap
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void test( SrtmRaster raster )
|
private static void test(SrtmRaster raster) {
|
||||||
{
|
|
||||||
int lat0 = 39828330;
|
int lat0 = 39828330;
|
||||||
int lon0 = 3115280;
|
int lon0 = 3115280;
|
||||||
|
|
||||||
for ( int iy = -9; iy <= 9; iy++ )
|
for (int iy = -9; iy <= 9; iy++) {
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
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 lat = lat0 + 90000000 - 100 * iy;
|
||||||
int lon = lon0 + 180000000 + 100 * ix;
|
int lon = lon0 + 180000000 + 100 * ix;
|
||||||
int ival = (int) (raster.getElevation(lon, lat) / 4.);
|
int ival = (int) (raster.getElevation(lon, lat) / 4.);
|
||||||
@ -281,14 +234,12 @@ btools.util.MixCoderDataOutputStream.stats();
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatLon( int lon )
|
private static String formatLon(int lon) {
|
||||||
{
|
|
||||||
if (lon >= 180)
|
if (lon >= 180)
|
||||||
lon -= 180; // TODO: w180 oder E180 ?
|
lon -= 180; // TODO: w180 oder E180 ?
|
||||||
|
|
||||||
String s = "e";
|
String s = "e";
|
||||||
if ( lon < 0 )
|
if (lon < 0) {
|
||||||
{
|
|
||||||
lon = -lon;
|
lon = -lon;
|
||||||
s = "w";
|
s = "w";
|
||||||
}
|
}
|
||||||
@ -296,11 +247,9 @@ btools.util.MixCoderDataOutputStream.stats();
|
|||||||
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";
|
String s = "n";
|
||||||
if ( lat < 0 )
|
if (lat < 0) {
|
||||||
{
|
|
||||||
lat = -lat;
|
lat = -lat;
|
||||||
s = "s";
|
s = "s";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,32 +4,26 @@ import java.io.BufferedReader;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
|
|
||||||
public class ConvertUrlList
|
public class ConvertUrlList {
|
||||||
{
|
|
||||||
public static final short NODATA = -32767;
|
public static final short NODATA = -32767;
|
||||||
|
|
||||||
public static void main( String[] args ) throws Exception
|
public static void main(String[] args) throws Exception {
|
||||||
{
|
|
||||||
BufferedReader br = new BufferedReader(new FileReader(args[0]));
|
BufferedReader br = new BufferedReader(new FileReader(args[0]));
|
||||||
|
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
String line = br.readLine();
|
String line = br.readLine();
|
||||||
if ( line == null )
|
if (line == null) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int idx1 = line.indexOf("srtm_");
|
int idx1 = line.indexOf("srtm_");
|
||||||
if ( idx1 < 0 )
|
if (idx1 < 0) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String filename90 = line.substring(idx1);
|
String filename90 = line.substring(idx1);
|
||||||
String filename30 = filename90.substring(0, filename90.length() - 3) + "bef";
|
String filename30 = filename90.substring(0, filename90.length() - 3) + "bef";
|
||||||
|
|
||||||
if ( new File( filename30 ).exists() )
|
if (new File(filename30).exists()) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,8 +39,7 @@ public class ConvertUrlList
|
|||||||
SrtmRaster raster90 = null;
|
SrtmRaster raster90 = null;
|
||||||
|
|
||||||
File file90 = new File(new File(args[1]), filename90);
|
File file90 = new File(new File(args[1]), filename90);
|
||||||
if ( file90.exists() )
|
if (file90.exists()) {
|
||||||
{
|
|
||||||
System.out.println("reading " + file90);
|
System.out.println("reading " + file90);
|
||||||
raster90 = new SrtmData(file90).getRaster();
|
raster90 = new SrtmData(file90).getRaster();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,34 +9,28 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import btools.util.CheapRuler;
|
import btools.util.CheapRuler;
|
||||||
|
|
||||||
public class DPFilter
|
public class DPFilter {
|
||||||
{
|
|
||||||
private static double dp_sql_threshold = 0.4 * 0.4;
|
private static double dp_sql_threshold = 0.4 * 0.4;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for each node (except first+last), eventually set the DP_SURVIVOR_BIT
|
* 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 first = 0;
|
||||||
int last = nodes.size() - 1;
|
int last = nodes.size() - 1;
|
||||||
while( first < last && (nodes.get(first+1).bits & OsmNodeP.DP_SURVIVOR_BIT) != 0 )
|
while (first < last && (nodes.get(first + 1).bits & OsmNodeP.DP_SURVIVOR_BIT) != 0) {
|
||||||
{
|
|
||||||
first++;
|
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--;
|
last--;
|
||||||
}
|
}
|
||||||
if ( last - first > 1 )
|
if (last - first > 1) {
|
||||||
{
|
|
||||||
doDPFilter(nodes, first, last);
|
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.;
|
double maxSqDist = -1.;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
OsmNodeP p1 = nodes.get(first);
|
OsmNodeP p1 = nodes.get(first);
|
||||||
@ -48,36 +42,29 @@ public class DPFilter
|
|||||||
double dx = (p2.ilon - p1.ilon) * dlon2m;
|
double dx = (p2.ilon - p1.ilon) * dlon2m;
|
||||||
double dy = (p2.ilat - p1.ilat) * dlat2m;
|
double dy = (p2.ilat - p1.ilat) * dlat2m;
|
||||||
double d2 = dx * dx + dy * dy;
|
double d2 = dx * dx + dy * dy;
|
||||||
for ( int i = first + 1; i < last; i++ )
|
for (int i = first + 1; i < last; i++) {
|
||||||
{
|
|
||||||
OsmNodeP p = nodes.get(i);
|
OsmNodeP p = nodes.get(i);
|
||||||
double t = 0.;
|
double t = 0.;
|
||||||
if ( d2 != 0f )
|
if (d2 != 0f) {
|
||||||
{
|
|
||||||
t = ((p.ilon - p1.ilon) * dlon2m * dx + (p.ilat - p1.ilat) * dlat2m * dy) / d2;
|
t = ((p.ilon - p1.ilon) * dlon2m * dx + (p.ilat - p1.ilat) * dlat2m * dy) / d2;
|
||||||
t = t > 1. ? 1. : (t < 0. ? 0. : t);
|
t = t > 1. ? 1. : (t < 0. ? 0. : t);
|
||||||
}
|
}
|
||||||
double dx2 = (p.ilon - (p1.ilon + t * (p2.ilon - p1.ilon))) * dlon2m;
|
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 dy2 = (p.ilat - (p1.ilat + t * (p2.ilat - p1.ilat))) * dlat2m;
|
||||||
double sqDist = dx2 * dx2 + dy2 * dy2;
|
double sqDist = dx2 * dx2 + dy2 * dy2;
|
||||||
if ( sqDist > maxSqDist )
|
if (sqDist > maxSqDist) {
|
||||||
{
|
|
||||||
index = i;
|
index = i;
|
||||||
maxSqDist = sqDist;
|
maxSqDist = sqDist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( index >= 0 )
|
if (index >= 0) {
|
||||||
{
|
if (index - first > 1) {
|
||||||
if ( index - first > 1 )
|
|
||||||
{
|
|
||||||
doDPFilter(nodes, first, index);
|
doDPFilter(nodes, first, index);
|
||||||
}
|
}
|
||||||
if ( maxSqDist >= dp_sql_threshold )
|
if (maxSqDist >= dp_sql_threshold) {
|
||||||
{
|
|
||||||
nodes.get(index).bits |= OsmNodeP.DP_SURVIVOR_BIT;
|
nodes.get(index).bits |= OsmNodeP.DP_SURVIVOR_BIT;
|
||||||
}
|
}
|
||||||
if ( last - index > 1 )
|
if (last - index > 1) {
|
||||||
{
|
|
||||||
doDPFilter(nodes, index, last);
|
doDPFilter(nodes, index, last);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,36 +17,30 @@ import java.util.HashMap;
|
|||||||
|
|
||||||
import btools.util.DiffCoderDataOutputStream;
|
import btools.util.DiffCoderDataOutputStream;
|
||||||
|
|
||||||
public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener
|
public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener {
|
||||||
{
|
|
||||||
private DiffCoderDataOutputStream[] tileOutStreams;
|
private DiffCoderDataOutputStream[] tileOutStreams;
|
||||||
protected File outTileDir;
|
protected File outTileDir;
|
||||||
|
|
||||||
protected HashMap<String, String> tags;
|
protected HashMap<String, String> tags;
|
||||||
|
|
||||||
public void putTag( String key, String value )
|
public void putTag(String key, String value) {
|
||||||
{
|
|
||||||
if (tags == null) tags = new HashMap<String, String>();
|
if (tags == null) tags = new HashMap<String, String>();
|
||||||
tags.put(key, value);
|
tags.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTag( String key )
|
public String getTag(String key) {
|
||||||
{
|
|
||||||
return tags == null ? null : tags.get(key);
|
return tags == null ? null : tags.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap<String,String> getTagsOrNull()
|
public HashMap<String, String> getTagsOrNull() {
|
||||||
{
|
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTags( HashMap<String,String> tags )
|
public void setTags(HashMap<String, String> tags) {
|
||||||
{
|
|
||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static long readId( DataInputStream is) throws IOException
|
protected static long readId(DataInputStream is) throws IOException {
|
||||||
{
|
|
||||||
int offset = is.readByte();
|
int offset = is.readByte();
|
||||||
if (offset == 32) return -1;
|
if (offset == 32) return -1;
|
||||||
long i = is.readInt();
|
long i = is.readInt();
|
||||||
@ -54,10 +48,8 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
|
|||||||
return i | offset;
|
return i | offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void writeId( DataOutputStream o, long id ) throws IOException
|
protected static void writeId(DataOutputStream o, long id) throws IOException {
|
||||||
{
|
if (id == -1) {
|
||||||
if ( id == -1 )
|
|
||||||
{
|
|
||||||
o.writeByte(32);
|
o.writeByte(32);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -68,20 +60,16 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static File[] sortBySizeAsc( File[] files )
|
protected static File[] sortBySizeAsc(File[] files) {
|
||||||
{
|
|
||||||
int n = files.length;
|
int n = files.length;
|
||||||
long[] sizes = new long[n];
|
long[] sizes = new long[n];
|
||||||
File[] sorted = new File[n];
|
File[] sorted = new File[n];
|
||||||
for (int i = 0; i < n; i++) sizes[i] = files[i].length();
|
for (int i = 0; i < n; i++) sizes[i] = files[i].length();
|
||||||
for(int nf=0; nf<n; nf++)
|
for (int nf = 0; nf < n; nf++) {
|
||||||
{
|
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
long min = -1;
|
long min = -1;
|
||||||
for( int i=0; i<n; i++ )
|
for (int i = 0; i < n; i++) {
|
||||||
{
|
if (sizes[i] != -1 && (idx == -1 || sizes[i] < min)) {
|
||||||
if ( sizes[i] != -1 && ( idx == -1 || sizes[i] < min ) )
|
|
||||||
{
|
|
||||||
min = sizes[i];
|
min = sizes[i];
|
||||||
idx = i;
|
idx = i;
|
||||||
}
|
}
|
||||||
@ -92,50 +80,40 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
|
|||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File fileFromTemplate( File template, File dir, String suffix )
|
protected File fileFromTemplate(File template, File dir, String suffix) {
|
||||||
{
|
|
||||||
String filename = template.getName();
|
String filename = template.getName();
|
||||||
filename = filename.substring(0, filename.length() - 3) + suffix;
|
filename = filename.substring(0, filename.length() - 3) + suffix;
|
||||||
return new File(dir, filename);
|
return new File(dir, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DataInputStream createInStream( File inFile ) throws IOException
|
protected DataInputStream createInStream(File inFile) throws IOException {
|
||||||
{
|
|
||||||
return new DataInputStream(new BufferedInputStream(new FileInputStream(inFile)));
|
return new DataInputStream(new BufferedInputStream(new FileInputStream(inFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DiffCoderDataOutputStream createOutStream( File outFile ) throws IOException
|
protected DiffCoderDataOutputStream createOutStream(File outFile) throws IOException {
|
||||||
{
|
|
||||||
return new DiffCoderDataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
|
return new DiffCoderDataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DiffCoderDataOutputStream getOutStreamForTile( int tileIndex ) throws Exception
|
protected DiffCoderDataOutputStream getOutStreamForTile(int tileIndex) throws Exception {
|
||||||
{
|
if (tileOutStreams == null) {
|
||||||
if ( tileOutStreams == null )
|
|
||||||
{
|
|
||||||
tileOutStreams = new DiffCoderDataOutputStream[64];
|
tileOutStreams = new DiffCoderDataOutputStream[64];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tileOutStreams[tileIndex] == null )
|
if (tileOutStreams[tileIndex] == null) {
|
||||||
{
|
|
||||||
tileOutStreams[tileIndex] = createOutStream(new File(outTileDir, getNameForTile(tileIndex)));
|
tileOutStreams[tileIndex] = createOutStream(new File(outTileDir, getNameForTile(tileIndex)));
|
||||||
}
|
}
|
||||||
return tileOutStreams[tileIndex];
|
return tileOutStreams[tileIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getNameForTile( int tileIndex )
|
protected String getNameForTile(int tileIndex) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("getNameForTile not implemented");
|
throw new IllegalArgumentException("getNameForTile not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void closeTileOutStreams() throws Exception
|
protected void closeTileOutStreams() throws Exception {
|
||||||
{
|
if (tileOutStreams == null) {
|
||||||
if ( tileOutStreams == null )
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for( int tileIndex=0; tileIndex<tileOutStreams.length; tileIndex++ )
|
for (int tileIndex = 0; tileIndex < tileOutStreams.length; tileIndex++) {
|
||||||
{
|
|
||||||
if (tileOutStreams[tileIndex] != null) tileOutStreams[tileIndex].close();
|
if (tileOutStreams[tileIndex] != null) tileOutStreams[tileIndex].close();
|
||||||
tileOutStreams[tileIndex] = null;
|
tileOutStreams[tileIndex] = null;
|
||||||
}
|
}
|
||||||
@ -145,27 +123,36 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
|
|||||||
// interface dummys
|
// interface dummys
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nodeFileStart( File nodefile ) throws Exception {}
|
public void nodeFileStart(File nodefile) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData n ) throws Exception {}
|
public void nextNode(NodeData n) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nodeFileEnd( File nodefile ) throws Exception {}
|
public void nodeFileEnd(File nodefile) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean wayFileStart( File wayfile ) throws Exception { return true; }
|
public boolean wayFileStart(File wayfile) throws Exception {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextWay( WayData data ) throws Exception {}
|
public void nextWay(WayData data) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void wayFileEnd( File wayfile ) throws Exception {}
|
public void wayFileEnd(File wayfile) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextRelation( RelationData data ) throws Exception {}
|
public void nextRelation(RelationData data) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@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 {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,60 +4,51 @@ import java.io.File;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeCutter does 1 step in map-processing:
|
* NodeCutter does 1 step in map-processing:
|
||||||
*
|
* <p>
|
||||||
* - cuts the 45*30 node tiles into 5*5 pieces
|
* - cuts the 45*30 node tiles into 5*5 pieces
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class NodeCutter extends MapCreatorBase
|
public class NodeCutter extends MapCreatorBase {
|
||||||
{
|
|
||||||
private int lonoffset;
|
private int lonoffset;
|
||||||
private int latoffset;
|
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");
|
System.out.println("*** NodeCutter: Cut big node-tiles into 5x5 tiles");
|
||||||
if (args.length != 2)
|
if (args.length != 2) {
|
||||||
{
|
|
||||||
System.out.println("usage: java NodeCutter <node-tiles-in> <node-tiles-out>");
|
System.out.println("usage: java NodeCutter <node-tiles-in> <node-tiles-out>");
|
||||||
return;
|
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;
|
this.outTileDir = nodeTilesOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process( File nodeTilesIn, File nodeTilesOut ) throws Exception
|
public void process(File nodeTilesIn, File nodeTilesOut) throws Exception {
|
||||||
{
|
|
||||||
init(nodeTilesOut);
|
init(nodeTilesOut);
|
||||||
|
|
||||||
new NodeIterator(this, true).processDir(nodeTilesIn, ".tlf");
|
new NodeIterator(this, true).processDir(nodeTilesIn, ".tlf");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nodeFileStart( File nodefile ) throws Exception
|
public void nodeFileStart(File nodefile) throws Exception {
|
||||||
{
|
|
||||||
lonoffset = -1;
|
lonoffset = -1;
|
||||||
latoffset = -1;
|
latoffset = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData n ) throws Exception
|
public void nextNode(NodeData n) throws Exception {
|
||||||
{
|
|
||||||
n.writeTo(getOutStreamForTile(getTileIndex(n.ilon, n.ilat)));
|
n.writeTo(getOutStreamForTile(getTileIndex(n.ilon, n.ilat)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nodeFileEnd( File nodeFile ) throws Exception
|
public void nodeFileEnd(File nodeFile) throws Exception {
|
||||||
{
|
|
||||||
closeTileOutStreams();
|
closeTileOutStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTileIndex( int ilon, int ilat )
|
private int getTileIndex(int ilon, int ilat) {
|
||||||
{
|
|
||||||
int lonoff = (ilon / 45000000) * 45;
|
int lonoff = (ilon / 45000000) * 45;
|
||||||
int latoff = (ilat / 30000000) * 30;
|
int latoff = (ilat / 30000000) * 30;
|
||||||
if (lonoffset == -1) lonoffset = lonoff;
|
if (lonoffset == -1) lonoffset = lonoff;
|
||||||
@ -67,13 +58,13 @@ public class NodeCutter extends MapCreatorBase
|
|||||||
|
|
||||||
int lon = (ilon / 5000000) % 9;
|
int lon = (ilon / 5000000) % 9;
|
||||||
int lat = (ilat / 5000000) % 6;
|
int lat = (ilat / 5000000) % 6;
|
||||||
if ( lon < 0 || lon > 8 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
|
if (lon < 0 || lon > 8 || lat < 0 || lat > 5)
|
||||||
|
throw new IllegalArgumentException("illegal pos: " + ilon + "," + ilat);
|
||||||
return lon * 6 + lat;
|
return lon * 6 + lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected String getNameForTile( int tileIndex )
|
protected String getNameForTile(int tileIndex) {
|
||||||
{
|
|
||||||
int lon = (tileIndex / 6) * 5 + lonoffset - 180;
|
int lon = (tileIndex / 6) * 5 + lonoffset - 180;
|
||||||
int lat = (tileIndex % 6) * 5 + latoffset - 90;
|
int lat = (tileIndex % 6) * 5 + latoffset - 90;
|
||||||
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
||||||
|
|||||||
@ -8,39 +8,42 @@ import btools.util.DiffCoderDataOutputStream;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class NodeData extends MapCreatorBase
|
public class NodeData extends MapCreatorBase {
|
||||||
{
|
|
||||||
public long nid;
|
public long nid;
|
||||||
public int ilon;
|
public int ilon;
|
||||||
public int ilat;
|
public int ilat;
|
||||||
public byte[] description;
|
public byte[] description;
|
||||||
public short selev = Short.MIN_VALUE;
|
public short selev = Short.MIN_VALUE;
|
||||||
|
|
||||||
public NodeData( long id, double lon, double lat )
|
public NodeData(long id, double lon, double lat) {
|
||||||
{
|
|
||||||
nid = id;
|
nid = id;
|
||||||
ilat = (int) ((lat + 90.) * 1000000. + 0.5);
|
ilat = (int) ((lat + 90.) * 1000000. + 0.5);
|
||||||
ilon = (int) ((lon + 180.) * 1000000. + 0.5);
|
ilon = (int) ((lon + 180.) * 1000000. + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeData( DiffCoderDataInputStream dis ) throws Exception
|
public NodeData(DiffCoderDataInputStream dis) throws Exception {
|
||||||
{
|
|
||||||
nid = dis.readDiffed(0);
|
nid = dis.readDiffed(0);
|
||||||
ilon = (int) dis.readDiffed(1);
|
ilon = (int) dis.readDiffed(1);
|
||||||
ilat = (int) dis.readDiffed(2);
|
ilat = (int) dis.readDiffed(2);
|
||||||
int mode = dis.readByte();
|
int mode = dis.readByte();
|
||||||
if ( ( mode & 1 ) != 0 ) { int dlen = dis.readShort(); description = new byte[dlen]; dis.readFully( description ); }
|
if ((mode & 1) != 0) {
|
||||||
|
int dlen = dis.readShort();
|
||||||
|
description = new byte[dlen];
|
||||||
|
dis.readFully(description);
|
||||||
|
}
|
||||||
if ((mode & 2) != 0) selev = dis.readShort();
|
if ((mode & 2) != 0) selev = dis.readShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo( DiffCoderDataOutputStream dos ) throws Exception
|
public void writeTo(DiffCoderDataOutputStream dos) throws Exception {
|
||||||
{
|
|
||||||
dos.writeDiffed(nid, 0);
|
dos.writeDiffed(nid, 0);
|
||||||
dos.writeDiffed(ilon, 1);
|
dos.writeDiffed(ilon, 1);
|
||||||
dos.writeDiffed(ilat, 2);
|
dos.writeDiffed(ilat, 2);
|
||||||
int mode = (description == null ? 0 : 1) | (selev == Short.MIN_VALUE ? 0 : 2);
|
int mode = (description == null ? 0 : 1) | (selev == Short.MIN_VALUE ? 0 : 2);
|
||||||
dos.writeByte((byte) mode);
|
dos.writeByte((byte) mode);
|
||||||
if ( ( mode & 1 ) != 0 ) { dos.writeShort( description.length ); dos.write( description ); }
|
if ((mode & 1) != 0) {
|
||||||
|
dos.writeShort(description.length);
|
||||||
|
dos.write(description);
|
||||||
|
}
|
||||||
if ((mode & 2) != 0) dos.writeShort(selev);
|
if ((mode & 2) != 0) dos.writeShort(selev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,22 +10,19 @@ import btools.util.TinyDenseLongMap;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeFilter does 1 step in map-processing:
|
* NodeFilter does 1 step in map-processing:
|
||||||
*
|
* <p>
|
||||||
* - filters out unused nodes according to the way file
|
* - filters out unused nodes according to the way file
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class NodeFilter extends MapCreatorBase
|
public class NodeFilter extends MapCreatorBase {
|
||||||
{
|
|
||||||
private DiffCoderDataOutputStream nodesOutStream;
|
private DiffCoderDataOutputStream nodesOutStream;
|
||||||
private File nodeTilesOut;
|
private File nodeTilesOut;
|
||||||
protected DenseLongMap nodebitmap;
|
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");
|
System.out.println("*** NodeFilter: Filter way related nodes");
|
||||||
if (args.length != 3)
|
if (args.length != 3) {
|
||||||
{
|
|
||||||
System.out.println("usage: java NodeFilter <node-tiles-in> <way-file-in> <node-tiles-out>");
|
System.out.println("usage: java NodeFilter <node-tiles-in> <way-file-in> <node-tiles-out>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -33,13 +30,11 @@ public class NodeFilter extends MapCreatorBase
|
|||||||
new NodeFilter().process(new File(args[0]), new File(args[1]), new File(args[2]));
|
new NodeFilter().process(new File(args[0]), new File(args[1]), new File(args[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() throws Exception
|
public void init() throws Exception {
|
||||||
{
|
|
||||||
nodebitmap = Boolean.getBoolean("useDenseMaps") ? new DenseLongMap(512) : new TinyDenseLongMap();
|
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();
|
init();
|
||||||
|
|
||||||
this.nodeTilesOut = nodeTilesOut;
|
this.nodeTilesOut = nodeTilesOut;
|
||||||
@ -52,41 +47,34 @@ public class NodeFilter extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextWay( WayData data ) throws Exception
|
public void nextWay(WayData data) throws Exception {
|
||||||
{
|
|
||||||
int nnodes = data.nodes.size();
|
int nnodes = data.nodes.size();
|
||||||
for (int i=0; i<nnodes; i++ )
|
for (int i = 0; i < nnodes; i++) {
|
||||||
{
|
|
||||||
nodebitmap.put(data.nodes.get(i), 0);
|
nodebitmap.put(data.nodes.get(i), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nodeFileStart( File nodefile ) throws Exception
|
public void nodeFileStart(File nodefile) throws Exception {
|
||||||
{
|
|
||||||
String filename = nodefile.getName();
|
String filename = nodefile.getName();
|
||||||
File outfile = new File(nodeTilesOut, filename);
|
File outfile = new File(nodeTilesOut, filename);
|
||||||
nodesOutStream = new DiffCoderDataOutputStream(new BufferedOutputStream(new FileOutputStream(outfile)));
|
nodesOutStream = new DiffCoderDataOutputStream(new BufferedOutputStream(new FileOutputStream(outfile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData n ) throws Exception
|
public void nextNode(NodeData n) throws Exception {
|
||||||
{
|
if (isRelevant(n)) {
|
||||||
if ( isRelevant( n ) )
|
|
||||||
{
|
|
||||||
n.writeTo(nodesOutStream);
|
n.writeTo(nodesOutStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRelevant( NodeData n )
|
public boolean isRelevant(NodeData n) {
|
||||||
{
|
|
||||||
// check if node passes bitmap
|
// 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
|
@Override
|
||||||
public void nodeFileEnd( File nodeFile ) throws Exception
|
public void nodeFileEnd(File nodeFile) throws Exception {
|
||||||
{
|
|
||||||
nodesOutStream.close();
|
nodesOutStream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,58 +13,46 @@ import btools.util.DiffCoderDataInputStream;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class NodeIterator extends MapCreatorBase
|
public class NodeIterator extends MapCreatorBase {
|
||||||
{
|
|
||||||
private NodeListener listener;
|
private NodeListener listener;
|
||||||
private boolean delete;
|
private boolean delete;
|
||||||
|
|
||||||
public NodeIterator( NodeListener nodeListener, boolean deleteAfterReading )
|
public NodeIterator(NodeListener nodeListener, boolean deleteAfterReading) {
|
||||||
{
|
|
||||||
listener = nodeListener;
|
listener = nodeListener;
|
||||||
delete = deleteAfterReading;
|
delete = deleteAfterReading;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processDir( File indir, String inSuffix ) throws Exception
|
public void processDir(File indir, String inSuffix) throws Exception {
|
||||||
{
|
if (!indir.isDirectory()) {
|
||||||
if ( !indir.isDirectory() )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("not a directory: " + indir);
|
throw new IllegalArgumentException("not a directory: " + indir);
|
||||||
}
|
}
|
||||||
|
|
||||||
File[] af = sortBySizeAsc(indir.listFiles());
|
File[] af = sortBySizeAsc(indir.listFiles());
|
||||||
for( int i=0; i<af.length; i++ )
|
for (int i = 0; i < af.length; i++) {
|
||||||
{
|
|
||||||
File nodefile = af[i];
|
File nodefile = af[i];
|
||||||
if ( nodefile.getName().endsWith( inSuffix ) )
|
if (nodefile.getName().endsWith(inSuffix)) {
|
||||||
{
|
|
||||||
processFile(nodefile);
|
processFile(nodefile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void processFile(File nodefile) throws Exception
|
public void processFile(File nodefile) throws Exception {
|
||||||
{
|
|
||||||
System.out.println("*** NodeIterator reading: " + nodefile);
|
System.out.println("*** NodeIterator reading: " + nodefile);
|
||||||
|
|
||||||
listener.nodeFileStart(nodefile);
|
listener.nodeFileStart(nodefile);
|
||||||
|
|
||||||
DiffCoderDataInputStream di = new DiffCoderDataInputStream(new BufferedInputStream(new FileInputStream(nodefile)));
|
DiffCoderDataInputStream di = new DiffCoderDataInputStream(new BufferedInputStream(new FileInputStream(nodefile)));
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
NodeData n = new NodeData(di);
|
NodeData n = new NodeData(di);
|
||||||
listener.nextNode(n);
|
listener.nextNode(n);
|
||||||
}
|
}
|
||||||
}
|
} catch (EOFException eof) {
|
||||||
catch( EOFException eof )
|
|
||||||
{
|
|
||||||
di.close();
|
di.close();
|
||||||
}
|
}
|
||||||
listener.nodeFileEnd(nodefile);
|
listener.nodeFileEnd(nodefile);
|
||||||
if ( delete && "true".equals( System.getProperty( "deletetmpfiles" ) ))
|
if (delete && "true".equals(System.getProperty("deletetmpfiles"))) {
|
||||||
{
|
|
||||||
nodefile.delete();
|
nodefile.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,7 @@ import java.io.File;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public interface NodeListener
|
public interface NodeListener {
|
||||||
{
|
|
||||||
void nodeFileStart(File nodefile) throws Exception;
|
void nodeFileStart(File nodefile) throws Exception;
|
||||||
|
|
||||||
void nextNode(NodeData data) throws Exception;
|
void nextNode(NodeData data) throws Exception;
|
||||||
|
|||||||
@ -18,8 +18,7 @@ import btools.expressions.BExpressionContextNode;
|
|||||||
import btools.expressions.BExpressionContextWay;
|
import btools.expressions.BExpressionContextWay;
|
||||||
import btools.expressions.BExpressionMetaData;
|
import btools.expressions.BExpressionMetaData;
|
||||||
|
|
||||||
public class OsmCutter extends MapCreatorBase
|
public class OsmCutter extends MapCreatorBase {
|
||||||
{
|
|
||||||
private long recordCnt;
|
private long recordCnt;
|
||||||
private long nodesParsed;
|
private long nodesParsed;
|
||||||
private long waysParsed;
|
private long waysParsed;
|
||||||
@ -34,11 +33,9 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
public RestrictionCutter restrictionCutter;
|
public RestrictionCutter restrictionCutter;
|
||||||
public NodeFilter nodeFilter;
|
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");
|
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("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> ");
|
System.out.println("or : java OsmCutter <lookup-file> <out-tile-dir> <out-way-file> <out-rel-file> <out-res-file> <filter-profile> <inputfile> ");
|
||||||
return;
|
return;
|
||||||
@ -61,10 +58,8 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
// private BExpressionContextWay _expctxWayStat;
|
// private BExpressionContextWay _expctxWayStat;
|
||||||
// private BExpressionContextNode _expctxNodeStat;
|
// private BExpressionContextNode _expctxNodeStat;
|
||||||
|
|
||||||
public void process (File lookupFile, File outTileDir, File wayFile, File relFile, File resFile, File profileFile, File mapFile ) throws Exception
|
public void process(File lookupFile, File outTileDir, File wayFile, File relFile, File resFile, File profileFile, File mapFile) throws Exception {
|
||||||
{
|
if (!lookupFile.exists()) {
|
||||||
if ( !lookupFile.exists() )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("lookup-file: " + lookupFile + " does not exist");
|
throw new IllegalArgumentException("lookup-file: " + lookupFile + " does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,12 +75,12 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
// _expctxNodeStat = new BExpressionContextNode( null );
|
// _expctxNodeStat = new BExpressionContextNode( null );
|
||||||
|
|
||||||
this.outTileDir = outTileDir;
|
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)));
|
wayDos = wayFile == null ? null : new DataOutputStream(new BufferedOutputStream(new FileOutputStream(wayFile)));
|
||||||
cyclewayDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(relFile)));
|
cyclewayDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(relFile)));
|
||||||
if ( resFile != null )
|
if (resFile != null) {
|
||||||
{
|
|
||||||
restrictionsDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(resFile)));
|
restrictionsDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(resFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,13 +93,11 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
|
|
||||||
// close all files
|
// close all files
|
||||||
closeTileOutStreams();
|
closeTileOutStreams();
|
||||||
if ( wayDos != null )
|
if (wayDos != null) {
|
||||||
{
|
|
||||||
wayDos.close();
|
wayDos.close();
|
||||||
}
|
}
|
||||||
cyclewayDos.close();
|
cyclewayDos.close();
|
||||||
if ( restrictionsDos != null )
|
if (restrictionsDos != null) {
|
||||||
{
|
|
||||||
restrictionsDos.close();
|
restrictionsDos.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,28 +109,23 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
System.out.println(statsLine());
|
System.out.println(statsLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkStats()
|
private void checkStats() {
|
||||||
{
|
|
||||||
if ((++recordCnt % 100000) == 0) System.out.println(statsLine());
|
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;
|
return "records read: " + recordCnt + " nodes=" + nodesParsed + " ways=" + waysParsed + " rels=" + relsParsed + " changesets=" + changesetsParsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData n ) throws Exception
|
public void nextNode(NodeData n) throws Exception {
|
||||||
{
|
|
||||||
nodesParsed++;
|
nodesParsed++;
|
||||||
checkStats();
|
checkStats();
|
||||||
|
|
||||||
if ( n.getTagsOrNull() != null )
|
if (n.getTagsOrNull() != null) {
|
||||||
{
|
|
||||||
int[] lookupData = _expctxNode.createNewLookupData();
|
int[] lookupData = _expctxNode.createNewLookupData();
|
||||||
for( Map.Entry<String,String> e : n.getTagsOrNull().entrySet() )
|
for (Map.Entry<String, String> e : n.getTagsOrNull().entrySet()) {
|
||||||
{
|
|
||||||
_expctxNode.addLookupValue(e.getKey(), e.getValue(), lookupData);
|
_expctxNode.addLookupValue(e.getKey(), e.getValue(), lookupData);
|
||||||
// _expctxNodeStat.addLookupValue( key, value, null );
|
// _expctxNodeStat.addLookupValue( key, value, null );
|
||||||
}
|
}
|
||||||
@ -145,49 +133,40 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
// write node to file
|
// write node to file
|
||||||
int tileIndex = getTileIndex(n.ilon, n.ilat);
|
int tileIndex = getTileIndex(n.ilon, n.ilat);
|
||||||
if ( tileIndex >= 0 )
|
if (tileIndex >= 0) {
|
||||||
{
|
|
||||||
n.writeTo(getOutStreamForTile(tileIndex));
|
n.writeTo(getOutStreamForTile(tileIndex));
|
||||||
if ( wayCutter != null )
|
if (wayCutter != null) {
|
||||||
{
|
|
||||||
wayCutter.nextNode(n);
|
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
|
// add pseudo.tags for concrete:lanes and concrete:plates
|
||||||
|
|
||||||
String concrete = null;
|
String concrete = null;
|
||||||
for( Map.Entry<String,String> e : map.entrySet() )
|
for (Map.Entry<String, String> e : map.entrySet()) {
|
||||||
{
|
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
|
|
||||||
if ( "concrete".equals( key ) )
|
if ("concrete".equals(key)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( "surface".equals( key ) )
|
if ("surface".equals(key)) {
|
||||||
{
|
|
||||||
String value = e.getValue();
|
String value = e.getValue();
|
||||||
if ( value.startsWith( "concrete:" ) )
|
if (value.startsWith("concrete:")) {
|
||||||
{
|
|
||||||
concrete = value.substring("concrete:".length());
|
concrete = value.substring("concrete:".length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( concrete != null )
|
if (concrete != null) {
|
||||||
{
|
|
||||||
map.put("concrete", concrete);
|
map.put("concrete", concrete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextWay( WayData w ) throws Exception
|
public void nextWay(WayData w) throws Exception {
|
||||||
{
|
|
||||||
waysParsed++;
|
waysParsed++;
|
||||||
checkStats();
|
checkStats();
|
||||||
|
|
||||||
@ -197,8 +176,7 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
generatePseudoTags(w.getTagsOrNull());
|
generatePseudoTags(w.getTagsOrNull());
|
||||||
|
|
||||||
int[] lookupData = _expctxWay.createNewLookupData();
|
int[] lookupData = _expctxWay.createNewLookupData();
|
||||||
for( String key : w.getTagsOrNull().keySet() )
|
for (String key : w.getTagsOrNull().keySet()) {
|
||||||
{
|
|
||||||
String value = w.getTag(key);
|
String value = w.getTag(key);
|
||||||
_expctxWay.addLookupValue(key, value.replace(' ', '_'), lookupData);
|
_expctxWay.addLookupValue(key, value.replace(' ', '_'), lookupData);
|
||||||
// _expctxWayStat.addLookupValue( key, value, null );
|
// _expctxWayStat.addLookupValue( key, value, null );
|
||||||
@ -214,30 +192,25 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
ok |= _expctxWay.getCostfactor() < 10000.;
|
ok |= _expctxWay.getCostfactor() < 10000.;
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
|
|
||||||
if ( wayDos != null )
|
if (wayDos != null) {
|
||||||
{
|
|
||||||
w.writeTo(wayDos);
|
w.writeTo(wayDos);
|
||||||
}
|
}
|
||||||
if ( wayCutter != null )
|
if (wayCutter != null) {
|
||||||
{
|
|
||||||
wayCutter.nextWay(w);
|
wayCutter.nextWay(w);
|
||||||
}
|
}
|
||||||
if ( nodeFilter != null )
|
if (nodeFilter != null) {
|
||||||
{
|
|
||||||
nodeFilter.nextWay(w);
|
nodeFilter.nextWay(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextRelation( RelationData r ) throws Exception
|
public void nextRelation(RelationData r) throws Exception {
|
||||||
{
|
|
||||||
relsParsed++;
|
relsParsed++;
|
||||||
checkStats();
|
checkStats();
|
||||||
|
|
||||||
String route = r.getTag("route");
|
String route = r.getTag("route");
|
||||||
// filter out non-cycle relations
|
// filter out non-cycle relations
|
||||||
if ( route == null )
|
if (route == null) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,8 +222,7 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
cyclewayDos.writeUTF(route);
|
cyclewayDos.writeUTF(route);
|
||||||
cyclewayDos.writeUTF(network);
|
cyclewayDos.writeUTF(network);
|
||||||
cyclewayDos.writeUTF(state);
|
cyclewayDos.writeUTF(state);
|
||||||
for ( int i=0; i<r.ways.size();i++ )
|
for (int i = 0; i < r.ways.size(); i++) {
|
||||||
{
|
|
||||||
long wid = r.ways.get(i);
|
long wid = r.ways.get(i);
|
||||||
writeId(cyclewayDos, wid);
|
writeId(cyclewayDos, wid);
|
||||||
}
|
}
|
||||||
@ -258,17 +230,14 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextRestriction( RelationData r, long fromWid, long toWid, long viaNid ) throws Exception
|
public void nextRestriction(RelationData r, long fromWid, long toWid, long viaNid) throws Exception {
|
||||||
{
|
|
||||||
String type = r.getTag("type");
|
String type = r.getTag("type");
|
||||||
if ( type == null || !"restriction".equals( type ) )
|
if (type == null || !"restriction".equals(type)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
short exceptions = 0;
|
short exceptions = 0;
|
||||||
String except = r.getTag("except");
|
String except = r.getTag("except");
|
||||||
if ( except != null )
|
if (except != null) {
|
||||||
{
|
|
||||||
exceptions |= toBit("bicycle", 0, except);
|
exceptions |= toBit("bicycle", 0, except);
|
||||||
exceptions |= toBit("motorcar", 1, except);
|
exceptions |= toBit("motorcar", 1, except);
|
||||||
exceptions |= toBit("agricultural", 2, except);
|
exceptions |= toBit("agricultural", 2, except);
|
||||||
@ -277,10 +246,8 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
exceptions |= toBit("hgv", 4, except);
|
exceptions |= toBit("hgv", 4, except);
|
||||||
}
|
}
|
||||||
|
|
||||||
for( String restrictionKey : r.getTagsOrNull().keySet() )
|
for (String restrictionKey : r.getTagsOrNull().keySet()) {
|
||||||
{
|
if (!(restrictionKey.equals("restriction") || restrictionKey.startsWith("restriction:"))) {
|
||||||
if ( !( restrictionKey.equals( "restriction" ) || restrictionKey.startsWith( "restriction:" ) ) )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String restriction = r.getTag(restrictionKey);
|
String restriction = r.getTag(restrictionKey);
|
||||||
@ -293,36 +260,30 @@ public class OsmCutter extends MapCreatorBase
|
|||||||
res.toWid = toWid;
|
res.toWid = toWid;
|
||||||
res.viaNid = viaNid;
|
res.viaNid = viaNid;
|
||||||
|
|
||||||
if ( restrictionsDos != null )
|
if (restrictionsDos != null) {
|
||||||
{
|
|
||||||
res.writeTo(restrictionsDos);
|
res.writeTo(restrictionsDos);
|
||||||
}
|
}
|
||||||
if ( restrictionCutter != null )
|
if (restrictionCutter != null) {
|
||||||
{
|
|
||||||
restrictionCutter.nextRestriction(res);
|
restrictionCutter.nextRestriction(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static short toBit( String tag, int bitpos, String s )
|
private static short toBit(String tag, int bitpos, String s) {
|
||||||
{
|
|
||||||
return (short) (s.indexOf(tag) < 0 ? 0 : 1 << bitpos);
|
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 lon = ilon / 45000000;
|
||||||
int lat = ilat / 30000000;
|
int lat = ilat / 30000000;
|
||||||
if ( lon < 0 || lon > 7 || lat < 0 || lat > 5 )
|
if (lon < 0 || lon > 7 || lat < 0 || lat > 5) {
|
||||||
{
|
|
||||||
System.out.println("warning: ignoring illegal pos: " + ilon + "," + ilat);
|
System.out.println("warning: ignoring illegal pos: " + ilon + "," + ilat);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return lon * 6 + lat;
|
return lon * 6 + lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getNameForTile( int tileIndex )
|
protected String getNameForTile(int tileIndex) {
|
||||||
{
|
|
||||||
int lon = (tileIndex / 6) * 45 - 180;
|
int lon = (tileIndex / 6) * 45 - 180;
|
||||||
int lat = (tileIndex % 6) * 30 - 90;
|
int lat = (tileIndex % 6) * 30 - 90;
|
||||||
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
||||||
|
|||||||
@ -9,13 +9,10 @@ package btools.mapcreator;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class OsmFastCutter extends MapCreatorBase
|
public class OsmFastCutter extends MapCreatorBase {
|
||||||
{
|
public static void main(String[] args) throws Exception {
|
||||||
public static void main(String[] args) throws Exception
|
|
||||||
{
|
|
||||||
System.out.println("*** OsmFastCutter: cut an osm map in node-tiles + way-tiles");
|
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>";
|
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("usage: bzip2 -dc <map> | " + common);
|
||||||
@ -39,8 +36,7 @@ public class OsmFastCutter extends MapCreatorBase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void doCut (File lookupFile, File nodeDir, File wayDir, File node55Dir, File way55Dir, File borderFile, File relFile, File resFile, File profileAll, File profileReport, File profileCheck, File mapFile ) throws Exception
|
public static void doCut(File lookupFile, File nodeDir, File wayDir, File node55Dir, File way55Dir, File borderFile, File relFile, File resFile, File profileAll, File profileReport, File profileCheck, File mapFile) throws Exception {
|
||||||
{
|
|
||||||
// **** run OsmCutter ****
|
// **** run OsmCutter ****
|
||||||
OsmCutter cutter = new OsmCutter();
|
OsmCutter cutter = new OsmCutter();
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,7 @@
|
|||||||
package btools.mapcreator;
|
package btools.mapcreator;
|
||||||
|
|
||||||
|
|
||||||
public class OsmLinkP
|
public class OsmLinkP {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* The description bitmap is mainly the way description
|
* The description bitmap is mainly the way description
|
||||||
* used to calculate the costfactor
|
* used to calculate the costfactor
|
||||||
@ -24,36 +23,27 @@ public class OsmLinkP
|
|||||||
protected OsmLinkP next;
|
protected OsmLinkP next;
|
||||||
|
|
||||||
|
|
||||||
public OsmLinkP( OsmNodeP source, OsmNodeP target )
|
public OsmLinkP(OsmNodeP source, OsmNodeP target) {
|
||||||
{
|
|
||||||
sourceNode = source;
|
sourceNode = source;
|
||||||
targetNode = target;
|
targetNode = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected OsmLinkP()
|
protected OsmLinkP() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean counterLinkWritten( )
|
public final boolean counterLinkWritten() {
|
||||||
{
|
|
||||||
return descriptionBitmap == null;
|
return descriptionBitmap == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the relevant next-pointer for the given source
|
* Set the relevant next-pointer for the given source
|
||||||
*/
|
*/
|
||||||
public void setNext( OsmLinkP link, OsmNodeP source )
|
public void setNext(OsmLinkP link, OsmNodeP source) {
|
||||||
{
|
if (sourceNode == source) {
|
||||||
if ( sourceNode == source )
|
|
||||||
{
|
|
||||||
next = link;
|
next = link;
|
||||||
}
|
} else if (targetNode == source) {
|
||||||
else if ( targetNode == source )
|
|
||||||
{
|
|
||||||
previous = link;
|
previous = link;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("internal error: setNext: unknown source");
|
throw new IllegalArgumentException("internal error: setNext: unknown source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,18 +51,12 @@ public class OsmLinkP
|
|||||||
/**
|
/**
|
||||||
* Get the relevant next-pointer for the given source
|
* Get the relevant next-pointer for the given source
|
||||||
*/
|
*/
|
||||||
public OsmLinkP getNext( OsmNodeP source )
|
public OsmLinkP getNext(OsmNodeP source) {
|
||||||
{
|
if (sourceNode == source) {
|
||||||
if ( sourceNode == source )
|
|
||||||
{
|
|
||||||
return next;
|
return next;
|
||||||
}
|
} else if (targetNode == source) {
|
||||||
else if ( targetNode == source )
|
|
||||||
{
|
|
||||||
return previous;
|
return previous;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("internal error: gextNext: unknown source");
|
throw new IllegalArgumentException("internal error: gextNext: unknown source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,18 +64,12 @@ public class OsmLinkP
|
|||||||
/**
|
/**
|
||||||
* Get the relevant target-node for the given source
|
* Get the relevant target-node for the given source
|
||||||
*/
|
*/
|
||||||
public OsmNodeP getTarget( OsmNodeP source )
|
public OsmNodeP getTarget(OsmNodeP source) {
|
||||||
{
|
if (sourceNode == source) {
|
||||||
if ( sourceNode == source )
|
|
||||||
{
|
|
||||||
return targetNode;
|
return targetNode;
|
||||||
}
|
} else if (targetNode == source) {
|
||||||
else if ( targetNode == source )
|
|
||||||
{
|
|
||||||
return sourceNode;
|
return sourceNode;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("internal error: getTarget: unknown source");
|
throw new IllegalArgumentException("internal error: getTarget: unknown source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,18 +77,12 @@ public class OsmLinkP
|
|||||||
/**
|
/**
|
||||||
* Check if reverse link for the given source
|
* Check if reverse link for the given source
|
||||||
*/
|
*/
|
||||||
public boolean isReverse( OsmNodeP source )
|
public boolean isReverse(OsmNodeP source) {
|
||||||
{
|
if (sourceNode == source) {
|
||||||
if ( sourceNode == source )
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (targetNode == source) {
|
||||||
else if ( targetNode == source )
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("internal error: isReverse: unknown source");
|
throw new IllegalArgumentException("internal error: isReverse: unknown source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,8 +12,7 @@ import java.util.HashMap;
|
|||||||
import btools.codec.MicroCache;
|
import btools.codec.MicroCache;
|
||||||
import btools.codec.MicroCache2;
|
import btools.codec.MicroCache2;
|
||||||
|
|
||||||
public class OsmNodeP extends OsmLinkP
|
public class OsmNodeP extends OsmLinkP {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* The latitude
|
* The latitude
|
||||||
*/
|
*/
|
||||||
@ -40,33 +39,27 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
public byte bits = 0;
|
public byte bits = 0;
|
||||||
|
|
||||||
// interface OsmPos
|
// interface OsmPos
|
||||||
public int getILat()
|
public int getILat() {
|
||||||
{
|
|
||||||
return ilat;
|
return ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getILon()
|
public int getILon() {
|
||||||
{
|
|
||||||
return ilon;
|
return ilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getSElev()
|
public short getSElev() {
|
||||||
{
|
|
||||||
// if all bridge or all tunnel, elevation=no-data
|
// 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.;
|
return selev / 4.;
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate and return the inherited link, if available,
|
// populate and return the inherited link, if available,
|
||||||
// else create a new one
|
// else create a new one
|
||||||
public OsmLinkP createLink( OsmNodeP source )
|
public OsmLinkP createLink(OsmNodeP source) {
|
||||||
{
|
if (sourceNode == null && targetNode == null) {
|
||||||
if ( sourceNode == null && targetNode == null )
|
|
||||||
{
|
|
||||||
// inherited instance is available, use this
|
// inherited instance is available, use this
|
||||||
sourceNode = source;
|
sourceNode = source;
|
||||||
targetNode = this;
|
targetNode = this;
|
||||||
@ -81,67 +74,52 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
|
|
||||||
// memory-squeezing-hack: OsmLinkP's "previous" also used as firstlink..
|
// memory-squeezing-hack: OsmLinkP's "previous" also used as firstlink..
|
||||||
|
|
||||||
public void addLink( OsmLinkP link )
|
public void addLink(OsmLinkP link) {
|
||||||
{
|
|
||||||
link.setNext(previous, this);
|
link.setNext(previous, this);
|
||||||
previous = link;
|
previous = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmLinkP getFirstLink()
|
public OsmLinkP getFirstLink() {
|
||||||
{
|
|
||||||
return sourceNode == null && targetNode == null ? previous : this;
|
return sourceNode == null && targetNode == null ? previous : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getNodeDecsription()
|
public byte[] getNodeDecsription() {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestrictionData getFirstRestriction()
|
public RestrictionData getFirstRestriction() {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeNodeData( MicroCache mc, OsmTrafficMap trafficMap ) throws IOException
|
public void writeNodeData(MicroCache mc, OsmTrafficMap trafficMap) throws IOException {
|
||||||
{
|
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
if ( mc instanceof MicroCache2 )
|
if (mc instanceof MicroCache2) {
|
||||||
{
|
|
||||||
valid = writeNodeData2((MicroCache2) mc, trafficMap);
|
valid = writeNodeData2((MicroCache2) mc, trafficMap);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("unknown cache version: " + mc.getClass());
|
throw new IllegalArgumentException("unknown cache version: " + mc.getClass());
|
||||||
if ( valid )
|
if (valid) {
|
||||||
{
|
|
||||||
mc.finishNode(getIdFromPos());
|
mc.finishNode(getIdFromPos());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
mc.discardNode();
|
mc.discardNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkDuplicateTargets()
|
public void checkDuplicateTargets() {
|
||||||
{
|
|
||||||
HashMap<OsmNodeP, OsmLinkP> targets = new HashMap<OsmNodeP, OsmLinkP>();
|
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;
|
OsmLinkP link = link0;
|
||||||
OsmNodeP origin = this;
|
OsmNodeP origin = this;
|
||||||
OsmNodeP target = null;
|
OsmNodeP target = null;
|
||||||
|
|
||||||
// first pass just to see if that link is consistent
|
// first pass just to see if that link is consistent
|
||||||
while (link != null)
|
while (link != null) {
|
||||||
{
|
|
||||||
target = link.getTarget(origin);
|
target = link.getTarget(origin);
|
||||||
if ( !target.isTransferNode() )
|
if (!target.isTransferNode()) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// next link is the one (of two), does does'nt point back
|
// next link is the one (of two), does does'nt point back
|
||||||
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
|
for (link = target.getFirstLink(); link != null; link = link.getNext(target)) {
|
||||||
{
|
|
||||||
if (link.getTarget(target) != origin)
|
if (link.getTarget(target) != origin)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -149,34 +127,28 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
}
|
}
|
||||||
if (link == null) continue;
|
if (link == null) continue;
|
||||||
OsmLinkP oldLink = targets.put(target, link0);
|
OsmLinkP oldLink = targets.put(target, link0);
|
||||||
if ( oldLink != null )
|
if (oldLink != null) {
|
||||||
{
|
|
||||||
unifyLink(oldLink);
|
unifyLink(oldLink);
|
||||||
unifyLink(link0);
|
unifyLink(link0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unifyLink( OsmLinkP link )
|
private void unifyLink(OsmLinkP link) {
|
||||||
{
|
|
||||||
if (link.isReverse(this)) return;
|
if (link.isReverse(this)) return;
|
||||||
OsmNodeP target = link.getTarget(this);
|
OsmNodeP target = link.getTarget(this);
|
||||||
if ( target.isTransferNode() )
|
if (target.isTransferNode()) {
|
||||||
{
|
|
||||||
target.incWayCount();
|
target.incWayCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean writeNodeData2( MicroCache2 mc, OsmTrafficMap trafficMap ) throws IOException
|
public boolean writeNodeData2(MicroCache2 mc, OsmTrafficMap trafficMap) throws IOException {
|
||||||
{
|
|
||||||
boolean hasLinks = false;
|
boolean hasLinks = false;
|
||||||
|
|
||||||
// write turn restrictions
|
// write turn restrictions
|
||||||
RestrictionData r = getFirstRestriction();
|
RestrictionData r = getFirstRestriction();
|
||||||
while( r != null )
|
while (r != null) {
|
||||||
{
|
if (r.isValid() && r.fromLon != 0 && r.toLon != 0) {
|
||||||
if ( r.isValid() && r.fromLon != 0 && r.toLon != 0 )
|
|
||||||
{
|
|
||||||
mc.writeBoolean(true); // restriction follows
|
mc.writeBoolean(true); // restriction follows
|
||||||
mc.writeShort(r.exceptions);
|
mc.writeShort(r.exceptions);
|
||||||
mc.writeBoolean(r.isPositive());
|
mc.writeBoolean(r.isPositive());
|
||||||
@ -195,8 +167,7 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
// buffer internal reverse links
|
// buffer internal reverse links
|
||||||
ArrayList<OsmNodeP> internalReverse = new ArrayList<OsmNodeP>();
|
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;
|
OsmLinkP link = link0;
|
||||||
OsmNodeP origin = this;
|
OsmNodeP origin = this;
|
||||||
OsmNodeP target = null;
|
OsmNodeP target = null;
|
||||||
@ -205,24 +176,20 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
linkNodes.add(this);
|
linkNodes.add(this);
|
||||||
|
|
||||||
// first pass just to see if that link is consistent
|
// first pass just to see if that link is consistent
|
||||||
while (link != null)
|
while (link != null) {
|
||||||
{
|
|
||||||
target = link.getTarget(origin);
|
target = link.getTarget(origin);
|
||||||
linkNodes.add(target);
|
linkNodes.add(target);
|
||||||
|
|
||||||
if ( !target.isTransferNode() )
|
if (!target.isTransferNode()) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// next link is the one (of two), does does'nt point back
|
// next link is the one (of two), does does'nt point back
|
||||||
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
|
for (link = target.getFirstLink(); link != null; link = link.getNext(target)) {
|
||||||
{
|
|
||||||
if (link.getTarget(target) != origin)
|
if (link.getTarget(target) != origin)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( link != null && link.descriptionBitmap != link0.descriptionBitmap )
|
if (link != null && link.descriptionBitmap != link0.descriptionBitmap) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("assertion failed: description change along transfer nodes");
|
throw new IllegalArgumentException("assertion failed: description change along transfer nodes");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,10 +203,8 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
|
|
||||||
// internal reverse links later
|
// internal reverse links later
|
||||||
boolean isReverse = link0.isReverse(this);
|
boolean isReverse = link0.isReverse(this);
|
||||||
if ( isReverse )
|
if (isReverse) {
|
||||||
{
|
if (mc.isInternal(target.ilon, target.ilat)) {
|
||||||
if ( mc.isInternal( target.ilon, target.ilat ) )
|
|
||||||
{
|
|
||||||
internalReverse.add(target);
|
internalReverse.add(target);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -247,8 +212,7 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
|
|
||||||
// add traffic simulation, if present
|
// add traffic simulation, if present
|
||||||
byte[] description = link0.descriptionBitmap;
|
byte[] description = link0.descriptionBitmap;
|
||||||
if ( trafficMap != null )
|
if (trafficMap != null) {
|
||||||
{
|
|
||||||
description = trafficMap.addTrafficClass(linkNodes, description);
|
description = trafficMap.addTrafficClass(linkNodes, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,11 +225,9 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
{
|
{
|
||||||
DPFilter.doDPFilter(linkNodes);
|
DPFilter.doDPFilter(linkNodes);
|
||||||
origin = this;
|
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);
|
OsmNodeP tranferNode = linkNodes.get(i);
|
||||||
if ( ( tranferNode.bits & OsmNodeP.DP_SURVIVOR_BIT ) != 0 )
|
if ((tranferNode.bits & OsmNodeP.DP_SURVIVOR_BIT) != 0) {
|
||||||
{
|
|
||||||
mc.writeVarLengthSigned(tranferNode.ilon - origin.ilon);
|
mc.writeVarLengthSigned(tranferNode.ilon - origin.ilon);
|
||||||
mc.writeVarLengthSigned(tranferNode.ilat - origin.ilat);
|
mc.writeVarLengthSigned(tranferNode.ilat - origin.ilat);
|
||||||
mc.writeVarLengthSigned(tranferNode.getSElev() - origin.getSElev());
|
mc.writeVarLengthSigned(tranferNode.getSElev() - origin.getSElev());
|
||||||
@ -276,17 +238,13 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
mc.injectSize(sizeoffset);
|
mc.injectSize(sizeoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (internalReverse.size() > 0)
|
while (internalReverse.size() > 0) {
|
||||||
{
|
|
||||||
int nextIdx = 0;
|
int nextIdx = 0;
|
||||||
if ( internalReverse.size() > 1 )
|
if (internalReverse.size() > 1) {
|
||||||
{
|
|
||||||
int max32 = Integer.MIN_VALUE;
|
int max32 = Integer.MIN_VALUE;
|
||||||
for ( int i = 0; i < internalReverse.size(); i++ )
|
for (int i = 0; i < internalReverse.size(); i++) {
|
||||||
{
|
|
||||||
int id32 = mc.shrinkId(internalReverse.get(i).getIdFromPos());
|
int id32 = mc.shrinkId(internalReverse.get(i).getIdFromPos());
|
||||||
if ( id32 > max32 )
|
if (id32 > max32) {
|
||||||
{
|
|
||||||
max32 = id32;
|
max32 = id32;
|
||||||
nextIdx = i;
|
nextIdx = i;
|
||||||
}
|
}
|
||||||
@ -302,49 +260,40 @@ public class OsmNodeP extends OsmLinkP
|
|||||||
return hasLinks;
|
return hasLinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString2()
|
public String toString2() {
|
||||||
{
|
|
||||||
return (ilon - 180000000) + "_" + (ilat - 90000000) + "_" + (selev / 4);
|
return (ilon - 180000000) + "_" + (ilat - 90000000) + "_" + (selev / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getIdFromPos()
|
public long getIdFromPos() {
|
||||||
{
|
|
||||||
return ((long) ilon) << 32 | ilat;
|
return ((long) ilon) << 32 | ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBorderNode()
|
public boolean isBorderNode() {
|
||||||
{
|
|
||||||
return (bits & BORDER_BIT) != 0;
|
return (bits & BORDER_BIT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasTraffic()
|
public boolean hasTraffic() {
|
||||||
{
|
|
||||||
return (bits & TRAFFIC_BIT) != 0;
|
return (bits & TRAFFIC_BIT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not really count the ways, just detect if more than one
|
* Not really count the ways, just detect if more than one
|
||||||
*/
|
*/
|
||||||
public void incWayCount()
|
public void incWayCount() {
|
||||||
{
|
if ((bits & ANY_WAY_BIT) != 0) {
|
||||||
if ( ( bits & ANY_WAY_BIT ) != 0 )
|
|
||||||
{
|
|
||||||
bits |= MULTI_WAY_BIT;
|
bits |= MULTI_WAY_BIT;
|
||||||
}
|
}
|
||||||
bits |= ANY_WAY_BIT;
|
bits |= ANY_WAY_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTransferNode()
|
public boolean isTransferNode() {
|
||||||
{
|
|
||||||
return (bits & BORDER_BIT) == 0 && (bits & MULTI_WAY_BIT) == 0 && _linkCnt() == 2;
|
return (bits & BORDER_BIT) == 0 && (bits & MULTI_WAY_BIT) == 0 && _linkCnt() == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _linkCnt()
|
private int _linkCnt() {
|
||||||
{
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
for ( OsmLinkP link = getFirstLink(); link != null; link = link.getNext( this ) )
|
for (OsmLinkP link = getFirstLink(); link != null; link = link.getNext(this)) {
|
||||||
{
|
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
|
|||||||
@ -6,44 +6,37 @@
|
|||||||
package btools.mapcreator;
|
package btools.mapcreator;
|
||||||
|
|
||||||
|
|
||||||
public class OsmNodePT extends OsmNodeP
|
public class OsmNodePT extends OsmNodeP {
|
||||||
{
|
|
||||||
public byte[] descriptionBits;
|
public byte[] descriptionBits;
|
||||||
|
|
||||||
public RestrictionData firstRestriction;
|
public RestrictionData firstRestriction;
|
||||||
|
|
||||||
public OsmNodePT()
|
public OsmNodePT() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNodePT( OsmNodeP n )
|
public OsmNodePT(OsmNodeP n) {
|
||||||
{
|
|
||||||
ilat = n.ilat;
|
ilat = n.ilat;
|
||||||
ilon = n.ilon;
|
ilon = n.ilon;
|
||||||
selev = n.selev;
|
selev = n.selev;
|
||||||
bits = n.bits;
|
bits = n.bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNodePT( byte[] descriptionBits )
|
public OsmNodePT(byte[] descriptionBits) {
|
||||||
{
|
|
||||||
this.descriptionBits = descriptionBits;
|
this.descriptionBits = descriptionBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final byte[] getNodeDecsription()
|
public final byte[] getNodeDecsription() {
|
||||||
{
|
|
||||||
return descriptionBits;
|
return descriptionBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final RestrictionData getFirstRestriction()
|
public final RestrictionData getFirstRestriction() {
|
||||||
{
|
|
||||||
return firstRestriction;
|
return firstRestriction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTransferNode()
|
public boolean isTransferNode() {
|
||||||
{
|
|
||||||
return false; // always have descriptionBits so never transfernode
|
return false; // always have descriptionBits so never transfernode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import java.util.zip.GZIPInputStream;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class OsmParser extends MapCreatorBase
|
public class OsmParser extends MapCreatorBase {
|
||||||
{
|
|
||||||
private BufferedReader _br;
|
private BufferedReader _br;
|
||||||
|
|
||||||
private NodeListener nListener;
|
private NodeListener nListener;
|
||||||
@ -22,31 +21,23 @@ public class OsmParser extends MapCreatorBase
|
|||||||
public void readMap(File mapFile,
|
public void readMap(File mapFile,
|
||||||
NodeListener nListener,
|
NodeListener nListener,
|
||||||
WayListener wListener,
|
WayListener wListener,
|
||||||
RelationListener rListener ) throws Exception
|
RelationListener rListener) throws Exception {
|
||||||
{
|
|
||||||
|
|
||||||
this.nListener = nListener;
|
this.nListener = nListener;
|
||||||
this.wListener = wListener;
|
this.wListener = wListener;
|
||||||
this.rListener = rListener;
|
this.rListener = rListener;
|
||||||
|
|
||||||
if ( mapFile == null )
|
if (mapFile == null) {
|
||||||
{
|
|
||||||
_br = new BufferedReader(new InputStreamReader(System.in));
|
_br = new BufferedReader(new InputStreamReader(System.in));
|
||||||
}
|
} else {
|
||||||
else
|
if (mapFile.getName().endsWith(".gz")) {
|
||||||
{
|
|
||||||
if ( mapFile.getName().endsWith( ".gz" ) )
|
|
||||||
{
|
|
||||||
_br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(mapFile))));
|
_br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(mapFile))));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
_br = new BufferedReader(new InputStreamReader(new FileInputStream(mapFile)));
|
_br = new BufferedReader(new InputStreamReader(new FileInputStream(mapFile)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
String line = _br.readLine();
|
String line = _br.readLine();
|
||||||
if (line == null) break;
|
if (line == null) break;
|
||||||
|
|
||||||
@ -56,15 +47,13 @@ public class OsmParser extends MapCreatorBase
|
|||||||
if (checkChangeset(line)) continue;
|
if (checkChangeset(line)) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mapFile != null )
|
if (mapFile != null) {
|
||||||
{
|
|
||||||
_br.close();
|
_br.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean checkNode( String line ) throws Exception
|
private boolean checkNode(String line) throws Exception {
|
||||||
{
|
|
||||||
int idx0 = line.indexOf("<node id=\"");
|
int idx0 = line.indexOf("<node id=\"");
|
||||||
if (idx0 < 0) return false;
|
if (idx0 < 0) return false;
|
||||||
idx0 += 10;
|
idx0 += 10;
|
||||||
@ -85,32 +74,26 @@ public class OsmParser extends MapCreatorBase
|
|||||||
|
|
||||||
NodeData n = new NodeData(nodeId, lon, lat);
|
NodeData n = new NodeData(nodeId, lon, lat);
|
||||||
|
|
||||||
if ( !line.endsWith( "/>" ) )
|
if (!line.endsWith("/>")) {
|
||||||
{
|
|
||||||
// read additional tags
|
// read additional tags
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
String l2 = _br.readLine();
|
String l2 = _br.readLine();
|
||||||
if (l2 == null) return false;
|
if (l2 == null) return false;
|
||||||
|
|
||||||
int i2;
|
int i2;
|
||||||
if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
|
if ((i2 = l2.indexOf("<tag k=\"")) >= 0) { // property-tag
|
||||||
{ // property-tag
|
|
||||||
i2 += 8;
|
i2 += 8;
|
||||||
int ri2 = l2.indexOf('"', i2);
|
int ri2 = l2.indexOf('"', i2);
|
||||||
String key = l2.substring(i2, ri2);
|
String key = l2.substring(i2, ri2);
|
||||||
i2 = l2.indexOf(" v=\"", ri2);
|
i2 = l2.indexOf(" v=\"", ri2);
|
||||||
if ( i2 >= 0 )
|
if (i2 >= 0) {
|
||||||
{
|
|
||||||
i2 += 4;
|
i2 += 4;
|
||||||
int ri3 = l2.indexOf('"', i2);
|
int ri3 = l2.indexOf('"', i2);
|
||||||
String value = l2.substring(i2, ri3);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,8 +103,7 @@ public class OsmParser extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean checkWay( String line ) throws Exception
|
private boolean checkWay(String line) throws Exception {
|
||||||
{
|
|
||||||
int idx0 = line.indexOf("<way id=\"");
|
int idx0 = line.indexOf("<way id=\"");
|
||||||
if (idx0 < 0) return false;
|
if (idx0 < 0) return false;
|
||||||
|
|
||||||
@ -132,35 +114,28 @@ public class OsmParser extends MapCreatorBase
|
|||||||
WayData w = new WayData(id);
|
WayData w = new WayData(id);
|
||||||
|
|
||||||
// read the nodes
|
// read the nodes
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
String l2 = _br.readLine();
|
String l2 = _br.readLine();
|
||||||
if (l2 == null) return false;
|
if (l2 == null) return false;
|
||||||
|
|
||||||
int i2;
|
int i2;
|
||||||
if ( (i2 = l2.indexOf( "<nd ref=\"" )) >= 0 )
|
if ((i2 = l2.indexOf("<nd ref=\"")) >= 0) { // node reference
|
||||||
{ // node reference
|
|
||||||
i2 += 9;
|
i2 += 9;
|
||||||
int ri2 = l2.indexOf('"', i2);
|
int ri2 = l2.indexOf('"', i2);
|
||||||
long nid = Long.parseLong(l2.substring(i2, ri2));
|
long nid = Long.parseLong(l2.substring(i2, ri2));
|
||||||
w.nodes.add(nid);
|
w.nodes.add(nid);
|
||||||
}
|
} else if ((i2 = l2.indexOf("<tag k=\"")) >= 0) { // property-tag
|
||||||
else if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
|
|
||||||
{ // property-tag
|
|
||||||
i2 += 8;
|
i2 += 8;
|
||||||
int ri2 = l2.indexOf('"', i2);
|
int ri2 = l2.indexOf('"', i2);
|
||||||
String key = l2.substring(i2, ri2);
|
String key = l2.substring(i2, ri2);
|
||||||
i2 = l2.indexOf(" v=\"", ri2);
|
i2 = l2.indexOf(" v=\"", ri2);
|
||||||
if ( i2 >= 0 )
|
if (i2 >= 0) {
|
||||||
{
|
|
||||||
i2 += 4;
|
i2 += 4;
|
||||||
int ri3 = l2.indexOf('"', i2);
|
int ri3 = l2.indexOf('"', i2);
|
||||||
String value = l2.substring(i2, ri3);
|
String value = l2.substring(i2, ri3);
|
||||||
w.putTag(key, value);
|
w.putTag(key, value);
|
||||||
}
|
}
|
||||||
}
|
} else if (l2.indexOf("</way>") >= 0) { // end-tag
|
||||||
else if ( l2.indexOf( "</way>" ) >= 0 )
|
|
||||||
{ // end-tag
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,16 +143,13 @@ public class OsmParser extends MapCreatorBase
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkChangeset( String line ) throws Exception
|
private boolean checkChangeset(String line) throws Exception {
|
||||||
{
|
|
||||||
int idx0 = line.indexOf("<changeset id=\"");
|
int idx0 = line.indexOf("<changeset id=\"");
|
||||||
if (idx0 < 0) return false;
|
if (idx0 < 0) return false;
|
||||||
|
|
||||||
if ( !line.endsWith( "/>" ) )
|
if (!line.endsWith("/>")) {
|
||||||
{
|
|
||||||
int loopcheck = 0;
|
int loopcheck = 0;
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
String l2 = _br.readLine();
|
String l2 = _br.readLine();
|
||||||
if (l2.indexOf("</changeset>") >= 0 || ++loopcheck > 10000) break;
|
if (l2.indexOf("</changeset>") >= 0 || ++loopcheck > 10000) break;
|
||||||
}
|
}
|
||||||
@ -185,8 +157,7 @@ public class OsmParser extends MapCreatorBase
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkRelation( String line ) throws Exception
|
private boolean checkRelation(String line) throws Exception {
|
||||||
{
|
|
||||||
int idx0 = line.indexOf("<relation id=\"");
|
int idx0 = line.indexOf("<relation id=\"");
|
||||||
if (idx0 < 0) return false;
|
if (idx0 < 0) return false;
|
||||||
|
|
||||||
@ -197,35 +168,28 @@ public class OsmParser extends MapCreatorBase
|
|||||||
RelationData r = new RelationData(rid);
|
RelationData r = new RelationData(rid);
|
||||||
|
|
||||||
// read the nodes
|
// read the nodes
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
String l2 = _br.readLine();
|
String l2 = _br.readLine();
|
||||||
if (l2 == null) return false;
|
if (l2 == null) return false;
|
||||||
|
|
||||||
int i2;
|
int i2;
|
||||||
if ( (i2 = l2.indexOf( "<member type=\"way\" ref=\"" )) >= 0 )
|
if ((i2 = l2.indexOf("<member type=\"way\" ref=\"")) >= 0) { // node reference
|
||||||
{ // node reference
|
|
||||||
i2 += 24;
|
i2 += 24;
|
||||||
int ri2 = l2.indexOf('"', i2);
|
int ri2 = l2.indexOf('"', i2);
|
||||||
long wid = Long.parseLong(l2.substring(i2, ri2));
|
long wid = Long.parseLong(l2.substring(i2, ri2));
|
||||||
r.ways.add(wid);
|
r.ways.add(wid);
|
||||||
}
|
} else if ((i2 = l2.indexOf("<tag k=\"")) >= 0) { // property-tag
|
||||||
else if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
|
|
||||||
{ // property-tag
|
|
||||||
i2 += 8;
|
i2 += 8;
|
||||||
int ri2 = l2.indexOf('"', i2);
|
int ri2 = l2.indexOf('"', i2);
|
||||||
String key = l2.substring(i2, ri2);
|
String key = l2.substring(i2, ri2);
|
||||||
i2 = l2.indexOf(" v=\"", ri2);
|
i2 = l2.indexOf(" v=\"", ri2);
|
||||||
if ( i2 >= 0 )
|
if (i2 >= 0) {
|
||||||
{
|
|
||||||
i2 += 4;
|
i2 += 4;
|
||||||
int ri3 = l2.indexOf('"', i2);
|
int ri3 = l2.indexOf('"', i2);
|
||||||
String value = l2.substring(i2, ri3);
|
String value = l2.substring(i2, ri3);
|
||||||
r.putTag(key, value);
|
r.putTag(key, value);
|
||||||
}
|
}
|
||||||
}
|
} else if (l2.indexOf("</relation>") >= 0) { // end-tag
|
||||||
else if ( l2.indexOf( "</relation>" ) >= 0 )
|
|
||||||
{ // end-tag
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,8 +22,7 @@ import btools.util.CompactLongMap;
|
|||||||
import btools.util.FrozenLongMap;
|
import btools.util.FrozenLongMap;
|
||||||
|
|
||||||
|
|
||||||
public class OsmTrafficMap
|
public class OsmTrafficMap {
|
||||||
{
|
|
||||||
int minLon;
|
int minLon;
|
||||||
int minLat;
|
int minLat;
|
||||||
int maxLon;
|
int maxLon;
|
||||||
@ -42,14 +41,12 @@ public class OsmTrafficMap
|
|||||||
private boolean doNotAdd = false;
|
private boolean doNotAdd = false;
|
||||||
private boolean debug = false;
|
private boolean debug = false;
|
||||||
|
|
||||||
public OsmTrafficMap( BExpressionContextWay expctxWay )
|
public OsmTrafficMap(BExpressionContextWay expctxWay) {
|
||||||
{
|
|
||||||
this.expctxWay = expctxWay;
|
this.expctxWay = expctxWay;
|
||||||
debug = Boolean.getBoolean("debugTrafficMap");
|
debug = Boolean.getBoolean("debugTrafficMap");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class OsmTrafficElement
|
public static class OsmTrafficElement {
|
||||||
{
|
|
||||||
public long node2;
|
public long node2;
|
||||||
public int traffic;
|
public int traffic;
|
||||||
public OsmTrafficElement next;
|
public OsmTrafficElement next;
|
||||||
@ -57,14 +54,12 @@ public class OsmTrafficMap
|
|||||||
|
|
||||||
private CompactLongMap<OsmTrafficElement> map = new CompactLongMap<OsmTrafficElement>();
|
private CompactLongMap<OsmTrafficElement> map = new CompactLongMap<OsmTrafficElement>();
|
||||||
|
|
||||||
public void loadAll( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception
|
public void loadAll(File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways) throws Exception {
|
||||||
{
|
|
||||||
load(file, minLon, minLat, maxLon, maxLat, includeMotorways);
|
load(file, minLon, minLat, maxLon, maxLat, includeMotorways);
|
||||||
|
|
||||||
// check for old traffic data
|
// check for old traffic data
|
||||||
oldTrafficFile = new File(file.getParentFile(), file.getName() + "_old");
|
oldTrafficFile = new File(file.getParentFile(), file.getName() + "_old");
|
||||||
if ( oldTrafficFile.exists() )
|
if (oldTrafficFile.exists()) {
|
||||||
{
|
|
||||||
oldTrafficClasses = new OsmTrafficMap(null);
|
oldTrafficClasses = new OsmTrafficMap(null);
|
||||||
oldTrafficClasses.doNotAdd = true;
|
oldTrafficClasses.doNotAdd = true;
|
||||||
oldTrafficClasses.load(oldTrafficFile, minLon, minLat, maxLon, maxLat, false);
|
oldTrafficClasses.load(oldTrafficFile, minLon, minLat, maxLon, maxLat, false);
|
||||||
@ -75,10 +70,8 @@ public class OsmTrafficMap
|
|||||||
newTrafficDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newTrafficFile)));
|
newTrafficDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newTrafficFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() throws Exception
|
public void finish() throws Exception {
|
||||||
{
|
if (newTrafficDos != null) {
|
||||||
if ( newTrafficDos != null )
|
|
||||||
{
|
|
||||||
newTrafficDos.close();
|
newTrafficDos.close();
|
||||||
newTrafficDos = null;
|
newTrafficDos = null;
|
||||||
oldTrafficFile.delete();
|
oldTrafficFile.delete();
|
||||||
@ -87,8 +80,7 @@ public class OsmTrafficMap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception
|
public void load(File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways) throws Exception {
|
||||||
{
|
|
||||||
this.minLon = minLon;
|
this.minLon = minLon;
|
||||||
this.minLat = minLat;
|
this.minLat = minLat;
|
||||||
this.maxLon = maxLon;
|
this.maxLon = maxLon;
|
||||||
@ -96,86 +88,70 @@ public class OsmTrafficMap
|
|||||||
|
|
||||||
int trafficElements = 0;
|
int trafficElements = 0;
|
||||||
DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
|
DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
long n1 = is.readLong();
|
long n1 = is.readLong();
|
||||||
long n2 = is.readLong();
|
long n2 = is.readLong();
|
||||||
int traffic = is.readInt();
|
int traffic = is.readInt();
|
||||||
if ( traffic == -1 && !includeMotorways )
|
if (traffic == -1 && !includeMotorways) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( isInsideBounds( n1 ) || isInsideBounds( n2 ) )
|
if (isInsideBounds(n1) || isInsideBounds(n2)) {
|
||||||
{
|
if (addElement(n1, n2, traffic)) {
|
||||||
if ( addElement( n1, n2, traffic ) )
|
|
||||||
{
|
|
||||||
trafficElements++;
|
trafficElements++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (EOFException eof) {
|
||||||
|
} finally {
|
||||||
|
is.close();
|
||||||
}
|
}
|
||||||
catch( EOFException eof ) {}
|
|
||||||
finally{ is.close(); }
|
|
||||||
|
|
||||||
map = new FrozenLongMap<OsmTrafficElement>(map);
|
map = new FrozenLongMap<OsmTrafficElement>(map);
|
||||||
System.out.println("read traffic-elements: " + trafficElements);
|
System.out.println("read traffic-elements: " + trafficElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean addElement( long n1, long n2, int traffic )
|
public boolean addElement(long n1, long n2, int traffic) {
|
||||||
{
|
|
||||||
OsmTrafficElement e = getElement(n1, n2);
|
OsmTrafficElement e = getElement(n1, n2);
|
||||||
if ( e == null )
|
if (e == null) {
|
||||||
{
|
|
||||||
e = new OsmTrafficElement();
|
e = new OsmTrafficElement();
|
||||||
e.node2 = n2;
|
e.node2 = n2;
|
||||||
e.traffic = traffic;
|
e.traffic = traffic;
|
||||||
|
|
||||||
OsmTrafficElement e0 = map.get(n1);
|
OsmTrafficElement e0 = map.get(n1);
|
||||||
if ( e0 != null )
|
if (e0 != null) {
|
||||||
{
|
while (e0.next != null) {
|
||||||
while( e0.next != null )
|
|
||||||
{
|
|
||||||
e0 = e0.next;
|
e0 = e0.next;
|
||||||
}
|
}
|
||||||
e0.next = e;
|
e0.next = e;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
map.fastPut(n1, e);
|
map.fastPut(n1, e);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( doNotAdd )
|
if (doNotAdd) {
|
||||||
{
|
|
||||||
e.traffic = Math.max(e.traffic, traffic);
|
e.traffic = Math.max(e.traffic, traffic);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
e.traffic = e.traffic == -1 || traffic == -1 ? -1 : e.traffic + traffic;
|
e.traffic = e.traffic == -1 || traffic == -1 ? -1 : e.traffic + traffic;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInsideBounds( long id )
|
private boolean isInsideBounds(long id) {
|
||||||
{
|
|
||||||
int ilon = (int) (id >> 32);
|
int ilon = (int) (id >> 32);
|
||||||
int ilat = (int) (id & 0xffffffff);
|
int ilat = (int) (id & 0xffffffff);
|
||||||
|
|
||||||
return ilon >= minLon && ilon < maxLon && ilat >= minLat && ilat < maxLat;
|
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
|
// 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;
|
return e == null ? 0 : e.traffic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTrafficClassForTraffic( int traffic )
|
public int getTrafficClassForTraffic(int traffic) {
|
||||||
{
|
|
||||||
if (traffic < 0) return -1;
|
if (traffic < 0) return -1;
|
||||||
if (traffic < 40000) return 0;
|
if (traffic < 40000) return 0;
|
||||||
if (traffic < 80000) return 2;
|
if (traffic < 80000) return 2;
|
||||||
@ -186,8 +162,7 @@ public class OsmTrafficMap
|
|||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTraffic( long n1, long n2 )
|
private int getTraffic(long n1, long n2) {
|
||||||
{
|
|
||||||
OsmTrafficElement e1 = getElement(n1, n2);
|
OsmTrafficElement e1 = getElement(n1, n2);
|
||||||
int traffic1 = e1 == null ? 0 : e1.traffic;
|
int traffic1 = e1 == null ? 0 : e1.traffic;
|
||||||
OsmTrafficElement e2 = getElement(n2, n1);
|
OsmTrafficElement e2 = getElement(n2, n1);
|
||||||
@ -195,17 +170,13 @@ public class OsmTrafficMap
|
|||||||
return traffic1 == -1 || traffic2 == -1 ? -1 : traffic1 > traffic2 ? traffic1 : traffic2;
|
return traffic1 == -1 || traffic2 == -1 ? -1 : traffic1 > traffic2 ? traffic1 : traffic2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void freeze()
|
public void freeze() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private OsmTrafficElement getElement( long n1, long n2 )
|
private OsmTrafficElement getElement(long n1, long n2) {
|
||||||
{
|
|
||||||
OsmTrafficElement e = map.get(n1);
|
OsmTrafficElement e = map.get(n1);
|
||||||
while( e != null )
|
while (e != null) {
|
||||||
{
|
if (e.node2 == n2) {
|
||||||
if ( e.node2 == n2 )
|
|
||||||
{
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
e = e.next;
|
e = e.next;
|
||||||
@ -213,18 +184,15 @@ public class OsmTrafficMap
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmTrafficElement getElement( long n )
|
public OsmTrafficElement getElement(long n) {
|
||||||
{
|
|
||||||
return map.get(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 distance = 0.;
|
||||||
double sum = 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 n1 = linkNodes.get(i);
|
||||||
OsmNodeP n2 = linkNodes.get(i + 1);
|
OsmNodeP n2 = linkNodes.get(i + 1);
|
||||||
int traffic = getTraffic(n1.getIdFromPos(), n2.getIdFromPos());
|
int traffic = getTraffic(n1.getIdFromPos(), n2.getIdFromPos());
|
||||||
@ -233,8 +201,7 @@ public class OsmTrafficMap
|
|||||||
sum += dist * traffic;
|
sum += dist * traffic;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( distance == 0. )
|
if (distance == 0.) {
|
||||||
{
|
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
int traffic = (int) (sum / distance + 0.5);
|
int traffic = (int) (sum / distance + 0.5);
|
||||||
@ -245,30 +212,25 @@ public class OsmTrafficMap
|
|||||||
int trafficClass = getTrafficClassForTraffic(traffic);
|
int trafficClass = getTrafficClassForTraffic(traffic);
|
||||||
|
|
||||||
// delta suppression: keep old traffic classes within some buffer range
|
// delta suppression: keep old traffic classes within some buffer range
|
||||||
if ( oldTrafficClasses != null )
|
if (oldTrafficClasses != null) {
|
||||||
{
|
|
||||||
int oldTrafficClass = oldTrafficClasses.getTrafficClass(id0, id1);
|
int oldTrafficClass = oldTrafficClasses.getTrafficClass(id0, id1);
|
||||||
if ( oldTrafficClass != trafficClass )
|
if (oldTrafficClass != trafficClass) {
|
||||||
{
|
|
||||||
totalChanges++;
|
totalChanges++;
|
||||||
boolean supressChange =
|
boolean supressChange =
|
||||||
oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 1.3))
|
oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 1.3))
|
||||||
|| oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 0.77));
|
|| oldTrafficClass == getTrafficClassForTraffic((int) (traffic * 0.77));
|
||||||
|
|
||||||
if ( debug )
|
if (debug) {
|
||||||
{
|
|
||||||
System.out.println("traffic class change " + oldTrafficClass + "->" + trafficClass + " supress=" + supressChange);
|
System.out.println("traffic class change " + oldTrafficClass + "->" + trafficClass + " supress=" + supressChange);
|
||||||
}
|
}
|
||||||
if ( supressChange )
|
if (supressChange) {
|
||||||
{
|
|
||||||
trafficClass = oldTrafficClass;
|
trafficClass = oldTrafficClass;
|
||||||
supressedChanges++;
|
supressedChanges++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( trafficClass > 0 )
|
if (trafficClass > 0) {
|
||||||
{
|
|
||||||
newTrafficDos.writeLong(id0);
|
newTrafficDos.writeLong(id0);
|
||||||
newTrafficDos.writeLong(id1);
|
newTrafficDos.writeLong(id1);
|
||||||
newTrafficDos.writeInt(trafficClass);
|
newTrafficDos.writeInt(trafficClass);
|
||||||
|
|||||||
@ -14,14 +14,13 @@ import btools.util.FrozenLongSet;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* PosUnifier does 3 steps in map-processing:
|
* PosUnifier does 3 steps in map-processing:
|
||||||
*
|
* <p>
|
||||||
* - unify positions - add srtm elevation data - make a bordernodes file
|
* - unify positions - add srtm elevation data - make a bordernodes file
|
||||||
* containing net data from the bordernids-file just containing ids
|
* containing net data from the bordernids-file just containing ids
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class PosUnifier extends MapCreatorBase
|
public class PosUnifier extends MapCreatorBase {
|
||||||
{
|
|
||||||
private DiffCoderDataOutputStream nodesOutStream;
|
private DiffCoderDataOutputStream nodesOutStream;
|
||||||
private DiffCoderDataOutputStream borderNodesOut;
|
private DiffCoderDataOutputStream borderNodesOut;
|
||||||
private File nodeTilesOut;
|
private File nodeTilesOut;
|
||||||
@ -35,36 +34,29 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
|
|
||||||
private CompactLongSet borderNids;
|
private CompactLongSet borderNids;
|
||||||
|
|
||||||
public static void main( String[] args ) throws Exception
|
public static void main(String[] args) throws Exception {
|
||||||
{
|
|
||||||
System.out.println("*** PosUnifier: Unify position values and enhance elevation");
|
System.out.println("*** PosUnifier: Unify position values and enhance elevation");
|
||||||
if ( args.length != 5 )
|
if (args.length != 5) {
|
||||||
{
|
|
||||||
System.out.println("usage: java PosUnifier <node-tiles-in> <node-tiles-out> <bordernids-in> <bordernodes-out> <srtm-data-dir>");
|
System.out.println("usage: java PosUnifier <node-tiles-in> <node-tiles-out> <bordernids-in> <bordernodes-out> <srtm-data-dir>");
|
||||||
return;
|
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.nodeTilesOut = nodeTilesOut;
|
||||||
this.srtmdir = srtmdir;
|
this.srtmdir = srtmdir;
|
||||||
|
|
||||||
// read border nids set
|
// read border nids set
|
||||||
DataInputStream dis = createInStream(bordernidsinfile);
|
DataInputStream dis = createInStream(bordernidsinfile);
|
||||||
borderNids = new CompactLongSet();
|
borderNids = new CompactLongSet();
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
long nid = readId(dis);
|
long nid = readId(dis);
|
||||||
if (!borderNids.contains(nid))
|
if (!borderNids.contains(nid))
|
||||||
borderNids.fastAdd(nid);
|
borderNids.fastAdd(nid);
|
||||||
}
|
}
|
||||||
}
|
} catch (EOFException eof) {
|
||||||
catch (EOFException eof)
|
|
||||||
{
|
|
||||||
dis.close();
|
dis.close();
|
||||||
}
|
}
|
||||||
borderNids = new FrozenLongSet(borderNids);
|
borderNids = new FrozenLongSet(borderNids);
|
||||||
@ -76,8 +68,7 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nodeFileStart( File nodefile ) throws Exception
|
public void nodeFileStart(File nodefile) throws Exception {
|
||||||
{
|
|
||||||
resetSrtm();
|
resetSrtm();
|
||||||
|
|
||||||
nodesOutStream = createOutStream(fileFromTemplate(nodefile, nodeTilesOut, "u5d"));
|
nodesOutStream = createOutStream(fileFromTemplate(nodefile, nodeTilesOut, "u5d"));
|
||||||
@ -86,37 +77,31 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData n ) throws Exception
|
public void nextNode(NodeData n) throws Exception {
|
||||||
{
|
|
||||||
SrtmRaster srtm = srtmForNode(n.ilon, n.ilat);
|
SrtmRaster srtm = srtmForNode(n.ilon, n.ilat);
|
||||||
n.selev = srtm == null ? Short.MIN_VALUE : srtm.getElevation(n.ilon, n.ilat);
|
n.selev = srtm == null ? Short.MIN_VALUE : srtm.getElevation(n.ilon, n.ilat);
|
||||||
|
|
||||||
findUniquePos(n);
|
findUniquePos(n);
|
||||||
|
|
||||||
n.writeTo(nodesOutStream);
|
n.writeTo(nodesOutStream);
|
||||||
if ( borderNids.contains( n.nid ) )
|
if (borderNids.contains(n.nid)) {
|
||||||
{
|
|
||||||
n.writeTo(borderNodesOut);
|
n.writeTo(borderNodesOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nodeFileEnd( File nodeFile ) throws Exception
|
public void nodeFileEnd(File nodeFile) throws Exception {
|
||||||
{
|
|
||||||
nodesOutStream.close();
|
nodesOutStream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkAdd( int lon, int lat )
|
private boolean checkAdd(int lon, int lat) {
|
||||||
{
|
|
||||||
int slot = ((lon % 5000000) / 100000) * 50 + ((lat % 5000000) / 100000);
|
int slot = ((lon % 5000000) / 100000) * 50 + ((lat % 5000000) / 100000);
|
||||||
long id = ((long) lon) << 32 | lat;
|
long id = ((long) lon) << 32 | lat;
|
||||||
CompactLongSet set = positionSets[slot];
|
CompactLongSet set = positionSets[slot];
|
||||||
if ( set == null )
|
if (set == null) {
|
||||||
{
|
|
||||||
positionSets[slot] = set = new CompactLongSet();
|
positionSets[slot] = set = new CompactLongSet();
|
||||||
}
|
}
|
||||||
if ( !set.contains( id ) )
|
if (!set.contains(id)) {
|
||||||
{
|
|
||||||
set.fastAdd(id);
|
set.fastAdd(id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -124,31 +109,23 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void findUniquePos(NodeData n) {
|
||||||
|
if (!checkAdd(n.ilon, n.ilat)) {
|
||||||
private void findUniquePos( NodeData n )
|
|
||||||
{
|
|
||||||
if ( !checkAdd( n.ilon, n.ilat ) )
|
|
||||||
{
|
|
||||||
_findUniquePos(n);
|
_findUniquePos(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _findUniquePos( NodeData n )
|
private void _findUniquePos(NodeData n) {
|
||||||
{
|
|
||||||
// fix the position for uniqueness
|
// fix the position for uniqueness
|
||||||
int lonmod = n.ilon % 1000000;
|
int lonmod = n.ilon % 1000000;
|
||||||
int londelta = lonmod < 500000 ? 1 : -1;
|
int londelta = lonmod < 500000 ? 1 : -1;
|
||||||
int latmod = n.ilat % 1000000;
|
int latmod = n.ilat % 1000000;
|
||||||
int latdelta = latmod < 500000 ? 1 : -1;
|
int latdelta = latmod < 500000 ? 1 : -1;
|
||||||
for ( int latsteps = 0; latsteps < 100; latsteps++ )
|
for (int latsteps = 0; latsteps < 100; latsteps++) {
|
||||||
{
|
for (int lonsteps = 0; lonsteps <= latsteps; lonsteps++) {
|
||||||
for ( int lonsteps = 0; lonsteps <= latsteps; lonsteps++ )
|
|
||||||
{
|
|
||||||
int lon = n.ilon + lonsteps * londelta;
|
int lon = n.ilon + lonsteps * londelta;
|
||||||
int lat = n.ilat + latsteps * latdelta;
|
int lat = n.ilat + latsteps * latdelta;
|
||||||
if ( checkAdd( lon, lat ) )
|
if (checkAdd(lon, lat)) {
|
||||||
{
|
|
||||||
n.ilon = lon;
|
n.ilon = lon;
|
||||||
n.ilat = lat;
|
n.ilat = lat;
|
||||||
return;
|
return;
|
||||||
@ -162,13 +139,11 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
* get the srtm data set for a position srtm coords are
|
* get the srtm data set for a position srtm coords are
|
||||||
* srtm_<srtmLon>_<srtmLat> where srtmLon = 180 + lon, srtmLat = 60 - lat
|
* srtm_<srtmLon>_<srtmLat> where srtmLon = 180 + lon, srtmLat = 60 - lat
|
||||||
*/
|
*/
|
||||||
private SrtmRaster srtmForNode( int ilon, int ilat ) throws Exception
|
private SrtmRaster srtmForNode(int ilon, int ilat) throws Exception {
|
||||||
{
|
|
||||||
int srtmLonIdx = (ilon + 5000000) / 5000000;
|
int srtmLonIdx = (ilon + 5000000) / 5000000;
|
||||||
int srtmLatIdx = (654999999 - ilat) / 5000000 - 100; // ugly negative rounding...
|
int srtmLatIdx = (654999999 - ilat) / 5000000 - 100; // ugly negative rounding...
|
||||||
|
|
||||||
if ( srtmLonIdx == lastSrtmLonIdx && srtmLatIdx == lastSrtmLatIdx )
|
if (srtmLonIdx == lastSrtmLonIdx && srtmLatIdx == lastSrtmLatIdx) {
|
||||||
{
|
|
||||||
return lastSrtmRaster;
|
return lastSrtmRaster;
|
||||||
}
|
}
|
||||||
lastSrtmLonIdx = srtmLonIdx;
|
lastSrtmLonIdx = srtmLonIdx;
|
||||||
@ -179,21 +154,16 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
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);
|
lastSrtmRaster = srtmmap.get(filename);
|
||||||
if ( lastSrtmRaster == null && !srtmmap.containsKey( filename ) )
|
if (lastSrtmRaster == null && !srtmmap.containsKey(filename)) {
|
||||||
{
|
|
||||||
File f = new File(new File(srtmdir), filename + ".bef");
|
File f = new File(new File(srtmdir), filename + ".bef");
|
||||||
System.out.println("checking: " + f + " ilon=" + ilon + " ilat=" + ilat);
|
System.out.println("checking: " + f + " ilon=" + ilon + " ilat=" + ilat);
|
||||||
if ( f.exists() )
|
if (f.exists()) {
|
||||||
{
|
|
||||||
System.out.println("*** reading: " + f);
|
System.out.println("*** reading: " + f);
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
InputStream isc = new BufferedInputStream(new FileInputStream(f));
|
InputStream isc = new BufferedInputStream(new FileInputStream(f));
|
||||||
lastSrtmRaster = new RasterCoder().decodeRaster(isc);
|
lastSrtmRaster = new RasterCoder().decodeRaster(isc);
|
||||||
isc.close();
|
isc.close();
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
System.out.println("**** ERROR reading " + f + " ****");
|
System.out.println("**** ERROR reading " + f + " ****");
|
||||||
}
|
}
|
||||||
srtmmap.put(filename, lastSrtmRaster);
|
srtmmap.put(filename, lastSrtmRaster);
|
||||||
@ -202,14 +172,10 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
|
|
||||||
f = new File(new File(srtmdir), filename + ".zip");
|
f = new File(new File(srtmdir), filename + ".zip");
|
||||||
System.out.println("reading: " + f + " ilon=" + ilon + " ilat=" + ilat);
|
System.out.println("reading: " + f + " ilon=" + ilon + " ilat=" + ilat);
|
||||||
if ( f.exists() )
|
if (f.exists()) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
lastSrtmRaster = new SrtmData(f).getRaster();
|
lastSrtmRaster = new SrtmData(f).getRaster();
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
System.out.println("**** ERROR reading " + f + " ****");
|
System.out.println("**** ERROR reading " + f + " ****");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,8 +184,7 @@ public class PosUnifier extends MapCreatorBase
|
|||||||
return lastSrtmRaster;
|
return lastSrtmRaster;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetSrtm()
|
private void resetSrtm() {
|
||||||
{
|
|
||||||
srtmmap = new HashMap<String, SrtmRaster>();
|
srtmmap = new HashMap<String, SrtmRaster>();
|
||||||
lastSrtmLonIdx = -1;
|
lastSrtmLonIdx = -1;
|
||||||
lastSrtmLatIdx = -1;
|
lastSrtmLatIdx = -1;
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
package btools.mapcreator;
|
package btools.mapcreator;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import btools.util.*;
|
import btools.util.*;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Encode/decode a raster
|
// Encode/decode a raster
|
||||||
//
|
//
|
||||||
|
|
||||||
public class RasterCoder
|
public class RasterCoder {
|
||||||
{
|
public void encodeRaster(SrtmRaster raster, OutputStream os) throws IOException {
|
||||||
public void encodeRaster(SrtmRaster raster, OutputStream os) throws IOException
|
|
||||||
{
|
|
||||||
DataOutputStream dos = new DataOutputStream(os);
|
DataOutputStream dos = new DataOutputStream(os);
|
||||||
|
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
@ -29,8 +28,7 @@ public class RasterCoder
|
|||||||
System.out.println("finished encoding in " + (t1 - t0) + " ms");
|
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);
|
DataInputStream dis = new DataInputStream(is);
|
||||||
|
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
@ -55,26 +53,20 @@ public class RasterCoder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void _encodeRaster(SrtmRaster raster, OutputStream os) throws IOException
|
private void _encodeRaster(SrtmRaster raster, OutputStream os) throws IOException {
|
||||||
{
|
|
||||||
MixCoderDataOutputStream mco = new MixCoderDataOutputStream(os);
|
MixCoderDataOutputStream mco = new MixCoderDataOutputStream(os);
|
||||||
int nrows = raster.nrows;
|
int nrows = raster.nrows;
|
||||||
int ncols = raster.ncols;
|
int ncols = raster.ncols;
|
||||||
short[] pixels = raster.eval_array;
|
short[] pixels = raster.eval_array;
|
||||||
int colstep = raster.halfcol ? 2 : 1;
|
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
|
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];
|
short val = pixels[row * ncols + col];
|
||||||
if ( val == -32766 )
|
if (val == -32766) {
|
||||||
{
|
|
||||||
val = lastval; // replace remaining (border) skips
|
val = lastval; // replace remaining (border) skips
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
lastval = val;
|
lastval = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,37 +78,30 @@ public class RasterCoder
|
|||||||
mco.flush();
|
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);
|
MixCoderDataInputStream mci = new MixCoderDataInputStream(is);
|
||||||
int nrows = raster.nrows;
|
int nrows = raster.nrows;
|
||||||
int ncols = raster.ncols;
|
int ncols = raster.ncols;
|
||||||
short[] pixels = raster.eval_array;
|
short[] pixels = raster.eval_array;
|
||||||
int colstep = raster.halfcol ? 2 : 1;
|
int colstep = raster.halfcol ? 2 : 1;
|
||||||
|
|
||||||
for (int row = 0; row < nrows; row++)
|
for (int row = 0; row < nrows; row++) {
|
||||||
{
|
for (int col = 0; col < ncols; col += colstep) {
|
||||||
for (int col = 0; col < ncols; col += colstep )
|
|
||||||
{
|
|
||||||
int code = mci.readMixed();
|
int code = mci.readMixed();
|
||||||
|
|
||||||
// remap nodata
|
// remap nodata
|
||||||
int v30 = code == -1 ? Short.MIN_VALUE : (code < 0 ? code + 1 : code);
|
int v30 = code == -1 ? Short.MIN_VALUE : (code < 0 ? code + 1 : code);
|
||||||
if ( raster.usingWeights && v30 > -32766 )
|
if (raster.usingWeights && v30 > -32766) {
|
||||||
{
|
|
||||||
v30 *= 2;
|
v30 *= 2;
|
||||||
}
|
}
|
||||||
pixels[row * ncols + col] = (short) (v30);
|
pixels[row * ncols + col] = (short) (v30);
|
||||||
}
|
}
|
||||||
if ( raster.halfcol )
|
if (raster.halfcol) {
|
||||||
{
|
for (int col = 1; col < ncols - 1; col += colstep) {
|
||||||
for (int col = 1; col < ncols-1; col += colstep )
|
|
||||||
{
|
|
||||||
int l = (int) pixels[row * ncols + col - 1];
|
int l = (int) pixels[row * ncols + col - 1];
|
||||||
int r = (int) pixels[row * ncols + col + 1];
|
int r = (int) pixels[row * ncols + col + 1];
|
||||||
short v30 = Short.MIN_VALUE; // nodata
|
short v30 = Short.MIN_VALUE; // nodata
|
||||||
if ( l > -32766 && r > -32766 )
|
if (l > -32766 && r > -32766) {
|
||||||
{
|
|
||||||
v30 = (short) ((l + r) / 2);
|
v30 = (short) ((l + r) / 2);
|
||||||
}
|
}
|
||||||
pixels[row * ncols + col] = v30;
|
pixels[row * ncols + col] = v30;
|
||||||
|
|||||||
@ -7,20 +7,17 @@ import btools.util.LongList;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class RelationData extends MapCreatorBase
|
public class RelationData extends MapCreatorBase {
|
||||||
{
|
|
||||||
public long rid;
|
public long rid;
|
||||||
public long description;
|
public long description;
|
||||||
public LongList ways;
|
public LongList ways;
|
||||||
|
|
||||||
public RelationData( long id )
|
public RelationData(long id) {
|
||||||
{
|
|
||||||
rid = 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;
|
rid = id;
|
||||||
this.ways = ways;
|
this.ways = ways;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,7 @@ package btools.mapcreator;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public interface RelationListener
|
public interface RelationListener {
|
||||||
{
|
|
||||||
void nextRelation(RelationData data) throws Exception;
|
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;
|
||||||
|
|||||||
@ -13,13 +13,12 @@ import btools.util.FrozenLongSet;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* RelationMerger does 1 step in map processing:
|
* RelationMerger does 1 step in map processing:
|
||||||
*
|
* <p>
|
||||||
* - enrich ways with relation information
|
* - enrich ways with relation information
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class RelationMerger extends MapCreatorBase
|
public class RelationMerger extends MapCreatorBase {
|
||||||
{
|
|
||||||
private HashMap<String, CompactLongSet> routesets;
|
private HashMap<String, CompactLongSet> routesets;
|
||||||
private CompactLongSet routesetall;
|
private CompactLongSet routesetall;
|
||||||
private BExpressionContextWay expctxReport;
|
private BExpressionContextWay expctxReport;
|
||||||
@ -28,11 +27,9 @@ public class RelationMerger extends MapCreatorBase
|
|||||||
|
|
||||||
private DataOutputStream wayOutStream;
|
private DataOutputStream wayOutStream;
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception
|
public static void main(String[] args) throws Exception {
|
||||||
{
|
|
||||||
System.out.println("*** RelationMerger: merge relations into ways");
|
System.out.println("*** RelationMerger: merge relations into ways");
|
||||||
if (args.length != 6)
|
if (args.length != 6) {
|
||||||
{
|
|
||||||
System.out.println("usage: java RelationMerger <way-file-in> <way-file-out> <relation-file> <lookup-file> <report-profile> <check-profile>");
|
System.out.println("usage: java RelationMerger <way-file-in> <way-file-out> <relation-file> <lookup-file> <report-profile> <check-profile>");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -40,8 +37,7 @@ public class RelationMerger extends MapCreatorBase
|
|||||||
new RelationMerger().process(new File(args[0]), new File(args[1]), new File(args[2]), new File(args[3]), new File(args[4]), new File(args[5]));
|
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
|
// read lookup + profile for relation access-check
|
||||||
BExpressionMetaData metaReport = new BExpressionMetaData();
|
BExpressionMetaData metaReport = new BExpressionMetaData();
|
||||||
expctxReport = new BExpressionContextWay(metaReport);
|
expctxReport = new BExpressionContextWay(metaReport);
|
||||||
@ -59,10 +55,8 @@ public class RelationMerger extends MapCreatorBase
|
|||||||
routesets = new HashMap<String, CompactLongSet>();
|
routesets = new HashMap<String, CompactLongSet>();
|
||||||
routesetall = new CompactLongSet();
|
routesetall = new CompactLongSet();
|
||||||
DataInputStream dis = createInStream(relationFileIn);
|
DataInputStream dis = createInStream(relationFileIn);
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
long rid = readId(dis);
|
long rid = readId(dis);
|
||||||
String route = dis.readUTF();
|
String route = dis.readUTF();
|
||||||
String network = dis.readUTF();
|
String network = dis.readUTF();
|
||||||
@ -72,44 +66,36 @@ public class RelationMerger extends MapCreatorBase
|
|||||||
String tagname = "route_" + route + "_" + network;
|
String tagname = "route_" + route + "_" + network;
|
||||||
|
|
||||||
CompactLongSet routeset = null;
|
CompactLongSet routeset = null;
|
||||||
if ( expctxCheck.getLookupNameIdx(tagname) >= 0 )
|
if (expctxCheck.getLookupNameIdx(tagname) >= 0) {
|
||||||
{
|
|
||||||
String key = tagname + "_" + value;
|
String key = tagname + "_" + value;
|
||||||
routeset = routesets.get(key);
|
routeset = routesets.get(key);
|
||||||
if ( routeset == null )
|
if (routeset == null) {
|
||||||
{
|
|
||||||
routeset = new CompactLongSet();
|
routeset = new CompactLongSet();
|
||||||
routesets.put(key, routeset);
|
routesets.put(key, routeset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
long wid = readId(dis);
|
long wid = readId(dis);
|
||||||
if (wid == -1) break;
|
if (wid == -1) break;
|
||||||
// expctxStat.addLookupValue( tagname, "yes", null );
|
// expctxStat.addLookupValue( tagname, "yes", null );
|
||||||
if ( routeset != null && !routeset.contains( wid ) )
|
if (routeset != null && !routeset.contains(wid)) {
|
||||||
{
|
|
||||||
routeset.add(wid);
|
routeset.add(wid);
|
||||||
routesetall.add(wid);
|
routesetall.add(wid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (EOFException eof) {
|
||||||
catch( EOFException eof )
|
|
||||||
{
|
|
||||||
dis.close();
|
dis.close();
|
||||||
}
|
}
|
||||||
for( String key : routesets.keySet() )
|
for (String key : routesets.keySet()) {
|
||||||
{
|
|
||||||
CompactLongSet routeset = new FrozenLongSet(routesets.get(key));
|
CompactLongSet routeset = new FrozenLongSet(routesets.get(key));
|
||||||
routesets.put(key, routeset);
|
routesets.put(key, routeset);
|
||||||
System.out.println("marked " + routeset.size() + " routes for key: " + key);
|
System.out.println("marked " + routeset.size() + " routes for key: " + key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process( File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception
|
public void process(File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile) throws Exception {
|
||||||
{
|
|
||||||
init(relationFileIn, lookupFile, reportProfile, checkProfile);
|
init(relationFileIn, lookupFile, reportProfile, checkProfile);
|
||||||
|
|
||||||
// *** finally process the way-file
|
// *** finally process the way-file
|
||||||
@ -122,31 +108,25 @@ public class RelationMerger extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextWay( WayData data ) throws Exception
|
public void nextWay(WayData data) throws Exception {
|
||||||
{
|
|
||||||
// propagate the route-bits
|
// propagate the route-bits
|
||||||
if ( routesetall.contains( data.wid ) )
|
if (routesetall.contains(data.wid)) {
|
||||||
{
|
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
// check access and log a warning for conflicts
|
// check access and log a warning for conflicts
|
||||||
expctxReport.evaluate(false, data.description);
|
expctxReport.evaluate(false, data.description);
|
||||||
boolean warn = expctxReport.getCostfactor() >= 10000.;
|
boolean warn = expctxReport.getCostfactor() >= 10000.;
|
||||||
if ( warn )
|
if (warn) {
|
||||||
{
|
|
||||||
expctxCheck.evaluate(false, data.description);
|
expctxCheck.evaluate(false, data.description);
|
||||||
ok = expctxCheck.getCostfactor() < 10000.;
|
ok = expctxCheck.getCostfactor() < 10000.;
|
||||||
|
|
||||||
System.out.println("** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription(false, data.description) + " (ok=" + ok + ")");
|
System.out.println("** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription(false, data.description) + " (ok=" + ok + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ok )
|
if (ok) {
|
||||||
{
|
|
||||||
expctxReport.decode(data.description);
|
expctxReport.decode(data.description);
|
||||||
for( String key : routesets.keySet() )
|
for (String key : routesets.keySet()) {
|
||||||
{
|
|
||||||
CompactLongSet routeset = routesets.get(key);
|
CompactLongSet routeset = routesets.get(key);
|
||||||
if ( routeset.contains( data.wid ) )
|
if (routeset.contains(data.wid)) {
|
||||||
{
|
|
||||||
int sepIdx = key.lastIndexOf('_');
|
int sepIdx = key.lastIndexOf('_');
|
||||||
String tagname = key.substring(0, sepIdx);
|
String tagname = key.substring(0, sepIdx);
|
||||||
int val = Integer.valueOf(key.substring(sepIdx + 1));
|
int val = Integer.valueOf(key.substring(sepIdx + 1));
|
||||||
@ -156,8 +136,7 @@ public class RelationMerger extends MapCreatorBase
|
|||||||
data.description = expctxReport.encode();
|
data.description = expctxReport.encode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( wayOutStream != null )
|
if (wayOutStream != null) {
|
||||||
{
|
|
||||||
data.writeTo(wayOutStream);
|
data.writeTo(wayOutStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,19 +10,16 @@ import btools.util.TinyDenseLongMap;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* WayCutter does 2 step in map-processing:
|
* WayCutter does 2 step in map-processing:
|
||||||
*
|
* <p>
|
||||||
* - cut the way file into 45*30 - pieces
|
* - cut the way file into 45*30 - pieces
|
||||||
* - enrich ways with relation information
|
* - enrich ways with relation information
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class RelationStatistics extends MapCreatorBase
|
public class RelationStatistics extends MapCreatorBase {
|
||||||
{
|
public static void main(String[] args) throws Exception {
|
||||||
public static void main(String[] args) throws Exception
|
|
||||||
{
|
|
||||||
System.out.println("*** RelationStatistics: count relation networks");
|
System.out.println("*** RelationStatistics: count relation networks");
|
||||||
if (args.length != 1)
|
if (args.length != 1) {
|
||||||
{
|
|
||||||
System.out.println("usage: java WayCutter <relation-file>");
|
System.out.println("usage: java WayCutter <relation-file>");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -30,41 +27,33 @@ public class RelationStatistics extends MapCreatorBase
|
|||||||
new RelationStatistics().process(new File(args[0]));
|
new RelationStatistics().process(new File(args[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process( File relationFileIn ) throws Exception
|
public void process(File relationFileIn) throws Exception {
|
||||||
{
|
|
||||||
HashMap<String, long[]> relstats = new HashMap<String, long[]>();
|
HashMap<String, long[]> relstats = new HashMap<String, long[]>();
|
||||||
|
|
||||||
DataInputStream dis = createInStream(relationFileIn);
|
DataInputStream dis = createInStream(relationFileIn);
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
long rid = readId(dis);
|
long rid = readId(dis);
|
||||||
String network = dis.readUTF();
|
String network = dis.readUTF();
|
||||||
int waycount = 0;
|
int waycount = 0;
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
long wid = readId(dis);
|
long wid = readId(dis);
|
||||||
if (wid == -1) break;
|
if (wid == -1) break;
|
||||||
waycount++;
|
waycount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
long[] stat = relstats.get(network);
|
long[] stat = relstats.get(network);
|
||||||
if ( stat == null )
|
if (stat == null) {
|
||||||
{
|
|
||||||
stat = new long[2];
|
stat = new long[2];
|
||||||
relstats.put(network, stat);
|
relstats.put(network, stat);
|
||||||
}
|
}
|
||||||
stat[0]++;
|
stat[0]++;
|
||||||
stat[1] += waycount;
|
stat[1] += waycount;
|
||||||
}
|
}
|
||||||
}
|
} catch (EOFException eof) {
|
||||||
catch( EOFException eof )
|
|
||||||
{
|
|
||||||
dis.close();
|
dis.close();
|
||||||
}
|
}
|
||||||
for( String network : relstats.keySet() )
|
for (String network : relstats.keySet()) {
|
||||||
{
|
|
||||||
long[] stat = relstats.get(network);
|
long[] stat = relstats.get(network);
|
||||||
System.out.println("network: " + network + " has " + stat[0] + " relations with " + stat[1] + " ways");
|
System.out.println("network: " + network + " has " + stat[0] + " relations with " + stat[1] + " ways");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,39 +4,33 @@ import java.io.File;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* RestrictionCutter writes Restrictions to tiles
|
* RestrictionCutter writes Restrictions to tiles
|
||||||
*
|
* <p>
|
||||||
* - cut the way file into 45*30 - pieces
|
* - cut the way file into 45*30 - pieces
|
||||||
* - enrich ways with relation information
|
* - enrich ways with relation information
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class RestrictionCutter extends MapCreatorBase
|
public class RestrictionCutter extends MapCreatorBase {
|
||||||
{
|
|
||||||
private WayCutter wayCutter;
|
private WayCutter wayCutter;
|
||||||
|
|
||||||
public void init( File outTileDir, WayCutter wayCutter ) throws Exception
|
public void init(File outTileDir, WayCutter wayCutter) throws Exception {
|
||||||
{
|
|
||||||
outTileDir.mkdir();
|
outTileDir.mkdir();
|
||||||
this.outTileDir = outTileDir;
|
this.outTileDir = outTileDir;
|
||||||
this.wayCutter = wayCutter;
|
this.wayCutter = wayCutter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() throws Exception
|
public void finish() throws Exception {
|
||||||
{
|
|
||||||
closeTileOutStreams();
|
closeTileOutStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void nextRestriction( RestrictionData data ) throws Exception
|
public void nextRestriction(RestrictionData data) throws Exception {
|
||||||
{
|
|
||||||
int tileIndex = wayCutter.getTileIndexForNid(data.viaNid);
|
int tileIndex = wayCutter.getTileIndexForNid(data.viaNid);
|
||||||
if ( tileIndex != -1 )
|
if (tileIndex != -1) {
|
||||||
{
|
|
||||||
data.writeTo(getOutStreamForTile(tileIndex));
|
data.writeTo(getOutStreamForTile(tileIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getNameForTile( int tileIndex )
|
protected String getNameForTile(int tileIndex) {
|
||||||
{
|
|
||||||
String name = wayCutter.getNameForTile(tileIndex);
|
String name = wayCutter.getNameForTile(tileIndex);
|
||||||
return name.substring(0, name.length() - 3) + "rtl";
|
return name.substring(0, name.length() - 3) + "rtl";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,39 +4,33 @@ import java.io.File;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* RestrictionCutter5 does 1 step in map-processing:
|
* RestrictionCutter5 does 1 step in map-processing:
|
||||||
*
|
* <p>
|
||||||
* - cut the 45*30 restriction files into 5*5 pieces
|
* - cut the 45*30 restriction files into 5*5 pieces
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class RestrictionCutter5 extends MapCreatorBase
|
public class RestrictionCutter5 extends MapCreatorBase {
|
||||||
{
|
|
||||||
private WayCutter5 wayCutter5;
|
private WayCutter5 wayCutter5;
|
||||||
|
|
||||||
public void init( File outTileDir, WayCutter5 wayCutter5 ) throws Exception
|
public void init(File outTileDir, WayCutter5 wayCutter5) throws Exception {
|
||||||
{
|
|
||||||
outTileDir.mkdir();
|
outTileDir.mkdir();
|
||||||
this.outTileDir = outTileDir;
|
this.outTileDir = outTileDir;
|
||||||
this.wayCutter5 = wayCutter5;
|
this.wayCutter5 = wayCutter5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() throws Exception
|
public void finish() throws Exception {
|
||||||
{
|
|
||||||
closeTileOutStreams();
|
closeTileOutStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void nextRestriction( RestrictionData data ) throws Exception
|
public void nextRestriction(RestrictionData data) throws Exception {
|
||||||
{
|
|
||||||
int tileIndex = wayCutter5.getTileIndexForNid(data.viaNid);
|
int tileIndex = wayCutter5.getTileIndexForNid(data.viaNid);
|
||||||
if ( tileIndex != -1 )
|
if (tileIndex != -1) {
|
||||||
{
|
|
||||||
data.writeTo(getOutStreamForTile(tileIndex));
|
data.writeTo(getOutStreamForTile(tileIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getNameForTile( int tileIndex )
|
protected String getNameForTile(int tileIndex) {
|
||||||
{
|
|
||||||
String name = wayCutter5.getNameForTile(tileIndex);
|
String name = wayCutter5.getNameForTile(tileIndex);
|
||||||
return name.substring(0, name.length() - 3) + "rt5";
|
return name.substring(0, name.length() - 3) + "rt5";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,7 @@ import btools.util.CheapAngleMeter;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class RestrictionData extends MapCreatorBase
|
public class RestrictionData extends MapCreatorBase {
|
||||||
{
|
|
||||||
public String restrictionKey;
|
public String restrictionKey;
|
||||||
public String restriction;
|
public String restriction;
|
||||||
public short exceptions;
|
public short exceptions;
|
||||||
@ -39,77 +38,58 @@ public class RestrictionData extends MapCreatorBase
|
|||||||
private static HashMap<String, String> names = new HashMap<>();
|
private static HashMap<String, String> names = new HashMap<>();
|
||||||
private static TreeSet<Long> badTRs = new TreeSet<>();
|
private static TreeSet<Long> badTRs = new TreeSet<>();
|
||||||
|
|
||||||
public RestrictionData()
|
public RestrictionData() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPositive()
|
public boolean isPositive() {
|
||||||
{
|
|
||||||
return restriction.startsWith("only_");
|
return restriction.startsWith("only_");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid()
|
public boolean isValid() {
|
||||||
{
|
|
||||||
boolean valid = fromLon != 0 && toLon != 0 && (restriction.startsWith("only_") || restriction.startsWith("no_"));
|
boolean valid = fromLon != 0 && toLon != 0 && (restriction.startsWith("only_") || restriction.startsWith("no_"));
|
||||||
if ( (!valid) || badWayMatch || !(checkGeometry()) )
|
if ((!valid) || badWayMatch || !(checkGeometry())) {
|
||||||
{
|
synchronized (badTRs) {
|
||||||
synchronized( badTRs )
|
|
||||||
{
|
|
||||||
badTRs.add(((long) viaLon) << 32 | viaLat);
|
badTRs.add(((long) viaLon) << 32 | viaLat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return valid && "restriction".equals(restrictionKey);
|
return valid && "restriction".equals(restrictionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkGeometry()
|
private boolean checkGeometry() {
|
||||||
{
|
|
||||||
double a = (new CheapAngleMeter()).calcAngle(fromLon, fromLat, viaLon, viaLat, toLon, toLat);
|
double a = (new CheapAngleMeter()).calcAngle(fromLon, fromLat, viaLon, viaLat, toLon, toLat);
|
||||||
String t;
|
String t;
|
||||||
if ( restriction.startsWith( "only_" ) )
|
if (restriction.startsWith("only_")) {
|
||||||
{
|
|
||||||
t = restriction.substring("only_".length());
|
t = restriction.substring("only_".length());
|
||||||
}
|
} else if (restriction.startsWith("no_")) {
|
||||||
else if ( restriction.startsWith( "no_" ) )
|
|
||||||
{
|
|
||||||
t = restriction.substring("no_".length());
|
t = restriction.substring("no_".length());
|
||||||
}
|
} else throw new RuntimeException("ups");
|
||||||
else throw new RuntimeException( "ups" );
|
|
||||||
|
|
||||||
if ( restrictionKey.endsWith( ":conditional" ) )
|
if (restrictionKey.endsWith(":conditional")) {
|
||||||
{
|
|
||||||
int idx = t.indexOf('@');
|
int idx = t.indexOf('@');
|
||||||
if ( idx >= 0 )
|
if (idx >= 0) {
|
||||||
{
|
|
||||||
t = t.substring(0, idx).trim();
|
t = t.substring(0, idx).trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( "left_turn".equals( t ) )
|
if ("left_turn".equals(t)) {
|
||||||
{
|
|
||||||
return a < -5. && a > -175.;
|
return a < -5. && a > -175.;
|
||||||
}
|
}
|
||||||
if ( "right_turn".equals( t ) )
|
if ("right_turn".equals(t)) {
|
||||||
{
|
|
||||||
return a > 5. && a < 175.;
|
return a > 5. && a < 175.;
|
||||||
}
|
}
|
||||||
if ( "straight_on".equals( t ) )
|
if ("straight_on".equals(t)) {
|
||||||
{
|
|
||||||
return a > -85. && a < 85.;
|
return a > -85. && a < 85.;
|
||||||
}
|
}
|
||||||
if ( "u_turn".equals( t ) )
|
if ("u_turn".equals(t)) {
|
||||||
{
|
|
||||||
return a < -95. || a > 95.;
|
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 )
|
private static String unifyName(String name) {
|
||||||
{
|
synchronized (names) {
|
||||||
synchronized( names )
|
|
||||||
{
|
|
||||||
String n = names.get(name);
|
String n = names.get(name);
|
||||||
if ( n == null )
|
if (n == null) {
|
||||||
{
|
|
||||||
names.put(name, name);
|
names.put(name, name);
|
||||||
n = name;
|
n = name;
|
||||||
}
|
}
|
||||||
@ -117,23 +97,17 @@ public class RestrictionData extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dumpBadTRs()
|
public static void dumpBadTRs() {
|
||||||
{
|
try (BufferedWriter bw = new BufferedWriter(new FileWriter("badtrs.txt"))) {
|
||||||
try( BufferedWriter bw = new BufferedWriter( new FileWriter( "badtrs.txt" ) ) )
|
for (Long id : badTRs) {
|
||||||
{
|
|
||||||
for( Long id : badTRs )
|
|
||||||
{
|
|
||||||
bw.write("" + id + " 26\n");
|
bw.write("" + id + " 26\n");
|
||||||
}
|
}
|
||||||
}
|
} catch (IOException ioe) {
|
||||||
catch( IOException ioe )
|
|
||||||
{
|
|
||||||
throw new RuntimeException(ioe);
|
throw new RuntimeException(ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestrictionData( DataInputStream di ) throws Exception
|
public RestrictionData(DataInputStream di) throws Exception {
|
||||||
{
|
|
||||||
restrictionKey = unifyName(di.readUTF());
|
restrictionKey = unifyName(di.readUTF());
|
||||||
restriction = unifyName(di.readUTF());
|
restriction = unifyName(di.readUTF());
|
||||||
exceptions = di.readShort();
|
exceptions = di.readShort();
|
||||||
@ -142,8 +116,7 @@ public class RestrictionData extends MapCreatorBase
|
|||||||
viaNid = readId(di);
|
viaNid = readId(di);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo( DataOutputStream dos ) throws Exception
|
public void writeTo(DataOutputStream dos) throws Exception {
|
||||||
{
|
|
||||||
dos.writeUTF(restrictionKey);
|
dos.writeUTF(restrictionKey);
|
||||||
dos.writeUTF(restriction);
|
dos.writeUTF(restriction);
|
||||||
dos.writeShort(exceptions);
|
dos.writeShort(exceptions);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package btools.mapcreator;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a wrapper for a 5*5 degree srtm file in ascii/zip-format
|
* 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
|
* - filter out unused nodes according to the way file
|
||||||
* - enhance with SRTM elevation data
|
* - enhance with SRTM elevation data
|
||||||
* - split further in smaller (5*5 degree) tiles
|
* - split further in smaller (5*5 degree) tiles
|
||||||
@ -23,54 +23,42 @@ import java.util.StringTokenizer;
|
|||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
public class SrtmData
|
public class SrtmData {
|
||||||
{
|
|
||||||
private SrtmRaster raster;
|
private SrtmRaster raster;
|
||||||
|
|
||||||
public SrtmData( File file ) throws Exception
|
public SrtmData(File file) throws Exception {
|
||||||
{
|
|
||||||
raster = new SrtmRaster();
|
raster = new SrtmRaster();
|
||||||
|
|
||||||
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
|
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
ZipEntry ze = zis.getNextEntry();
|
ZipEntry ze = zis.getNextEntry();
|
||||||
if ( ze.getName().endsWith( ".asc" ) )
|
if (ze.getName().endsWith(".asc")) {
|
||||||
{
|
|
||||||
readFromStream(zis);
|
readFromStream(zis);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
zis.close();
|
zis.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SrtmRaster getRaster()
|
public SrtmRaster getRaster() {
|
||||||
{
|
|
||||||
return raster;
|
return raster;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String secondToken( String s )
|
private String secondToken(String s) {
|
||||||
{
|
|
||||||
StringTokenizer tk = new StringTokenizer(s, " ");
|
StringTokenizer tk = new StringTokenizer(s, " ");
|
||||||
tk.nextToken();
|
tk.nextToken();
|
||||||
return tk.nextToken();
|
return tk.nextToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readFromStream( InputStream is ) throws Exception
|
public void readFromStream(InputStream is) throws Exception {
|
||||||
{
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||||
int linenr = 0;
|
int linenr = 0;
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
linenr++;
|
linenr++;
|
||||||
if ( linenr <= 6 )
|
if (linenr <= 6) {
|
||||||
{
|
|
||||||
String line = br.readLine();
|
String line = br.readLine();
|
||||||
if (linenr == 1)
|
if (linenr == 1)
|
||||||
raster.ncols = Integer.parseInt(secondToken(line));
|
raster.ncols = Integer.parseInt(secondToken(line));
|
||||||
@ -82,45 +70,35 @@ public class SrtmData
|
|||||||
raster.yllcorner = Double.parseDouble(secondToken(line));
|
raster.yllcorner = Double.parseDouble(secondToken(line));
|
||||||
else if (linenr == 5)
|
else if (linenr == 5)
|
||||||
raster.cellsize = Double.parseDouble(secondToken(line));
|
raster.cellsize = Double.parseDouble(secondToken(line));
|
||||||
else if ( linenr == 6 )
|
else if (linenr == 6) {
|
||||||
{
|
|
||||||
// nodata ignored here ( < -250 assumed nodata... )
|
// nodata ignored here ( < -250 assumed nodata... )
|
||||||
// raster.noDataValue = Short.parseShort( secondToken( line ) );
|
// raster.noDataValue = Short.parseShort( secondToken( line ) );
|
||||||
raster.eval_array = new short[raster.ncols * raster.nrows];
|
raster.eval_array = new short[raster.ncols * raster.nrows];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
int col = 0;
|
int col = 0;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
boolean negative = false;
|
boolean negative = false;
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
int c = br.read();
|
int c = br.read();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
break;
|
break;
|
||||||
if ( c == ' ' )
|
if (c == ' ') {
|
||||||
{
|
|
||||||
if (negative)
|
if (negative)
|
||||||
n = -n;
|
n = -n;
|
||||||
short val = n < -250 ? Short.MIN_VALUE : (short) (n);
|
short val = n < -250 ? Short.MIN_VALUE : (short) (n);
|
||||||
|
|
||||||
raster.eval_array[row * raster.ncols + col] = val;
|
raster.eval_array[row * raster.ncols + col] = val;
|
||||||
if ( ++col == raster.ncols )
|
if (++col == raster.ncols) {
|
||||||
{
|
|
||||||
col = 0;
|
col = 0;
|
||||||
++row;
|
++row;
|
||||||
}
|
}
|
||||||
n = 0;
|
n = 0;
|
||||||
negative = false;
|
negative = false;
|
||||||
}
|
} else if (c >= '0' && c <= '9') {
|
||||||
else if ( c >= '0' && c <= '9' )
|
|
||||||
{
|
|
||||||
n = 10 * n + (c - '0');
|
n = 10 * n + (c - '0');
|
||||||
}
|
} else if (c == '-') {
|
||||||
else if ( c == '-' )
|
|
||||||
{
|
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,16 +108,13 @@ public class SrtmData
|
|||||||
br.close();
|
br.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main( String[] args ) throws Exception
|
public static void main(String[] args) throws Exception {
|
||||||
{
|
|
||||||
String fromDir = args[0];
|
String fromDir = args[0];
|
||||||
String toDir = args[1];
|
String toDir = args[1];
|
||||||
|
|
||||||
File[] files = new File(fromDir).listFiles();
|
File[] files = new File(fromDir).listFiles();
|
||||||
for( File f : files )
|
for (File f : files) {
|
||||||
{
|
if (!f.getName().endsWith(".zip")) {
|
||||||
if ( !f.getName().endsWith( ".zip" ) )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
System.out.println("*** reading: " + f);
|
System.out.println("*** reading: " + f);
|
||||||
@ -171,21 +146,17 @@ public class SrtmData
|
|||||||
String s1 = raster.toString();
|
String s1 = raster.toString();
|
||||||
String s2 = raster2.toString();
|
String s2 = raster2.toString();
|
||||||
|
|
||||||
if ( !s1.equals( s2 ) )
|
if (!s1.equals(s2)) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("missmatch: " + s1 + "<--->" + s2);
|
throw new IllegalArgumentException("missmatch: " + s1 + "<--->" + s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cols = raster.ncols;
|
int cols = raster.ncols;
|
||||||
int rows = raster.nrows;
|
int rows = raster.nrows;
|
||||||
for( int c = 0; c < cols; c++ )
|
for (int c = 0; c < cols; c++) {
|
||||||
{
|
for (int r = 0; r < rows; r++) {
|
||||||
for( int r = 0; r < rows; r++ )
|
|
||||||
{
|
|
||||||
int idx = r * cols + c;
|
int idx = r * cols + c;
|
||||||
|
|
||||||
if ( raster.eval_array[idx] != raster2.eval_array[idx] )
|
if (raster.eval_array[idx] != raster2.eval_array[idx]) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("missmatch: at " + c + "," + r + ": " + raster.eval_array[idx] + "<--->" + raster2.eval_array[idx]);
|
throw new IllegalArgumentException("missmatch: at " + c + "," + r + ": " + raster.eval_array[idx] + "<--->" + raster2.eval_array[idx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,7 @@ import btools.util.ReducedMedianFilter;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class SrtmRaster
|
public class SrtmRaster {
|
||||||
{
|
|
||||||
public int ncols;
|
public int ncols;
|
||||||
public int nrows;
|
public int nrows;
|
||||||
public boolean halfcol;
|
public boolean halfcol;
|
||||||
@ -22,13 +21,11 @@ public class SrtmRaster
|
|||||||
|
|
||||||
private boolean missingData = false;
|
private boolean missingData = false;
|
||||||
|
|
||||||
public short getElevation( int ilon, int ilat )
|
public short getElevation(int ilon, int ilat) {
|
||||||
{
|
|
||||||
double lon = ilon / 1000000. - 180.;
|
double lon = ilon / 1000000. - 180.;
|
||||||
double lat = ilat / 1000000. - 90.;
|
double lat = ilat / 1000000. - 90.;
|
||||||
|
|
||||||
if ( usingWeights )
|
if (usingWeights) {
|
||||||
{
|
|
||||||
return getElevationFromShiftWeights(lon, lat);
|
return getElevationFromShiftWeights(lon, lat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,15 +51,13 @@ public class SrtmRaster
|
|||||||
return missingData ? Short.MIN_VALUE : (short) (eval * 4);
|
return missingData ? Short.MIN_VALUE : (short) (eval * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private short get( int r, int c )
|
private short get(int r, int c) {
|
||||||
{
|
|
||||||
short e = eval_array[(nrows - 1 - r) * ncols + c];
|
short e = eval_array[(nrows - 1 - r) * ncols + c];
|
||||||
if (e == Short.MIN_VALUE) missingData = true;
|
if (e == Short.MIN_VALUE) missingData = true;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
private short getElevationFromShiftWeights( double lon, double lat )
|
private short getElevationFromShiftWeights(double lon, double lat) {
|
||||||
{
|
|
||||||
// calc lat-idx and -weight
|
// calc lat-idx and -weight
|
||||||
double alat = lat < 0. ? -lat : lat;
|
double alat = lat < 0. ? -lat : lat;
|
||||||
alat /= 5.;
|
alat /= 5.;
|
||||||
@ -111,10 +106,8 @@ public class SrtmRaster
|
|||||||
|
|
||||||
private ReducedMedianFilter rmf = new ReducedMedianFilter(256);
|
private ReducedMedianFilter rmf = new ReducedMedianFilter(256);
|
||||||
|
|
||||||
private double getElevation( Weights w, int row, int col )
|
private double getElevation(Weights w, int row, int col) {
|
||||||
{
|
if (missingData) {
|
||||||
if ( missingData )
|
|
||||||
{
|
|
||||||
return 0.;
|
return 0.;
|
||||||
}
|
}
|
||||||
int nx = w.nx;
|
int nx = w.nx;
|
||||||
@ -126,10 +119,8 @@ public class SrtmRaster
|
|||||||
|
|
||||||
rmf.reset();
|
rmf.reset();
|
||||||
|
|
||||||
for( int ix = 0; ix < nx; ix ++ )
|
for (int ix = 0; ix < nx; ix++) {
|
||||||
{
|
for (int iy = 0; iy < ny; iy++) {
|
||||||
for( int iy = 0; iy < ny; iy ++ )
|
|
||||||
{
|
|
||||||
short val = get(row + iy - my, col + ix - mx);
|
short val = get(row + iy - my, col + ix - mx);
|
||||||
rmf.addSample(w.getWeight(ix, iy), val);
|
rmf.addSample(w.getWeight(ix, iy), val);
|
||||||
}
|
}
|
||||||
@ -138,51 +129,42 @@ public class SrtmRaster
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class Weights
|
private static class Weights {
|
||||||
{
|
|
||||||
int nx;
|
int nx;
|
||||||
int ny;
|
int ny;
|
||||||
double[] weights;
|
double[] weights;
|
||||||
long total = 0;
|
long total = 0;
|
||||||
|
|
||||||
Weights( int nx, int ny )
|
Weights(int nx, int ny) {
|
||||||
{
|
|
||||||
this.nx = nx;
|
this.nx = nx;
|
||||||
this.ny = ny;
|
this.ny = ny;
|
||||||
weights = new double[nx * ny];
|
weights = new double[nx * ny];
|
||||||
}
|
}
|
||||||
|
|
||||||
void inc( int ix, int iy )
|
void inc(int ix, int iy) {
|
||||||
{
|
|
||||||
weights[iy * nx + ix] += 1.;
|
weights[iy * nx + ix] += 1.;
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void normalize( boolean verbose )
|
void normalize(boolean verbose) {
|
||||||
{
|
for (int iy = 0; iy < ny; iy++) {
|
||||||
for( int iy =0; iy < ny; iy++ )
|
|
||||||
{
|
|
||||||
StringBuilder sb = verbose ? new StringBuilder() : null;
|
StringBuilder sb = verbose ? new StringBuilder() : null;
|
||||||
for( int ix =0; ix < nx; ix++ )
|
for (int ix = 0; ix < nx; ix++) {
|
||||||
{
|
|
||||||
weights[iy * nx + ix] /= total;
|
weights[iy * nx + ix] /= total;
|
||||||
if ( sb != null )
|
if (sb != null) {
|
||||||
{
|
|
||||||
int iweight = (int) (1000 * weights[iy * nx + ix] + 0.5);
|
int iweight = (int) (1000 * weights[iy * nx + ix] + 0.5);
|
||||||
String sval = " " + iweight;
|
String sval = " " + iweight;
|
||||||
sb.append(sval.substring(sval.length() - 4));
|
sb.append(sval.substring(sval.length() - 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( sb != null )
|
if (sb != null) {
|
||||||
{
|
|
||||||
System.out.println(sb);
|
System.out.println(sb);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double getWeight( int ix, int iy )
|
double getWeight(int ix, int iy) {
|
||||||
{
|
|
||||||
return weights[iy * nx + ix];
|
return weights[iy * nx + ix];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,17 +175,14 @@ public class SrtmRaster
|
|||||||
private static double filterCenterFraction = 0.2;
|
private static double filterCenterFraction = 0.2;
|
||||||
private static double filterDiscRadius = 4.999; // in pixels
|
private static double filterDiscRadius = 4.999; // in pixels
|
||||||
|
|
||||||
static
|
static {
|
||||||
{
|
|
||||||
String sRadius = System.getProperty("filterDiscRadius");
|
String sRadius = System.getProperty("filterDiscRadius");
|
||||||
if ( sRadius != null && sRadius.length() > 0 )
|
if (sRadius != null && sRadius.length() > 0) {
|
||||||
{
|
|
||||||
filterDiscRadius = Integer.parseInt(sRadius);
|
filterDiscRadius = Integer.parseInt(sRadius);
|
||||||
System.out.println("using filterDiscRadius = " + filterDiscRadius);
|
System.out.println("using filterDiscRadius = " + filterDiscRadius);
|
||||||
}
|
}
|
||||||
String sFraction = System.getProperty("filterCenterFraction");
|
String sFraction = System.getProperty("filterCenterFraction");
|
||||||
if ( sFraction != null && sFraction.length() > 0 )
|
if (sFraction != null && sFraction.length() > 0) {
|
||||||
{
|
|
||||||
filterCenterFraction = Integer.parseInt(sFraction) / 100.;
|
filterCenterFraction = Integer.parseInt(sFraction) / 100.;
|
||||||
System.out.println("using filterCenterFraction = " + filterCenterFraction);
|
System.out.println("using filterCenterFraction = " + filterCenterFraction);
|
||||||
}
|
}
|
||||||
@ -213,21 +192,18 @@ public class SrtmRaster
|
|||||||
// calculate interpolation weights from the overlap of a probe disc of given radius at given latitude
|
// calculate interpolation weights from the overlap of a probe disc of given radius at given latitude
|
||||||
// ( latIndex = 0 -> 0 deg, latIndex = 16 -> 80 degree)
|
// ( 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;
|
int idx = latIndex < 16 ? latIndex : 16;
|
||||||
|
|
||||||
Weights[][] res = allShiftWeights[idx];
|
Weights[][] res = allShiftWeights[idx];
|
||||||
if ( res == null )
|
if (res == null) {
|
||||||
{
|
|
||||||
res = calcWeights(idx);
|
res = calcWeights(idx);
|
||||||
allShiftWeights[idx] = res;
|
allShiftWeights[idx] = res;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Weights[][] calcWeights( int latIndex )
|
private static Weights[][] calcWeights(int latIndex) {
|
||||||
{
|
|
||||||
double coslat = Math.cos(latIndex * 5. / 57.3);
|
double coslat = Math.cos(latIndex * 5. / 57.3);
|
||||||
|
|
||||||
// radius in pixel units
|
// radius in pixel units
|
||||||
@ -248,13 +224,11 @@ public class SrtmRaster
|
|||||||
Weights[][] shiftWeights = new Weights[gridSteps + 1][];
|
Weights[][] shiftWeights = new Weights[gridSteps + 1][];
|
||||||
|
|
||||||
// loop the intergrid-position
|
// loop the intergrid-position
|
||||||
for( int gx=0; gx<=gridSteps; gx++ )
|
for (int gx = 0; gx <= gridSteps; gx++) {
|
||||||
{
|
|
||||||
shiftWeights[gx] = new Weights[gridSteps + 1];
|
shiftWeights[gx] = new Weights[gridSteps + 1];
|
||||||
double x0 = mx + ((double) gx) / gridSteps;
|
double x0 = mx + ((double) gx) / gridSteps;
|
||||||
|
|
||||||
for( int gy=0; gy<=gridSteps; gy++ )
|
for (int gy = 0; gy <= gridSteps; gy++) {
|
||||||
{
|
|
||||||
double y0 = my + ((double) gy) / gridSteps;
|
double y0 = my + ((double) gy) / gridSteps;
|
||||||
|
|
||||||
// create the weight-matrix
|
// create the weight-matrix
|
||||||
@ -263,16 +237,13 @@ public class SrtmRaster
|
|||||||
|
|
||||||
double sampleStep = 0.001;
|
double sampleStep = 0.001;
|
||||||
|
|
||||||
for( double x = -1. + sampleStep/2.; x < 1.; x += sampleStep )
|
for (double x = -1. + sampleStep / 2.; x < 1.; x += sampleStep) {
|
||||||
{
|
|
||||||
double mx2 = 1. - x * x;
|
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 )
|
for (double y = -1. + sampleStep / 2.; y < 1.; y += sampleStep) {
|
||||||
{
|
if (y * y > mx2) {
|
||||||
if ( y*y > mx2 )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// we are in the ellipse, see what pixel we are on
|
// we are in the ellipse, see what pixel we are on
|
||||||
@ -287,8 +258,7 @@ public class SrtmRaster
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString() {
|
||||||
{
|
|
||||||
return ncols + "," + nrows + "," + halfcol + "," + xllcorner + "," + yllcorner + "," + cellsize + "," + noDataValue + "," + usingWeights;
|
return ncols + "," + nrows + "," + halfcol + "," + xllcorner + "," + yllcorner + "," + cellsize + "," + noDataValue + "," + usingWeights;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,21 +7,18 @@ import btools.util.TinyDenseLongMap;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* WayCutter does 2 step in map-processing:
|
* WayCutter does 2 step in map-processing:
|
||||||
*
|
* <p>
|
||||||
* - cut the way file into 45*30 - pieces
|
* - cut the way file into 45*30 - pieces
|
||||||
* - enrich ways with relation information
|
* - enrich ways with relation information
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class WayCutter extends MapCreatorBase
|
public class WayCutter extends MapCreatorBase {
|
||||||
{
|
|
||||||
private DenseLongMap tileIndexMap;
|
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");
|
System.out.println("*** WayCutter: Soft-Cut way-data into tiles");
|
||||||
if (args.length != 3)
|
if (args.length != 3) {
|
||||||
{
|
|
||||||
System.out.println("usage: java WayCutter <node-tiles-in> <way-file-in> <way-tiles-out>");
|
System.out.println("usage: java WayCutter <node-tiles-in> <way-file-in> <way-tiles-out>");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -29,8 +26,7 @@ public class WayCutter extends MapCreatorBase
|
|||||||
new WayCutter().process(new File(args[0]), new File(args[1]), new File(args[2]));
|
new WayCutter().process(new File(args[0]), new File(args[1]), new File(args[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process( File nodeTilesIn, File wayFileIn, File wayTilesOut ) throws Exception
|
public void process(File nodeTilesIn, File wayFileIn, File wayTilesOut) throws Exception {
|
||||||
{
|
|
||||||
init(wayTilesOut);
|
init(wayTilesOut);
|
||||||
|
|
||||||
new NodeIterator(this, false).processDir(nodeTilesIn, ".tlf");
|
new NodeIterator(this, false).processDir(nodeTilesIn, ".tlf");
|
||||||
@ -40,46 +36,38 @@ public class WayCutter extends MapCreatorBase
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init( File wayTilesOut ) throws Exception
|
public void init(File wayTilesOut) throws Exception {
|
||||||
{
|
|
||||||
this.outTileDir = wayTilesOut;
|
this.outTileDir = wayTilesOut;
|
||||||
|
|
||||||
// *** read all nodes into tileIndexMap
|
// *** 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();
|
closeTileOutStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData n ) throws Exception
|
public void nextNode(NodeData n) throws Exception {
|
||||||
{
|
|
||||||
tileIndexMap.put(n.nid, getTileIndex(n.ilon, n.ilat));
|
tileIndexMap.put(n.nid, getTileIndex(n.ilon, n.ilat));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextWay( WayData data ) throws Exception
|
public void nextWay(WayData data) throws Exception {
|
||||||
{
|
|
||||||
long waytileset = 0;
|
long waytileset = 0;
|
||||||
int nnodes = data.nodes.size();
|
int nnodes = data.nodes.size();
|
||||||
|
|
||||||
// determine the tile-index for each node
|
// determine the tile-index for each node
|
||||||
for (int i=0; i<nnodes; i++ )
|
for (int i = 0; i < nnodes; i++) {
|
||||||
{
|
|
||||||
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
|
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
|
||||||
if ( tileIndex != -1 )
|
if (tileIndex != -1) {
|
||||||
{
|
|
||||||
waytileset |= (1L << tileIndex);
|
waytileset |= (1L << tileIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now write way to all tiles hit
|
// now write way to all tiles hit
|
||||||
for( int tileIndex=0; tileIndex<54; tileIndex++ )
|
for (int tileIndex = 0; tileIndex < 54; tileIndex++) {
|
||||||
{
|
if ((waytileset & (1L << tileIndex)) == 0) {
|
||||||
if ( ( waytileset & ( 1L << tileIndex ) ) == 0 )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
data.writeTo(getOutStreamForTile(tileIndex));
|
data.writeTo(getOutStreamForTile(tileIndex));
|
||||||
@ -87,21 +75,19 @@ public class WayCutter extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getTileIndexForNid( long nid )
|
public int getTileIndexForNid(long nid) {
|
||||||
{
|
|
||||||
return tileIndexMap.getInt(nid);
|
return tileIndexMap.getInt(nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTileIndex( int ilon, int ilat )
|
private int getTileIndex(int ilon, int ilat) {
|
||||||
{
|
|
||||||
int lon = ilon / 45000000;
|
int lon = ilon / 45000000;
|
||||||
int lat = ilat / 30000000;
|
int lat = ilat / 30000000;
|
||||||
if ( lon < 0 || lon > 7 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
|
if (lon < 0 || lon > 7 || lat < 0 || lat > 5)
|
||||||
|
throw new IllegalArgumentException("illegal pos: " + ilon + "," + ilat);
|
||||||
return lon * 6 + lat;
|
return lon * 6 + lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNameForTile( int tileIndex )
|
public String getNameForTile(int tileIndex) {
|
||||||
{
|
|
||||||
int lon = (tileIndex / 6) * 45 - 180;
|
int lon = (tileIndex / 6) * 45 - 180;
|
||||||
int lat = (tileIndex % 6) * 30 - 90;
|
int lat = (tileIndex % 6) * 30 - 90;
|
||||||
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
||||||
|
|||||||
@ -12,14 +12,13 @@ import btools.util.TinyDenseLongMap;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* WayCutter5 does 2 step in map-processing:
|
* WayCutter5 does 2 step in map-processing:
|
||||||
*
|
* <p>
|
||||||
* - cut the 45*30 way files into 5*5 pieces
|
* - cut the 45*30 way files into 5*5 pieces
|
||||||
* - create a file containing all border node ids
|
* - create a file containing all border node ids
|
||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class WayCutter5 extends MapCreatorBase
|
public class WayCutter5 extends MapCreatorBase {
|
||||||
{
|
|
||||||
private DataOutputStream borderNidsOutStream;
|
private DataOutputStream borderNidsOutStream;
|
||||||
private DenseLongMap tileIndexMap;
|
private DenseLongMap tileIndexMap;
|
||||||
private File nodeTilesIn;
|
private File nodeTilesIn;
|
||||||
@ -31,19 +30,16 @@ public class WayCutter5 extends MapCreatorBase
|
|||||||
public NodeCutter nodeCutter;
|
public NodeCutter nodeCutter;
|
||||||
public RestrictionCutter5 restrictionCutter5;
|
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");
|
System.out.println("*** WayCutter5: Soft-Cut way-data into tiles");
|
||||||
if (args.length != 4)
|
if (args.length != 4) {
|
||||||
{
|
|
||||||
System.out.println("usage: java WayCutter5 <node-tiles-in> <way-tiles-in> <way-tiles-out> <border-nids-out>");
|
System.out.println("usage: java WayCutter5 <node-tiles-in> <way-tiles-in> <way-tiles-out> <border-nids-out>");
|
||||||
return;
|
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.nodeTilesIn = nodeTilesIn;
|
||||||
this.outTileDir = wayTilesOut;
|
this.outTileDir = wayTilesOut;
|
||||||
|
|
||||||
@ -55,8 +51,7 @@ public class WayCutter5 extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean wayFileStart( File wayfile ) throws Exception
|
public boolean wayFileStart(File wayfile) throws Exception {
|
||||||
{
|
|
||||||
// read corresponding node-file into tileIndexMap
|
// read corresponding node-file into tileIndexMap
|
||||||
String name = wayfile.getName();
|
String name = wayfile.getName();
|
||||||
String nodefilename = name.substring(0, name.length() - 3) + "ntl";
|
String nodefilename = name.substring(0, name.length() - 3) + "ntl";
|
||||||
@ -66,33 +61,26 @@ public class WayCutter5 extends MapCreatorBase
|
|||||||
lonoffset = -1;
|
lonoffset = -1;
|
||||||
latoffset = -1;
|
latoffset = -1;
|
||||||
|
|
||||||
if ( nodeCutter != null )
|
if (nodeCutter != null) {
|
||||||
{
|
|
||||||
nodeCutter.nodeFileStart(null);
|
nodeCutter.nodeFileStart(null);
|
||||||
}
|
}
|
||||||
new NodeIterator(this, nodeCutter != null).processFile(nodefile);
|
new NodeIterator(this, nodeCutter != null).processFile(nodefile);
|
||||||
|
|
||||||
if ( restrictionCutter5 != null )
|
if (restrictionCutter5 != null) {
|
||||||
{
|
|
||||||
String resfilename = name.substring(0, name.length() - 3) + "rtl";
|
String resfilename = name.substring(0, name.length() - 3) + "rtl";
|
||||||
File resfile = new File("restrictions", resfilename);
|
File resfile = new File("restrictions", resfilename);
|
||||||
|
|
||||||
if ( resfile.exists() )
|
if (resfile.exists()) {
|
||||||
{
|
|
||||||
// read restrictions for nodes in nodesMap
|
// 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;
|
int ntr = 0;
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
RestrictionData res = new RestrictionData(di);
|
RestrictionData res = new RestrictionData(di);
|
||||||
restrictionCutter5.nextRestriction(res);
|
restrictionCutter5.nextRestriction(res);
|
||||||
ntr++;
|
ntr++;
|
||||||
}
|
}
|
||||||
}
|
} catch (EOFException eof) {
|
||||||
catch( EOFException eof )
|
|
||||||
{
|
|
||||||
di.close();
|
di.close();
|
||||||
}
|
}
|
||||||
System.out.println("read " + ntr + " turn-restrictions");
|
System.out.println("read " + ntr + " turn-restrictions");
|
||||||
@ -102,17 +90,13 @@ public class WayCutter5 extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData n ) throws Exception
|
public void nextNode(NodeData n) throws Exception {
|
||||||
{
|
if (nodeFilter != null) {
|
||||||
if ( nodeFilter != null )
|
if (!nodeFilter.isRelevant(n)) {
|
||||||
{
|
|
||||||
if ( !nodeFilter.isRelevant( n ) )
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( nodeCutter != null )
|
if (nodeCutter != null) {
|
||||||
{
|
|
||||||
nodeCutter.nextNode(n);
|
nodeCutter.nextNode(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,46 +104,37 @@ public class WayCutter5 extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextWay( WayData data ) throws Exception
|
public void nextWay(WayData data) throws Exception {
|
||||||
{
|
|
||||||
long waytileset = 0;
|
long waytileset = 0;
|
||||||
int nnodes = data.nodes.size();
|
int nnodes = data.nodes.size();
|
||||||
int[] tiForNode = new int[nnodes];
|
int[] tiForNode = new int[nnodes];
|
||||||
|
|
||||||
// determine the tile-index for each node
|
// determine the tile-index for each node
|
||||||
for (int i=0; i<nnodes; i++ )
|
for (int i = 0; i < nnodes; i++) {
|
||||||
{
|
|
||||||
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
|
int tileIndex = tileIndexMap.getInt(data.nodes.get(i));
|
||||||
if ( tileIndex != -1 )
|
if (tileIndex != -1) {
|
||||||
{
|
|
||||||
waytileset |= (1L << tileIndex);
|
waytileset |= (1L << tileIndex);
|
||||||
}
|
}
|
||||||
tiForNode[i] = tileIndex;
|
tiForNode[i] = tileIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( relMerger != null )
|
if (relMerger != null) {
|
||||||
{
|
|
||||||
relMerger.nextWay(data);
|
relMerger.nextWay(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now write way to all tiles hit
|
// now write way to all tiles hit
|
||||||
for( int tileIndex=0; tileIndex<54; tileIndex++ )
|
for (int tileIndex = 0; tileIndex < 54; tileIndex++) {
|
||||||
{
|
if ((waytileset & (1L << tileIndex)) == 0) {
|
||||||
if ( ( waytileset & ( 1L << tileIndex ) ) == 0 )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
data.writeTo(getOutStreamForTile(tileIndex));
|
data.writeTo(getOutStreamForTile(tileIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// and write edge nodes to the border-nid file
|
// 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];
|
int ti = tiForNode[i];
|
||||||
if ( ti != -1 )
|
if (ti != -1) {
|
||||||
{
|
if ((i > 0 && tiForNode[i - 1] != ti) || (i + 1 < nnodes && tiForNode[i + 1] != ti)) {
|
||||||
if ( ( i > 0 && tiForNode[i-1] != ti ) || (i+1 < nnodes && tiForNode[i+1] != ti ) )
|
|
||||||
{
|
|
||||||
writeId(borderNidsOutStream, data.nodes.get(i));
|
writeId(borderNidsOutStream, data.nodes.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,26 +142,21 @@ public class WayCutter5 extends MapCreatorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void wayFileEnd( File wayFile ) throws Exception
|
public void wayFileEnd(File wayFile) throws Exception {
|
||||||
{
|
|
||||||
closeTileOutStreams();
|
closeTileOutStreams();
|
||||||
if ( nodeCutter != null )
|
if (nodeCutter != null) {
|
||||||
{
|
|
||||||
nodeCutter.nodeFileEnd(null);
|
nodeCutter.nodeFileEnd(null);
|
||||||
}
|
}
|
||||||
if ( restrictionCutter5 != null )
|
if (restrictionCutter5 != null) {
|
||||||
{
|
|
||||||
restrictionCutter5.finish();
|
restrictionCutter5.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTileIndexForNid( long nid )
|
public int getTileIndexForNid(long nid) {
|
||||||
{
|
|
||||||
return tileIndexMap.getInt(nid);
|
return tileIndexMap.getInt(nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTileIndex( int ilon, int ilat )
|
private int getTileIndex(int ilon, int ilat) {
|
||||||
{
|
|
||||||
int lonoff = (ilon / 45000000) * 45;
|
int lonoff = (ilon / 45000000) * 45;
|
||||||
int latoff = (ilat / 30000000) * 30;
|
int latoff = (ilat / 30000000) * 30;
|
||||||
if (lonoffset == -1) lonoffset = lonoff;
|
if (lonoffset == -1) lonoffset = lonoff;
|
||||||
@ -196,13 +166,13 @@ public class WayCutter5 extends MapCreatorBase
|
|||||||
|
|
||||||
int lon = (ilon / 5000000) % 9;
|
int lon = (ilon / 5000000) % 9;
|
||||||
int lat = (ilat / 5000000) % 6;
|
int lat = (ilat / 5000000) % 6;
|
||||||
if ( lon < 0 || lon > 8 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
|
if (lon < 0 || lon > 8 || lat < 0 || lat > 5)
|
||||||
|
throw new IllegalArgumentException("illegal pos: " + ilon + "," + ilat);
|
||||||
return lon * 6 + lat;
|
return lon * 6 + lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected String getNameForTile( int tileIndex )
|
protected String getNameForTile(int tileIndex) {
|
||||||
{
|
|
||||||
int lon = (tileIndex / 6) * 5 + lonoffset - 180;
|
int lon = (tileIndex / 6) * 5 + lonoffset - 180;
|
||||||
int lat = (tileIndex % 6) * 5 + latoffset - 90;
|
int lat = (tileIndex % 6) * 5 + latoffset - 90;
|
||||||
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
||||||
|
|||||||
@ -10,44 +10,40 @@ import btools.util.LongList;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class WayData extends MapCreatorBase
|
public class WayData extends MapCreatorBase {
|
||||||
{
|
|
||||||
public long wid;
|
public long wid;
|
||||||
public byte[] description;
|
public byte[] description;
|
||||||
public LongList nodes;
|
public LongList nodes;
|
||||||
|
|
||||||
public WayData( long id )
|
public WayData(long id) {
|
||||||
{
|
|
||||||
wid = 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;
|
wid = id;
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WayData( DataInputStream di ) throws Exception
|
public WayData(DataInputStream di) throws Exception {
|
||||||
{
|
|
||||||
nodes = new LongList(16);
|
nodes = new LongList(16);
|
||||||
wid = readId(di);
|
wid = readId(di);
|
||||||
int dlen = di.readByte(); description = new byte[dlen]; di.readFully( description );
|
int dlen = di.readByte();
|
||||||
for (;;)
|
description = new byte[dlen];
|
||||||
{
|
di.readFully(description);
|
||||||
|
for (; ; ) {
|
||||||
long nid = readId(di);
|
long nid = readId(di);
|
||||||
if (nid == -1) break;
|
if (nid == -1) break;
|
||||||
nodes.add(nid);
|
nodes.add(nid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo( DataOutputStream dos ) throws Exception
|
public void writeTo(DataOutputStream dos) throws Exception {
|
||||||
{
|
|
||||||
writeId(dos, wid);
|
writeId(dos, wid);
|
||||||
dos.writeByte( description.length ); dos.write( description );
|
dos.writeByte(description.length);
|
||||||
|
dos.write(description);
|
||||||
int size = nodes.size();
|
int size = nodes.size();
|
||||||
for( int i=0; i < size; i++ )
|
for (int i = 0; i < size; i++) {
|
||||||
{
|
|
||||||
writeId(dos, nodes.get(i));
|
writeId(dos, nodes.get(i));
|
||||||
}
|
}
|
||||||
writeId(dos, -1); // stopbyte
|
writeId(dos, -1); // stopbyte
|
||||||
|
|||||||
@ -12,68 +12,54 @@ import java.io.FileInputStream;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class WayIterator extends MapCreatorBase
|
public class WayIterator extends MapCreatorBase {
|
||||||
{
|
|
||||||
private WayListener listener;
|
private WayListener listener;
|
||||||
private boolean delete;
|
private boolean delete;
|
||||||
private boolean descendingSize;
|
private boolean descendingSize;
|
||||||
|
|
||||||
public WayIterator( WayListener wayListener, boolean deleteAfterReading )
|
public WayIterator(WayListener wayListener, boolean deleteAfterReading) {
|
||||||
{
|
|
||||||
listener = wayListener;
|
listener = wayListener;
|
||||||
delete = deleteAfterReading;
|
delete = deleteAfterReading;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WayIterator( WayListener wayListener, boolean deleteAfterReading, boolean descendingSize )
|
public WayIterator(WayListener wayListener, boolean deleteAfterReading, boolean descendingSize) {
|
||||||
{
|
|
||||||
this(wayListener, deleteAfterReading);
|
this(wayListener, deleteAfterReading);
|
||||||
this.descendingSize = descendingSize;
|
this.descendingSize = descendingSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processDir( File indir, String inSuffix ) throws Exception
|
public void processDir(File indir, String inSuffix) throws Exception {
|
||||||
{
|
if (!indir.isDirectory()) {
|
||||||
if ( !indir.isDirectory() )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("not a directory: " + indir);
|
throw new IllegalArgumentException("not a directory: " + indir);
|
||||||
}
|
}
|
||||||
|
|
||||||
File[] af = sortBySizeAsc(indir.listFiles());
|
File[] af = sortBySizeAsc(indir.listFiles());
|
||||||
for( int i=0; i<af.length; i++ )
|
for (int i = 0; i < af.length; i++) {
|
||||||
{
|
|
||||||
File wayfile = descendingSize ? af[af.length - 1 - i] : af[i];
|
File wayfile = descendingSize ? af[af.length - 1 - i] : af[i];
|
||||||
if ( wayfile.getName().endsWith( inSuffix ) )
|
if (wayfile.getName().endsWith(inSuffix)) {
|
||||||
{
|
|
||||||
processFile(wayfile);
|
processFile(wayfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void processFile(File wayfile) throws Exception
|
public void processFile(File wayfile) throws Exception {
|
||||||
{
|
|
||||||
System.out.println("*** WayIterator reading: " + wayfile);
|
System.out.println("*** WayIterator reading: " + wayfile);
|
||||||
|
|
||||||
if ( !listener.wayFileStart( wayfile ) )
|
if (!listener.wayFileStart(wayfile)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(wayfile)));
|
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(wayfile)));
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
WayData w = new WayData(di);
|
WayData w = new WayData(di);
|
||||||
listener.nextWay(w);
|
listener.nextWay(w);
|
||||||
}
|
}
|
||||||
}
|
} catch (EOFException eof) {
|
||||||
catch( EOFException eof )
|
|
||||||
{
|
|
||||||
di.close();
|
di.close();
|
||||||
}
|
}
|
||||||
listener.wayFileEnd(wayfile);
|
listener.wayFileEnd(wayfile);
|
||||||
if ( delete && "true".equals( System.getProperty( "deletetmpfiles" ) ))
|
if (delete && "true".equals(System.getProperty("deletetmpfiles"))) {
|
||||||
{
|
|
||||||
wayfile.delete();
|
wayfile.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,8 +32,7 @@ import btools.util.LazyArrayOfLists;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public class WayLinker extends MapCreatorBase implements Runnable
|
public class WayLinker extends MapCreatorBase implements Runnable {
|
||||||
{
|
|
||||||
private File nodeTilesIn;
|
private File nodeTilesIn;
|
||||||
private File wayTilesIn;
|
private File wayTilesIn;
|
||||||
private File trafficTilesIn;
|
private File trafficTilesIn;
|
||||||
@ -70,43 +69,33 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
private boolean isSlave;
|
private boolean isSlave;
|
||||||
private ThreadController tc;
|
private ThreadController tc;
|
||||||
|
|
||||||
public static final class ThreadController
|
public static final class ThreadController {
|
||||||
{
|
|
||||||
long maxFileSize = 0L;
|
long maxFileSize = 0L;
|
||||||
long currentSlaveSize;
|
long currentSlaveSize;
|
||||||
long currentMasterSize = 2000000000L;
|
long currentMasterSize = 2000000000L;
|
||||||
|
|
||||||
synchronized boolean setCurrentMasterSize( long size )
|
synchronized boolean setCurrentMasterSize(long size) {
|
||||||
{
|
try {
|
||||||
try
|
if (size <= currentSlaveSize) {
|
||||||
{
|
|
||||||
if ( size <= currentSlaveSize )
|
|
||||||
{
|
|
||||||
maxFileSize = Long.MAX_VALUE;
|
maxFileSize = Long.MAX_VALUE;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
currentMasterSize = size;
|
currentMasterSize = size;
|
||||||
if ( maxFileSize == 0L )
|
if (maxFileSize == 0L) {
|
||||||
{
|
|
||||||
maxFileSize = size;
|
maxFileSize = size;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
notify();
|
notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized boolean setCurrentSlaveSize( long size ) throws Exception
|
synchronized boolean setCurrentSlaveSize(long size) throws Exception {
|
||||||
{
|
if (size >= currentMasterSize) {
|
||||||
if ( size >= currentMasterSize )
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( size + currentMasterSize + 50000000L > maxFileSize )
|
while (size + currentMasterSize + 50000000L > maxFileSize) {
|
||||||
{
|
|
||||||
System.out.println("****** slave thread waiting for permission to process file of size " + size
|
System.out.println("****** slave thread waiting for permission to process file of size " + size
|
||||||
+ " currentMaster=" + currentMasterSize + " maxFileSize=" + maxFileSize);
|
+ " currentMaster=" + currentMasterSize + " maxFileSize=" + maxFileSize);
|
||||||
wait(10000);
|
wait(10000);
|
||||||
@ -117,20 +106,16 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void reset() {
|
||||||
private void reset()
|
|
||||||
{
|
|
||||||
minLon = -1;
|
minLon = -1;
|
||||||
minLat = -1;
|
minLat = -1;
|
||||||
nodesMap = new CompactLongMap<OsmNodeP>();
|
nodesMap = new CompactLongMap<OsmNodeP>();
|
||||||
borderSet = new CompactLongSet();
|
borderSet = new CompactLongSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main( String[] args ) throws Exception
|
public static void main(String[] args) throws Exception {
|
||||||
{
|
|
||||||
System.out.println("*** WayLinker: Format a region of an OSM map for routing");
|
System.out.println("*** WayLinker: Format a region of an OSM map for routing");
|
||||||
if ( args.length != 8 )
|
if (args.length != 8) {
|
||||||
{
|
|
||||||
System.out
|
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;
|
return;
|
||||||
@ -144,8 +129,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
|
public void process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
|
||||||
String dataTilesSuffix ) throws Exception
|
String dataTilesSuffix) throws Exception {
|
||||||
{
|
|
||||||
WayLinker master = new WayLinker();
|
WayLinker master = new WayLinker();
|
||||||
WayLinker slave = new WayLinker();
|
WayLinker slave = new WayLinker();
|
||||||
slave.isSlave = true;
|
slave.isSlave = true;
|
||||||
@ -167,8 +151,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void _process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
|
private void _process(File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut,
|
||||||
String dataTilesSuffix ) throws Exception
|
String dataTilesSuffix) throws Exception {
|
||||||
{
|
|
||||||
this.nodeTilesIn = nodeTilesIn;
|
this.nodeTilesIn = nodeTilesIn;
|
||||||
this.wayTilesIn = wayTilesIn;
|
this.wayTilesIn = wayTilesIn;
|
||||||
this.trafficTilesIn = new File("../traffic");
|
this.trafficTilesIn = new File("../traffic");
|
||||||
@ -197,30 +180,22 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run() {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
// then process all segments
|
// then process all segments
|
||||||
new WayIterator(this, true, !isSlave).processDir(wayTilesIn, ".wt5");
|
new WayIterator(this, true, !isSlave).processDir(wayTilesIn, ".wt5");
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch( Exception e )
|
|
||||||
{
|
|
||||||
System.out.println("******* thread (slave=" + isSlave + ") got Exception: " + e);
|
System.out.println("******* thread (slave=" + isSlave + ") got Exception: " + e);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
} finally {
|
||||||
finally
|
if (!isSlave) {
|
||||||
{
|
|
||||||
if (!isSlave)
|
|
||||||
{
|
|
||||||
tc.setCurrentMasterSize(0L);
|
tc.setCurrentMasterSize(0L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean wayFileStart( File wayfile ) throws Exception
|
public boolean wayFileStart(File wayfile) throws Exception {
|
||||||
{
|
|
||||||
|
|
||||||
// master/slave logic:
|
// master/slave logic:
|
||||||
// total memory size should stay below a maximum
|
// total memory size should stay below a maximum
|
||||||
@ -230,31 +205,22 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
|
|
||||||
System.out.println("**** wayFileStart() for isSlave=" + isSlave + " size=" + filesize);
|
System.out.println("**** wayFileStart() for isSlave=" + isSlave + " size=" + filesize);
|
||||||
|
|
||||||
if ( isSlave )
|
if (isSlave) {
|
||||||
{
|
if (!tc.setCurrentSlaveSize(filesize)) {
|
||||||
if ( !tc.setCurrentSlaveSize( filesize ) )
|
return false;
|
||||||
{
|
}
|
||||||
|
} else {
|
||||||
|
if (!tc.setCurrentMasterSize(filesize)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
// process corresponding node-file, if any
|
||||||
File nodeFile = fileFromTemplate(wayfile, nodeTilesIn, "u5d");
|
File nodeFile = fileFromTemplate(wayfile, nodeTilesIn, "u5d");
|
||||||
if ( nodeFile.exists() )
|
if (nodeFile.exists()) {
|
||||||
{
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
// read the border file
|
// read the border file
|
||||||
@ -272,20 +238,15 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
|
|
||||||
File restrictionFile = fileFromTemplate(wayfile, new File(nodeTilesIn.getParentFile(), "restrictions55"), "rt5");
|
File restrictionFile = fileFromTemplate(wayfile, new File(nodeTilesIn.getParentFile(), "restrictions55"), "rt5");
|
||||||
// read restrictions for nodes in nodesMap
|
// read restrictions for nodes in nodesMap
|
||||||
if ( restrictionFile.exists() )
|
if (restrictionFile.exists()) {
|
||||||
{
|
|
||||||
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(restrictionFile)));
|
DataInputStream di = new DataInputStream(new BufferedInputStream(new FileInputStream(restrictionFile)));
|
||||||
int ntr = 0;
|
int ntr = 0;
|
||||||
try
|
try {
|
||||||
{
|
for (; ; ) {
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
RestrictionData res = new RestrictionData(di);
|
RestrictionData res = new RestrictionData(di);
|
||||||
OsmNodeP n = nodesMap.get(res.viaNid);
|
OsmNodeP n = nodesMap.get(res.viaNid);
|
||||||
if ( n != null )
|
if (n != null) {
|
||||||
{
|
if (!(n instanceof OsmNodePT)) {
|
||||||
if ( ! ( n instanceof OsmNodePT ) )
|
|
||||||
{
|
|
||||||
n = new OsmNodePT(n);
|
n = new OsmNodePT(n);
|
||||||
nodesMap.put(res.viaNid, n);
|
nodesMap.put(res.viaNid, n);
|
||||||
}
|
}
|
||||||
@ -297,9 +258,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
ntr++;
|
ntr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (EOFException eof) {
|
||||||
catch( EOFException eof )
|
|
||||||
{
|
|
||||||
di.close();
|
di.close();
|
||||||
}
|
}
|
||||||
System.out.println("read " + ntr + " turn-restrictions");
|
System.out.println("read " + ntr + " turn-restrictions");
|
||||||
@ -309,8 +268,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read a traffic-file, if any
|
// read a traffic-file, if any
|
||||||
if ( trafficFile.exists() )
|
if (trafficFile.exists()) {
|
||||||
{
|
|
||||||
trafficMap = new OsmTrafficMap(expctxWay);
|
trafficMap = new OsmTrafficMap(expctxWay);
|
||||||
trafficMap.loadAll(trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false);
|
trafficMap.loadAll(trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false);
|
||||||
}
|
}
|
||||||
@ -318,20 +276,17 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextNode( NodeData data ) throws Exception
|
public void nextNode(NodeData data) throws Exception {
|
||||||
{
|
|
||||||
OsmNodeP n = data.description == null ? new OsmNodeP() : new OsmNodePT(data.description);
|
OsmNodeP n = data.description == null ? new OsmNodeP() : new OsmNodePT(data.description);
|
||||||
n.ilon = data.ilon;
|
n.ilon = data.ilon;
|
||||||
n.ilat = data.ilat;
|
n.ilat = data.ilat;
|
||||||
n.selev = data.selev;
|
n.selev = data.selev;
|
||||||
|
|
||||||
if ( readingBorder || ( !borderSet.contains( data.nid ) ) )
|
if (readingBorder || (!borderSet.contains(data.nid))) {
|
||||||
{
|
|
||||||
nodesMap.fastPut(data.nid, n);
|
nodesMap.fastPut(data.nid, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( readingBorder )
|
if (readingBorder) {
|
||||||
{
|
|
||||||
n.bits |= OsmNodeP.BORDER_BIT;
|
n.bits |= OsmNodeP.BORDER_BIT;
|
||||||
borderSet.fastAdd(data.nid);
|
borderSet.fastAdd(data.nid);
|
||||||
return;
|
return;
|
||||||
@ -354,39 +309,30 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
// starts or ends at it's via node. However, we allow
|
// starts or ends at it's via node. However, we allow
|
||||||
// ways not ending at the via node, and in this case we take
|
// ways not ending at the via node, and in this case we take
|
||||||
// the leg according to the mapped direction
|
// the leg according to the mapped direction
|
||||||
private void checkRestriction( OsmNodeP n1, OsmNodeP n2, WayData w )
|
private void checkRestriction(OsmNodeP n1, OsmNodeP n2, WayData w) {
|
||||||
{
|
|
||||||
checkRestriction(n1, n2, w, true);
|
checkRestriction(n1, n2, w, true);
|
||||||
checkRestriction(n2, n1, w, false);
|
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();
|
RestrictionData r = n2.getFirstRestriction();
|
||||||
while ( r != null )
|
while (r != null) {
|
||||||
{
|
if (r.fromWid == w.wid) {
|
||||||
if ( r.fromWid == w.wid )
|
if (r.fromLon == 0 || checkFrom) {
|
||||||
{
|
|
||||||
if ( r.fromLon == 0 || checkFrom )
|
|
||||||
{
|
|
||||||
r.fromLon = n1.ilon;
|
r.fromLon = n1.ilon;
|
||||||
r.fromLat = n1.ilat;
|
r.fromLat = n1.ilat;
|
||||||
n1.bits |= OsmNodeP.DP_SURVIVOR_BIT;
|
n1.bits |= OsmNodeP.DP_SURVIVOR_BIT;
|
||||||
if ( !isEndNode( n2, w ) )
|
if (!isEndNode(n2, w)) {
|
||||||
{
|
|
||||||
r.badWayMatch = true;
|
r.badWayMatch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( r.toWid == w.wid )
|
if (r.toWid == w.wid) {
|
||||||
{
|
if (r.toLon == 0 || !checkFrom) {
|
||||||
if ( r.toLon == 0 || !checkFrom )
|
|
||||||
{
|
|
||||||
r.toLon = n1.ilon;
|
r.toLon = n1.ilon;
|
||||||
r.toLat = n1.ilat;
|
r.toLat = n1.ilat;
|
||||||
n1.bits |= OsmNodeP.DP_SURVIVOR_BIT;
|
n1.bits |= OsmNodeP.DP_SURVIVOR_BIT;
|
||||||
if ( !isEndNode( n2, w ) )
|
if (!isEndNode(n2, w)) {
|
||||||
{
|
|
||||||
r.badWayMatch = true;
|
r.badWayMatch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -395,14 +341,12 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEndNode( OsmNodeP n, WayData w )
|
private boolean isEndNode(OsmNodeP n, WayData w) {
|
||||||
{
|
|
||||||
return n == nodesMap.get(w.nodes.get(0)) || n == nodesMap.get(w.nodes.get(w.nodes.size() - 1));
|
return n == nodesMap.get(w.nodes.get(0)) || n == nodesMap.get(w.nodes.get(w.nodes.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextWay( WayData way ) throws Exception
|
public void nextWay(WayData way) throws Exception {
|
||||||
{
|
|
||||||
byte[] description = abUnifier.unify(way.description);
|
byte[] description = abUnifier.unify(way.description);
|
||||||
|
|
||||||
// filter according to profile
|
// filter according to profile
|
||||||
@ -422,28 +366,24 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
|
|
||||||
OsmNodeP n1 = null;
|
OsmNodeP n1 = null;
|
||||||
OsmNodeP n2 = null;
|
OsmNodeP n2 = null;
|
||||||
for ( int i = 0; i < way.nodes.size(); i++ )
|
for (int i = 0; i < way.nodes.size(); i++) {
|
||||||
{
|
|
||||||
long nid = way.nodes.get(i);
|
long nid = way.nodes.get(i);
|
||||||
n1 = n2;
|
n1 = n2;
|
||||||
n2 = nodesMap.get(nid);
|
n2 = nodesMap.get(nid);
|
||||||
|
|
||||||
if ( n1 != null && n2 != null && n1 != n2 )
|
if (n1 != null && n2 != null && n1 != n2) {
|
||||||
{
|
|
||||||
checkRestriction(n1, n2, way);
|
checkRestriction(n1, n2, way);
|
||||||
|
|
||||||
OsmLinkP link = n2.createLink(n1);
|
OsmLinkP link = n2.createLink(n1);
|
||||||
|
|
||||||
link.descriptionBitmap = description;
|
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
|
n2.incWayCount(); // force first node after cell-change to be a
|
||||||
// network node
|
// network node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( n2 != null )
|
if (n2 != null) {
|
||||||
{
|
|
||||||
n2.bits |= wayBits;
|
n2.bits |= wayBits;
|
||||||
n2.incWayCount();
|
n2.incWayCount();
|
||||||
}
|
}
|
||||||
@ -451,8 +391,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void wayFileEnd( File wayfile ) throws Exception
|
public void wayFileEnd(File wayfile) throws Exception {
|
||||||
{
|
|
||||||
int ncaches = divisor * divisor;
|
int ncaches = divisor * divisor;
|
||||||
int indexsize = ncaches * 4;
|
int indexsize = ncaches * 4;
|
||||||
|
|
||||||
@ -466,8 +405,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
int maxLat = minLat + 5000000;
|
int maxLat = minLat + 5000000;
|
||||||
|
|
||||||
// cleanup duplicate targets
|
// cleanup duplicate targets
|
||||||
for ( OsmNodeP n : nodesList )
|
for (OsmNodeP n : nodesList) {
|
||||||
{
|
|
||||||
if (n == null || n.getFirstLink() == null || n.isTransferNode())
|
if (n == null || n.getFirstLink() == null || n.isTransferNode())
|
||||||
continue;
|
continue;
|
||||||
n.checkDuplicateTargets();
|
n.checkDuplicateTargets();
|
||||||
@ -480,8 +418,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
|
|
||||||
// sort the nodes into segments
|
// sort the nodes into segments
|
||||||
LazyArrayOfLists<OsmNodeP> seglists = new LazyArrayOfLists<OsmNodeP>(nLonSegs * nLatSegs);
|
LazyArrayOfLists<OsmNodeP> seglists = new LazyArrayOfLists<OsmNodeP>(nLonSegs * nLatSegs);
|
||||||
for ( OsmNodeP n : nodesList )
|
for (OsmNodeP n : nodesList) {
|
||||||
{
|
|
||||||
if (n == null || n.getFirstLink() == null || n.isTransferNode())
|
if (n == null || n.getFirstLink() == null || n.isTransferNode())
|
||||||
continue;
|
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)
|
||||||
@ -503,26 +440,21 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
int[] fileHeaderCrcs = new int[25];
|
int[] fileHeaderCrcs = new int[25];
|
||||||
|
|
||||||
// write 5*5 index dummy
|
// write 5*5 index dummy
|
||||||
for ( int i55 = 0; i55 < 25; i55++ )
|
for (int i55 = 0; i55 < 25; i55++) {
|
||||||
{
|
|
||||||
os.writeLong(0);
|
os.writeLong(0);
|
||||||
}
|
}
|
||||||
long filepos = 200L;
|
long filepos = 200L;
|
||||||
|
|
||||||
// sort further in 1/divisor-degree squares
|
// sort further in 1/divisor-degree squares
|
||||||
for ( int lonIdx = 0; lonIdx < nLonSegs; lonIdx++ )
|
for (int lonIdx = 0; lonIdx < nLonSegs; lonIdx++) {
|
||||||
{
|
for (int latIdx = 0; latIdx < nLatSegs; latIdx++) {
|
||||||
for ( int latIdx = 0; latIdx < nLatSegs; latIdx++ )
|
|
||||||
{
|
|
||||||
int tileIndex = lonIdx * nLatSegs + latIdx;
|
int tileIndex = lonIdx * nLatSegs + latIdx;
|
||||||
if ( seglists.getSize( tileIndex ) > 0 )
|
if (seglists.getSize(tileIndex) > 0) {
|
||||||
{
|
|
||||||
List<OsmNodeP> nlist = seglists.getList(tileIndex);
|
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][];
|
byte[][] subByteArrays = new byte[ncaches][];
|
||||||
for ( int ni = 0; ni < nlist.size(); ni++ )
|
for (int ni = 0; ni < nlist.size(); ni++) {
|
||||||
{
|
|
||||||
OsmNodeP n = nlist.get(ni);
|
OsmNodeP n = nlist.get(ni);
|
||||||
int subLonIdx = (n.ilon - minLon) / cellsize - divisor * lonIdx;
|
int subLonIdx = (n.ilon - minLon) / cellsize - divisor * lonIdx;
|
||||||
int subLatIdx = (n.ilat - minLat) / cellsize - divisor * latIdx;
|
int subLatIdx = (n.ilat - minLat) / cellsize - divisor * latIdx;
|
||||||
@ -533,12 +465,10 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
int[] posIdx = new int[ncaches];
|
int[] posIdx = new int[ncaches];
|
||||||
int pos = indexsize;
|
int pos = indexsize;
|
||||||
|
|
||||||
for ( int si = 0; si < ncaches; si++ )
|
for (int si = 0; si < ncaches; si++) {
|
||||||
{
|
|
||||||
List<OsmNodeP> subList = subs.getList(si);
|
List<OsmNodeP> subList = subs.getList(si);
|
||||||
int size = subList.size();
|
int size = subList.size();
|
||||||
if ( size > 0 )
|
if (size > 0) {
|
||||||
{
|
|
||||||
OsmNodeP n0 = subList.get(0);
|
OsmNodeP n0 = subList.get(0);
|
||||||
int lonIdxDiv = n0.ilon / cellsize;
|
int lonIdxDiv = n0.ilon / cellsize;
|
||||||
int latIdxDiv = n0.ilat / cellsize;
|
int latIdxDiv = n0.ilat / cellsize;
|
||||||
@ -546,46 +476,38 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
|
|
||||||
// sort via treemap
|
// sort via treemap
|
||||||
TreeMap<Integer, OsmNodeP> sortedList = new TreeMap<Integer, OsmNodeP>();
|
TreeMap<Integer, OsmNodeP> sortedList = new TreeMap<Integer, OsmNodeP>();
|
||||||
for ( OsmNodeP n : subList )
|
for (OsmNodeP n : subList) {
|
||||||
{
|
|
||||||
long longId = n.getIdFromPos();
|
long longId = n.getIdFromPos();
|
||||||
int shrinkid = mc.shrinkId(longId);
|
int shrinkid = mc.shrinkId(longId);
|
||||||
if ( mc.expandId( shrinkid ) != longId )
|
if (mc.expandId(shrinkid) != longId) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("inconstistent shrinking: " + longId);
|
throw new IllegalArgumentException("inconstistent shrinking: " + longId);
|
||||||
}
|
}
|
||||||
sortedList.put(Integer.valueOf(shrinkid), n);
|
sortedList.put(Integer.valueOf(shrinkid), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( OsmNodeP n : sortedList.values() )
|
for (OsmNodeP n : sortedList.values()) {
|
||||||
{
|
|
||||||
n.writeNodeData(mc, trafficMap);
|
n.writeNodeData(mc, trafficMap);
|
||||||
}
|
}
|
||||||
if ( mc.getSize() > 0 )
|
if (mc.getSize() > 0) {
|
||||||
{
|
|
||||||
byte[] subBytes;
|
byte[] subBytes;
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
int len = mc.encodeMicroCache(abBuf1);
|
int len = mc.encodeMicroCache(abBuf1);
|
||||||
subBytes = new byte[len];
|
subBytes = new byte[len];
|
||||||
System.arraycopy(abBuf1, 0, subBytes, 0, len);
|
System.arraycopy(abBuf1, 0, subBytes, 0, len);
|
||||||
|
|
||||||
if ( skipEncodingCheck )
|
if (skipEncodingCheck) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// cross-check the encoding: re-instantiate the cache
|
// 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
|
// ..and check if still the same
|
||||||
String diffMessage = mc.compareWith(mc2);
|
String diffMessage = mc.compareWith(mc2);
|
||||||
if ( diffMessage != null )
|
if (diffMessage != null) {
|
||||||
{
|
|
||||||
if (MicroCache.debug)
|
if (MicroCache.debug)
|
||||||
throw new RuntimeException("encoding crosscheck failed: " + diffMessage);
|
throw new RuntimeException("encoding crosscheck failed: " + diffMessage);
|
||||||
else
|
else
|
||||||
MicroCache.debug = true;
|
MicroCache.debug = true;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pos += subBytes.length + 4; // reserve 4 bytes for crc
|
pos += subBytes.length + 4; // reserve 4 bytes for crc
|
||||||
@ -598,11 +520,9 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
byte[] abSubIndex = compileSubFileIndex(posIdx);
|
byte[] abSubIndex = compileSubFileIndex(posIdx);
|
||||||
fileHeaderCrcs[tileIndex] = Crc32.crc(abSubIndex, 0, abSubIndex.length);
|
fileHeaderCrcs[tileIndex] = Crc32.crc(abSubIndex, 0, abSubIndex.length);
|
||||||
os.write(abSubIndex, 0, abSubIndex.length);
|
os.write(abSubIndex, 0, abSubIndex.length);
|
||||||
for ( int si = 0; si < ncaches; si++ )
|
for (int si = 0; si < ncaches; si++) {
|
||||||
{
|
|
||||||
byte[] ab = subByteArrays[si];
|
byte[] ab = subByteArrays[si];
|
||||||
if ( ab != null )
|
if (ab != null) {
|
||||||
{
|
|
||||||
os.write(ab);
|
os.write(ab);
|
||||||
os.writeInt(Crc32.crc(ab, 0, ab.length) ^ microCacheEncoding);
|
os.writeInt(Crc32.crc(ab, 0, ab.length) ^ microCacheEncoding);
|
||||||
}
|
}
|
||||||
@ -618,8 +538,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
// write extra data: timestamp + index-checksums
|
// write extra data: timestamp + index-checksums
|
||||||
os.writeLong(creationTimeStamp);
|
os.writeLong(creationTimeStamp);
|
||||||
os.writeInt(Crc32.crc(abFileIndex, 0, abFileIndex.length) ^ microCacheEncoding);
|
os.writeInt(Crc32.crc(abFileIndex, 0, abFileIndex.length) ^ microCacheEncoding);
|
||||||
for ( int i55 = 0; i55 < 25; i55++ )
|
for (int i55 = 0; i55 < 25; i55++) {
|
||||||
{
|
|
||||||
os.writeInt(fileHeaderCrcs[i55]);
|
os.writeInt(fileHeaderCrcs[i55]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,20 +549,17 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
ra.write(abFileIndex, 0, abFileIndex.length);
|
ra.write(abFileIndex, 0, abFileIndex.length);
|
||||||
ra.close();
|
ra.close();
|
||||||
}
|
}
|
||||||
if ( trafficMap != null )
|
if (trafficMap != null) {
|
||||||
{
|
|
||||||
trafficMap.finish();
|
trafficMap.finish();
|
||||||
trafficMap = null;
|
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();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
for ( int i55 = 0; i55 < 25; i55++ )
|
for (int i55 = 0; i55 < 25; i55++) {
|
||||||
{
|
|
||||||
long versionPrefix = i55 == 1 ? lookupMinorVersion : lookupVersion;
|
long versionPrefix = i55 == 1 ? lookupMinorVersion : lookupVersion;
|
||||||
versionPrefix <<= 48;
|
versionPrefix <<= 48;
|
||||||
dos.writeLong(fileIndex[i55] | versionPrefix);
|
dos.writeLong(fileIndex[i55] | versionPrefix);
|
||||||
@ -652,12 +568,10 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
|||||||
return bos.toByteArray();
|
return bos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] compileSubFileIndex( int[] posIdx ) throws Exception
|
private byte[] compileSubFileIndex(int[] posIdx) throws Exception {
|
||||||
{
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
for ( int si = 0; si < posIdx.length; si++ )
|
for (int si = 0; si < posIdx.length; si++) {
|
||||||
{
|
|
||||||
dos.writeInt(posIdx[si]);
|
dos.writeInt(posIdx[si]);
|
||||||
}
|
}
|
||||||
dos.close();
|
dos.close();
|
||||||
|
|||||||
@ -7,8 +7,7 @@ import java.io.File;
|
|||||||
*
|
*
|
||||||
* @author ab
|
* @author ab
|
||||||
*/
|
*/
|
||||||
public interface WayListener
|
public interface WayListener {
|
||||||
{
|
|
||||||
boolean wayFileStart(File wayfile) throws Exception;
|
boolean wayFileStart(File wayfile) throws Exception;
|
||||||
|
|
||||||
void nextWay(WayData data) throws Exception;
|
void nextWay(WayData data) throws Exception;
|
||||||
|
|||||||
@ -5,14 +5,13 @@ import java.util.HashMap;
|
|||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class MapcreatorTest
|
public class MapcreatorTest {
|
||||||
{
|
|
||||||
@Test
|
@Test
|
||||||
public void mapcreatorTest() throws Exception
|
public void mapcreatorTest() throws Exception {
|
||||||
{
|
|
||||||
URL mapurl = this.getClass().getResource("/dreieich.osm.gz");
|
URL mapurl = this.getClass().getResource("/dreieich.osm.gz");
|
||||||
Assert.assertTrue("test-osm-map dreieich.osm not found", mapurl != null);
|
Assert.assertTrue("test-osm-map dreieich.osm not found", mapurl != null);
|
||||||
File mapFile = new File(mapurl.getFile());
|
File mapFile = new File(mapurl.getFile());
|
||||||
|
|||||||
@ -14,14 +14,12 @@ import btools.util.IByteArrayUnifier;
|
|||||||
* DirectWeaver does the same decoding as MicroCache2, but decodes directly
|
* DirectWeaver does the same decoding as MicroCache2, but decodes directly
|
||||||
* into the instance-graph, not into the intermediate nodes-cache
|
* 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 long id64Base;
|
||||||
|
|
||||||
private int size = 0;
|
private int size = 0;
|
||||||
|
|
||||||
public DirectWeaver( StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes )
|
public DirectWeaver(StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes) {
|
||||||
{
|
|
||||||
super(null);
|
super(null);
|
||||||
int cellsize = 1000000 / divisor;
|
int cellsize = 1000000 / divisor;
|
||||||
id64Base = ((long) (lonIdx * cellsize)) << 32 | (latIdx * cellsize);
|
id64Base = ((long) (lonIdx * cellsize)) << 32 | (latIdx * cellsize);
|
||||||
@ -41,18 +39,14 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
bc.decodeSortedArray(faid, 0, size, 29, 0);
|
bc.decodeSortedArray(faid, 0, size, 29, 0);
|
||||||
|
|
||||||
OsmNode[] nodes = new OsmNode[size];
|
OsmNode[] nodes = new OsmNode[size];
|
||||||
for( int n = 0; n<size; n++ )
|
for (int n = 0; n < size; n++) {
|
||||||
{
|
|
||||||
long id = expandId(faid[n]);
|
long id = expandId(faid[n]);
|
||||||
int ilon = (int) (id >> 32);
|
int ilon = (int) (id >> 32);
|
||||||
int ilat = (int) (id & 0xffffffff);
|
int ilat = (int) (id & 0xffffffff);
|
||||||
OsmNode node = hollowNodes.get(ilon, ilat);
|
OsmNode node = hollowNodes.get(ilon, ilat);
|
||||||
if ( node == null )
|
if (node == null) {
|
||||||
{
|
|
||||||
node = new OsmNode(ilon, ilat);
|
node = new OsmNode(ilon, ilat);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
node.visitID = 1;
|
node.visitID = 1;
|
||||||
hollowNodes.remove(node);
|
hollowNodes.remove(node);
|
||||||
}
|
}
|
||||||
@ -72,8 +66,7 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
|
|
||||||
// future escapes (turn restrictions?)
|
// future escapes (turn restrictions?)
|
||||||
short trExceptions = 0;
|
short trExceptions = 0;
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
int featureId = bc.decodeVarBits();
|
int featureId = bc.decodeVarBits();
|
||||||
if (featureId == 0) break;
|
if (featureId == 0) break;
|
||||||
int bitsize = bc.decodeNoisyNumber(5);
|
int bitsize = bc.decodeNoisyNumber(5);
|
||||||
@ -81,8 +74,7 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
if (featureId == 2) // exceptions to turn-restriction
|
if (featureId == 2) // exceptions to turn-restriction
|
||||||
{
|
{
|
||||||
trExceptions = (short) bc.decodeBounded(1023);
|
trExceptions = (short) bc.decodeBounded(1023);
|
||||||
}
|
} else if (featureId == 1) // turn-restriction
|
||||||
else if ( featureId == 1 ) // turn-restriction
|
|
||||||
{
|
{
|
||||||
TurnRestriction tr = new TurnRestriction();
|
TurnRestriction tr = new TurnRestriction();
|
||||||
tr.exceptions = trExceptions;
|
tr.exceptions = trExceptions;
|
||||||
@ -93,9 +85,7 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
tr.toLon = ilon + bc.decodeNoisyDiff(10);
|
tr.toLon = ilon + bc.decodeNoisyDiff(10);
|
||||||
tr.toLat = ilat + bc.decodeNoisyDiff(10);
|
tr.toLat = ilat + bc.decodeNoisyDiff(10);
|
||||||
node.addTurnRestriction(tr);
|
node.addTurnRestriction(tr);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
|
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,8 +96,7 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
node.nodeDescription = nodeTags == null ? null : nodeTags.data; // TODO: unified?
|
node.nodeDescription = nodeTags == null ? null : nodeTags.data; // TODO: unified?
|
||||||
|
|
||||||
int links = bc.decodeNoisyNumber(1);
|
int links = bc.decodeNoisyNumber(1);
|
||||||
for( int li=0; li<links; li++ )
|
for (int li = 0; li < links; li++) {
|
||||||
{
|
|
||||||
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
|
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
|
||||||
|
|
||||||
int dlon_remaining;
|
int dlon_remaining;
|
||||||
@ -118,9 +107,7 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
{
|
{
|
||||||
dlon_remaining = nodes[nodeIdx].ilon - ilon;
|
dlon_remaining = nodes[nodeIdx].ilon - ilon;
|
||||||
dlat_remaining = nodes[nodeIdx].ilat - ilat;
|
dlat_remaining = nodes[nodeIdx].ilat - ilat;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
isReverse = bc.decodeBit();
|
isReverse = bc.decodeBit();
|
||||||
dlon_remaining = extLonDiff.decodeSignedValue();
|
dlon_remaining = extLonDiff.decodeSignedValue();
|
||||||
dlat_remaining = extLatDiff.decodeSignedValue();
|
dlat_remaining = extLatDiff.decodeSignedValue();
|
||||||
@ -136,41 +123,36 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
||||||
int ilontarget = ilon + dlon_remaining;
|
int ilontarget = ilon + dlon_remaining;
|
||||||
int ilattarget = ilat + dlat_remaining;
|
int ilattarget = ilat + dlat_remaining;
|
||||||
if ( matcher != null )
|
if (matcher != null) {
|
||||||
{
|
if (!matcher.start(ilon, ilat, ilontarget, ilattarget)) {
|
||||||
if ( !matcher.start( ilon, ilat, ilontarget, ilattarget ) )
|
|
||||||
{
|
|
||||||
matcher = null;
|
matcher = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int transcount = bc.decodeVarBits();
|
int transcount = bc.decodeVarBits();
|
||||||
int count = transcount + 1;
|
int count = transcount + 1;
|
||||||
for( int i=0; i<transcount; i++ )
|
for (int i = 0; i < transcount; i++) {
|
||||||
{
|
|
||||||
int dlon = bc.decodePredictedValue(dlon_remaining / count);
|
int dlon = bc.decodePredictedValue(dlon_remaining / count);
|
||||||
int dlat = bc.decodePredictedValue(dlat_remaining / count);
|
int dlat = bc.decodePredictedValue(dlat_remaining / count);
|
||||||
dlon_remaining -= dlon;
|
dlon_remaining -= dlon;
|
||||||
dlat_remaining -= dlat;
|
dlat_remaining -= dlat;
|
||||||
count--;
|
count--;
|
||||||
int elediff = transEleDiff.decodeSignedValue();
|
int elediff = transEleDiff.decodeSignedValue();
|
||||||
if ( wayTags != null )
|
if (wayTags != null) {
|
||||||
{
|
|
||||||
writeVarLengthSigned(dlon);
|
writeVarLengthSigned(dlon);
|
||||||
writeVarLengthSigned(dlat);
|
writeVarLengthSigned(dlat);
|
||||||
writeVarLengthSigned(elediff);
|
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;
|
byte[] geometry = null;
|
||||||
if ( aboffset > 0 )
|
if (aboffset > 0) {
|
||||||
{
|
|
||||||
geometry = new byte[aboffset];
|
geometry = new byte[aboffset];
|
||||||
System.arraycopy(ab, 0, geometry, 0, aboffset);
|
System.arraycopy(ab, 0, geometry, 0, aboffset);
|
||||||
}
|
}
|
||||||
@ -179,15 +161,13 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
{
|
{
|
||||||
OsmNode node2 = nodes[nodeIdx];
|
OsmNode node2 = nodes[nodeIdx];
|
||||||
OsmLink link = node.isLinkUnused() ? node : (node2.isLinkUnused() ? node2 : null);
|
OsmLink link = node.isLinkUnused() ? node : (node2.isLinkUnused() ? node2 : null);
|
||||||
if ( link == null )
|
if (link == null) {
|
||||||
{
|
|
||||||
link = new OsmLink();
|
link = new OsmLink();
|
||||||
}
|
}
|
||||||
link.descriptionBitmap = wayTags.data;
|
link.descriptionBitmap = wayTags.data;
|
||||||
link.geometry = geometry;
|
link.geometry = geometry;
|
||||||
node.addLink(link, isReverse, node2);
|
node.addLink(link, isReverse, node2);
|
||||||
}
|
} else // weave external link
|
||||||
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;
|
node.visitID = 1;
|
||||||
@ -203,23 +183,19 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
private static final long[] id32_10 = new long[1024];
|
private static final long[] id32_10 = new long[1024];
|
||||||
private static final long[] id32_20 = new long[1024];
|
private static final long[] id32_20 = new long[1024];
|
||||||
|
|
||||||
static
|
static {
|
||||||
{
|
for (int i = 0; i < 1024; i++) {
|
||||||
for( int i=0; i<1024; i++ )
|
|
||||||
{
|
|
||||||
id32_00[i] = _expandId(i);
|
id32_00[i] = _expandId(i);
|
||||||
id32_10[i] = _expandId(i << 10);
|
id32_10[i] = _expandId(i << 10);
|
||||||
id32_20[i] = _expandId(i << 20);
|
id32_20[i] = _expandId(i << 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long _expandId( int id32 )
|
private static long _expandId(int id32) {
|
||||||
{
|
|
||||||
int dlon = 0;
|
int dlon = 0;
|
||||||
int dlat = 0;
|
int dlat = 0;
|
||||||
|
|
||||||
for( int bm = 1; bm < 0x8000; bm <<= 1 )
|
for (int bm = 1; bm < 0x8000; bm <<= 1) {
|
||||||
{
|
|
||||||
if ((id32 & 1) != 0) dlon |= bm;
|
if ((id32 & 1) != 0) dlon |= bm;
|
||||||
if ((id32 & 2) != 0) dlat |= bm;
|
if ((id32 & 2) != 0) dlat |= bm;
|
||||||
id32 >>= 2;
|
id32 >>= 2;
|
||||||
@ -227,8 +203,7 @@ public final class DirectWeaver extends ByteDataWriter
|
|||||||
return ((long) dlon) << 32 | dlat;
|
return ((long) dlon) << 32 | dlat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long expandId( int id32 )
|
public long expandId(int id32) {
|
||||||
{
|
|
||||||
return id64Base + id32_00[id32 & 1023] + id32_10[(id32 >> 10) & 1023] + id32_20[(id32 >> 20) & 1023];
|
return id64Base + id32_00[id32 & 1023] + id32_10[(id32 >> 10) & 1023] + id32_20[(id32 >> 20) & 1023];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,7 @@ package btools.mapaccess;
|
|||||||
import btools.util.ByteDataReader;
|
import btools.util.ByteDataReader;
|
||||||
|
|
||||||
|
|
||||||
public final class GeometryDecoder
|
public final class GeometryDecoder {
|
||||||
{
|
|
||||||
private ByteDataReader r = new ByteDataReader(null);
|
private ByteDataReader r = new ByteDataReader(null);
|
||||||
private OsmTransferNode[] cachedNodes;
|
private OsmTransferNode[] cachedNodes;
|
||||||
private int nCachedNodes = 128;
|
private int nCachedNodes = 128;
|
||||||
@ -19,20 +18,16 @@ public final class GeometryDecoder
|
|||||||
private boolean lastReverse;
|
private boolean lastReverse;
|
||||||
private byte[] lastGeometry;
|
private byte[] lastGeometry;
|
||||||
|
|
||||||
public GeometryDecoder()
|
public GeometryDecoder() {
|
||||||
{
|
|
||||||
// create some caches
|
// create some caches
|
||||||
cachedNodes = new OsmTransferNode[nCachedNodes];
|
cachedNodes = new OsmTransferNode[nCachedNodes];
|
||||||
for( int i=0; i<nCachedNodes; i++ )
|
for (int i = 0; i < nCachedNodes; i++) {
|
||||||
{
|
|
||||||
cachedNodes[i] = new OsmTransferNode();
|
cachedNodes[i] = new OsmTransferNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmTransferNode decodeGeometry( byte[] geometry, OsmNode sourceNode, OsmNode targetNode, boolean reverseLink )
|
public OsmTransferNode decodeGeometry(byte[] geometry, OsmNode sourceNode, OsmNode targetNode, boolean reverseLink) {
|
||||||
{
|
if ((lastGeometry == geometry) && (lastReverse == reverseLink)) {
|
||||||
if ( ( lastGeometry == geometry ) && ( lastReverse == reverseLink ) )
|
|
||||||
{
|
|
||||||
return firstTransferNode;
|
return firstTransferNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,8 +39,7 @@ public final class GeometryDecoder
|
|||||||
int olat = startnode.ilat;
|
int olat = startnode.ilat;
|
||||||
int oselev = startnode.selev;
|
int oselev = startnode.selev;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
while ( r.hasMoreData() )
|
while (r.hasMoreData()) {
|
||||||
{
|
|
||||||
OsmTransferNode trans = idx < nCachedNodes ? cachedNodes[idx++] : new OsmTransferNode();
|
OsmTransferNode trans = idx < nCachedNodes ? cachedNodes[idx++] : new OsmTransferNode();
|
||||||
trans.ilon = olon + r.readVarLengthSigned();
|
trans.ilon = olon + r.readVarLengthSigned();
|
||||||
trans.ilat = olat + r.readVarLengthSigned();
|
trans.ilat = olat + r.readVarLengthSigned();
|
||||||
@ -57,16 +51,11 @@ public final class GeometryDecoder
|
|||||||
{
|
{
|
||||||
trans.next = firstTransferNode;
|
trans.next = firstTransferNode;
|
||||||
firstTransferNode = trans;
|
firstTransferNode = trans;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
trans.next = null;
|
trans.next = null;
|
||||||
if ( lastTransferNode == null )
|
if (lastTransferNode == null) {
|
||||||
{
|
|
||||||
firstTransferNode = trans;
|
firstTransferNode = trans;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
lastTransferNode.next = trans;
|
lastTransferNode.next = trans;
|
||||||
}
|
}
|
||||||
lastTransferNode = trans;
|
lastTransferNode = trans;
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
|
|
||||||
public final class MatchedWaypoint
|
public final class MatchedWaypoint {
|
||||||
{
|
|
||||||
public OsmNode node1;
|
public OsmNode node1;
|
||||||
public OsmNode node2;
|
public OsmNode node2;
|
||||||
public OsmNode crosspoint;
|
public OsmNode crosspoint;
|
||||||
@ -22,8 +21,7 @@ public final class MatchedWaypoint
|
|||||||
|
|
||||||
public boolean hasUpdate;
|
public boolean hasUpdate;
|
||||||
|
|
||||||
public void writeToStream( DataOutput dos ) throws IOException
|
public void writeToStream(DataOutput dos) throws IOException {
|
||||||
{
|
|
||||||
dos.writeInt(node1.ilat);
|
dos.writeInt(node1.ilat);
|
||||||
dos.writeInt(node1.ilon);
|
dos.writeInt(node1.ilon);
|
||||||
dos.writeInt(node2.ilat);
|
dos.writeInt(node2.ilat);
|
||||||
@ -35,8 +33,7 @@ public final class MatchedWaypoint
|
|||||||
dos.writeDouble(radius);
|
dos.writeDouble(radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MatchedWaypoint readFromStream( DataInput dis ) throws IOException
|
public static MatchedWaypoint readFromStream(DataInput dis) throws IOException {
|
||||||
{
|
|
||||||
MatchedWaypoint mwp = new MatchedWaypoint();
|
MatchedWaypoint mwp = new MatchedWaypoint();
|
||||||
mwp.node1 = new OsmNode();
|
mwp.node1 = new OsmNode();
|
||||||
mwp.node2 = new OsmNode();
|
mwp.node2 = new OsmNode();
|
||||||
|
|||||||
@ -15,8 +15,7 @@ import btools.codec.MicroCache;
|
|||||||
import btools.codec.WaypointMatcher;
|
import btools.codec.WaypointMatcher;
|
||||||
import btools.expressions.BExpressionContextWay;
|
import btools.expressions.BExpressionContextWay;
|
||||||
|
|
||||||
public final class NodesCache
|
public final class NodesCache {
|
||||||
{
|
|
||||||
private File segmentDir;
|
private File segmentDir;
|
||||||
private File secondarySegmentsDir = null;
|
private File secondarySegmentsDir = null;
|
||||||
|
|
||||||
@ -51,13 +50,11 @@ public final class NodesCache
|
|||||||
|
|
||||||
private boolean directWeaving = !Boolean.getBoolean("disableDirectWeaving");
|
private boolean directWeaving = !Boolean.getBoolean("disableDirectWeaving");
|
||||||
|
|
||||||
public String formatStatus()
|
public String formatStatus() {
|
||||||
{
|
|
||||||
return "collecting=" + garbageCollectionEnabled + " noGhosts=" + ghostCleaningDone + " cacheSum=" + cacheSum + " cacheSumClean=" + cacheSumClean + " ghostSum=" + ghostSum + " ghostWakeup=" + ghostWakeup;
|
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.maxmemtiles = maxmem / 8;
|
||||||
this.segmentDir = segmentDir;
|
this.segmentDir = segmentDir;
|
||||||
this.nodesMap = new OsmNodesMap();
|
this.nodesMap = new OsmNodesMap();
|
||||||
@ -68,8 +65,7 @@ public final class NodesCache
|
|||||||
this.forceSecondaryData = forceSecondaryData;
|
this.forceSecondaryData = forceSecondaryData;
|
||||||
this.detailed = detailed;
|
this.detailed = detailed;
|
||||||
|
|
||||||
if ( ctxWay != null )
|
if (ctxWay != null) {
|
||||||
{
|
|
||||||
ctxWay.setDecodeForbidden(detailed);
|
ctxWay.setDecodeForbidden(detailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,33 +75,25 @@ public final class NodesCache
|
|||||||
if (!this.segmentDir.isDirectory())
|
if (!this.segmentDir.isDirectory())
|
||||||
throw new RuntimeException("segment directory " + segmentDir.getAbsolutePath() + " does not exist");
|
throw new RuntimeException("segment directory " + segmentDir.getAbsolutePath() + " does not exist");
|
||||||
|
|
||||||
if ( oldCache != null )
|
if (oldCache != null) {
|
||||||
{
|
|
||||||
fileCache = oldCache.fileCache;
|
fileCache = oldCache.fileCache;
|
||||||
dataBuffers = oldCache.dataBuffers;
|
dataBuffers = oldCache.dataBuffers;
|
||||||
secondarySegmentsDir = oldCache.secondarySegmentsDir;
|
secondarySegmentsDir = oldCache.secondarySegmentsDir;
|
||||||
|
|
||||||
// re-use old, virgin caches (if same detail-mode)
|
// re-use old, virgin caches (if same detail-mode)
|
||||||
if ( oldCache.detailed == detailed)
|
if (oldCache.detailed == detailed) {
|
||||||
{
|
|
||||||
fileRows = oldCache.fileRows;
|
fileRows = oldCache.fileRows;
|
||||||
for ( OsmFile[] fileRow : fileRows )
|
for (OsmFile[] fileRow : fileRows) {
|
||||||
{
|
|
||||||
if (fileRow == null)
|
if (fileRow == null)
|
||||||
continue;
|
continue;
|
||||||
for ( OsmFile osmf : fileRow )
|
for (OsmFile osmf : fileRow) {
|
||||||
{
|
|
||||||
cacheSum += osmf.setGhostState();
|
cacheSum += osmf.setGhostState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fileRows = new OsmFile[180][];
|
fileRows = new OsmFile[180][];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fileCache = new HashMap<String, PhysicalFile>(4);
|
fileCache = new HashMap<String, PhysicalFile>(4);
|
||||||
fileRows = new OsmFile[180][];
|
fileRows = new OsmFile[180][];
|
||||||
dataBuffers = new DataBuffers();
|
dataBuffers = new DataBuffers();
|
||||||
@ -114,14 +102,11 @@ public final class NodesCache
|
|||||||
ghostSum = cacheSum;
|
ghostSum = cacheSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clean( boolean all )
|
public void clean(boolean all) {
|
||||||
{
|
for (OsmFile[] fileRow : fileRows) {
|
||||||
for ( OsmFile[] fileRow : fileRows )
|
|
||||||
{
|
|
||||||
if (fileRow == null)
|
if (fileRow == null)
|
||||||
continue;
|
continue;
|
||||||
for ( OsmFile osmf : fileRow )
|
for (OsmFile osmf : fileRow) {
|
||||||
{
|
|
||||||
osmf.clean(all);
|
osmf.clean(all);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,74 +114,56 @@ public final class NodesCache
|
|||||||
|
|
||||||
// if the cache sum exceeded a threshold,
|
// if the cache sum exceeded a threshold,
|
||||||
// clean all ghosts and enable garbage collection
|
// clean all ghosts and enable garbage collection
|
||||||
private void checkEnableCacheCleaning()
|
private void checkEnableCacheCleaning() {
|
||||||
{
|
if (cacheSum < maxmemtiles) {
|
||||||
if ( cacheSum < maxmemtiles )
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < fileRows.length; i++ )
|
for (int i = 0; i < fileRows.length; i++) {
|
||||||
{
|
|
||||||
OsmFile[] fileRow = fileRows[i];
|
OsmFile[] fileRow = fileRows[i];
|
||||||
if ( fileRow == null )
|
if (fileRow == null) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for ( OsmFile osmf : fileRow )
|
for (OsmFile osmf : fileRow) {
|
||||||
{
|
if (garbageCollectionEnabled && !ghostCleaningDone) {
|
||||||
if ( garbageCollectionEnabled && !ghostCleaningDone )
|
|
||||||
{
|
|
||||||
cacheSum -= osmf.cleanGhosts();
|
cacheSum -= osmf.cleanGhosts();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cacheSum -= osmf.collectAll();
|
cacheSum -= osmf.collectAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( garbageCollectionEnabled )
|
if (garbageCollectionEnabled) {
|
||||||
{
|
|
||||||
ghostCleaningDone = true;
|
ghostCleaningDone = true;
|
||||||
maxmemtiles *= 2;
|
maxmemtiles *= 2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cacheSumClean = cacheSum;
|
cacheSumClean = cacheSum;
|
||||||
garbageCollectionEnabled = true;
|
garbageCollectionEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int loadSegmentFor( int ilon, int ilat )
|
public int loadSegmentFor(int ilon, int ilat) {
|
||||||
{
|
|
||||||
MicroCache mc = getSegmentFor(ilon, ilat);
|
MicroCache mc = getSegmentFor(ilon, ilat);
|
||||||
return mc == null ? 0 : mc.getSize();
|
return mc == null ? 0 : mc.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MicroCache getSegmentFor( int ilon, int ilat )
|
public MicroCache getSegmentFor(int ilon, int ilat) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
int lonDegree = ilon / 1000000;
|
int lonDegree = ilon / 1000000;
|
||||||
int latDegree = ilat / 1000000;
|
int latDegree = ilat / 1000000;
|
||||||
OsmFile osmf = null;
|
OsmFile osmf = null;
|
||||||
OsmFile[] fileRow = fileRows[latDegree];
|
OsmFile[] fileRow = fileRows[latDegree];
|
||||||
int ndegrees = fileRow == null ? 0 : fileRow.length;
|
int ndegrees = fileRow == null ? 0 : fileRow.length;
|
||||||
for ( int i = 0; i < ndegrees; i++ )
|
for (int i = 0; i < ndegrees; i++) {
|
||||||
{
|
if (fileRow[i].lonDegree == lonDegree) {
|
||||||
if ( fileRow[i].lonDegree == lonDegree )
|
|
||||||
{
|
|
||||||
osmf = fileRow[i];
|
osmf = fileRow[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( osmf == null )
|
if (osmf == null) {
|
||||||
{
|
|
||||||
osmf = fileForSegment(lonDegree, latDegree);
|
osmf = fileForSegment(lonDegree, latDegree);
|
||||||
OsmFile[] newFileRow = new OsmFile[ndegrees + 1];
|
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[i] = fileRow[i];
|
||||||
}
|
}
|
||||||
newFileRow[ndegrees] = osmf;
|
newFileRow[ndegrees] = osmf;
|
||||||
@ -204,32 +171,24 @@ public final class NodesCache
|
|||||||
}
|
}
|
||||||
currentFileName = osmf.filename;
|
currentFileName = osmf.filename;
|
||||||
|
|
||||||
if ( !osmf.hasData() )
|
if (!osmf.hasData()) {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
MicroCache segment = osmf.getMicroCache(ilon, ilat);
|
MicroCache segment = osmf.getMicroCache(ilon, ilat);
|
||||||
if ( segment == null )
|
if (segment == null) {
|
||||||
{
|
|
||||||
checkEnableCacheCleaning();
|
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();
|
cacheSum += segment.getDataSize();
|
||||||
}
|
} else if (segment.ghost) {
|
||||||
else if ( segment.ghost )
|
|
||||||
{
|
|
||||||
segment.unGhost();
|
segment.unGhost();
|
||||||
ghostWakeup += segment.getDataSize();
|
ghostWakeup += segment.getDataSize();
|
||||||
}
|
}
|
||||||
return segment;
|
return segment;
|
||||||
}
|
} catch (RuntimeException re) {
|
||||||
catch (RuntimeException re)
|
|
||||||
{
|
|
||||||
throw re;
|
throw re;
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("error reading datafile " + currentFileName + ": " + e, e);
|
throw new RuntimeException("error reading datafile " + currentFileName + ": " + e, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,24 +200,20 @@ public final class NodesCache
|
|||||||
*
|
*
|
||||||
* @return true if successfull, false if node is still hollow
|
* @return true if successfull, false if node is still hollow
|
||||||
*/
|
*/
|
||||||
public boolean obtainNonHollowNode( OsmNode node )
|
public boolean obtainNonHollowNode(OsmNode node) {
|
||||||
{
|
|
||||||
if (!node.isHollow())
|
if (!node.isHollow())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
MicroCache segment = getSegmentFor(node.ilon, node.ilat);
|
MicroCache segment = getSegmentFor(node.ilon, node.ilat);
|
||||||
if ( segment == null )
|
if (segment == null) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( !node.isHollow() )
|
if (!node.isHollow()) {
|
||||||
{
|
|
||||||
return true; // direct weaving...
|
return true; // direct weaving...
|
||||||
}
|
}
|
||||||
|
|
||||||
long id = node.getIdFromPos();
|
long id = node.getIdFromPos();
|
||||||
if ( segment.getAndClear( id ) )
|
if (segment.getAndClear(id)) {
|
||||||
{
|
|
||||||
node.parseNodeBody(segment, nodesMap, expCtxWay);
|
node.parseNodeBody(segment, nodesMap, expCtxWay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,14 +226,11 @@ public final class NodesCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* make sure all link targets of the given node are non-hollow
|
* make sure all link targets of the given node are non-hollow
|
||||||
*/
|
*/
|
||||||
public void expandHollowLinkTargets( OsmNode n )
|
public void expandHollowLinkTargets(OsmNode n) {
|
||||||
{
|
for (OsmLink link = n.firstlink; link != null; link = link.getNext(n)) {
|
||||||
for( OsmLink link = n.firstlink; link != null; link = link.getNext( n ) )
|
|
||||||
{
|
|
||||||
obtainNonHollowNode(link.getTarget(n));
|
obtainNonHollowNode(link.getTarget(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,12 +238,9 @@ public final class NodesCache
|
|||||||
/**
|
/**
|
||||||
* make sure all link targets of the given node are non-hollow
|
* make sure all link targets of the given node are non-hollow
|
||||||
*/
|
*/
|
||||||
public boolean hasHollowLinkTargets( OsmNode n )
|
public boolean hasHollowLinkTargets(OsmNode n) {
|
||||||
{
|
for (OsmLink link = n.firstlink; link != null; link = link.getNext(n)) {
|
||||||
for( OsmLink link = n.firstlink; link != null; link = link.getNext( n ) )
|
if (link.getTarget(n).isHollow()) {
|
||||||
{
|
|
||||||
if ( link.getTarget( n ).isHollow() )
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,85 +249,70 @@ public final class NodesCache
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* get a node for the given id with all link-targets also non-hollow
|
* 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
|
* It is required that an instance of the start-node does not yet
|
||||||
* exist, not even a hollow instance, so getStartNode should only
|
* exist, not even a hollow instance, so getStartNode should only
|
||||||
* be called once right after resetting the cache
|
* be called once right after resetting the cache
|
||||||
*
|
*
|
||||||
* @param id the id of the node to load
|
* @param id the id of the node to load
|
||||||
*
|
|
||||||
* @return the fully expanded node for id, or null if it was not found
|
* @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
|
// initialize the start-node
|
||||||
OsmNode n = new OsmNode(id);
|
OsmNode n = new OsmNode(id);
|
||||||
n.setHollow();
|
n.setHollow();
|
||||||
nodesMap.put(n);
|
nodesMap.put(n);
|
||||||
if ( !obtainNonHollowNode( n ) )
|
if (!obtainNonHollowNode(n)) {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
expandHollowLinkTargets(n);
|
expandHollowLinkTargets(n);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNode getGraphNode( OsmNode template )
|
public OsmNode getGraphNode(OsmNode template) {
|
||||||
{
|
|
||||||
OsmNode graphNode = new OsmNode(template.ilon, template.ilat);
|
OsmNode graphNode = new OsmNode(template.ilon, template.ilat);
|
||||||
graphNode.setHollow();
|
graphNode.setHollow();
|
||||||
OsmNode existing = nodesMap.put(graphNode);
|
OsmNode existing = nodesMap.put(graphNode);
|
||||||
if ( existing == null )
|
if (existing == null) {
|
||||||
{
|
|
||||||
return graphNode;
|
return graphNode;
|
||||||
}
|
}
|
||||||
nodesMap.put(existing);
|
nodesMap.put(existing);
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs )
|
public void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs) {
|
||||||
{
|
|
||||||
waypointMatcher = new WaypointMatcherImpl(unmatchedWaypoints, maxDistance, islandNodePairs);
|
waypointMatcher = new WaypointMatcherImpl(unmatchedWaypoints, maxDistance, islandNodePairs);
|
||||||
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
for (MatchedWaypoint mwp : unmatchedWaypoints) {
|
||||||
{
|
|
||||||
preloadPosition(mwp.waypoint);
|
preloadPosition(mwp.waypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( first_file_access_failed )
|
if (first_file_access_failed) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
|
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
|
||||||
}
|
}
|
||||||
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
for (MatchedWaypoint mwp : unmatchedWaypoints) {
|
||||||
{
|
if (mwp.crosspoint == null) {
|
||||||
if ( mwp.crosspoint == null )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
|
throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preloadPosition( OsmNode n )
|
private void preloadPosition(OsmNode n) {
|
||||||
{
|
|
||||||
int d = 12500;
|
int d = 12500;
|
||||||
first_file_access_failed = false;
|
first_file_access_failed = false;
|
||||||
first_file_access_name = null;
|
first_file_access_name = null;
|
||||||
loadSegmentFor(n.ilon, n.ilat);
|
loadSegmentFor(n.ilon, n.ilat);
|
||||||
if ( first_file_access_failed )
|
if (first_file_access_failed) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
|
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
|
||||||
}
|
}
|
||||||
for (int idxLat = -1; idxLat <= 1; idxLat++)
|
for (int idxLat = -1; idxLat <= 1; idxLat++)
|
||||||
for( int idxLon=-1; idxLon<=1; idxLon++ )
|
for (int idxLon = -1; idxLon <= 1; idxLon++) {
|
||||||
{
|
if (idxLon != 0 || idxLat != 0) {
|
||||||
if ( idxLon != 0 || idxLat != 0 )
|
|
||||||
{
|
|
||||||
loadSegmentFor(n.ilon + d * idxLon, n.ilat + d * idxLat);
|
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 lonMod5 = lonDegree % 5;
|
||||||
int latMod5 = latDegree % 5;
|
int latMod5 = latDegree % 5;
|
||||||
|
|
||||||
@ -392,27 +326,21 @@ public final class NodesCache
|
|||||||
currentFileName = filenameBase + ".rd5";
|
currentFileName = filenameBase + ".rd5";
|
||||||
|
|
||||||
PhysicalFile ra = null;
|
PhysicalFile ra = null;
|
||||||
if ( !fileCache.containsKey( filenameBase ) )
|
if (!fileCache.containsKey(filenameBase)) {
|
||||||
{
|
|
||||||
File f = null;
|
File f = null;
|
||||||
if ( !forceSecondaryData )
|
if (!forceSecondaryData) {
|
||||||
{
|
|
||||||
File primary = new File(segmentDir, filenameBase + ".rd5");
|
File primary = new File(segmentDir, filenameBase + ".rd5");
|
||||||
if ( primary .exists() )
|
if (primary.exists()) {
|
||||||
{
|
|
||||||
f = primary;
|
f = primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( f == null )
|
if (f == null) {
|
||||||
{
|
|
||||||
File secondary = new File(secondarySegmentsDir, filenameBase + ".rd5");
|
File secondary = new File(secondarySegmentsDir, filenameBase + ".rd5");
|
||||||
if ( secondary.exists() )
|
if (secondary.exists()) {
|
||||||
{
|
|
||||||
f = secondary;
|
f = secondary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( f != null )
|
if (f != null) {
|
||||||
{
|
|
||||||
currentFileName = f.getName();
|
currentFileName = f.getName();
|
||||||
ra = new PhysicalFile(f, dataBuffers, lookupVersion, lookupMinorVersion);
|
ra = new PhysicalFile(f, dataBuffers, lookupVersion, lookupMinorVersion);
|
||||||
}
|
}
|
||||||
@ -421,8 +349,7 @@ public final class NodesCache
|
|||||||
ra = fileCache.get(filenameBase);
|
ra = fileCache.get(filenameBase);
|
||||||
OsmFile osmf = new OsmFile(ra, lonDegree, latDegree, dataBuffers);
|
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_name = currentFileName;
|
||||||
first_file_access_failed = osmf.filename == null;
|
first_file_access_failed = osmf.filename == null;
|
||||||
}
|
}
|
||||||
@ -430,17 +357,12 @@ public final class NodesCache
|
|||||||
return osmf;
|
return osmf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close()
|
public void close() {
|
||||||
{
|
for (PhysicalFile f : fileCache.values()) {
|
||||||
for ( PhysicalFile f : fileCache.values() )
|
try {
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (f != null)
|
if (f != null)
|
||||||
f.ra.close();
|
f.ra.close();
|
||||||
}
|
} catch (IOException ioe) {
|
||||||
catch (IOException ioe)
|
|
||||||
{
|
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,7 @@
|
|||||||
package btools.mapaccess;
|
package btools.mapaccess;
|
||||||
|
|
||||||
|
|
||||||
final class NodesList
|
final class NodesList {
|
||||||
{
|
|
||||||
public OsmNode node;
|
public OsmNode node;
|
||||||
public NodesList next;
|
public NodesList next;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,7 @@ import btools.codec.WaypointMatcher;
|
|||||||
import btools.util.ByteDataReader;
|
import btools.util.ByteDataReader;
|
||||||
import btools.util.Crc32;
|
import btools.util.Crc32;
|
||||||
|
|
||||||
final class OsmFile
|
final class OsmFile {
|
||||||
{
|
|
||||||
private RandomAccessFile is = null;
|
private RandomAccessFile is = null;
|
||||||
private long fileOffset;
|
private long fileOffset;
|
||||||
|
|
||||||
@ -35,16 +34,14 @@ final class OsmFile
|
|||||||
private int ncaches;
|
private int ncaches;
|
||||||
private int indexsize;
|
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.lonDegree = lonDegree;
|
||||||
this.latDegree = latDegree;
|
this.latDegree = latDegree;
|
||||||
int lonMod5 = lonDegree % 5;
|
int lonMod5 = lonDegree % 5;
|
||||||
int latMod5 = latDegree % 5;
|
int latMod5 = latDegree % 5;
|
||||||
int tileIndex = lonMod5 * 5 + latMod5;
|
int tileIndex = lonMod5 * 5 + latMod5;
|
||||||
|
|
||||||
if ( rafile != null )
|
if (rafile != null) {
|
||||||
{
|
|
||||||
divisor = rafile.divisor;
|
divisor = rafile.divisor;
|
||||||
|
|
||||||
cellsize = 1000000 / divisor;
|
cellsize = 1000000 / divisor;
|
||||||
@ -65,30 +62,25 @@ final class OsmFile
|
|||||||
is.seek(fileOffset);
|
is.seek(fileOffset);
|
||||||
is.readFully(iobuffer, 0, indexsize);
|
is.readFully(iobuffer, 0, indexsize);
|
||||||
|
|
||||||
if ( rafile.fileHeaderCrcs != null )
|
if (rafile.fileHeaderCrcs != null) {
|
||||||
{
|
|
||||||
int headerCrc = Crc32.crc(iobuffer, 0, indexsize);
|
int headerCrc = Crc32.crc(iobuffer, 0, indexsize);
|
||||||
if ( rafile.fileHeaderCrcs[tileIndex] != headerCrc )
|
if (rafile.fileHeaderCrcs[tileIndex] != headerCrc) {
|
||||||
{
|
|
||||||
throw new IOException("sub index checksum error");
|
throw new IOException("sub index checksum error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteDataReader dis = new ByteDataReader(iobuffer);
|
ByteDataReader dis = new ByteDataReader(iobuffer);
|
||||||
for ( int i = 0; i < ncaches; i++ )
|
for (int i = 0; i < ncaches; i++) {
|
||||||
{
|
|
||||||
posIdx[i] = dis.readInt();
|
posIdx[i] = dis.readInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasData()
|
public boolean hasData() {
|
||||||
{
|
|
||||||
return microCaches != null;
|
return microCaches != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MicroCache getMicroCache( int ilon, int ilat )
|
public MicroCache getMicroCache(int ilon, int ilat) {
|
||||||
{
|
|
||||||
int lonIdx = ilon / cellsize;
|
int lonIdx = ilon / cellsize;
|
||||||
int latIdx = ilat / cellsize;
|
int latIdx = ilat / cellsize;
|
||||||
int subIdx = (latIdx - divisor * latDegree) * divisor + (lonIdx - divisor * lonDegree);
|
int subIdx = (latIdx - divisor * latDegree) * divisor + (lonIdx - divisor * lonDegree);
|
||||||
@ -96,8 +88,7 @@ final class OsmFile
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MicroCache createMicroCache(int ilon, int ilat, DataBuffers dataBuffers, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes)
|
public MicroCache createMicroCache(int ilon, int ilat, DataBuffers dataBuffers, TagValueValidator wayValidator, WaypointMatcher waypointMatcher, OsmNodesMap hollowNodes)
|
||||||
throws Exception
|
throws Exception {
|
||||||
{
|
|
||||||
int lonIdx = ilon / cellsize;
|
int lonIdx = ilon / cellsize;
|
||||||
int latIdx = ilat / cellsize;
|
int latIdx = ilat / cellsize;
|
||||||
MicroCache segment = createMicroCache(lonIdx, latIdx, dataBuffers, wayValidator, waypointMatcher, true, hollowNodes);
|
MicroCache segment = createMicroCache(lonIdx, latIdx, dataBuffers, wayValidator, waypointMatcher, true, hollowNodes);
|
||||||
@ -106,21 +97,17 @@ final class OsmFile
|
|||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPosIdx( int idx )
|
private int getPosIdx(int idx) {
|
||||||
{
|
|
||||||
return idx == -1 ? indexsize : posIdx[idx];
|
return idx == -1 ? indexsize : posIdx[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDataInputForSubIdx( int subIdx, byte[] iobuffer ) throws IOException
|
public int getDataInputForSubIdx(int subIdx, byte[] iobuffer) throws IOException {
|
||||||
{
|
|
||||||
int startPos = getPosIdx(subIdx - 1);
|
int startPos = getPosIdx(subIdx - 1);
|
||||||
int endPos = getPosIdx(subIdx);
|
int endPos = getPosIdx(subIdx);
|
||||||
int size = endPos - startPos;
|
int size = endPos - startPos;
|
||||||
if ( size > 0 )
|
if (size > 0) {
|
||||||
{
|
|
||||||
is.seek(fileOffset + startPos);
|
is.seek(fileOffset + startPos);
|
||||||
if ( size <= iobuffer.length )
|
if (size <= iobuffer.length) {
|
||||||
{
|
|
||||||
is.readFully(iobuffer, 0, size);
|
is.readFully(iobuffer, 0, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,52 +115,40 @@ final class OsmFile
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MicroCache createMicroCache(int lonIdx, int latIdx, DataBuffers dataBuffers, TagValueValidator wayValidator,
|
public MicroCache createMicroCache(int lonIdx, int latIdx, DataBuffers dataBuffers, TagValueValidator wayValidator,
|
||||||
WaypointMatcher waypointMatcher, boolean reallyDecode, OsmNodesMap hollowNodes ) throws IOException
|
WaypointMatcher waypointMatcher, boolean reallyDecode, OsmNodesMap hollowNodes) throws IOException {
|
||||||
{
|
|
||||||
int subIdx = (latIdx - divisor * latDegree) * divisor + (lonIdx - divisor * lonDegree);
|
int subIdx = (latIdx - divisor * latDegree) * divisor + (lonIdx - divisor * lonDegree);
|
||||||
|
|
||||||
byte[] ab = dataBuffers.iobuffer;
|
byte[] ab = dataBuffers.iobuffer;
|
||||||
int asize = getDataInputForSubIdx(subIdx, ab);
|
int asize = getDataInputForSubIdx(subIdx, ab);
|
||||||
|
|
||||||
if ( asize == 0 )
|
if (asize == 0) {
|
||||||
{
|
|
||||||
return MicroCache.emptyCache();
|
return MicroCache.emptyCache();
|
||||||
}
|
}
|
||||||
if ( asize > ab.length )
|
if (asize > ab.length) {
|
||||||
{
|
|
||||||
ab = new byte[asize];
|
ab = new byte[asize];
|
||||||
asize = getDataInputForSubIdx(subIdx, ab);
|
asize = getDataInputForSubIdx(subIdx, ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatCoderContext bc = new StatCoderContext(ab);
|
StatCoderContext bc = new StatCoderContext(ab);
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
if (!reallyDecode) {
|
||||||
if ( !reallyDecode )
|
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ( hollowNodes == null )
|
if (hollowNodes == null) {
|
||||||
{
|
|
||||||
return new MicroCache2(bc, dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher);
|
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;
|
return MicroCache.emptyNonVirgin;
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
// crc check only if the buffer has not been fully read
|
// crc check only if the buffer has not been fully read
|
||||||
int readBytes = (bc.getReadingBitPosition() + 7) >> 3;
|
int readBytes = (bc.getReadingBitPosition() + 7) >> 3;
|
||||||
if ( readBytes != asize-4 )
|
if (readBytes != asize - 4) {
|
||||||
{
|
|
||||||
int crcData = Crc32.crc(ab, 0, asize - 4);
|
int crcData = Crc32.crc(ab, 0, asize - 4);
|
||||||
int crcFooter = new ByteDataReader(ab, asize - 4).readInt();
|
int crcFooter = new ByteDataReader(ab, asize - 4).readInt();
|
||||||
if ( crcData == crcFooter )
|
if (crcData == crcFooter) {
|
||||||
{
|
|
||||||
throw new IOException("old, unsupported data-format");
|
throw new IOException("old, unsupported data-format");
|
||||||
}
|
} else if ((crcData ^ 2) != crcFooter) {
|
||||||
else if ( ( crcData ^ 2 ) != crcFooter )
|
|
||||||
{
|
|
||||||
throw new IOException("checkum error");
|
throw new IOException("checkum error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,72 +156,58 @@ final class OsmFile
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set this OsmFile to ghost-state:
|
// set this OsmFile to ghost-state:
|
||||||
long setGhostState()
|
long setGhostState() {
|
||||||
{
|
|
||||||
long sum = 0;
|
long sum = 0;
|
||||||
int nc = microCaches == null ? 0 : microCaches.length;
|
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];
|
MicroCache mc = microCaches[i];
|
||||||
if (mc == null)
|
if (mc == null)
|
||||||
continue;
|
continue;
|
||||||
if ( mc.virgin )
|
if (mc.virgin) {
|
||||||
{
|
|
||||||
mc.ghost = true;
|
mc.ghost = true;
|
||||||
sum += mc.getDataSize();
|
sum += mc.getDataSize();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
microCaches[i] = null;
|
microCaches[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
long collectAll()
|
long collectAll() {
|
||||||
{
|
|
||||||
long deleted = 0;
|
long deleted = 0;
|
||||||
int nc = microCaches == null ? 0 : microCaches.length;
|
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];
|
MicroCache mc = microCaches[i];
|
||||||
if (mc == null)
|
if (mc == null)
|
||||||
continue;
|
continue;
|
||||||
if ( !mc.ghost )
|
if (!mc.ghost) {
|
||||||
{
|
|
||||||
deleted += mc.collect(0);
|
deleted += mc.collect(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
long cleanGhosts()
|
long cleanGhosts() {
|
||||||
{
|
|
||||||
long deleted = 0;
|
long deleted = 0;
|
||||||
int nc = microCaches == null ? 0 : microCaches.length;
|
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];
|
MicroCache mc = microCaches[i];
|
||||||
if (mc == null)
|
if (mc == null)
|
||||||
continue;
|
continue;
|
||||||
if ( mc.ghost )
|
if (mc.ghost) {
|
||||||
{
|
|
||||||
microCaches[i] = null;
|
microCaches[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean( boolean all )
|
void clean(boolean all) {
|
||||||
{
|
|
||||||
int nc = microCaches == null ? 0 : microCaches.length;
|
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];
|
MicroCache mc = microCaches[i];
|
||||||
if (mc == null)
|
if (mc == null)
|
||||||
continue;
|
continue;
|
||||||
if ( all || !mc.virgin )
|
if (all || !mc.virgin) {
|
||||||
{
|
|
||||||
microCaches[i] = null;
|
microCaches[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,9 +6,7 @@
|
|||||||
package btools.mapaccess;
|
package btools.mapaccess;
|
||||||
|
|
||||||
|
|
||||||
|
public class OsmLink {
|
||||||
public class OsmLink
|
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* The description bitmap contains the waytags (valid for both directions)
|
* The description bitmap contains the waytags (valid for both directions)
|
||||||
*/
|
*/
|
||||||
@ -30,12 +28,10 @@ public class OsmLink
|
|||||||
private OsmLinkHolder reverselinkholder = null;
|
private OsmLinkHolder reverselinkholder = null;
|
||||||
private OsmLinkHolder firstlinkholder = null;
|
private OsmLinkHolder firstlinkholder = null;
|
||||||
|
|
||||||
protected OsmLink()
|
protected OsmLink() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmLink( OsmNode source, OsmNode target )
|
public OsmLink(OsmNode source, OsmNode target) {
|
||||||
{
|
|
||||||
n1 = source;
|
n1 = source;
|
||||||
n2 = target;
|
n2 = target;
|
||||||
}
|
}
|
||||||
@ -43,8 +39,7 @@ public class OsmLink
|
|||||||
/**
|
/**
|
||||||
* Get the relevant target-node for the given source
|
* 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;
|
return n2 != source && n2 != null ? n2 : n1;
|
||||||
/* if ( n2 != null && n2 != source )
|
/* if ( n2 != null && n2 != source )
|
||||||
{
|
{
|
||||||
@ -64,8 +59,7 @@ public class OsmLink
|
|||||||
/**
|
/**
|
||||||
* Get the relevant next-pointer for the given source
|
* 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;
|
return n2 != source && n2 != null ? next : previous;
|
||||||
/* if ( n2 != null && n2 != source )
|
/* if ( n2 != null && n2 != source )
|
||||||
{
|
{
|
||||||
@ -84,69 +78,49 @@ public class OsmLink
|
|||||||
/**
|
/**
|
||||||
* Reset this link for the given direction
|
* Reset this link for the given direction
|
||||||
*/
|
*/
|
||||||
protected final OsmLink clear( OsmNode source )
|
protected final OsmLink clear(OsmNode source) {
|
||||||
{
|
|
||||||
OsmLink n;
|
OsmLink n;
|
||||||
if ( n2 != null && n2 != source )
|
if (n2 != null && n2 != source) {
|
||||||
{
|
|
||||||
n = next;
|
n = next;
|
||||||
next = null;
|
next = null;
|
||||||
n2 = null;
|
n2 = null;
|
||||||
firstlinkholder = null;
|
firstlinkholder = null;
|
||||||
}
|
} else if (n1 != null && n1 != source) {
|
||||||
else if ( n1 != null && n1 != source )
|
|
||||||
{
|
|
||||||
n = previous;
|
n = previous;
|
||||||
previous = null;
|
previous = null;
|
||||||
n1 = null;
|
n1 = null;
|
||||||
reverselinkholder = null;
|
reverselinkholder = null;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("internal error: setNext: unknown source");
|
throw new IllegalArgumentException("internal error: setNext: unknown source");
|
||||||
}
|
}
|
||||||
if ( n1 == null && n2 == null )
|
if (n1 == null && n2 == null) {
|
||||||
{
|
|
||||||
descriptionBitmap = null;
|
descriptionBitmap = null;
|
||||||
geometry = null;
|
geometry = null;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setFirstLinkHolder( OsmLinkHolder holder, OsmNode source )
|
public final void setFirstLinkHolder(OsmLinkHolder holder, OsmNode source) {
|
||||||
{
|
if (n2 != null && n2 != source) {
|
||||||
if ( n2 != null && n2 != source )
|
|
||||||
{
|
|
||||||
firstlinkholder = holder;
|
firstlinkholder = holder;
|
||||||
}
|
} else if (n1 != null && n1 != source) {
|
||||||
else if ( n1 != null && n1 != source )
|
|
||||||
{
|
|
||||||
reverselinkholder = holder;
|
reverselinkholder = holder;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("internal error: setFirstLinkHolder: unknown source");
|
throw new IllegalArgumentException("internal error: setFirstLinkHolder: unknown source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final OsmLinkHolder getFirstLinkHolder( OsmNode source )
|
public final OsmLinkHolder getFirstLinkHolder(OsmNode source) {
|
||||||
{
|
if (n2 != null && n2 != source) {
|
||||||
if ( n2 != null && n2 != source )
|
|
||||||
{
|
|
||||||
return firstlinkholder;
|
return firstlinkholder;
|
||||||
}
|
} else if (n1 != null && n1 != source) {
|
||||||
else if ( n1 != null && n1 != source )
|
|
||||||
{
|
|
||||||
return reverselinkholder;
|
return reverselinkholder;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("internal error: getFirstLinkHolder: unknown source");
|
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;
|
return n1 != source && n1 != null;
|
||||||
/* if ( n2 != null && n2 != source )
|
/* if ( n2 != null && n2 != source )
|
||||||
{
|
{
|
||||||
@ -162,20 +136,19 @@ public class OsmLink
|
|||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isBidirectional()
|
public final boolean isBidirectional() {
|
||||||
{
|
|
||||||
return n1 != null && n2 != null;
|
return n1 != null && n2 != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isLinkUnused()
|
public final boolean isLinkUnused() {
|
||||||
{
|
|
||||||
return n1 == null && n2 == null;
|
return n1 == null && n2 == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addLinkHolder( OsmLinkHolder holder, OsmNode source )
|
public final void addLinkHolder(OsmLinkHolder holder, OsmNode source) {
|
||||||
{
|
|
||||||
OsmLinkHolder firstHolder = getFirstLinkHolder(source);
|
OsmLinkHolder firstHolder = getFirstLinkHolder(source);
|
||||||
if ( firstHolder != null ) { holder.setNextForLink( firstHolder ); }
|
if (firstHolder != null) {
|
||||||
|
holder.setNextForLink(firstHolder);
|
||||||
|
}
|
||||||
setFirstLinkHolder(holder, source);
|
setFirstLinkHolder(holder, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package btools.mapaccess;
|
package btools.mapaccess;
|
||||||
|
|
||||||
public interface OsmLinkHolder
|
public interface OsmLinkHolder {
|
||||||
{
|
|
||||||
void setNextForLink(OsmLinkHolder holder);
|
void setNextForLink(OsmLinkHolder holder);
|
||||||
|
|
||||||
OsmLinkHolder getNextForLink();
|
OsmLinkHolder getNextForLink();
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import btools.util.ByteArrayUnifier;
|
|||||||
import btools.util.CheapRuler;
|
import btools.util.CheapRuler;
|
||||||
import btools.util.IByteArrayUnifier;
|
import btools.util.IByteArrayUnifier;
|
||||||
|
|
||||||
public class OsmNode extends OsmLink implements OsmPos
|
public class OsmNode extends OsmLink implements OsmPos {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* The latitude
|
* The latitude
|
||||||
*/
|
*/
|
||||||
@ -37,8 +36,7 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
|
|
||||||
public int visitID;
|
public int visitID;
|
||||||
|
|
||||||
public void addTurnRestriction( TurnRestriction tr )
|
public void addTurnRestriction(TurnRestriction tr) {
|
||||||
{
|
|
||||||
tr.next = firstRestriction;
|
tr.next = firstRestriction;
|
||||||
firstRestriction = tr;
|
firstRestriction = tr;
|
||||||
}
|
}
|
||||||
@ -48,62 +46,50 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
*/
|
*/
|
||||||
public OsmLink firstlink;
|
public OsmLink firstlink;
|
||||||
|
|
||||||
public OsmNode()
|
public OsmNode() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNode( int ilon, int ilat )
|
public OsmNode(int ilon, int ilat) {
|
||||||
{
|
|
||||||
this.ilon = ilon;
|
this.ilon = ilon;
|
||||||
this.ilat = ilat;
|
this.ilat = ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNode( long id )
|
public OsmNode(long id) {
|
||||||
{
|
|
||||||
ilon = (int) (id >> 32);
|
ilon = (int) (id >> 32);
|
||||||
ilat = (int) (id & 0xffffffff);
|
ilat = (int) (id & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// interface OsmPos
|
// interface OsmPos
|
||||||
public final int getILat()
|
public final int getILat() {
|
||||||
{
|
|
||||||
return ilat;
|
return ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getILon()
|
public final int getILon() {
|
||||||
{
|
|
||||||
return ilon;
|
return ilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final short getSElev()
|
public final short getSElev() {
|
||||||
{
|
|
||||||
return selev;
|
return selev;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final double getElev()
|
public final double getElev() {
|
||||||
{
|
|
||||||
return selev / 4.;
|
return selev / 4.;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addLink( OsmLink link, boolean isReverse, OsmNode tn )
|
public final void addLink(OsmLink link, boolean isReverse, OsmNode tn) {
|
||||||
{
|
if (link == firstlink) {
|
||||||
if ( link == firstlink )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("UUUUPS");
|
throw new IllegalArgumentException("UUUUPS");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isReverse )
|
if (isReverse) {
|
||||||
{
|
|
||||||
link.n1 = tn;
|
link.n1 = tn;
|
||||||
link.n2 = this;
|
link.n2 = this;
|
||||||
link.next = tn.firstlink;
|
link.next = tn.firstlink;
|
||||||
link.previous = firstlink;
|
link.previous = firstlink;
|
||||||
tn.firstlink = link;
|
tn.firstlink = link;
|
||||||
firstlink = link;
|
firstlink = link;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
link.n1 = this;
|
link.n1 = this;
|
||||||
link.n2 = tn;
|
link.n2 = tn;
|
||||||
link.next = firstlink;
|
link.next = firstlink;
|
||||||
@ -113,33 +99,26 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int calcDistance( OsmPos p )
|
public final int calcDistance(OsmPos p) {
|
||||||
{
|
|
||||||
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
|
return (int) (CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString()
|
public String toString() {
|
||||||
{
|
|
||||||
return "n_" + (ilon - 180000000) + "_" + (ilat - 90000000);
|
return "n_" + (ilon - 180000000) + "_" + (ilat - 90000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay )
|
public final void parseNodeBody(MicroCache mc, OsmNodesMap hollowNodes, IByteArrayUnifier expCtxWay) {
|
||||||
{
|
if (mc instanceof MicroCache2) {
|
||||||
if ( mc instanceof MicroCache2 )
|
|
||||||
{
|
|
||||||
parseNodeBody2((MicroCache2) mc, hollowNodes, expCtxWay);
|
parseNodeBody2((MicroCache2) mc, hollowNodes, expCtxWay);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("unknown cache version: " + mc.getClass());
|
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();
|
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
|
||||||
|
|
||||||
// read turn restrictions
|
// read turn restrictions
|
||||||
while( mc.readBoolean() )
|
while (mc.readBoolean()) {
|
||||||
{
|
|
||||||
TurnRestriction tr = new TurnRestriction();
|
TurnRestriction tr = new TurnRestriction();
|
||||||
tr.exceptions = mc.readShort();
|
tr.exceptions = mc.readShort();
|
||||||
tr.isPositive = mc.readBoolean();
|
tr.isPositive = mc.readBoolean();
|
||||||
@ -154,8 +133,7 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
int nodeDescSize = mc.readVarLengthUnsigned();
|
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
|
// read link data
|
||||||
int endPointer = mc.getEndPointer();
|
int endPointer = mc.getEndPointer();
|
||||||
int linklon = ilon + mc.readVarLengthSigned();
|
int linklon = ilon + mc.readVarLengthSigned();
|
||||||
@ -164,8 +142,7 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
boolean isReverse = (sizecode & 1) != 0;
|
boolean isReverse = (sizecode & 1) != 0;
|
||||||
byte[] description = null;
|
byte[] description = null;
|
||||||
int descSize = sizecode >> 1;
|
int descSize = sizecode >> 1;
|
||||||
if ( descSize > 0 )
|
if (descSize > 0) {
|
||||||
{
|
|
||||||
description = mc.readUnified(descSize, expCtxWay);
|
description = mc.readUnified(descSize, expCtxWay);
|
||||||
}
|
}
|
||||||
byte[] geometry = mc.readDataUntil(endPointer);
|
byte[] geometry = mc.readDataUntil(endPointer);
|
||||||
@ -175,10 +152,8 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
hollowNodes.remove(this);
|
hollowNodes.remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLink( int linklon, int linklat, byte[] description, byte[] geometry, OsmNodesMap hollowNodes, boolean isReverse )
|
public void addLink(int linklon, int linklat, byte[] description, byte[] geometry, OsmNodesMap hollowNodes, boolean isReverse) {
|
||||||
{
|
if (linklon == ilon && linklat == ilat) {
|
||||||
if ( linklon == ilon && linklat == ilat )
|
|
||||||
{
|
|
||||||
return; // skip self-ref
|
return; // skip self-ref
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,14 +161,11 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
OsmLink link = null;
|
OsmLink link = null;
|
||||||
|
|
||||||
// ...in our known links
|
// ...in our known links
|
||||||
for ( OsmLink l = firstlink; l != null; l = l.getNext( this ) )
|
for (OsmLink l = firstlink; l != null; l = l.getNext(this)) {
|
||||||
{
|
|
||||||
OsmNode t = l.getTarget(this);
|
OsmNode t = l.getTarget(this);
|
||||||
if ( t.ilon == linklon && t.ilat == linklat )
|
if (t.ilon == linklon && t.ilat == linklat) {
|
||||||
{
|
|
||||||
tn = t;
|
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
|
link = l; // the correct one that needs our data
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -210,47 +182,37 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
addLink(link = tn, isReverse, tn); // technical inheritance: link instance in node
|
addLink(link = tn, isReverse, tn); // technical inheritance: link instance in node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( link == null )
|
if (link == null) {
|
||||||
{
|
|
||||||
addLink(link = new OsmLink(), isReverse, tn);
|
addLink(link = new OsmLink(), isReverse, tn);
|
||||||
}
|
}
|
||||||
if ( !isReverse )
|
if (!isReverse) {
|
||||||
{
|
|
||||||
link.descriptionBitmap = description;
|
link.descriptionBitmap = description;
|
||||||
link.geometry = geometry;
|
link.geometry = geometry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final boolean isHollow()
|
public final boolean isHollow() {
|
||||||
{
|
|
||||||
return selev == -12345;
|
return selev == -12345;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setHollow()
|
public final void setHollow() {
|
||||||
{
|
|
||||||
selev = -12345;
|
selev = -12345;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final long getIdFromPos()
|
public final long getIdFromPos() {
|
||||||
{
|
|
||||||
return ((long) ilon) << 32 | ilat;
|
return ((long) ilon) << 32 | ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void vanish()
|
public void vanish() {
|
||||||
{
|
if (!isHollow()) {
|
||||||
if ( !isHollow() )
|
|
||||||
{
|
|
||||||
OsmLink l = firstlink;
|
OsmLink l = firstlink;
|
||||||
while( l != null )
|
while (l != null) {
|
||||||
{
|
|
||||||
OsmNode target = l.getTarget(this);
|
OsmNode target = l.getTarget(this);
|
||||||
OsmLink nextLink = l.getNext(this);
|
OsmLink nextLink = l.getNext(this);
|
||||||
if ( !target.isHollow() )
|
if (!target.isHollow()) {
|
||||||
{
|
|
||||||
unlinkLink(l);
|
unlinkLink(l);
|
||||||
if ( !l.isLinkUnused() )
|
if (!l.isLinkUnused()) {
|
||||||
{
|
|
||||||
target.unlinkLink(l);
|
target.unlinkLink(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,41 +221,32 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void unlinkLink( OsmLink link )
|
public final void unlinkLink(OsmLink link) {
|
||||||
{
|
|
||||||
OsmLink n = link.clear(this);
|
OsmLink n = link.clear(this);
|
||||||
|
|
||||||
if ( link == firstlink )
|
if (link == firstlink) {
|
||||||
{
|
|
||||||
firstlink = n;
|
firstlink = n;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OsmLink l = firstlink;
|
OsmLink l = firstlink;
|
||||||
while( l != null )
|
while (l != null) {
|
||||||
{
|
|
||||||
// if ( l.isReverse( this ) )
|
// 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;
|
OsmLink nl = l.previous;
|
||||||
if ( nl == link )
|
if (nl == link) {
|
||||||
{
|
|
||||||
l.previous = n;
|
l.previous = n;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
l = nl;
|
l = nl;
|
||||||
}
|
} else if (l.n2 != this && l.n2 != null) {
|
||||||
else if ( l.n2 != this && l.n2 != null )
|
|
||||||
{
|
|
||||||
OsmLink nl = l.next;
|
OsmLink nl = l.next;
|
||||||
if ( nl == link )
|
if (nl == link) {
|
||||||
{
|
|
||||||
l.next = n;
|
l.next = n;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
l = nl;
|
l = nl;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unlinkLink: unknown source");
|
throw new IllegalArgumentException("unlinkLink: unknown source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,14 +254,12 @@ public class OsmNode extends OsmLink implements OsmPos
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals( Object o )
|
public final boolean equals(Object o) {
|
||||||
{
|
|
||||||
return ((OsmNode) o).ilon == ilon && ((OsmNode) o).ilat == ilat;
|
return ((OsmNode) o).ilon == ilon && ((OsmNode) o).ilat == ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode()
|
public final int hashCode() {
|
||||||
{
|
|
||||||
return ilon + ilat;
|
return ilon + ilat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,7 @@ package btools.mapaccess;
|
|||||||
|
|
||||||
import btools.util.CompactLongMap;
|
import btools.util.CompactLongMap;
|
||||||
|
|
||||||
public class OsmNodePairSet
|
public class OsmNodePairSet {
|
||||||
{
|
|
||||||
private long[] n1a;
|
private long[] n1a;
|
||||||
private long[] n2a;
|
private long[] n2a;
|
||||||
private int tempNodes = 0;
|
private int tempNodes = 0;
|
||||||
@ -16,108 +15,86 @@ public class OsmNodePairSet
|
|||||||
private int npairs = 0;
|
private int npairs = 0;
|
||||||
private int freezecount = 0;
|
private int freezecount = 0;
|
||||||
|
|
||||||
public OsmNodePairSet( int maxTempNodeCount )
|
public OsmNodePairSet(int maxTempNodeCount) {
|
||||||
{
|
|
||||||
maxTempNodes = maxTempNodeCount;
|
maxTempNodes = maxTempNodeCount;
|
||||||
n1a = new long[maxTempNodes];
|
n1a = new long[maxTempNodes];
|
||||||
n2a = new long[maxTempNodes];
|
n2a = new long[maxTempNodes];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class OsmNodePair
|
private static class OsmNodePair {
|
||||||
{
|
|
||||||
public long node2;
|
public long node2;
|
||||||
public OsmNodePair next;
|
public OsmNodePair next;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompactLongMap<OsmNodePair> map;
|
private CompactLongMap<OsmNodePair> map;
|
||||||
|
|
||||||
public void addTempPair( long n1, long n2 )
|
public void addTempPair(long n1, long n2) {
|
||||||
{
|
if (tempNodes < maxTempNodes) {
|
||||||
if ( tempNodes < maxTempNodes )
|
|
||||||
{
|
|
||||||
n1a[tempNodes] = n1;
|
n1a[tempNodes] = n1;
|
||||||
n2a[tempNodes] = n2;
|
n2a[tempNodes] = n2;
|
||||||
tempNodes++;
|
tempNodes++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void freezeTempPairs()
|
public void freezeTempPairs() {
|
||||||
{
|
|
||||||
freezecount++;
|
freezecount++;
|
||||||
for( int i=0; i<tempNodes; i++ )
|
for (int i = 0; i < tempNodes; i++) {
|
||||||
{
|
|
||||||
addPair(n1a[i], n2a[i]);
|
addPair(n1a[i], n2a[i]);
|
||||||
}
|
}
|
||||||
tempNodes = 0;
|
tempNodes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearTempPairs()
|
public void clearTempPairs() {
|
||||||
{
|
|
||||||
tempNodes = 0;
|
tempNodes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPair( long n1, long n2 )
|
private void addPair(long n1, long n2) {
|
||||||
{
|
if (map == null) {
|
||||||
if ( map == null )
|
|
||||||
{
|
|
||||||
map = new CompactLongMap<OsmNodePair>();
|
map = new CompactLongMap<OsmNodePair>();
|
||||||
}
|
}
|
||||||
npairs++;
|
npairs++;
|
||||||
|
|
||||||
OsmNodePair e = getElement(n1, n2);
|
OsmNodePair e = getElement(n1, n2);
|
||||||
if ( e == null )
|
if (e == null) {
|
||||||
{
|
|
||||||
e = new OsmNodePair();
|
e = new OsmNodePair();
|
||||||
e.node2 = n2;
|
e.node2 = n2;
|
||||||
|
|
||||||
OsmNodePair e0 = map.get(n1);
|
OsmNodePair e0 = map.get(n1);
|
||||||
if ( e0 != null )
|
if (e0 != null) {
|
||||||
{
|
while (e0.next != null) {
|
||||||
while( e0.next != null )
|
|
||||||
{
|
|
||||||
e0 = e0.next;
|
e0 = e0.next;
|
||||||
}
|
}
|
||||||
e0.next = e;
|
e0.next = e;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
map.fastPut(n1, e);
|
map.fastPut(n1, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size()
|
public int size() {
|
||||||
{
|
|
||||||
return npairs;
|
return npairs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int tempSize()
|
public int tempSize() {
|
||||||
{
|
|
||||||
return tempNodes;
|
return tempNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxTmpNodes()
|
public int getMaxTmpNodes() {
|
||||||
{
|
|
||||||
return maxTempNodes;
|
return maxTempNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFreezeCount()
|
public int getFreezeCount() {
|
||||||
{
|
|
||||||
return freezecount;
|
return freezecount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPair( long n1, long n2 )
|
public boolean hasPair(long n1, long n2) {
|
||||||
{
|
|
||||||
return map != null && (getElement(n1, n2) != null || getElement(n2, n1) != null);
|
return map != null && (getElement(n1, n2) != null || getElement(n2, n1) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OsmNodePair getElement( long n1, long n2 )
|
private OsmNodePair getElement(long n1, long n2) {
|
||||||
{
|
|
||||||
OsmNodePair e = map.get(n1);
|
OsmNodePair e = map.get(n1);
|
||||||
while (e != null)
|
while (e != null) {
|
||||||
{
|
if (e.node2 == n2) {
|
||||||
if ( e.node2 == n2 )
|
|
||||||
{
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
e = e.next;
|
e = e.next;
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import java.util.HashMap;
|
|||||||
import btools.util.ByteArrayUnifier;
|
import btools.util.ByteArrayUnifier;
|
||||||
import btools.util.SortedHeap;
|
import btools.util.SortedHeap;
|
||||||
|
|
||||||
public final class OsmNodesMap
|
public final class OsmNodesMap {
|
||||||
{
|
|
||||||
private HashMap<OsmNode, OsmNode> hmap = new HashMap<OsmNode, OsmNode>(4096);
|
private HashMap<OsmNode, OsmNode> hmap = new HashMap<OsmNode, OsmNode>(4096);
|
||||||
|
|
||||||
private ByteArrayUnifier abUnifier = new ByteArrayUnifier(16384, false);
|
private ByteArrayUnifier abUnifier = new ByteArrayUnifier(16384, false);
|
||||||
@ -34,46 +33,33 @@ public final class OsmNodesMap
|
|||||||
|
|
||||||
public int cleanupMode = 0;
|
public int cleanupMode = 0;
|
||||||
|
|
||||||
public void cleanupAndCount( OsmNode[] nodes )
|
public void cleanupAndCount(OsmNode[] nodes) {
|
||||||
{
|
if (cleanupMode == 0) {
|
||||||
if ( cleanupMode == 0 )
|
|
||||||
{
|
|
||||||
justCount(nodes);
|
justCount(nodes);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cleanupPeninsulas(nodes);
|
cleanupPeninsulas(nodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void justCount( OsmNode[] nodes )
|
private void justCount(OsmNode[] nodes) {
|
||||||
{
|
for (int i = 0; i < nodes.length; i++) {
|
||||||
for( int i=0; i<nodes.length; i++ )
|
|
||||||
{
|
|
||||||
OsmNode n = nodes[i];
|
OsmNode n = nodes[i];
|
||||||
if ( n.firstlink != null )
|
if (n.firstlink != null) {
|
||||||
{
|
|
||||||
nodesCreated++;
|
nodesCreated++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanupPeninsulas( OsmNode[] nodes )
|
private void cleanupPeninsulas(OsmNode[] nodes) {
|
||||||
{
|
|
||||||
baseID = lastVisitID++;
|
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];
|
OsmNode n = nodes[i];
|
||||||
if ( n.firstlink != null )
|
if (n.firstlink != null) {
|
||||||
{
|
if (n.visitID == 1) {
|
||||||
if ( n.visitID == 1 )
|
try {
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
minVisitIdInSubtree(null, n);
|
minVisitIdInSubtree(null, n);
|
||||||
}
|
} catch (StackOverflowError soe) {
|
||||||
catch( StackOverflowError soe )
|
|
||||||
{
|
|
||||||
// System.out.println( "+++++++++++++++ StackOverflowError ++++++++++++++++" );
|
// System.out.println( "+++++++++++++++ StackOverflowError ++++++++++++++++" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,16 +67,14 @@ public final class OsmNodesMap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int minVisitIdInSubtree( OsmNode source, OsmNode n )
|
private int minVisitIdInSubtree(OsmNode source, OsmNode n) {
|
||||||
{
|
|
||||||
if (n.visitID == 1) n.visitID = baseID; // border node
|
if (n.visitID == 1) n.visitID = baseID; // border node
|
||||||
else n.visitID = lastVisitID++;
|
else n.visitID = lastVisitID++;
|
||||||
int minId = n.visitID;
|
int minId = n.visitID;
|
||||||
nodesCreated++;
|
nodesCreated++;
|
||||||
|
|
||||||
OsmLink nextLink = null;
|
OsmLink nextLink = null;
|
||||||
for( OsmLink l = n.firstlink; l != null; l = nextLink )
|
for (OsmLink l = n.firstlink; l != null; l = nextLink) {
|
||||||
{
|
|
||||||
nextLink = l.getNext(n);
|
nextLink = l.getNext(n);
|
||||||
|
|
||||||
OsmNode t = l.getTarget(n);
|
OsmNode t = l.getTarget(n);
|
||||||
@ -98,12 +82,9 @@ public final class OsmNodesMap
|
|||||||
if (t.isHollow()) continue;
|
if (t.isHollow()) continue;
|
||||||
|
|
||||||
int minIdSub = t.visitID;
|
int minIdSub = t.visitID;
|
||||||
if ( minIdSub == 1 )
|
if (minIdSub == 1) {
|
||||||
{
|
|
||||||
minIdSub = baseID;
|
minIdSub = baseID;
|
||||||
}
|
} else if (minIdSub == 0) {
|
||||||
else if ( minIdSub == 0 )
|
|
||||||
{
|
|
||||||
int nodesCreatedUntilHere = nodesCreated;
|
int nodesCreatedUntilHere = nodesCreated;
|
||||||
minIdSub = minVisitIdInSubtree(n, t);
|
minIdSub = minVisitIdInSubtree(n, t);
|
||||||
if (minIdSub > n.visitID) // peninsula ?
|
if (minIdSub > n.visitID) // peninsula ?
|
||||||
@ -112,13 +93,9 @@ public final class OsmNodesMap
|
|||||||
n.unlinkLink(l);
|
n.unlinkLink(l);
|
||||||
t.unlinkLink(l);
|
t.unlinkLink(l);
|
||||||
}
|
}
|
||||||
}
|
} else if (minIdSub < baseID) {
|
||||||
else if ( minIdSub < baseID )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
} else if (cleanupMode == 2) {
|
||||||
else if ( cleanupMode == 2 )
|
|
||||||
{
|
|
||||||
minIdSub = baseID; // in tree-mode, hitting anything is like a gateway
|
minIdSub = baseID; // in tree-mode, hitting anything is like a gateway
|
||||||
}
|
}
|
||||||
if (minIdSub < minId) minId = minIdSub;
|
if (minIdSub < minId) minId = minIdSub;
|
||||||
@ -127,23 +104,18 @@ public final class OsmNodesMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isInMemoryBounds(int npaths, boolean extend) {
|
||||||
public boolean isInMemoryBounds( int npaths, boolean extend )
|
|
||||||
{
|
|
||||||
// long total = nodesCreated * 76L + linksCreated * 48L;
|
// long total = nodesCreated * 76L + linksCreated * 48L;
|
||||||
long total = nodesCreated * 95L + npaths * 200L;
|
long total = nodesCreated * 95L + npaths * 200L;
|
||||||
|
|
||||||
if ( extend )
|
if (extend) {
|
||||||
{
|
|
||||||
total += 100000;
|
total += 100000;
|
||||||
|
|
||||||
// when extending, try to have 1 MB space
|
// when extending, try to have 1 MB space
|
||||||
long delta = total + 1900000 - currentmaxmem;
|
long delta = total + 1900000 - currentmaxmem;
|
||||||
if ( delta > 0 )
|
if (delta > 0) {
|
||||||
{
|
|
||||||
currentmaxmem += delta;
|
currentmaxmem += delta;
|
||||||
if ( currentmaxmem > maxmem )
|
if (currentmaxmem > maxmem) {
|
||||||
{
|
|
||||||
currentmaxmem = maxmem;
|
currentmaxmem = maxmem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,8 +123,7 @@ public final class OsmNodesMap
|
|||||||
return total <= currentmaxmem;
|
return total <= currentmaxmem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addActiveNode( ArrayList<OsmNode> nodes2check, OsmNode n )
|
private void addActiveNode(ArrayList<OsmNode> nodes2check, OsmNode n) {
|
||||||
{
|
|
||||||
n.visitID = lastVisitID;
|
n.visitID = lastVisitID;
|
||||||
nodesCreated++;
|
nodesCreated++;
|
||||||
nodes2check.add(n);
|
nodes2check.add(n);
|
||||||
@ -160,45 +131,35 @@ public final class OsmNodesMap
|
|||||||
|
|
||||||
// is there an escape from this node
|
// is there an escape from this node
|
||||||
// to a hollow node (or destination node) ?
|
// to a hollow node (or destination node) ?
|
||||||
public boolean canEscape( OsmNode n0 )
|
public boolean canEscape(OsmNode n0) {
|
||||||
{
|
|
||||||
boolean sawLowIDs = false;
|
boolean sawLowIDs = false;
|
||||||
lastVisitID++;
|
lastVisitID++;
|
||||||
nodes2check.clear();
|
nodes2check.clear();
|
||||||
nodes2check.add(n0);
|
nodes2check.add(n0);
|
||||||
while ( !nodes2check.isEmpty() )
|
while (!nodes2check.isEmpty()) {
|
||||||
{
|
|
||||||
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
|
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
|
||||||
if ( n.visitID < baseID )
|
if (n.visitID < baseID) {
|
||||||
{
|
|
||||||
n.visitID = lastVisitID;
|
n.visitID = lastVisitID;
|
||||||
nodesCreated++;
|
nodesCreated++;
|
||||||
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
|
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
|
||||||
{
|
|
||||||
OsmNode t = l.getTarget(n);
|
OsmNode t = l.getTarget(n);
|
||||||
nodes2check.add(t);
|
nodes2check.add(t);
|
||||||
}
|
}
|
||||||
}
|
} else if (n.visitID < lastVisitID) {
|
||||||
else if ( n.visitID < lastVisitID )
|
|
||||||
{
|
|
||||||
sawLowIDs = true;
|
sawLowIDs = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( sawLowIDs )
|
if (sawLowIDs) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes2check.add(n0);
|
nodes2check.add(n0);
|
||||||
while ( !nodes2check.isEmpty() )
|
while (!nodes2check.isEmpty()) {
|
||||||
{
|
|
||||||
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
|
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
|
||||||
if ( n.visitID == lastVisitID )
|
if (n.visitID == lastVisitID) {
|
||||||
{
|
|
||||||
n.visitID = lastVisitID;
|
n.visitID = lastVisitID;
|
||||||
nodesCreated--;
|
nodesCreated--;
|
||||||
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
|
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
|
||||||
{
|
|
||||||
OsmNode t = l.getTarget(n);
|
OsmNode t = l.getTarget(n);
|
||||||
nodes2check.add(t);
|
nodes2check.add(t);
|
||||||
}
|
}
|
||||||
@ -211,71 +172,60 @@ public final class OsmNodesMap
|
|||||||
|
|
||||||
private ArrayList<OsmNode> nodes2check;
|
private ArrayList<OsmNode> nodes2check;
|
||||||
|
|
||||||
public void clearTemp()
|
public void clearTemp() {
|
||||||
{
|
|
||||||
nodes2check = null;
|
nodes2check = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectOutreachers()
|
public void collectOutreachers() {
|
||||||
{
|
|
||||||
nodes2check = new ArrayList<OsmNode>(nodesCreated);
|
nodes2check = new ArrayList<OsmNode>(nodesCreated);
|
||||||
nodesCreated = 0;
|
nodesCreated = 0;
|
||||||
for( OsmNode n : hmap.values() )
|
for (OsmNode n : hmap.values()) {
|
||||||
{
|
|
||||||
addActiveNode(nodes2check, n);
|
addActiveNode(nodes2check, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastVisitID++;
|
lastVisitID++;
|
||||||
baseID = lastVisitID;
|
baseID = lastVisitID;
|
||||||
|
|
||||||
while ( !nodes2check.isEmpty() )
|
while (!nodes2check.isEmpty()) {
|
||||||
{
|
|
||||||
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
|
OsmNode n = nodes2check.remove(nodes2check.size() - 1);
|
||||||
n.visitID = lastVisitID;
|
n.visitID = lastVisitID;
|
||||||
|
|
||||||
for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) )
|
for (OsmLink l = n.firstlink; l != null; l = l.getNext(n)) {
|
||||||
{
|
|
||||||
OsmNode t = l.getTarget(n);
|
OsmNode t = l.getTarget(n);
|
||||||
if ( t.visitID != lastVisitID )
|
if (t.visitID != lastVisitID) {
|
||||||
{
|
|
||||||
addActiveNode(nodes2check, t);
|
addActiveNode(nodes2check, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( destination != null && currentMaxCost < 1000000000 )
|
if (destination != null && currentMaxCost < 1000000000) {
|
||||||
{
|
|
||||||
int distance = n.calcDistance(destination);
|
int distance = n.calcDistance(destination);
|
||||||
if ( distance > currentMaxCost - currentPathCost + 100 )
|
if (distance > currentMaxCost - currentPathCost + 100) {
|
||||||
{
|
|
||||||
n.vanish();
|
n.vanish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( n.firstlink == null )
|
if (n.firstlink == null) {
|
||||||
{
|
|
||||||
nodesCreated--;
|
nodesCreated--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ByteArrayUnifier getByteArrayUnifier()
|
public ByteArrayUnifier getByteArrayUnifier() {
|
||||||
{
|
|
||||||
return abUnifier;
|
return abUnifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a node from the map
|
* Get a node from the map
|
||||||
|
*
|
||||||
* @return the node for the given id if exist, else null
|
* @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.ilon = ilon;
|
||||||
testKey.ilat = ilat;
|
testKey.ilat = ilat;
|
||||||
return hmap.get(testKey);
|
return hmap.get(testKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void remove( OsmNode node )
|
public void remove(OsmNode node) {
|
||||||
{
|
|
||||||
if (node != endNode1 && node != endNode2) // keep endnodes in hollow-map even when loaded
|
if (node != endNode1 && node != endNode2) // keep endnodes in hollow-map even when loaded
|
||||||
{ // (needed for escape analysis)
|
{ // (needed for escape analysis)
|
||||||
hmap.remove(node);
|
hmap.remove(node);
|
||||||
@ -284,37 +234,32 @@ public final class OsmNodesMap
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Put a node into the map
|
* Put a node into the map
|
||||||
|
*
|
||||||
* @return the previous node if that id existed, else null
|
* @return the previous node if that id existed, else null
|
||||||
*/
|
*/
|
||||||
public OsmNode put( OsmNode node )
|
public OsmNode put(OsmNode node) {
|
||||||
{
|
|
||||||
return hmap.put(node, node);
|
return hmap.put(node, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ********************** test cleanup **********************
|
// ********************** 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];
|
OsmNode n = nodes[idx];
|
||||||
n.visitID = isBorder ? 1 : 0;
|
n.visitID = isBorder ? 1 : 0;
|
||||||
n.selev = (short) idx;
|
n.selev = (short) idx;
|
||||||
for( int i : links )
|
for (int i : links) {
|
||||||
{
|
|
||||||
OsmNode t = nodes[i];
|
OsmNode t = nodes[i];
|
||||||
OsmLink link = n.isLinkUnused() ? n : (t.isLinkUnused() ? t : null);
|
OsmLink link = n.isLinkUnused() ? n : (t.isLinkUnused() ? t : null);
|
||||||
if ( link == null )
|
if (link == null) {
|
||||||
{
|
|
||||||
link = new OsmLink();
|
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];
|
OsmNode[] nodes = new OsmNode[12];
|
||||||
for( int i=0; i<nodes.length; i++ )
|
for (int i = 0; i < nodes.length; i++) {
|
||||||
{
|
|
||||||
nodes[i] = new OsmNode((i + 1000) * 1000, (i + 1000) * 1000);
|
nodes[i] = new OsmNode((i + 1000) * 1000, (i + 1000) * 1000);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,7 @@
|
|||||||
package btools.mapaccess;
|
package btools.mapaccess;
|
||||||
|
|
||||||
|
|
||||||
public interface OsmPos
|
public interface OsmPos {
|
||||||
{
|
|
||||||
public int getILat();
|
public int getILat();
|
||||||
|
|
||||||
public int getILon();
|
public int getILon();
|
||||||
|
|||||||
@ -6,10 +6,7 @@
|
|||||||
package btools.mapaccess;
|
package btools.mapaccess;
|
||||||
|
|
||||||
|
|
||||||
|
public final class OsmTransferNode {
|
||||||
|
|
||||||
public final class OsmTransferNode
|
|
||||||
{
|
|
||||||
public OsmTransferNode next;
|
public OsmTransferNode next;
|
||||||
|
|
||||||
public int ilon;
|
public int ilon;
|
||||||
|
|||||||
@ -14,8 +14,7 @@ import btools.codec.MicroCache;
|
|||||||
import btools.util.ByteDataReader;
|
import btools.util.ByteDataReader;
|
||||||
import btools.util.Crc32;
|
import btools.util.Crc32;
|
||||||
|
|
||||||
final public class PhysicalFile
|
final public class PhysicalFile {
|
||||||
{
|
|
||||||
RandomAccessFile ra = null;
|
RandomAccessFile ra = null;
|
||||||
long[] fileIndex = new long[25];
|
long[] fileIndex = new long[25];
|
||||||
int[] fileHeaderCrcs;
|
int[] fileHeaderCrcs;
|
||||||
@ -27,8 +26,7 @@ final public class PhysicalFile
|
|||||||
|
|
||||||
public int divisor = 80;
|
public int divisor = 80;
|
||||||
|
|
||||||
public static void main( String[] args )
|
public static void main(String[] args) {
|
||||||
{
|
|
||||||
MicroCache.debug = true;
|
MicroCache.debug = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -45,11 +43,9 @@ final public class PhysicalFile
|
|||||||
*
|
*
|
||||||
* @return the error message if file corrupt, else null
|
* @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;
|
PhysicalFile pf = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
DataBuffers dataBuffers = new DataBuffers();
|
DataBuffers dataBuffers = new DataBuffers();
|
||||||
pf = new PhysicalFile(f, dataBuffers, -1, -1);
|
pf = new PhysicalFile(f, dataBuffers, -1, -1);
|
||||||
int div = pf.divisor;
|
int div = pf.divisor;
|
||||||
@ -64,35 +60,27 @@ final public class PhysicalFile
|
|||||||
osmf.createMicroCache(lonDegree * div + lonIdx, latDegree * div + latIdx, dataBuffers, null, null, MicroCache.debug, null);
|
osmf.createMicroCache(lonDegree * div + lonIdx, latDegree * div + latIdx, dataBuffers, null, null, MicroCache.debug, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (pf != null)
|
if (pf != null)
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
pf.ra.close();
|
pf.ra.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
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();
|
fileName = f.getName();
|
||||||
byte[] iobuffer = dataBuffers.iobuffer;
|
byte[] iobuffer = dataBuffers.iobuffer;
|
||||||
ra = new RandomAccessFile(f, "r");
|
ra = new RandomAccessFile(f, "r");
|
||||||
ra.readFully(iobuffer, 0, 200);
|
ra.readFully(iobuffer, 0, 200);
|
||||||
fileIndexCrc = Crc32.crc(iobuffer, 0, 200);
|
fileIndexCrc = Crc32.crc(iobuffer, 0, 200);
|
||||||
ByteDataReader dis = new ByteDataReader(iobuffer);
|
ByteDataReader dis = new ByteDataReader(iobuffer);
|
||||||
for( int i=0; i<25; i++ )
|
for (int i = 0; i < 25; i++) {
|
||||||
{
|
|
||||||
long lv = dis.readLong();
|
long lv = dis.readLong();
|
||||||
short readVersion = (short) (lv >> 48);
|
short readVersion = (short) (lv >> 48);
|
||||||
if ( i == 0 && lookupVersion != -1 && readVersion != lookupVersion )
|
if (i == 0 && lookupVersion != -1 && readVersion != lookupVersion) {
|
||||||
{
|
|
||||||
throw new IOException("lookup version mismatch (old rd5?) lookups.dat="
|
throw new IOException("lookup version mismatch (old rd5?) lookups.dat="
|
||||||
+ lookupVersion + " " + f.getAbsolutePath() + "=" + readVersion);
|
+ lookupVersion + " " + f.getAbsolutePath() + "=" + readVersion);
|
||||||
}
|
}
|
||||||
@ -118,21 +106,15 @@ final public class PhysicalFile
|
|||||||
creationTime = dis.readLong();
|
creationTime = dis.readLong();
|
||||||
|
|
||||||
int crcData = dis.readInt();
|
int crcData = dis.readInt();
|
||||||
if ( crcData == fileIndexCrc )
|
if (crcData == fileIndexCrc) {
|
||||||
{
|
|
||||||
divisor = 80; // old format
|
divisor = 80; // old format
|
||||||
}
|
} else if ((crcData ^ 2) == fileIndexCrc) {
|
||||||
else if ( (crcData ^ 2) == fileIndexCrc )
|
|
||||||
{
|
|
||||||
divisor = 32; // new format
|
divisor = 32; // new format
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IOException("top index checksum error");
|
throw new IOException("top index checksum error");
|
||||||
}
|
}
|
||||||
fileHeaderCrcs = new int[25];
|
fileHeaderCrcs = new int[25];
|
||||||
for( int i=0; i<25; i++ )
|
for (int i = 0; i < 25; i++) {
|
||||||
{
|
|
||||||
fileHeaderCrcs[i] = dis.readInt();
|
fileHeaderCrcs[i] = dis.readInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,38 +13,31 @@ import java.security.DigestInputStream;
|
|||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
final public class Rd5DiffManager
|
final public class Rd5DiffManager {
|
||||||
{
|
public static void main(String[] args) throws Exception {
|
||||||
public static void main( String[] args ) throws Exception
|
|
||||||
{
|
|
||||||
calcDiffs(new File(args[0]), new File(args[1]));
|
calcDiffs(new File(args[0]), new File(args[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute diffs for all RD5 files
|
* Compute diffs for all RD5 files
|
||||||
*/
|
*/
|
||||||
public static void calcDiffs( File oldDir, File newDir ) throws Exception
|
public static void calcDiffs(File oldDir, File newDir) throws Exception {
|
||||||
{
|
|
||||||
File oldDiffDir = new File(oldDir, "diff");
|
File oldDiffDir = new File(oldDir, "diff");
|
||||||
File newDiffDir = new File(newDir, "diff");
|
File newDiffDir = new File(newDir, "diff");
|
||||||
|
|
||||||
File[] filesNew = newDir.listFiles();
|
File[] filesNew = newDir.listFiles();
|
||||||
|
|
||||||
for( File fn : filesNew )
|
for (File fn : filesNew) {
|
||||||
{
|
|
||||||
String name = fn.getName();
|
String name = fn.getName();
|
||||||
if ( !name.endsWith( ".rd5" ) )
|
if (!name.endsWith(".rd5")) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( fn.length() < 1024*1024 )
|
if (fn.length() < 1024 * 1024) {
|
||||||
{
|
|
||||||
continue; // exclude very small files from diffing
|
continue; // exclude very small files from diffing
|
||||||
}
|
}
|
||||||
String basename = name.substring(0, name.length() - 4);
|
String basename = name.substring(0, name.length() - 4);
|
||||||
File fo = new File(oldDir, name);
|
File fo = new File(oldDir, name);
|
||||||
if ( !fo.isFile() )
|
if (!fo.isFile()) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,23 +63,18 @@ final public class Rd5DiffManager
|
|||||||
|
|
||||||
// ... and add that to old diff files
|
// ... and add that to old diff files
|
||||||
File specificOldDiffs = new File(oldDiffDir, basename);
|
File specificOldDiffs = new File(oldDiffDir, basename);
|
||||||
if ( specificOldDiffs.isDirectory() )
|
if (specificOldDiffs.isDirectory()) {
|
||||||
{
|
|
||||||
File[] oldDiffs = specificOldDiffs.listFiles();
|
File[] oldDiffs = specificOldDiffs.listFiles();
|
||||||
for( File od : oldDiffs )
|
for (File od : oldDiffs) {
|
||||||
{
|
if (!od.getName().endsWith(".df5")) {
|
||||||
if ( !od.getName().endsWith( ".df5" ) )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( System.currentTimeMillis() - od.lastModified() > 9*86400000L )
|
if (System.currentTimeMillis() - od.lastModified() > 9 * 86400000L) {
|
||||||
{
|
|
||||||
continue; // limit diff history to 9 days
|
continue; // limit diff history to 9 days
|
||||||
}
|
}
|
||||||
|
|
||||||
File updatedDiff = new File(specificNewDiffs, od.getName());
|
File updatedDiff = new File(specificNewDiffs, od.getName());
|
||||||
if ( !updatedDiff.exists() )
|
if (!updatedDiff.exists()) {
|
||||||
{
|
|
||||||
Rd5DiffTool.addDeltas(od, diffFile, updatedDiff);
|
Rd5DiffTool.addDeltas(od, diffFile, updatedDiff);
|
||||||
updatedDiff.setLastModified(od.lastModified());
|
updatedDiff.setLastModified(od.lastModified());
|
||||||
}
|
}
|
||||||
@ -95,8 +83,7 @@ final public class Rd5DiffManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getMD5( File f ) throws IOException
|
public static String getMD5(File f) throws IOException {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
|
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
|
||||||
@ -122,8 +109,7 @@ final public class Rd5DiffManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static char hexChar( int v )
|
private static char hexChar(int v) {
|
||||||
{
|
|
||||||
return (char) (v > 9 ? 'a' + (v - 10) : '0' + v);
|
return (char) (v > 9 ? 'a' + (v - 10) : '0' + v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,29 +22,20 @@ import btools.codec.StatCoderContext;
|
|||||||
import btools.util.Crc32;
|
import btools.util.Crc32;
|
||||||
import btools.util.ProgressListener;
|
import btools.util.ProgressListener;
|
||||||
|
|
||||||
final public class Rd5DiffTool implements ProgressListener
|
final public class Rd5DiffTool implements ProgressListener {
|
||||||
{
|
public static void main(String[] args) throws Exception {
|
||||||
public static void main( String[] args ) throws Exception
|
if (args.length == 2) {
|
||||||
{
|
|
||||||
if ( args.length == 2 )
|
|
||||||
{
|
|
||||||
reEncode(new File(args[0]), new File(args[1]));
|
reEncode(new File(args[0]), new File(args[1]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( args[1].endsWith( ".df5" ) )
|
if (args[1].endsWith(".df5")) {
|
||||||
{
|
if (args[0].endsWith(".df5")) {
|
||||||
if ( args[0].endsWith( ".df5" ) )
|
|
||||||
{
|
|
||||||
addDeltas(new File(args[0]), new File(args[1]), new File(args[2]));
|
addDeltas(new File(args[0]), new File(args[1]), new File(args[2]));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
recoverFromDelta(new File(args[0]), new File(args[1]), new File(args[2]), new Rd5DiffTool() /*, new File( args[3] ) */);
|
recoverFromDelta(new File(args[0]), new File(args[1]), new File(args[2]), new Rd5DiffTool() /*, new File( args[3] ) */);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
diff2files(new File(args[0]), new File(args[1]), new File(args[2]));
|
diff2files(new File(args[0]), new File(args[1]), new File(args[2]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,69 +46,55 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCanceled()
|
public boolean isCanceled() {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long[] readFileIndex( DataInputStream dis, DataOutputStream dos ) throws IOException
|
private static long[] readFileIndex(DataInputStream dis, DataOutputStream dos) throws IOException {
|
||||||
{
|
|
||||||
long[] fileIndex = new long[25];
|
long[] fileIndex = new long[25];
|
||||||
for( int i=0; i<25; i++ )
|
for (int i = 0; i < 25; i++) {
|
||||||
{
|
|
||||||
long lv = dis.readLong();
|
long lv = dis.readLong();
|
||||||
fileIndex[i] = lv & 0xffffffffffffL;
|
fileIndex[i] = lv & 0xffffffffffffL;
|
||||||
if ( dos != null )
|
if (dos != null) {
|
||||||
{
|
|
||||||
dos.writeLong(lv);
|
dos.writeLong(lv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fileIndex;
|
return fileIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getTileStart( long[] index, int tileIndex )
|
private static long getTileStart(long[] index, int tileIndex) {
|
||||||
{
|
|
||||||
return tileIndex > 0 ? index[tileIndex - 1] : 200L;
|
return tileIndex > 0 ? index[tileIndex - 1] : 200L;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getTileEnd( long[] index, int tileIndex )
|
private static long getTileEnd(long[] index, int tileIndex) {
|
||||||
{
|
|
||||||
return index[tileIndex];
|
return index[tileIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readPosIndex( DataInputStream dis, DataOutputStream dos ) throws IOException
|
private static int[] readPosIndex(DataInputStream dis, DataOutputStream dos) throws IOException {
|
||||||
{
|
|
||||||
int[] posIndex = new int[1024];
|
int[] posIndex = new int[1024];
|
||||||
for( int i=0; i<1024; i++ )
|
for (int i = 0; i < 1024; i++) {
|
||||||
{
|
|
||||||
int iv = dis.readInt();
|
int iv = dis.readInt();
|
||||||
posIndex[i] = iv;
|
posIndex[i] = iv;
|
||||||
if ( dos != null )
|
if (dos != null) {
|
||||||
{
|
|
||||||
dos.writeInt(iv);
|
dos.writeInt(iv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return posIndex;
|
return posIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getPosIdx( int[] posIdx, int idx )
|
private static int getPosIdx(int[] posIdx, int idx) {
|
||||||
{
|
|
||||||
return idx == -1 ? 4096 : posIdx[idx];
|
return idx == -1 ? 4096 : posIdx[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] createMicroCache( int[] posIdx, int tileIdx, DataInputStream dis, boolean deltaMode ) throws IOException
|
private static byte[] createMicroCache(int[] posIdx, int tileIdx, DataInputStream dis, boolean deltaMode) throws IOException {
|
||||||
{
|
if (posIdx == null) {
|
||||||
if ( posIdx == null )
|
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int size = getPosIdx(posIdx, tileIdx) - getPosIdx(posIdx, tileIdx - 1);
|
int size = getPosIdx(posIdx, tileIdx) - getPosIdx(posIdx, tileIdx - 1);
|
||||||
if ( size == 0 )
|
if (size == 0) {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ( deltaMode )
|
if (deltaMode) {
|
||||||
{
|
|
||||||
size = dis.readInt();
|
size = dis.readInt();
|
||||||
}
|
}
|
||||||
byte[] ab = new byte[size];
|
byte[] ab = new byte[size];
|
||||||
@ -125,10 +102,8 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
return ab;
|
return ab;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MicroCache createMicroCache( byte[] ab, DataBuffers dataBuffers )
|
private static MicroCache createMicroCache(byte[] ab, DataBuffers dataBuffers) {
|
||||||
{
|
if (ab == null || ab.length == 0) {
|
||||||
if ( ab == null || ab.length == 0 )
|
|
||||||
{
|
|
||||||
return MicroCache.emptyCache();
|
return MicroCache.emptyCache();
|
||||||
}
|
}
|
||||||
StatCoderContext bc = new StatCoderContext(ab);
|
StatCoderContext bc = new StatCoderContext(ab);
|
||||||
@ -139,8 +114,7 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
* Compute the delta between 2 RD5 files and
|
* Compute the delta between 2 RD5 files and
|
||||||
* show statistics on the expected size of the delta file
|
* show statistics on the expected size of the delta file
|
||||||
*/
|
*/
|
||||||
public static void diff2files( File f1, File f2, File outFile ) throws Exception
|
public static void diff2files(File f1, File f2, File outFile) throws Exception {
|
||||||
{
|
|
||||||
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
||||||
byte[] abBuf2 = new byte[10 * 1024 * 1024];
|
byte[] abBuf2 = new byte[10 * 1024 * 1024];
|
||||||
|
|
||||||
@ -160,28 +134,23 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
|
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
DataBuffers dataBuffers = new DataBuffers();
|
DataBuffers dataBuffers = new DataBuffers();
|
||||||
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
|
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
|
||||||
{
|
|
||||||
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
|
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
|
||||||
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx);
|
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx);
|
||||||
|
|
||||||
int[] posIdx1 = hasData1 ? readPosIndex(dis1, null) : null;
|
int[] posIdx1 = hasData1 ? readPosIndex(dis1, null) : null;
|
||||||
int[] posIdx2 = hasData2 ? readPosIndex(dis2, dos) : null;
|
int[] posIdx2 = hasData2 ? readPosIndex(dis2, dos) : null;
|
||||||
|
|
||||||
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
|
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
|
||||||
{
|
|
||||||
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
|
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
|
||||||
byte[] ab2 = createMicroCache(posIdx2, tileIdx, dis2, false);
|
byte[] ab2 = createMicroCache(posIdx2, tileIdx, dis2, false);
|
||||||
|
|
||||||
MicroCache mc;
|
MicroCache mc;
|
||||||
if ( Arrays.equals( ab1, ab2 ) )
|
if (Arrays.equals(ab1, ab2)) {
|
||||||
{
|
|
||||||
mc = MicroCache.emptyCache(); // empty diff
|
mc = MicroCache.emptyCache(); // empty diff
|
||||||
}
|
} else // calc diff of the 2 tiles
|
||||||
else // calc diff of the 2 tiles
|
|
||||||
{
|
{
|
||||||
MicroCache mc1 = createMicroCache(ab1, dataBuffers);
|
MicroCache mc1 = createMicroCache(ab1, dataBuffers);
|
||||||
MicroCache mc2 = createMicroCache(ab2, dataBuffers);
|
MicroCache mc2 = createMicroCache(ab2, dataBuffers);
|
||||||
@ -190,8 +159,7 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
int len = mcOut.writeMC(mc);
|
int len = mcOut.writeMC(mc);
|
||||||
if ( len > 0 )
|
if (len > 0) {
|
||||||
{
|
|
||||||
bytesDiff += len;
|
bytesDiff += len;
|
||||||
nodesDiff += mc.getSize();
|
nodesDiff += mc.getSize();
|
||||||
diffedTiles++;
|
diffedTiles++;
|
||||||
@ -238,58 +206,40 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write any remaining data to the output file
|
// write any remaining data to the output file
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
int len = dis2.read(abBuf1);
|
int len = dis2.read(abBuf1);
|
||||||
if (len < 0)
|
if (len < 0) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dos.write(abBuf1, 0, len);
|
dos.write(abBuf1, 0, len);
|
||||||
}
|
}
|
||||||
long t1 = System.currentTimeMillis();
|
long t1 = System.currentTimeMillis();
|
||||||
System.out.println("nodesDiff=" + nodesDiff + " bytesDiff=" + bytesDiff + " diffedTiles=" + diffedTiles + " took " + (t1 - t0) + "ms");
|
System.out.println("nodesDiff=" + nodesDiff + " bytesDiff=" + bytesDiff + " diffedTiles=" + diffedTiles + " took " + (t1 - t0) + "ms");
|
||||||
}
|
} finally {
|
||||||
finally
|
if (dis1 != null) {
|
||||||
{
|
try {
|
||||||
if ( dis1 != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dis1.close();
|
dis1.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dis2 != null )
|
if (dis2 != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dis2.close();
|
dis2.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dos != null )
|
if (dos != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dos.close();
|
dos.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void recoverFromDelta( File f1, File f2, File outFile, ProgressListener progress /* , File cmpFile */ ) throws IOException
|
public static void recoverFromDelta(File f1, File f2, File outFile, ProgressListener progress /* , File cmpFile */) throws IOException {
|
||||||
{
|
if (f2.length() == 0L) {
|
||||||
if ( f2.length() == 0L )
|
|
||||||
{
|
|
||||||
copyFile(f1, outFile, progress);
|
copyFile(f1, outFile, progress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -313,13 +263,11 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
|
|
||||||
int lastPct = -1;
|
int lastPct = -1;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
DataBuffers dataBuffers = new DataBuffers();
|
DataBuffers dataBuffers = new DataBuffers();
|
||||||
MCInputStream mcIn = new MCInputStream(dis2, dataBuffers);
|
MCInputStream mcIn = new MCInputStream(dis2, dataBuffers);
|
||||||
|
|
||||||
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
|
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
|
||||||
{
|
|
||||||
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx); // has the basefile data
|
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx); // has the basefile data
|
||||||
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx); // has the *result* data
|
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx); // has the *result* data
|
||||||
|
|
||||||
@ -330,17 +278,14 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
|
|
||||||
// int[] posIdxCmp = hasDataCmp ? readPosIndex( disCmp, null ) : null;
|
// int[] posIdxCmp = hasDataCmp ? readPosIndex( disCmp, null ) : null;
|
||||||
|
|
||||||
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
|
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
|
||||||
{
|
if (progress.isCanceled()) {
|
||||||
if ( progress.isCanceled() )
|
|
||||||
{
|
|
||||||
canceled = true;
|
canceled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
double bytesProcessed = getTileStart(fileIndex1, subFileIdx) + (posIdx1 == null ? 0 : getPosIdx(posIdx1, tileIdx - 1));
|
double bytesProcessed = getTileStart(fileIndex1, subFileIdx) + (posIdx1 == null ? 0 : getPosIdx(posIdx1, tileIdx - 1));
|
||||||
int pct = (int) (100. * bytesProcessed / getTileEnd(fileIndex1, 24) + 0.5);
|
int pct = (int) (100. * bytesProcessed / getTileEnd(fileIndex1, 24) + 0.5);
|
||||||
if ( pct != lastPct )
|
if (pct != lastPct) {
|
||||||
{
|
|
||||||
progress.updateProgress("Applying delta", pct);
|
progress.updateProgress("Applying delta", pct);
|
||||||
lastPct = pct;
|
lastPct = pct;
|
||||||
}
|
}
|
||||||
@ -356,15 +301,12 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// no-delta shortcut: just copy base data
|
// no-delta shortcut: just copy base data
|
||||||
if ( mc2.getSize() == 0 )
|
if (mc2.getSize() == 0) {
|
||||||
{
|
if (ab1 != null) {
|
||||||
if ( ab1 != null )
|
|
||||||
{
|
|
||||||
dos.write(ab1);
|
dos.write(ab1);
|
||||||
}
|
}
|
||||||
int newTargetSize = ab1 == null ? 0 : ab1.length;
|
int newTargetSize = ab1 == null ? 0 : ab1.length;
|
||||||
if ( targetSize != newTargetSize )
|
if (targetSize != newTargetSize) {
|
||||||
{
|
|
||||||
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "!=" + newTargetSize);
|
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "!=" + newTargetSize);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -377,10 +319,8 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
MicroCache mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
|
MicroCache mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
|
||||||
mc.addDelta(mc1, mc2, false);
|
mc.addDelta(mc1, mc2, false);
|
||||||
|
|
||||||
if ( mc.size() == 0 )
|
if (mc.size() == 0) {
|
||||||
{
|
if (targetSize != 0) {
|
||||||
if ( targetSize != 0 )
|
|
||||||
{
|
|
||||||
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + ">0");
|
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + ">0");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -408,8 +348,7 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
*/
|
*/
|
||||||
dos.write(abBuf1, 0, len);
|
dos.write(abBuf1, 0, len);
|
||||||
dos.writeInt(Crc32.crc(abBuf1, 0, len) ^ 2);
|
dos.writeInt(Crc32.crc(abBuf1, 0, len) ^ 2);
|
||||||
if ( targetSize != len+4 )
|
if (targetSize != len + 4) {
|
||||||
{
|
|
||||||
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "<>" + (len + 4));
|
throw new RuntimeException("size mismatch at " + subFileIdx + "/" + tileIdx + " " + targetSize + "<>" + (len + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,121 +356,86 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
mcIn.finish();
|
mcIn.finish();
|
||||||
}
|
}
|
||||||
// write any remaining data to the output file
|
// write any remaining data to the output file
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
int len = dis2.read(abBuf1);
|
int len = dis2.read(abBuf1);
|
||||||
if (len < 0)
|
if (len < 0) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dos.write(abBuf1, 0, len);
|
dos.write(abBuf1, 0, len);
|
||||||
}
|
}
|
||||||
long t1 = System.currentTimeMillis();
|
long t1 = System.currentTimeMillis();
|
||||||
System.out.println("recovering from diffs took " + (t1 - t0) + "ms");
|
System.out.println("recovering from diffs took " + (t1 - t0) + "ms");
|
||||||
}
|
} finally {
|
||||||
finally
|
if (dis1 != null) {
|
||||||
{
|
try {
|
||||||
if ( dis1 != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dis1.close();
|
dis1.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dis2 != null )
|
if (dis2 != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dis2.close();
|
dis2.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dos != null )
|
if (dos != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dos.close();
|
dos.close();
|
||||||
|
} catch (Exception ee) {
|
||||||
}
|
}
|
||||||
catch (Exception ee)
|
if (canceled) {
|
||||||
{
|
|
||||||
}
|
|
||||||
if ( canceled )
|
|
||||||
{
|
|
||||||
outFile.delete();
|
outFile.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyFile( File f1, File outFile, ProgressListener progress ) throws IOException
|
public static void copyFile(File f1, File outFile, ProgressListener progress) throws IOException {
|
||||||
{
|
|
||||||
boolean canceled = false;
|
boolean canceled = false;
|
||||||
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
|
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
|
||||||
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
|
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
|
||||||
int lastPct = -1;
|
int lastPct = -1;
|
||||||
long sizeTotal = f1.length();
|
long sizeTotal = f1.length();
|
||||||
long sizeRead = 0L;
|
long sizeRead = 0L;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
byte buf[] = new byte[65536];
|
byte buf[] = new byte[65536];
|
||||||
for (;;)
|
for (; ; ) {
|
||||||
{
|
if (progress.isCanceled()) {
|
||||||
if ( progress.isCanceled() )
|
|
||||||
{
|
|
||||||
canceled = true;
|
canceled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int pct = (int) ((100. * sizeRead) / (sizeTotal + 1) + 0.5);
|
int pct = (int) ((100. * sizeRead) / (sizeTotal + 1) + 0.5);
|
||||||
if ( pct != lastPct )
|
if (pct != lastPct) {
|
||||||
{
|
|
||||||
progress.updateProgress("Copying", pct);
|
progress.updateProgress("Copying", pct);
|
||||||
lastPct = pct;
|
lastPct = pct;
|
||||||
}
|
}
|
||||||
int len = dis1.read(buf);
|
int len = dis1.read(buf);
|
||||||
if ( len <= 0 )
|
if (len <= 0) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sizeRead += len;
|
sizeRead += len;
|
||||||
dos.write(buf, 0, len);
|
dos.write(buf, 0, len);
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally
|
if (dis1 != null) {
|
||||||
{
|
try {
|
||||||
if ( dis1 != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dis1.close();
|
dis1.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dos != null )
|
if (dos != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dos.close();
|
dos.close();
|
||||||
|
} catch (Exception ee) {
|
||||||
}
|
}
|
||||||
catch (Exception ee)
|
if (canceled) {
|
||||||
{
|
|
||||||
}
|
|
||||||
if ( canceled )
|
|
||||||
{
|
|
||||||
outFile.delete();
|
outFile.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addDeltas( File f1, File f2, File outFile ) throws Exception
|
public static void addDeltas(File f1, File f2, File outFile) throws Exception {
|
||||||
{
|
|
||||||
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
||||||
byte[] abBuf2 = new byte[10 * 1024 * 1024];
|
byte[] abBuf2 = new byte[10 * 1024 * 1024];
|
||||||
|
|
||||||
@ -545,32 +449,26 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
|
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
DataBuffers dataBuffers = new DataBuffers();
|
DataBuffers dataBuffers = new DataBuffers();
|
||||||
MCInputStream mcIn1 = new MCInputStream(dis1, dataBuffers);
|
MCInputStream mcIn1 = new MCInputStream(dis1, dataBuffers);
|
||||||
MCInputStream mcIn2 = new MCInputStream(dis2, dataBuffers);
|
MCInputStream mcIn2 = new MCInputStream(dis2, dataBuffers);
|
||||||
MCOutputStream mcOut = new MCOutputStream(dos, abBuf1);
|
MCOutputStream mcOut = new MCOutputStream(dos, abBuf1);
|
||||||
|
|
||||||
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
|
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
|
||||||
{
|
|
||||||
// copy tile-header to outfile
|
// copy tile-header to outfile
|
||||||
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
|
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
|
||||||
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx);
|
boolean hasData2 = getTileStart(fileIndex2, subFileIdx) < getTileEnd(fileIndex2, subFileIdx);
|
||||||
int[] posIdx1 = hasData1 ? readPosIndex(dis1, null) : null;
|
int[] posIdx1 = hasData1 ? readPosIndex(dis1, null) : null;
|
||||||
int[] posIdx2 = hasData2 ? readPosIndex(dis2, dos) : null;
|
int[] posIdx2 = hasData2 ? readPosIndex(dis2, dos) : null;
|
||||||
|
|
||||||
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
|
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
|
||||||
{
|
|
||||||
MicroCache mc1 = mcIn1.readMC();
|
MicroCache mc1 = mcIn1.readMC();
|
||||||
MicroCache mc2 = mcIn2.readMC();
|
MicroCache mc2 = mcIn2.readMC();
|
||||||
MicroCache mc;
|
MicroCache mc;
|
||||||
if ( mc1.getSize() == 0 && mc2.getSize() == 0 )
|
if (mc1.getSize() == 0 && mc2.getSize() == 0) {
|
||||||
{
|
|
||||||
mc = mc1;
|
mc = mc1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
|
mc = new MicroCache2(mc1.getSize() + mc2.getSize(), abBuf2, 0, 0, 32);
|
||||||
mc.addDelta(mc1, mc2, true);
|
mc.addDelta(mc1, mc2, true);
|
||||||
}
|
}
|
||||||
@ -581,56 +479,39 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
mcOut.finish();
|
mcOut.finish();
|
||||||
}
|
}
|
||||||
// write any remaining data to the output file
|
// write any remaining data to the output file
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
int len = dis2.read(abBuf1);
|
int len = dis2.read(abBuf1);
|
||||||
if (len < 0)
|
if (len < 0) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dos.write(abBuf1, 0, len);
|
dos.write(abBuf1, 0, len);
|
||||||
}
|
}
|
||||||
long t1 = System.currentTimeMillis();
|
long t1 = System.currentTimeMillis();
|
||||||
System.out.println("adding diffs took " + (t1 - t0) + "ms");
|
System.out.println("adding diffs took " + (t1 - t0) + "ms");
|
||||||
}
|
} finally {
|
||||||
finally
|
if (dis1 != null) {
|
||||||
{
|
try {
|
||||||
if ( dis1 != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dis1.close();
|
dis1.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dis2 != null )
|
if (dis2 != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dis2.close();
|
dis2.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dos != null )
|
if (dos != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dos.close();
|
dos.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void reEncode( File f1, File outFile ) throws Exception
|
public static void reEncode(File f1, File outFile) throws Exception {
|
||||||
{
|
|
||||||
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
||||||
|
|
||||||
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
|
DataInputStream dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream(f1)));
|
||||||
@ -641,17 +522,14 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
|
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
DataBuffers dataBuffers = new DataBuffers();
|
DataBuffers dataBuffers = new DataBuffers();
|
||||||
for ( int subFileIdx = 0; subFileIdx < 25; subFileIdx++ )
|
for (int subFileIdx = 0; subFileIdx < 25; subFileIdx++) {
|
||||||
{
|
|
||||||
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
|
boolean hasData1 = getTileStart(fileIndex1, subFileIdx) < getTileEnd(fileIndex1, subFileIdx);
|
||||||
|
|
||||||
int[] posIdx1 = hasData1 ? readPosIndex(dis1, dos) : null;
|
int[] posIdx1 = hasData1 ? readPosIndex(dis1, dos) : null;
|
||||||
|
|
||||||
for ( int tileIdx = 0; tileIdx < 1024; tileIdx++ )
|
for (int tileIdx = 0; tileIdx < 1024; tileIdx++) {
|
||||||
{
|
|
||||||
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
|
byte[] ab1 = createMicroCache(posIdx1, tileIdx, dis1, false);
|
||||||
|
|
||||||
if (ab1 == null) continue;
|
if (ab1 == null) continue;
|
||||||
@ -665,67 +543,50 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// write any remaining data to the output file
|
// write any remaining data to the output file
|
||||||
for(;;)
|
for (; ; ) {
|
||||||
{
|
|
||||||
int len = dis1.read(abBuf1);
|
int len = dis1.read(abBuf1);
|
||||||
if (len < 0)
|
if (len < 0) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dos.write(abBuf1, 0, len);
|
dos.write(abBuf1, 0, len);
|
||||||
}
|
}
|
||||||
long t1 = System.currentTimeMillis();
|
long t1 = System.currentTimeMillis();
|
||||||
System.out.println("re-encoding took " + (t1 - t0) + "ms");
|
System.out.println("re-encoding took " + (t1 - t0) + "ms");
|
||||||
}
|
} finally {
|
||||||
finally
|
if (dis1 != null) {
|
||||||
{
|
try {
|
||||||
if ( dis1 != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dis1.close();
|
dis1.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dos != null )
|
if (dos != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
dos.close();
|
dos.close();
|
||||||
}
|
} catch (Exception ee) {
|
||||||
catch (Exception ee)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MCOutputStream
|
private static class MCOutputStream {
|
||||||
{
|
|
||||||
private DataOutputStream dos;
|
private DataOutputStream dos;
|
||||||
private byte[] buffer;
|
private byte[] buffer;
|
||||||
private short skips = 0;
|
private short skips = 0;
|
||||||
|
|
||||||
public MCOutputStream(DataOutputStream dos, byte[] buffer)
|
public MCOutputStream(DataOutputStream dos, byte[] buffer) {
|
||||||
{
|
|
||||||
this.dos = dos;
|
this.dos = dos;
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int writeMC(MicroCache mc) throws Exception
|
public int writeMC(MicroCache mc) throws Exception {
|
||||||
{
|
if (mc.getSize() == 0) {
|
||||||
if ( mc.getSize() == 0 )
|
|
||||||
{
|
|
||||||
skips++;
|
skips++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dos.writeShort(skips);
|
dos.writeShort(skips);
|
||||||
skips = 0;
|
skips = 0;
|
||||||
int len = mc.encodeMicroCache(buffer);
|
int len = mc.encodeMicroCache(buffer);
|
||||||
if ( len == 0 )
|
if (len == 0) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("encoded buffer of non-empty micro-cache cannot be empty");
|
throw new IllegalArgumentException("encoded buffer of non-empty micro-cache cannot be empty");
|
||||||
}
|
}
|
||||||
dos.writeInt(len);
|
dos.writeInt(len);
|
||||||
@ -733,38 +594,31 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() throws Exception
|
public void finish() throws Exception {
|
||||||
{
|
if (skips > 0) {
|
||||||
if ( skips > 0 )
|
|
||||||
{
|
|
||||||
dos.writeShort(skips);
|
dos.writeShort(skips);
|
||||||
skips = 0;
|
skips = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MCInputStream
|
private static class MCInputStream {
|
||||||
{
|
|
||||||
private short skips = -1;
|
private short skips = -1;
|
||||||
private DataInputStream dis;
|
private DataInputStream dis;
|
||||||
private DataBuffers dataBuffers;
|
private DataBuffers dataBuffers;
|
||||||
private MicroCache empty = MicroCache.emptyCache();
|
private MicroCache empty = MicroCache.emptyCache();
|
||||||
|
|
||||||
public MCInputStream( DataInputStream dis, DataBuffers dataBuffers )
|
public MCInputStream(DataInputStream dis, DataBuffers dataBuffers) {
|
||||||
{
|
|
||||||
this.dis = dis;
|
this.dis = dis;
|
||||||
this.dataBuffers = dataBuffers;
|
this.dataBuffers = dataBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MicroCache readMC() throws IOException
|
public MicroCache readMC() throws IOException {
|
||||||
{
|
if (skips < 0) {
|
||||||
if (skips < 0 )
|
|
||||||
{
|
|
||||||
skips = dis.readShort();
|
skips = dis.readShort();
|
||||||
}
|
}
|
||||||
MicroCache mc = empty;
|
MicroCache mc = empty;
|
||||||
if ( skips == 0 )
|
if (skips == 0) {
|
||||||
{
|
|
||||||
int size = dis.readInt();
|
int size = dis.readInt();
|
||||||
byte[] ab = new byte[size];
|
byte[] ab = new byte[size];
|
||||||
dis.readFully(ab);
|
dis.readFully(ab);
|
||||||
@ -775,8 +629,7 @@ final public class Rd5DiffTool implements ProgressListener
|
|||||||
return mc;
|
return mc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish()
|
public void finish() {
|
||||||
{
|
|
||||||
skips = -1;
|
skips = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,38 +7,31 @@ package btools.mapaccess;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
final public class Rd5DiffValidator
|
final public class Rd5DiffValidator {
|
||||||
{
|
public static void main(String[] args) throws Exception {
|
||||||
public static void main( String[] args ) throws Exception
|
|
||||||
{
|
|
||||||
validateDiffs(new File(args[0]), new File(args[1]));
|
validateDiffs(new File(args[0]), new File(args[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate diffs for all DF5 files
|
* Validate diffs for all DF5 files
|
||||||
*/
|
*/
|
||||||
public static void validateDiffs( File oldDir, File newDir ) throws Exception
|
public static void validateDiffs(File oldDir, File newDir) throws Exception {
|
||||||
{
|
|
||||||
File oldDiffDir = new File(oldDir, "diff");
|
File oldDiffDir = new File(oldDir, "diff");
|
||||||
File newDiffDir = new File(newDir, "diff");
|
File newDiffDir = new File(newDir, "diff");
|
||||||
|
|
||||||
File[] filesNew = newDir.listFiles();
|
File[] filesNew = newDir.listFiles();
|
||||||
|
|
||||||
for( File fn : filesNew )
|
for (File fn : filesNew) {
|
||||||
{
|
|
||||||
String name = fn.getName();
|
String name = fn.getName();
|
||||||
if ( !name.endsWith( ".rd5" ) )
|
if (!name.endsWith(".rd5")) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( fn.length() < 1024*1024 )
|
if (fn.length() < 1024 * 1024) {
|
||||||
{
|
|
||||||
continue; // expecting no diff for small files
|
continue; // expecting no diff for small files
|
||||||
}
|
}
|
||||||
String basename = name.substring(0, name.length() - 4);
|
String basename = name.substring(0, name.length() - 4);
|
||||||
File fo = new File(oldDir, name);
|
File fo = new File(oldDir, name);
|
||||||
if ( !fo.isFile() )
|
if (!fo.isFile()) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +53,7 @@ final public class Rd5DiffValidator
|
|||||||
Rd5DiffTool.recoverFromDelta(fo, diffFile, fcmp, new Rd5DiffTool());
|
Rd5DiffTool.recoverFromDelta(fo, diffFile, fcmp, new Rd5DiffTool());
|
||||||
String md5Cmp = Rd5DiffManager.getMD5(fcmp);
|
String md5Cmp = Rd5DiffManager.getMD5(fcmp);
|
||||||
|
|
||||||
if ( !md5Cmp.equals( md5New ) )
|
if (!md5Cmp.equals(md5New)) {
|
||||||
{
|
|
||||||
throw new RuntimeException("**************** md5 mismatch!! *****************");
|
throw new RuntimeException("**************** md5 mismatch!! *****************");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,51 +9,38 @@ import java.io.BufferedReader;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
|
|
||||||
public class StorageConfigHelper
|
public class StorageConfigHelper {
|
||||||
{
|
public static File getSecondarySegmentDir(File segmentDir) {
|
||||||
public static File getSecondarySegmentDir( File segmentDir )
|
|
||||||
{
|
|
||||||
return getStorageLocation(segmentDir, "secondary_segment_dir=");
|
return getStorageLocation(segmentDir, "secondary_segment_dir=");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getAdditionalMaptoolDir( File segmentDir )
|
public static File getAdditionalMaptoolDir(File segmentDir) {
|
||||||
{
|
|
||||||
return getStorageLocation(segmentDir, "additional_maptool_dir=");
|
return getStorageLocation(segmentDir, "additional_maptool_dir=");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File getStorageLocation( File segmentDir, String tag )
|
private static File getStorageLocation(File segmentDir, String tag) {
|
||||||
{
|
|
||||||
File res = null;
|
File res = null;
|
||||||
BufferedReader br = null;
|
BufferedReader br = null;
|
||||||
File configFile = new File(segmentDir, "storageconfig.txt");
|
File configFile = new File(segmentDir, "storageconfig.txt");
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
br = new BufferedReader(new FileReader(configFile));
|
br = new BufferedReader(new FileReader(configFile));
|
||||||
for ( ;; )
|
for (; ; ) {
|
||||||
{
|
|
||||||
String line = br.readLine();
|
String line = br.readLine();
|
||||||
if (line == null) break;
|
if (line == null) break;
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
if (line.startsWith("#")) continue;
|
if (line.startsWith("#")) continue;
|
||||||
if ( line.startsWith( tag ) )
|
if (line.startsWith(tag)) {
|
||||||
{
|
|
||||||
String path = line.substring(tag.length()).trim();
|
String path = line.substring(tag.length()).trim();
|
||||||
res = path.startsWith("/") ? new File(path) : new File(segmentDir, path);
|
res = path.startsWith("/") ? new File(path) : new File(segmentDir, path);
|
||||||
if (!res.exists()) res = null;
|
if (!res.exists()) res = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception e) { /* ignore */ } finally {
|
||||||
catch (Exception e) { /* ignore */ }
|
if (br != null) {
|
||||||
finally
|
try {
|
||||||
{
|
|
||||||
if ( br != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
br.close();
|
br.close();
|
||||||
}
|
} catch (Exception ee) { /* ignore */ }
|
||||||
catch (Exception ee) { /* ignore */ }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user