map access layer cleanup

This commit is contained in:
Arndt 2015-09-12 16:12:24 +02:00
parent 2cec35f3cc
commit f8dee5b7d1
7 changed files with 163 additions and 150 deletions

View file

@ -109,7 +109,7 @@ final class OsmPath implements OsmLinkHolder
private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc ) private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc )
{ {
if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() ); if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for: " + link );
boolean recordTransferNodes = detailMode || rc.countTraffic; boolean recordTransferNodes = detailMode || rc.countTraffic;
boolean recordMessageData = detailMode; boolean recordMessageData = detailMode;

View file

@ -381,7 +381,7 @@ public class RoutingEngine extends Thread
{ {
continue; continue;
} }
expandHollowLinkTargets( n, false ); expandHollowLinkTargets( n );
OsmLink startLink = new OsmLink(); OsmLink startLink = new OsmLink();
startLink.targetNode = n; startLink.targetNode = n;
OsmPath startPath = new OsmPath( startLink ); OsmPath startPath = new OsmPath( startLink );
@ -418,30 +418,12 @@ public class RoutingEngine extends Thread
} }
// expand hollow link targets and resolve reverse links // expand hollow link targets and resolve reverse links
private void expandHollowLinkTargets( OsmNode n, boolean failOnReverseNotFound ) private void expandHollowLinkTargets( OsmNode n )
{ {
for( OsmLink link = n.firstlink; link != null; link = link.next ) for( OsmLink link = n.firstlink; link != null; link = link.next )
{ {
if ( ! nodesCache.obtainNonHollowNode( link.targetNode ) ) nodesCache.obtainNonHollowNode( link.targetNode );
{
continue;
}
if ( link.counterLinkWritten )
{
OsmLink rlink = link.targetNode.getReverseLink( n.getILon(), n.getILat() );
if ( rlink == null )
{
if ( failOnReverseNotFound ) throw new RuntimeException( "reverse link not found!" );
}
else
{
link.descriptionBitmap = rlink.descriptionBitmap;
link.firsttransferBytes = rlink.firsttransferBytes;
}
}
} }
n.wasProcessed = true;
} }
private OsmTrack searchTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack ) private OsmTrack searchTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack )
@ -541,7 +523,7 @@ public class RoutingEngine extends Thread
{ {
return null; return null;
} }
expandHollowLinkTargets( start, true ); expandHollowLinkTargets( start );
return start; return start;
} }
@ -804,10 +786,7 @@ public class RoutingEngine extends Thread
continue; continue;
} }
if ( !currentNode.wasProcessed ) expandHollowLinkTargets( currentNode );
{
expandHollowLinkTargets( currentNode, true );
}
if ( sourceNode != null ) if ( sourceNode != null )
{ {

View file

@ -26,6 +26,7 @@ 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:";
private static final String VARLENGTH_TAG = "---readvarlength";
public short lookupVersion = -1; public short lookupVersion = -1;
public short lookupMinorVersion = -1; public short lookupMinorVersion = -1;
@ -66,6 +67,10 @@ public final class BExpressionMetaData
lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) ); lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) );
continue; continue;
} }
if ( line.startsWith( VARLENGTH_TAG ) ) // tag removed...
{
continue;
}
if ( ctx != null ) ctx.parseMetaLine( line ); if ( ctx != null ) ctx.parseMetaLine( line );
} }
br.close(); br.close();

View file

