예제 #1
0
def test_inverse_vs_geographiclib():
    glib = Geodesic.WGS84

    lats = np.arange(-90, 90, 45)
    lons = np.arange(-180, 180, 30)
    vp1 = [(p1, p2) for p1 in lats for p2 in lons]
    vp2 = [(12.5, 175.2) for _ in range(len(vp1))]

    g1s = [glib.Inverse(*vp1[i], *vp2[i]) for i in range(len(vp1))]
    g2s = geod.inverse(*list(zip(*vp1)), *list(zip(*vp2)))
    s12 = [g1s[i]['s12'] for i in range(len(g1s))]
    azi1 = [g1s[i]['azi1'] for i in range(len(g1s))]

    np.testing.assert_allclose(g2s['s12'], s12, rtol=1e-3, atol=1e-3)
    np.testing.assert_allclose(
        g2s['azi1'], utils.wrap360deg(np.asarray(azi1)), rtol=1e-3, atol=1e-3
    )

    # test equal longitudes
    lats = np.arange(-89, 89, 45)
    lons = np.arange(-179, 179, 90)
    vp1 = [(p1, p2) for p1 in lats for p2 in lons]
    vp2 = [(0, p2) for _ in lats for p2 in lons]

    g1s = [glib.Inverse(*vp1[i], *vp2[i]) for i in range(len(vp1))]
    g2s = geod.inverse(*list(zip(*vp1)), *list(zip(*vp2)))
    s12 = [g1s[i]['s12'] for i in range(len(g1s))]
    azi1 = [g1s[i]['azi1'] for i in range(len(g1s))]

    np.testing.assert_allclose(g2s['s12'], s12, rtol=1e-5, atol=1e-5)
    np.testing.assert_allclose(
        g2s['azi1'], utils.wrap360deg(np.asarray(azi1)), rtol=1e-3, atol=1e-3
    )

    # test close longitudes
    vp1 = [
        (0, -179.99999),
        (0, -179.9999999),
        (0, -179.9999999),
        (0, 179.9999999),
        (12.5, 179.9999999),
        (12.99999999, 175),
        (0, 178.9999999),
    ]
    vp2 = [
        (0, 180),
        (0, -180),
        (0, 180),
        (0, 180),
        (12.5, 180),
        (13, 175),
        (0, 179.9999999),
    ]

    g1s = [glib.Inverse(*vp1[i], *vp2[i]) for i in range(len(vp1))]
    g2s = geod.inverse(*list(zip(*vp1)), *list(zip(*vp2)))
    s12 = [g1s[i]['s12'] for i in range(len(g1s))]
    np.testing.assert_allclose(g2s['s12'], s12, rtol=1, atol=1e-2)
예제 #2
0
def get_gcr_points(lat1, lon1, lat2, lon2, n_points=10):
    """Discretize gcr between two scalar coordinate points."""
    points = [(lat1, lon1)]

    inv = geod.inverse([lat1], [lon1], [lat2], [lon2])
    dist = inv['s12'] / (n_points)

    for i in range(n_points):
        dir = geod.direct(lat1, lon1, inv['azi1'], dist)
        points.append((dir['lat2'][0], dir['lon2'][0]))
        lat1 = dir['lat2'][0]
        lon1 = dir['lon2'][0]
        inv = geod.inverse([lat1], [lon1], [lat2], [lon2])

    return points
예제 #3
0
def test_inverse_base(expect):
    r = geod.inverse(
        [-90, -89, 0, 89, 90, 0, 0],
        [-180, -170, 0, 150, 180, 0, -180],
        [90, 89, 0, -89, -90, 0, 0],
        [180, 170, 0, -150, -180, -180, 180],
    )
    t = {
        's12': [
            20003931.4586233,
            19783938.13763718,
            0.0,
            19810477.039079,
            20003931.4586233,
            20003931.4586233,
            0.0,
        ],
        'azi1': [0.0, 349.99759033, 0, 149.99358, 0.0, 0.0, 0],
        'azi2': [180.0, 349.99759033, 0, 149.99358, 180.0, 180.0, 0],
        'iterations': 3,
    }
    np.testing.assert_allclose(r['s12'], t['s12'], rtol=1e-7, atol=1e-7)
    np.testing.assert_allclose(r['azi1'], t['azi1'], rtol=1e-7, atol=1e-7)
    np.testing.assert_allclose(r['azi2'], t['azi2'], rtol=1e-7, atol=1e-7)
    expect(r['iterations']) == t['iterations']
