public String toString() { String out = ""; if (elevationProfile == null || elevationProfile.size() == 0) { return "(empty elevation profile)"; } for (int i = 0; i < elevationProfile.size(); ++i) { Coordinate coord = elevationProfile.getCoordinate(i); out += "(" + coord.x + "," + coord.y + "), "; } return out.substring(0, out.length() - 2); }
public boolean setElevationProfile( PackedCoordinateSequence elev, boolean computed, boolean slopeLimit) { if (elev == null || elev.size() < 2) { return false; } if (slopeOverride && !computed) { return false; } elevationProfile = elev; // compute the various costs of the elevation changes double lengthMultiplier = ElevationUtils.getLengthMultiplierFromElevation(elev); if (Double.isNaN(lengthMultiplier)) { LOG.error("lengthMultiplier from elevation profile is NaN, setting to 1"); lengthMultiplier = 1; } length *= lengthMultiplier; bicycleSafetyEffectiveLength *= lengthMultiplier; SlopeCosts costs = ElevationUtils.getSlopeCosts(elev, slopeLimit); slopeSpeedEffectiveLength = costs.slopeSpeedEffectiveLength; maxSlope = costs.maxSlope; slopeWorkCost = costs.slopeWorkCost; bicycleSafetyEffectiveLength += costs.slopeSafetyCost; flattened = costs.flattened; return costs.flattened; }
public static PackedCoordinateSequence getPartialElevationProfile( PackedCoordinateSequence elevationProfile, double start, double end) { if (elevationProfile == null) { return null; } List<Coordinate> coordList = new LinkedList<Coordinate>(); if (start < 0) start = 0; Coordinate[] coordinateArray = elevationProfile.toCoordinateArray(); double length = coordinateArray[coordinateArray.length - 1].x; if (end > length) end = length; boolean started = false; boolean finished = false; Coordinate lastCoord = null; for (Coordinate coord : coordinateArray) { if (coord.x >= start && coord.x <= end) { coordList.add(new Coordinate(coord.x - start, coord.y)); if (!started) { started = true; if (lastCoord == null) { // no need to interpolate as this is the first coordinate continue; } // interpolate start coordinate double run = coord.x - lastCoord.x; if (run < 1) { // tiny runs are likely to lead to errors, so we'll skip them continue; } double p = (coord.x - start) / run; double rise = coord.y - lastCoord.y; Coordinate interpolatedStartCoordinate = new Coordinate(0, lastCoord.y + p * rise); coordList.add(0, interpolatedStartCoordinate); } } else if (coord.x > end && !finished && started && lastCoord != null) { finished = true; // interpolate end coordinate double run = coord.x - lastCoord.x; if (run < 1) { // tiny runs are likely to lead to errors, so we'll skip them continue; } double p = (end - lastCoord.x) / run; double rise = coord.y - lastCoord.y; Coordinate interpolatedEndCoordinate = new Coordinate(end, lastCoord.y + p * rise); coordList.add(interpolatedEndCoordinate); } lastCoord = coord; } Coordinate coordArr[] = new Coordinate[coordList.size()]; return new PackedCoordinateSequence.Float(coordList.toArray(coordArr), 2); }
/** * Adjusts an Itinerary's elevation fields from an elevation profile * * @return the elevation at the end of the profile */ private double applyElevation( PackedCoordinateSequence profile, Itinerary itinerary, double previousElevation) { if (profile != null) { for (Coordinate coordinate : profile.toCoordinateArray()) { if (previousElevation == Double.MAX_VALUE) { previousElevation = coordinate.y; continue; } double elevationChange = previousElevation - coordinate.y; if (elevationChange > 0) { itinerary.elevationGained += elevationChange; } else { itinerary.elevationLost -= elevationChange; } previousElevation = coordinate.y; } } return previousElevation; }
public static SlopeCosts getSlopeCosts(PackedCoordinateSequence elev, String name) { Coordinate[] coordinates = elev.toCoordinateArray(); double maxSlope = 0; double slopeSpeedEffectiveLength = 0; double slopeWorkCost = 0; double slopeSafetyCost = 0; for (int i = 0; i < coordinates.length - 1; ++i) { double run = coordinates[i + 1].x - coordinates[i].x; double rise = coordinates[i + 1].y - coordinates[i].y; if (run == 0) { continue; } double slope = rise / run; if (slope > 0.35 || slope < -0.35) { slope = 0; // Baldwin St in Dunedin, NZ, is the steepest street // on earth, and has a // grade of 35%. So, this must be a data error. log.warn( "Warning: street " + name + " steeper than Baldwin Street. This is an error in the algorithm or the data"); } if (maxSlope < Math.abs(slope)) { maxSlope = Math.abs(slope); } double slope_or_zero = Math.max(slope, 0); double hypotenuse = Math.sqrt(rise * rise + run * run); double energy = hypotenuse * (ENERGY_PER_METER_ON_FLAT + ENERGY_SLOPE_FACTOR * slope_or_zero * slope_or_zero * slope_or_zero); slopeWorkCost += energy; slopeSpeedEffectiveLength += hypotenuse / slopeSpeedCoefficient(slope, coordinates[i].y); // assume that speed and safety are inverses double safetyCost = hypotenuse * (slopeSpeedCoefficient(slope, coordinates[i].y) - 1) * 0.25; if (safetyCost > 0) { slopeSafetyCost += safetyCost; } } return new SlopeCosts(slopeSpeedEffectiveLength, slopeWorkCost, slopeSafetyCost, maxSlope); }