Пример #1
0
def astar_cnx(g, source_id=None, target_id=None, routes=None):
    from limic.util import locate_by_id, distance
    cs, node2closest, node2c = g.cs, g.node2closest, g.node2c
    if isinstance(source_id, tuple) and isinstance(target_id, tuple):
        source, target = source_id[0], target_id[0]
    else:
        nodes = list(node2closest.keys())
        nodes.extend(node2c.keys())
        ids = list(map(lambda x: x[0], nodes))
        source, target = locate_by_id(ids, source_id, target_id)
        source, target = nodes[source], nodes[target]
        if not routes is None:
            routes.append((source, target))
    if source not in node2closest:
        if target in node2closest or node2c[source] != node2c[target]:
            cost = dist = distance(source, target)
            path = None, [(0., 0., False) + source,
                          (float('inf'), dist, True) + target]
            return path
        path = astar_nx(node2c[source], (source, ), (target, ))
        return path
    if target not in node2closest:
        cost = dist = distance(source, target)
        path = None, [(0., 0., False) + source,
                      (float('inf'), dist, True) + target]
        return path
    paths = []

    def extend(cp1, cp2):
        cost = cp1[0]
        path = cp1[1]
        assert (path[-1][3:] == cp2[1][0][3:])
        path.extend(map(lambda x: ((x[0] + cost, ) + x[1:]), cp2[1][1:]))
        cost += cp2[0]
        return cost, path

    for ns, ps, cs in node2closest[source]:
        for nt, pt, ct in node2closest[target]:
            c = node2c[ns]
            if c != node2c[nt]:
                cost = dist = distance(source, target)
                path = None, [(0., 0., False) + source,
                              (float('inf'), dist, True) + target]
                return path
            cp = astar_nx(ps, (source, ), (ns, ))
            cpc = astar_nx(c, (ns, ), (nt, ))
            for u, v in zip(cpc[1], cpc[1][1:]):
                u, v = u[3:], v[3:]
                cuv = c[u][v]
                sg = cuv["path"]
                cpuv = astar_nx(sg, (u, ), (v, ))
                cp = extend(cp, cpuv)
            cpt = astar_nx(pt, (nt, ), (target, ))
            cp = extend(cp, cpt)
            paths.append(cp)


#            paths.append((cs+c.graph['lengths'][ns][nt]+ct,[]))
    return min(paths)
Пример #2
0
def build_edges(g, find_all_neighbours, around, eps, safe_dist, penalize):
    from limic.overpass import pylon
    from limic.util import distance
    #count = 0
    neighbours2intersection = {}
    minusid = [0]
    latlon2id = {}
    for tower in list(g.nodes()):
        #count += 1
        #if verbosity >= 2: print(count,"of",total)
        for neighbour in find_all_neighbours(tower, around, eps, safe_dist,
                                             minusid, latlon2id, penalize):
            if neighbour.tower in g or neighbour.tower.id < 0:
                #if verbosity >= 2: print("adding",neighbour)
                g.add_edge(tower,
                           pylon(neighbour.tower.id, neighbour.tower.latlon),
                           weight=neighbour.dist,
                           type=neighbour.air)
                if neighbour.tower.id < 0:
                    for intersection in neighbours2intersection.setdefault(
                            neighbour.tower.neighbours, []):
                        if intersection.latlon != neighbour.tower.latlon:
                            #if verbosity >= 2: print("double intersection:",intersection.latlon,neighbour.tower.latlon)
                            g.add_edge(intersection,
                                       neighbour.tower,
                                       weight=distance(intersection.latlon,
                                                       neighbour.tower.latlon),
                                       type=False)
                    neighbours2intersection[neighbour.tower.neighbours].append(
                        neighbour.tower)
