Search in sources :

Example 6 with LinearLocation

use of com.vividsolutions.jts.linearref.LinearLocation in project OpenTripPlanner by opentripplanner.

the class TestHalfEdges method testHalfEdges.

@Test
public void testHalfEdges() {
    // the shortest half-edge from the start vertex takes you down, but the shortest total path
    // is up and over
    int nVertices = graph.getVertices().size();
    int nEdges = graph.getEdges().size();
    RoutingRequest options = new RoutingRequest();
    HashSet<Edge> turns = new HashSet<Edge>();
    turns.add(left);
    turns.add(leftBack);
    TemporaryStreetLocation start = StreetVertexIndexServiceImpl.createTemporaryStreetLocation(graph, "start", new NonLocalizedString("start"), filter(turns, StreetEdge.class), new LinearLocation(0, 0.4).getCoordinate(left.getGeometry()), false);
    HashSet<Edge> endTurns = new HashSet<Edge>();
    endTurns.add(right);
    endTurns.add(rightBack);
    TemporaryStreetLocation end = StreetVertexIndexServiceImpl.createTemporaryStreetLocation(graph, "end", new NonLocalizedString("end"), filter(endTurns, StreetEdge.class), new LinearLocation(0, 0.8).getCoordinate(right.getGeometry()), true);
    assertTrue(start.getX() < end.getX());
    assertTrue(start.getY() < end.getY());
    Collection<Edge> edges = end.getIncoming();
    assertEquals(2, edges.size());
    long startTime = TestUtils.dateInSeconds("America/New_York", 2009, 11, 1, 12, 34, 25);
    options.dateTime = startTime;
    options.setRoutingContext(graph, br, end);
    options.setMaxWalkDistance(Double.MAX_VALUE);
    ShortestPathTree spt1 = aStar.getShortestPathTree(options);
    GraphPath pathBr = spt1.getPath(end, false);
    assertNotNull("There must be a path from br to end", pathBr);
    options.setRoutingContext(graph, tr, end);
    ShortestPathTree spt2 = aStar.getShortestPathTree(options);
    GraphPath pathTr = spt2.getPath(end, false);
    assertNotNull("There must be a path from tr to end", pathTr);
    assertTrue("path from bottom to end must be longer than path from top to end", pathBr.getWeight() > pathTr.getWeight());
    options.setRoutingContext(graph, start, end);
    ShortestPathTree spt = aStar.getShortestPathTree(options);
    GraphPath path = spt.getPath(end, false);
    assertNotNull("There must be a path from start to end", path);
    // the bottom is not part of the shortest path
    for (State s : path.states) {
        assertNotSame(s.getVertex(), graph.getVertex("bottom"));
        assertNotSame(s.getVertex(), graph.getVertex("bottomBack"));
    }
    options.setArriveBy(true);
    options.setRoutingContext(graph, start, end);
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(start, false);
    assertNotNull("There must be a path from start to end (looking back)", path);
    // the bottom edge is not part of the shortest path
    for (State s : path.states) {
        assertNotSame(s.getVertex(), graph.getVertex("bottom"));
        assertNotSame(s.getVertex(), graph.getVertex("bottomBack"));
    }
    // Number of vertices and edges should be the same as before after a cleanup.
    options.cleanup();
    assertEquals(nVertices, graph.getVertices().size());
    assertEquals(nEdges, graph.getEdges().size());
    /*
         * Now, the right edge is not bikeable. But the user can walk their bike. So here are some tests that prove (a) that walking bikes works, but
         * that (b) it is not preferred to riding a tiny bit longer.
         */
    options = new RoutingRequest(new TraverseModeSet(TraverseMode.BICYCLE));
    start = StreetVertexIndexServiceImpl.createTemporaryStreetLocation(graph, "start1", new NonLocalizedString("start1"), filter(turns, StreetEdge.class), new LinearLocation(0, 0.95).getCoordinate(top.getGeometry()), false);
    end = StreetVertexIndexServiceImpl.createTemporaryStreetLocation(graph, "end1", new NonLocalizedString("end1"), filter(turns, StreetEdge.class), new LinearLocation(0, 0.95).getCoordinate(bottom.getGeometry()), true);
    options.setRoutingContext(graph, start, end);
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(start, false);
    assertNotNull("There must be a path from top to bottom along the right", path);
    // the left edge is not part of the shortest path (even though the bike must be walked along the right)
    for (State s : path.states) {
        assertNotSame(s.getVertex(), graph.getVertex("left"));
        assertNotSame(s.getVertex(), graph.getVertex("leftBack"));
    }
    // Number of vertices and edges should be the same as before after a cleanup.
    options.cleanup();
    assertEquals(nVertices, graph.getVertices().size());
    assertEquals(nEdges, graph.getEdges().size());
    start = StreetVertexIndexServiceImpl.createTemporaryStreetLocation(graph, "start2", new NonLocalizedString("start2"), filter(turns, StreetEdge.class), new LinearLocation(0, 0.55).getCoordinate(top.getGeometry()), false);
    end = StreetVertexIndexServiceImpl.createTemporaryStreetLocation(graph, "end2", new NonLocalizedString("end2"), filter(turns, StreetEdge.class), new LinearLocation(0, 0.55).getCoordinate(bottom.getGeometry()), true);
    options.setRoutingContext(graph, start, end);
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(start, false);
    assertNotNull("There must be a path from top to bottom", path);
    // the right edge is not part of the shortest path, e
    for (State s : path.states) {
        assertNotSame(s.getVertex(), graph.getVertex("right"));
        assertNotSame(s.getVertex(), graph.getVertex("rightBack"));
    }
    // Number of vertices and edges should be the same as before after a cleanup.
    options.cleanup();
    assertEquals(nVertices, graph.getVertices().size());
    assertEquals(nEdges, graph.getEdges().size());
}
Also used : LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) GraphPath(org.opentripplanner.routing.spt.GraphPath) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) TemporaryStreetLocation(org.opentripplanner.routing.location.TemporaryStreetLocation) ShortestPathTree(org.opentripplanner.routing.spt.ShortestPathTree) State(org.opentripplanner.routing.core.State) NonLocalizedString(org.opentripplanner.util.NonLocalizedString) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) TemporaryFreeEdge(org.opentripplanner.routing.edgetype.TemporaryFreeEdge) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) Edge(org.opentripplanner.routing.graph.Edge) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 7 with LinearLocation

