/** Build the weight table, parallelized according to the number of processors */ public void buildTable() { ArrayList<TransitStop> stopVertices; LOG.debug("Number of vertices: " + g.getVertices().size()); stopVertices = new ArrayList<TransitStop>(); for (Vertex gv : g.getVertices()) if (gv instanceof TransitStop) stopVertices.add((TransitStop) gv); int nStops = stopVertices.size(); stopIndices = new IdentityHashMap<Vertex, Integer>(nStops); for (int i = 0; i < nStops; i++) stopIndices.put(stopVertices.get(i), i); LOG.debug("Number of stops: " + nStops); table = new float[nStops][nStops]; for (float[] row : table) Arrays.fill(row, Float.POSITIVE_INFINITY); LOG.debug("Performing search at each transit stop."); int nThreads = Runtime.getRuntime().availableProcessors(); LOG.debug("number of threads: " + nThreads); ArrayBlockingQueue<Runnable> taskQueue = new ArrayBlockingQueue<Runnable>(nStops); ThreadPoolExecutor threadPool = new ThreadPoolExecutor(nThreads, nThreads, 10, TimeUnit.SECONDS, taskQueue); GenericObjectPool heapPool = new GenericObjectPool(new PoolableBinHeapFactory<State>(g.getVertices().size()), nThreads); // make one heap and recycle it TraverseOptions options = new TraverseOptions(); options.speed = maxWalkSpeed; final double MAX_WEIGHT = 60 * 60 * options.walkReluctance; final double OPTIMISTIC_BOARD_COST = options.boardCost; // create a task for each transit stop in the graph ArrayList<Callable<Void>> tasks = new ArrayList<Callable<Void>>(); for (TransitStop origin : stopVertices) { SPTComputer task = new SPTComputer(heapPool, options, MAX_WEIGHT, OPTIMISTIC_BOARD_COST, origin); tasks.add(task); } try { // invoke all of tasks. threadPool.invokeAll(tasks); threadPool.shutdown(); } catch (InterruptedException e) { throw new RuntimeException(e); } floyd(); }
/** * The safest bike lane should have a safety weight no lower than the time weight of a flat * street. This method divides the safety lengths by the length ratio of the safest street, * ensuring this property. * * @param graph */ private void applyBikeSafetyFactor(Graph graph) { _log.info( GraphBuilderAnnotation.register( graph, Variety.GRAPHWIDE, "Multiplying all bike safety values by " + (1 / bestBikeSafety))); HashSet<Edge> seenEdges = new HashSet<Edge>(); for (Vertex vertex : graph.getVertices()) { for (Edge e : vertex.getOutgoing()) { if (!(e instanceof PlainStreetEdge)) { continue; } PlainStreetEdge pse = (PlainStreetEdge) e; if (!seenEdges.contains(e)) { seenEdges.add(e); pse.setBicycleSafetyEffectiveLength( pse.getBicycleSafetyEffectiveLength() / bestBikeSafety); } } for (Edge e : vertex.getIncoming()) { if (!(e instanceof PlainStreetEdge)) { continue; } PlainStreetEdge pse = (PlainStreetEdge) e; if (!seenEdges.contains(e)) { seenEdges.add(e); pse.setBicycleSafetyEffectiveLength( pse.getBicycleSafetyEffectiveLength() / bestBikeSafety); } } } }
public synchronized void initIndexes() { if (vertexIndex != null) { return; } graphService.setLoadLevel(LoadLevel.DEBUG); Graph graph = graphService.getGraph(); vertexIndex = new STRtree(); edgeIndex = new STRtree(); for (Vertex v : graph.getVertices()) { Envelope vertexEnvelope = new Envelope(v.getCoordinate()); vertexIndex.insert(vertexEnvelope, v); for (Edge e : v.getOutgoing()) { Envelope envelope; Geometry geometry = e.getGeometry(); if (geometry == null) { envelope = vertexEnvelope; } else { envelope = geometry.getEnvelopeInternal(); } edgeIndex.insert(envelope, e); } } vertexIndex.build(); edgeIndex.build(); }
@BeforeClass public static void setUp() throws Exception { context = GtfsLibrary.readGtfs(new File(ConstantsForTests.FAKE_GTFS)); graph = new Graph(); GTFSPatternHopFactory factory = new GTFSPatternHopFactory(context); factory.run(graph); graph.putService( CalendarServiceData.class, GtfsLibrary.createCalendarServiceData(context.getDao())); patternIndex = new HashMap<AgencyAndId, TripPattern>(); for (TransitStopDepart tsd : filter(graph.getVertices(), TransitStopDepart.class)) { for (TransitBoardAlight tba : filter(tsd.getOutgoing(), TransitBoardAlight.class)) { if (!tba.isBoarding()) continue; TripPattern pattern = tba.getPattern(); for (Trip trip : pattern.getTrips()) { patternIndex.put(trip.getId(), pattern); } } } pattern = patternIndex.get(new AgencyAndId("agency", "1.1")); timetable = pattern.scheduledTimetable; }
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; }
/* * Iterate through all vertices and their (outgoing) edges. If they are of 'interesting' types, add them to the corresponding spatial index. */ public synchronized void buildSpatialIndex() { vertexIndex = new STRtree(); edgeIndex = new STRtree(); Envelope env; // int xminx, xmax, ymin, ymax; for (Vertex v : graph.getVertices()) { Coordinate c = v.getCoordinate(); env = new Envelope(c); vertexIndex.insert(env, v); for (Edge e : v.getOutgoing()) { if (e.getGeometry() == null) continue; if (e instanceof PatternEdge || e instanceof StreetTransitLink || e instanceof StreetEdge) { env = e.getGeometry().getEnvelopeInternal(); edgeIndex.insert(env, e); } } } vertexIndex.build(); edgeIndex.build(); }
/** * 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; }
@Override public void buildGraph(Graph graph, HashMap<Class<?>, Object> extra) { final Parser parser[] = new Parser[] {new Parser()}; GeometryFactory geometryFactory = GeometryUtils.getGeometryFactory(); EarliestArrivalSPTService earliestArrivalSPTService = new EarliestArrivalSPTService(); earliestArrivalSPTService.maxDuration = (maxDuration); for (TransitStop ts : Iterables.filter(graph.getVertices(), TransitStop.class)) { // Only link street linkable stops if (!ts.isStreetLinkable()) continue; LOG.trace("linking stop '{}' {}", ts.getStop(), ts); // Determine the set of pathway/transfer destinations Set<TransitStop> pathwayDestinations = new HashSet<TransitStop>(); for (Edge e : ts.getOutgoing()) { if (e instanceof PathwayEdge || e instanceof SimpleTransfer) { if (e.getToVertex() instanceof TransitStop) { TransitStop to = (TransitStop) e.getToVertex(); pathwayDestinations.add(to); } } } int n = 0; RoutingRequest routingRequest = new RoutingRequest(TraverseMode.WALK); routingRequest.clampInitialWait = (0L); routingRequest.setRoutingContext(graph, ts, null); routingRequest.rctx.pathParsers = parser; ShortestPathTree spt = earliestArrivalSPTService.getShortestPathTree(routingRequest); if (spt != null) { for (State state : spt.getAllStates()) { Vertex vertex = state.getVertex(); if (ts == vertex) continue; if (vertex instanceof TransitStop) { TransitStop other = (TransitStop) vertex; if (!other.isStreetLinkable()) continue; if (pathwayDestinations.contains(other)) { LOG.trace("Skipping '{}', {}, already connected.", other.getStop(), other); continue; } double distance = 0.0; GraphPath graphPath = new GraphPath(state, false); CoordinateArrayListSequence coordinates = new CoordinateArrayListSequence(); for (Edge edge : graphPath.edges) { if (edge instanceof StreetEdge) { LineString geometry = edge.getGeometry(); if (geometry != null) { if (coordinates.size() == 0) { coordinates.extend(geometry.getCoordinates()); } else { coordinates.extend(geometry.getCoordinates(), 1); } } distance += edge.getDistance(); } } if (coordinates.size() < 2) { // Otherwise the walk step generator breaks. ArrayList<Coordinate> coordinateList = new ArrayList<Coordinate>(2); coordinateList.add(graphPath.states.get(1).getVertex().getCoordinate()); State lastState = graphPath.states.getLast().getBackState(); coordinateList.add(lastState.getVertex().getCoordinate()); coordinates = new CoordinateArrayListSequence(coordinateList); } LineString geometry = geometryFactory.createLineString( new PackedCoordinateSequence.Double(coordinates.toCoordinateArray())); LOG.trace(" to stop: '{}' {} ({}m) [{}]", other.getStop(), other, distance, geometry); new SimpleTransfer(ts, other, distance, geometry); n++; } } } LOG.trace("linked to {} others.", n); if (n == 0) { LOG.warn(graph.addBuilderAnnotation(new StopNotLinkedForTransfers(ts))); } } }