Example #1
0
def test_should_add_multiple_nodes_and_find_them():
    index = Index(INDEX_BBOX)
    index.insert(ITEM1, BBOX1)
    index.insert(ITEM2, BBOX2)
    assert len(index) == 2
    assert index.intersect(BBOX1) == {ITEM1}
    assert index.intersect(BBOX2) == {ITEM2}
    assert index.intersect(INDEX_BBOX) == {ITEM1, ITEM2}
Example #2
0
def test_should_add_multiple_nodes_and_find_them():
    index = Index(INDEX_BBOX)
    index.insert(ITEM1, BBOX1)
    index.insert(ITEM2, BBOX2)
    assert len(index) == 2
    assert index.intersect(BBOX1) == [ITEM1]
    assert index.intersect(BBOX2) == [ITEM2]
    res = index.intersect(INDEX_BBOX)
    assert ITEM1 in res
    assert ITEM2 in res
Example #3
0
def remove_overlapping_points(missed_points_coord):
    missed_points_qtree = Index(bbox=(np.amin(missed_points_coord[:, 0]), np.amin(missed_points_coord[:,1]), np.amax(missed_points_coord[:,0]), np.amax(missed_points_coord[:, 1])))
    d_y = 1/444444.0 ## 0.25 meters
    d_x = np.cos(missed_points_coord[0][1] / (180 / np.pi))/444444.0 ## 0.25 meters
    for i in trange(len(missed_points_coord), desc='check for double points'):
        mp = missed_points_coord[i]
        if not missed_points_qtree.intersect((mp[0] - d_x, mp[1] - d_y, mp[0] + d_x, mp[1] + d_y)):
            missed_points_qtree.insert(mp, (mp[0] - d_x, mp[1] - d_y, mp[0] + d_x, mp[1] + d_y))
    
    missed_points_coord = missed_points_qtree.intersect(bbox=(np.amin(missed_points_coord[:, 0]), np.amin(missed_points_coord[:,1]), np.amax(missed_points_coord[:,0]), np.amax(missed_points_coord[:, 1])))
    return missed_points_coord
Example #4
0
def nearest(main_points, aux_points, radius=1):
    """
    Objective is to find the nearest point to the points in the aux_points set.
    The nearest point is to be identified among the points in the main_points
    set.
    """
    xmin, ymin = np.min(np.array(list(main_points.values())), axis=0)
    xmax, ymax = np.max(np.array(list(main_points.values())), axis=0)
    bbox = (xmin, ymin, xmax, ymax)
    idx = Index(bbox)

    # keep track of points so we can recover them later
    points = []

    # create bounding box around each point in main_points set
    for i, p in enumerate(main_points):
        pt_main = Point(main_points[p])
        pt_bounds_main = pt_main.x-radius, pt_main.y-radius, \
            pt_main.x+radius, pt_main.y+radius
        idx.insert(i, pt_bounds_main)
        points.append((pt_main, pt_bounds_main, p))

    # find intersection with bounding box around aux point set
    for n in aux_points:
        pt_aux = Point(aux_points[n])
        pt_bounds_aux = pt_aux.x-radius, pt_aux.y-radius, \
            pt_aux.x+radius, pt_aux.y+radius
        matches = idx.intersect(pt_bounds_aux)
        ind_closest = min(matches, key=lambda i: geodist(points[i][0], pt_aux))
        print(points[ind_closest][-1])
    return
Example #5
0
def query_quadtree(chr, start, end, files):
    chromLength = chromosomes[chr]
    print("chromLength", chromLength)
    dims = 2
    hlevel = math.ceil(math.log2(chromLength) / dims)
    print("hlevel", hlevel)
    x_y_dim = math.ceil(math.pow(2, hlevel))
    print("max x|y =", x_y_dim)
    # tree = Index(bbox=(0, 0, x_y_dim, x_y_dim), disk = "quadtree/indexes/roadmap." + chr + ".quadtree.index")
    tree = Index(bbox=(0, 0, x_y_dim, x_y_dim),
                 disk="./roadmap." + chr + ".quadtree.index")

    xstart, ystart, _ = hcoords(start, chromLength)
    xend, yend, _ = hcoords(end, chromLength)

    print("xstart, ystart, xend, yend", xstart, ystart, xend, yend)
    margin = 0
    overlapbbox = (xstart - margin, ystart - margin, xend + margin,
                   yend + margin)
    matches = tree.intersect(overlapbbox)

    df = pandas.DataFrame(matches,
                          columns=["start", "end", "offset", "size", "fileid"])
    print("before file filter")
    print(df.shape)
    print(df)
    df = df[(df["fileid"].isin(files)) & (df["start"] <= end) &
            (df["end"] >= start)]
    print("after file filter")
    print(df.shape)
    print(df)
    return df
Example #6
0
    def query(self, file, chr, start, end, zoomlvl=-2):
        chromLength = self.genome[chr]
        dims = 2
        hlevel = math.ceil(math.log2(chromLength) / dims)
        # print("hlevel", hlevel)
        x_y_dim = math.ceil(math.pow(2, hlevel))
        # print("max x|y =", x_y_dim)
        tree = Index(bbox=(0, 0, x_y_dim, x_y_dim),
                     disk=base_path + "quadtree." + chr + ".index")

        xstart, ystart, _ = hcoords(start, chromLength)
        xend, yend, _ = hcoords(end, chromLength)

        overlapbbox = (start - 1, start - 1, end + 1, end + 1)
        matches = tree.intersect(overlapbbox)

        df = pandas.DataFrame(
            matches, columns=["start", "end", "offset", "size", "fileid"])
        df = df[df["fileid"] == self.file_mapping[file]]

        bw = self.file_objects[file]
        chrmId = bw.chrmIds[chr]

        result = []
        for i, row in df.iterrows():
            result += bw.parseLeafDataNode(chrmId, start, end, zoomlvl, chrmId,
                                           row["start"], chrmId, row["end"],
                                           row["offset"], row["size"])

        result = toDataFrame(values, bw.columns)
        result["chr"] = chr

        return result