Пример #3
0
def reconstruct_path_direct(current):
    from limic.util import distance
    dist = current.g - current.origin.g if current.origin else 0.
    air = distance(
        current.tower.latlon,
        current.origin.tower.latlon) < 0.9 * dist if current.origin else False
    cost = 0.
    path = [(current.g, dist, air, current.tower.id, current.tower.latlon[0],
             current.tower.latlon[1])]
    while current.origin:
        current = current.origin
        cost = current.g
        dist = cost - current.origin.g if current.origin else 0.
        air = distance(
            current.tower.latlon, current.origin.tower.latlon) < 0.9 * (
                current.g - current.origin.g) if current.origin else False
        path.append((cost, dist, air, current.tower.id,
                     current.tower.latlon[0], current.tower.latlon[1]))
    path.reverse()
    return cost, path
Пример #4
0
def nodes_in_geometry(tree, polygon):
    from limic.util import distance
    from shapely.geometry import Point, Polygon
    southwest, middle, _ = bounds_center(polygon)
    radius = distance(southwest, middle)
    candidates = tree.query(middle, radius)
    get_latlon = tree.get_latlon
    return [
        candidate for candidate in candidates
        if Point(*get_latlon(candidate)).within(Polygon(polygon))
    ]
Пример #5
0
def astar_nx(g, source_id=None, target_id=None):
    from limic.util import locate_by_id, haversine_distance
    from networkx import astar_path, NetworkXNoPath
    if isinstance(source_id, tuple) and isinstance(target_id, tuple):
        source, target = source_id[0], target_id[0]
    else:
        nodes = list(g.nodes())
        ids = list(map(lambda x: x[0], nodes))
        source, target = locate_by_id(ids, source_id, target_id)
        source, target = nodes[source], nodes[target]
    targetlat, targetlong = target[1], target[2]

    def distance(x, y):
        #assert(target==y)
        return haversine_distance(longx=x[2],
                                  latx=x[1],
                                  longy=targetlong,
                                  laty=targetlat)

    try:
        if 'paths' in g.graph and g.graph['paths']:
            path = g.graph['paths'][source][target]
        else:
            path = astar_path(g, source, target, heuristic=distance)
        cost = dist = 0.0
        dpath = [(cost, dist, False) + path[0]]
        for i in range(1, len(path)):
            ggg = g[path[i - 1]][path[i]]
            dist = ggg['weight']
            cost += dist
            air = ggg['type']
            dpath.append((cost, dist, air < 0) + path[i])
        return cost, dpath
    except NetworkXNoPath as e:
        cost = dist = distance(source, target)
        path = None, [(0., 0., False) + source,
                      (float('inf'), dist, True) + target]
    return path
Пример #6
0
def astar_tower_direct(start,
                       end,
                       max_fly=1000,
                       eps=0.01,
                       safe_dist=100,
                       penalty=20,
                       prec=1):
    class node:
        def __init__(self, f, g, tower, origin):
            self.f = f
            self.g = g
            self.tower = tower
            self.origin = origin

        def __lt__(self, other):
            return self.f < other.f

        def __repr__(self):
            return "node(f=" + repr(self.f) + ",g=" + repr(
                self.g) + ",tower=" + repr(self.tower) + ",origin=" + repr(
                    self.origin.tower.id if self.origin else self.origin) + ")"

    from limic.overpass import find_all_neighbours
    from heapq import heappop, heappush, heapify
    from limic.util import distance
    from math import inf
    latlon2id = {}
    minusid = [0]
    start_node = node(
        distance(start.latlon, end.latlon) * prec, 0, start, None)
    nodes = {start.id: start_node}
    todo = [start_node]
    while todo:
        #if verbosity >= 4: print("*******************\n"+str(todo)+"\n***************")
        #if verbosity >= 4: print("*******************\n"+str(sorted(todo))+"\n***************")
        current = heappop(todo)
        #if verbosity >= 2: print("visiting",current.f,current.tower.id,current.tower.latlon)
        #if verbosity >= 2: print("full node",current)
        if current.tower.id == end.id:
            return reconstruct_path_direct(current)
        #if verbosity >=2:
        #    print("CURRENT PATH:\nnode(id:"+(",".join(map(str,reconstruct_path(current)[1])))+");out;")
        #    print("FRONT:\nnode(id:"+(",".join(map(lambda n:str(n.tower.id),todo)))+");out;")
        neighbours = find_all_neighbours(current.tower, max_fly, eps,
                                         safe_dist, minusid, latlon2id,
                                         penalty)
        for neighbour in neighbours:
            g = current.g + neighbour.dist
            neighbour_node = nodes.get(neighbour.tower.id,
                                       node(None, inf, neighbour.tower, None))
            if g < neighbour_node.g:
                if not neighbour_node.f:
                    nodes[neighbour.tower.id] = neighbour_node
                must_add = neighbour_node not in todo
                neighbour_node.origin = current
                neighbour_node.g = g
                neighbour_node.f = g + distance(neighbour.tower.latlon,
                                                end.latlon) * prec
                if must_add:
                    #if verbosity >= 3: print("added",neighbour_node)
                    heappush(todo, neighbour_node)
                #else:
                #if verbosity >= 3: print("modified",neighbour_node)
                heapify(todo)
    return None, [(0., 0., False, start.id, start.latlon[0], start.latlon[1]),
                  (float('inf'), start_node.f, True, end.id, end.latlon[0],
                   end.latlon[1])]
