use of org.onebusaway.transit_data_federation.impl.shapes.PointAndIndex in project onebusaway-application-modules by camsys.
the class DistanceAlongShapeLibraryTest method test02.
@Test
public void test02() throws IOException, DistanceAlongShapeException {
ShapePoints shapePoints = readShapePoints("shapes-02.txt");
List<StopTimeEntryImpl> stopTimes = readStopTimes("stops-02.txt");
DistanceAlongShapeLibrary library = new DistanceAlongShapeLibrary();
PointAndIndex[] points = library.getDistancesAlongShape(shapePoints, stopTimes);
assertEquals(4, points.length);
// STOP A
assertEquals(155.4, points[0].distanceAlongShape, 0.1);
assertEquals(1, points[0].index);
// STOP B
assertEquals(816.7, points[1].distanceAlongShape, 0.1);
assertEquals(4, points[1].index);
// STOP C
assertEquals(819.3, points[2].distanceAlongShape, 0.1);
assertEquals(5, points[2].index);
// STOP D
assertEquals(1151.1, points[3].distanceAlongShape, 0.1);
assertEquals(9, points[3].index);
}
use of org.onebusaway.transit_data_federation.impl.shapes.PointAndIndex in project onebusaway-application-modules by camsys.
the class DistanceAlongShapeLibrary method computeBestAssignment.
private List<PointAndIndex> computeBestAssignment(ShapePoints shapePoints, List<StopTimeEntryImpl> stopTimes, List<List<PointAndIndex>> possibleAssignments, UTMProjection projection, List<XYPoint> projectedShapePoints) throws InvalidStopToShapeMappingException {
checkFirstAndLastStop(stopTimes, possibleAssignments, shapePoints, projection, projectedShapePoints);
int startIndex = 0;
int assingmentCount = 1;
/**
* We iterate over each stop, examining its possible assignments. If we find
* a region of stops where the first and last stop have a single assignment
* but the stops in-between have multiple assignments, we compute the best
* assignments for that section. We also handle the edge-cases where the
* multiple potential assignments occur at the start or end of the route.
*/
for (int index = 0; index < possibleAssignments.size(); index++) {
List<PointAndIndex> possibleAssignment = possibleAssignments.get(index);
int count = possibleAssignment.size();
if (count == 0) {
constructErrorForPotentialAssignmentCount(shapePoints, stopTimes, count);
}
boolean hasRegion = index > startIndex;
boolean hasSingleAssignmentFollowingMultipleAssignments = count == 1 && assingmentCount > 1;
boolean hasMultipleAssignmentsAndLastPoint = count > 1 && index == possibleAssignments.size() - 1;
if (hasRegion && (hasSingleAssignmentFollowingMultipleAssignments || hasMultipleAssignmentsAndLastPoint)) {
List<PointAndIndex> currentAssignment = new ArrayList<PointAndIndex>(index - startIndex + 1);
Min<Assignment> bestAssignments = new Min<Assignment>();
recursivelyConstructAssignments(possibleAssignments, currentAssignment, startIndex, startIndex, index + 1, bestAssignments);
if (bestAssignments.isEmpty()) {
constructError(shapePoints, stopTimes, possibleAssignments, projection);
} else {
List<PointAndIndex> bestAssignment = bestAssignments.getMinElement().assigment;
for (int bestIndex = 0; bestIndex < bestAssignment.size(); bestIndex++) {
possibleAssignments.set(startIndex + bestIndex, Arrays.asList(bestAssignment.get(bestIndex)));
}
}
}
if (count == 1) {
startIndex = index;
assingmentCount = 1;
} else {
assingmentCount *= count;
if (assingmentCount > _maximumNumberOfPotentialAssignments) {
constructErrorForPotentialAssignmentCount(shapePoints, stopTimes, assingmentCount);
}
}
}
List<PointAndIndex> bestAssignment = new ArrayList<PointAndIndex>();
for (List<PointAndIndex> possibleAssignment : possibleAssignments) {
if (possibleAssignment.size() != 1) {
String msg = "expected just one assignment at this point, found " + possibleAssignment.size() + "; " + "shapePoint=" + shapePoints.getShapeId() + ", " + "\npossibleAssignments=\n";
for (PointAndIndex pa : possibleAssignment) {
msg += "PointAndIndex(index=" + pa.index + ", point=" + pa.point + ", distanceAlongShape=" + pa.distanceAlongShape + ", distanceFromTarget=" + pa.distanceFromTarget + "), ";
}
msg += "\nstopTime=\n";
for (StopTimeEntryImpl st : stopTimes) {
msg += "StopTimeEntry(Stop(" + st.getStop().getId() + ":" + st.getStop().getStopLat() + ", " + st.getStop().getStopLon() + ")" + ", trip=" + st.getTrip().getId() + "), ";
}
_log.error(msg);
if (!_lenientStopShapeAssignment)
throw new IllegalStateException(msg);
}
bestAssignment.add(possibleAssignment.get(0));
}
return bestAssignment;
}
use of org.onebusaway.transit_data_federation.impl.shapes.PointAndIndex in project onebusaway-application-modules by camsys.
the class DistanceAlongShapeLibrary method recursivelyConstructAssignments.
private void recursivelyConstructAssignments(List<List<PointAndIndex>> possibleAssignments, List<PointAndIndex> currentAssignment, int index, int indexFrom, int indexTo, Min<Assignment> best) {
/**
* If we've made it through ALL assignments, we have a valid assignment!
*/
if (index == indexTo) {
double score = 0;
for (PointAndIndex p : currentAssignment) score += p.distanceFromTarget;
currentAssignment = new ArrayList<PointAndIndex>(currentAssignment);
Assignment result = new Assignment(currentAssignment, score);
best.add(score, result);
return;
}
List<PointAndIndex> possibleAssignmentsForIndex = possibleAssignments.get(index);
List<PointAndIndex> validAssignments = new ArrayList<PointAndIndex>();
double lastDistanceAlongShape = -1;
if (index > indexFrom) {
PointAndIndex prev = currentAssignment.get(index - 1 - indexFrom);
lastDistanceAlongShape = prev.distanceAlongShape;
}
for (PointAndIndex possibleAssignmentForIndex : possibleAssignmentsForIndex) {
if (possibleAssignmentForIndex.distanceAlongShape >= lastDistanceAlongShape)
validAssignments.add(possibleAssignmentForIndex);
}
/**
* There is no satisfying assignment for this search tree, so we return
*/
if (validAssignments.isEmpty()) {
return;
}
/**
* For each valid assignment, pop it onto the current assignment and
* recursively evaluate
*/
for (PointAndIndex validAssignment : validAssignments) {
currentAssignment.add(validAssignment);
recursivelyConstructAssignments(possibleAssignments, currentAssignment, index + 1, indexFrom, indexTo, best);
currentAssignment.remove(currentAssignment.size() - 1);
}
}
use of org.onebusaway.transit_data_federation.impl.shapes.PointAndIndex in project onebusaway-application-modules by camsys.
the class DistanceAlongShapeLibrary method getLastStopSnappedToEndOfShape.
private PointAndIndex getLastStopSnappedToEndOfShape(List<StopTimeEntryImpl> stopTimes, ShapePoints shapePoints, UTMProjection projection, List<XYPoint> projectedShapePoints) {
int i = stopTimes.size() - 1;
StopTimeEntryImpl lastStopTime = stopTimes.get(i);
int lastShapePointIndex = projectedShapePoints.size() - 1;
XYPoint lastShapePoint = projectedShapePoints.get(lastShapePointIndex);
XYPoint stopLocation = projection.forward(lastStopTime.getStop().getStopLocation());
double existingDistanceAlongShape = shapePoints.getDistTraveledForIndex(lastShapePointIndex);
double extraDistanceAlongShape = lastShapePoint.getDistance(stopLocation);
double distanceAlongShape = existingDistanceAlongShape + extraDistanceAlongShape;
double d = lastShapePoint.getDistance(stopLocation);
return new PointAndIndex(lastShapePoint, lastShapePointIndex, d, distanceAlongShape);
}
use of org.onebusaway.transit_data_federation.impl.shapes.PointAndIndex in project onebusaway-application-modules by camsys.
the class DistanceAlongShapeLibrary method computePotentialAssignments.
private List<List<PointAndIndex>> computePotentialAssignments(UTMProjection projection, List<XYPoint> projectedShapePoints, double[] shapePointDistance, List<StopTimeEntryImpl> stopTimes) {
List<List<PointAndIndex>> possibleAssignments = new ArrayList<List<PointAndIndex>>();
for (StopTimeEntryImpl stopTime : stopTimes) {
StopEntryImpl stop = stopTime.getStop();
XYPoint stopPoint = projection.forward(stop.getStopLocation());
List<PointAndIndex> assignments = _shapePointsLibrary.computePotentialAssignments(projectedShapePoints, shapePointDistance, stopPoint, 0, projectedShapePoints.size());
possibleAssignments.add(assignments);
}
return possibleAssignments;
}
Aggregations