From f8dee5b7d1bab7ba72552023a2d4a330f2d29f74 Mon Sep 17 00:00:00 2001 From: Arndt Date: Sat, 12 Sep 2015 16:12:24 +0200 Subject: [PATCH] map access layer cleanup --- .../src/main/java/btools/router/OsmPath.java | 2 +- .../java/btools/router/RoutingEngine.java | 31 +-- .../expressions/BExpressionMetaData.java | 5 + .../java/btools/mapaccess/MicroCache.java | 50 +++-- .../main/java/btools/mapaccess/OsmLink.java | 13 +- .../main/java/btools/mapaccess/OsmNode.java | 196 +++++++++--------- .../java/btools/mapaccess/OsmNodesMap.java | 16 +- 7 files changed, 163 insertions(+), 150 deletions(-) diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index 32fd056..4e20fb6 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -109,7 +109,7 @@ final class OsmPath implements OsmLinkHolder 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 recordMessageData = detailMode; diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index 99f395d..74f3c91 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -381,7 +381,7 @@ public class RoutingEngine extends Thread { continue; } - expandHollowLinkTargets( n, false ); + expandHollowLinkTargets( n ); OsmLink startLink = new OsmLink(); startLink.targetNode = n; OsmPath startPath = new OsmPath( startLink ); @@ -418,30 +418,12 @@ public class RoutingEngine extends Thread } // 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 ) { - if ( ! 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; - } - } + nodesCache.obtainNonHollowNode( link.targetNode ); } - n.wasProcessed = true; } private OsmTrack searchTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack ) @@ -541,7 +523,7 @@ public class RoutingEngine extends Thread { return null; } - expandHollowLinkTargets( start, true ); + expandHollowLinkTargets( start ); return start; } @@ -804,10 +786,7 @@ public class RoutingEngine extends Thread continue; } - if ( !currentNode.wasProcessed ) - { - expandHollowLinkTargets( currentNode, true ); - } + expandHollowLinkTargets( currentNode ); if ( sourceNode != null ) { diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java index 477de29..6d5a901 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionMetaData.java @@ -26,6 +26,7 @@ public final class BExpressionMetaData private static final String CONTEXT_TAG = "---context:"; private static final String VERSION_TAG = "---lookupversion:"; private static final String MINOR_VERSION_TAG = "---minorversion:"; + private static final String VARLENGTH_TAG = "---readvarlength"; public short lookupVersion = -1; public short lookupMinorVersion = -1; @@ -66,6 +67,10 @@ public final class BExpressionMetaData lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) ); continue; } + if ( line.startsWith( VARLENGTH_TAG ) ) // tag removed... + { + continue; + } if ( ctx != null ) ctx.parseMetaLine( line ); } br.close(); diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/MicroCache.java b/brouter-mapaccess/src/main/java/btools/mapaccess/MicroCache.java index b3db47d..b48f514 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/MicroCache.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/MicroCache.java @@ -14,7 +14,7 @@ import btools.util.Crc32; final class MicroCache extends ByteDataReader { - private long[] faid; + private int[] faid; private int[] fapos; private int size = 0; private int delcount = 0; @@ -24,6 +24,9 @@ final class MicroCache extends ByteDataReader // the object parsing position and length private int aboffsetEnd; + private int lonIdxBase; + private int latIdxBase; + // cache control: a virgin cache can be // put to ghost state for later recovery boolean virgin = true; @@ -35,8 +38,8 @@ final class MicroCache extends ByteDataReader int lonDegree = lonIdx80/80; int latDegree = latIdx80/80; - int lonIdxBase = (lonIdx80/5)*62500 + 31250; - int latIdxBase = (latIdx80/5)*62500 + 31250; + lonIdxBase = (lonIdx80/5)*62500 + 31250; + latIdxBase = (latIdx80/5)*62500 + 31250; int subIdx = (latIdx80-80*latDegree)*80 + (lonIdx80-80*lonDegree); @@ -61,8 +64,7 @@ final class MicroCache extends ByteDataReader int nbytes = 0; for(int i = 0; i size ) p2size >>= 1; - + for(int i = 0; i> 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() { return aboffset < aboffsetEnd; diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmLink.java b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmLink.java index 2b8cebc..3243f81 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmLink.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmLink.java @@ -19,12 +19,6 @@ public class OsmLink */ public OsmNode targetNode; - /** - * The origin position - */ - public int ilatOrigin; - public int ilonOrigin; - public OsmLink next; public byte[] firsttransferBytes; @@ -42,6 +36,8 @@ public class OsmLink public boolean counterLinkWritten; + public byte state; + public OsmLinkHolder firstlinkholder = null; final public void addLinkHolder( OsmLinkHolder holder ) @@ -49,4 +45,9 @@ public class OsmLink if ( firstlinkholder != null ) { holder.setNextForLink( firstlinkholder ); } firstlinkholder = holder; } + + public String toString() + { + return "Link(target=" + targetNode.getIdFromPos() + " counterLinkWritten=" + counterLinkWritten + " state=" + state + ")"; + } } diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java index 9e539d5..f736a65 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java @@ -81,16 +81,52 @@ public class OsmNode implements OsmPos */ public OsmLink firstlink = null; - public OsmLink firstreverse = null; - - public boolean wasProcessed; // whether this node has all it's links resolved - + // preliminry in forward order to avoid regressions public void addLink( OsmLink link ) { - if ( firstlink != null ) link.next = firstlink; - firstlink = link; + if ( firstlink == null ) + { + 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 ) { double l = (ilat-90000000) * 0.00000001234134; @@ -104,6 +140,10 @@ public class OsmNode implements OsmPos return (int)(d + 1.0 ); } + public String toString() + { + return "" + getIdFromPos(); + } public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc ) { @@ -111,17 +151,12 @@ public class OsmNode implements OsmPos selev = is.readShort(); - OsmLink lastlink = null; - - OsmLink firstHollowLink = firstlink; - firstlink = null; - while( is.hasMoreData() ) { int ilonref = ilon; int ilatref = ilat; - OsmLink link = new OsmLink(); + boolean counterLinkWritten = false; OsmTransferNode firstTransferNode = null; OsmTransferNode lastTransferNode = null; int linklon; @@ -163,10 +198,10 @@ public class OsmNode implements OsmPos } 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; if ( isTransfer ) @@ -188,17 +223,16 @@ public class OsmNode implements OsmPos } else { - link.descriptionBitmap = description; break; } } // 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 ) ) { - // continue; + continue; } } @@ -207,57 +241,46 @@ public class OsmNode implements OsmPos continue; // skip self-ref } - if ( lastlink == null ) - { - firstlink = link; - } - 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 + // first check the known links for that target + OsmLink link = getCompatibleLink( linklon, linklat, counterLinkWritten, 2 ); + if ( link == null ) // .. not found, then check the hollow nodes { 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 { tn = new OsmNode(linklon, linklat); tn.setHollow(); - hollowNodes.put( targetNodeId, tn ); + hollowNodes.put( tn ); } - - OsmLink hollowLink = new OsmLink(); - hollowLink.targetNode = this; - tn.addLink( hollowLink ); // make us known at the hollow link + link = new OsmLink(); + link.targetNode = tn; + link.counterLinkWritten = counterLinkWritten; + link.state = 1; + addLink( link ); } - link.targetNode = tn; - link.encodeFirsttransfer(firstTransferNode); - - // compute the reverse link - if ( !link.counterLinkWritten ) + // now we have a link with a target node -> get the reverse link + OsmLink rlink = link.targetNode.getCompatibleLink( ilon, ilat, !counterLinkWritten, 1 ); + if ( rlink == null ) // .. not found, create it { - OsmLink rlink = new OsmLink(); - byte[] linkDescriptionBitmap = link.descriptionBitmap; - rlink.ilonOrigin = tn.ilon; - rlink.ilatOrigin = tn.ilat; - rlink.targetNode = this; - rlink.descriptionBitmap = linkDescriptionBitmap; // default for no transfer-nodes + rlink = new OsmLink(); + rlink.targetNode = this; + rlink.counterLinkWritten = !counterLinkWritten; + rlink.state = 2; + link.targetNode.addLink( rlink ); + } + + 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 rtrans = null; for( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next ) @@ -275,17 +298,18 @@ public class OsmNode implements OsmPos rtrans.ilat = trans.ilat; rtrans.selev = trans.selev; rtrans.next = previous; - rtrans.descriptionBitmap = linkDescriptionBitmap; + rtrans.descriptionBitmap = description; previous = rtrans; } rlink.encodeFirsttransfer(rtrans); - rlink.next = firstreverse; - firstreverse = rlink; + } } } - - hollowNodes.remove( getIdFromPos() ); + if ( dc == null ) + { + hollowNodes.remove( this ); + } } public boolean isHollow() @@ -320,34 +344,20 @@ public class OsmNode implements OsmPos } } - 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; - } - } - } - + @Override + public boolean equals( Object o ) + { + if ( o instanceof OsmNode ) + { + OsmNode n = (OsmNode)o; + return n.ilon == ilon && n.ilat == ilat; + } + return false; + } + + @Override + public int hashCode( ) + { + return ilon + ilat; + } } diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNodesMap.java b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNodesMap.java index a1fa035..631aa4d 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNodesMap.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNodesMap.java @@ -11,10 +11,12 @@ import btools.util.ByteArrayUnifier; public final class OsmNodesMap { - private HashMap hmap = new HashMap(); + private HashMap hmap = new HashMap(); private ByteArrayUnifier abUnifier = new ByteArrayUnifier( 16384, false ); + private OsmNode testKey = new OsmNode(); + public ByteArrayUnifier getByteArrayUnifier() { return abUnifier; @@ -26,22 +28,24 @@ public final class OsmNodesMap */ 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 * @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 ); }