def test_get_point_hash(self):
     from editolido.geoindex import GeoGridIndex
     grid = GeoGridIndex(4)
     self.assertEqual(grid.get_point_hash(LatLng(45, 10)), 'u0p0')
     self.assertEqual(grid.get_point_hash(GeoPoint((45, 10))), 'u0p0')
     grid = GeoGridIndex()
     self.assertEqual(grid.get_point_hash(LatLng(45, 10)), 'u0p')
 def test_wmo_importer(self):
     from editolido.geoindex import GeoGridIndex, wmo_importer
     wmo_grid = GeoGridIndex()
     for name, _, lon, lat in wmo_importer():
         wmo_grid.add_point(
             GeoPoint(LatLng(lat, lon), name, normalizer=None))
     self.assertTrue(len(wmo_grid.data) > 5000)
Exemple #3
0
 def test_get_nearest_points(self):
     center_point = GeoPoint([49, 2])
     wmo_grid = GeoGridIndex()
     wmo_grid.load()
     nearest = list(wmo_grid.get_nearest_points(center_point, 27))
     self.assertEqual(len(nearest), 1)
     self.assertEqual(nearest[0][0].name, "07145")
Exemple #4
0
 def test_get_nearest_points_dirty(self):
     center_point = GeoPoint([49, 2])
     wmo_grid = GeoGridIndex()
     wmo_grid.load()
     # with self.assertRaises(ValueError):
     #     wmo_grid.get_nearest_points_dirty(center_point, 100)
     nearest = list(wmo_grid.get_nearest_points_dirty(center_point, 75))
     self.assertEqual(len(nearest), 42)
 def test_get_nearest_points(self):
     from editolido.geoindex import GeoGridIndex
     c = GeoPoint((45, 10.5))
     p = GeoPoint((45, 10))  # à 21,23NM
     grid = GeoGridIndex()
     grid.add_point(p)
     nearby = grid.get_nearest_points(c, 20, converter=nm_to_rad)
     self.assertEqual(list(nearby), [])
     nearby = grid.get_nearest_points(c, 23, converter=nm_to_rad)
     self.assertEqual(list(nearby),
                      [(p, c.distance_to(p, converter=rad_to_nm))])
Exemple #6
0
def ogimet_route(route, segment_size=300, debug=False,
                 name="", description=""):
    wmo_grid = GeoGridIndex()
    wmo_grid.load()
    start = route[0]
    end = route[-1]

    def print_ogimet(points):
        print('Route Ogimet (%s): %s' % (
            len(points), '_'.join([p.name for p in points])))

    # noinspection PyShadowingNames
    def build_ogimet(default_step):
        ogimet_sites = [start.name]
        previous = start
        ogimet_points = [start]
        sid = True
        for i, p in enumerate(
                route.split(60, converter=km_to_rad, preserve=True)):
            if i == 0:
                continue
            neighbours = sorted(
                wmo_grid.get_nearest_points(p, 30, converter=km_to_rad),
                key=lambda t: t[1])
            if neighbours:
                point, d = neighbours[0]
                if sid and point.distance_to(start, converter=rad_to_km) < 500:
                    step = min(60, default_step)
                else:
                    sid = False
                    step = default_step
                if point.name not in ogimet_sites and previous.distance_to(
                        point, converter=rad_to_km) > step:
                    previous = point
                    ogimet_points.append(point)
                    ogimet_sites.append(point.name)
        ogimet_points[-1] = end
        return ogimet_points

    step = start.distance_to(end, converter=rad_to_km) / 200
    ogimet_points = []
    while True:
        ogimet_points = build_ogimet(step)
        if len(ogimet_points) < 23:
            break
        if debug:
            print_ogimet(ogimet_points)
        step *= 2
    if debug:
        print_ogimet(ogimet_points)
    return Route(ogimet_points).split(
        segment_size, preserve=True, name=name, description=description)
 def test_get_nearest_points_dirty(self):
     from editolido.geoindex import GeoGridIndex
     c = GeoPoint((45, 10.5))
     p = GeoPoint((45, 10))  # à 21,23NM
     grid = GeoGridIndex(4)
     grid.add_point(p)
     with self.assertRaises(ValueError):
         grid.get_nearest_points_dirty(c, 30, converter=nm_to_rad)
     grid = GeoGridIndex()
     grid.add_point(p)
     nearby = grid.get_nearest_points_dirty(c, 20, converter=nm_to_rad)
     self.assertEqual(list(nearby), [p])
