
org.opentripplanner.transit.model.network.TripPatternBuilder 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.transit.model.network;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.LineString;
import org.opentripplanner.framework.geometry.CompactLineStringUtils;
import org.opentripplanner.framework.geometry.GeometryUtils;
import org.opentripplanner.model.Timetable;
import org.opentripplanner.routing.algorithm.raptoradapter.api.SlackProvider;
import org.opentripplanner.transit.model.basic.SubMode;
import org.opentripplanner.transit.model.basic.TransitMode;
import org.opentripplanner.transit.model.framework.AbstractEntityBuilder;
import org.opentripplanner.transit.model.framework.FeedScopedId;
@SuppressWarnings("UnusedReturnValue")
public final class TripPatternBuilder
extends AbstractEntityBuilder {
private Route route;
private TransitMode mode;
private SubMode netexSubMode;
private boolean containsMultipleModes;
private StopPattern stopPattern;
private Timetable scheduledTimetable;
private String name;
private boolean createdByRealtimeUpdate;
private TripPattern originalTripPattern;
private List hopGeometries;
TripPatternBuilder(FeedScopedId id) {
super(id);
}
TripPatternBuilder(TripPattern original) {
super(original);
this.name = original.getName();
this.route = original.getRoute();
this.mode = original.getMode();
this.netexSubMode = original.getNetexSubmode();
this.containsMultipleModes = original.getContainsMultipleModes();
this.stopPattern = original.getStopPattern();
this.scheduledTimetable = original.getScheduledTimetable();
this.createdByRealtimeUpdate = original.isCreatedByRealtimeUpdater();
this.originalTripPattern = original.getOriginalTripPattern();
this.hopGeometries =
original.getGeometry() == null
? null
: IntStream
.range(0, original.numberOfStops() - 1)
.mapToObj(original::getHopGeometry)
.toList();
}
public TripPatternBuilder withName(String name) {
this.name = name;
return this;
}
public TripPatternBuilder withRoute(Route route) {
this.route = route;
return this;
}
public TripPatternBuilder withMode(TransitMode mode) {
this.mode = mode;
return this;
}
public TripPatternBuilder withNetexSubmode(SubMode netexSubmode) {
this.netexSubMode = netexSubmode;
return this;
}
public TripPatternBuilder withContainsMultipleModes(boolean containsMultipleModes) {
this.containsMultipleModes = containsMultipleModes;
return this;
}
public TripPatternBuilder withStopPattern(StopPattern stopPattern) {
this.stopPattern = stopPattern;
return this;
}
public TripPatternBuilder withScheduledTimeTable(Timetable scheduledTimetable) {
this.scheduledTimetable = scheduledTimetable;
return this;
}
public TripPatternBuilder withCreatedByRealtimeUpdater(boolean createdByRealtimeUpdate) {
this.createdByRealtimeUpdate = createdByRealtimeUpdate;
return this;
}
public TripPatternBuilder withOriginalTripPattern(TripPattern originalTripPattern) {
this.originalTripPattern = originalTripPattern;
return this;
}
public TripPatternBuilder withHopGeometries(List hopGeometries) {
this.hopGeometries = hopGeometries;
return this;
}
// TODO: This uses a static SlackProvider. Change it to be injectable if required
public int slackIndex() {
return SlackProvider.slackIndex(route.getMode());
}
// TODO: Change the calculation to be injectable if required
public int transitReluctanceFactorIndex() {
return route.getMode().ordinal();
}
@Override
protected TripPattern buildFromValues() {
return new TripPattern(this);
}
public Route getRoute() {
return route;
}
public TransitMode getMode() {
return mode;
}
public SubMode getNetexSubmode() {
return netexSubMode;
}
public boolean getContainsMultipleModes() {
return containsMultipleModes;
}
public StopPattern getStopPattern() {
return stopPattern;
}
public Timetable getScheduledTimetable() {
return scheduledTimetable;
}
public String getName() {
return name;
}
public TripPattern getOriginalTripPattern() {
return originalTripPattern;
}
public boolean isCreatedByRealtimeUpdate() {
return createdByRealtimeUpdate;
}
public byte[][] hopGeometries() {
List geometries;
if (this.hopGeometries != null) {
geometries = this.hopGeometries;
} else if (this.originalTripPattern != null) {
geometries = generateHopGeometriesFromOriginalTripPattern();
} else {
return null;
}
return geometries
.stream()
.map(hopGeometry -> CompactLineStringUtils.compactLineString(hopGeometry, false))
.toArray(byte[][]::new);
}
/**
* This will copy the geometry from another TripPattern to this one. It checks if each hop is
* between the same stops before copying that hop geometry. If the stops are different but lie
* within same station, old geometry will be used with overwrite on first and last point (to match
* new stop places). Otherwise, it will default to straight lines between hops.
*/
private List generateHopGeometriesFromOriginalTripPattern() {
// This accounts for the new TripPattern provided by a real-time update and the one that is
// being replaced having a different number of stops. In that case the geometry will be
// preserved up until the first mismatching stop, and a straight line will be used for
// all segments after that.
int sizeOfShortestPattern = Math.min(
stopPattern.getSize(),
originalTripPattern.numberOfStops()
);
List hopGeometries = new ArrayList<>();
for (int i = 0; i < sizeOfShortestPattern - 1; i++) {
LineString hopGeometry = originalTripPattern.getHopGeometry(i);
if (hopGeometry != null && stopPattern.sameStops(originalTripPattern.getStopPattern(), i)) {
// Copy hop geometry from previous pattern
hopGeometries.add(originalTripPattern.getHopGeometry(i));
} else if (
hopGeometry != null && stopPattern.sameStations(originalTripPattern.getStopPattern(), i)
) {
// Use old geometry but patch first and last point with new stops
var newStart = new Coordinate(
stopPattern.getStop(i).getCoordinate().longitude(),
stopPattern.getStop(i).getCoordinate().latitude()
);
var newEnd = new Coordinate(
stopPattern.getStop(i + 1).getCoordinate().longitude(),
stopPattern.getStop(i + 1).getCoordinate().latitude()
);
Coordinate[] coordinates = originalTripPattern.getHopGeometry(i).getCoordinates().clone();
coordinates[0].setCoordinate(newStart);
coordinates[coordinates.length - 1].setCoordinate(newEnd);
hopGeometries.add(GeometryUtils.getGeometryFactory().createLineString(coordinates));
} else {
// Create new straight-line geometry for hop
hopGeometries.add(
GeometryUtils
.getGeometryFactory()
.createLineString(
new Coordinate[] {
stopPattern.getStop(i).getCoordinate().asJtsCoordinate(),
stopPattern.getStop(i + 1).getCoordinate().asJtsCoordinate(),
}
)
);
}
}
return hopGeometries;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy