@Override public void disconnect(CHEdgeExplorer explorer, EdgeIteratorState edgeState) { // search edge with opposite direction but we need to know the previousEdge for the internalEdgeDisconnect so we cannot simply do: // EdgeIteratorState tmpIter = getEdgeProps(iter.getEdge(), iter.getBaseNode()); CHEdgeIterator tmpIter = explorer.setBaseNode(edgeState.getAdjNode()); int tmpPrevEdge = EdgeIterator.NO_EDGE; while (tmpIter.next()) { if (tmpIter.isShortcut() && tmpIter.getEdge() == edgeState.getEdge()) { // TODO this is ugly, move this somehow into the underlying iteration logic long edgePointer = tmpPrevEdge == EdgeIterator.NO_EDGE ? -1 : isShortcut(tmpPrevEdge) ? chEdgeAccess.toPointer(tmpPrevEdge) : baseGraph.edgeAccess.toPointer(tmpPrevEdge); chEdgeAccess.internalEdgeDisconnect(edgeState.getEdge(), edgePointer, edgeState.getAdjNode(), edgeState.getBaseNode()); break; } tmpPrevEdge = tmpIter.getEdge(); } }
final void connectNewEdge(int fromNode, int otherNode, int newOrExistingEdge) { int edge = getEdgeRef(fromNode); if (edge > EdgeIterator.NO_EDGE) { long edgePointer = toPointer(newOrExistingEdge); long lastLink = _getLinkPosInEdgeArea(fromNode, otherNode, edgePointer); edges.setInt(lastLink, edge); } setEdgeRef(fromNode, newOrExistingEdge); }
/** * Write new edge between nodes fromNodeId, and toNodeId both to nodes index and edges index */ final int internalEdgeAdd(int newEdgeId, int fromNodeId, int toNodeId) { writeEdge(newEdgeId, fromNodeId, toNodeId, EdgeIterator.NO_EDGE, EdgeIterator.NO_EDGE); connectNewEdge(fromNodeId, toNodeId, newEdgeId); if (fromNodeId != toNodeId) connectNewEdge(toNodeId, fromNodeId, newEdgeId); return newEdgeId; }
@Override public final CHEdgeIteratorState getEdgeIteratorState(int edgeId, int endNode) { if (isShortcut(edgeId)) { if (!chEdgeAccess.isInBounds(edgeId)) throw new IllegalStateException("shortcutId " + edgeId + " out of bounds"); } else if (!baseGraph.edgeAccess.isInBounds(edgeId)) throw new IllegalStateException("edgeId " + edgeId + " out of bounds"); return (CHEdgeIteratorState) chEdgeAccess.getEdgeProps(edgeId, endNode); }
long edgeToRemovePointer = edgeAccess.toPointer(edgeToRemove); edgeAccess.internalEdgeDisconnect(edgeToRemove, prev, removeNode, nodeId); edgeAccess.invalidateEdge(edgeToRemovePointer); } else { prev = adjNodesToDelIter.edgePointer; long edgePointer = edgeAccess.toPointer(edgeId); int linkA = edgeAccess.getEdgeRef(nodeA, nodeB, edgePointer); int linkB = edgeAccess.getEdgeRef(nodeB, nodeA, edgePointer); long flags = edgeAccess.getFlags_(edgePointer, false); edgeAccess.writeEdge(edgeId, updatedA, updatedB, linkA, linkB); edgeAccess.setFlags_(edgePointer, updatedA > updatedB, flags); if (updatedA < updatedB != nodeA < nodeB) setWayGeometry_(fetchWayGeometry_(edgePointer, true, 0, -1, -1), edgePointer, false);
@Override public final boolean next() { while (true) { if (nextEdgeId == EdgeIterator.NO_EDGE) return false; selectEdgeAccess(); edgePointer = edgeAccess.toPointer(nextEdgeId); edgeId = nextEdgeId; adjNode = edgeAccess.getOtherNode(baseNode, edgePointer); reverse = baseNode > adjNode; freshFlags = false; // position to next edge nextEdgeId = edgeAccess.getEdgeRef(baseNode, adjNode, edgePointer); assert nextEdgeId != edgeId : ("endless loop detected for base node: " + baseNode + ", adj node: " + adjNode + ", edge pointer: " + edgePointer + ", edge: " + edgeId); if (filter.accept(this)) return true; } }
/** * This method disconnects the specified edge from the list of edges of the specified node. It * does not release the freed space to be reused. * <p> * * @param edgeToUpdatePointer if it is negative then the nextEdgeId will be saved to refToEdges * of nodes */ final long internalEdgeDisconnect(int edgeToRemove, long edgeToUpdatePointer, int baseNode, int adjNode) { long edgeToRemovePointer = toPointer(edgeToRemove); // an edge is shared across the two nodes even if the edge is not in both directions // so we need to know two edge-pointers pointing to the edge before edgeToRemovePointer int nextEdgeId = getEdgeRef(baseNode, adjNode, edgeToRemovePointer); if (edgeToUpdatePointer < 0) { setEdgeRef(baseNode, nextEdgeId); } else { // adjNode is different for the edge we want to update with the new link long link = edges.getInt(edgeToUpdatePointer + E_NODEA) == baseNode ? edgeToUpdatePointer + E_LINKA : edgeToUpdatePointer + E_LINKB; edges.setInt(link, nextEdgeId); } return edgeToRemovePointer; }
@Override public EdgeIterator setBaseNode(int baseNode) { // always use base graph edge access setEdgeId(baseGraph.edgeAccess.getEdgeRef(baseNode)); _setBaseNode(baseNode); return this; }
final EdgeIteratorState getEdgeProps(int edgeId, int adjNode) { if (edgeId <= EdgeIterator.NO_EDGE) throw new IllegalStateException("edgeId invalid " + edgeId + ", " + this); BaseGraph.EdgeIterable edge = createSingleEdge(EdgeFilter.ALL_EDGES); if (edge.init(edgeId, adjNode)) return edge; // if edgeId exists but adjacent nodes do not match return null; } }
final long getDirectFlags() { if (!freshFlags) { cachedFlags = edgeAccess.getFlags_(edgePointer, reverse); freshFlags = true; } return cachedFlags; }
@Override public final double getDistance() { return edgeAccess.getDist(edgePointer); }
final void setDist(long edgePointer, double distance) { edges.setInt(edgePointer + E_DIST, distToInt(distance)); }
final int getEdgeRef(int nodeThis, int nodeOther, long edgePointer) { return edges.getInt(_getLinkPosInEdgeArea(nodeThis, nodeOther, edgePointer)); }
@Override public boolean next() { while (true) { edgeId++; edgePointer = (long) edgeId * edgeAccess.getEntryBytes(); if (!checkRange()) return false; baseNode = edgeAccess.edges.getInt(edgePointer + edgeAccess.E_NODEA); // some edges are deleted and have a negative node if (baseNode == EdgeAccess.NO_NODE) continue; freshFlags = false; adjNode = edgeAccess.edges.getInt(edgePointer + edgeAccess.E_NODEB); // this is always false because of 'getBaseNode() <= getAdjNode()' reverse = false; return true; } }
@Test public void internalDisconnect() { GraphHopperStorage storage = createGHStorage(); BaseGraph graph = (BaseGraph) storage.getGraph(Graph.class); EdgeIteratorState iter0 = graph.edge(0, 1, 10, true); EdgeIteratorState iter2 = graph.edge(1, 2, 10, true); EdgeIteratorState iter3 = graph.edge(0, 3, 10, true); EdgeExplorer explorer = graph.createEdgeExplorer(); assertEquals(GHUtility.asSet(3, 1), GHUtility.getNeighbors(explorer.setBaseNode(0))); assertEquals(GHUtility.asSet(2, 0), GHUtility.getNeighbors(explorer.setBaseNode(1))); // remove edge "1-2" but only from 1 not from 2 graph.edgeAccess.internalEdgeDisconnect(iter2.getEdge(), -1, iter2.getBaseNode(), iter2.getAdjNode()); assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(1))); assertEquals(GHUtility.asSet(1), GHUtility.getNeighbors(explorer.setBaseNode(2))); // let 0 unchanged -> no side effects assertEquals(GHUtility.asSet(3, 1), GHUtility.getNeighbors(explorer.setBaseNode(0))); // remove edge "0-1" but only from 0 graph.edgeAccess.internalEdgeDisconnect(iter0.getEdge(), (long) iter3.getEdge() * graph.edgeEntryBytes, iter0.getBaseNode(), iter0.getAdjNode()); assertEquals(GHUtility.asSet(3), GHUtility.getNeighbors(explorer.setBaseNode(0))); assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(3))); assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(1))); storage.close(); }
long edgeToRemovePointer = edgeAccess.toPointer(edgeToRemove); edgeAccess.internalEdgeDisconnect(edgeToRemove, prev, removeNode, nodeId); edgeAccess.invalidateEdge(edgeToRemovePointer); } else { prev = adjNodesToDelIter.edgePointer; long edgePointer = edgeAccess.toPointer(edgeId); int linkA = edgeAccess.getEdgeRef(nodeA, nodeB, edgePointer); int linkB = edgeAccess.getEdgeRef(nodeB, nodeA, edgePointer); long flags = edgeAccess.getFlags_(edgePointer, false); edgeAccess.writeEdge(edgeId, updatedA, updatedB, linkA, linkB); edgeAccess.setFlags_(edgePointer, updatedA > updatedB, flags); if (updatedA < updatedB != nodeA < nodeB) setWayGeometry_(fetchWayGeometry_(edgePointer, true, 0, -1, -1), edgePointer, false);
@Override public final boolean next() { while (true) { if (nextEdgeId == EdgeIterator.NO_EDGE) return false; selectEdgeAccess(); edgePointer = edgeAccess.toPointer(nextEdgeId); edgeId = nextEdgeId; adjNode = edgeAccess.getOtherNode(baseNode, edgePointer); reverse = baseNode > adjNode; freshFlags = false; // position to next edge nextEdgeId = edgeAccess.getEdgeRef(baseNode, adjNode, edgePointer); assert nextEdgeId != edgeId : ("endless loop detected for base node: " + baseNode + ", adj node: " + adjNode + ", edge pointer: " + edgePointer + ", edge: " + edgeId); if (filter.accept(this)) return true; } }
/** * This method disconnects the specified edge from the list of edges of the specified node. It * does not release the freed space to be reused. * <p> * @param edgeToUpdatePointer if it is negative then the nextEdgeId will be saved to refToEdges * of nodes */ final long internalEdgeDisconnect( int edgeToRemove, long edgeToUpdatePointer, int baseNode, int adjNode ) { long edgeToRemovePointer = toPointer(edgeToRemove); // an edge is shared across the two nodes even if the edge is not in both directions // so we need to know two edge-pointers pointing to the edge before edgeToRemovePointer int nextEdgeId = getEdgeRef(baseNode, adjNode, edgeToRemovePointer); if (edgeToUpdatePointer < 0) { setEdgeRef(baseNode, nextEdgeId); } else { // adjNode is different for the edge we want to update with the new link long link = edges.getInt(edgeToUpdatePointer + E_NODEA) == baseNode ? edgeToUpdatePointer + E_LINKA : edgeToUpdatePointer + E_LINKB; edges.setInt(link, nextEdgeId); } return edgeToRemovePointer; }
@Override public EdgeIteratorState getEdgeIteratorState(int edgeId, int adjNode) { if (!edgeAccess.isInBounds(edgeId)) throw new IllegalStateException("edgeId " + edgeId + " out of bounds"); checkAdjNodeBounds(adjNode); return edgeAccess.getEdgeProps(edgeId, adjNode); }
@Override public final CHEdgeIterator setBaseNode(int baseNode) { assert baseGraph.isFrozen() : "Traversal CHGraph is only possible if BaseGraph is frozen"; // always use ch edge access setEdgeId(chEdgeAccess.getEdgeRef(baseNode)); _setBaseNode(baseNode); return this; }