Example #7
0
def produce_fov_ids(lookers,
                    viewed,
                    count,
                    fov_dilation=[-0.1, -0.1, 0.1, 0.1]):
    """
    Produce ids of bboxes each of lookers can 'see' (intersect) in the viewed wordbox.
    bbox = l, t, r, b
    """
    xs = [item[0] for item in viewed] + [item[2] for item in viewed]
    ys = [item[1] for item in viewed] + [item[3] for item in viewed]
    l = min(xs)
    t = min(ys)
    r = max(xs)
    b = max(ys)
    spindex = Index(bbox=(l, t, r, b))
    # this example assumes you have a list of items with bbox attribute
    for i, bbox in enumerate(viewed):
        spindex.insert(i, bbox)

    ids_r = np.full((len(lookers), count), -1)

    for i, bbox in enumerate(lookers):
        matches = spindex.intersect(fov_dilate(bbox, fov_dilation))
        # now find the closest to the center of the original:
        center = bb_center(bbox)
        matches.sort(
            key=lambda j: ss_to_center(center, viewed[j]))  # ascending
        cnt = min(len(matches), count)
        ids_r[i, :cnt] = matches[:cnt]

    return ids_r
Example #8
0
def find_nearest_node(center_cord, node_cord):
    """
    Computes the nearest node in the dictionary 'node_cord' to the point denoted
    by the 'center_cord'
    
    center_cord: 
        TYPE: list of two entries
        DESCRIPTION: geographical coordinates of the center denoted by a list
                     of two entries
    
    node_cord: 
        TYPE: dictionary 
        DESCRIPTION: dictionary of nodelist with values as the geographical 
                     coordinate
    """
    xmin, ymin = np.min(np.array(list(node_cord.values())), axis=0)
    xmax, ymax = np.max(np.array(list(node_cord.values())), axis=0)
    bbox = (xmin, ymin, xmax, ymax)
    idx = Index(bbox)

    nodes = []
    for i, n in enumerate(list(node_cord.keys())):
        node_geom = Point(node_cord[n])
        node_bound = bounds(node_geom, 0.0)
        idx.insert(i, node_bound)
        nodes.append((node_geom, node_bound, n))

    pt_center = Point(center_cord)
    center_bd = bounds(pt_center, 0.1)
    matches = idx.intersect(center_bd)
    closest_node = min(matches, key=lambda i: geodist(nodes[i][0], pt_center))
    return nodes[closest_node][-1]
Example #9
0
    def fit_transform(self, X):

        self.check_data(X)

        max_x, max_y = X.max(axis=0)
        quadtree = Index(bbox=[0, 0, max_x + 10, max_y + 10])

        for i, x in enumerate(X):
            bbox = (x[0], x[1], x[0], x[1])
            quadtree.insert(item={
                'point': x,
                'bbox': bbox,
                'id': i
            },
                            bbox=bbox)

        maxy = int(max_x / self.size + 50)
        maxx = int(max_y / self.size + 50)

        cells = []

        for i in range(1, maxy + 1):
            for j in range(1, maxx + 1):
                bbox = ((i - 1) * self.size, (j - 1) * self.size,
                        i * self.size, j * self.size)
                d = quadtree.intersect(bbox)
                if len(d) != 0:
                    cells.append({'x': (i - 1), 'y': (j - 1), 'points': d})

        samples = self._sample(quadtree, cells, self.size, self.alpha,
                               self.size_search, maxx, maxy, 1)

        return np.array([u['id'] for u in samples])
Example #10
0
def test_should_empty_index_after_removing_multiple_added_nodes_in_all_quad_nodes():
    index = Index(INDEX_BBOX, max_items=1)
    index.insert(ITEM1, BBOX1)
    index.insert(ITEM2, INDEX_BBOX)
    index.remove(ITEM1, BBOX1)
    index.remove(ITEM2, INDEX_BBOX)
    assert len(index) == 0
    assert index.intersect(INDEX_BBOX) == []
def combine_osm_components(road,radius = 0.01):
    """
    Combines network components by finding nearest nodes
    based on a QD Tree Approach.

    Parameters
    ----------
    graph : TYPE
        DESCRIPTION.

    Returns
    -------
    None.

    """
    # Initialize QD Tree
    longitudes = [road.nodes[n]['x'] for n in road.nodes()]
    latitudes = [road.nodes[n]['y'] for n in road.nodes()]
    xmin = min(longitudes); xmax = max(longitudes)
    ymin = min(latitudes); ymax = max(latitudes)
    bbox = (xmin,ymin,xmax,ymax)
    idx = Index(bbox)
    
    # Differentiate large and small components
    comps = [c for c in list(nx.connected_components(road))]
    lencomps = [len(c) for c in list(nx.connected_components(road))]
    indlarge = lencomps.index(max(lencomps))
    node_main = list(road.subgraph(comps[indlarge]).nodes())
    del(comps[indlarge])
    
    # keep track of nodes so we can recover them later
    nodes = []
    
    # create bounding box around each point in large component
    for i,node in enumerate(node_main):
        pt = Point([road.nodes[node]['x'],road.nodes[node]['y']])
        pt_bounds = pt.x-radius, pt.y-radius, pt.x+radius, pt.y+radius
        idx.insert(i, pt_bounds)
        nodes.append((pt, pt_bounds, node))
        
    # find intersection and add edges
    edgelist = []
    for c in comps:
        node_comp = list(road.subgraph(c).nodes())
        nodepairs = []
        for n in node_comp:
            pt = Point([road.nodes[n]['x'],road.nodes[n]['y']])
            pt_bounds = pt.x-radius, pt.y-radius, pt.x+radius, pt.y+radius
            matches = idx.intersect(pt_bounds)
            closest_pt = min(matches,key=lambda i: nodes[i][0].distance(pt))
            nodepairs.append((n,nodes[closest_pt][-1]))
        
        # Get the geodesic distance
        dist = [MeasureDistance([road.nodes[p[0]]['x'],road.nodes[p[0]]['y']],
                                [road.nodes[p[1]]['x'],road.nodes[p[1]]['y']]) \
                for p in nodepairs]
        edgelist.append(nodepairs[np.argmin(dist)]+tuple([0]))
    return edgelist
