Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correctly calculate elevation profile for partial street edges #2752

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Remove CarFreeAtoZ from list of deployments
- Fix XML response serialization (#2685)
- Refactor InterleavedBidirectionalHeuristic (#2671)
- Correctly calculation elevation profile for partial street edges

## 1.3 (2018-08-03)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.linearref.LocationIndexedLine;
import org.opentripplanner.common.TurnRestriction;
import org.opentripplanner.common.geometry.PackedCoordinateSequence;
import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.util.ElevationUtils;
import org.opentripplanner.routing.vertextype.StreetVertex;
import org.opentripplanner.routing.vertextype.TemporaryVertex;
import org.opentripplanner.util.I18NString;

import java.util.LinkedList;
import java.util.List;


Expand Down Expand Up @@ -68,6 +71,73 @@ public boolean isPartial() {
return true;
}

/**
* Return a subset of the parent elevation profile.
*/
@Override
public PackedCoordinateSequence getElevationProfile() {
PackedCoordinateSequence parentElev = super.getElevationProfile();
if (parentElev == null) return null;

// Compute the linear-reference bounds of the partial edge as fractions of the parent edge
LocationIndexedLine line = new LocationIndexedLine(parentEdge.getGeometry());
double startFraction =line.indexOf(this.getGeometry().getStartPoint().getCoordinate()).getSegmentFraction();
double endFraction = line.indexOf(this.getGeometry().getEndPoint().getCoordinate()).getSegmentFraction();
if (endFraction == 0) endFraction = 1;

double parentDistance = parentEdge.getDistance();
double distanceAdjust = this.getDistance() / ((endFraction - startFraction) * parentDistance);

// Iterate through each entry of the elevation profile for the full parent edge
Coordinate parentElevCoords[] = parentElev.toCoordinateArray();
List<Coordinate> partialElevCoords = new LinkedList<>();
boolean inPartialEdge = false;
double startOffset = startFraction * parentDistance;
for (int i = 1; i < parentElevCoords.length; i++) {
// compute the fraction range covered by this entry in the elevation profile
double x1 = parentElevCoords[i - 1].x;
double x2 = parentElevCoords[i].x;
double y1 = parentElevCoords[i - 1].y;
double y2 = parentElevCoords[i].y;
double f1 = x1 / parentDistance;
double f2 = x2 / parentDistance;
if (f2 > 1) f2 = 1;

// Check if the partial edge begins in current section of the elevation profile
if (startFraction >= f1 && startFraction < f2) {
// Compute and add the interpolated elevation coordinate
double pct = (startFraction - f1) / (f2 - f1);
double x = x1 + pct * (x2 - x1);
double y = y1 + pct * (y2 - y1);
partialElevCoords.add(new Coordinate((x - startOffset) * distanceAdjust, y));

// We are now "in" the partial-edge portion of the parent edge
inPartialEdge = true;
}

// Check if the partial edge ends in current section of the elevation profile
if (endFraction >= f1 && endFraction < f2) {
// Compute and add the interpolated elevation coordinate
double pct = (endFraction - f1) / (f2 - f1);
double x = x1 + pct * (x2 - x1);
double y = y1 + pct * (y2 - y1);
partialElevCoords.add(new Coordinate((x - startOffset) * distanceAdjust, y));

// This is the end of the partial edge, so we can end the iteration
break;
}

if (inPartialEdge) {
Coordinate c = new Coordinate((x2 - startOffset) * distanceAdjust, y2);
partialElevCoords.add(c);
}

}

Coordinate coords[] = partialElevCoords.toArray(new Coordinate[partialElevCoords.size()]);
return new PackedCoordinateSequence.Double(coords, 2);
}

/**
* Have the ID of their parent.
*/
Expand Down