use of com.vividsolutions.jts.linearref.LinearLocation in project OpenTripPlanner by opentripplanner.

the class GeometryUtils method splitGeometryAtFraction.

/**
 * Splits the input geometry into two LineStrings at a fraction of the distance covered.
 */
public static P2<LineString> splitGeometryAtFraction(Geometry geometry, double fraction) {
    LineString empty = new LineString(null, gf);
    Coordinate[] coordinates = geometry.getCoordinates();
    CoordinateSequence sequence = gf.getCoordinateSequenceFactory().create(coordinates);
    LineString total = new LineString(sequence, gf);
    if (coordinates.length < 2)
        return new P2<LineString>(empty, empty);
    if (fraction <= 0)
        return new P2<LineString>(empty, total);
    if (fraction >= 1)
        return new P2<LineString>(total, empty);
    double totalDistance = total.getLength();
    double requestedDistance = totalDistance * fraction;
    // An index in JTS can actually refer to any point along the line. It is NOT an array index.
    LocationIndexedLine line = new LocationIndexedLine(geometry);
    LinearLocation l = LengthLocationMap.getLocation(geometry, requestedDistance);
    LineString beginning = (LineString) line.extractLine(line.getStartIndex(), l);
    LineString ending = (LineString) line.extractLine(l, line.getEndIndex());
    return new P2<LineString>(beginning, ending);
}
Also used : P2(org.opentripplanner.common.model.P2) LocationIndexedLine(com.vividsolutions.jts.linearref.LocationIndexedLine) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation)

Example 8 with LinearLocation

use of com.vividsolutions.jts.linearref.LinearLocation in project OpenTripPlanner by opentripplanner.

the class GTFSPatternHopFactory method createGeometry.

/**
 * Creates a set of geometries for a single trip, considering the GTFS shapes.txt,
 * The geometry is broken down into one geometry per inter-stop segment ("hop"). We also need a shape for the entire
 * trip and tripPattern, but given the complexity of the existing code for generating hop geometries, we will create
 * the full-trip geometry by simply concatenating the hop geometries.
 *
 * This geometry will in fact be used for an entire set of trips in a trip pattern. Technically one of the trips
 * with exactly the same sequence of stops could follow a different route on the streets, but that's very uncommon.
 */
