routers 0.2.7

Rust-Based Routing Tooling for System-Agnostic Maps.
Documentation
use crate::transition::Trip;
use routers_codec::osm::OsmEntryId;

use approx::assert_relative_eq;
use geo::wkt;
use routers_network::Node;

const SHARED_DISTANCE: f64 = 900.0;

#[test]
fn test_trip() {
    use geo::Point;

    let nodes: Vec<Node<OsmEntryId>> = vec![
        Node::new(Point::new(0.0, 0.0), OsmEntryId::null()),
        Node::new(Point::new(0.0, 1.0), OsmEntryId::null()),
        Node::new(Point::new(1.0, 1.0), OsmEntryId::null()),
        Node::new(Point::new(1.0, 0.0), OsmEntryId::null()),
        Node::new(Point::new(1.0, -1.0), OsmEntryId::null()),
    ];

    let trip = Trip::from(nodes);

    let angles = trip.headings();
    assert_relative_eq!(angles[0], 0.0);
    assert_relative_eq!(angles[1], 90.0, max_relative = 1.0);
    assert_relative_eq!(angles[2], 180.0);
    assert_relative_eq!(angles[3], 180.0);

    assert_relative_eq!(trip.total_angle(), 180.0);
}

#[test]
fn validate_segment() {
    let linestring = wkt! {
        LINESTRING (-118.618033 34.166292, -118.623419 34.164641, -118.626895 34.163434)
    };

    let nodes = linestring
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()))
        .collect::<Vec<_>>();

    let trip = Trip::from(nodes);

    let angle = trip.total_angle();
    assert_relative_eq!(angle, 2.44, max_relative = 0.1);

    let imm_angle = trip.immediate_angle().abs();
    assert_relative_eq!(imm_angle, 0.81, max_relative = 0.1);

    let exp_angle = trip.angular_complexity();
    assert_relative_eq!(exp_angle, 0.95, max_relative = 0.1);
}

#[test]
fn validate_turning_path() {
    let linestring = wkt! {
        LINESTRING (-118.61829 34.166594, -118.623312 34.164996, -118.62329 34.164073, -118.624127 34.163896, -118.624449 34.163736, -118.625554 34.163461, -118.625929 34.163327, -118.626637 34.162928)
    };

    let nodes = linestring
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));

    let trip = Trip::new(nodes);

    let angle = trip.total_angle();
    assert_relative_eq!(angle, 195.30, max_relative = 0.1);

    let imm_angle = trip.immediate_angle().abs();
    assert_relative_eq!(imm_angle, 24.41, max_relative = 0.1);

    let exp_angle = trip.angular_complexity();
    assert_relative_eq!(exp_angle, 0.76, max_relative = 0.1);
}

#[test]
fn validate_uturn_expensive() {
    let linestring = wkt! {
        LINESTRING (-118.509833 34.170873, -118.505648 34.170891, -118.51406 34.170908, -118.509849 34.170926, -118.509865 34.172293)
    };

    let nodes = linestring
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));

    let trip = Trip::new(nodes);

    let length = trip.length();
    assert_relative_eq!(length, 1698.0, max_relative = 0.1);

    let angle = trip.total_angle();
    assert_relative_eq!(angle, 449.40, max_relative = 0.1);

    // Discouragingly complex
    let imm_angle = trip.angular_complexity();
    assert_relative_eq!(imm_angle, 0., max_relative = 0.1);
}

#[test]
fn validate_through_lower_cost() {
    let linestring_through_trip = wkt! {
        LINESTRING (-118.236761 33.945685, -118.236447 33.945696, -118.236341 33.945703, -118.23623 33.945723, -118.236133 33.945751, -118.236041 33.945797, -118.235908 33.945868, -118.235774 33.94596, -118.235509 33.946225, -118.235419 33.946304, -118.235322 33.946382, -118.235192 33.946447, -118.235031 33.946503, -118.234928 33.946525, -118.234797 33.946538, -118.234501 33.946542)
    };

    let linestring_around_trip = wkt! {
        LINESTRING (-118.236761 33.945685, -118.236759 33.946891, -118.236759 33.946891, -118.236758 33.947095, -118.235875 33.947112, -118.235546 33.947118, -118.235546 33.947118, -118.234899 33.947131, -118.234483 33.947139, -118.234501 33.946542)
    };

    let nodes = linestring_through_trip
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));
    let through = Trip::new(nodes);

    let nodes = linestring_around_trip
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));
    let around = Trip::new(nodes);

    const SHARED_DISTANCE: f64 = 227.;

    let imm_angle = around.angular_complexity();
    assert_relative_eq!(imm_angle, 0.56, max_relative = 0.1);

    let imm_angle = through.angular_complexity();
    assert_relative_eq!(imm_angle, 0.99, max_relative = 0.1);

    let len = around.length();
    assert_relative_eq!(len, 433.0, max_relative = 0.1);

    let len = through.length();
    assert_relative_eq!(len, 241.52, max_relative = 0.1);
}

