Search in sources :

Example 1 with LinearLocation

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

the class StreetMatcher method match.

@SuppressWarnings("unchecked")
public List<Edge> match(Geometry routeGeometry) {
    routeGeometry = removeDuplicatePoints(routeGeometry);
    if (routeGeometry == null)
        return null;
    routeGeometry = DouglasPeuckerSimplifier.simplify(routeGeometry, 0.00001);
    // initial state: start midway along a block.
    LocationIndexedLine indexedLine = new LocationIndexedLine(routeGeometry);
    LinearLocation startIndex = indexedLine.getStartIndex();
    Coordinate routeStartCoordinate = startIndex.getCoordinate(routeGeometry);
    Envelope envelope = new Envelope(routeStartCoordinate);
    double distanceThreshold = DISTANCE_THRESHOLD;
    envelope.expandBy(distanceThreshold);
    BinHeap<MatchState> states = new BinHeap<MatchState>();
    List<Edge> nearbyEdges = index.query(envelope);
    while (nearbyEdges.isEmpty()) {
        envelope.expandBy(distanceThreshold);
        distanceThreshold *= 2;
        nearbyEdges = index.query(envelope);
    }
    // compute initial states
    for (Edge initialEdge : nearbyEdges) {
        Geometry edgeGeometry = initialEdge.getGeometry();
        LocationIndexedLine indexedEdge = new LocationIndexedLine(edgeGeometry);
        LinearLocation initialLocation = indexedEdge.project(routeStartCoordinate);
        double error = MatchState.distance(initialLocation.getCoordinate(edgeGeometry), routeStartCoordinate);
        MidblockMatchState state = new MidblockMatchState(null, routeGeometry, initialEdge, startIndex, initialLocation, error, 0.01);
        // make sure all initial states are visited by inserting them at 0
        states.insert(state, 0);
    }
    // search for best-matching path
    int seen_count = 0, total = 0;
    HashSet<MatchState> seen = new HashSet<MatchState>();
    while (!states.empty()) {
        double k = states.peek_min_key();
        MatchState state = states.extract_min();
        if (++total % 50000 == 0) {
            log.debug("seen / total: " + seen_count + " / " + total);
        }
        if (seen.contains(state)) {
            ++seen_count;
            continue;
        } else {
            if (k != 0) {
                // but do not mark states as closed if we start at them
                seen.add(state);
            }
        }
        if (state instanceof EndMatchState) {
            return toEdgeList(state);
        }
        for (MatchState next : state.getNextStates()) {
            if (seen.contains(next)) {
                continue;
            }
            states.insert(next, next.getTotalError() - next.getDistanceAlongRoute());
        }
    }
    return null;
}
Also used : LocationIndexedLine(com.vividsolutions.jts.linearref.LocationIndexedLine) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) BinHeap(org.opentripplanner.common.pqueue.BinHeap) Envelope(com.vividsolutions.jts.geom.Envelope) Geometry(com.vividsolutions.jts.geom.Geometry) Coordinate(com.vividsolutions.jts.geom.Coordinate) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) Edge(org.opentripplanner.routing.graph.Edge) HashSet(java.util.HashSet)

Example 2 with LinearLocation

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

the class MatchState method distanceAlongGeometry.

/* computes the distance, in meters, along a geometry */
protected static double distanceAlongGeometry(Geometry geometry, LinearLocation startIndex, LinearLocation endIndex) {
    if (endIndex == null) {
        endIndex = LinearLocation.getEndLocation(geometry);
    }
    double total = 0;
    LinearIterator it = new LinearIterator(geometry, startIndex);
    LinearLocation index = startIndex;
    Coordinate previousCoordinate = startIndex.getCoordinate(geometry);
    it.next();
    index = it.getLocation();
    while (index.compareTo(endIndex) < 0) {
        Coordinate thisCoordinate = index.getCoordinate(geometry);
        double distance = SphericalDistanceLibrary.fastDistance(previousCoordinate, thisCoordinate);
        total += distance;
        previousCoordinate = thisCoordinate;
        if (!it.hasNext())
            break;
        it.next();
        index = it.getLocation();
    }
    // now, last bit of last segment
    Coordinate finalCoordinate = endIndex.getCoordinate(geometry);
    total += SphericalDistanceLibrary.distance(previousCoordinate, finalCoordinate);
    return total;
}
Also used : Coordinate(com.vividsolutions.jts.geom.Coordinate) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation)

