public StateEditor(State parent, Edge e) { child = parent.clone(); child.backState = parent; child.backEdge = e; // We clear child.next here, since it could have already been set in the // parent child.next = null; if (e == null) { child.backState = null; child.hops = 0; child.vertex = parent.vertex; child.stateData = child.stateData.clone(); } else { child.hops = parent.hops + 1; // be clever // Note that we use equals(), not ==, here to allow for dynamically // created vertices if (e.getFromVertex().equals(e.getToVertex()) && parent.vertex.equals(e.getFromVertex())) { // TODO LG: We disable this test: the assumption that // the from and to vertex of an edge are not the same // is not true anymore: bike rental on/off edges. traversingBackward = parent.getOptions().isArriveBy(); child.vertex = e.getToVertex(); } else if (parent.vertex.equals(e.getFromVertex())) { traversingBackward = false; child.vertex = e.getToVertex(); } else if (parent.vertex.equals(e.getToVertex())) { traversingBackward = true; child.vertex = e.getFromVertex(); } else { // Parent state is not at either end of edge. LOG.warn("Edge is not connected to parent state: {}", e); LOG.warn(" from vertex: {}", e.getFromVertex()); LOG.warn(" to vertex: {}", e.getToVertex()); LOG.warn(" parent vertex: {}", parent.vertex); defectiveTraversal = true; } if (traversingBackward != parent.getOptions().isArriveBy()) { LOG.error( "Actual traversal direction does not match traversal direction in TraverseOptions."); defectiveTraversal = true; } if (parent.stateData.noThruTrafficState == NoThruTrafficState.INIT && !(e instanceof FreeEdge)) { setNoThruTrafficState(NoThruTrafficState.BETWEEN_ISLANDS); } } }
public static int getPreviousArriveTime( RoutingRequest request, int arrivalTime, Vertex stopVertex) { int bestArrivalTime = -1; request.arriveBy = true; // find the alights for (Edge prealight : stopVertex.getIncoming()) { if (prealight instanceof PreAlightEdge) { Vertex arrival = prealight.getFromVertex(); // this is the arrival vertex for (Edge alight : arrival.getIncoming()) { if (alight instanceof TransitBoardAlight) { State state = new State(alight.getToVertex(), arrivalTime, request); State result = alight.traverse(state); if (result == null) continue; int time = (int) result.getTime(); if (time > bestArrivalTime) { bestArrivalTime = time; } } } } } request.arriveBy = false; return bestArrivalTime; }
public static int getNextDepartTime( RoutingRequest request, int departureTime, Vertex stopVertex) { int bestArrivalTime = Integer.MAX_VALUE; request.arriveBy = false; // find the boards for (Edge preboard : stopVertex.getOutgoing()) { if (preboard instanceof PreBoardEdge) { Vertex departure = preboard.getToVertex(); // this is the departure vertex for (Edge board : departure.getOutgoing()) { if (board instanceof TransitBoardAlight) { State state = new State(board.getFromVertex(), departureTime, request); State result = board.traverse(state); if (result == null) continue; int time = (int) result.getTime(); if (time < bestArrivalTime) { bestArrivalTime = time; } } } } } request.arriveBy = true; return bestArrivalTime; }
public void drawAnotation(GraphBuilderAnnotation anno) { Envelope env = new Envelope(); Edge e = anno.getReferencedEdge(); if (e != null) { this.enqueueHighlightedEdge(e); env.expandToInclude(e.getFromVertex().getCoordinate()); env.expandToInclude(e.getToVertex().getCoordinate()); } ArrayList<Vertex> vertices = new ArrayList<Vertex>(); Vertex v = anno.getReferencedVertex(); if (v != null) { env.expandToInclude(v.getCoordinate()); vertices.add(v); } if (e == null && v == null) return; // make it a little bigger, especially needed for STOP_UNLINKED env.expandBy(0.02); // highlight relevant things this.clearHighlights(); this.setHighlightedVertices(vertices); // zoom the graph display this.zoomToEnvelope(env); // and draw this.draw(); }
public static DisjointSet<Vertex> getConnectedComponents(Graph graph) { DisjointSet<Vertex> components = new DisjointSet<Vertex>(); for (Vertex v : graph.getVertices()) { for (Edge e : v.getOutgoing()) { components.union(e.getFromVertex(), e.getToVertex()); } } return components; }
/** * Get vertices connected to an edge * * @return */ @Secured({"ROLE_USER"}) @GET @Path("/verticesForEdge") @Produces({MediaType.APPLICATION_JSON}) public Object getVerticesForEdge(@QueryParam("edge") int edgeId) { Graph graph = graphService.getGraph(); Edge edge = graph.getEdgeById(edgeId); VertexSet out = new VertexSet(); out.vertices = new ArrayList<Vertex>(2); out.vertices.add(edge.getFromVertex()); out.vertices.add(edge.getToVertex()); return out.withGraph(graph); }
private WalkStep createWalkStep(State s) { Edge en = s.getBackEdge(); WalkStep step; step = new WalkStep(); step.streetName = en.getName(); step.lon = en.getFromVertex().getX(); step.lat = en.getFromVertex().getY(); step.elevation = encodeElevationProfile(s.getBackEdge(), 0); step.bogusName = en.hasBogusName(); step.addAlerts(s.getBackAlerts()); step.angle = DirectionUtils.getFirstAngle(s.getBackEdge().getGeometry()); if (s.getBackEdge() instanceof AreaEdge) { step.area = true; } return step; }
public InferredEdge(@Nonnull Edge edge, @Nonnull Integer edgeId, @Nonnull OtpGraph graph) { Preconditions.checkNotNull(edge); Preconditions.checkNotNull(graph); Preconditions.checkNotNull(edgeId); assert !(edge instanceof TurnEdge || edge == null); this.graph = graph; this.edgeId = edgeId; this.edge = edge; /* * Warning: this geometry is in lon/lat and may contain more than one * straight line. */ this.geometry = edge.getGeometry(); this.locationIndexedLine = new LocationIndexedLine(geometry); this.lengthIndexedLine = new LengthIndexedLine(geometry); this.lengthLocationMap = new LengthLocationMap(geometry); this.startVertex = edge.getFromVertex(); this.endVertex = edge.getToVertex(); final Coordinate startPointCoord = this.locationIndexedLine.extractPoint(this.locationIndexedLine.getStartIndex()); this.startPoint = VectorFactory.getDefault().createVector2D(startPointCoord.x, startPointCoord.y); final Coordinate endPointCoord = this.locationIndexedLine.extractPoint(this.locationIndexedLine.getEndIndex()); this.endPoint = VectorFactory.getDefault().createVector2D(endPointCoord.x, endPointCoord.y); this.velocityPrecisionDist = // ~4.4 m/s, std. dev ~ 30 m/s, Gamma with exp. value = 30 m/s // TODO perhaps variance of velocity should be in m/s^2. yeah... new NormalInverseGammaDistribution( 4.4d, 1d / Math.pow(30d, 2d), 1d / Math.pow(30d, 2d) + 1d, Math.pow(30d, 2d)); this.velocityEstimator = new UnivariateGaussianMeanVarianceBayesianEstimator(velocityPrecisionDist); }
/** * Internals of getRegionsForVertex; keeps track of seen vertices to avoid loops. * * @param regionData * @param vertex * @param seen * @param depth * @return */ private static HashSet<Integer> getRegionsForVertex( RegionData regionData, Vertex vertex, HashSet<Vertex> seen, int depth) { seen.add(vertex); HashSet<Integer> regions = new HashSet<Integer>(); int region = vertex.getGroupIndex(); if (region >= 0) { regions.add(region); } else { for (Edge e : vertex.getOutgoing()) { final Vertex tov = e.getToVertex(); if (!seen.contains(tov)) regions.addAll(getRegionsForVertex(regionData, tov, seen, depth + 1)); } for (Edge e : vertex.getIncoming()) { final Vertex fromv = e.getFromVertex(); if (!seen.contains(fromv)) regions.addAll(getRegionsForVertex(regionData, fromv, seen, depth + 1)); } } return regions; }
@Test public final void testOnBoardDepartureTime() { Coordinate[] coordinates = new Coordinate[5]; coordinates[0] = new Coordinate(0.0, 0.0); coordinates[1] = new Coordinate(0.0, 1.0); coordinates[2] = new Coordinate(2.0, 1.0); coordinates[3] = new Coordinate(5.0, 1.0); coordinates[4] = new Coordinate(5.0, 5.0); PatternDepartVertex depart = mock(PatternDepartVertex.class); PatternArriveVertex dwell = mock(PatternArriveVertex.class); PatternArriveVertex arrive = mock(PatternArriveVertex.class); Graph graph = mock(Graph.class); RoutingRequest routingRequest = mock(RoutingRequest.class); ServiceDay serviceDay = mock(ServiceDay.class); when(graph.getTimeZone()).thenReturn(TimeZone.getTimeZone("GMT")); GeometryFactory geometryFactory = GeometryUtils.getGeometryFactory(); CoordinateSequenceFactory coordinateSequenceFactory = geometryFactory.getCoordinateSequenceFactory(); CoordinateSequence coordinateSequence = coordinateSequenceFactory.create(coordinates); LineString geometry = new LineString(coordinateSequence, geometryFactory); ArrayList<Edge> hops = new ArrayList<Edge>(2); RoutingContext routingContext = new RoutingContext(routingRequest, graph, null, arrive); AgencyAndId agencyAndId = new AgencyAndId("Agency", "ID"); Route route = new Route(); ArrayList<StopTime> stopTimes = new ArrayList<StopTime>(3); StopTime stopDepartTime = new StopTime(); StopTime stopDwellTime = new StopTime(); StopTime stopArriveTime = new StopTime(); Stop stopDepart = new Stop(); Stop stopDwell = new Stop(); Stop stopArrive = new Stop(); Trip trip = new Trip(); routingContext.serviceDays = new ArrayList<ServiceDay>(Collections.singletonList(serviceDay)); route.setId(agencyAndId); stopDepart.setId(agencyAndId); stopDwell.setId(agencyAndId); stopArrive.setId(agencyAndId); stopDepartTime.setStop(stopDepart); stopDepartTime.setDepartureTime(0); stopDwellTime.setArrivalTime(20); stopDwellTime.setStop(stopDwell); stopDwellTime.setDepartureTime(40); stopArriveTime.setArrivalTime(60); stopArriveTime.setStop(stopArrive); stopTimes.add(stopDepartTime); stopTimes.add(stopDwellTime); stopTimes.add(stopArriveTime); trip.setId(agencyAndId); trip.setTripHeadsign("The right"); TripTimes tripTimes = new TripTimes(trip, stopTimes, new Deduplicator()); StopPattern stopPattern = new StopPattern(stopTimes); TripPattern tripPattern = new TripPattern(route, stopPattern); when(depart.getTripPattern()).thenReturn(tripPattern); when(dwell.getTripPattern()).thenReturn(tripPattern); PatternHop patternHop0 = new PatternHop(depart, dwell, stopDepart, stopDwell, 0); PatternHop patternHop1 = new PatternHop(dwell, arrive, stopDwell, stopArrive, 1); hops.add(patternHop0); hops.add(patternHop1); when(graph.getEdges()).thenReturn(hops); when(depart.getCoordinate()).thenReturn(new Coordinate(0, 0)); when(dwell.getCoordinate()).thenReturn(new Coordinate(0, 0)); when(arrive.getCoordinate()).thenReturn(new Coordinate(0, 0)); when(routingRequest.getFrom()).thenReturn(new GenericLocation()); when(routingRequest.getStartingTransitTripId()).thenReturn(agencyAndId); when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(9); patternHop0.setGeometry(geometry); tripPattern.add(tripTimes); graph.index = new GraphIndex(graph); coordinates = new Coordinate[3]; coordinates[0] = new Coordinate(3.5, 1.0); coordinates[1] = new Coordinate(5.0, 1.0); coordinates[2] = new Coordinate(5.0, 5.0); coordinateSequence = coordinateSequenceFactory.create(coordinates); geometry = new LineString(coordinateSequence, geometryFactory); Vertex vertex = onBoardDepartServiceImpl.setupDepartOnBoard(routingContext); Edge edge = vertex.getOutgoing().toArray(new Edge[1])[0]; assertEquals(vertex, edge.getFromVertex()); assertEquals(dwell, edge.getToVertex()); assertEquals("The right", edge.getDirection()); assertEquals(geometry, edge.getGeometry()); assertEquals(coordinates[0].x, vertex.getX(), 0.0); assertEquals(coordinates[0].y, vertex.getY(), 0.0); }
/** * Filters all input edges and returns all those as LineString geometries, that have at least one * end point within the time limits. If they have only one end point inside, then the sub-edge is * returned. * * @param maxTime the time limit in seconds that defines the size of the walkshed * @param allConnectingStateEdges all Edges that have been found to connect all states < maxTime * @param spt the ShortestPathTree generated for the pushpin drop point as origin * @param angleLimit the angle tolerance to detect roads with u-shapes, i.e. Pi/2 angles, in * Radiant. * @param distanceTolerance in percent (e.g. 1.1 = 110%) for u-shape detection based on distance * criteria * @param hasCar is travel mode by CAR? * @param performSpeedTest if true applies a test to each edge to check if the edge can be * traversed in time. The test can detect u-shaped roads. * @return */ ArrayList<LineString> getLinesAndSubEdgesWithinMaxTime( long maxTime, ArrayList<Edge> allConnectingStateEdges, ShortestPathTree spt, double angleLimit, double distanceTolerance, double userSpeed, boolean hasCar, boolean performSpeedTest) { LOG.debug("maximal userSpeed set to: " + userSpeed + " m/sec "); if (hasCar) { LOG.debug("travel mode is set to CAR, hence the given speed may be adjusted for each edge"); } ArrayList<LineString> walkShedEdges = new ArrayList<LineString>(); ArrayList<LineString> otherEdges = new ArrayList<LineString>(); ArrayList<LineString> borderEdges = new ArrayList<LineString>(); ArrayList<LineString> uShapes = new ArrayList<LineString>(); int countEdgesOutside = 0; // -- determination of walkshed edges via edge states for (Iterator iterator = allConnectingStateEdges.iterator(); iterator.hasNext(); ) { Edge edge = (Edge) iterator.next(); State sFrom = spt.getState(edge.getFromVertex()); State sTo = spt.getState(edge.getToVertex()); if ((sFrom != null) && (sTo != null)) { long fromTime = sFrom.getElapsedTimeSeconds(); long toTime = sTo.getElapsedTimeSeconds(); long dt = Math.abs(toTime - fromTime); Geometry edgeGeom = edge.getGeometry(); if ((edgeGeom != null) && (edgeGeom instanceof LineString)) { LineString ls = (LineString) edgeGeom; // detect u-shape roads/crescents - they need to be treated separately boolean uShapeOrLonger = testForUshape( edge, maxTime, fromTime, toTime, angleLimit, distanceTolerance, userSpeed, hasCar, performSpeedTest); if (uShapeOrLonger) { uShapes.add(ls); } // evaluate if an edge is completely within the time or only with one end if ((fromTime < maxTime) && (toTime < maxTime)) { // this one is within the time limit on both ends, however we need to do // a second test if we have a u-shaped road. if (uShapeOrLonger) { treatAndAddUshapeWithinTimeLimits( maxTime, userSpeed, walkShedEdges, edge, fromTime, toTime, ls, hasCar); } else { walkShedEdges.add(ls); } } // end if:fromTime & toTime < maxTime else { // check if at least one end is inside, because then we need to // create the sub edge if ((fromTime < maxTime) || (toTime < maxTime)) { double lineDist = edge.getDistance(); LineString inputLS = ls; double fraction = 1.0; if (fromTime < toTime) { double distanceToWalkInTimeMissing = distanceToMoveInRemainingTime( maxTime, fromTime, dt, userSpeed, edge, hasCar, uShapeOrLonger); fraction = (double) distanceToWalkInTimeMissing / (double) lineDist; } else { // toTime < fromTime : invert the edge direction inputLS = (LineString) ls.reverse(); double distanceToWalkInTimeMissing = distanceToMoveInRemainingTime( maxTime, toTime, dt, userSpeed, edge, hasCar, uShapeOrLonger); fraction = (double) distanceToWalkInTimeMissing / (double) lineDist; } // get the subedge LineString subLine = this.getSubLineString(inputLS, fraction); borderEdges.add(subLine); } else { // this edge is completely outside - this should actually not happen // we will not do anything, just count countEdgesOutside++; } } // end else: fromTime & toTime < maxTime } // end if: edge instance of LineString else { // edge is not instance of LineString LOG.debug("edge not instance of LineString"); } } // end if(sFrom && sTo != null) start Else else { // LOG.debug("could not retrieve state for edge-endpoint"); //for a 6min car ride, there can // be (too) many of such messages Geometry edgeGeom = edge.getGeometry(); if ((edgeGeom != null) && (edgeGeom instanceof LineString)) { otherEdges.add((LineString) edgeGeom); } } // end else: sFrom && sTo != null } // end for loop over edges walkShedEdges.addAll(borderEdges); this.debugGeoms.addAll(uShapes); LOG.debug("number of detected u-shapes/crescents: " + uShapes.size()); return walkShedEdges; }
private State getStateArriveBy(RaptorData data, ArrayList<RaptorState> states) { RoutingRequest options = states.get(0).getRequest(); State state = new State(options.rctx.origin, options); for (int i = states.size() - 1; i >= 0; --i) { RaptorState cur = states.get(i); if (cur.walkPath != null) { GraphPath path = new GraphPath(cur.walkPath, false); for (ListIterator<Edge> it = path.edges.listIterator(path.edges.size()); it.hasPrevious(); ) { Edge e = it.previous(); State oldState = state; state = e.traverse(state); if (state == null) { e.traverse(oldState); } } } else { // so, cur is at this point at a transit stop; we have a route to alight from if (cur.getParent() == null || !cur.getParent().interlining) { for (Edge e : state.getVertex().getIncoming()) { if (e instanceof PreAlightEdge) { state = e.traverse(state); } } TransitBoardAlight alight = cur.getRoute().alights[cur.boardStopSequence - 1][cur.patternIndex]; State oldState = state; state = alight.traverse(state); if (state == null) { state = alight.traverse(oldState); } } // now traverse the hops and dwells until we find the board we're looking for HOP: while (true) { for (Edge e : state.getVertex().getIncoming()) { if (e instanceof PatternDwell) { state = e.traverse(state); } else if (e instanceof PatternHop) { state = e.traverse(state); if (cur.interlining) { for (Edge e2 : state.getVertex().getIncoming()) { RaptorState next = states.get(i - 1); if (e2 instanceof PatternInterlineDwell) { Stop fromStop = ((TransitVertex) e2.getFromVertex()).getStop(); Stop expectedStop = next.boardStop.stopVertex.getStop(); if (fromStop.equals(expectedStop)) { State newState = e2.traverse(state); if (newState == null) continue; if (newState.getTripId() != next.tripId) continue; state = newState; break HOP; } } } } else { for (Edge e2 : state.getVertex().getIncoming()) { if (e2 instanceof TransitBoardAlight) { for (Edge e3 : e2.getFromVertex().getIncoming()) { if (e3 instanceof PreBoardEdge) { if (data.raptorStopsForStopId.get( ((TransitStop) e3.getFromVertex()).getStopId()) == cur.stop) { state = e2.traverse(state); state = e3.traverse(state); break HOP; } } } } } } } } } } } return state; }
/** * Get polygons covering the components of the graph. The largest component (in terms of number of * nodes) will not overlap any other components (it will have holes); the others may overlap each * other. * * @param dateTime */ public static List<Geometry> getComponentPolygons( Graph graph, RoutingRequest options, long time) { DisjointSet<Vertex> components = getConnectedComponents(graph); LinkedListMultimap<Integer, Coordinate> componentCoordinates = LinkedListMultimap.create(); options.setDummyRoutingContext(graph); for (Vertex v : graph.getVertices()) { for (Edge e : v.getOutgoing()) { State s0 = new State(v, time, options); State s1 = e.traverse(s0); if (s1 != null) { Integer component = components.find(e.getFromVertex()); Geometry geometry = s1.getBackEdge().getGeometry(); if (geometry != null) { List<Coordinate> coordinates = new ArrayList<Coordinate>(Arrays.asList(geometry.getCoordinates())); for (int i = 0; i < coordinates.size(); ++i) { Coordinate coordinate = new Coordinate(coordinates.get(i)); coordinate.x = Math.round(coordinate.x * PRECISION) / PRECISION; coordinate.y = Math.round(coordinate.y * PRECISION) / PRECISION; coordinates.set(i, coordinate); } componentCoordinates.putAll(component, coordinates); } } } } // generate convex hull of each component List<Geometry> geoms = new ArrayList<Geometry>(); int mainComponentSize = 0; int mainComponentIndex = -1; int component = 0; for (Integer key : componentCoordinates.keySet()) { List<Coordinate> coords = componentCoordinates.get(key); Coordinate[] coordArray = new Coordinate[coords.size()]; ConvexHull hull = new ConvexHull(coords.toArray(coordArray), GeometryUtils.getGeometryFactory()); Geometry geom = hull.getConvexHull(); // buffer components which are mere lines so that they do not disappear. if (geom instanceof LineString) { geom = geom.buffer(0.01); // ~10 meters } else if (geom instanceof Point) { geom = geom.buffer(0.05); // ~50 meters, so that it shows up } geoms.add(geom); if (mainComponentSize < coordArray.length) { mainComponentIndex = component; mainComponentSize = coordArray.length; } ++component; } // subtract small components out of main component // (small components are permitted to overlap each other) Geometry mainComponent = geoms.get(mainComponentIndex); for (int i = 0; i < geoms.size(); ++i) { Geometry geom = geoms.get(i); if (i == mainComponentIndex) { continue; } mainComponent = mainComponent.difference(geom); } geoms.set(mainComponentIndex, mainComponent); return geoms; }
protected boolean carsCanTraverse(Edge edge) { // should be done with a method on edge (canTraverse already exists on turnEdge) State s0 = new State(edge.getFromVertex(), traverseOptions); State s1 = edge.traverse(s0); return s1 != null; }