Exemple #8
0
 def test_dumps(self):
     p = GeoPoint((45, 10), name='P1', description='D2')
     grid = GeoGridIndex()
     self.assertEqual(grid.dumps(), '{}')
     grid.add_point([p.name, float(p.latitude), float(p.longitude)])
     grid.data['__test__'] = 'test'  # test default encoder is called
     jsondata = grid.dumps()
     self.assertDictEqual(grid.data, json.loads(jsondata, encoding='utf-8'))
 def test_dumps(self):
     from editolido.geoindex import GeoGridIndex
     p = GeoPoint((45, 10), name='P1', description='D2')
     grid = GeoGridIndex()
     self.assertEqual(grid.dumps(), '{}')
     grid.add_point(p)
     grid.data['__test__'] = 'test'  # test default encoder is called
     jsondata = grid.dumps()
     self.assertDictEqual(
         grid.data,
         json.loads(jsondata, encoding='utf-8', object_hook=as_geopoint))
Exemple #10
0
 def test_get_nearest_points(self):
     c = GeoPoint((45, 10.5))
     p = GeoPoint((45, 10))  # à 21,23NM
     grid = GeoGridIndex()
     grid.add_point([p.name, float(p.latitude), float(p.longitude)])
     nearby = grid.get_nearest_points(c, 20, converter=nm_to_rad)
     if six.PY2:
         self.assertEqual(list(nearby), [])
     else:
         pass  # TODO
     nearby = grid.get_nearest_points(c, 23, converter=nm_to_rad)
     if six.PY2:
         self.assertEqual(list(nearby),
                          [(p, c.distance_to(p, converter=rad_to_nm))])
     else:
         pass  # TODO
Exemple #11
0
def ogimet_route(route, segment_size=300, name="", description=""):
    Result = namedtuple('Result', ['fpl', 'ogimet'])
    wmo_grid = GeoGridIndex()
    wmo_grid.load()
    neighbour_radius = (rad_to_km(wmo_grid.grid_size) / 2.0) - 0.1

    def get_neighbour(point):
        """
        Find neighbour ogimet point
        Prefer fpl point if it exists
        :param point:
        :return: tuple(Geopoint, float)
        """
        neighbours = sorted(
            wmo_grid.get_nearest_points(point, neighbour_radius),
            key=lambda t: t[1]
        )
        if neighbours:
            if point.name in [n.name for n, _ in neighbours]:
                return point, 0
            return neighbours[0][0], neighbours[0][1]
        return None, None

    def find_strategic(start, end, results):
        """
        Find point you can not suppress without increasing xtd
        :param start: int
        :param end: int
        :param results: [Result]
        :return:
        """
        # search in reverse order to stop at the latest point in the route direction
        # in segment [i, j] we try to remove inner elements by checking the xtd
        for k in range(end - 1, start, -1):
            # xtd from ogimet point to fpl segment
            o_xtd = results[k].ogimet.xtd_to(
                (results[k].fpl, results[k + 1].fpl)
            )
            # xtd from fpl point to ogimet segment
            f_xtd = results[k].fpl.xtd_to(
                (results[start].ogimet, results[end].ogimet)
            )
            if abs(f_xtd) > abs(o_xtd):
                return k
        return None

    def filter_by_xtd(results):
        """
        Here we keep significant ogimet points.

        By significant, I mean points which increase the xtd if missing.
        The algorithm is recursive, if route is A B C D E F
        and ogimet route found is A B'C'D'E'F
        We try to suppress B', if successful we try to suppress C' and so on
        For example if B', C' and E' are not relevant the loop
        will try to suppress B' and C', then it will keep D' and
        start again from D' to suppress E' and keep F
        At the end we try again (recursion) until the route size is constant.
        For information a typical NAT route will reduce from 26 to 15 points
        and a flight to NRT will end with 26 points (starting from 79)
        :param results: [Result]
        :return: [Result]
        """
        res = [results[0]]
        i = -1
        while i < (len(results) - 1):
            i += 1
            j = i + 2
            # we try to remove many consecutive points until it fails
            while j <= len(results) - 1:
                k = find_strategic(i, j, results)
                if k is None:
                    j += 1  # no significant point yet, try to extend to next
                else:
                    # a significant point was found, store it
                    if results[k].ogimet.name not in [o.name for _, o in res]:
                        res.append(results[k])
                    i = k - 1  # will start at k on next round
                    break
        res.append(results[-1])
        # recursion works, so try it until there is no change
        if len(res) < len(results):
            return filter_by_xtd(res)
        else:
            return res

    # noinspection PyUnusedLocal
    def lowest_crs_index(results):
        """
        Index to the point which causes the smallest course change if removed
        :param results: [Result]
        :return: int
        """
        best_diff = 0
        best = None
        maxi = len(results) - 1
        for i, r in enumerate(results):
            if 1 <= i < maxi:
                diff = abs(
                    results[i - 1].ogimet.course_to(results[i].ogimet)
                    - results[i - 1].ogimet.course_to(results[i+1].ogimet)
                )
                if best is None or diff < best_diff:
                    best = i
                    best_diff = diff
        return best

    def lowest_xtd_index(results):
        """
        Index to the point which causes the less xtd loss if removed
        :param results: [Result]
        :return: int
        """
        best_xtd = 0
        best = None
        maxi = len(results) - 1
        for i, r in enumerate(results):
            if 1 <= i < maxi:
                xtd = abs(
                    r.fpl.xtd_to((results[i - 1].ogimet, results[i + 1].ogimet))
                )
                if best is None or xtd < best_xtd:
                    best = i
                    best_xtd = xtd
        return best

    # Here we find all ogimet points for our route
    # The same ogimet point can be used by many fpl points
    # prepare o_index which will be used to deduplicate
    # we place in o_index points with the shortest distance
    ogimet_results = []
    o_index = {}
    for p in route.split(60, converter=km_to_rad, preserve=True):
        neighbour, x = get_neighbour(p)
        if neighbour:
            if neighbour.name in o_index:
                if o_index[neighbour.name][0] > x:
                    o_index[neighbour.name] = (x, p)
            else:
                o_index[neighbour.name] = (x, p)
            ogimet_results.append(Result(p, neighbour))

    # filter using o_index (keep points that were stored in o.index)
    ogimet_results = list(
        filter(lambda r: o_index[r.ogimet.name][1] == r.fpl, ogimet_results)
    )

    # keep only significant points (strategic points)
    ogimet_results = filter_by_xtd(ogimet_results)

    # Reduce ogimet route size to 22 points
    # We have to loose precision, we score the lowest xtd loss
    # as an alternative you may use lowest_crs_index but I did
    # not find major gain yet.
    while len(ogimet_results) > 21:
        idx = lowest_xtd_index(ogimet_results)
        ogimet_results = ogimet_results[:idx] + ogimet_results[idx+1:]

    return Route(points=[ogimet for _, ogimet in ogimet_results]).split(
        segment_size, preserve=True, name=name, description=description)