Example #12
0
def test_should_empty_index_after_removing_multiple_added_nodes_in_multiple_horizontal_quad_nodes():
    index = Index(INDEX_BBOX, max_items=1)
    bbox2 = (0, 0, INDEX_BBOX[2], 1)
    index.insert(ITEM1, BBOX1)
    index.insert(ITEM2, bbox2)
    index.remove(ITEM1, BBOX1)
    index.remove(ITEM2, bbox2)
    assert len(index) == 0
    assert index.intersect(INDEX_BBOX) == []
Example #13
0
    def update(self):
        qt = Index(bbox=(0, 0, self.w, self.h), max_items=5)

        for i in range(len(self.people)):
            s = self.people[i]
            qt.insert(i, (s.x, s.y, s.x, s.y))
            s.update(self.peopleSpeed)

        for s in self.people:
            if self.distanceRadius > 0:  # 사회적 거리두기
                distance = self.distanceRadius

                for i in qt.intersect((s.x - distance, s.y - distance,
                                       s.x + distance, s.y + distance)):
                    other = self.people[i]
                    if np.sqrt((s.x - other.x) * (s.x - other.x) +
                               (s.y - other.y) * (s.y - other.y)) > distance:
                        continue

                    if s != self.people[i]:
                        direct = np.arctan2(s.y - self.people[i].y,
                                            s.x - self.people[i].x)
                        s.dx += np.cos(direct) * 2
                        s.dy += np.sin(direct) * 2

                mag = np.sqrt(s.dx * s.dx + s.dy * s.dy)
                s.dx /= mag
                s.dy /= mag

            for i in qt.intersect(
                (s.x - self.infectionRadius, s.y - self.infectionRadius,
                 s.x + self.infectionRadius, s.y + self.infectionRadius)):
                other = self.people[i]
                if np.sqrt((s.x - other.x) * (s.x - other.x) +
                           (s.y - other.y) *
                           (s.y - other.y)) > self.infectionRadius:
                    continue

                if s.status == 1 and np.random.rand() < self.infectionPercent:
                    self.people[i].GetInfection(self.recoverTime,
                                                self.reinfectionPercent)

        self.setLogData()
Example #14
0
def remove_overlapping_points(new_points, missed_points_coord):
    d_y = 1/222222.0 ## 0.5 meters
    d_x = np.cos(missed_points_coord[0][1] / (180 / np.pi))/222222.0 ## 0.5 meters
    missed_new_points_qtree = Index(bbox=(np.amin(new_points[:,0]), np.amin(new_points[:,1]), np.amax(new_points[:,0]), np.amax(new_points[:,1])))
    for n in new_points:
        if not missed_new_points_qtree.intersect((n[0] - d_x, n[1] - d_y, n[0] + d_x, n[1] + d_y)):
            missed_new_points_qtree.insert(n, bbox=(n[0], n[1], n[0], n[1]))
    new_points = missed_new_points_qtree.intersect((np.amin(new_points[:,0]), np.amin(new_points[:,1]), np.amax(new_points[:,0]), np.amax(new_points[:,1])))
    missed_points_qtree = Index(bbox=(np.amin(missed_points_coord[:, 0]), np.amin(missed_points_coord[:,1]), np.amax(missed_points_coord[:,0]), np.amax(missed_points_coord[:, 1])))
    checked_points = []
    
    for p in missed_points_coord:
        missed_points_qtree.insert(p, (p[0], p[1], p[0], p[1]))
    for i in trange(len(new_points), desc='check for double points'):
        mp = new_points[i]
        if not missed_points_qtree.intersect((mp[0] - d_x, mp[1] - d_y, mp[0] + d_x, mp[1] + d_y)):
            checked_points.append(mp)
    
    return checked_points
def combine_components(graph,cords,radius = 0.01):
    """
    Combines network components by finding nearest nodes
    based on a QD Tree Approach.

    Parameters
    ----------
    graph : TYPE
        DESCRIPTION.

    Returns
    -------
    None.

    """
    # Initialize QD Tree
    xmin,ymin = np.min(np.array(list(cords.values())),axis=0)
    xmax,ymax = np.max(np.array(list(cords.values())),axis=0)
    bbox = (xmin,ymin,xmax,ymax)
    idx = Index(bbox)
    
    # Differentiate large and small components
    comps = [c for c in list(nx.connected_components(graph))]
    lencomps = [len(c) for c in list(nx.connected_components(graph))]
    indlarge = lencomps.index(max(lencomps))
    node_main = list(graph.subgraph(comps[indlarge]).nodes())
    del(comps[indlarge])
    
    # keep track of lines so we can recover them later
    nodes = []
    
    # create bounding box around each point in large component
    for i,node in enumerate(node_main):
        pt = Point(cords[node])
        pt_bounds = pt.x-radius, pt.y-radius, pt.x+radius, pt.y+radius
        idx.insert(i, pt_bounds)
        nodes.append((pt, pt_bounds, node))
        
    # find intersection and add edges
    edgelist = []
    for c in comps:
        node_comp = list(graph.subgraph(c).nodes())
        nodepairs = []
        for n in node_comp:
            pt = Point(cords[n])
            pt_bounds = pt.x-radius, pt.y-radius, pt.x+radius, pt.y+radius
            matches = idx.intersect(pt_bounds)
            closest_pt = min(matches,key=lambda i: nodes[i][0].distance(pt))
            nodepairs.append((n,nodes[closest_pt][-1]))
        dist = [MeasureDistance(cords[p[0]],cords[p[1]]) for p in nodepairs]
        edgelist.append(nodepairs[np.argmin(dist)])
    return edgelist