Пример #7
0
def astar_gt(g, source_id=None, target_id=None):
    from graph_tool.search import astar_search, AStarVisitor, StopSearch
    from limic.util import locate_by_id, haversine_distance
    long = g.vp.long
    lat = g.vp.lat
    ids = list(map(lambda x: x[1], g.get_vertices([g.vp.id])))
    source, target = locate_by_id(ids, source_id, target_id)
    source, target = g.vertex(source), g.vertex(target)
    targetlong, targetlat = long[target], lat[target]

    class Visitor(AStarVisitor):
        def __init__(self, target):
            self.target = target

        def edge_relaxed(self, e):
            if e.target() == self.target:
                raise StopSearch()

    def distance(x):
        return haversine_distance(longx=long[x],
                                  latx=lat[x],
                                  longy=targetlong,
                                  laty=targetlat)

    dist, pred = astar_search(g,
                              source,
                              g.ep.weight,
                              Visitor(target),
                              heuristic=distance)
    path = []
    current = target
    total_cost = cost = dist[current]
    if g.vertex(pred[current]) == current:
        air = True
        dist = distance(source)
    else:
        e = g.edge(g.vertex(pred[current]), g.vertex(current))
        dist = g.ep.weight[e]
        air = True if g.ep.type[e] < 0 else False
    while True:
        i = int(current)
        path.append((cost, dist, air < 0, ids[i], lat[i], long[i]))
        pre = g.vertex(pred[current])
        if pre == current:
            break
        cost -= dist
        current = pre
        pre = g.vertex(pred[current])
        if pre == current:
            dist = 0.
            air = False
        else:
            e = g.edge(g.vertex(pre), g.vertex(current))
            dist = g.ep.weight[e]
            air = True if g.ep.type[e] < 0 else False
    path.reverse()
    if len(path) < 2:
        assert (len(path) == 1)
        source = int(source)
        return None if source != target else 0., [
            (0., 0., False, ids[source], lat[source], long[source])
        ] + (path if source != target else [])
    else:
        return total_cost, path
