From 9e64eb39c433842d4a5c02cb4902d023fe24ca2b Mon Sep 17 00:00:00 2001 From: Arndt Brenschede Date: Wed, 17 Apr 2019 18:00:38 +0200 Subject: [PATCH] refactored waypoint-matching into map-access-layer --- .../main/java/btools/router/OsmNodeNamed.java | 9 ++ .../src/main/java/btools/router/OsmTrack.java | 4 +- .../java/btools/router/RoutingEngine.java | 74 ++---------- .../btools/mapaccess}/MatchedWaypoint.java | 114 +++++++++--------- .../java/btools/mapaccess/NodesCache.java | 70 ++++++++++- .../mapaccess}/WaypointMatcherImpl.java | 6 +- 6 files changed, 148 insertions(+), 129 deletions(-) rename {brouter-core/src/main/java/btools/router => brouter-mapaccess/src/main/java/btools/mapaccess}/MatchedWaypoint.java (78%) rename {brouter-core/src/main/java/btools/router => brouter-mapaccess/src/main/java/btools/mapaccess}/WaypointMatcherImpl.java (97%) diff --git a/brouter-core/src/main/java/btools/router/OsmNodeNamed.java b/brouter-core/src/main/java/btools/router/OsmNodeNamed.java index 56a0a59..f0f89ba 100644 --- a/brouter-core/src/main/java/btools/router/OsmNodeNamed.java +++ b/brouter-core/src/main/java/btools/router/OsmNodeNamed.java @@ -15,6 +15,15 @@ public class OsmNodeNamed extends OsmNode public double nogoWeight; // weight for nogopoint public boolean isNogo = false; + public OsmNodeNamed() + { + } + + public OsmNodeNamed( OsmNode n) + { + super( n.ilon, n.ilat ); + } + @Override public String toString() { diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java index dca0212..631b49b 100644 --- a/brouter-core/src/main/java/btools/router/OsmTrack.java +++ b/brouter-core/src/main/java/btools/router/OsmTrack.java @@ -16,13 +16,13 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; -import java.io.InputStreamReader; import java.io.IOException; +import java.io.InputStreamReader; import java.io.StringWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import btools.mapaccess.MatchedWaypoint; import btools.mapaccess.OsmPos; import btools.util.CompactLongMap; import btools.util.FrozenLongMap; diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index d377711..a9b6445 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -10,18 +10,17 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import btools.mapaccess.MatchedWaypoint; import btools.mapaccess.NodesCache; import btools.mapaccess.OsmLink; import btools.mapaccess.OsmLinkHolder; import btools.mapaccess.OsmNode; import btools.mapaccess.OsmNodePairSet; -import btools.mapaccess.OsmNodesMap; import btools.util.SortedHeap; import btools.util.StackSampler; public class RoutingEngine extends Thread { - private OsmNodesMap nodesMap; private NodesCache nodesCache; private SortedHeap openSet = new SortedHeap(); private boolean finished = false; @@ -326,7 +325,6 @@ public class RoutingEngine extends Thread public void cleanOnOOM() { - nodesMap = null; terminate(); } @@ -385,6 +383,7 @@ public class RoutingEngine extends Thread { MatchedWaypoint mwp = new MatchedWaypoint(); mwp.waypoint = waypoints.get(i); + mwp.name = waypoints.get(i).name; matchedWaypoints.add( mwp ); } matchWaypointsToNodes( matchedWaypoints ); @@ -452,46 +451,9 @@ public class RoutingEngine extends Thread private void matchWaypointsToNodes( List unmatchedWaypoints ) { resetCache( false ); - nodesCache.waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250., islandNodePairs ); - for( MatchedWaypoint mwp : unmatchedWaypoints ) - { - preloadPosition( mwp.waypoint ); - } - - if ( nodesCache.first_file_access_failed ) - { - throw new IllegalArgumentException( "datafile " + nodesCache.first_file_access_name + " not found" ); - } - for( MatchedWaypoint mwp : unmatchedWaypoints ) - { - if ( mwp.crosspoint == null ) - { - throw new IllegalArgumentException( mwp.waypoint.name + "-position not mapped in existing datafile" ); - } - } + nodesCache.matchWaypointsToNodes( unmatchedWaypoints, 250., islandNodePairs ); } - private void preloadPosition( OsmNode n ) - { - int d = 12500; - nodesCache.first_file_access_failed = false; - nodesCache.first_file_access_name = null; - nodesCache.loadSegmentFor( n.ilon, n.ilat ); - if ( nodesCache.first_file_access_failed ) - { - throw new IllegalArgumentException( "datafile " + nodesCache.first_file_access_name + " not found" ); - } - for( int idxLat=-1; idxLat<=1; idxLat++ ) - for( int idxLon=-1; idxLon<=1; idxLon++ ) - { - if ( idxLon != 0 || idxLat != 0 ) - { - nodesCache.loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat ); - } - } - } - - private OsmTrack searchTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack ) { OsmTrack track = null; @@ -613,30 +575,15 @@ public class RoutingEngine extends Thread { logInfo( "NodesCache status before reset=" + nodesCache.formatStatus() ); } - nodesMap = new OsmNodesMap(); - long maxmem = routingContext.memoryclass * 131072L; // 1/8 of total - nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed ); + nodesCache = new NodesCache(segmentDir, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed ); islandNodePairs.clearTempPairs(); } - private OsmNode getStartNode( long startId ) - { - // initialize the start-node - OsmNode start = new OsmNode( startId ); - start.setHollow(); - if ( !nodesCache.obtainNonHollowNode( start ) ) - { - return null; - } - nodesCache.expandHollowLinkTargets( start ); - return start; - } - private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, OsmNodeNamed endPos, boolean sameSegmentSearch ) { - OsmPath p = getStartPath( n1, n2, mwp.waypoint, endPos ); + OsmPath p = getStartPath( n1, n2, new OsmNodeNamed( mwp.waypoint ), endPos ); // special case: start+end on same segment if ( sameSegmentSearch ) @@ -680,7 +627,7 @@ public class RoutingEngine extends Thread - private OsmPath getStartPath( OsmNode n1, OsmNode n2, OsmNodeNamed wp, OsmNode endPos ) + private OsmPath getStartPath( OsmNode n1, OsmNode n2, OsmNodeNamed wp, OsmNodeNamed endPos ) { try { @@ -775,12 +722,12 @@ public class RoutingEngine extends Thread long startNodeId1 = startWp.node1.getIdFromPos(); long startNodeId2 = startWp.node2.getIdFromPos(); - OsmNodeNamed endPos = endWp == null ? null : endWp.crosspoint; + OsmNodeNamed endPos = endWp == null ? null : new OsmNodeNamed( endWp.crosspoint ); boolean sameSegmentSearch = ( startNodeId1 == endNodeId1 && startNodeId2 == endNodeId2 ) || ( startNodeId1 == endNodeId2 && startNodeId2 == endNodeId1 ); - OsmNode start1 = getStartNode( startNodeId1 ); + OsmNode start1 = nodesCache.getStartNode( startNodeId1 ); if ( start1 == null ) return null; OsmNode start2 = null; for( OsmLink link = start1.firstlink; link != null; link = link.getNext( start1 ) ) @@ -793,11 +740,6 @@ public class RoutingEngine extends Thread } if ( start2 == null ) return null; - - - - if ( start1 == null || start2 == null ) return null; - routingContext.startDirectionValid = routingContext.forceUseStartDirection || fastPartialRecalc; routingContext.startDirectionValid &= routingContext.startDirection != null && !routingContext.inverseDirection; if ( routingContext.startDirectionValid ) diff --git a/brouter-core/src/main/java/btools/router/MatchedWaypoint.java b/brouter-mapaccess/src/main/java/btools/mapaccess/MatchedWaypoint.java similarity index 78% rename from brouter-core/src/main/java/btools/router/MatchedWaypoint.java rename to brouter-mapaccess/src/main/java/btools/mapaccess/MatchedWaypoint.java index 14441f5..53960f5 100644 --- a/brouter-core/src/main/java/btools/router/MatchedWaypoint.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/MatchedWaypoint.java @@ -1,56 +1,58 @@ -/** - * Information on matched way point - * - * @author ab - */ -package btools.router; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import btools.mapaccess.OsmNode; - -final class MatchedWaypoint -{ - public OsmNode node1; - public OsmNode node2; - public OsmNodeNamed crosspoint; - public OsmNodeNamed waypoint; - public double radius; // radius in meters - public boolean hasUpdate; - - public void writeToStream( DataOutput dos ) throws IOException - { - dos.writeInt( node1.ilat ); - dos.writeInt( node1.ilon ); - dos.writeInt( node2.ilat ); - dos.writeInt( node2.ilon ); - dos.writeInt( crosspoint.ilat ); - dos.writeInt( crosspoint.ilon ); - dos.writeInt( waypoint.ilat ); - dos.writeInt( waypoint.ilon ); - dos.writeDouble( radius ); - } - - public static MatchedWaypoint readFromStream( DataInput dis ) throws IOException - { - MatchedWaypoint mwp = new MatchedWaypoint(); - mwp.node1 = new OsmNode(); - mwp.node2 = new OsmNode(); - mwp.crosspoint = new OsmNodeNamed(); - mwp.waypoint = new OsmNodeNamed(); - - mwp.node1.ilat = dis.readInt(); - mwp.node1.ilon = dis.readInt(); - mwp.node2.ilat = dis.readInt(); - mwp.node2.ilon = dis.readInt(); - mwp.crosspoint.ilat = dis.readInt(); - mwp.crosspoint.ilon = dis.readInt(); - mwp.waypoint.ilat = dis.readInt(); - mwp.waypoint.ilon = dis.readInt(); - mwp.radius = dis.readDouble(); - return mwp; - } - -} +/** + * Information on matched way point + * + * @author ab + */ +package btools.mapaccess; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +import btools.mapaccess.OsmNode; + +public final class MatchedWaypoint +{ + public OsmNode node1; + public OsmNode node2; + public OsmNode crosspoint; + public OsmNode waypoint; + public String name; // waypoint name used in error messages + public double radius; // distance in meter between waypoint and crosspoint + + public boolean hasUpdate; + + public void writeToStream( DataOutput dos ) throws IOException + { + dos.writeInt( node1.ilat ); + dos.writeInt( node1.ilon ); + dos.writeInt( node2.ilat ); + dos.writeInt( node2.ilon ); + dos.writeInt( crosspoint.ilat ); + dos.writeInt( crosspoint.ilon ); + dos.writeInt( waypoint.ilat ); + dos.writeInt( waypoint.ilon ); + dos.writeDouble( radius ); + } + + public static MatchedWaypoint readFromStream( DataInput dis ) throws IOException + { + MatchedWaypoint mwp = new MatchedWaypoint(); + mwp.node1 = new OsmNode(); + mwp.node2 = new OsmNode(); + mwp.crosspoint = new OsmNode(); + mwp.waypoint = new OsmNode(); + + mwp.node1.ilat = dis.readInt(); + mwp.node1.ilon = dis.readInt(); + mwp.node2.ilat = dis.readInt(); + mwp.node2.ilon = dis.readInt(); + mwp.crosspoint.ilat = dis.readInt(); + mwp.crosspoint.ilon = dis.readInt(); + mwp.waypoint.ilat = dis.readInt(); + mwp.waypoint.ilon = dis.readInt(); + mwp.radius = dis.readDouble(); + return mwp; + } + +} diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java b/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java index ab04c60..0a0a0db 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java @@ -8,6 +8,7 @@ package btools.mapaccess; import java.io.File; import java.io.IOException; import java.util.HashMap; +import java.util.List; import btools.codec.DataBuffers; import btools.codec.MicroCache; @@ -53,10 +54,10 @@ public final class NodesCache return "collecting=" + garbageCollectionEnabled + " noGhosts=" + ghostCleaningDone + " cacheSum=" + cacheSum + " cacheSumClean=" + cacheSumClean + " ghostSum=" + ghostSum + " ghostWakeup=" + ghostWakeup ; } - public NodesCache( String segmentDir, OsmNodesMap nodesMap, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache, boolean detailed ) + public NodesCache( String segmentDir, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache, boolean detailed ) { this.segmentDir = new File( segmentDir ); - this.nodesMap = nodesMap; + this.nodesMap = new OsmNodesMap(); this.expCtxWay = ctxWay; this.lookupVersion = ctxWay.meta.lookupVersion; this.lookupMinorVersion = ctxWay.meta.lookupMinorVersion; @@ -275,6 +276,71 @@ public final class NodesCache } } + /** + * get a node for the given id with all link-targets also non-hollow + * + * It is required that an instance of the start-node does not yet + * exist, not even a hollow instance, so getStartNode should only + * be called once right after resetting the cache + * + * @param id the id of the node to load + * + * @return the fully expanded node for id, or null if it was not found + */ + public OsmNode getStartNode( long id ) + { + // initialize the start-node + OsmNode n = new OsmNode( id ); + n.setHollow(); + if ( !obtainNonHollowNode( n ) ) + { + return null; + } + expandHollowLinkTargets( n ); + return n; + } + + public void matchWaypointsToNodes( List unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs ) + { + waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250., islandNodePairs ); + for( MatchedWaypoint mwp : unmatchedWaypoints ) + { + preloadPosition( mwp.waypoint ); + } + + if ( first_file_access_failed ) + { + throw new IllegalArgumentException( "datafile " + first_file_access_name + " not found" ); + } + for( MatchedWaypoint mwp : unmatchedWaypoints ) + { + if ( mwp.crosspoint == null ) + { + throw new IllegalArgumentException( mwp.name + "-position not mapped in existing datafile" ); + } + } + } + + private void preloadPosition( OsmNode n ) + { + int d = 12500; + first_file_access_failed = false; + first_file_access_name = null; + loadSegmentFor( n.ilon, n.ilat ); + if ( first_file_access_failed ) + { + throw new IllegalArgumentException( "datafile " + first_file_access_name + " not found" ); + } + for( int idxLat=-1; idxLat<=1; idxLat++ ) + for( int idxLon=-1; idxLon<=1; idxLon++ ) + { + if ( idxLon != 0 || idxLat != 0 ) + { + loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat ); + } + } + } + private OsmFile fileForSegment( int lonDegree, int latDegree ) throws Exception { int lonMod5 = lonDegree % 5; diff --git a/brouter-core/src/main/java/btools/router/WaypointMatcherImpl.java b/brouter-mapaccess/src/main/java/btools/mapaccess/WaypointMatcherImpl.java similarity index 97% rename from brouter-core/src/main/java/btools/router/WaypointMatcherImpl.java rename to brouter-mapaccess/src/main/java/btools/mapaccess/WaypointMatcherImpl.java index 57a1247..b67938d 100644 --- a/brouter-core/src/main/java/btools/router/WaypointMatcherImpl.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/WaypointMatcherImpl.java @@ -1,4 +1,4 @@ -package btools.router; +package btools.mapaccess; import java.util.List; @@ -54,7 +54,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher for ( MatchedWaypoint mwp : waypoints ) { - OsmNodeNamed wp = mwp.waypoint; + OsmNode wp = mwp.waypoint; double x1 = ( lon1 - wp.ilon ) * dlon2m; double y1 = ( lat1 - wp.ilat ) * dlat2m; @@ -86,7 +86,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher anyUpdate = true; // calculate crosspoint if ( mwp.crosspoint == null ) - mwp.crosspoint = new OsmNodeNamed(); + mwp.crosspoint = new OsmNode(); if ( s2 < 0. ) { double wayfraction = -s2 / ( d * d );