Search in sources :

Example 1 with LocationIndexedLine

use of org.locationtech.jts.linearref.LocationIndexedLine in project OpenTripPlanner by opentripplanner.

the class GeometryAndBlockProcessor method getHopGeometryViaShapeDistTraveled.

private LineString getHopGeometryViaShapeDistTraveled(FeedScopedId 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) {
        issueStore.add(new BogusShapeGeometry(shapeId));
        return null;
    } else {
        LinearLocation startIndex = getSegmentFraction(distances, startDistance);
        LinearLocation endIndex = getSegmentFraction(distances, endDistance);
        if (equals(startIndex, endIndex)) {
            // bogus shape_dist_traveled
            issueStore.add(new BogusShapeDistanceTraveled(st1));
            return createSimpleGeometry(st0.getStop(), st1.getStop());
        }
        LineString line = getLineStringForShapeId(shapeId);
        LocationIndexedLine lol = new LocationIndexedLine(line);
        geometry = getSegmentGeometry(shapeId, lol, startIndex, endIndex, startDistance, endDistance, st0, st1);
        return geometry;
    }
}
Also used : LineString(org.locationtech.jts.geom.LineString) BogusShapeGeometry(org.opentripplanner.graph_builder.issues.BogusShapeGeometry) LinearLocation(org.locationtech.jts.linearref.LinearLocation) LocationIndexedLine(org.locationtech.jts.linearref.LocationIndexedLine) BogusShapeDistanceTraveled(org.opentripplanner.graph_builder.issues.BogusShapeDistanceTraveled)

Example 2 with LocationIndexedLine

use of org.locationtech.jts.linearref.LocationIndexedLine 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(org.locationtech.jts.linearref.LocationIndexedLine) LinearLocation(org.locationtech.jts.linearref.LinearLocation) BinHeap(org.opentripplanner.common.pqueue.BinHeap) Envelope(org.locationtech.jts.geom.Envelope) Geometry(org.locationtech.jts.geom.Geometry) Coordinate(org.locationtech.jts.geom.Coordinate) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) Edge(org.opentripplanner.routing.graph.Edge) HashSet(java.util.HashSet)

Example 3 with LocationIndexedLine

use of org.locationtech.jts.linearref.LocationIndexedLine 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(org.locationtech.jts.linearref.LinearLocation) LocationIndexedLine(org.locationtech.jts.linearref.LocationIndexedLine) ArrayList(java.util.ArrayList) Geometry(org.locationtech.jts.geom.Geometry) Coordinate(org.locationtech.jts.geom.Coordinate) AssertionFailedException(org.locationtech.jts.util.AssertionFailedException) Edge(org.opentripplanner.routing.graph.Edge)

Example 4 with LocationIndexedLine

use of org.locationtech.jts.linearref.LocationIndexedLine 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) LineString(org.locationtech.jts.geom.LineString) LocationIndexedLine(org.locationtech.jts.linearref.LocationIndexedLine) LinearLocation(org.locationtech.jts.linearref.LinearLocation)

Example 5 with LocationIndexedLine

use of org.locationtech.jts.linearref.LocationIndexedLine 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 : CoordinateSequence(org.locationtech.jts.geom.CoordinateSequence) P2(org.opentripplanner.common.model.P2) LineString(org.locationtech.jts.geom.LineString) Coordinate(org.locationtech.jts.geom.Coordinate) LocationIndexedLine(org.locationtech.jts.linearref.LocationIndexedLine) LinearLocation(org.locationtech.jts.linearref.LinearLocation)

Aggregations

LinearLocation (org.locationtech.jts.linearref.LinearLocation)7 LocationIndexedLine (org.locationtech.jts.linearref.LocationIndexedLine)7 Coordinate (org.locationtech.jts.geom.Coordinate)5 LineString (org.locationtech.jts.geom.LineString)5 CoordinateSequence (org.locationtech.jts.geom.CoordinateSequence)2 Geometry (org.locationtech.jts.geom.Geometry)2 P2 (org.opentripplanner.common.model.P2)2 Edge (org.opentripplanner.routing.graph.Edge)2 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Envelope (org.locationtech.jts.geom.Envelope)1 AssertionFailedException (org.locationtech.jts.util.AssertionFailedException)1 PackedCoordinateSequence (org.opentripplanner.common.geometry.PackedCoordinateSequence)1 BinHeap (org.opentripplanner.common.pqueue.BinHeap)1 BogusShapeDistanceTraveled (org.opentripplanner.graph_builder.issues.BogusShapeDistanceTraveled)1 BogusShapeGeometry (org.opentripplanner.graph_builder.issues.BogusShapeGeometry)1 ShapePoint (org.opentripplanner.model.ShapePoint)1 AreaEdge (org.opentripplanner.routing.edgetype.AreaEdge)1 StreetEdge (org.opentripplanner.routing.edgetype.StreetEdge)1 Vertex (org.opentripplanner.routing.graph.Vertex)1