Beispiel #1
0
def polygon_collection_to_graph(polygon_collection, weights, split, is_contiguous, weight_attr="weight"):
    """ Convert collection of polygons to networkx graph

    Conversion of a polygon collection into a graph allows
    later graph partitioning
    :param polygon_collection:
    :param weights: weight of each polygon in collection
    :param split: split function
    :param is_contiguous: True or False (metis options)
    :param weight_attr: name of weight attribute
    :return:
    """
    if not is_iterable(polygon_collection):
        raise TypeError("Input must be a collection but is '{}'".format(type(polygon_collection)))

    if 'katana' in split.__name__:
        is_katana = True
    else:
        is_katana = False

    r_tree = r_tree_idx(polygon_collection)
    graph = nx.Graph()

    for n, polygon in enumerate(polygon_collection):
        list_of_intersecting_features, _ = intersecting_features(polygon, polygon_collection, r_tree)
        list_of_intersecting_features.remove(n)
        if list_of_intersecting_features or not is_contiguous:
            if is_katana:
                graph.add_edges_from([(n, feature) for feature in list_of_intersecting_features
                                      if not isinstance(polygon.intersection(polygon_collection[feature]), Point)])
            else:
                graph.add_edges_from([(n, feature) for feature in list_of_intersecting_features])
            graph.add_node(n, **{weight_attr: weights[n]})

    return graph
Beispiel #2
0
    def _get_nearest_edge_node(self):
        """ Get nearest node from edge

        :return:
        """
        nodes = self._edges.get_nodes()
        idx = r_tree_idx(nodes.geometry)
        edge_nodes = []
        for geom in self.nodes.geometry:
            nn = list(idx.nearest(geom.bounds, 1))
            edge_nodes.append(nodes.geometry[nn[0]])

        return Node.from_gpd(geometry=edge_nodes, crs=self._edges.crs)
Beispiel #3
0
def intersects(geometry, geometry_collection, r_tree=None):
    """ Return if geometry intersects with geometries of collection

    Use this function with large geometry collections
    :param geometry:
    :param geometry_collection:
    :param r_tree:
    :return: list of boolean of length = length(geometry_collection)
    """
    # Use Rtree to speed up !
    if r_tree is None:
        r_tree = r_tree_idx(geometry_collection)

    list_of_intersecting_features = list(r_tree.intersection(geometry.bounds))

    return [False if f not in list_of_intersecting_features else geometry.intersects(geometry_collection[f]) for f in
            range(len(geometry_collection))]
Beispiel #4
0
def dissolve(geometry_collection):
    """ Recursively join contiguous geometries in collection

    :param geometry_collection:
    :return:
    """
    if not is_iterable(geometry_collection):
        raise TypeError("Input must be a collection but is '{}'".format(type(geometry_collection)))

    while "There is still geometries to aggregate":

        joint = []
        idx = r_tree_idx(geometry_collection)
        geom_idx = []
        increment = 0

        while len(geom_idx) < len(geometry_collection):

            if increment not in geom_idx:
                geom = geometry_collection[increment]
                union_idx, union = intersecting_features(geom, geometry_collection, idx)

                if len(union) > 0:
                    joint.append(cascaded_union(union))

                for ix in union_idx:
                    idx.delete(ix, geometry_collection[ix].bounds)

                geom_idx.extend(union_idx)

            increment += 1

        if len(joint) < len(geometry_collection):
            geometry_collection = joint
        else:
            break

    return joint
Beispiel #5
0
def mask(polygon_collection, mask_collection, fast_intersection_surface):
    """ Geometry mask

    :param polygon_collection:
    :param mask_collection:
    :param fast_intersection_surface:
    :return:
    """

    # Retrieve base layer and mask geometry, split it for faster intersection
    # and explode it (to be sure there is no multi-parts)
    geometry = split_polygon_collection(polygon_collection, fast_intersection_surface, get_explode=True)
    mask_geometry = split_polygon_collection(mask_collection, fast_intersection_surface, get_explode=True)

    # Use Rtree to speed up !
    idx = r_tree_idx(mask_geometry)

    # 0. Initialization
    result = []

    for geom in geometry:
        list_of_intersecting_mask = list(idx.intersection(geom.bounds))
        within = [geom.within(mask_geometry[n]) for n in list_of_intersecting_mask]
        if not any(within):
            is_intersecting = [geom.intersects(mask_geometry[n]) for n in list_of_intersecting_mask]
            if any(is_intersecting):
                difference = geom.difference(cascaded_union([mask_geometry[n] for n in list_of_intersecting_mask]))
                if not difference.is_empty:
                    result.append(difference)
            else:
                result.append(geom)

    # Multi to single + dissolve coincident polygons
    result = explode(result)
    result = [no_artifact_unary_union(poly) for poly in dissolve(result)]

    return result
Beispiel #6
0
def nearest_feature(geometry, geometry_collection, r_tree=None):
    """ Return nearest feature from geometry collection to given geometry

    If some of the geometries intersect, the nearest feature is the one whose centroid is the closest to the centroid
    of the given geometry (but distance remains 0)
    :param geometry:
    :param geometry_collection:
    :param r_tree: rtree index corresponding to geometry collection
    :return: nearest feature index and corresponding distance
    """
    # Use Rtree to speed up !
    if r_tree is None:
        r_tree = r_tree_idx(geometry_collection)

    # Look if some geometries intersect
    list_of_intersecting_features, _ = intersecting_features(geometry, geometry_collection, r_tree)

    if list_of_intersecting_features:
        distance = [geometry.centroid.distance(geometry_collection[n].centroid) for n in list_of_intersecting_features]
        return list_of_intersecting_features[np.argmin(distance)], 0
    else:
        list_of_nearest_features = list(r_tree.nearest(geometry.bounds, 1))
        distance = [geometry.distance(geometry_collection[n]) for n in list_of_nearest_features]
        return list_of_nearest_features[np.argmin(distance)], np.min(distance)