diff --git a/application/src/main/java/org/opentripplanner/routing/linking/LinkingContextFactory.java b/application/src/main/java/org/opentripplanner/routing/linking/LinkingContextFactory.java index 09e8bf86662..077241546e1 100644 --- a/application/src/main/java/org/opentripplanner/routing/linking/LinkingContextFactory.java +++ b/application/src/main/java/org/opentripplanner/routing/linking/LinkingContextFactory.java @@ -280,7 +280,10 @@ private Set getStreetVerticesForLocation( var carRoutableVertex = getCarRoutableStreetVertex(container, location, type); carRoutableVertex.ifPresent(results::add); } - } else if (location.getCoordinate() != null) { + } + + // If no vertices found from stop ID lookup and coordinates are available, use coordinates as fallback + if (results.isEmpty() && location.getCoordinate() != null) { // Connect a temporary vertex from coordinate to graph results.add( vertexCreationService.createVertexFromCoordinate( diff --git a/application/src/test/java/org/opentripplanner/routing/linking/LinkingContextFactoryTest.java b/application/src/test/java/org/opentripplanner/routing/linking/LinkingContextFactoryTest.java index 021d2b1225f..093af655d8b 100644 --- a/application/src/test/java/org/opentripplanner/routing/linking/LinkingContextFactoryTest.java +++ b/application/src/test/java/org/opentripplanner/routing/linking/LinkingContextFactoryTest.java @@ -28,6 +28,7 @@ import org.opentripplanner.street.model.edge.Edge; import org.opentripplanner.street.model.edge.StreetStationCentroidLink; import org.opentripplanner.street.model.vertex.StationCentroidVertex; +import org.opentripplanner.street.model.vertex.TemporaryStreetLocation; import org.opentripplanner.street.model.vertex.TransitStopVertex; import org.opentripplanner.street.model.vertex.Vertex; import org.opentripplanner.street.search.TraverseMode; @@ -288,6 +289,41 @@ void walkingBetterThanTransitException() { assertEquals(RoutingErrorCode.WALKING_BETTER_THAN_TRANSIT, fromError.code); } + @Test + void nonExistingPlaceIdWithCoordinatesShouldFallbackToCoordinates() { + var container = new TemporaryVerticesContainer(); + var nonExistingStopId = new FeedScopedId("F", "NonExistingStop"); + + // Create locations with both a non-existing stop ID and valid coordinates + var from = new GenericLocation("From", nonExistingStopId, stopA.getLat(), stopA.getLon()); + var to = new GenericLocation( + "To", + new FeedScopedId("F", "AnotherNonExisting"), + stopD.getLat(), + stopD.getLon() + ); + + var request = LinkingContextRequest.of() + .withFrom(from) + .withTo(to) + .withDirectMode(StreetMode.WALK) + .build(); + + // This should NOT throw an exception - it should fall back to using coordinates + var linkingContext = linkingContextFactory.create(container, request); + + // Verify that vertices were created from the coordinates + var fromVertices = linkingContext.findVertices(from); + assertThat(fromVertices).hasSize(1); + assertTemporaryVertexOnStop(fromVertices.stream().findFirst().get(), stopA); + + var toVertices = linkingContext.findVertices(to); + assertThat(toVertices).hasSize(1); + assertTemporaryVertexOnStop(toVertices.stream().findFirst().get(), stopD); + + container.close(); + } + private static Graph buildGraph(Station station, RegularStop... stops) { var graph = new Graph(); var left = StreetModelForTest.intersectionVertex(CENTER.asJtsCoordinate()); @@ -319,6 +355,12 @@ private static Graph buildGraph(Station station, RegularStop... stops) { return graph; } + private void assertTemporaryVertexOnStop(Vertex vertex, RegularStop stop) { + assertThat(vertex).isInstanceOf(TemporaryStreetLocation.class); + assertEquals(stop.getLat(), vertex.getLat(), 0.0001); + assertEquals(stop.getLon(), vertex.getLon(), 0.0001); + } + private RegularStop toStop(Set fromVertices) { assertThat(fromVertices).hasSize(1); var id = ((TransitStopVertex) List.copyOf(fromVertices).getFirst()).getId();