예제 #4
0
def test_direct_large_size():
    np.random.seed(42)
    lats1 = np.random.uniform(-90, 90, 100000)
    lons1 = np.random.uniform(-180, 180, 100000)
    brgs = np.random.uniform(0, 360, 100000)
    dist = np.random.uniform(0, 20e6, 100000)
    _ = geod.inverse(lats1, lons1, brgs, dist)
예제 #5
0
def test_inverse_large_size():
    np.random.seed(42)
    lats1 = np.random.uniform(-90, 90, 100000)
    lons1 = np.random.uniform(-180, 180, 100000)
    lats2 = np.random.uniform(-90, 90, 100000)
    lons2 = np.random.uniform(-180, 180, 100000)
    _ = geod.inverse(lats1, lons1, lats2, lons2)
예제 #6
0
    def test_recursive_routing(self):
        """Unit test."""

        start = (43.5, 7.2)
        finish = (33.8, 35.5)
        start_time = dt.datetime.strptime('2020111607', '%Y%m%d%H')

        gcr = geod.inverse([start[0]], [start[1]], [finish[0]], [finish[1]])

        iso = isochrone.Isochrone(
            count=0,
            start=start,
            finish=finish,
            gcr_azi=gcr['azi1'],
            lats1=np.array([[start[0]]]),
            lons1=np.array([[start[1]]]),
            azi12=np.array([[None]]),
            s12=np.array([[0]]),
            azi02=gcr['azi1'],
            s02=np.array([]),
            time1=start_time,
            elapsed=dt.timedelta(seconds=0)
        )

        boat = polars.boat_properties('data/polar-ITA70.csv')
        model = '2020111600'
        winds = weather.read_wind_functions(model, 24)
        params = {
            'ROUTER_HDGS_SEGMENTS': 30,
            'ROUTER_HDGS_INCREMENTS_DEG': 1,
            'ISOCHRONE_EXPECTED_SPEED_KTS': 8,
            'ISOCHRONE_RESOLUTION_RAD': 1,
            'ISOCHRONE_PRUNE_SECTOR_DEG_HALF': 15,
            'ISOCHRONE_PRUNE_SEGMENTS': 5}

        delta_time_sec = 3600

        for i in range(2):
            iso = router.recursive_routing(
                iso, boat, winds,
                delta_time_sec, params,
                verbose=False)

        expected_azi02 = np.array([
            100.45741406,
            113.20471345,
            95.06500765,
            117.72590944,
            106.25658986])
        expected_s02 = np.array([
            39090.76869898,
            42504.71278082,
            36630.65067096,
            43113.25351592,
            41573.10032953])
        self.assertTrue(np.allclose(iso.azi02, expected_azi02))
        self.assertTrue(np.allclose(iso.s02, expected_s02))
        return None
