-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Process boarding location for linear platforms #6247
Open
miklcct
wants to merge
16
commits into
opentripplanner:dev-2.x
Choose a base branch
from
Jnction:boarding-locations
base: dev-2.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 12 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
f7ed65d
add Platform and PlatformEdge into the graph
miklcct 2d423a8
link linear platforms to stops
miklcct 89b3ac7
render PlatformEdge on debug layer
miklcct 363dedc
Merge branch 'dev-2.x' into boarding-locations
miklcct 364c401
fix test after merge
miklcct b445ab8
Merge branch 'dev-2.x' into boarding-locations
miklcct 3825a02
feature: Create a repository to store OSM info for other graph build …
t2gran 0771f0f
Merge branch 'dev-2.x' into boarding-locations
miklcct 12e5eb2
Merge commit '3825a024000a7bc576ab2f5a19b44bb1dd333822' into boarding…
miklcct d40d0b3
use a service to store platform data
miklcct 271f305
move Herrenberg data into the test method
miklcct eaafc68
add test for linear platform
miklcct 8771d5c
apply review suggestion
miklcct c174928
add Javadoc
miklcct cbe125a
Merge remote-tracking branch 'origin/boarding-locations' into boardin…
miklcct 3c9055d
Merge branch 'dev-2.x' into boarding-locations
miklcct File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,12 @@ | ||
package org.opentripplanner.graph_builder.module; | ||
|
||
import jakarta.inject.Inject; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import javax.annotation.Nullable; | ||
import org.locationtech.jts.geom.Coordinate; | ||
import org.locationtech.jts.geom.Envelope; | ||
import org.opentripplanner.framework.geometry.GeometryUtils; | ||
|
@@ -13,6 +17,8 @@ | |
import org.opentripplanner.routing.graph.index.StreetIndex; | ||
import org.opentripplanner.routing.linking.LinkingDirection; | ||
import org.opentripplanner.routing.linking.VertexLinker; | ||
import org.opentripplanner.service.osminfo.OsmInfoGraphBuildService; | ||
import org.opentripplanner.service.osminfo.model.Platform; | ||
import org.opentripplanner.street.model.StreetTraversalPermission; | ||
import org.opentripplanner.street.model.edge.AreaEdge; | ||
import org.opentripplanner.street.model.edge.BoardingLocationToStopLink; | ||
|
@@ -24,9 +30,11 @@ | |
import org.opentripplanner.street.model.vertex.OsmBoardingLocationVertex; | ||
import org.opentripplanner.street.model.vertex.StreetVertex; | ||
import org.opentripplanner.street.model.vertex.TransitStopVertex; | ||
import org.opentripplanner.street.model.vertex.Vertex; | ||
import org.opentripplanner.street.model.vertex.VertexFactory; | ||
import org.opentripplanner.street.search.TraverseMode; | ||
import org.opentripplanner.street.search.TraverseModeSet; | ||
import org.opentripplanner.transit.model.site.StationElement; | ||
import org.opentripplanner.transit.service.TimetableRepository; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
@@ -55,14 +63,20 @@ public class OsmBoardingLocationsModule implements GraphBuilderModule { | |
|
||
private final Graph graph; | ||
|
||
private final OsmInfoGraphBuildService osmInfoGraphBuildService; | ||
private final TimetableRepository timetableRepository; | ||
private final VertexFactory vertexFactory; | ||
|
||
private VertexLinker linker; | ||
|
||
@Inject | ||
public OsmBoardingLocationsModule(Graph graph, TimetableRepository timetableRepository) { | ||
public OsmBoardingLocationsModule( | ||
Graph graph, | ||
OsmInfoGraphBuildService osmInfoGraphBuildService, | ||
TimetableRepository timetableRepository | ||
) { | ||
this.graph = graph; | ||
this.osmInfoGraphBuildService = osmInfoGraphBuildService; | ||
this.timetableRepository = timetableRepository; | ||
this.vertexFactory = new VertexFactory(graph); | ||
} | ||
|
@@ -99,14 +113,14 @@ public void buildGraph() { | |
} | ||
|
||
private boolean connectVertexToStop(TransitStopVertex ts, StreetIndex index) { | ||
var stopCode = ts.getStop().getCode(); | ||
var stopId = ts.getStop().getId().getId(); | ||
var stop = ts.getStop(); | ||
var stopCode = stop.getCode(); | ||
Envelope envelope = new Envelope(ts.getCoordinate()); | ||
|
||
double xscale = Math.cos(ts.getCoordinate().y * Math.PI / 180); | ||
envelope.expandBy(searchRadiusDegrees / xscale, searchRadiusDegrees); | ||
|
||
// if the boarding location is an OSM node it's generated in the OSM processing step but we need | ||
// if the boarding location is a node it's generated in the OSM processing step but we need | ||
// link it here | ||
var nearbyBoardingLocations = index | ||
.getVerticesForEnvelope(envelope) | ||
|
@@ -116,36 +130,66 @@ private boolean connectVertexToStop(TransitStopVertex ts, StreetIndex index) { | |
.collect(Collectors.toSet()); | ||
|
||
for (var boardingLocation : nearbyBoardingLocations) { | ||
if ( | ||
(stopCode != null && boardingLocation.references.contains(stopCode)) || | ||
boardingLocation.references.contains(stopId) | ||
) { | ||
if (matchesReference(stop, boardingLocation.references)) { | ||
if (!boardingLocation.isConnectedToStreetNetwork()) { | ||
linker.linkVertexPermanently( | ||
boardingLocation, | ||
new TraverseModeSet(TraverseMode.WALK), | ||
LinkingDirection.BOTH_WAYS, | ||
(osmBoardingLocationVertex, splitVertex) -> { | ||
if (osmBoardingLocationVertex == splitVertex) { | ||
return List.of(); | ||
} | ||
// the OSM boarding location vertex is not connected to the street network, so we | ||
// need to link it first | ||
return List.of( | ||
linkBoardingLocationToStreetNetwork(boardingLocation, splitVertex), | ||
linkBoardingLocationToStreetNetwork(splitVertex, boardingLocation) | ||
); | ||
} | ||
(osmBoardingLocationVertex, splitVertex) -> | ||
getConnectingEdges(boardingLocation, osmBoardingLocationVertex, splitVertex) | ||
); | ||
} | ||
linkBoardingLocationToStop(ts, stopCode, boardingLocation); | ||
return true; | ||
} | ||
} | ||
|
||
// if the boarding location is an OSM way (an area) then we are generating the vertex here and | ||
// if the boarding location is a non-area way we are finding the vertex representing the | ||
// center of the way, splitting if needed | ||
var nearbyEdges = new HashMap<Platform, List<Edge>>(); | ||
|
||
for (var edge : index.getEdgesForEnvelope(envelope)) { | ||
osmInfoGraphBuildService | ||
.findPlatform(edge) | ||
.ifPresent(platform -> { | ||
if (matchesReference(stop, platform.references())) { | ||
if (!nearbyEdges.containsKey(platform)) { | ||
var list = new ArrayList<Edge>(); | ||
list.add(edge); | ||
nearbyEdges.put(platform, list); | ||
} else { | ||
nearbyEdges.get(platform).add(edge); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
for (var platformEdgeList : nearbyEdges.entrySet()) { | ||
Platform platform = platformEdgeList.getKey(); | ||
var name = platform.name(); | ||
var label = "platform-centroid/%s".formatted(stop.getId().toString()); | ||
var centroid = platform.geometry().getCentroid(); | ||
var boardingLocation = vertexFactory.osmBoardingLocation( | ||
new Coordinate(centroid.getX(), centroid.getY()), | ||
label, | ||
platform.references(), | ||
name | ||
); | ||
Comment on lines
+169
to
+178
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is copy&paste. Please extract a method. |
||
for (var vertex : linker.linkToSpecificStreetEdgesPermanently( | ||
boardingLocation, | ||
new TraverseModeSet(TraverseMode.WALK), | ||
LinkingDirection.BOTH_WAYS, | ||
platformEdgeList.getValue().stream().map(StreetEdge.class::cast).collect(Collectors.toSet()) | ||
)) { | ||
linkBoardingLocationToStop(ts, stopCode, vertex); | ||
} | ||
return true; | ||
} | ||
|
||
// if the boarding location is an area then we are generating the vertex here and | ||
// use the AreaEdgeList to link it to the correct vertices of the platform edge | ||
var nearbyEdgeLists = index | ||
var nearbyAreaEdgeList = index | ||
.getEdgesForEnvelope(envelope) | ||
.stream() | ||
.filter(AreaEdge.class::isInstance) | ||
|
@@ -155,18 +199,15 @@ private boolean connectVertexToStop(TransitStopVertex ts, StreetIndex index) { | |
|
||
// Iterate over all nearby areas representing transit stops in OSM, linking to them if they have a stop code or id | ||
// in their ref= tag that matches the GTFS stop code of this StopVertex. | ||
for (var edgeList : nearbyEdgeLists) { | ||
if ( | ||
(stopCode != null && edgeList.references.contains(stopCode)) || | ||
edgeList.references.contains(stopId) | ||
) { | ||
for (var edgeList : nearbyAreaEdgeList) { | ||
if (matchesReference(stop, edgeList.references)) { | ||
var name = edgeList | ||
.getAreas() | ||
.stream() | ||
.findFirst() | ||
.map(NamedArea::getName) | ||
.orElse(LOCALIZED_PLATFORM_NAME); | ||
var label = "platform-centroid/%s".formatted(ts.getStop().getId().toString()); | ||
var label = "platform-centroid/%s".formatted(stop.getId().toString()); | ||
var centroid = edgeList.getGeometry().getCentroid(); | ||
var boardingLocation = vertexFactory.osmBoardingLocation( | ||
new Coordinate(centroid.getX(), centroid.getY()), | ||
|
@@ -182,6 +223,22 @@ private boolean connectVertexToStop(TransitStopVertex ts, StreetIndex index) { | |
return false; | ||
} | ||
|
||
private List<Edge> getConnectingEdges( | ||
OsmBoardingLocationVertex boardingLocation, | ||
Vertex osmBoardingLocationVertex, | ||
StreetVertex splitVertex | ||
) { | ||
if (osmBoardingLocationVertex == splitVertex) { | ||
return List.of(); | ||
} | ||
// the OSM boarding location vertex is not connected to the street network, so we | ||
// need to link it first | ||
return List.of( | ||
linkBoardingLocationToStreetNetwork(boardingLocation, splitVertex), | ||
linkBoardingLocationToStreetNetwork(splitVertex, boardingLocation) | ||
); | ||
} | ||
|
||
private StreetEdge linkBoardingLocationToStreetNetwork(StreetVertex from, StreetVertex to) { | ||
var line = GeometryUtils.makeLineString(List.of(from.getCoordinate(), to.getCoordinate())); | ||
return new StreetEdgeBuilder<>() | ||
|
@@ -197,8 +254,8 @@ private StreetEdge linkBoardingLocationToStreetNetwork(StreetVertex from, Street | |
|
||
private void linkBoardingLocationToStop( | ||
TransitStopVertex ts, | ||
String stopCode, | ||
OsmBoardingLocationVertex boardingLocation | ||
@Nullable String stopCode, | ||
StreetVertex boardingLocation | ||
) { | ||
BoardingLocationToStopLink.createBoardingLocationToStopLink(ts, boardingLocation); | ||
BoardingLocationToStopLink.createBoardingLocationToStopLink(boardingLocation, ts); | ||
|
@@ -210,4 +267,11 @@ private void linkBoardingLocationToStop( | |
boardingLocation.getCoordinate() | ||
); | ||
} | ||
|
||
private boolean matchesReference(StationElement<?, ?> stop, Collection<String> references) { | ||
var stopCode = stop.getCode(); | ||
var stopId = stop.getId().getId(); | ||
|
||
return (stopCode != null && references.contains(stopCode)) || references.contains(stopId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is getting too large. Please extract three methods for the three cases:
Move the inline comments into Javadoc.