GIScience / openrouteservice

🌍 The open source route planner api with plenty of features.
https://openrouteservice.org
GNU General Public License v3.0
1.43k stars 392 forks source link

HGV specific restrictions fail when their value > 12.8 #263

Closed aoles closed 5 years ago

aoles commented 6 years ago

HGV restrictions such as maxweight are encoded as byte values after parsing the original OSM value as double and multiplying it by 10. This causes values > 12.8 to exceed the Byte.MAX_VALUE limit such that they cannot be reliably stored and retrieved.

As an example consider the Neckar bridge in Ziegelhausen tagged with maxweight=20. Even after setting weight=100 the route passing the bridge is still returned: https://maps.openrouteservice.org/directions?n1=49.412586&n2=8.760492&n3=16&a=49.416111,8.756747,49.416725,8.765202&b=4a&c=0&f1=100&k1=en-US&k2=km

As counter example see e.g. the weight restriction of 12t on Hebelstrasse which is properly resolved: https://maps.openrouteservice.org/directions?n1=49.397391&n2=8.685009&n3=17&a=49.396193,8.685561,49.397136,8.679907&b=4a&c=0&f1=100&k1=en-US&k2=km

aoles commented 6 years ago

For example in the Karlsruhe region there are 189 cases when the hgv restriction values exceed the available byte data range (mostly for maxweight but for maxlength too)

aoles commented 6 years ago

As the restrictions are positive values which normally don't exceed 100, and usually they are well defined by 2 significant digits, a possible way of packing them into byte values would involve the following transformation which uses (almost) the whole available range by storing the digit after decimal point only for values < 17, and for the greater ones just the decimal part.

if (x <= 17)
  x = x * 10 - 127
else
  x = x + 26

The transformation in the opposite direction from byte encoded values int doubles would then be

if (x >= 44)
  x = x - 26
else
  (x + 127) / 10

The switching point could be probably tuned to make use of byte shifting.

aoles commented 5 years ago

Moved to 4.7.2 because the fix requires updating the graph builders, so more time is needed to test this properly.

aoles commented 5 years ago

In order to be able to almost fully cover all possible values, such as maxaxleload=22.5 or maxwidth=2.49, I've decided to increase the external storage dedicated for each of the maxheight, maxwidth, maxlength, maxweight and maxaxleload restrictions from one to two bytes. In the new approach the OSM string values after being parsed to doubles are multiplied by 100 and stored as shorts. This allows for covering a range from 0 to 327.67 with a resolution of 0.01 across the whole range. The increased accuracy will also improve handling of values originally provided in imperial units.

rabidllama commented 5 years ago

Should be fixed now that we have updated to 4.7.2