Example 3 with LinearLocation

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

the class GeometryUtils method splitGeometryAtPoint.

/**
 * Splits the input geometry into two LineStrings at the given point.
 */
public static P2<LineString> splitGeometryAtPoint(Geometry geometry, Coordinate nearestPoint) {
    // 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 = line.indexOf(nearestPoint);
    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 4 with LinearLocation

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

the class GTFSPatternHopFactory method getSegmentFraction.

private LinearLocation getSegmentFraction(double[] distances, double distance) {
    int index = Arrays.binarySearch(distances, distance);
    if (index < 0)
        index = -(index + 1);
    if (index == 0)
        return new LinearLocation(0, 0.0);
    if (index == distances.length)
        return new LinearLocation(distances.length, 0.0);
    double prevDistance = distances[index - 1];
    if (prevDistance == distances[index]) {
        return new LinearLocation(index - 1, 1.0);
    }
    double indexPart = (distance - distances[index - 1]) / (distances[index] - prevDistance);
    return new LinearLocation(index - 1, indexPart);
}
Also used : LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) ShapePoint(org.onebusaway.gtfs.model.ShapePoint)

Example 5 with LinearLocation

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

the class MidblockMatchState method getNextStates.

@Override
public List<MatchState> getNextStates() {
    ArrayList<MatchState> nextStates = new ArrayList<MatchState>();
    if (routeIndex.getSegmentIndex() == routeGeometry.getNumPoints() - 1) {
        // this has either hit the end, or gone off the end. It's not real clear which.
        // for now, let's assume it means that the ending is somewhere along this edge,
        // so we return an end state
        Coordinate pt = routeIndex.getCoordinate(routeGeometry);
        double error = distance(pt, edgeIndex.getCoordinate(edgeGeometry));
        nextStates.add(new EndMatchState(this, error, 0));
        return nextStates;
    }
    LinearIterator it = new LinearIterator(routeGeometry, routeIndex);
    if (it.hasNext()) {
        it.next();
        LinearLocation routeSuccessor = it.getLocation();
        // now we want to see where this new point is in terms of the edge's geometry
        Coordinate newRouteCoord = routeSuccessor.getCoordinate(routeGeometry);
        LinearLocation newEdgeIndex = indexedEdge.project(newRouteCoord);
        Coordinate edgeCoord = newEdgeIndex.getCoordinate(edgeGeometry);
        if (newEdgeIndex.compareTo(edgeIndex) <= 0) {
            /* this should not require the try/catch, but there is a bug in JTS */
            try {
                LinearLocation projected2 = indexedEdge.indexOfAfter(edgeCoord, edgeIndex);
                // another bug in JTS
                if (Double.isNaN(projected2.getSegmentFraction())) {
                    // we are probably moving backwards
                    return Collections.emptyList();
                } else {
                    newEdgeIndex = projected2;
                    if (newEdgeIndex.equals(edgeIndex)) {
                        return Collections.emptyList();
                    }
                }
                edgeCoord = newEdgeIndex.getCoordinate(edgeGeometry);
            } catch (AssertionFailedException e) {
                // we are not making progress, so just return an empty list
                return Collections.emptyList();
            }
        }
        if (newEdgeIndex.getSegmentIndex() == edgeGeometry.getNumPoints() - 1) {
            // we might choose to continue from the end of the edge and a point mid-way
            // along this route segment
            // find nearest point that makes progress along the route
            Vertex toVertex = edge.getToVertex();
            Coordinate endCoord = toVertex.getCoordinate();
            LocationIndexedLine indexedRoute = new LocationIndexedLine(routeGeometry);
            // FIXME: it would be better to do this project/indexOfAfter in one step
            // as the two-step version could snap to a bad place and be unable to escape.
            LinearLocation routeProjectedEndIndex = indexedRoute.project(endCoord);
            Coordinate routeProjectedEndCoord = routeProjectedEndIndex.getCoordinate(routeGeometry);
            if (routeProjectedEndIndex.compareTo(routeIndex) <= 0) {
                try {
                    routeProjectedEndIndex = indexedRoute.indexOfAfter(routeProjectedEndCoord, routeIndex);
                    if (Double.isNaN(routeProjectedEndIndex.getSegmentFraction())) {
                        // can't go forward
                        // this is bad, but not terrible
                        routeProjectedEndIndex = routeIndex;
                    // since we are advancing along the edge
                    }
                } catch (AssertionFailedException e) {
                    routeProjectedEndIndex = routeIndex;
                }
                routeProjectedEndCoord = routeProjectedEndIndex.getCoordinate(routeGeometry);
            }
            double positionError = distance(routeProjectedEndCoord, endCoord);
            double travelAlongRoute = distanceAlongGeometry(routeGeometry, routeIndex, routeProjectedEndIndex);
            double travelAlongEdge = distanceAlongGeometry(edgeGeometry, edgeIndex, newEdgeIndex);
            double travelError = Math.abs(travelAlongEdge - travelAlongRoute);
            double error = positionError + travelError;
            if (error > MAX_ERROR) {
                // totally wrong
                return nextStates;
            }
            for (Edge e : getOutgoingMatchableEdges(toVertex)) {
                double cost = error + NEW_SEGMENT_PENALTY;
                if (!carsCanTraverse(e)) {
                    cost += NO_TRAVERSE_PENALTY;
                }
                MatchState nextState = new MidblockMatchState(this, routeGeometry, e, routeProjectedEndIndex, new LinearLocation(), cost, travelAlongRoute);
                nextStates.add(nextState);
            }
        } else {
            double travelAlongEdge = distanceAlongGeometry(edgeGeometry, edgeIndex, newEdgeIndex);
            double travelAlongRoute = distanceAlongGeometry(routeGeometry, routeIndex, routeSuccessor);
            double travelError = Math.abs(travelAlongRoute - travelAlongEdge);
            double positionError = distance(edgeCoord, newRouteCoord);
            double error = travelError + positionError;
            MatchState nextState = new MidblockMatchState(this, routeGeometry, edge, routeSuccessor, newEdgeIndex, error, travelAlongRoute);
            nextStates.add(nextState);
            // it's also possible that, although we have not yet reached the end of this edge,
            // we are going to turn, because the route turns earlier than the edge. In that
            // case, we jump to the corner, and our error is the distance from the route point
            // and the corner
            Vertex toVertex = edge.getToVertex();
            double travelAlongOldEdge = distanceAlongGeometry(edgeGeometry, edgeIndex, null);
            for (Edge e : getOutgoingMatchableEdges(toVertex)) {
                Geometry newEdgeGeometry = e.getGeometry();
                LocationIndexedLine newIndexedEdge = new LocationIndexedLine(newEdgeGeometry);
                newEdgeIndex = newIndexedEdge.project(newRouteCoord);
                Coordinate newEdgeCoord = newEdgeIndex.getCoordinate(newEdgeGeometry);
                positionError = distance(newEdgeCoord, newRouteCoord);
                travelAlongEdge = travelAlongOldEdge + distanceAlongGeometry(newEdgeGeometry, new LinearLocation(), newEdgeIndex);
                travelError = Math.abs(travelAlongRoute - travelAlongEdge);
                error = travelError + positionError;
                if (error > MAX_ERROR) {
                    // totally wrong
                    return nextStates;
                }
                double cost = error + NEW_SEGMENT_PENALTY;
                if (!carsCanTraverse(e)) {
                    cost += NO_TRAVERSE_PENALTY;
                }
                nextState = new MidblockMatchState(this, routeGeometry, e, routeSuccessor, new LinearLocation(), cost, travelAlongRoute);
                nextStates.add(nextState);
            }
        }
        return nextStates;
    } else {
        Coordinate routeCoord = routeIndex.getCoordinate(routeGeometry);
        LinearLocation projected = indexedEdge.project(routeCoord);
        double locationError = distance(projected.getCoordinate(edgeGeometry), routeCoord);
        MatchState end = new EndMatchState(this, locationError, 0);
        return Arrays.asList(end);
    }
}
Also used : Vertex(org.opentripplanner.routing.graph.Vertex) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) LocationIndexedLine(com.vividsolutions.jts.linearref.LocationIndexedLine) ArrayList(java.util.ArrayList) Geometry(com.vividsolutions.jts.geom.Geometry) Coordinate(com.vividsolutions.jts.geom.Coordinate) AssertionFailedException(com.vividsolutions.jts.util.AssertionFailedException) Edge(org.opentripplanner.routing.graph.Edge)

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