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

Add "DIVIDE" command and new "maxslope" and "maxslopecost" parameters #642

Merged
merged 10 commits into from
Jan 17, 2024
34 changes: 32 additions & 2 deletions brouter-core/src/main/java/btools/router/StdPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ protected double processWaySection(RoutingContext rc, double distance, double de
float turncostbase = rc.expctxWay.getTurncost();
float uphillcutoff = rc.expctxWay.getUphillcutoff() * 10000;
float downhillcutoff = rc.expctxWay.getDownhillcutoff() * 10000;
float uphillmaxslope = rc.expctxWay.getUphillmaxslope() * 10000;
float downhillmaxslope = rc.expctxWay.getDownhillmaxslope() * 10000;
float cfup = rc.expctxWay.getUphillCostfactor();
float cfdown = rc.expctxWay.getDownhillCostfactor();
float cf = rc.expctxWay.getCostfactor();
Expand All @@ -60,11 +62,27 @@ protected double processWaySection(RoutingContext rc, double distance, double de
downhillcostdiv = 1000000 / downhillcostdiv;
}

int downhillmaxslopecostdiv = (int) rc.expctxWay.getDownhillmaxslopecost();
if (downhillmaxslopecostdiv > 0) {
downhillmaxslopecostdiv = 1000000 / downhillmaxslopecostdiv;
} else {
// if not given, use legacy behavior
downhillmaxslopecostdiv = downhillcostdiv;
}

uphillcostdiv = (int) rc.expctxWay.getUphillcost();
if (uphillcostdiv > 0) {
uphillcostdiv = 1000000 / uphillcostdiv;
}

int uphillmaxslopecostdiv = (int) rc.expctxWay.getUphillmaxslopecost();
if (uphillmaxslopecostdiv > 0) {
uphillmaxslopecostdiv = 1000000 / uphillmaxslopecostdiv;
} else {
// if not given, use legacy behavior
uphillmaxslopecostdiv = uphillcostdiv;
}

int dist = (int) distance; // legacy arithmetics needs int

// penalty for turning angle
Expand Down Expand Up @@ -99,8 +117,14 @@ protected double processWaySection(RoutingContext rc, double distance, double de
reduce = excess;
}
ehbd -= reduce;
float elevationCost = 0.f;
if (downhillcostdiv > 0) {
int elevationCost = reduce / downhillcostdiv;
elevationCost += Math.min(reduce, dist * downhillmaxslope) / downhillcostdiv;
}
if (downhillmaxslopecostdiv > 0) {
elevationCost += Math.max(0, reduce - dist * downhillmaxslope) / downhillmaxslopecostdiv;
}
if (elevationCost > 0) {
sectionCost += elevationCost;
if (message != null) {
message.linkelevationcost += elevationCost;
Expand All @@ -125,8 +149,14 @@ protected double processWaySection(RoutingContext rc, double distance, double de
reduce = excess;
}
ehbu -= reduce;
float elevationCost = 0.f;
if (uphillcostdiv > 0) {
int elevationCost = reduce / uphillcostdiv;
elevationCost += Math.min(reduce, dist * uphillmaxslope) / uphillcostdiv;
}
if (uphillmaxslopecostdiv > 0) {
elevationCost += Math.max(0, reduce - dist * uphillmaxslope) / uphillmaxslopecostdiv;
}
if (elevationCost > 0) {
sectionCost += elevationCost;
if (message != null) {
message.linkelevationcost += elevationCost;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ final class BExpression {

private static final int ADD_EXP = 20;
private static final int MULTIPLY_EXP = 21;
private static final int MAX_EXP = 22;
private static final int EQUAL_EXP = 23;
private static final int GREATER_EXP = 24;
private static final int MIN_EXP = 25;
private static final int DIVIDE_EXP = 22;
private static final int MAX_EXP = 23;
private static final int EQUAL_EXP = 24;
private static final int GREATER_EXP = 25;
private static final int MIN_EXP = 26;

private static final int SUB_EXP = 26;
private static final int LESSER_EXP = 27;
private static final int XOR_EXP = 28;
private static final int SUB_EXP = 27;
private static final int LESSER_EXP = 28;
private static final int XOR_EXP = 29;

private static final int SWITCH_EXP = 30;
private static final int ASSIGN_EXP = 31;
Expand Down Expand Up @@ -144,6 +145,8 @@ private static BExpression parseRaw(BExpressionContext ctx, int level, String op
exp.typ = AND_EXP;
} else if ("multiply".equals(operator)) {
exp.typ = MULTIPLY_EXP;
} else if ("divide".equals(operator)) {
exp.typ = DIVIDE_EXP;
} else if ("add".equals(operator)) {
exp.typ = ADD_EXP;
} else if ("max".equals(operator)) {
Expand Down Expand Up @@ -277,6 +280,8 @@ public float evaluate(BExpressionContext ctx) {
return op1.evaluate(ctx) - op2.evaluate(ctx);
case MULTIPLY_EXP:
return op1.evaluate(ctx) * op2.evaluate(ctx);
case DIVIDE_EXP:
return divide(op1.evaluate(ctx), op2.evaluate(ctx));
case MAX_EXP:
return max(op1.evaluate(ctx), op2.evaluate(ctx));
case MIN_EXP:
Expand Down Expand Up @@ -360,6 +365,11 @@ private float min(float v1, float v2) {
return v1 < v2 ? v1 : v2;
}

private float divide(float v1, float v2) {
if (v2 == 0f) throw new IllegalArgumentException("div by zero");
return v1 / v2;
}

@Override
public String toString() {
if (typ == NUMBER_EXP) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public final class BExpressionContextWay extends BExpressionContext implements T
private boolean decodeForbidden = true;

private static String[] buildInVariables =
{"costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier", "trafficsourcedensity", "istrafficbackbone", "priorityclassifier", "classifiermask", "maxspeed", "uphillcost", "downhillcost", "uphillcutoff", "downhillcutoff"};
{"costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier", "trafficsourcedensity", "istrafficbackbone", "priorityclassifier", "classifiermask", "maxspeed", "uphillcost", "downhillcost", "uphillcutoff", "downhillcutoff", "uphillmaxslope", "downhillmaxslope", "uphillmaxslopecost", "downhillmaxslopecost"};

protected String[] getBuildInVariableNames() {
return buildInVariables;
Expand Down Expand Up @@ -82,6 +82,22 @@ public float getDownhillcutoff() {
return getBuildInVariable(15);
}

public float getUphillmaxslope() {
return getBuildInVariable(16);
}

public float getDownhillmaxslope() {
return getBuildInVariable(17);
}

public float getUphillmaxslopecost() {
return getBuildInVariable(18);
}

public float getDownhillmaxslopecost() {
return getBuildInVariable(19);
}

public BExpressionContextWay(BExpressionMetaData meta) {
super("way", meta);
}
Expand Down
27 changes: 18 additions & 9 deletions docs/developers/profile_developers_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,16 @@ Some variable names are pre-defined and accessed by the routing engine:

- for the global section these are:

- 7 elevation configuration parameters:
- 11 elevation configuration parameters:

- `downhillcost`
- `downhillcutoff`
- `downhillmaxslope`
- `downhillmaxslopecost`
- `uphillcost`
- `uphillcutoff`
- `uphillmaxslope`
- `uphillmaxslopecost`
- `elevationpenaltybuffer`
- `elevationmaxbuffer`
- `elevationbufferreduce`
Expand Down Expand Up @@ -172,6 +176,7 @@ All expressions have one of the following basic forms:
- `and <boolean expression 1> <boolean expression 2>`
- `xor <boolean expression 1> <boolean expression 2>`
- `multiply <numeric expression 1> <numeric expression 2>`
- `div <numeric expression 1> <numeric expression 2>`
- `add <numeric expression 1> <numeric expression 2>`
- `sub <numeric expression 1> <numeric expression 2>`
- `max <numeric expression 1> <numeric expression 2>`
Expand Down Expand Up @@ -276,33 +281,37 @@ it climbed only 10 m on those 500 m, all 10 m would be *swallowed* by cutoff,
together with up to 5 m from the buffer, if there were any.

When elevation does not fit the buffer of size `elevationmaxbuffer`, it is
converted by up/downhillcost ratio to Elevationcost portion of Equivalentlength.
Up/downhillcostfactors are used, if defined, otherwise costfactor is used.
converted by `up/downhill[maxslope]cost` ratio to Elevationcost portion of Equivalentlength.
`up/downhillcostfactors` are used, if defined, otherwise `costfactor` is used.

- `elevationpenaltybuffer` - default 5(m).

The variable value is used for 2 purposes

- with `buffer content > elevationpenaltybuffer`, it starts partially convert
the buffered elevation to ElevationCost by Up/downhillcost
the buffered elevation to ElevationCost by `up/downhillcost`

- with `elevation taken = MIN (buffer content - elevationpenaltybuffer, WayLength[km] * elevationbufferreduce*10`
Up/downhillcost factor takes place instead of costfactor at the percentage
The `up/downhillcostfactor` takes place instead of `costfactor` at the percentage
of how much is `WayLength[km] * elevationbufferreduce*10` is saturated by
the buffer content above elevationpenaltybuffer.

- `elevationmaxbuffer` - default 10(m)

is the size of the buffer, above which all elevation is converted to
Elevationcost by Up/Downhillcost ratio, and - if defined -
Up/downhillcostfactor fully replaces costfactor in way cost calculation.
Elevationcost by `up/downhill[maxslope]cost` ratio, and - if defined -
`up/downhillcostfactor` fully replaces `costfactor` in way cost calculation.

- `elevationbufferreduce` - default 0(slope%)

is rate of conversion of the buffer content above elevationpenaltybuffer to
ElevationCost. For a way of length L, the amount of converted elevation is
L[km] * elevationbufferreduce[%] * 10. The elevation to Elevationcost
conversion ratio is given by Up/downhillcost.
conversion ratio is given by `up/downhill[maxslope]cost`.

Whether `up/downhillmaxslope` or `up/downhillmaxslopecost` is used as conversion
ratio depends on whether the elevation was accumulated below or above the slope
threshold values defined in `up/downhillmaxslope`.

Example: Let's examine steady slopes with `elevationmaxbuffer=10`,
`elevationpenaltybuffer=5`, `elevationbufferreduce=0.5`, `cutoffs=1.5`,
Expand All @@ -313,7 +322,7 @@ All slopes within 0 .. 1.5% are swallowed by the cutoff.
- For slope 1.75%, there will remain 0.25%.

That saturates the elevationbufferreduce 0.5% by 50%. That gives Way cost to
be calculated 50% from costfactor and 50% from Up/downhillcostfactor.
be calculated 50% from `costfactor` and 50% from `up/downhillcostfactor`.
Additionally, 0.25% gives 2.5m per 1km, converted to 2.5*60 = 150m of
Elevationcost.

Expand Down