Exemple #12
0
def main():  # pragma: no cover
    wmo_grid = GeoGridIndex()
    for name, lon, lat in wmo_importer():
        wmo_grid.add_point(GeoPoint(LatLng(lat, lon), name, normalizer=None))
    wmo_grid.save()
Exemple #13
0
 def test_wmo_importer(self):
     wmo_grid = GeoGridIndex()
     for name, _, lon, lat in wmo_importer():
         wmo_grid.add_point(
             GeoPoint(LatLng(lat, lon), name, normalizer=None))
     self.assertTrue(len(wmo_grid.data) > 5000)
Exemple #14
0
 def test_load(self):
     grid = GeoGridIndex()
     grid.load()
     self.assertGreater(len(grid.data), 4000)
Exemple #15
0
 def test_get_nearest_points_dirty(self):
     c = GeoPoint((45, 10.5))
     p = GeoPoint((45, 10))  # à 21,23NM
     grid = GeoGridIndex(4)
     print(grid.precision, rad_to_km(grid.grid_size))
     grid.add_point([p.name, float(p.latitude), float(p.longitude)])
     with self.assertRaises(ValueError):
         grid.get_nearest_points_dirty(c, 30, converter=nm_to_rad)
     grid = GeoGridIndex()
     grid.add_point([p.name, float(p.latitude), float(p.longitude)])
     nearby = grid.get_nearest_points_dirty(c, 20, converter=nm_to_rad)
     self.assertEqual(list(nearby), [p])
Exemple #16
0
 def test_add_point(self):
     grid = GeoGridIndex(4)
     p = ["", 45, 10]
     grid.add_point(p)
     self.assertEqual(grid.data['u0p0'], [p])
Exemple #17
0
 def test_get_point_hash(self):
     grid = GeoGridIndex(4)
     self.assertEqual(grid.get_point_hash(LatLng(45, 10)), 'u0p0')
     self.assertEqual(grid.get_point_hash(GeoPoint((45, 10))), 'u0p0')
     grid = GeoGridIndex()
     self.assertEqual(grid.get_point_hash(LatLng(45, 10)), 'u0p')
 def test_add_point(self):
     from editolido.geoindex import GeoGridIndex
     grid = GeoGridIndex(4)
     p = GeoPoint((45, 10))
     grid.add_point(p)
     self.assertEqual(grid.data['u0p0'], [p])
 def test_load(self):
     from editolido.geoindex import GeoGridIndex
     grid = GeoGridIndex()
     grid.load()
     self.assertGreater(len(grid.data), 4000)