
org.opentripplanner.graph_builder.module.islandpruning.Subgraph Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
The newest version!
package org.opentripplanner.graph_builder.module.islandpruning;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.MultiPoint;
import org.locationtech.jts.geom.Point;
import org.opentripplanner.framework.geometry.GeometryUtils;
import org.opentripplanner.framework.geometry.SphericalDistanceLibrary;
import org.opentripplanner.routing.graph.index.StreetIndex;
import org.opentripplanner.street.model.vertex.OsmVertex;
import org.opentripplanner.street.model.vertex.TransitStopVertex;
import org.opentripplanner.street.model.vertex.Vertex;
import org.opentripplanner.transit.model.basic.TransitMode;
class Subgraph {
private final Set streetVertexSet;
private final Set stopsVertexSet;
Subgraph() {
streetVertexSet = new HashSet<>();
stopsVertexSet = new HashSet<>();
}
void addVertex(Vertex vertex) {
if (vertex instanceof TransitStopVertex transitStopVertex) {
stopsVertexSet.add(transitStopVertex);
} else {
streetVertexSet.add(vertex);
}
}
boolean contains(Vertex vertex) {
return (streetVertexSet.contains(vertex) || stopsVertexSet.contains(vertex));
}
int streetSize() {
return streetVertexSet.size();
}
int stopSize() {
return stopsVertexSet.size();
}
Vertex getRepresentativeVertex() {
// Return first OSM vertex if available
for (var vertx : streetVertexSet) {
if (vertx instanceof OsmVertex) {
return vertx;
}
}
// Otherwise fallback to what is available
return streetVertexSet.iterator().next();
}
Iterator streetIterator() {
return streetVertexSet.iterator();
}
Iterator stopIterator() {
return stopsVertexSet.iterator();
}
// find minimal distance from a given vertex to vertices of this subgraph
double vertexDistanceFromSubgraph(Vertex v, double searchRadius) {
double d1 = streetVertexSet
.stream()
.map(x -> SphericalDistanceLibrary.distance(x.getCoordinate(), v.getCoordinate()))
.min(Double::compareTo)
.orElse(searchRadius);
double d2 = stopsVertexSet
.stream()
.map(x -> SphericalDistanceLibrary.distance(x.getCoordinate(), v.getCoordinate()))
.min(Double::compareTo)
.orElse(searchRadius);
return Math.min(d1, d2);
}
// Estimate distance of a subgraph from other parts of the graph.
// For speed reasons, graph geometry only within given search radius is considered.
// Distance is estimated using minimal vertex to vertex search instead of computing
// distances between graph edges. This is good enough for our heuristics.
double distanceFromOtherGraph(StreetIndex index, double searchRadius) {
Vertex v = getRepresentativeVertex();
double xscale = Math.cos(v.getCoordinate().y * Math.PI / 180);
double searchRadiusDegrees = SphericalDistanceLibrary.metersToDegrees(searchRadius);
Envelope envelope = new Envelope();
for (Iterator vIter = streetIterator(); vIter.hasNext();) {
Vertex vx = vIter.next();
envelope.expandToInclude(vx.getCoordinate());
}
for (TransitStopVertex vx : stopsVertexSet) {
envelope.expandToInclude(vx.getCoordinate());
}
envelope.expandBy(searchRadiusDegrees / xscale, searchRadiusDegrees);
return index
.getVerticesForEnvelope(envelope)
.stream()
.filter(vx -> !contains(vx))
.map(vx -> vertexDistanceFromSubgraph(vx, searchRadius))
.min(Double::compareTo)
.orElse(searchRadius);
}
/**
* Get a {@link Geometry for all the contained vertices}
*/
Geometry getGeometry() {
List points = new ArrayList<>();
GeometryFactory geometryFactory = GeometryUtils.getGeometryFactory();
Consumer vertexAdder = vertex ->
points.add(geometryFactory.createPoint(vertex.getCoordinate()));
streetIterator().forEachRemaining(vertexAdder);
stopIterator().forEachRemaining(vertexAdder);
return new MultiPoint(points.toArray(new Point[0]), geometryFactory);
}
/**
* Checks whether the subgraph has only transit-stops for ferries
*
* @return true if only ferries stop at the subgraph and false if other or no modes are
* stopping at the subgraph
*/
boolean hasOnlyFerryStops() {
for (TransitStopVertex v : stopsVertexSet) {
Set modes = v.getModes();
// test if stop has other transit modes than FERRY
if (!modes.contains(TransitMode.FERRY)) {
return false;
}
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy