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 void testTriangle() { Coordinate c1 = new Coordinate(-122.575033, 45.456773); Coordinate c2 = new Coordinate(-122.576668, 45.451426); Vertex v1 = new Vertex("v1", c1, null); Vertex v2 = new Vertex("v2", c2, null); GeometryFactory factory = new GeometryFactory(); LineString geometry = factory.createLineString(new Coordinate[] {c1, c2}); double length = 650.0; PlainStreetEdge testStreet = new PlainStreetEdge( v1, v2, geometry, "Test Lane", length, StreetTraversalPermission.ALL, false); testStreet.setBicycleSafetyEffectiveLength(length * 0.74); // a safe street Coordinate[] profile = new Coordinate[] { new Coordinate(0, 0), // slope = 0.1 new Coordinate(length / 2, length / 20.0), new Coordinate(length, 0) // slope = -0.1 }; PackedCoordinateSequence elev = new PackedCoordinateSequence.Double(profile); testStreet.setElevationProfile(elev); double trueLength = ElevationUtils.getLengthMultiplierFromElevation(elev) * length; testStreet.setSlopeSpeedEffectiveLength(trueLength); // normalize length SlopeCosts costs = ElevationUtils.getSlopeCosts(elev, "test"); TraverseOptions options = new TraverseOptions(TraverseMode.BICYCLE); options.optimizeFor = OptimizeType.TRIANGLE; options.speed = 6.0; options.walkReluctance = 1; options.setTriangleSafetyFactor(0); options.setTriangleSlopeFactor(0); options.setTriangleTimeFactor(1); State startState = new State(v1, options); State result = testStreet.traverse(startState); double timeWeight = result.getWeight(); double expectedSpeedWeight = trueLength / options.speed; assertEquals(expectedSpeedWeight, timeWeight); options.setTriangleSafetyFactor(0); options.setTriangleSlopeFactor(1); options.setTriangleTimeFactor(0); startState = new State(v1, options); result = testStreet.traverse(startState); double slopeWeight = result.getWeight(); assertTrue(length * 1.5 / options.speed < slopeWeight); assertTrue(length * 1.5 * 10 / options.speed > slopeWeight); options.setTriangleSafetyFactor(1); options.setTriangleSlopeFactor(0); options.setTriangleTimeFactor(0); startState = new State(v1, options); result = testStreet.traverse(startState); double safetyWeight = result.getWeight(); double slopeSafety = costs.slopeSafetyCost; double expectedSafetyWeight = (trueLength * 0.74 + slopeSafety) / options.speed; assertTrue(expectedSafetyWeight - safetyWeight < 0.00001); final double ONE_THIRD = 1 / 3.0; options.setTriangleSafetyFactor(ONE_THIRD); options.setTriangleSlopeFactor(ONE_THIRD); options.setTriangleTimeFactor(ONE_THIRD); startState = new State(v1, options); result = testStreet.traverse(startState); double averageWeight = result.getWeight(); assertTrue( Math.abs( safetyWeight * ONE_THIRD + slopeWeight * ONE_THIRD + timeWeight * ONE_THIRD - averageWeight) < 0.00000001); }