#[test]
fn validate_slip_road_optimality() {
    use crate::transition::Trip;

    let linestring_sliproad = wkt! {
        LINESTRING (-118.138707 33.917051, -118.13859 33.917027, -118.138402 33.916998, -118.138172 33.916897, -118.138106 33.916837, -118.138078 33.916778, -118.138076 33.916697, -118.138251 33.916449, -118.138268 33.916424)
    };

    let linestring_around = wkt! {
        LINESTRING (-118.138707 33.917051, -118.13859 33.917027, -118.138402 33.916998, -118.138174 33.916984, -118.137992 33.916977, -118.137992 33.916977, -118.137881 33.916973, -118.138076 33.916697, -118.138251 33.916449, -118.138273 33.916417)
    };

    let nodes = linestring_sliproad
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));
    let sliproad = Trip::new(nodes);

    let nodes = linestring_around
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));
    let around = Trip::new(nodes);

    const SHARED_DISTANCE: f64 = 90.;

    let tot_angle = sliproad.total_angle();
    assert_relative_eq!(tot_angle, 114.1, max_relative = 0.1);

    let tot_angle = around.total_angle();
    assert_relative_eq!(tot_angle, 129.97, max_relative = 0.1);

    let imm_angle = around.angular_complexity();
    assert_relative_eq!(imm_angle, 0.0, max_relative = 0.1);

    let imm_angle = sliproad.angular_complexity();
    assert_relative_eq!(imm_angle, 0.96, max_relative = 0.1);

    let len = around.length();
    assert_relative_eq!(len, 148.5, max_relative = 0.1);

    let len = sliproad.length();
    assert_relative_eq!(len, 113.0, max_relative = 0.1);
}

#[test]
fn analyse_cost() {
    let linestring = wkt! {
        LINESTRING(151.18064990000005 -33.905052799999986,151.18070819999963 -33.905169800000344,151.18070819999963 -33.905169800000344,151.18086930000004 -33.9055141,151.18086930000004 -33.9055141,151.18090719999984 -33.90559339999998,151.18090719999984 -33.90559339999998,151.18094959999962 -33.90568200000043,151.18094959999962 -33.90568200000043,151.18103189999988 -33.90585909999962,151.18103189999988 -33.90585909999962,151.18104849999983 -33.90589269999998,151.18104849999983 -33.90589269999998,151.18106179999984 -33.90591879999998,151.18106179999984 -33.90591879999998,151.1813739999998 -33.90660519999986,151.1813739999998 -33.90660519999986,151.1813864999998 -33.90663029999992,151.1813864999998 -33.90663029999992,151.1814165999996 -33.90669080000043,151.1814165999996 -33.90669080000043,151.1814724999998 -33.906742999999864,151.1814724999998 -33.906742999999864,151.1814967999998 -33.906765699999916,151.1814967999998 -33.906765699999916,151.18154590000012 -33.90686859999996,151.18154590000012 -33.90686859999996,151.18155790000014 -33.90692399999996,151.18155790000014 -33.90692399999996,151.18157819999982 -33.90703049999995,151.18157819999982 -33.90703049999995,151.18157960000013 -33.907060299999955,151.18157960000013 -33.907060299999955,151.18158290000014 -33.90712769999996,151.18158290000014 -33.90712769999996,151.1815839000002 -33.90718219999998,151.1815839000002 -33.90718219999998,151.18144600000016 -33.907155299999964,151.18144600000016 -33.907155299999964,151.1814532000003 -33.90706179999995)
    };

    let nodes = linestring
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));
    let trip = Trip::new(nodes);

    let complexity = trip.angular_complexity();
    assert_relative_eq!(complexity, 0.68, max_relative = 0.1);
}

