org.opentripplanner.analyst.scenario.AddTripPattern Maven / Gradle / Ivy
package org.opentripplanner.analyst.scenario;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.LineString;
import org.onebusaway.gtfs.model.Route;
import org.opentripplanner.analyst.core.Sample;
import org.opentripplanner.analyst.request.SampleFactory;
import org.opentripplanner.model.json_serialization.*;
import org.opentripplanner.routing.graph.Graph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.BitSet;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
/** Add a trip pattern */
public class AddTripPattern extends Modification {
public static final long serialVersionUID = 1L;
public static final Logger LOG = LoggerFactory.getLogger(AddTripPattern.class);
/** The name of this pattern */
public String name;
/** The geometry of this pattern */
@JsonDeserialize(using = EncodedPolylineJSONDeserializer.class)
@JsonSerialize(using = EncodedPolylineJSONSerializer.class)
public LineString geometry;
/** What coordinate indices should be stops */
@JsonDeserialize(using = BitSetDeserializer.class)
@JsonSerialize(using = BitSetSerializer.class)
public BitSet stops;
/** The timetables for this trip pattern */
public Collection timetables;
/** used to store the indices of the temporary stops in the graph */
public transient TemporaryStop[] temporaryStops;
/** GTFS mode (route_type), see constants at https://developers.google.com/transit/gtfs/reference/#routestxt */
public int mode = 3;
/** Create temporary stops associated with the given graph. Note that a given AddTripPattern can be associated only with a single graph. */
public void materialize (Graph graph) {
SampleFactory sfac = graph.getSampleFactory();
temporaryStops = new TemporaryStop[stops.cardinality()];
int stop = 0;
for (int i = stops.nextSetBit(0); i >= 0; i = stops.nextSetBit(i + 1)) {
temporaryStops[stop++] = new TemporaryStop(geometry.getCoordinateN(i), sfac);
}
}
@Override
public String getType() {
return "add-trip-pattern";
}
/** a class representing a minimal timetable */
public static class PatternTimetable implements Serializable {
/** hop times in seconds */
public int[] hopTimes;
/** dwell times in seconds */
public int[] dwellTimes;
/** is this a frequency entry? */
public boolean frequency;
/** start time (seconds since GTFS midnight) */
public int startTime;
/** end time for frequency-based trips (seconds since GTFS midnight) */
public int endTime;
/** headway for frequency-based patterns */
public int headwaySecs;
/** What days is this active on (starting with Monday at 0)? */
@JsonDeserialize(using = BitSetDeserializer.class)
@JsonSerialize(using = BitSetSerializer.class)
public BitSet days;
}
/** A class representing a stop temporarily in the graph */
public static class TemporaryStop {
/** The indices of temporary stops are negative numbers to avoid clashes with the positive (vertex) indices of permanent stops. Note that code in RaptorWorkerData depends on these being negative. */
private static AtomicInteger nextId = new AtomicInteger(-1);
/** the index of this stop in the graph */
public final int index;
/** The latitude of this stop */
public final double lat;
/** The longitude of this stop */
public final double lon;
/** how this vertex is connected to the graph */
public final Sample sample;
public TemporaryStop (Coordinate c, SampleFactory sampleFactory) {
this(c.y, c.x, sampleFactory);
}
public TemporaryStop (double lat, double lon, SampleFactory sampleFactory) {
this.lat = lat;
this.lon = lon;
this.index = nextId.decrementAndGet();
this.sample = sampleFactory.getSample(this.lon, this.lat);
if (this.sample == null)
LOG.warn("Temporary stop unlinked: {}", this);
}
public String toString () {
return "Temporary stop at " + this.lat + ", " + this.lon;
}
}
}