@ -14,7 +14,7 @@ import btools.util.Crc32;
final class MicroCache extends ByteDataReader final class MicroCache extends ByteDataReader
{ {
private long[] faid; private int[] faid;
private int[] fapos; private int[] fapos;
private int size = 0; private int size = 0;
private int delcount = 0; private int delcount = 0;
@ -24,6 +24,9 @@ final class MicroCache extends ByteDataReader
// the object parsing position and length // the object parsing position and length
private int aboffsetEnd; private int aboffsetEnd;
private int lonIdxBase;
private int latIdxBase;
// cache control: a virgin cache can be // cache control: a virgin cache can be
// put to ghost state for later recovery // put to ghost state for later recovery
boolean virgin = true; boolean virgin = true;
@ -35,8 +38,8 @@ final class MicroCache extends ByteDataReader
int lonDegree = lonIdx80/80; int lonDegree = lonIdx80/80;
int latDegree = latIdx80/80; int latDegree = latIdx80/80;
int lonIdxBase = (lonIdx80/5)*62500 + 31250; lonIdxBase = (lonIdx80/5)*62500 + 31250;
int latIdxBase = (latIdx80/5)*62500 + 31250; latIdxBase = (latIdx80/5)*62500 + 31250;
int subIdx = (latIdx80-80*latDegree)*80 + (lonIdx80-80*lonDegree); int subIdx = (latIdx80-80*latDegree)*80 + (lonIdx80-80*lonDegree);
@ -61,8 +64,7 @@ final class MicroCache extends ByteDataReader
int nbytes = 0; int nbytes = 0;
for(int i = 0; i<size; i++) for(int i = 0; i<size; i++)
{ {
int ilon = readShort(); aboffset += 4;
int ilat = readShort();
int bodySize = readVarLengthUnsigned(); int bodySize = readVarLengthUnsigned();
aboffset += bodySize; aboffset += bodySize;
@ -79,20 +81,15 @@ final class MicroCache extends ByteDataReader
byte[] nab = new byte[nbytes]; byte[] nab = new byte[nbytes];
aboffset = 4; aboffset = 4;
int noffset = 0; int noffset = 0;
faid = new long[size]; faid = new int[size];
fapos = new int[size]; fapos = new int[size];
p2size = 0x40000000; p2size = 0x40000000;
while( p2size > size ) p2size >>= 1; while( p2size > size ) p2size >>= 1;
for(int i = 0; i<size; i++) for(int i = 0; i<size; i++)
{ {
int ilon = readShort(); faid[i] = readInt() ^ 0x8000; // flip lat-sign for correct ordering
int ilat = readShort();
ilon += lonIdxBase;
ilat += latIdxBase;
long nodeId = ((long)ilon)<<32 | ilat;
faid[i] = nodeId;
int bodySize = readVarLengthUnsigned(); int bodySize = readVarLengthUnsigned();
fapos[i] = noffset; fapos[i] = noffset;
System.arraycopy( ab, aboffset, nab, noffset, bodySize ); System.arraycopy( ab, aboffset, nab, noffset, bodySize );
@ -123,13 +120,14 @@ final class MicroCache extends ByteDataReader
* Throws an exception if that id was already requested * Throws an exception if that id was already requested
* as an early detector for identity problems * as an early detector for identity problems
*/ */
private boolean getAndClear( long id ) private boolean getAndClear( long id64 )
{ {
if ( size == 0 ) if ( size == 0 )
{ {
return false; return false;
} }
long[] a = faid; int id = shrinkId( id64 );
int[] a = faid;
int offset = p2size; int offset = p2size;
int n = 0; int n = 0;
@ -194,7 +192,7 @@ final class MicroCache extends ByteDataReader
} }
else else
{ {
long[] nfaid = new long[nsize]; int[] nfaid = new int[nsize];
int[] nfapos = new int[nsize]; int[] nfapos = new int[nsize];
int idx = 0; int idx = 0;
@ -242,14 +240,30 @@ final class MicroCache extends ByteDataReader
for( int i=0; i<size; i++ ) for( int i=0; i<size; i++ )
{ {
OsmNode n = new OsmNode( faid[i] ); int id32 = faid[i];
long id64 = expandId( id32 );
OsmNode n = new OsmNode( id64 );
n.setHollow(); n.setHollow();
nodesMap.put( faid[i], n ); nodesMap.put( n );
positions.add( n ); positions.add( n );
} }
return positions; return positions;
} }
private long expandId( int id32 )
{
int lon32 = lonIdxBase + (short)(id32 >> 16);
int lat32 = latIdxBase + (short)((id32 & 0xffff) ^ 0x8000);
return ((long)lon32)<<32 | lat32;
}
private int shrinkId( long id64 )
{
int lon32 = (int)(id64 >> 32);
int lat32 = (int)(id64 & 0xffffffff);
return (lon32 - lonIdxBase)<<16 | ( ( (lat32 - latIdxBase) & 0xffff) ^ 0x8000);
}
public boolean hasMoreData() public boolean hasMoreData()
{ {
return aboffset < aboffsetEnd; return aboffset < aboffsetEnd;

View file

@ -19,12 +19,6 @@ public class OsmLink
*/ */
public OsmNode targetNode; public OsmNode targetNode;
/**
* The origin position
*/
public int ilatOrigin;
public int ilonOrigin;
public OsmLink next; public OsmLink next;
public byte[] firsttransferBytes; public byte[] firsttransferBytes;
@ -42,6 +36,8 @@ public class OsmLink
public boolean counterLinkWritten; public boolean counterLinkWritten;
public byte state;
public OsmLinkHolder firstlinkholder = null; public OsmLinkHolder firstlinkholder = null;
final public void addLinkHolder( OsmLinkHolder holder ) final public void addLinkHolder( OsmLinkHolder holder )
@ -49,4 +45,9 @@ public class OsmLink
if ( firstlinkholder != null ) { holder.setNextForLink( firstlinkholder ); } if ( firstlinkholder != null ) { holder.setNextForLink( firstlinkholder ); }
firstlinkholder = holder; firstlinkholder = holder;
} }
public String toString()
{
return "Link(target=" + targetNode.getIdFromPos() + " counterLinkWritten=" + counterLinkWritten + " state=" + state + ")";
}
} }

View file

@ -81,16 +81,52 @@ public class OsmNode implements OsmPos
*/ */
public OsmLink firstlink = null; public OsmLink firstlink = null;
public OsmLink firstreverse = null; // preliminry in forward order to avoid regressions
public boolean wasProcessed; // whether this node has all it's links resolved
public void addLink( OsmLink link ) public void addLink( OsmLink link )
{ {
if ( firstlink != null ) link.next = firstlink; if ( firstlink == null )
firstlink = link; {
firstlink = link;
}
else
{
OsmLink l = firstlink;
while( l.next != null ) l = l.next;
l.next = link;
}
} }
private OsmLink getCompatibleLink( int ilon, int ilat, boolean counterLinkWritten, int state )
{
for( OsmLink l = firstlink; l != null; l = l.next )
{
if ( counterLinkWritten == l.counterLinkWritten && l.state == state )
{
OsmNode t = l.targetNode;
if ( t.ilon == ilon && t.ilat == ilat )
{
l.state = 0;
return l;
}
}
}
// second try ignoring counterLinkWritten
// (border links are written in both directions)
for( OsmLink l = firstlink; l != null; l = l.next )
{
if ( l.state == state )
{
OsmNode t = l.targetNode;
if ( t.ilon == ilon && t.ilat == ilat )
{
l.state = 0;
return l;
}
}
}
return null;
}
public int calcDistance( OsmPos p ) public int calcDistance( OsmPos p )
{ {
double l = (ilat-90000000) * 0.00000001234134; double l = (ilat-90000000) * 0.00000001234134;
@ -104,6 +140,10 @@ public class OsmNode implements OsmPos
return (int)(d + 1.0 ); return (int)(d + 1.0 );
} }
public String toString()
{
return "" + getIdFromPos();
}
public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc ) public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc )
{ {
@ -111,17 +151,12 @@ public class OsmNode implements OsmPos
selev = is.readShort(); selev = is.readShort();
OsmLink lastlink = null;
OsmLink firstHollowLink = firstlink;
firstlink = null;
while( is.hasMoreData() ) while( is.hasMoreData() )
{ {
int ilonref = ilon; int ilonref = ilon;
int ilatref = ilat; int ilatref = ilat;
OsmLink link = new OsmLink(); boolean counterLinkWritten = false;
OsmTransferNode firstTransferNode = null; OsmTransferNode firstTransferNode = null;
OsmTransferNode lastTransferNode = null; OsmTransferNode lastTransferNode = null;
int linklon; int linklon;
@ -163,10 +198,10 @@ public class OsmNode implements OsmPos
} }
if ( (bitField & SKIPDETAILS_BITMASK ) != 0 ) if ( (bitField & SKIPDETAILS_BITMASK ) != 0 )
{ {
link.counterLinkWritten = true; counterLinkWritten = true;
} }
if ( description == null && !link.counterLinkWritten ) throw new IllegalArgumentException( "internal error: missing way description!" ); if ( description == null && !counterLinkWritten ) throw new IllegalArgumentException( "internal error: missing way description!" );
boolean isTransfer = (bitField & TRANSFERNODE_BITMASK ) != 0; boolean isTransfer = (bitField & TRANSFERNODE_BITMASK ) != 0;
if ( isTransfer ) if ( isTransfer )
@ -188,17 +223,16 @@ public class OsmNode implements OsmPos
} }
else else
{ {
link.descriptionBitmap = description;
break; break;
} }
} }
// performance shortcut: ignore link if out of reach // performance shortcut: ignore link if out of reach
if ( dc != null && !link.counterLinkWritten ) if ( dc != null && !counterLinkWritten )
{ {
if ( !dc.isWithinRadius( ilon, ilat, firstTransferNode, linklon, linklat ) ) if ( !dc.isWithinRadius( ilon, ilat, firstTransferNode, linklon, linklat ) )
{ {
// continue; continue;
} }
} }
@ -207,57 +241,46 @@ public class OsmNode implements OsmPos
continue; // skip self-ref continue; // skip self-ref
} }
if ( lastlink == null ) // first check the known links for that target
{ OsmLink link = getCompatibleLink( linklon, linklat, counterLinkWritten, 2 );
firstlink = link; if ( link == null ) // .. not found, then check the hollow nodes
}
else
{
lastlink.next = link;
}
lastlink = link;
OsmNode tn = null;
// first check the hollow links for that target
for( OsmLink l = firstHollowLink; l != null; l = l.next )
{
OsmNode t = l.targetNode;
if ( t.ilon == linklon && t.ilat == linklat )
{
tn = t;
break;
}
}
if ( tn == null ) // then check the hollow-nodes
{ {
long targetNodeId = ((long)linklon)<<32 | linklat; long targetNodeId = ((long)linklon)<<32 | linklat;
tn = hollowNodes.get( targetNodeId ); // target node OsmNode tn = hollowNodes.get( targetNodeId ); // target node
if ( tn == null ) // node not yet known, create a new hollow proxy if ( tn == null ) // node not yet known, create a new hollow proxy
{ {
tn = new OsmNode(linklon, linklat); tn = new OsmNode(linklon, linklat);
tn.setHollow(); tn.setHollow();
hollowNodes.put( targetNodeId, tn ); hollowNodes.put( tn );
} }
link = new OsmLink();
OsmLink hollowLink = new OsmLink(); link.targetNode = tn;
hollowLink.targetNode = this; link.counterLinkWritten = counterLinkWritten;
tn.addLink( hollowLink ); // make us known at the hollow link link.state = 1;
addLink( link );
} }
link.targetNode = tn;
link.encodeFirsttransfer(firstTransferNode); // now we have a link with a target node -> get the reverse link
OsmLink rlink = link.targetNode.getCompatibleLink( ilon, ilat, !counterLinkWritten, 1 );
// compute the reverse link if ( rlink == null ) // .. not found, create it
if ( !link.counterLinkWritten )
{ {
OsmLink rlink = new OsmLink(); rlink = new OsmLink();
byte[] linkDescriptionBitmap = link.descriptionBitmap; rlink.targetNode = this;
rlink.ilonOrigin = tn.ilon; rlink.counterLinkWritten = !counterLinkWritten;
rlink.ilatOrigin = tn.ilat; rlink.state = 2;
rlink.targetNode = this; link.targetNode.addLink( rlink );
rlink.descriptionBitmap = linkDescriptionBitmap; // default for no transfer-nodes }
if ( !counterLinkWritten )
{
// we have the data for that link, so fill both the link ..
link.descriptionBitmap = description;
link.encodeFirsttransfer(firstTransferNode);
// .. and the reverse
if ( rlink.counterLinkWritten )
{
rlink.descriptionBitmap = description; // default for no transfer-nodes
OsmTransferNode previous = null; OsmTransferNode previous = null;
OsmTransferNode rtrans = null; OsmTransferNode rtrans = null;
for( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next ) for( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next )
@ -275,17 +298,18 @@ public class OsmNode implements OsmPos
rtrans.ilat = trans.ilat; rtrans.ilat = trans.ilat;
rtrans.selev = trans.selev; rtrans.selev = trans.selev;
rtrans.next = previous; rtrans.next = previous;
rtrans.descriptionBitmap = linkDescriptionBitmap; rtrans.descriptionBitmap = description;
previous = rtrans; previous = rtrans;
} }
rlink.encodeFirsttransfer(rtrans); rlink.encodeFirsttransfer(rtrans);
rlink.next = firstreverse; }
firstreverse = rlink;
} }
} }
if ( dc == null )
hollowNodes.remove( getIdFromPos() ); {
hollowNodes.remove( this );
}
} }
public boolean isHollow() public boolean isHollow()
@ -320,34 +344,20 @@ public class OsmNode implements OsmPos
} }
} }
public OsmLink getReverseLink( int lon, int lat ) @Override
{ public boolean equals( Object o )
for( OsmLink rlink = firstreverse; rlink != null; rlink = rlink.next ) {
{ if ( o instanceof OsmNode )
if ( rlink.ilonOrigin == lon && rlink.ilatOrigin == lat ) {
{ OsmNode n = (OsmNode)o;
unlinkRLink( rlink ); return n.ilon == ilon && n.ilat == ilat;
return rlink; }
} return false;
} }
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;
}
}
}
@Override
public int hashCode( )
{
return ilon + ilat;
}
} }