예제 #7
0
파일: router.py 프로젝트: omdv/wind-router
def routing(start,
            finish,
            boat,
            winds,
            start_time,
            delta_time,
            steps,
            params,
            verbose=False):
    """
    Do full isochrone routing.

            Parameters:
                iso1 (Isochrone) - starting isochrone
                start_point (tuple) - starting point of the route
                end_point (tuple) - end point of the route
                x1_coords (tuple) - tuple of arrays (lats, lons)
                x2_coords (tuple) - tuple of arrays (lats, lons)
                boat (dict) - boat profile
                winds (dict) - wind functions
                start_time (datetime) - start time
                delta_time (float) - time to move in seconds
                params (dict) - isochrone calculation parameters

            Returns:
                iso (Isochrone) - next isochrone
    """
    gcr = geod.inverse([start[0]], [start[1]], [finish[0]], [finish[1]])

    iso = Isochrone(
        count=0,
        start=start,
        finish=finish,
        gcr_azi=gcr['azi1'],
        lats1=np.array([[start[0]]]),
        lons1=np.array([[start[1]]]),
        azi12=np.array([[None]]),
        s12=np.array([[0]]),
        azi02=gcr['azi1'],
        s02=np.array([]),
        time1=start_time,
        elapsed=dt.timedelta(seconds=0)
    )

    for i in range(steps):
        iso = recursive_routing(
            iso, boat, winds,
            delta_time, params,
            verbose=False)

    return iso
예제 #8
0
def test_inverse_near_antipodal():
    glib = Geodesic.WGS84

    lats1 = [0, 0, 16.24568372, 0]
    lons1 = [0, -180, 124.84613035, 0]
    lats2 = [0, 0, -16.70728358, 0.5]
    lons2 = [180, 180, -55.2234313, 179.7]

    vInverse = np.vectorize(glib.Inverse)

    g1s = vInverse(lats1, lons1, lats2, lons2)
    g2s = geod.inverse(lats1, lons1, lats2, lons2)

    s12 = [g1s[i]['s12'] for i in range(len(g1s))]
    np.testing.assert_allclose(g2s['s12'], s12, rtol=1e-10, atol=1e-10)
예제 #9
0
    def test_recursive_isochrone_method(self):
        """Test isochrone."""
        start = (43.5, 7.2)
        finish = (33.8, 35.5)
        start_time = dt.datetime.strptime('2020111607', '%Y%m%d%H')

        gcr = geod.inverse([start[0]], [start[1]], [finish[0]], [finish[1]])

        iso = isochrone.Isochrone(
            count=0,
            start=start,
            finish=finish,
            gcr_azi=gcr['azi1'],
            lats1=np.array([[start[0]]]),
            lons1=np.array([[start[1]]]),
            azi12=np.array([[None]]),
            s12=np.array([[0]]),
            azi02=gcr['azi1'],
            s02=np.array([0]),
            time1=start_time,
            elapsed=dt.timedelta(seconds=0)
        )

        boat = polars.boat_properties('data/polar-ITA70.csv')
        model = '2020111600'
        winds = weather.read_wind_functions(model, 24)
        params = {
            'ROUTER_HDGS_SEGMENTS': 30,
            'ROUTER_HDGS_INCREMENTS_DEG': 1,
            'ISOCHRONE_EXPECTED_SPEED_KTS': 8,
            'ISOCHRONE_RESOLUTION_RAD': 1,
            'ISOCHRONE_PRUNE_SECTOR_DEG_HALF': 15,
            'ISOCHRONE_PRUNE_SEGMENTS': 5}

        delta_time_sec = 3600
        result = router.recursive_routing(
            iso, boat, winds,
            delta_time_sec, params,
            verbose=False)
        expected_s12 = np.array([
            [13235.5216, 12843.9842, 13150.357, 13541.8945, 13933.4320],
            [0., 0., 0., 0., 0.]])

        self.assertTrue(np.allclose(result.s12, expected_s12))
        self.assertTrue(
            result.time1,
            start_time+dt.timedelta(seconds=delta_time_sec))
        return None