private LineString[] createGeometry(Graph graph, Trip trip, List<StopTime> stopTimes) {
    AgencyAndId shapeId = trip.getShapeId();
    // One less geometry than stoptime as array indexes represetn hops not stops (fencepost problem).
    LineString[] geoms = new LineString[stopTimes.size() - 1];
    // Detect presence or absence of shape_dist_traveled on a per-trip basis
    StopTime st0 = stopTimes.get(0);
    boolean hasShapeDist = st0.isShapeDistTraveledSet();
    if (hasShapeDist) {
        // this trip has shape_dist in stop_times
        for (int i = 0; i < stopTimes.size() - 1; ++i) {
            st0 = stopTimes.get(i);
            StopTime st1 = stopTimes.get(i + 1);
            geoms[i] = getHopGeometryViaShapeDistTraveled(graph, shapeId, st0, st1);
        }
        return geoms;
    }
    LineString shape = getLineStringForShapeId(shapeId);
    if (shape == null) {
        // create straight line segments between stops for each hop
        for (int i = 0; i < stopTimes.size() - 1; ++i) {
            st0 = stopTimes.get(i);
            StopTime st1 = stopTimes.get(i + 1);
            LineString geometry = createSimpleGeometry(st0.getStop(), st1.getStop());
            geoms[i] = geometry;
        }
        return geoms;
    }
    // This trip does not have shape_dist in stop_times, but does have an associated shape.
    ArrayList<IndexedLineSegment> segments = new ArrayList<IndexedLineSegment>();
    for (int i = 0; i < shape.getNumPoints() - 1; ++i) {
        segments.add(new IndexedLineSegment(i, shape.getCoordinateN(i), shape.getCoordinateN(i + 1)));
    }
    // Find possible segment matches for each stop.
    List<List<IndexedLineSegment>> possibleSegmentsForStop = new ArrayList<List<IndexedLineSegment>>();
    int minSegmentIndex = 0;
    for (int i = 0; i < stopTimes.size(); ++i) {
        Stop stop = stopTimes.get(i).getStop();
        Coordinate coord = new Coordinate(stop.getLon(), stop.getLat());
        List<IndexedLineSegment> stopSegments = new ArrayList<IndexedLineSegment>();
        double bestDistance = Double.MAX_VALUE;
        IndexedLineSegment bestSegment = null;
        int maxSegmentIndex = -1;
        int index = -1;
        int minSegmentIndexForThisStop = -1;
        for (IndexedLineSegment segment : segments) {
            index++;
            if (segment.index < minSegmentIndex) {
                continue;
            }
            double distance = segment.distance(coord);
            if (distance < maxStopToShapeSnapDistance) {
                stopSegments.add(segment);
                maxSegmentIndex = index;
                if (minSegmentIndexForThisStop == -1)
                    minSegmentIndexForThisStop = index;
            } else if (distance < bestDistance) {
                bestDistance = distance;
                bestSegment = segment;
                if (maxSegmentIndex != -1) {
                    maxSegmentIndex = index;
                }
            }
        }
        if (stopSegments.size() == 0) {
            // no segments within 150m
            // fall back to nearest segment
            stopSegments.add(bestSegment);
            minSegmentIndex = bestSegment.index;
        } else {
            minSegmentIndex = minSegmentIndexForThisStop;
            Collections.sort(stopSegments, new IndexedLineSegmentComparator(coord));
        }
        for (int j = i - 1; j >= 0; j--) {
            for (Iterator<IndexedLineSegment> it = possibleSegmentsForStop.get(j).iterator(); it.hasNext(); ) {
                IndexedLineSegment segment = it.next();
                if (segment.index > maxSegmentIndex) {
                    it.remove();
                }
            }
        }
        possibleSegmentsForStop.add(stopSegments);
    }
    List<LinearLocation> locations = getStopLocations(possibleSegmentsForStop, stopTimes, 0, -1);
    if (locations == null) {
        for (int i = 0; i < stopTimes.size() - 1; ++i) {
            st0 = stopTimes.get(i);
            StopTime st1 = stopTimes.get(i + 1);
            LineString geometry = createSimpleGeometry(st0.getStop(), st1.getStop());
            geoms[i] = geometry;
            // this warning is not strictly correct, but will do
            LOG.warn(graph.addBuilderAnnotation(new BogusShapeGeometryCaught(shapeId, st0, st1)));
        }
        return geoms;
    }
    Iterator<LinearLocation> locationIt = locations.iterator();
    LinearLocation endLocation = locationIt.next();
    double distanceSoFar = 0;
    int last = 0;
    for (int i = 0; i < stopTimes.size() - 1; ++i) {
        LinearLocation startLocation = endLocation;
        endLocation = locationIt.next();
        // it does not matter at all if this is accurate so long as it is consistent
        for (int j = last; j < startLocation.getSegmentIndex(); ++j) {
            Coordinate from = shape.getCoordinateN(j);
            Coordinate to = shape.getCoordinateN(j + 1);
            double xd = from.x - to.x;
            double yd = from.y - to.y;
            distanceSoFar += FastMath.sqrt(xd * xd + yd * yd);
        }
        last = startLocation.getSegmentIndex();
        double startIndex = distanceSoFar + startLocation.getSegmentFraction() * startLocation.getSegmentLength(shape);
        // advance distanceSoFar up to start of segment containing endLocation
        for (int j = last; j < endLocation.getSegmentIndex(); ++j) {
            Coordinate from = shape.getCoordinateN(j);
            Coordinate to = shape.getCoordinateN(j + 1);
            double xd = from.x - to.x;
            double yd = from.y - to.y;
            distanceSoFar += FastMath.sqrt(xd * xd + yd * yd);
        }
        last = startLocation.getSegmentIndex();
        double endIndex = distanceSoFar + endLocation.getSegmentFraction() * endLocation.getSegmentLength(shape);
        ShapeSegmentKey key = new ShapeSegmentKey(shapeId, startIndex, endIndex);
        LineString geometry = _geometriesByShapeSegmentKey.get(key);
        if (geometry == null) {
            LocationIndexedLine locationIndexed = new LocationIndexedLine(shape);
            geometry = (LineString) locationIndexed.extractLine(startLocation, endLocation);
            // Pack the resulting line string
            CoordinateSequence sequence = new PackedCoordinateSequence.Double(geometry.getCoordinates(), 2);
            geometry = _geometryFactory.createLineString(sequence);
        }
        geoms[i] = geometry;
    }
    return geoms;
}
Also used : CoordinateSequence(com.vividsolutions.jts.geom.CoordinateSequence) PackedCoordinateSequence(org.opentripplanner.common.geometry.PackedCoordinateSequence) AgencyAndId(org.onebusaway.gtfs.model.AgencyAndId) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) Stop(org.onebusaway.gtfs.model.Stop) TransitStationStop(org.opentripplanner.routing.vertextype.TransitStationStop) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) BogusShapeGeometryCaught(org.opentripplanner.graph_builder.annotation.BogusShapeGeometryCaught) TIntArrayList(gnu.trove.list.array.TIntArrayList) TIntList(gnu.trove.list.TIntList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) StopTime(org.onebusaway.gtfs.model.StopTime) LocationIndexedLine(com.vividsolutions.jts.linearref.LocationIndexedLine) ShapePoint(org.onebusaway.gtfs.model.ShapePoint) LineString(com.vividsolutions.jts.geom.LineString) Coordinate(com.vividsolutions.jts.geom.Coordinate)