View file

@ -11,10 +11,12 @@ import btools.util.ByteArrayUnifier;
public final class OsmNodesMap public final class OsmNodesMap
{ {
private HashMap<Long,OsmNode> hmap = new HashMap<Long,OsmNode>(); private HashMap<OsmNode,OsmNode> hmap = new HashMap<OsmNode,OsmNode>();
private ByteArrayUnifier abUnifier = new ByteArrayUnifier( 16384, false ); private ByteArrayUnifier abUnifier = new ByteArrayUnifier( 16384, false );
private OsmNode testKey = new OsmNode();
public ByteArrayUnifier getByteArrayUnifier() public ByteArrayUnifier getByteArrayUnifier()
{ {
return abUnifier; return abUnifier;
@ -26,22 +28,24 @@ public final class OsmNodesMap
*/ */
public OsmNode get( long id ) public OsmNode get( long id )
{ {
return hmap.get( new Long( id ) ); testKey.ilon = (int)(id >> 32);
testKey.ilat = (int)(id & 0xffffffff);
return hmap.get( testKey );
} }
public void remove( long id ) public void remove( OsmNode node )
{ {
hmap.remove( new Long( id ) ); hmap.remove( node );
} }
/** /**
* 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( long id, OsmNode node ) public OsmNode put( OsmNode node )
{ {
return hmap.put( new Long( id ), node ); return hmap.put( node, node );
} }