#[test]
fn analyse_cost2() {
    let linestring = wkt! {
        LINESTRING(151.18064990000005 -33.905052799999986,151.18070819999963 -33.905169800000344,151.18070819999963 -33.905169800000344,151.18086930000004 -33.9055141,151.18086930000004 -33.9055141,151.18090719999984 -33.90559339999998,151.18090719999984 -33.90559339999998,151.18094959999962 -33.90568200000043,151.18094959999962 -33.90568200000043,151.18103189999988 -33.90585909999962,151.18103189999988 -33.90585909999962,151.18104849999983 -33.90589269999998,151.18104849999983 -33.90589269999998,151.18106179999984 -33.90591879999998,151.18106179999984 -33.90591879999998,151.1813739999998 -33.90660519999986,151.1813739999998 -33.90660519999986,151.1813864999998 -33.90663029999992,151.1813864999998 -33.90663029999992,151.1814165999996 -33.90669080000043,151.1814165999996 -33.90669080000043,151.1814724999998 -33.906742999999864,151.1814724999998 -33.906742999999864,151.1814967999998 -33.906765699999916,151.1814967999998 -33.906765699999916,151.18154590000012 -33.90686859999996,151.18154590000012 -33.90686859999996,151.1816426000002 -33.90698009999998,151.1816426000002 -33.90698009999998,151.1816914000002 -33.907027399999976,151.1816914000002 -33.907027399999976,151.18171760000018 -33.90704789999998,151.18171760000018 -33.90704789999998,151.1817446000003 -33.90706209999995,151.1817446000003 -33.90706209999995,151.18178040000018 -33.907072599999964,151.18178040000018 -33.907072599999964,151.1819206000004 -33.907030799999774,151.1819206000004 -33.907030799999774,151.18205480000015 -33.90698719999997,151.18205480000015 -33.90698719999997,151.18217080000042 -33.90696129999977,151.18217080000042 -33.90696129999977,151.18228580000016 -33.906941999999965,151.18228580000016 -33.906941999999965,151.1824249000004 -33.90692949999978,151.1824249000004 -33.90692949999978,151.18254500000015 -33.906928599999965,151.18254500000015 -33.906928599999965,151.18263230000025 -33.9069372000001,151.18263230000025 -33.9069372000001,151.1826744000002 -33.90694129999998,151.1826744000002 -33.90694129999998,151.18286189999984 -33.90696769999995,151.18286189999984 -33.90696769999995,151.18306010000015 -33.90699009999996,151.18306010000015 -33.90699009999996,151.18327180000017 -33.90703279999996,151.18327180000017 -33.90703279999996,151.18302770000017 -33.90703229999996,151.18302770000017 -33.90703229999996,151.18282790000018 -33.90702669999997,151.18282790000018 -33.90702669999997,151.18269839999982 -33.90702639999995,151.18269839999982 -33.90702639999995,151.18256139999983 -33.90703109999995,151.18256139999983 -33.90703109999995,151.18242359999982 -33.90703949999995,151.18242359999982 -33.90703949999995,151.18226560000016 -33.90705399999996,151.18226560000016 -33.90705399999996,151.18211229999983 -33.90706109999995,151.18211229999983 -33.90706109999995,151.18203139999986 -33.90707569999995,151.18203139999986 -33.90707569999995,151.1819356000002 -33.90710009999998,151.1819356000002 -33.90710009999998,151.18185060000016 -33.90712689999996,151.18185060000016 -33.90712689999996,151.18169679999983 -33.90717059999995)
    };

    let nodes = linestring
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));
    let trip = Trip::new(nodes);

    let complexity = trip.angular_complexity();
    assert_relative_eq!(complexity, 0., max_relative = 0.1);
}

#[test]
fn analyse_cost3() {
    let linestring = wkt! {
        LINESTRING(151.19106219999895 -33.90324030000019,151.19114050000033 -33.903136900000014,151.19114050000033 -33.903136900000014,151.19112239999896 -33.9031260000002,151.19112239999896 -33.9031260000002,151.19110859999896 -33.9031113000002,151.19110859999896 -33.9031113000002,151.19110030000027 -33.903094000000024,151.19110030000027 -33.903094000000024,151.19109809999895 -33.9030754000002,151.19109809999895 -33.9030754000002,151.19110220000033 -33.90305710000001,151.19110220000033 -33.90305710000001,151.19111220000025 -33.90304050000002,151.19111220000025 -33.90304050000002,151.19112969999895 -33.903025300000195,151.19112969999895 -33.903025300000195,151.19115199999897 -33.90301540000019,151.19115199999897 -33.90301540000019,151.19117699999896 -33.90301180000019,151.19117699999896 -33.90301180000019,151.19120200000032 -33.903014900000024,151.19120200000032 -33.903014900000024,151.1912246000003 -33.90302430000003,151.1912246000003 -33.90302430000003,151.19124260000027 -33.90303910000002,151.19124260000027 -33.90303910000002,151.19129360000002 -33.9029905,151.19129360000002 -33.9029905,151.19132969999947 -33.90295480000014,151.19132969999947 -33.90295480000014,151.19136500000002 -33.902918700000136,151.19136500000002 -33.902918700000136,151.19152799999958 -33.90273960000017,151.19152799999958 -33.90273960000017,151.19214730000013 -33.9020587,151.19214730000013 -33.9020587,151.1921603999998 -33.90204429999985,151.1921603999998 -33.90204429999985,151.19223609999977 -33.901961800000095,151.19223609999977 -33.901961800000095,151.19229550000014 -33.9018959)
    };

    let nodes = linestring
        .into_points()
        .into_iter()
        .map(|p| Node::new(p, OsmEntryId::null()));
    let trip = Trip::new(nodes);

    let complexity = trip.angular_complexity();
    assert_relative_eq!(complexity, 0.80, max_relative = 0.1);
}