initial commit of BRouter Version 0.98
This commit is contained in:
parent
e4ae2b37d3
commit
91e62f1164
120 changed files with 15382 additions and 0 deletions
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* fast data-reading from a byte-array
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
|
||||
final class ByteDataReader
|
||||
{
|
||||
private byte[] ab;
|
||||
private int aboffset;
|
||||
|
||||
public ByteDataReader( byte[] byteArray )
|
||||
{
|
||||
ab = byteArray;
|
||||
}
|
||||
|
||||
public int readInt()
|
||||
{
|
||||
int i3 = ab[aboffset++]& 0xff;
|
||||
int i2 = ab[aboffset++]& 0xff;
|
||||
int i1 = ab[aboffset++]& 0xff;
|
||||
int i0 = ab[aboffset++]& 0xff;
|
||||
return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
}
|
||||
|
||||
public long readLong()
|
||||
{
|
||||
long i7 = ab[aboffset++]& 0xff;
|
||||
long i6 = ab[aboffset++]& 0xff;
|
||||
long i5 = ab[aboffset++]& 0xff;
|
||||
long i4 = ab[aboffset++]& 0xff;
|
||||
long i3 = ab[aboffset++]& 0xff;
|
||||
long i2 = ab[aboffset++]& 0xff;
|
||||
long i1 = ab[aboffset++]& 0xff;
|
||||
long i0 = ab[aboffset++]& 0xff;
|
||||
return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
}
|
||||
|
||||
public boolean readBoolean()
|
||||
{
|
||||
int i0 = ab[aboffset++]& 0xff;
|
||||
return i0 != 0;
|
||||
}
|
||||
|
||||
public byte readByte()
|
||||
{
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (byte)(i0);
|
||||
}
|
||||
|
||||
public short readShort()
|
||||
{
|
||||
int i1 = ab[aboffset++] & 0xff;
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (short)( (i1 << 8) | i0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* fast data-reading from a byte-array
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
|
||||
final class ByteDataWriter
|
||||
{
|
||||
private byte[] ab;
|
||||
private int aboffset;
|
||||
|
||||
public ByteDataWriter( byte[] byteArray )
|
||||
{
|
||||
ab = byteArray;
|
||||
}
|
||||
|
||||
public void writeInt( int v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v >> 24) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 16) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
}
|
||||
|
||||
public void writeLong( long v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v >> 56) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 48) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 40) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 32) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 24) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 16) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
}
|
||||
|
||||
public void writeBoolean( boolean v)
|
||||
{
|
||||
ab[aboffset++] = (byte)( v ? 1 : 0 );
|
||||
}
|
||||
|
||||
public void writeByte( int v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
}
|
||||
|
||||
public void writeShort( int v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Container for routig configs
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
public interface DistanceChecker
|
||||
{
|
||||
/**
|
||||
* Checks whether the given path is within a maximum distance
|
||||
* known to the distance checker
|
||||
* @return true if close enough
|
||||
*/
|
||||
boolean isWithinRadius( int ilon0, int ilat0, OsmTransferNode firstTransfer, int ilon1, int ilat1 );
|
||||
}
|
||||
232
brouter-mapaccess/src/main/java/btools/mapaccess/MicroCache.java
Normal file
232
brouter-mapaccess/src/main/java/btools/mapaccess/MicroCache.java
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/**
|
||||
* cache for a single square
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
final class MicroCache
|
||||
{
|
||||
private long[] faid;
|
||||
private int[] fapos;
|
||||
private int size = 0;
|
||||
private int delcount = 0;
|
||||
private int delbytes = 0;
|
||||
private int p2size; // next power of 2 of size
|
||||
|
||||
// the object parsing position and length
|
||||
private byte[] ab;
|
||||
private int aboffset;
|
||||
private int ablength;
|
||||
|
||||
public MicroCache( OsmFile segfile, int lonIdx80, int latIdx80, byte[] iobuffer ) throws Exception
|
||||
{
|
||||
int lonDegree = lonIdx80/80;
|
||||
int latDegree = latIdx80/80;
|
||||
|
||||
int lonIdxBase = (lonIdx80/5)*62500 + 31250;
|
||||
int latIdxBase = (latIdx80/5)*62500 + 31250;
|
||||
|
||||
int subIdx = (latIdx80-80*latDegree)*80 + (lonIdx80-80*lonDegree);
|
||||
|
||||
try
|
||||
{
|
||||
ab = iobuffer;
|
||||
int asize = segfile.getDataInputForSubIdx(subIdx, ab);
|
||||
if ( asize == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ( asize > iobuffer.length )
|
||||
{
|
||||
ab = new byte[asize];
|
||||
asize = segfile.getDataInputForSubIdx(subIdx, ab);
|
||||
}
|
||||
aboffset = 0;
|
||||
size = readInt();
|
||||
|
||||
// new array with only net data
|
||||
byte[] nab = new byte[asize - 4 - size*8];
|
||||
int noffset = 0;
|
||||
faid = new long[size];
|
||||
fapos = new int[size];
|
||||
p2size = 0x40000000;
|
||||
while( p2size > size ) p2size >>= 1;
|
||||
|
||||
for(int i = 0; i<size; i++)
|
||||
{
|
||||
int ilon = readShort();
|
||||
int ilat = readShort();
|
||||
ilon += lonIdxBase;
|
||||
ilat += latIdxBase;
|
||||
long nodeId = ((long)ilon)<<32 | ilat;
|
||||
|
||||
faid[i] = nodeId;
|
||||
int bodySize = readInt();
|
||||
fapos[i] = noffset;
|
||||
System.arraycopy( ab, aboffset, nab, noffset, bodySize );
|
||||
aboffset += bodySize;
|
||||
noffset += bodySize;
|
||||
}
|
||||
ab = nab;
|
||||
}
|
||||
catch( EOFException eof )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value for "id",
|
||||
* Throw an exception if not contained in the map.
|
||||
*/
|
||||
private boolean getAndClear( long id )
|
||||
{
|
||||
if ( size == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
long[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
|
||||
while ( offset> 0 )
|
||||
{
|
||||
int nn = n + offset;
|
||||
if ( nn < size && a[nn] <= id )
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
if ( ( fapos[n] & 0x80000000 ) == 0 )
|
||||
{
|
||||
aboffset = fapos[n];
|
||||
ablength = ( n+1 < size ? fapos[n+1] & 0x7fffffff : ab.length ) - aboffset;
|
||||
fapos[n] |= 0x80000000; // mark deleted
|
||||
delbytes+= ablength;
|
||||
delcount++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException( "MicroCache: node already consumed: id=" + id );
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void fillNode( OsmNode node, OsmNodesMap nodesMap, DistanceChecker dc )
|
||||
{
|
||||
long id = node.getIdFromPos();
|
||||
if ( getAndClear( id ) )
|
||||
{
|
||||
node.parseNodeBody( this, ablength, nodesMap, dc );
|
||||
}
|
||||
|
||||
if ( delcount > size / 2 ) // garbage collection
|
||||
{
|
||||
int nsize = size - delcount;
|
||||
if ( nsize == 0 )
|
||||
{
|
||||
faid = null;
|
||||
fapos = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
long[] nfaid = new long[nsize];
|
||||
int[] nfapos = new int[nsize];
|
||||
int idx = 0;
|
||||
|
||||
byte[] nab = new byte[ab.length - delbytes];
|
||||
int nab_off = 0;
|
||||
for( int i=0; i<size; i++ )
|
||||
{
|
||||
int pos = fapos[i];
|
||||
if ( ( pos & 0x80000000 ) == 0 )
|
||||
{
|
||||
ablength = ( i+1 < size ? fapos[i+1] & 0x7fffffff : ab.length ) - pos;
|
||||
System.arraycopy( ab, pos, nab, nab_off, ablength );
|
||||
nfaid[idx] = faid[i];
|
||||
nfapos[idx] = nab_off;
|
||||
nab_off += ablength;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
faid = nfaid;
|
||||
fapos = nfapos;
|
||||
ab = nab;
|
||||
}
|
||||
size = nsize;
|
||||
delcount = 0;
|
||||
delbytes = 0;
|
||||
p2size = 0x40000000;
|
||||
while( p2size > size ) p2size >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
public List<OsmNode> getPositions( OsmNodesMap nodesMap )
|
||||
{
|
||||
ArrayList<OsmNode> positions = new ArrayList<OsmNode>();
|
||||
|
||||
for( int i=0; i<size; i++ )
|
||||
{
|
||||
OsmNode n = new OsmNode( faid[i] );
|
||||
n.setHollow();
|
||||
nodesMap.put( faid[i], n );
|
||||
positions.add( n );
|
||||
}
|
||||
return positions;
|
||||
}
|
||||
|
||||
public int readInt()
|
||||
{
|
||||
int i3 = ab[aboffset++]& 0xff;
|
||||
int i2 = ab[aboffset++]& 0xff;
|
||||
int i1 = ab[aboffset++]& 0xff;
|
||||
int i0 = ab[aboffset++]& 0xff;
|
||||
return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
}
|
||||
|
||||
public long readLong()
|
||||
{
|
||||
long i7 = ab[aboffset++]& 0xff;
|
||||
long i6 = ab[aboffset++]& 0xff;
|
||||
long i5 = ab[aboffset++]& 0xff;
|
||||
long i4 = ab[aboffset++]& 0xff;
|
||||
long i3 = ab[aboffset++]& 0xff;
|
||||
long i2 = ab[aboffset++]& 0xff;
|
||||
long i1 = ab[aboffset++]& 0xff;
|
||||
long i0 = ab[aboffset++]& 0xff;
|
||||
return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
}
|
||||
|
||||
public boolean readBoolean()
|
||||
{
|
||||
int i0 = ab[aboffset++]& 0xff;
|
||||
return i0 != 0;
|
||||
}
|
||||
|
||||
public byte readByte()
|
||||
{
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (byte)(i0);
|
||||
}
|
||||
|
||||
public short readShort()
|
||||
{
|
||||
int i1 = ab[aboffset++] & 0xff;
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (short)( (i1 << 8) | i0);
|
||||
}
|
||||
}
|
||||
223
brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java
Normal file
223
brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/**
|
||||
* Efficient cache or osmnodes
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
public final class NodesCache
|
||||
{
|
||||
private String segmentDir;
|
||||
private OsmNodesMap nodesMap;
|
||||
private int lookupVersion;
|
||||
private boolean carMode;
|
||||
private String currentFileName;
|
||||
|
||||
private HashMap<String,RandomAccessFile> fileCache;
|
||||
private HashMap<String,long[]> indexCache;
|
||||
private byte[] iobuffer;
|
||||
|
||||
private OsmFile[][] fileRows = new OsmFile[180][];
|
||||
private ArrayList<MicroCache> segmentList = new ArrayList<MicroCache>();
|
||||
|
||||
public DistanceChecker distanceChecker;
|
||||
|
||||
public boolean oom_carsubset_hint = false;
|
||||
|
||||
public NodesCache( String segmentDir, OsmNodesMap nodesMap, int lookupVersion, boolean carMode, NodesCache oldCache )
|
||||
{
|
||||
this.segmentDir = segmentDir;
|
||||
this.nodesMap = nodesMap;
|
||||
this.lookupVersion = lookupVersion;
|
||||
this.carMode = carMode;
|
||||
|
||||
if ( oldCache != null )
|
||||
{
|
||||
fileCache = oldCache.fileCache;
|
||||
indexCache = oldCache.indexCache;
|
||||
iobuffer = oldCache.iobuffer;
|
||||
oom_carsubset_hint = oldCache.oom_carsubset_hint;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileCache = new HashMap<String,RandomAccessFile>(4);
|
||||
indexCache = new HashMap<String,long[]>(4);
|
||||
iobuffer = new byte[65636];
|
||||
}
|
||||
}
|
||||
|
||||
public int loadSegmentFor( int ilon, int ilat )
|
||||
{
|
||||
MicroCache mc = getSegmentFor( ilon, ilat );
|
||||
return mc == null ? 0 : mc.getSize();
|
||||
}
|
||||
|
||||
public MicroCache getSegmentFor( int ilon, int ilat )
|
||||
{
|
||||
try
|
||||
{
|
||||
int lonIdx80 = ilon/12500;
|
||||
int latIdx80 = ilat/12500;
|
||||
int lonDegree = lonIdx80/80;
|
||||
int latDegree = latIdx80/80;
|
||||
OsmFile osmf = null;
|
||||
OsmFile[] fileRow = fileRows[latDegree];
|
||||
int ndegrees = fileRow == null ? 0 : fileRow.length;
|
||||
for( int i=0; i<ndegrees; i++ )
|
||||
{
|
||||
if ( fileRow[i].lonDegree == lonDegree )
|
||||
{
|
||||
osmf = fileRow[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( osmf == null )
|
||||
{
|
||||
osmf = fileForSegment( lonDegree, latDegree );
|
||||
OsmFile[] newFileRow = new OsmFile[ndegrees+1];
|
||||
for( int i=0; i<ndegrees; i++ )
|
||||
{
|
||||
newFileRow[i] = fileRow[i];
|
||||
}
|
||||
newFileRow[ndegrees] = osmf;
|
||||
fileRows[latDegree] = newFileRow;
|
||||
}
|
||||
currentFileName = osmf.filename;
|
||||
if ( osmf.microCaches == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int subIdx = (latIdx80-80*latDegree)*80 + (lonIdx80-80*lonDegree);
|
||||
MicroCache segment = osmf.microCaches[subIdx];
|
||||
if ( segment == null )
|
||||
{
|
||||
// nodesMap.removeCompleteNodes();
|
||||
|
||||
segment = new MicroCache( osmf, lonIdx80, latIdx80, iobuffer );
|
||||
osmf.microCaches[subIdx] = segment;
|
||||
segmentList.add( segment );
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
catch( RuntimeException re )
|
||||
{
|
||||
throw re;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
throw new RuntimeException( "error reading datafile " + currentFileName + ": " + e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean obtainNonHollowNode( OsmNode node )
|
||||
{
|
||||
if ( !node.isHollow() ) return true;
|
||||
|
||||
MicroCache segment = getSegmentFor( node.ilon, node.ilat );
|
||||
if ( segment == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
segment.fillNode( node, nodesMap, distanceChecker );
|
||||
return !node.isHollow();
|
||||
}
|
||||
|
||||
private OsmFile fileForSegment( int lonDegree, int latDegree ) throws Exception
|
||||
{
|
||||
File base = new File( segmentDir );
|
||||
if ( !base.isDirectory() ) throw new RuntimeException( "segment directory " + segmentDir + " does not exist" );
|
||||
|
||||
int lonMod5 = lonDegree % 5;
|
||||
int latMod5 = latDegree % 5;
|
||||
int tileIndex = lonMod5 * 5 + latMod5;
|
||||
|
||||
int lon = lonDegree - 180 - lonMod5;
|
||||
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
|
||||
int lat = latDegree - 90 - latMod5;
|
||||
|
||||
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
|
||||
String filenameBase = slon + "_" + slat;
|
||||
|
||||
currentFileName = filenameBase + ".rd5/cd5";
|
||||
|
||||
if ( !fileCache.containsKey( filenameBase ) )
|
||||
{
|
||||
File f = null;
|
||||
if ( carMode )
|
||||
{
|
||||
File carFile = new File( new File( base, "carsubset" ), filenameBase + ".cd5" );
|
||||
if ( carFile.exists() ) f = carFile;
|
||||
}
|
||||
if ( f == null )
|
||||
{
|
||||
File fullFile = new File( base, filenameBase + ".rd5" );
|
||||
if ( fullFile.exists() ) f = fullFile;
|
||||
if ( carMode && f != null ) oom_carsubset_hint = true;
|
||||
}
|
||||
RandomAccessFile ra = f != null ? new RandomAccessFile( f, "r" ) : null;
|
||||
fileCache.put( filenameBase, ra );
|
||||
if ( ra != null )
|
||||
{
|
||||
long[] fileIndex = new long[25];
|
||||
ra.readFully( iobuffer, 0, 200 );
|
||||
ByteDataReader dis = new ByteDataReader( iobuffer );
|
||||
for( int i=0; i<25; i++ )
|
||||
{
|
||||
long lv = dis.readLong();
|
||||
short readVersion = (short)(lv >> 48);
|
||||
if ( readVersion != lookupVersion )
|
||||
{
|
||||
throw new IllegalArgumentException( "lookup version mismatch (old rd5?) lookups.dat="
|
||||
+ lookupVersion + " " + f. getAbsolutePath() + "=" + readVersion );
|
||||
}
|
||||
fileIndex[i] = lv & 0xffffffffffffL;
|
||||
}
|
||||
indexCache.put( filenameBase, fileIndex );
|
||||
}
|
||||
}
|
||||
RandomAccessFile ra = fileCache.get( filenameBase );
|
||||
long startPos = 0L;
|
||||
if ( ra != null )
|
||||
{
|
||||
long[] index = indexCache.get( filenameBase );
|
||||
startPos = tileIndex > 0 ? index[ tileIndex-1 ] : 200L;
|
||||
if ( startPos == index[ tileIndex] ) ra = null;
|
||||
}
|
||||
OsmFile osmf = new OsmFile( ra, startPos, iobuffer );
|
||||
osmf.lonDegree = lonDegree;
|
||||
osmf.latDegree = latDegree;
|
||||
osmf.filename = currentFileName;
|
||||
return osmf;
|
||||
}
|
||||
|
||||
public List<OsmNode> getAllNodes()
|
||||
{
|
||||
List<OsmNode> all = new ArrayList<OsmNode>();
|
||||
for( MicroCache segment : segmentList )
|
||||
{
|
||||
List<OsmNode> positions = segment.getPositions( nodesMap );
|
||||
all.addAll( positions );
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
|
||||
public void close()
|
||||
{
|
||||
for( RandomAccessFile f: fileCache.values() )
|
||||
{
|
||||
try
|
||||
{
|
||||
f.close();
|
||||
}
|
||||
catch( IOException ioe )
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Container for link between two Osm nodes
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
final class NodesList
|
||||
{
|
||||
public OsmNode node;
|
||||
public NodesList next;
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* cache for a single square
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
final class OsmFile
|
||||
{
|
||||
private RandomAccessFile is = null;
|
||||
private long fileOffset;
|
||||
|
||||
private int[] posIdx;
|
||||
public MicroCache[] microCaches;
|
||||
|
||||
public int lonDegree;
|
||||
public int latDegree;
|
||||
|
||||
public String filename;
|
||||
|
||||
public OsmFile( RandomAccessFile rafile, long startPos, byte[] iobuffer ) throws Exception
|
||||
{
|
||||
fileOffset = startPos;
|
||||
if ( rafile != null )
|
||||
{
|
||||
is = rafile;
|
||||
posIdx = new int[6400];
|
||||
microCaches = new MicroCache[6400];
|
||||
is.seek( fileOffset );
|
||||
is.readFully( iobuffer, 0, 25600 );
|
||||
ByteDataReader dis = new ByteDataReader( iobuffer );
|
||||
for( int i=0; i<6400; i++ )
|
||||
{
|
||||
posIdx[i] = dis.readInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getPosIdx( int idx )
|
||||
{
|
||||
return idx == -1 ? 25600 : posIdx[idx];
|
||||
}
|
||||
|
||||
public int getDataInputForSubIdx( int subIdx, byte[] iobuffer ) throws Exception
|
||||
{
|
||||
int startPos = getPosIdx(subIdx-1);
|
||||
int endPos = getPosIdx(subIdx);
|
||||
int size = endPos-startPos;
|
||||
if ( size > 0 )
|
||||
{
|
||||
is.seek( fileOffset + startPos );
|
||||
if ( size <= iobuffer.length )
|
||||
{
|
||||
is.readFully( iobuffer );
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
try { is.close(); } catch( IOException e ) { throw new RuntimeException( e ); }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Container for link between two Osm nodes
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class OsmLink
|
||||
{
|
||||
/**
|
||||
* The description bitmap is mainly the way description
|
||||
* used to calculate the costfactor
|
||||
*/
|
||||
public long descriptionBitmap;
|
||||
|
||||
/**
|
||||
* The target is either the next link or the target node
|
||||
*/
|
||||
public OsmNode targetNode;
|
||||
|
||||
/**
|
||||
* The origin position
|
||||
*/
|
||||
public int ilatOrigin;
|
||||
public int ilonOrigin;
|
||||
|
||||
public OsmLink next;
|
||||
|
||||
public byte[] firsttransferBytes;
|
||||
|
||||
public OsmTransferNode decodeFirsttransfer()
|
||||
{
|
||||
return firsttransferBytes == null ? null : OsmTransferNode.decode( firsttransferBytes );
|
||||
}
|
||||
|
||||
public void encodeFirsttransfer( OsmTransferNode firsttransfer )
|
||||
{
|
||||
if ( firsttransfer == null ) firsttransferBytes = null;
|
||||
else firsttransferBytes = OsmTransferNode.encode( firsttransfer );
|
||||
}
|
||||
|
||||
public boolean counterLinkWritten;
|
||||
|
||||
public OsmLinkHolder firstlinkholder = null;
|
||||
|
||||
public void addLinkHolder( OsmLinkHolder holder )
|
||||
{
|
||||
if ( firstlinkholder != null ) { holder.setNextForLink( firstlinkholder ); }
|
||||
firstlinkholder = holder;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Container for routig configs
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
public interface OsmLinkHolder
|
||||
{
|
||||
void setNextForLink( OsmLinkHolder holder );
|
||||
|
||||
OsmLinkHolder getNextForLink();
|
||||
}
|
||||
397
brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java
Normal file
397
brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
/**
|
||||
* Container for an osm node
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
|
||||
|
||||
public class OsmNode implements OsmPos, Comparable
|
||||
{
|
||||
private static final long serialVersionUID = -4166565134085275556L;
|
||||
|
||||
public static final int EXTERNAL_BITMASK = 0x80;
|
||||
public static final int FIRSTFORWAY_BITMASK = 0x40;
|
||||
public static final int TRANSFERNODE_BITMASK = 0x20;
|
||||
public static final int WRITEDESC_BITMASK = 0x10;
|
||||
public static final int SKIPDETAILS_BITMASK = 0x08;
|
||||
public static final int NODEDESC_BITMASK = 0x04;
|
||||
|
||||
public OsmNode()
|
||||
{
|
||||
}
|
||||
|
||||
public OsmNode( int ilon, int ilat )
|
||||
{
|
||||
this.ilon = ilon;
|
||||
this.ilat = ilat;
|
||||
}
|
||||
|
||||
public OsmNode( long id )
|
||||
{
|
||||
ilon = (int)(id >> 32);
|
||||
ilat = (int)(id & 0xffffffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* The latitude
|
||||
*/
|
||||
public int ilat;
|
||||
|
||||
/**
|
||||
* The longitude
|
||||
*/
|
||||
public int ilon;
|
||||
|
||||
/**
|
||||
* The elevation
|
||||
*/
|
||||
public short selev;
|
||||
|
||||
public long nodeDescription;
|
||||
|
||||
// interface OsmPos
|
||||
public int getILat()
|
||||
{
|
||||
return ilat;
|
||||
}
|
||||
|
||||
public int getILon()
|
||||
{
|
||||
return ilon;
|
||||
}
|
||||
|
||||
public short getSElev()
|
||||
{
|
||||
return selev;
|
||||
}
|
||||
|
||||
public double getElev()
|
||||
{
|
||||
return selev / 4.;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether there's a traffic signal
|
||||
*/
|
||||
|
||||
/**
|
||||
* The links to other nodes
|
||||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
public OsmLink firstreverse = null;
|
||||
|
||||
// whether this node is completed and registerd for map-removal
|
||||
public boolean completed;
|
||||
|
||||
public boolean wasProcessed;
|
||||
public int maxcost; // maximum cost to consider for that node
|
||||
|
||||
public void addLink( OsmLink link )
|
||||
{
|
||||
if ( firstlink != null ) link.next = firstlink;
|
||||
firstlink = link;
|
||||
}
|
||||
|
||||
public int calcDistance( OsmPos p )
|
||||
{
|
||||
double l = (ilat-90000000) * 0.00000001234134;
|
||||
double l2 = l*l;
|
||||
double l4 = l2*l2;
|
||||
double coslat = 1.- l2 + l4 / 6.;
|
||||
|
||||
double dlat = (ilat - p.getILat() )/1000000.;
|
||||
double dlon = (ilon - p.getILon() )/1000000. * coslat;
|
||||
double d = Math.sqrt( dlat*dlat + dlon*dlon ) * (6378000. / 57.3);
|
||||
return (int)(d + 1.0 );
|
||||
}
|
||||
|
||||
|
||||
public void parseNodeBody( MicroCache is, int bodySize, OsmNodesMap hollowNodes, DistanceChecker dc )
|
||||
{
|
||||
selev = is.readShort();
|
||||
bodySize -= 2;
|
||||
|
||||
OsmLink lastlink = null;
|
||||
|
||||
int lonIdx = ilon/62500;
|
||||
int latIdx = ilat/62500;
|
||||
|
||||
while( bodySize > 0 )
|
||||
{
|
||||
OsmLink link = new OsmLink();
|
||||
OsmTransferNode firstTransferNode = null;
|
||||
OsmTransferNode lastTransferNode = null;
|
||||
int linklon;
|
||||
int linklat;
|
||||
long description = 0L;
|
||||
for(;;)
|
||||
{
|
||||
int bitField = is.readByte();
|
||||
bodySize -= 1;
|
||||
if ( (bitField & EXTERNAL_BITMASK) != 0 )
|
||||
{
|
||||
// full position for external target
|
||||
bodySize -= 8;
|
||||
linklon = is.readInt();
|
||||
linklat = is.readInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
// reduced position for internal target
|
||||
bodySize -= 4;
|
||||
linklon = is.readShort();
|
||||
linklat = is.readShort();
|
||||
linklon += lonIdx*62500 + 31250;
|
||||
linklat += latIdx*62500 + 31250;
|
||||
}
|
||||
if ( (bitField & WRITEDESC_BITMASK ) != 0 )
|
||||
{
|
||||
description = is.readLong();
|
||||
bodySize -= 8;
|
||||
}
|
||||
if ( (bitField & NODEDESC_BITMASK ) != 0 )
|
||||
{
|
||||
nodeDescription = is.readLong();
|
||||
bodySize -= 8;
|
||||
}
|
||||
if ( (bitField & SKIPDETAILS_BITMASK ) != 0 )
|
||||
{
|
||||
link.counterLinkWritten = true;
|
||||
}
|
||||
boolean isTransfer = (bitField & TRANSFERNODE_BITMASK ) != 0;
|
||||
if ( isTransfer )
|
||||
{
|
||||
OsmTransferNode trans = new OsmTransferNode();
|
||||
trans.ilon = linklon;
|
||||
trans.ilat = linklat;
|
||||
trans.descriptionBitmap = description;
|
||||
bodySize -= 2;
|
||||
trans.selev = is.readShort();
|
||||
if ( lastTransferNode == null )
|
||||
{
|
||||
firstTransferNode = trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastTransferNode.next = trans;
|
||||
}
|
||||
lastTransferNode = trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
link.descriptionBitmap = description;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// performance shortcut: ignore link if out of reach
|
||||
if ( dc != null && !link.counterLinkWritten )
|
||||
{
|
||||
if ( !dc.isWithinRadius( ilon, ilat, firstTransferNode, linklon, linklat ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( linklon == ilon && linklat == ilat )
|
||||
{
|
||||
continue; // skip self-ref
|
||||
}
|
||||
|
||||
if ( lastlink == null )
|
||||
{
|
||||
firstlink = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastlink.next = link;
|
||||
}
|
||||
lastlink = link;
|
||||
|
||||
|
||||
long targetNodeId = ((long)linklon)<<32 | linklat;
|
||||
OsmNode tn = hollowNodes.get( targetNodeId ); // target node
|
||||
|
||||
if ( tn == null )
|
||||
{
|
||||
// node not yet known, create a hollow proxy
|
||||
tn = new OsmNode(linklon, linklat);
|
||||
tn.setHollow();
|
||||
hollowNodes.put( targetNodeId, tn );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !( tn.isHollow() || tn.hasHollowLinks() ) )
|
||||
{
|
||||
hollowNodes.registerCompletedNode( tn );
|
||||
}
|
||||
}
|
||||
link.targetNode = tn;
|
||||
|
||||
link.encodeFirsttransfer(firstTransferNode);
|
||||
|
||||
// compute the reverse link
|
||||
if ( !link.counterLinkWritten )
|
||||
{
|
||||
OsmLink rlink = new OsmLink();
|
||||
long rerverseLinkBitmap = link.descriptionBitmap ^ 1L;
|
||||
|
||||
rlink.ilonOrigin = tn.ilon;
|
||||
rlink.ilatOrigin = tn.ilat;
|
||||
rlink.targetNode = this;
|
||||
rlink.descriptionBitmap = rerverseLinkBitmap; // default for no transfer-nodes
|
||||
OsmTransferNode previous = null;
|
||||
OsmTransferNode rtrans = null;
|
||||
for( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next )
|
||||
{
|
||||
long rerverseTransBitmap = trans.descriptionBitmap ^ 1L;
|
||||
if ( previous == null )
|
||||
{
|
||||
rlink.descriptionBitmap = rerverseTransBitmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous.descriptionBitmap = rerverseTransBitmap;
|
||||
}
|
||||
rtrans = new OsmTransferNode();
|
||||
rtrans.ilon = trans.ilon;
|
||||
rtrans.ilat = trans.ilat;
|
||||
rtrans.selev = trans.selev;
|
||||
rtrans.next = previous;
|
||||
rtrans.descriptionBitmap = rerverseLinkBitmap;
|
||||
previous = rtrans;
|
||||
}
|
||||
rlink.encodeFirsttransfer(rtrans);
|
||||
rlink.next = firstreverse;
|
||||
firstreverse = rlink;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !hasHollowLinks() )
|
||||
{
|
||||
hollowNodes.registerCompletedNode( this );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHollow()
|
||||
{
|
||||
return selev == -12345;
|
||||
}
|
||||
|
||||
public void setHollow()
|
||||
{
|
||||
selev = -12345;
|
||||
}
|
||||
|
||||
public long getIdFromPos()
|
||||
{
|
||||
return ((long)ilon)<<32 | ilat;
|
||||
}
|
||||
|
||||
public boolean hasHollowLinks()
|
||||
{
|
||||
for( OsmLink link = firstlink; link != null; link = link.next )
|
||||
{
|
||||
if ( link.targetNode.isHollow() ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public int linkCnt()
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
for( OsmLink link = firstlink; link != null; link = link.next )
|
||||
{
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
public void unlinkLink( OsmLink link )
|
||||
{
|
||||
if ( link == firstlink )
|
||||
{
|
||||
firstlink = link.next;
|
||||
return;
|
||||
}
|
||||
for( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( l.next == link )
|
||||
{
|
||||
l.next = link.next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two OsmNodes for position ordering.
|
||||
*
|
||||
* @return -1,0,1 depending an comparson result
|
||||
*/
|
||||
public int compareTo( Object o )
|
||||
{
|
||||
OsmNode n = (OsmNode)o;
|
||||
long id1 = getIdFromPos();
|
||||
long id2 = n.getIdFromPos();
|
||||
if ( id1 < id2 ) return -1;
|
||||
if ( id1 > id2 ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if equals in the sense of compareTo == 0
|
||||
*/
|
||||
public boolean equals( Object o )
|
||||
{
|
||||
return compareTo( o ) == 0;
|
||||
}
|
||||
|
||||
// mark the link to the given node as written,
|
||||
// don't want to write the counter-direction
|
||||
// in full details
|
||||
public void markLinkWritten( OsmNode t )
|
||||
{
|
||||
for( OsmLink link = firstlink; link != null; link = link.next )
|
||||
{
|
||||
if ( link.targetNode == t) link.counterLinkWritten = true;
|
||||
}
|
||||
}
|
||||
|
||||
public OsmLink getReverseLink( int lon, int lat )
|
||||
{
|
||||
for( OsmLink rlink = firstreverse; rlink != null; rlink = rlink.next )
|
||||
{
|
||||
if ( rlink.ilonOrigin == lon && rlink.ilatOrigin == lat )
|
||||
{
|
||||
unlinkRLink( rlink );
|
||||
return rlink;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void unlinkRLink( OsmLink rlink )
|
||||
{
|
||||
if ( rlink == firstreverse )
|
||||
{
|
||||
firstreverse = rlink.next;
|
||||
return;
|
||||
}
|
||||
for( OsmLink l = firstreverse; l != null; l = l.next )
|
||||
{
|
||||
if ( l.next == rlink )
|
||||
{
|
||||
l.next = rlink.next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* Container for link between two Osm nodes
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class OsmNodesMap
|
||||
{
|
||||
private HashMap<Long,OsmNode> hmap = new HashMap<Long,OsmNode>();
|
||||
|
||||
private NodesList completedNodes = null;
|
||||
|
||||
/**
|
||||
* Get a node from the map
|
||||
* @return the node for the given id if exist, else null
|
||||
*/
|
||||
public OsmNode get( long id )
|
||||
{
|
||||
return hmap.get( new Long( id ) );
|
||||
}
|
||||
|
||||
|
||||
public void remove( long id )
|
||||
{
|
||||
hmap.remove( new Long( id ) );
|
||||
}
|
||||
|
||||
public void removeCompletedNodes()
|
||||
{
|
||||
for( NodesList le = completedNodes; le != null; le = le.next )
|
||||
{
|
||||
remove( le.node.getIdFromPos() );
|
||||
}
|
||||
completedNodes = null;
|
||||
}
|
||||
|
||||
public void registerCompletedNode( OsmNode n )
|
||||
{
|
||||
if ( n.completed ) return;
|
||||
n.completed = true;
|
||||
NodesList le = new NodesList();
|
||||
le.node = n;
|
||||
if ( completedNodes != null ) le.next = completedNodes;
|
||||
completedNodes = le;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a node into the map
|
||||
* @return the previous node if that id existed, else null
|
||||
*/
|
||||
public OsmNode put( long id, OsmNode node )
|
||||
{
|
||||
return hmap.put( new Long( id ), node );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the internal list.
|
||||
* A reference is returned, not a copy-
|
||||
* @return the nodes list
|
||||
*/
|
||||
public Collection<OsmNode> nodes()
|
||||
{
|
||||
return hmap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of nodes in that map
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return hmap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup the map by removing the nodes
|
||||
* with no hollow issues
|
||||
*/
|
||||
|
||||
private int dontCareCount = 0;
|
||||
|
||||
public void removeCompleteNodes()
|
||||
{
|
||||
if ( ++dontCareCount < 5 ) return;
|
||||
dontCareCount = 0;
|
||||
|
||||
ArrayList<OsmNode> delNodes = new ArrayList<OsmNode>();
|
||||
|
||||
for( OsmNode n : hmap.values() )
|
||||
{
|
||||
if ( n.isHollow() || n.hasHollowLinks() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
delNodes.add( n );
|
||||
}
|
||||
|
||||
if ( delNodes.size() > 0 )
|
||||
{
|
||||
// System.out.println( "removing " + delNodes.size() + " nodes" );
|
||||
for( OsmNode n : delNodes )
|
||||
{
|
||||
hmap.remove( new Long( n.getIdFromPos() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
brouter-mapaccess/src/main/java/btools/mapaccess/OsmPos.java
Normal file
23
brouter-mapaccess/src/main/java/btools/mapaccess/OsmPos.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Interface for a position (OsmNode or OsmPath)
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
|
||||
public interface OsmPos
|
||||
{
|
||||
public int getILat();
|
||||
|
||||
public int getILon();
|
||||
|
||||
public short getSElev();
|
||||
|
||||
public double getElev();
|
||||
|
||||
public int calcDistance( OsmPos p );
|
||||
|
||||
public long getIdFromPos();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
* Container for link between two Osm nodes
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
public final class OsmTransferNode
|
||||
{
|
||||
/**
|
||||
* The description bitmap is mainly the way description
|
||||
* used to calculate the costfactor
|
||||
*/
|
||||
public long descriptionBitmap;
|
||||
|
||||
public OsmTransferNode next;
|
||||
|
||||
public int ilon;
|
||||
public int ilat;
|
||||
public short selev;
|
||||
|
||||
private static final int BIT_DESC = 1;
|
||||
private static final int BIT_ILONHIGH = 2;
|
||||
private static final int BIT_ILATHIGH = 4;
|
||||
private static final int BIT_STOP = 8;
|
||||
|
||||
// encode this transfer-node into a byte array
|
||||
public static byte[] encode( OsmTransferNode tn )
|
||||
{
|
||||
long currentDesc = 0;
|
||||
int currentILonHigh = 0;
|
||||
int currentILatHigh = 0;
|
||||
OsmTransferNode n = tn;
|
||||
|
||||
// first loop to calc size
|
||||
int size = 1; // stop-bit
|
||||
|
||||
while( n != null )
|
||||
{
|
||||
if( n.descriptionBitmap != currentDesc )
|
||||
{
|
||||
size += 8;
|
||||
currentDesc = n.descriptionBitmap;
|
||||
}
|
||||
if( ( n.ilon >> 16 ) != currentILonHigh )
|
||||
{
|
||||
size += 2;
|
||||
currentILonHigh = n.ilon >> 16;
|
||||
}
|
||||
if( (n.ilat >> 16) != currentILatHigh )
|
||||
{
|
||||
size += 2;
|
||||
currentILatHigh = n.ilat >> 16;
|
||||
}
|
||||
size += 7;
|
||||
n = n.next;
|
||||
}
|
||||
|
||||
byte[] ab = new byte[size];
|
||||
ByteDataWriter os = new ByteDataWriter( ab );
|
||||
|
||||
currentDesc = 0;
|
||||
currentILonHigh = 0;
|
||||
currentILatHigh = 0;
|
||||
n = tn;
|
||||
while( n != null )
|
||||
{
|
||||
int mode = 0;
|
||||
if( n.descriptionBitmap != currentDesc )
|
||||
{
|
||||
mode |= BIT_DESC;
|
||||
currentDesc = n.descriptionBitmap;
|
||||
}
|
||||
if( ( n.ilon >> 16 ) != currentILonHigh )
|
||||
{
|
||||
mode |= BIT_ILONHIGH;
|
||||
currentILonHigh = n.ilon >> 16;
|
||||
}
|
||||
if( (n.ilat >> 16) != currentILatHigh )
|
||||
{
|
||||
mode |= BIT_ILATHIGH;
|
||||
currentILatHigh = n.ilat >> 16;
|
||||
}
|
||||
os.writeByte( mode);
|
||||
if ( (mode & BIT_DESC) != 0 ) os.writeLong( currentDesc );
|
||||
if ( (mode & BIT_ILONHIGH) != 0 ) os.writeShort( currentILonHigh );
|
||||
if ( (mode & BIT_ILATHIGH) != 0 ) os.writeShort( currentILatHigh );
|
||||
os.writeShort( n.ilon );
|
||||
os.writeShort( n.ilat );
|
||||
os.writeShort( n.selev );
|
||||
n = n.next;
|
||||
}
|
||||
os.writeByte( BIT_STOP );
|
||||
return ab;
|
||||
}
|
||||
|
||||
// decode a transfer-node from a byte array
|
||||
public static OsmTransferNode decode( byte[] ab )
|
||||
{
|
||||
ByteDataReader is = new ByteDataReader( ab );
|
||||
|
||||
OsmTransferNode firstNode = null;
|
||||
OsmTransferNode lastNode = null;
|
||||
long currentDesc = 0;
|
||||
int currentILonHigh = 0;
|
||||
int currentILatHigh = 0;
|
||||
for(;;)
|
||||
{
|
||||
byte mode = is.readByte();
|
||||
if ( (mode & BIT_STOP ) != 0 ) break;
|
||||
|
||||
OsmTransferNode n = new OsmTransferNode();
|
||||
if ( (mode & BIT_DESC) != 0 ) currentDesc = is.readLong();
|
||||
if ( (mode & BIT_ILONHIGH) != 0 ) currentILonHigh = is.readShort();
|
||||
if ( (mode & BIT_ILATHIGH) != 0 ) currentILatHigh = is.readShort();
|
||||
n.descriptionBitmap = currentDesc;
|
||||
int ilon = is.readShort() & 0xffff; ilon |= currentILonHigh << 16;
|
||||
int ilat = is.readShort() & 0xffff; ilat |= currentILatHigh << 16;
|
||||
n.ilon = ilon;
|
||||
n.ilat = ilat;
|
||||
n.selev = is.readShort();
|
||||
|
||||
if ( ilon != n.ilon ) System.out.println( "ilon=" + ilon + " n.ilon=" + n.ilon );
|
||||
if ( ilat != n.ilat ) System.out.println( "ilat=" + ilat + " n.ilat=" + n.ilat );
|
||||
|
||||
if ( lastNode != null )
|
||||
{
|
||||
lastNode.next = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstNode = n;
|
||||
}
|
||||
lastNode = n;
|
||||
}
|
||||
return firstNode;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue