From 1d19a052a8bf2523c3af537edfc92fe9a72e8c62 Mon Sep 17 00:00:00 2001 From: Henrik Sundell Date: Wed, 18 Sep 2024 17:22:19 +0300 Subject: [PATCH] Add subway station entrances to walk steps --- .../apis/gtfs/datafetchers/stepImpl.java | 5 +++++ .../gtfs/generated/GraphQLDataFetchers.java | 11 +++++++++++ .../apis/gtfs/generated/GraphQLTypes.java | 1 + .../module/osm/VertexGenerator.java | 9 +++++++++ .../opentripplanner/model/plan/WalkStep.java | 10 ++++++++++ .../model/plan/WalkStepBuilder.java | 7 +++++++ .../openstreetmap/model/OSMNode.java | 9 +++++++++ .../mapping/StatesToWalkStepsMapper.java | 18 ++++++++++++++++++ .../model/vertex/StationEntranceVertex.java | 19 +++++++++++++++++++ .../street/model/vertex/VertexFactory.java | 9 +++++++++ .../opentripplanner/apis/gtfs/schema.graphqls | 2 ++ 11 files changed, 100 insertions(+) create mode 100644 src/main/java/org/opentripplanner/street/model/vertex/StationEntranceVertex.java diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java index 6bd51ae5f29..d79e224e51e 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java @@ -53,6 +53,11 @@ public DataFetcher exit() { return environment -> getSource(environment).getExit(); } + @Override + public DataFetcher entrance() { + return environment -> getSource(environment).getEntrance(); + } + @Override public DataFetcher lat() { return environment -> getSource(environment).getStartLocation().latitude(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 67944543580..3c162b14112 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -1,9 +1,11 @@ //THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. package org.opentripplanner.apis.gtfs.generated; +import graphql.relay.Connection; import graphql.relay.Connection; import graphql.relay.DefaultEdge; import graphql.relay.Edge; +import graphql.relay.Edge; import graphql.schema.DataFetcher; import graphql.schema.TypeResolver; import java.util.Currency; @@ -24,8 +26,12 @@ import org.opentripplanner.apis.gtfs.model.FeedPublisher; import org.opentripplanner.apis.gtfs.model.PlanPageInfo; import org.opentripplanner.apis.gtfs.model.RideHailingProvider; +import org.opentripplanner.apis.gtfs.model.RouteTypeModel; +import org.opentripplanner.apis.gtfs.model.StopOnRouteModel; +import org.opentripplanner.apis.gtfs.model.StopOnTripModel; import org.opentripplanner.apis.gtfs.model.StopPosition; import org.opentripplanner.apis.gtfs.model.TripOccupancy; +import org.opentripplanner.apis.gtfs.model.UnknownModel; import org.opentripplanner.ext.fares.model.FareRuleSet; import org.opentripplanner.ext.ridehailing.model.RideEstimate; import org.opentripplanner.model.StopTimesInPattern; @@ -48,6 +54,8 @@ import org.opentripplanner.routing.graphfinder.PatternAtStop; import org.opentripplanner.routing.graphfinder.PlaceAtDistance; import org.opentripplanner.routing.vehicle_parking.VehicleParking; +import org.opentripplanner.routing.vehicle_parking.VehicleParking; +import org.opentripplanner.routing.vehicle_parking.VehicleParking; import org.opentripplanner.routing.vehicle_parking.VehicleParkingSpaces; import org.opentripplanner.routing.vehicle_parking.VehicleParkingState; import org.opentripplanner.service.realtimevehicles.model.RealtimeVehicle; @@ -58,6 +66,7 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; +import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalSystem; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; import org.opentripplanner.transit.model.basic.Money; @@ -1419,6 +1428,8 @@ public interface GraphQLStep { public DataFetcher> elevationProfile(); + public DataFetcher entrance(); + public DataFetcher exit(); public DataFetcher lat(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 67051444cdf..8edc0cce870 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -1,6 +1,7 @@ // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. package org.opentripplanner.apis.gtfs.generated; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; diff --git a/src/main/java/org/opentripplanner/graph_builder/module/osm/VertexGenerator.java b/src/main/java/org/opentripplanner/graph_builder/module/osm/VertexGenerator.java index 14489777dd4..df9c4376871 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/osm/VertexGenerator.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/osm/VertexGenerator.java @@ -95,6 +95,15 @@ IntersectionVertex getVertexForOsmNode(OSMNode node, OSMWithTags way) { iv = bv; } + if (node.isSubwayEntrance()) { + String ref = node.getTag("ref"); + if (ref != null) { + iv = vertexFactory.stationEntrance(nid, coordinate, ref); + } else { + iv = vertexFactory.stationEntrance(nid, coordinate, "MAIN_ENTRANCE"); + } + } + if (iv == null) { iv = vertexFactory.osm( diff --git a/src/main/java/org/opentripplanner/model/plan/WalkStep.java b/src/main/java/org/opentripplanner/model/plan/WalkStep.java index 13249d5da52..9a650ecef3e 100644 --- a/src/main/java/org/opentripplanner/model/plan/WalkStep.java +++ b/src/main/java/org/opentripplanner/model/plan/WalkStep.java @@ -44,6 +44,7 @@ public final class WalkStep { private final boolean walkingBike; private final String exit; + private final String entrance; private final ElevationProfile elevationProfile; private final boolean stayOn; @@ -56,6 +57,7 @@ public final class WalkStep { I18NString directionText, Set streetNotes, String exit, + String entrance, ElevationProfile elevationProfile, boolean bogusName, boolean walkingBike, @@ -76,6 +78,7 @@ public final class WalkStep { this.walkingBike = walkingBike; this.area = area; this.exit = exit; + this.entrance = entrance; this.elevationProfile = elevationProfile; this.stayOn = stayOn; this.edges = List.copyOf(Objects.requireNonNull(edges)); @@ -130,6 +133,13 @@ public String getExit() { return exit; } + /** + * When entering or exiting a public transport station, the entrance name + */ + public String getEntrance() { + return entrance; + } + /** * Indicates whether a street changes direction at an intersection. */ diff --git a/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java b/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java index 25c6ee25b6b..8b5d2cedb11 100644 --- a/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java +++ b/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java @@ -25,6 +25,7 @@ public class WalkStepBuilder { private RelativeDirection relativeDirection; private ElevationProfile elevationProfile; private String exit; + private String entrance; private boolean stayOn = false; /** * Distance used for appending elevation profiles @@ -74,6 +75,11 @@ public WalkStepBuilder withExit(String exit) { return this; } + public WalkStepBuilder withEntrance(String entrance) { + this.entrance = entrance; + return this; + } + public WalkStepBuilder withStayOn(boolean stayOn) { this.stayOn = stayOn; return this; @@ -156,6 +162,7 @@ public WalkStep build() { directionText, streetNotes, exit, + entrance, elevationProfile, bogusName, walkingBike, diff --git a/src/main/java/org/opentripplanner/openstreetmap/model/OSMNode.java b/src/main/java/org/opentripplanner/openstreetmap/model/OSMNode.java index d181cde4564..371751d5e4a 100644 --- a/src/main/java/org/opentripplanner/openstreetmap/model/OSMNode.java +++ b/src/main/java/org/opentripplanner/openstreetmap/model/OSMNode.java @@ -63,6 +63,15 @@ public boolean isBarrier() { ); } + /** + * Checks if this node is an subway station entrance + * + * @return true if it does + */ + public boolean isSubwayEntrance() { + return hasTag("railway") && "subway_entrance".equals(getTag("railway")); + } + /** * Consider barrier tag in permissions. Leave the rest for the super class. */ diff --git a/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java index 94905bb840a..d49755bb548 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java @@ -26,6 +26,7 @@ import org.opentripplanner.street.model.edge.StreetEdge; import org.opentripplanner.street.model.edge.StreetTransitEntranceLink; import org.opentripplanner.street.model.vertex.ExitVertex; +import org.opentripplanner.street.model.vertex.StationEntranceVertex; import org.opentripplanner.street.model.vertex.Vertex; import org.opentripplanner.street.search.TraverseMode; import org.opentripplanner.street.search.state.State; @@ -258,6 +259,8 @@ private void processState(State backState, State forwardState) { setMotorwayExit(backState); + setStationEntrance(backState); + if (createdNewStep && !modeTransition) { // check last three steps for zag int lastIndex = steps.size() - 1; @@ -380,6 +383,21 @@ private void setMotorwayExit(State backState) { } } + /** + * Update the walk step with the name of the station entrance if set from OSM + */ + private void setStationEntrance(State backState) { + State entranceState = backState; + Edge entranceEdge = entranceState.getBackEdge(); + while (entranceEdge instanceof FreeEdge) { + entranceState = entranceState.getBackState(); + entranceEdge = entranceState.getBackEdge(); + } + if (entranceState.getVertex() instanceof StationEntranceVertex) { + current.withEntrance(((StationEntranceVertex) entranceState.getVertex()).getEntranceName()); + } + } + /** * Is it possible to turn to another street from this previous state */ diff --git a/src/main/java/org/opentripplanner/street/model/vertex/StationEntranceVertex.java b/src/main/java/org/opentripplanner/street/model/vertex/StationEntranceVertex.java new file mode 100644 index 00000000000..af1e824a7bd --- /dev/null +++ b/src/main/java/org/opentripplanner/street/model/vertex/StationEntranceVertex.java @@ -0,0 +1,19 @@ +package org.opentripplanner.street.model.vertex; + +public class StationEntranceVertex extends OsmVertex { + + private final String entranceName; + + public StationEntranceVertex(double x, double y, long nodeId, String entranceName) { + super(x, y, nodeId); + this.entranceName = entranceName; + } + + public String getEntranceName() { + return entranceName; + } + + public String toString() { + return "StationEntranceVertex(" + super.toString() + ")"; + } +} diff --git a/src/main/java/org/opentripplanner/street/model/vertex/VertexFactory.java b/src/main/java/org/opentripplanner/street/model/vertex/VertexFactory.java index c7e38ca0032..3fe201070d4 100644 --- a/src/main/java/org/opentripplanner/street/model/vertex/VertexFactory.java +++ b/src/main/java/org/opentripplanner/street/model/vertex/VertexFactory.java @@ -103,6 +103,15 @@ public ExitVertex exit(long nid, Coordinate coordinate, String exitName) { return addToGraph(new ExitVertex(coordinate.x, coordinate.y, nid, exitName)); } + @Nonnull + public StationEntranceVertex stationEntrance( + long nid, + Coordinate coordinate, + String entranceName + ) { + return addToGraph(new StationEntranceVertex(coordinate.x, coordinate.y, nid, entranceName)); + } + @Nonnull public OsmVertex osm( Coordinate coordinate, diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 927af19f8b1..12decc1e3d5 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -2628,6 +2628,8 @@ type step { elevationProfile: [elevationProfileComponent] "When exiting a highway or traffic circle, the exit name/number." exit: String + "Name of entrance to a public transport station" + entrance: String "The latitude of the start of the step." lat: Float "The longitude of the start of the step."