Example #16
0
    def update(self):
        collisionIndex = Index((0, 0, 800, 600))
        for o in self.gameObjects:
            o.update()
            if o.collidable:
                collisionIndex.insert(
                    o, (o.rect.left, o.rect.top, o.rect.right, o.rect.bottom))

        for i in self.collidableObjects:
            collisions = collisionIndex.intersect(
                (i.rect.left, i.rect.top, i.rect.right, i.rect.bottom))

            if (len(collisions) > 1):  # Intersecting more than self
                # logging.info("Collision!")
                CollisionHandler(collisions)
class BlockSearch(object):
    def __init__(self, blocks):
        bboxs = [block.bounding_box for block in blocks]
        xmax = max([bb.x + bb.width for bb in bboxs])
        ymax = max([bb.y + bb.height for bb in bboxs])
        self.spindex = PqtreeIndex(bbox=(0, 0, xmax, ymax))
        self.wrapper_map = {}
        for block in blocks:
            wrapper = DeletableWrapper(block)
            self.wrapper_map[block] = wrapper
            self.spindex.insert(wrapper, _to_bbox(block.bounding_box))

    def find_intersection_with(self, search_bounding_box):
        return [
            wrapper.data for wrapper in self.spindex.intersect(
                _to_bbox(search_bounding_box)) if not wrapper.deleted
        ]

    def remove(self, block):
        wrapper = self.wrapper_map.get(block)
        if wrapper is not None:
            wrapper.deleted = True
Example #18
0
class TreeStruct:
    bbox = (-10000, -10000, 10000, 10000)

    ##
    # Maintain link from points to rectangle objects?
    def __init__(self):
        self.index = Index(bbox=self.bbox, max_items=40, max_depth=15)

    def addRect(self, rect):
        if (bboxoutside(rect.bbox, self.bbox)):
            print('outside')
            pass  # TODO

        self.index.insert(rect, rect.bbox)

    def removeRect(self, rect):
        self.index.remove(rect, rect.bbox)

    def query(self, rect):
        candidates = self.index.intersect(rect.bbox)
        # return candidates
        # TBD if we want to make the check both ways or are okay with overlaps only being detected on one end
        return [candidate for candidate in candidates if rect.overlaps(candidate) or candidate.overlaps(rect)]
Example #19
0
xmin = min(subx)
ymax = max(suby)
ymin = min(suby)
bbox = (xmin, ymin, xmax, ymax)

# Urban substations
idx = Index(bbox)
for pos, poly in enumerate(urban_blocks):
    idx.insert(pos, poly.bounds)

#iterate through points
urban_subs = []
for i in range(len(subs)):
    point = subs.iloc[i]["geometry"]
    # iterate through spatial index
    for j in idx.intersect(point.coords[0]):
        if point.within(urban_blocks[j]):
            urban_subs.append(subs.iloc[i]["ID"])

# Rural substations
idx = Index(bbox)
for pos, poly in enumerate(rural_blocks):
    idx.insert(pos, poly.bounds)

#iterate through points
rural_subs = []
for i in range(len(subs)):
    point = subs.iloc[i]["geometry"]
    # iterate through spatial index
    for j in idx.intersect(point.coords[0]):
        if point.within(rural_blocks[j]):
Example #20
0
pbar0.close()

pyq = Index(bbox=bbox)
for i, p in enumerate(plants):
    pyq.insert(i, p.bounds)

convex_hull = Polygon([(p.x, p.y) for p in plants]).convex_hull

pbar = tqdm(total=len(voronoi_paths), position=0)
for j, f in enumerate(polys_list):
    pbar1 = tqdm(total=len(polys_list[j]), position=0)
    for i, p in enumerate(f):
        if (p.is_valid and p.within(convex_hull)) or (
                not p.is_valid and p.buffer(0).within(convex_hull)):
            bbox = p.bounds
            intersected = pyq.intersect(bbox)
            if intersected:
                for k in intersected:
                    if not np.isnan(heights_list[j][i]) and abs(
                            heights_list[j][i]) > 0 and abs(
                                heights_list[j][i]) < 10:
                        heights[j][k] = heights_list[j][i] / len(intersected)
        pbar1.update(1)
    pbar.update(1)
    pbar1.close()
pbar.close()