Example 9 with LinearLocation

use of com.vividsolutions.jts.linearref.LinearLocation in project OpenTripPlanner by opentripplanner.

the class GTFSPatternHopFactory method getHopGeometryViaShapeDistTraveled.

private LineString getHopGeometryViaShapeDistTraveled(Graph graph, AgencyAndId shapeId, StopTime st0, StopTime st1) {
    double startDistance = st0.getShapeDistTraveled();
    double endDistance = st1.getShapeDistTraveled();
    ShapeSegmentKey key = new ShapeSegmentKey(shapeId, startDistance, endDistance);
    LineString geometry = _geometriesByShapeSegmentKey.get(key);
    if (geometry != null)
        return geometry;
    double[] distances = getDistanceForShapeId(shapeId);
    if (distances == null) {
        LOG.warn(graph.addBuilderAnnotation(new BogusShapeGeometry(shapeId)));
        return null;
    } else {
        LinearLocation startIndex = getSegmentFraction(distances, startDistance);
        LinearLocation endIndex = getSegmentFraction(distances, endDistance);
        if (equals(startIndex, endIndex)) {
            // bogus shape_dist_traveled
            graph.addBuilderAnnotation(new BogusShapeDistanceTraveled(st1));
            return createSimpleGeometry(st0.getStop(), st1.getStop());
        }
        LineString line = getLineStringForShapeId(shapeId);
        LocationIndexedLine lol = new LocationIndexedLine(line);
        geometry = getSegmentGeometry(graph, shapeId, lol, startIndex, endIndex, startDistance, endDistance, st0, st1);
        return geometry;
    }
}
Also used : LineString(com.vividsolutions.jts.geom.LineString) BogusShapeGeometry(org.opentripplanner.graph_builder.annotation.BogusShapeGeometry) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) LocationIndexedLine(com.vividsolutions.jts.linearref.LocationIndexedLine) BogusShapeDistanceTraveled(org.opentripplanner.graph_builder.annotation.BogusShapeDistanceTraveled)