Пример #8
0
def osm_post(lim,
             file_name_out,
             around=1000,
             eps=0.01,
             safe_dist=100,
             penalize=20):
    from limic.util import start, end, status, file_size, load_pickled, distance, save_pickled
    from scipy.spatial import cKDTree as KDTree
    from networkx import Graph, astar_path_length
    from pyproj import CRS, Transformer
    from itertools import chain
    from limic.overpass import intersect, pylon
    lines, substations, towers, id2tower, id2node, id2lines, id2types = lim
    start("Building KD-tree from white nodes")
    from limic.util import kdtree
    towers_tree = kdtree(towers, get_latlon=lambda x: x.latlon)
    end('')
    status(len(towers))
    start("Deleting black nodes")
    to_delete = set()
    from limic.util import nodes_in_geometry
    for substation in substations:
        to_delete.update(
            nodes_in_geometry(towers_tree,
                              list(map(lambda x: id2node[x], substation))))
    towers = [tower for tower in towers if tower not in to_delete]
    end('')
    status(len(towers))
    start("Building initial graph")
    g = Graph()
    g.add_nodes_from(towers)
    for line in lines:
        line_nodes = list(map(lambda x: id2tower[x], line))
        for from_node, to_node in zip(line_nodes, line_nodes[1:]):
            if from_node in to_delete or to_node in to_delete:
                continue
            w = distance(from_node.latlon, to_node.latlon)
            g.add_edge(from_node,
                       to_node,
                       weight=w,
                       type=id2types[from_node.id])
    end('')
    status(len(g.nodes()), end='/')
    status(len(g.edges()))
    start("Finding neighbours within " + str(around) + "m")
    towers_tree = kdtree(towers, get_latlon=lambda x: x.latlon)
    end('')
    neighbour_indices, neighbours = towers_tree.get_neighbours(around=1000)
    end()
    start("Computing non-logical intersections")
    tower2index = {}
    for i, t in zip(range(len(towers)), towers):
        tower2index[t] = i
    for k, v in id2lines.items():
        id2lines[k] = tuple(map(tuple, v))
    end('')
    segments = set()
    for u, v in g.edges():
        this = (u, v) if u < v else (v, u)
        ui, vi = tower2index[u], tower2index[v]
        lines = set()
        lines.update(id2lines[u.id])
        lines.update(id2lines[v.id])
        for neighbour in chain(neighbours[ui], neighbours[vi]):
            if neighbour == u or neighbour == v:
                continue
            if not lines.intersection(id2lines[neighbour.id]):
                for nn in g.neighbors(neighbour):
                    other = (neighbour, nn) if neighbour < nn else (nn,
                                                                    neighbour)
                    segments.add(tuple(sorted((this, other))))
    end('')
    status(len(segments), end='   ')
    neighbours2intersection = {}
    minusid = 0
    latlon2id = {}
    segments2intersections = {}
    for (t1, t2), (t3, t4) in segments:
        res = intersect(t1.latlon,
                        t2.latlon,
                        t3.latlon,
                        t4.latlon,
                        eps=eps,
                        no_tu=False)
        if res:
            intersection, (t, u) = res
            if not intersection in latlon2id:
                minusid -= 1
                latlon2id[intersection] = minusid
            segments2intersections.setdefault((t1, t2), []).append(
                (t, latlon2id[intersection], intersection))
            segments2intersections.setdefault((t3, t4), []).append(
                (u, latlon2id[intersection], intersection))
    end('')
    status(-minusid, end='   ')
    for (u, v), intersections in segments2intersections.items():
        intersections.sort()
        g.remove_edge(u, v)
        type = id2types[u.id]
        assert (type == id2types[v.id])
        seq = [u]
        for _, id, latlon in intersections:
            seq.append(pylon(id, latlon))
        seq.append(v)
        for from_node, to_node in zip(seq, seq[1:]):
            w = distance(from_node.latlon, to_node.latlon)
            g.add_edge(from_node, to_node, weight=w, type=type)
    end()
    start("Adding routing through air")
    airs = set()
    for ns in neighbours:
        n = ns[0]
        for m in ns[1:]:
            if not g.has_edge(n, m):
                airs.add((n, m))
    end('')
    for n, m in airs:
        w = penalize * distance(n.latlon, m.latlon)
        g.add_edge(n, m, weight=w, type=-1)
    end('')
    status(len(g.nodes()), end='/')
    status(len(g.edges()))
    from networkx import relabel_nodes
    start("Prune redundant edges (incomplete)")
    prune_incomplete(g)
    end('')
    status(len(g.edges()))
    start("Prune redundant edges (complete)")
    prune_complete(g)
    end('')
    status(len(g.edges()))
    start("Cleaning up graph")
    relabel = dict(
        map(
            lambda tower: (tower,
                           (tower.id, tower.latlon[0], tower.latlon[1])),
            g.nodes()))
    relabel_nodes(g, relabel, copy=False)
    end()
    start("Saving graph to", file_name_out)
    save_pickled(file_name_out, g)
    end('')
    file_size(file_name_out)