with open(csv_dest, "w") as file:
    writer = csv.writer(file,
                        delimiter=';',
                        quotechar='"',
Example #21
0
# repeating to see overhead
data = pickle.load(open("result1.p", "rb"))
print(len(data))
for entry in data:
    print(entry)
    (start, end, offset, length, fileName) = (entry[0], entry[1], entry[2],
                                              entry[3], 3)
    x, y, _ = hcoords(start, chromLength)
    print("x,y", x, y)
    tree.insert((start, end, offset, length, fileName), (x, y, x + 1, y + 1))

# need to store the mapping of file names to node ids
map = {
    39033: 1,
    39031: 2,
    39033: 3  # same as 1
}

overlapbbox = (0, 0, 2860, 2860)
matches = tree.intersect(overlapbbox)
print("intersect comes back")

print(len(matches))

# print(matches[0])
print("all matched nodes")
print("format is (start, end, offset, length, fileName)")
for item in matches:
    print(item)
    print(sys.getsizeof(item))
# print(sys.getsizeof(data))
        Polygon(utilv.readable_values_inv(vor.points, mx, my)).bounds)
    for i, p in enumerate(utilv.readable_values_inv(vor.points, mx, my)):
        spindex.insert({'index': i, 'coord': p}, (p[0], p[1], p[0], p[1]))

    pbar15 = tqdm(total=len(ordered), desc="sorting", position=0)
    ints = []
    for i, key in enumerate(ordered.keys()):
        if (isinstance(ordered[key]['boundary'], Polygon)
                and ordered[key]['boundary'].exterior) or isinstance(
                    ordered[key]['boundary'], MultiPolygon):
            prepped = prep(ordered[key]['boundary'])
            filtered = list(
                filter(
                    lambda a: prepped.contains(
                        Point(a['coord'][0], a['coord'][1])),
                    spindex.intersect(ordered[key]['boundary'].bounds)))
            points_list[i].extend([p['index'] for p in filtered])
        pbar15.update(1)
    pbar15.close()

    vread_values = np.vectorize(readable_values_inv,
                                excluded=["mean_x_coord", "mean_y_coord"])
    pbar2 = tqdm(total=len(ordered.keys()), desc='sorting more', position=0)
    for i, key in enumerate(ordered.keys()):
        if (isinstance(ordered[key]['boundary'], Polygon)
                and ordered[key]['boundary'].exterior) or isinstance(
                    ordered[key]['boundary'], MultiPolygon):
            prepped = prep(ordered[key]['boundary'])
            prepped_exterior = prep(
                ordered[key]['boundary'].exterior if isinstance(
                    ordered[key]['boundary'], Polygon) else unary_union(
Example #23
0
class Tiler:

    def set_extent(self, tags):
        self.max_x = max((tag.x for tag in tags)) + SHIFT
        self.min_x = min((tag.x for tag in tags)) - SHIFT

        self.max_y = max((tag.y for tag in tags)) + SHIFT
        self.min_y = min((tag.y for tag in tags)) - SHIFT

        self.origin = Point(self.min_x, self.min_y)
        max_size = max(self.max_x - self.min_x, self.max_y - self.min_y)
        self.map_size = max_size

        self.tile_size = [self.map_size / (1 << i) * METATILE_SIZE for i in range(20)]

        self.tag_to_normpos = dict()
        for tag in tags:
            x, y = tag.x, tag.y
            rel_x, rel_y = x - self.origin.x, y - self.origin.y
            norm_x, norm_y = rel_x / self.map_size, rel_y / self.map_size
            self.tag_to_normpos[tag.name] = (norm_x, norm_y)


    def set_bbox(self, tags):
        self.tag_spatial_index = Index(bbox=(self.min_x, self.min_y, self.max_x, self.max_y))
        for tag in tags:
            bbox = (tag.x, tag.y, tag.x, tag.y)
            self.tag_spatial_index.insert(tag, bbox)


    def set_postcount(self, tags):
        for tag in tags:
            tag.PostCount = int(getattr(tag, 'PostCount', -1))
        self.max_post_count = max(int(tag.PostCount) for tag in tags)


    def set_fonts(self):
        path_to_font = os.path.join(os.path.dirname(os.path.abspath(__file__)), './Verdana.ttf')
        self.fonts = [ImageFont.truetype(path_to_font, ANTIALIASING_SCALE * (25 - zoom * 2)) for zoom in range(8 + 1)]


    def __init__(self, tags):
        self.set_extent(tags)
        self.set_bbox(tags)
        self.set_postcount(tags)
        self.set_fonts()


    def search(self, name):
        return self.tag_to_normpos.get(name, '')


    def get_postcount_measure(self, tag):
        tag_count = tag.PostCount
        max_post_count = self.max_post_count
        return tag_count / max_post_count


    def get_tags_in_tile(self, meta_x, meta_y, zoom, with_shift):
        tile_size = self.tile_size[zoom]
        lower_left_corner = Point(self.origin.x + meta_x * tile_size,
                                  self.origin.y + meta_y * tile_size)

        shift = SHIFT if with_shift else 0
        tags_inside_tile = self.tag_spatial_index.intersect((lower_left_corner.x - shift, 
                                                             lower_left_corner.y - shift,
                                                             lower_left_corner.x + tile_size + shift, 
                                                             lower_left_corner.y + tile_size + shift))

        return tags_inside_tile


    def get_names_of_shown_tags(self, meta_x, meta_y, zoom):
        """
        Return the names of tags that we will show on the map.

        On low zoom levels, not all names are shown. 
        """
        if zoom >= ZOOM_TEXT_SHOW:
            # We know that all tag names will be shown anyway, so just return.
            return []

        tags_inside_tile = self.get_tags_in_tile(meta_x, meta_y, zoom, False)

        all_postcounts = sorted([(tag.PostCount, tag.name) for tag in tags_inside_tile])
        largest_tags = heapq.nlargest(TAGS_ANNOTATED_PER_TILE, all_postcounts)
        return {x[1] for x in largest_tags if x[0] > 0}


    def get_metatile(self, meta_x, meta_y, zoom):
        ''' 
        Get 8x8 rectangle of tiles, compute them at once. 
        This is faster than computing them one-by-one.

        `meta_x` and `meta_y` are coordinates of upper-left tile of the 
        generated metatile.
        '''
        meta_x /= METATILE_SIZE
        meta_y /= METATILE_SIZE

        img = Image.new('RGB', (TILE_DIM * METATILE_SIZE, 
            TILE_DIM * METATILE_SIZE), (240, 240, 240))
        draw = ImageDraw.Draw(img)

        tile_size = self.tile_size[zoom]
        lower_left_corner = Point(self.origin.x + meta_x * tile_size,
                                  self.origin.y + meta_y * tile_size)
        max_circle_rad = zoom * 1
        cnt_points = 0

        names_of_shown_tags = set()
        for dx in (-1, 0, 1):
            for dy in (-1, 0, 1):
                names_of_shown_tags.update(self.get_names_of_shown_tags(meta_x + dx, meta_y + dy, zoom))

        # Match slightly more tags, so that circles from neighbouring tiles can be drawn partially.
        tags_inside_tile = self.get_tags_in_tile(meta_x, meta_y, zoom, True)


        def get_point_from_tag(tag):
            x, y = tag.x, tag.y

            # Get coordinates from tile origin.
            point_coords = Point(x - lower_left_corner.x, y - lower_left_corner.y)
            # Now scale to TILE_DIM.
            pnt = Point(point_coords.x / tile_size * TILE_DIM * METATILE_SIZE,
                        point_coords.y / tile_size * TILE_DIM * METATILE_SIZE)
            return pnt


        for tag in tags_inside_tile:
            pnt = get_point_from_tag(tag)

            # Heuristic formula for showing post counts by circle sizes.
            post_count_measure = self.get_postcount_measure(tag)
            circle_rad = max(0.5, max_circle_rad * post_count_measure)

            draw.ellipse([pnt.x - circle_rad, pnt.y - circle_rad,
                   pnt.x + circle_rad, pnt.y + circle_rad],
                   fill=(122, 176, 42))

            cnt_points += 1

        # Draw text after all circles, so that it is not overwritten.
        # (because I did not find any kind of z-index feature in PIL)
        for tag in tags_inside_tile:
            pnt = get_point_from_tag(tag)
            fill = (0, 0, 0)
            if zoom >= ZOOM_TEXT_SHOW or tag.name in names_of_shown_tags:
                draw.text(pnt, tag.name, fill=fill, font=self.fonts[zoom])

        del draw

        return img, cnt_points
class MapLink:
    """
    This class consists of attributes and methods to evaluate the nearest road
    network link to a point. The point may be a home location or a substation.
    The algorithm uses a QD-Tree approach to evaluate a bounding box for each
    point and link then finds the nearest link to each point.
    """
    def __init__(self,road,radius=0.01):
        '''
        '''
        longitudes = [road.nodes[n]['x'] for n in road.nodes()]
        latitudes = [road.nodes[n]['y'] for n in road.nodes()]
        xmin = min(longitudes); xmax = max(longitudes)
        ymin = min(latitudes); ymax = max(latitudes)
        bbox = (xmin,ymin,xmax,ymax)
    
        # keep track of lines so we can recover them later
        all_link = list(road.edges())
        self.lines = []
    
        # initialize the quadtree index
        self.idx = Index(bbox)
        
        # add edge bounding boxes to the index
        for i, link in enumerate(all_link):
            # create line geometry
            link_geom = road.edges[link]['geometry']
        
            # bounding boxes, with padding
            x1, y1, x2, y2 = link_geom.bounds
            bounds = x1-radius, y1-radius, x2+radius, y2+radius
        
            # add to quadtree
            self.idx.insert(i, bounds)
        
            # save the line for later use
            self.lines.append((link_geom, bounds, link))
        return
    
    
    def map_point(self,points,path=os.getcwd(),fiscode='121',
                  radius=0.01):
        '''
        Finds the nearest link to the point under consideration and saves the
        map as a csv file in the specified location.
        '''
        Map2Link = {}
        for h in points.cord:
            pt = Point(points.cord[h])
            pt_bounds = pt.x-radius, pt.y-radius, pt.x+radius, pt.y+radius
            matches = self.idx.intersect(pt_bounds)
            
            # find closest path
            try:
                closest_path = min(matches, 
                                   key=lambda i: self.lines[i][0].distance(pt))
                Map2Link[h] = self.lines[closest_path][-1]
            except:
                Map2Link[h] = None
        
        # Delete unmapped points
        unmapped = [p for p in Map2Link if Map2Link[p]==None]
        for p in unmapped:
            del Map2Link[p]
        
        # Save as a csv file
        df_map = pd.DataFrame.from_dict(Map2Link,orient='index',
                                        columns=['source','target'])
        df_map.index.names = ['hid']
        df_map.to_csv(path+fiscode+'-home2link.csv')
        return Map2Link
class MapOSM:
    """
    Class consisting of attributes and methods to map OSM links to the residences
    """
    def __init__(self,road,radius=0.01):
        """
        Initializes the class object by creating a bounding box of known radius
        around each OSM road link.

        Parameters
        ----------
        road : networkx Multigraph
            The Open Street Map multigraph with node and edge attributes.
        radius : float, optional
            The radius of the bounding box around each road link. 
            The default is 0.01.

        Returns
        -------
        None.

        """
        longitudes = [road.nodes[n]['x'] for n in road.nodes()]
        latitudes = [road.nodes[n]['y'] for n in road.nodes()]
        xmin = min(longitudes); xmax = max(longitudes)
        ymin = min(latitudes); ymax = max(latitudes)
        bbox = (xmin,ymin,xmax,ymax)
        
        # keep track of edges so we can recover them later
        all_link = list(road.edges(keys=True))
        self.links = []
    
        # initialize the quadtree index
        self.idx = Index(bbox)
        
        # add edge bounding boxes to the index
        for i, link in enumerate(all_link):
            # create line geometry
            link_geom = road.edges[link]['geometry']
        
            # bounding boxes, with padding
            x1, y1, x2, y2 = link_geom.bounds
            bounds = x1-radius, y1-radius, x2+radius, y2+radius
        
            # add to quadtree
            self.idx.insert(i, bounds)
        
            # save the line for later use
            self.links.append((link_geom, bounds, link))
        return
    
    def map_point(self,points,path=os.getcwd(),fiscode='121',
                  radius=0.01):
        '''
        Finds the nearest link to the residence under consideration and saves the
        map as a csv file in the specified location.
        '''
        Map2Link = {}
        for h in points.cord:
            pt = Point(points.cord[h])
            pt_bounds = pt.x-radius, pt.y-radius, pt.x+radius, pt.y+radius
            matches = self.idx.intersect(pt_bounds)
            
            # find closest path
            try:
                closest_path = min(matches, 
                                   key=lambda i: self.links[i][0].distance(pt))
                Map2Link[h] = self.links[closest_path][-1]
            except:
                Map2Link[h] = None
        
        # Delete unmapped points
        unmapped = [p for p in Map2Link if Map2Link[p]==None]
        for p in unmapped:
            del Map2Link[p]
        
        # Save as a csv file
        df_map = pd.DataFrame.from_dict(Map2Link,orient='index',
                                        columns=['source','target','key'])
        df_map.index.names = ['hid']
        df_map.to_csv(path+fiscode+'-home2OSM.csv')
        return Map2Link
Example #26
0
def test_should_add_single_node_and_find_its_intersection():
    index = Index(INDEX_BBOX)
    index.insert(ITEM1, BBOX1)
    assert len(index) == 1
    assert index.intersect(BBOX1) == [ITEM1]
Example #27
0
def test_should_empty_index_after_removing_added_node():
    index = Index(INDEX_BBOX)
    index.insert(ITEM1, BBOX1)
    index.remove(ITEM1, BBOX1)
    assert len(index) == 0
    assert index.intersect(BBOX1) == []
Example #28
0
            'index': i,
            'plant': list(plants.loc[i, 'geometry'].coords)[0]
        }, (list(plants.loc[i, 'geometry'].coords)[0][0],
            list(plants.loc[i, 'geometry'].coords)[0][1],
            list(plants.loc[i, 'geometry'].coords)[0][0],
            list(plants.loc[i, 'geometry'].coords)[0][1]))