예제 #10
0
파일: router.py 프로젝트: omdv/wind-router
def recursive_routing(iso1,
                      boat,
                      winds,
                      delta_time,
                      params,
                      verbose=False):
    """
    Progress one isochrone with pruning.

            Parameters:
                iso1 (Isochrone) - starting isochrone
                start_point (tuple) - starting point of the route
                end_point (tuple) - end point of the route
                x1_coords (tuple) - tuple of arrays (lats, lons)
                x2_coords (tuple) - tuple of arrays (lats, lons)
                boat (dict) - boat profile
                winds (dict) - wind functions
                start_time (datetime) - start time
                delta_time (float) - time to move in seconds
                params (dict) - isochrone calculation parameters

            Returns:
                iso (Isochrone) - next isochrone
    """
    # branch out for multiple headings
    lats = np.repeat(iso1.lats1, params['ROUTER_HDGS_SEGMENTS'] + 1, axis=1)
    lons = np.repeat(iso1.lons1, params['ROUTER_HDGS_SEGMENTS'] + 1, axis=1)
    azi12 = np.repeat(iso1.azi12, params['ROUTER_HDGS_SEGMENTS'] + 1, axis=1)
    s12 = np.repeat(iso1.s12, params['ROUTER_HDGS_SEGMENTS'] + 1, axis=1)
    start_lats = np.repeat(iso1.start[0], lats.shape[1])
    start_lons = np.repeat(iso1.start[1], lons.shape[1])

    # determine new headings - centered around gcrs X0 -> X_prev_step
    hdgs = iso1.azi02
    delta_hdgs = np.linspace(
        -params['ROUTER_HDGS_SEGMENTS'] * params['ROUTER_HDGS_INCREMENTS_DEG'],
        +params['ROUTER_HDGS_SEGMENTS'] * params['ROUTER_HDGS_INCREMENTS_DEG'],
        params['ROUTER_HDGS_SEGMENTS'] + 1)
    delta_hdgs = np.tile(delta_hdgs, iso1.lats1.shape[1])
    hdgs = np.repeat(hdgs, params['ROUTER_HDGS_SEGMENTS'] + 1)
    hdgs = hdgs - delta_hdgs

    # move boat with defined headings N_coords x (ROUTER_HDGS_SEGMENTS+1) times
    move = move_boat_direct(lats[0, :], lons[0, :], hdgs,
                            boat, winds,
                            iso1.time1, delta_time,
                            verbose=False)

    # create new isochrone before pruning
    lats = np.vstack((move['lats2'], lats))
    lons = np.vstack((move['lons2'], lons))
    azi12 = np.vstack((move['azi1'], azi12))
    s12 = np.vstack((move['s12'], s12))

    # determine gcrs from start to new isochrone
    gcrs = geod.inverse(start_lats, start_lons, move['lats2'], move['lons2'])

    # remove those which ended on land
    is_on_land = globe.is_land(move['lats2'], move['lons2'])
    gcrs['s12'][is_on_land] = 0

    azi02 = gcrs['azi1']
    s02 = gcrs['s12']

    iso2 = Isochrone(
        start=iso1.start,
        finish=iso1.finish,
        gcr_azi=iso1.gcr_azi,
        count=iso1.count+1,
        elapsed=iso1.elapsed+dt.timedelta(seconds=delta_time),
        time1=iso1.time1+dt.timedelta(seconds=delta_time),
        lats1=lats,
        lons1=lons,
        azi12=azi12,
        s12=s12,
        azi02=azi02,
        s02=s02
    )

    # ---- pruning isochrone ----

    # new gcr azimuth to finish from the current isochrone
    mean_dist = np.mean(iso2.s02)
    gcr_point = geod.direct(
        [iso1.start[0]],
        [iso1.start[1]],
        iso1.gcr_azi, mean_dist)
    new_azi = geod.inverse(
        gcr_point['lat2'],
        gcr_point['lon2'],
        [iso1.finish[0]],
        [iso1.finish[1]]
    )
    azi0s = np.repeat(
        new_azi['azi1'],
        params['ISOCHRONE_PRUNE_SEGMENTS'] + 1)

    # determine bins
    delta_hdgs = np.linspace(
        -params['ISOCHRONE_PRUNE_SECTOR_DEG_HALF'],
        +params['ISOCHRONE_PRUNE_SECTOR_DEG_HALF'],
        params['ISOCHRONE_PRUNE_SEGMENTS']+1)
    bins = azi0s - delta_hdgs
    bins = np.sort(bins)

    iso2 = prune_isochrone(iso2, 'azi02', 's02', bins, True)

    return iso2