Example 10 with LinearLocation

use of com.vividsolutions.jts.linearref.LinearLocation in project OpenTripPlanner by opentripplanner.

the class GTFSPatternHopFactory method getStopLocations.

/**
 * Find a consistent, increasing list of LinearLocations along a shape for a set of stops.
 * Handles loops routes.
 * @return
 */
private List<LinearLocation> getStopLocations(List<List<IndexedLineSegment>> possibleSegmentsForStop, List<StopTime> stopTimes, int index, int prevSegmentIndex) {
    if (index == stopTimes.size()) {
        return new LinkedList<LinearLocation>();
    }
    StopTime st = stopTimes.get(index);
    Stop stop = st.getStop();
    Coordinate stopCoord = new Coordinate(stop.getLon(), stop.getLat());
    for (IndexedLineSegment segment : possibleSegmentsForStop.get(index)) {
        if (segment.index < prevSegmentIndex) {
            // can't go backwards along line
            continue;
        }
        List<LinearLocation> locations = getStopLocations(possibleSegmentsForStop, stopTimes, index + 1, segment.index);
        if (locations != null) {
            LinearLocation location = new LinearLocation(0, segment.index, segment.fraction(stopCoord));
            locations.add(0, location);
            // we found one!
            return locations;
        }
    }
    return null;
}
Also used : TransitStop(org.opentripplanner.routing.vertextype.TransitStop) Stop(org.onebusaway.gtfs.model.Stop) TransitStationStop(org.opentripplanner.routing.vertextype.TransitStationStop) Coordinate(com.vividsolutions.jts.geom.Coordinate) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) LinkedList(java.util.LinkedList) StopTime(org.onebusaway.gtfs.model.StopTime)

Aggregations

LinearLocation (com.vividsolutions.jts.linearref.LinearLocation)14 LocationIndexedLine (com.vividsolutions.jts.linearref.LocationIndexedLine)7 Coordinate (com.vividsolutions.jts.geom.Coordinate)6 Edge (org.opentripplanner.routing.graph.Edge)6 HashSet (java.util.HashSet)5 StreetEdge (org.opentripplanner.routing.edgetype.StreetEdge)5 Test (org.junit.Test)4 RoutingRequest (org.opentripplanner.routing.core.RoutingRequest)4 TemporaryFreeEdge (org.opentripplanner.routing.edgetype.TemporaryFreeEdge)4 TemporaryStreetLocation (org.opentripplanner.routing.location.TemporaryStreetLocation)4 NonLocalizedString (org.opentripplanner.util.NonLocalizedString)4 LineString (com.vividsolutions.jts.geom.LineString)3 GraphPath (org.opentripplanner.routing.spt.GraphPath)3 ShortestPathTree (org.opentripplanner.routing.spt.ShortestPathTree)3 Geometry (com.vividsolutions.jts.geom.Geometry)2 ArrayList (java.util.ArrayList)2 LinkedList (java.util.LinkedList)2 ShapePoint (org.onebusaway.gtfs.model.ShapePoint)2 Stop (org.onebusaway.gtfs.model.Stop)2 StopTime (org.onebusaway.gtfs.model.StopTime)2