pbar = tqdm(total=len(polys_paths), desc="Computing areas", position=0)
for path in polys_paths:
    polys = geopandas.read_file(path)
    polys = polys.to_crs({'init': 'epsg:28992'})
    key = 'area' + re.findall(r'\d+', path)[-1]
    pbar2 = tqdm(total=len(polys.index), desc="computing areas", position=0)
    for poly in polys.loc[:, 'geometry']:
        if poly.is_valid:
            plants_i = spindex.intersect(poly.bounds)
            if isinstance(plants_i, list):
                n = sum([
                    poly.contains(Point(plant['plant'])) for plant in plants_i
                ])
                for plant in plants_i:
                    if Point(plant['plant']).within(poly):
                        plants.loc[plant['index'], key] = (poly.area / n)
            else:
                n = 1
                if Point(plants_i['plant']).within(poly):
                    plants.loc[plant['index'], key] = (poly.area / n)
        pbar2.update(1)
    pbar2.close()
    pbar.update(1)
pbar.close()
Example #29
0
pbar0.close()

pyq = Index(bbox=bbox)
for i, p in enumerate(plants):
    pyq.insert(i, p.bounds)

convex_hull = Polygon([(p.x, p.y) for p in plants]).convex_hull

pbar = tqdm(total=len(voronoi_paths), position=0)
for j, f in enumerate(polys_list):
    pbar1 = tqdm(total=len(polys_list[j]), position=0)
    for p in f:
        if (p.is_valid and p.within(convex_hull)) or (
                not p.is_valid and p.buffer(0).within(convex_hull)):
            bbox = p.bounds
            intersected = pyq.intersect(bbox)
            if intersected:
                for k in intersected:
                    areas[j][k] = p.area / len(intersected)
        pbar1.update(1)
    pbar.update(1)
    pbar1.close()
