| | 1 | | using System; |
| | 2 | |
|
| | 3 | | namespace Itinero.Instructions.Types.Generators; |
| | 4 | |
|
| | 5 | | internal class TurnGenerator : IInstructionGenerator |
| | 6 | | { |
| 9 | 7 | | public string Name { get; } = "turn"; |
| | 8 | |
|
| | 9 | | public BaseInstruction? Generate(IndexedRoute route, int offset) |
| 7 | 10 | | { |
| 7 | 11 | | if (offset == 0 || offset == route.Last) |
| 2 | 12 | | { |
| | 13 | | // We never have a bend at first or as last... |
| 2 | 14 | | return null; |
| | 15 | | } |
| | 16 | | // Okay folks! |
| | 17 | | // We will be walking forward - as long as we are turning in one direction, it is fine! |
| | 18 | |
|
| | 19 | |
|
| 5 | 20 | | var angleDiff = route.DirectionChangeAt(offset); |
| 5 | 21 | | var angleSign = Math.Sign(angleDiff); |
| 5 | 22 | | var usedShapes = 1; |
| | 23 | |
|
| 5 | 24 | | var totalDistance = route.DistanceToNextPoint(offset); |
| | 25 | | // We walk forward and detect a true gentle bend: |
| 5 | 26 | | while (offset + usedShapes < route.Last) |
| 2 | 27 | | { |
| 2 | 28 | | var distance = route.DistanceToNextPoint(offset + usedShapes); |
| 2 | 29 | | if (distance > 5) |
| 2 | 30 | | { |
| | 31 | | // a sharp bend must have pieces that are short |
| 2 | 32 | | break; |
| | 33 | | } |
| | 34 | |
|
| 0 | 35 | | var dAngle = route.DirectionChangeAt(offset + usedShapes); |
| 0 | 36 | | if (Math.Sign(route.DirectionChangeAt(offset + usedShapes)) != angleSign) |
| 0 | 37 | | { |
| | 38 | | // A turn should only go in the same direction as the first angle |
| | 39 | | // Here, it doesn't have that... |
| 0 | 40 | | break; |
| | 41 | | } |
| | 42 | |
|
| 0 | 43 | | totalDistance += distance; |
| 0 | 44 | | angleDiff += dAngle; |
| | 45 | | // We keep the total angle too; as it might turn more then 180° |
| | 46 | | // We do NOT normalize the angle |
| 0 | 47 | | usedShapes++; |
| 0 | 48 | | } |
| | 49 | |
|
| | 50 | |
|
| | 51 | | // A turn does turn, at least a few degrees per meter |
| 5 | 52 | | if (Math.Abs(angleDiff) < 45) |
| 2 | 53 | | { |
| | 54 | | // There is little change - does it at least turn a bit? |
| 2 | 55 | | if (Math.Abs(angleDiff) / totalDistance < 2.5) |
| 2 | 56 | | { |
| | 57 | | // Nope, we turn only 2.5° per meter - that isn't a lot |
| 2 | 58 | | return null; |
| | 59 | | } |
| 0 | 60 | | } |
| | 61 | |
|
| 3 | 62 | | return new TurnInstruction( |
| 3 | 63 | | route, |
| 3 | 64 | | offset, |
| 3 | 65 | | offset + usedShapes - 1, |
| 3 | 66 | | angleDiff |
| 3 | 67 | | ); |
| 7 | 68 | | } |
| | 69 | | } |