/** * Container for link between two Osm nodes * * @author ab */ package btools.mapaccess; import java.util.ArrayList; import java.util.HashMap; import btools.util.ByteArrayUnifier; import btools.util.SortedHeap; public final class OsmNodesMap { private HashMap hmap = new HashMap(4096); private ByteArrayUnifier abUnifier = new ByteArrayUnifier( 16384, false ); private OsmNode testKey = new OsmNode(); public int nodesCreated; public long maxmem; private long currentmaxmem = 4000000; // start with 4 MB public int lastVisitID = 1000; public int baseID = 1000; public OsmNode destination; public int currentPathCost; public int currentMaxCost = 1000000000; public OsmNode endNode1; public OsmNode endNode2; public int cleanupMode = 0; public void cleanupAndCount( OsmNode[] nodes ) { if ( cleanupMode == 0 ) { justCount( nodes ); } else { cleanupPeninsulas( nodes ); } } private void justCount( OsmNode[] nodes ) { for( int i=0; i n.visitID ) // peninsula ? { nodesCreated = nodesCreatedUntilHere; n.unlinkLink( l ); t.unlinkLink( l ); } } else if ( minIdSub < baseID ) { continue; } else if ( cleanupMode == 2 ) { minIdSub = baseID; // in tree-mode, hitting anything is like a gateway } if ( minIdSub < minId ) minId = minIdSub; } return minId; } public boolean isInMemoryBounds( int npaths, boolean extend ) { // long total = nodesCreated * 76L + linksCreated * 48L; long total = nodesCreated * 95L + npaths * 200L; if ( extend ) { total += 100000; // when extending, try to have 1 MB space long delta = total + 1900000 - currentmaxmem; if ( delta > 0 ) { currentmaxmem += delta; if ( currentmaxmem > maxmem ) { currentmaxmem = maxmem; } } } return total <= currentmaxmem; } private void addActiveNode( ArrayList nodes2check, OsmNode n ) { n.visitID = lastVisitID; nodesCreated++; nodes2check.add( n ); } // is there an escape from this node // to a hollow node (or destination node) ? public boolean canEscape( OsmNode n0 ) { boolean sawLowIDs = false; lastVisitID++; nodes2check.clear(); nodes2check.add( n0 ); while ( !nodes2check.isEmpty() ) { OsmNode n = nodes2check.remove( nodes2check.size()-1 ); if ( n.visitID < baseID ) { n.visitID = lastVisitID; nodesCreated++; for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) ) { OsmNode t = l.getTarget( n ); nodes2check.add( t ); } } else if ( n.visitID < lastVisitID ) { sawLowIDs = true; } } if ( sawLowIDs ) { return true; } nodes2check.add( n0 ); while ( !nodes2check.isEmpty() ) { OsmNode n = nodes2check.remove( nodes2check.size()-1 ); if ( n.visitID == lastVisitID ) { n.visitID = lastVisitID; nodesCreated--; for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) ) { OsmNode t = l.getTarget( n ); nodes2check.add( t ); } n.vanish(); } } return false; } private ArrayList nodes2check; public void clearTemp() { nodes2check = null; } public void collectOutreachers() { nodes2check = new ArrayList(nodesCreated); nodesCreated=0; for( OsmNode n : hmap.values() ) { addActiveNode( nodes2check, n ); } lastVisitID++; baseID = lastVisitID; while ( !nodes2check.isEmpty() ) { OsmNode n = nodes2check.remove( nodes2check.size()-1 ); n.visitID = lastVisitID; for( OsmLink l = n.firstlink; l != null; l = l.getNext( n ) ) { OsmNode t = l.getTarget( n ); if ( t.visitID != lastVisitID ) { addActiveNode( nodes2check, t ); } } if ( destination != null && currentMaxCost < 1000000000 ) { int distance = n.calcDistance( destination ); if ( distance > currentMaxCost - currentPathCost + 100 ) { n.vanish(); } } if ( n.firstlink == null ) { nodesCreated--; } } } public ByteArrayUnifier getByteArrayUnifier() { return abUnifier; } /** * Get a node from the map * @return the node for the given id if exist, else null */ public OsmNode get( int ilon, int ilat ) { testKey.ilon = ilon; testKey.ilat = ilat; return hmap.get( testKey ); } public void remove( OsmNode node ) { if ( node != endNode1 && node != endNode2 ) // keep endnodes in hollow-map even when loaded { // (needed for escape analysis) hmap.remove( node ); } } /** * Put a node into the map * @return the previous node if that id existed, else null */ public OsmNode put( OsmNode node ) { return hmap.put( node, node ); } // ********************** test cleanup ********************** private static void addLinks( OsmNode[] nodes, int idx, boolean isBorder, int[] links ) { OsmNode n = nodes[idx]; n.visitID = isBorder ? 1 : 0; n.selev = (short)idx; for( int i : links ) { OsmNode t = nodes[i]; OsmLink link = n.isLinkUnused() ? n : ( t.isLinkUnused() ? t : null ); if ( link == null ) { link = new OsmLink(); } n.addLink( link, false, t ); } } public static void main( String[] args ) { OsmNode[] nodes = new OsmNode[12]; for( int i=0; i