pbar.close()

#with open(csv_dest, "w") as file:
#    writer = csv.writer(file, delimiter=';', quotechar='"', quoting=csv.QUOTE_MINIMAL)
#
#    writer.writerow(['x','y'] + keys)
#    for i in range(len(plants)):
#        p = plants[i] if isinstance(plants[i], Point) else plants[i][0]
#        writer.writerow([p.x, p.y] + [areas[j][i] for j in range(len(keys))])
Example #30
0
def filter_and_merge_overlap_boxes(words,
                                   thres,
                                   maxsize,
                                   use_merge_same_line_only=False,
                                   same_line_multiplier=1.0):

    if not use_merge_same_line_only:
        words_len = [l for _, _, l in words]
        words = [(b, m) for b, m, _ in words]

    if (len(words) < 2):
        if use_merge_same_line_only:
            expand_char_mask(words, thres)
        return words

    # create quad tree
    h, w = maxsize
    spindex = Index(bbox=(0, 0, w - 1, h - 1))

    rects = [Rect((b[0], b[1]), (b[2], b[3])) for b, _ in words]
    for i, r in enumerate(rects):
        spindex.insert(i, r.as_list())

    masks = [m for _, m in words]
    is_slant = [False] * len(rects)

    for i, mask in enumerate(masks):
        mask = (mask > 0)
        proj_x = numpy.sum(mask, axis=0)

        if (mask.shape[0] > thres * 5 or mask.shape[0] <
                thres * 2) and mask.shape[1] > thres * 20 and numpy.percentile(
                    proj_x, 90) < mask.shape[0] * 0.7:
            is_slant[i] = True
        else:
            masks[i].fill(0)
            mh, mw = masks[i].shape
            masks[i][int(mh * 0.12):int(mh * 0.88), :].fill(255)

    merged_with = [set() for i in range(len(rects))]

    done = [False] * len(rects)
    new_boxes = []

    height_diff_thres = thres

    for i in range(len(rects)):
        same_line_thres = max(int(
            thres * 0.8), 5) if not use_merge_same_line_only else max(
                rects[i].height() * 0.3, thres * same_line_multiplier)
        overlapbbox = rects[i].pad(same_line_thres, 2).as_list()
        matches = spindex.intersect(overlapbbox)

        for j in matches:

            if (i == j) or is_slant[i] or is_slant[j]: continue

            same_line_thres = max(int(
                thres * 0.8), 5) if not use_merge_same_line_only else max(
                    min(rects[i].height(), rects[j].height()) * 0.3, thres *
                    same_line_multiplier)

            #if use_merge_same_line_only: height_diff_thres = max(thres, min(rects[i].height(), rects[j].height()) * 0.7)

            rule_intersect_boxes_on_same_line = rects[i].intersectY(rects[j]) > 0.8 * min(rects[i].height(), rects[j].height())  \
                                                        and rects[i].intersectX(rects[j], pad = same_line_thres) > 0 \
                                                        and rects[i].intersectX(rects[j], pad=0) < thres * 20

            rule_big_intersect_area = rects[i].intersectArea(rects[j]) > 0.33 * min(rects[i].area(), rects[j].area()) \
                                      and max(rects[i].width(), rects[j].width()) < thres * 35 \
                                      and min(rects[i].width(), rects[j].width()) < thres * 8
            #and min(rects[i].height(), rects[j].height()) > thres * 10

            rule_same_height_or_very_short_box = abs(rects[i].height() - rects[j].height()) < height_diff_thres * 0.8           \
                                                or (max(rects[i].height(), rects[j].height()) < thres * 1.8
                                                        and min(rects[i].width(), rects[j].width()) < thres * 9) \
                                                 or (abs(rects[i].height() - rects[j].height()) < thres * 1.6
                                                    and max(rects[i].height(), rects[j].height()) < thres * 3)

            rule_small_diacritic_inline = rects[i].intersectY(rects[j]) > 0.94 * rects[i].height() \
                                              and rects[i].intersectX(rects[j], pad=max(int(thres * 0.8), 5)) > 0  and (
                                              rects[i].height() < rects[j].height() * 0.4 and
                                              rects[i].width() < thres * 9) and rects[j].height() < thres * 15 and rects[j].width() > thres * 10

            if not use_merge_same_line_only:

                rule_same_width_box_intersect = rects[i].intersectX(rects[j], pad=0) > 0.9 * min(rects[i].width(),
                                                                                                 rects[j].width()) \
                                                and rects[i].intersectY(rects[j],
                                                                        pad=2) > 0 and abs(
                                                rects[i].width() - rects[j].width()) < thres \
                                                and max(rects[i].width(), rects[j].width()) < thres * 12 and min(
                                                rects[i].height(), rects[j].height()) < thres * 5  \
                                                and rects[i].height() + rects[j].height() < max(rects[i].width(), rects[j].width()) * 1.3 \
                                                and words_len[i] == 1 and words_len[j] == 1

                rule_very_big_intersect_with_height_limit = ((rects[i].intersectY(rects[j]) > 0.6 * max(rects[i].height(), rects[j].height())
                            and rects[i].intersectX(rects[j], pad = 0) > thres * 1.6)
                            or (rects[i].intersectX(rects[j]) > 0.4 * max(rects[i].width(), rects[j].width())
                                and rects[i].intersectY(rects[j]) > thres * 1.4)) and max(rects[i].height(), rects[j].height()) < thres * 3.7  \
                            and max(rects[i].width(), rects[j].width()) < thres * 30
            else:

                rule_very_big_intersect_with_height_limit = False
                rule_same_width_box_intersect = False


            if ((rule_intersect_boxes_on_same_line
                        or rule_big_intersect_area)
                    and rule_same_height_or_very_short_box) \
                    or rule_same_width_box_intersect \
                    or rule_very_big_intersect_with_height_limit \
                    or rule_small_diacritic_inline:

                merged_with[i].add(j)
                merged_with[j].add(i)

    #print('merging')
    for i in range(len(rects)):
        if not done[i]:
            new_boxes.append(merge_rect(rects, masks, i, merged_with, done))

    ### filter overlap boxes:
    is_overlap = [False] * len(new_boxes)
    spindex = Index(bbox=(0, 0, w - 1, h - 1))
    for i in range(len(new_boxes)):
        spindex.insert(i, new_boxes[i][0].as_list())

    for i in range(len(new_boxes)):
        overlapbbox = new_boxes[i][0].pad(3, 3).as_list()
        matches = spindex.intersect(overlapbbox)
        for j in matches:
            if i == j: continue
            if new_boxes[i][0].is_overlap_by(new_boxes[j][0]):
                is_overlap[i] = True
                #print('overlap')
            # if new_boxes[j][0].is_overlap_by(new_boxes[i][0]):
            #     is_overlap[j] = True
            #     #print('overlap')

    if use_merge_same_line_only:
        expand_char_mask(new_boxes, thres)

    new_boxes = [(new_boxes[i][0].as_list(), new_boxes[i][1])
                 for i in range(len(new_boxes)) if not is_overlap[i]]

    return new_boxes