def tree_query(tree, queried): # tree: point, queried: polygon case_list = [] centroid_tree = STRtree(tree.geometry.representative_point()) for index, row in queried.iterrows(): if centroid_tree.query(Polygon(row['geometry'])) == []: case_list.append([]) else: point_input = [] point = centroid_tree.query(Polygon(row['geometry'])) for i in range(len(point)): if Polygon(row['geometry']).intersects(point[i]) == True: point_input.append(point[i]) case_list.append(point_input) tree['X'] = tree['geometry'].representative_point().x tree['Y'] = tree['geometry'].representative_point().y queried['Case'] = None # Initialized the attribute column for index, points in enumerate(case_list): tempID = [] for point in points: tempRow = tree.query('X == @point.x and Y == @point.y') tempID.append(tempRow['PID'].values) if tempID: queried.loc[index, 'Case'] = tempID return queried
def test_query(self): points = [Point(i, i) for i in range(10)] tree = STRtree(points) results = tree.query(Point(2, 2).buffer(0.99)) self.assertEqual(len(results), 1) results = tree.query(Point(2, 2).buffer(1.0)) self.assertEqual(len(results), 3)
def test_query(): points = [Point(i, i) for i in range(10)] tree = STRtree(points) results = tree.query(Point(2, 2).buffer(0.99)) assert len(results) == 1 results = tree.query(Point(2, 2).buffer(1.0)) assert len(results) == 3
def test_query(self): points = [Point(i, i) for i in range(10)] tree = STRtree(points) results = tree.query(Point(2,2).buffer(0.99)) self.assertEqual(len(results), 1) results = tree.query(Point(2,2).buffer(1.0)) self.assertEqual(len(results), 3)
def test_query(): points = [Point(i, i) for i in range(10)] with pytest.warns(ShapelyDeprecationWarning): tree = STRtree(points) results = tree.query(Point(2, 2).buffer(0.99)) assert len(results) == 1 results = tree.query(Point(2, 2).buffer(1.0)) assert len(results) == 3
def find_sample_points_with_data(case_dir, sample_name, spacing, wind_directions, field='U', write=False): base_points = np.loadtxt(case_dir / "sample_points.txt") base_points = base_points[:, :2] buffered_base_points = [(p, Point(p).buffer(spacing * 0.45)) for p in base_points] filename = f"{sample_name}_{field}.xyz" kept_sample_points = [] for w in wind_directions: # case_data_points = np.loadtxt(case_dir/str(w)/filename) case_data_points = orient_sample_date(case_dir / str(w), sample_name, field) # case_data_points_2D = [Point(p) for p in case_data_points[:,:2]] case_data_points_2D = MultiPoint(case_data_points[:, :2]) rtree = STRtree(case_data_points_2D) kept_sample_index = [] for idx, (p, pt) in enumerate(buffered_base_points): res = rtree.query(pt) if len(res) == 0: continue else: kept_sample_points.append(p) kept_sample_index.append(idx) for i in kept_sample_index[::-1]: buffered_base_points.pop(i) kept_sample_points = np.array(kept_sample_points) if write: np.savetxt(case_dir / f"{sample_name}_sample_points.txt", kept_sample_points) return kept_sample_points
def select_geoms_by_geometry(geoms, geometry): """Build a STRtree from geoms and returns intersection with geometry :param geoms: list of geometries you want to search from :param geometry: intersection geometry :return: list of geoms intersecting with geometry """ if shapely is None: raise_import_exception('shapely') if type(geometry) in (bytes, str): if isinstance(geometry, bytes): geometry = geometry.decode('utf-8') # assume wkt, try to load geometry = loads(geometry) tree = STRtree(geoms) # STRtree checks intersection based on bbox of the geometry only: # https://github.com/Toblerity/Shapely/issues/558 intersected_geoms = tree.query(geometry) # reverse loop because we pop elements based on index for i, intersected_geom in zip(reversed(range(len(intersected_geoms))), reversed(intersected_geoms)): if not intersected_geom.intersects(geometry): intersected_geoms.pop(i) return intersected_geoms
def _occult_layer( layers: Dict[int, LineCollection], tolerance: float, keep_occulted: bool = False ) -> Tuple[Dict[int, LineCollection], LineCollection]: """ Perform occlusion on all provided layers. Optionally returns occulted lines in a separate LineCollection. Args: layers: dictionary of LineCollections to perform occlusion on, keyed by layer ID tolerance: Max distance between start and end point to consider a path closed keep_occulted: if True, save removed lines in removed_lines LineCollection. Otherwise, removed_lines is an empty LineCollection. Returns: a tuple with two items: - new_lines, a dictionary of LineCollections for each layer ID received - removed_lines, a LineCollection of removed lines """ removed_lines = LineCollection() new_lines = {l_id: LineCollection() for l_id in layers} line_arr = [] line_arr_lines = [] for l_id, lines in layers.items(): line_arr.extend([[l_id, line] for line in lines.as_mls().geoms]) line_arr_lines.extend([line for line in lines.as_mls().geoms]) # Build R-tree from previous geometries tree = STRtree(line_arr_lines) index_by_id = dict((id(pt), i) for i, pt in enumerate(line_arr_lines)) for i, (l_id, line) in enumerate(line_arr): coords = np.array(line.coords) if not (len(coords) > 3 and math.hypot(coords[-1, 0] - coords[0, 0], coords[-1, 1] - coords[0, 1]) < tolerance): continue p = Polygon(coords) geom_idx = [index_by_id[id(g)] for g in tree.query(p)] geom_idx = [idx for idx in geom_idx if idx < i] for gi in geom_idx: # Aggregate removed lines if keep_occulted: rl = p.intersection(line_arr_lines[gi]) add_to_linecollection(removed_lines, rl) # Update previous geometries line_arr[gi][1] = line_arr[gi][1].difference(p) for (l_id, line) in line_arr: add_to_linecollection(new_lines[l_id], line) return new_lines, removed_lines
def table_polygons(self, kernel=(6, 5)): # kernel = (6, 5) fixes missed left bottom " in SNP2436020X-19100601-0-0-0-0.13 # and fixes non-contiguous table regions in SNP2436020X-19100601-1-0-0-0.03 # and avoids spilling over v sep in SNP2436020X-19000601-0-0-0-0.09 #mini_regions = self._table_regions_at_iterations((3, 3), (1,))[0] micro_regions, macro_regions = self._table_regions_at_iterations( kernel, (2, 5)) # don't do more than 5 iterations here, otherwise tables will merge over text in # SNP2436020X-19100601-0-0-0-0.14 background0 = self.text_stopper(kernel=(7, 3), iterations=1) # iterations=1 tuned via SNP2436020X-19100601-0-0-0-0.13. # kernel, see SNP2436020X-19200601-1-0-0-0.03. labels, num = skimage.morphology.label(macro_regions.astype( numpy.bool), return_num=True) from .utils.geometry import contours, Simplifier, convex_hull, convex_contours simplify = Simplifier(simplify=0) # detect border cases like bottom table in 2436020X_1925-02-27_70_98_006. tree = STRtree( [s.path for s in self.segments if s.dominant_label == Label.V]) hulls = [] #tables = numpy.zeros(self._annotations.shape, dtype=numpy.bool) for i in range(1, num + 1): added = numpy.logical_and(labels == i, micro_regions) if not added.any(): continue added = skimage.morphology.convex_hull_image(added) added = numpy.logical_and(added, numpy.logical_not(background0)) hull = convex_hull(simplify(contours(added))) segment_by = None for s in tree.query(hull): if hull.buffer(-5).contains( shapely.geometry.Point(*s.centroid.coords)): segment_by = s break if segment_by: added = numpy.logical_and(labels == i, micro_regions) added = numpy.logical_and(added, numpy.logical_not(background0)) for c in convex_contours(added): hulls.append(c) else: hulls.append(hull) return _merge_convex_all(hulls)
def split_points_into_chunks(self, MP, boxes): tree = STRtree(MP) pt_chunks = [] for b in boxes: query_geom = b pts = [o.wkt for o in tree.query(query_geom)] pt_chunks.append(pts) return pt_chunks
def _intersects(shape, polygons): tree = STRtree(polygons) indices = dict((id(polygon), index) for index, polygon in enumerate(polygons)) mask = numpy.zeros(len(polygons), dtype=bool) polygonsToCheck = tree.query(shape) indicesInShape = [indices[id(polygon)] for polygon in polygonsToCheck if shape.intersects(polygon)] mask[indicesInShape] = True return mask
def _contains(shapes, points): tree = STRtree(points) indices = dict((id(point), index) for index, point in enumerate(points)) mask = numpy.zeros(len(points), dtype=bool) for shape in shapes: pointsToCheck = tree.query(shape) indicesInShape = [indices[id(point)] for point in pointsToCheck if (shape.contains(point) or shape.intersects(point))] mask[indicesInShape] = True return mask
def test_insert_empty_geometry(self): """ Passing nothing but empty geometries results in an empty strtree. The query segfaults if the empty geometry was actually inserted. """ empty = Polygon() geoms = [empty] tree = STRtree(geoms) assert(tree._n_geoms == 0) query = Polygon([(0,0),(1,1),(2,0),(0,0)]) results = tree.query(query)
def get_results(filename): print(filename) _dir, _, _file = filename.rpartition('/') _image, _, _ext = _file.rpartition('.') _annots, _, _im_ext = _image.rpartition('.') files.append(_image) # print _image # grab the train and test annotations trains = np.load(os.path.join(args.train_dir, _annots + _ + _ext)).item() tests = np.load(filename) #print filename, maps_dir+_image, args.train_dir+_annots+_+_ext # data structure for saving the IoU values IoU_vals = np.zeros((len(tests), len(trains.keys()))) # save the train anots train_polys = [] for i in trains.keys(): # print(trains[i]['vertices']) train_polys.append(Polygon(trains[i]['vertices'])) pass s = STRtree(train_polys) # save the test annots test_polys = [] for i in range(len(tests)): poly = tests[i] poly = poly.tolist() # poly.append(poly[0]) test_poly = Polygon(poly) if not test_poly.is_valid: continue try: results = s.query(test_poly) for j in range(len(results)): _id = train_polys.index(results[j]) _intersection = train_polys[_id].intersection(test_poly).area _union = train_polys[_id].union(test_poly).area IoU_vals[i, _id] = _intersection / _union test_polys.append(test_poly) except Exception: continue # do the linear sum assignment _row, _col = lsa(1 - IoU_vals) assignment_matrix = IoU_vals[_row, _col] # compute the numbers TP = (assignment_matrix >= IoU_thresh).sum() FP = (assignment_matrix < IoU_thresh).sum() FN = len(trains.keys()) - TP return [TP, FP, FN]
def test_insert_empty_geometry(self): """ Passing nothing but empty geometries results in an empty strtree. The query segfaults if the empty geometry was actually inserted. """ empty = Polygon() geoms = [empty] tree = STRtree(geoms) assert (tree._n_geoms == 0) query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)]) results = tree.query(query)
def process_travel_edges(graph, fill_stitch_graph, shape, travel_edges): """Weight the interior edges and pre-calculate intersection with fill stitch rows.""" # Set the weight equal to 5x the edge length, to encourage travel() # to avoid them. weight_edges_by_length(graph, 5) segments = get_segments(fill_stitch_graph) # The shapely documentation is pretty unclear on this. An STRtree # allows for building a set of shapes and then efficiently testing # the set for intersection. This allows us to do blazing-fast # queries of which line segments overlap each underpath edge. strtree = STRtree(segments) # This makes the distance calculations below a bit faster. We're # not looking for high precision anyway. outline = shape.boundary.simplify(0.5 * PIXELS_PER_MM, preserve_topology=False) for ls in travel_edges: # In most cases, ls will be a simple line segment. If we're # unlucky, in rare cases we can get a tiny little extra squiggle # at the end that can be ignored. points = [InkstitchPoint(*coord) for coord in ls.coords] p1, p2 = points[0], points[-1] edge = (p1.as_tuple(), p2.as_tuple(), 'travel') for segment in strtree.query(ls): # It seems like the STRTree only gives an approximate answer of # segments that _might_ intersect ls. Refining the result is # necessary but the STRTree still saves us a ton of time. if segment.crosses(ls): start, end = segment.coords fill_stitch_graph[start][end]['segment'][ 'underpath_edges'].append(edge) # The weight of a travel edge is the length of the line segment. weight = p1.distance(p2) # Give a bonus to edges that are far from the outline of the shape. # This includes the outer outline and the outlines of the holes. # The result is that travel stitching will tend to hug the center # of the shape. weight /= ls.distance(outline) + 0.1 graph.add_edge(*edge, weight=weight) # without this, we sometimes get exceptions like this: # Exception AttributeError: "'NoneType' object has no attribute 'GEOSSTRtree_destroy'" in # <bound method STRtree.__del__ of <shapely.strtree.STRtree instance at 0x0D2BFD50>> ignored del strtree
def get_features_inside_shape(geojson_data, border_shape): optimized_shapes = katana(border_shape, SPLIT_SIZE) tree = STRtree(optimized_shapes) inside_shape = [] for feature in geojson_data['features']: shape = geometry.shape(feature['geometry']) for segment in tree.query(shape): if segment.contains(shape): inside_shape.append(feature) geojson_data['features'] = inside_shape return geojson_data
def test_query_empty_geometry(): """ Empty geometries should be filtered out. The query segfaults if the empty geometry was actually inserted. """ empty = Polygon() point = Point(1, 0.5) geoms = [empty, point] tree = STRtree(geoms) query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)]) results = tree.query(query) assert len(results) == 1 assert results[0] == point
def find_borders(polygons): str_tree = STRtree(polygons) for polygon in polygons: potentials = str_tree.query(polygon) for potential in potentials: if potential is polygon: continue intersect = potential.intersection(polygon) # if not intersect.is_empty and hasattr(intersect, 'exterior'): if not intersect.is_empty: yield intersect.convex_hull
def test_insert_empty_geometry(): """ Passing nothing but empty geometries results in an empty strtree. The query segfaults if the empty geometry was actually inserted. """ empty = Polygon() geoms = [empty] with pytest.warns(ShapelyDeprecationWarning): tree = STRtree(geoms) assert tree._n_geoms == 0 query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)]) results = tree.query(query) assert len(results) == 0
def detector_counts_time(gdf_d, gdf_s, buff, source, mu=[0], polys=None): ''' This function tallies the total counts each detector sees at each point in time. It does so by finding all detectors with the same timestep as the source, and then finding all detectors within range. Parameters ---------- gdf_d: GeoDataFrame The geodataframe containing the information for the mobile and or stationary detectors. gdf_s: GeoDataFrame The geodataframe containing the information for the mobile and or stationary sources. buff: float The maximum detection distance source: float The strength of the mobile source Returns ------- gdf_d: GeoDataFrame The geodataframe containing the information for the mobile and or stationary detectors updated with counts. ''' for index_s in range(len(gdf_s)): cols = ['detID', 'sourceID', 'counts', 'dist', 'dist2'] interaction_array = [] spoint = gdf_s.at[index_s, 'geometry'] time = gdf_s.at[index_s, 'time'] gdf_t=gdf_d[gdf_d['time'] == time] geometries = np.append(gdf_t.geometry.values, gdf_s.geometry.values) tree=STRtree(geometries) buff1 = buff/111180 d_list = tree.query(spoint.buffer(buff1)) for d in d_list: if d in gdf_t['geometry']: index = gdf_t[gdf_t['geometry']==d].index for index_d in index: if polys is None: dist = spoint.distance(d)*111180 val = tally_counts(dist, mu[0], source) gdf_d.at[index_d, 'count'] += val gdf_s.at[index_s, 'count'] += val interaction_array.append([index_d, index_s, val, dist, 0.0]) else: dist = attenu_lengths(gdf_d, gdf_s, index_d, index_s, polys) val = tally_counts_buildings(dist, mu, source) gdf_d.at[index_d, 'count'] += val gdf_s.at[index_s, 'count'] += val interaction_array.append([index_d, index_s, val, dist[0], dist[1]]) pd1 = pd.DataFrame(interaction_array, columns=cols) return pd1
def find_adjacent_polygons(in_polygon, polygon_list, buffer_size=None, Rtree=None): # find adjacent polygons # in_polygon is the center polygon # polygon_list is a polygon list without in_polygon if buffer_size is not None: center_poly = in_polygon.buffer(buffer_size) else: center_poly = in_polygon if len(polygon_list) < 1: return [], [] # https://shapely.readthedocs.io/en/stable/manual.html#str-packed-r-tree if Rtree is None: tree = STRtree(polygon_list) else: tree = Rtree # query: Returns a list of all geometries in the strtree whose extents intersect the extent of geom. # This means that a subsequent search through the returned subset using the desired binary predicate # (eg. intersects, crosses, contains, overlaps) may be necessary to further filter the results according # to their specific spatial relationships. # https://www.geeksforgeeks.org/introduction-to-r-tree/ # R-trees are faster than Quad-trees for Nearest Neighbour queries while for window queries, Quad-trees are faster than R-trees # quicker than check one by one # adjacent_polygons = [item for item in tree.query(center_poly) if item.intersection(center_poly) ] # t0= time.time() adjacent_polygons = [ item for item in tree.query(center_poly) if item.intersects(center_poly) ] adjacent_poly_idx = [ polygon_list.index(item) for item in adjacent_polygons ] # print('cost %f seconds'%(time.time() - t0)) # adjacent_polygons = [] # adjacent_poly_idx = [] # for idx, poly in enumerate(polygon_list): # if is_two_polygons_connected(poly, center_poly): # adjacent_polygons.append(poly) # adjacent_poly_idx.append(idx) # print(datetime.now(), 'find %d adjacent polygons' % len(adjacent_polygons)) return adjacent_polygons, adjacent_poly_idx
def filter_out_of_campus_points(self, whole_campus_x, whole_campus_y): """pre processing function to remove all the points that are not within campus. Args: whole_campus_x (np.array): x "utm" coordinate in integer (east axis) whole_campus_y (np.array): y "utm" coordinate in integer (north axis) Returns: filtered_x, filtered_y: x, y array with out of campus points removed. """ if configure.getboolean("Configure", "debug"): print("filtering points that are not within campus...") # open the campus boundary geojson file and read it as a polygon file = open(configure.get("Constants", "boundary_geojson_file_path")) df = geopandas.read_file(file) # translate utm to geographic lat = (whole_campus_x / 100.0) + self.min_east * 100 lon = (whole_campus_y / 100.0) + self.min_north * 100 raw_geo = utm.to_latlon(lat, lon, 10, "U") # map 2d array to shapely points stacked = np.vstack((raw_geo[1], raw_geo[0])).T s = GeoSeries(map(Point, stacked)) # query the points for faster processing. # according to https://stackoverflow.com/questions/62280398/checking-if-a-point-is-contained-in-a-polygon-multipolygon-for-many-points tree = STRtree(s) # we have to do a if check after query, according to the post res = [ o for o in tree.query(df.geometry[0]) if df.geometry[0].contains(o) ] # translate from geographic to utm filtered_stacked = np.zeros((len(res), 2)) count = 0 for point in res: filtered_stacked[count, :] = np.asarray(point.xy).reshape(1, 2) count += 1 raw_utm = utm.from_latlon(filtered_stacked[:, 1], filtered_stacked[:, 0]) filtered_x = (raw_utm[0] - self.min_east * 100) * 100 filtered_y = (raw_utm[1] - self.min_north * 100) * 100 filtered_x = filtered_x.astype(int) filtered_y = filtered_y.astype(int) if configure.getboolean("Configure", "debug"): print("filtering completed.") return filtered_x, filtered_y
def test_query_empty_geometry(self): """ Empty geometries should be filtered out. The query segfaults if the empty geometry was actually inserted. """ empty = Polygon() point = Point(1, 0.5) geoms = [empty, point] tree = STRtree(geoms) assert(tree._n_geoms == 1) query = Polygon([(0,0),(1,1),(2,0),(0,0)]) results = tree.query(query) self.assertEqual(len(results), 1) self.assertEqual(results[0], point)
def test_query_empty_geometry(self): """ Empty geometries should be filtered out. The query segfaults if the empty geometry was actually inserted. """ empty = Polygon() point = Point(1, 0.5) geoms = [empty, point] tree = STRtree(geoms) assert (tree._n_geoms == 1) query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)]) results = tree.query(query) self.assertEqual(len(results), 1) self.assertEqual(results[0], point)
def intersect(mglist, shp, shptype="POLYGON", length_area_greater_than=0.0): intersect_dict = {} s = STRtree(mglist) result = s.query(shp) isectshp = [] cellids = [] vertices = [] areas = [] lengths = [] for i, r in enumerate(result): intersect = shp.intersection(r) if shptype == "POLYGON": if intersect.area > length_area_greater_than: #cellids.append(mglist.index(r)) # this is extremely slow cellids.append(r.index) # vincent post isectshp.append(intersect) areas.append(intersect.area) vertices.append(intersect.__geo_interface__["coordinates"]) elif shptype == "POLYLINE": try: isect_iter = iter(intersect) except TypeError: isect_iter = [intersect] for isect in isect_iter: if isect.length > length_area_greater_than: #cellids.append(mglist.index(r)) # this is extremely slow cellids.append(r.index) # vincent post isectshp.append(isect) lengths.append(isect.length) vertices.append(isect.__geo_interface__["coordinates"]) else: raise NotImplementedError( "shptype '{}' is not supported!".format(shptype)) intersect_dict["intersect"] = isectshp intersect_dict["cellids"] = cellids intersect_dict["vertices"] = vertices if shptype == "POLYGON": intersect_dict["areas"] = areas elif shptype == "POLYLINE": intersect_dict["lengths"] = lengths return intersect_dict
def getNeigbors(): coordinates = [] for key in precincts_geo_data.keys(): coordinates.append(precincts_geo_data[key].get('polygon').boundary) # print(f"Total {len(precincts_geo_data.keys())} precincts") tree = STRtree(coordinates) for coordinate in coordinates: neighboring_coordinates = tree.query(coordinate) precinctId = getPIdByBoundary(coordinate) precinct = precincts_geo_data[precinctId] neighborIds = [getPIdByBoundary(n) for n in neighboring_coordinates] neighborIds.remove(precinctId) # print(f"{precinct['name']} id: {precinctId} neighbors: {[n for n in neighborIds]}") precinct["neighbors"] = neighborIds
def test_references(): """Don't crash due to dangling references""" empty = Polygon() point = Point(1, 0.5) geoms = [empty, point] tree = STRtree(geoms) empty = None point = None gc.collect() query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)]) results = tree.query(query) assert len(results) == 1 assert results[0] == Point(1, 0.5)
def test_query_empty_geometry(): """ Empty geometries should be filtered out. The query segfaults if the empty geometry was actually inserted. """ empty = Polygon() point = Point(1, 0.5) geoms = [empty, point] with pytest.warns(ShapelyDeprecationWarning): tree = STRtree(geoms) assert tree._n_geoms == 1 query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)]) results = tree.query(query) assert len(results) == 1 assert results[0] == point
def check_cnt_contain(cnts): if not cnts: return None polygons = [Polygon(np.int32(r)) for r in cnts] tree = STRtree(polygons) for cnt in cnts: query_rect = Polygon(np.int32(cnt)).buffer(1.0) result = tree.query(query_rect) if len(result) == len(polygons): return cnt areas = [p.area for p in polygons] return cnts[np.argmax(areas)]
def merge_polygon_for_demDiff_headwall_grids(dem_subsidence_shp, headwall_shp_list, output_dir, buffer_size=50): output = os.path.join( output_dir, os.path.basename( io_function.get_name_by_adding_tail(dem_subsidence_shp, 'HW_select'))) if os.path.isfile(output): print('warning, %s already exists' % output) return output # check projections? subsidence_list = vector_gpd.read_polygons_gpd(dem_subsidence_shp) headwall_all_list = [] for shp in headwall_shp_list: headwall_list = vector_gpd.read_polygons_gpd(shp) headwall_all_list.extend(headwall_list) # # https://shapely.readthedocs.io/en/stable/manual.html#str-packed-r-tree tree = STRtree(headwall_all_list) subsidence_buff_list = [ item.buffer(buffer_size) for item in subsidence_list ] select_idx = [] for idx, subsi_buff in enumerate(subsidence_buff_list): adjacent_polygons = [ item for item in tree.query(subsi_buff) if item.intersects(subsi_buff) or item.touches(subsi_buff) ] if len(adjacent_polygons) > 0: select_idx.append(idx) basic.outputlogMessage('Select %d polygons from %d ones' % (len(select_idx), len(subsidence_list))) if len(select_idx) < 1: return None # save to subset of shaepfile if vector_gpd.save_shapefile_subset_as(select_idx, dem_subsidence_shp, output) is True: return output
def test_references(self): """Don't crash due to dangling references""" empty = Polygon() point = Point(1, 0.5) geoms = [empty, point] tree = STRtree(geoms) assert (tree._n_geoms == 1) empty = None point = None gc.collect() query = Polygon([(0, 0), (1, 1), (2, 0), (0, 0)]) results = tree.query(query) self.assertEqual(len(results), 1) self.assertEqual(results[0], Point(1, 0.5))
class IndexedGeometries: def __init__(self, geometries): self.geometries = get_geometries(geometries) for i, geometry in self.geometries.items(): geometry.index = i self.spatial_index = STRtree(self.geometries) self.index = self.geometries.index def query(self, geometry): relevant_indices = [ geom.index for geom in self.spatial_index.query(geometry) ] relevant_geometries = self.geometries.loc[relevant_indices] return relevant_geometries def intersections(self, geometry): relevant_geometries = self.query(geometry) intersections = relevant_geometries.intersection(geometry) return intersections[-(intersections.is_empty | intersections.isna())] def covered_by(self, container): relevant_geometries = self.query(container) prepared_container = prep(container) if len(relevant_geometries) == 0: # in case nothing is covered return relevant_geometries else: selected_geometries = relevant_geometries.apply( prepared_container.covers) return relevant_geometries[selected_geometries] def assign(self, targets): target_geometries = get_geometries(targets) groups = [ self.covered_by(container).apply(lambda x: container_index) for container_index, container in progress( target_geometries.items(), len(target_geometries)) ] assignment = pandas.concat(groups).reindex(self.index) return assignment def enumerate_intersections(self, targets): target_geometries = get_geometries(targets) for i, target in progress(target_geometries.items(), len(target_geometries)): for j, intersection in self.intersections(target).items(): yield i, j, intersection
def _process(self, element, key=None): # Compute view port x0, x1 = self.p.x_range or element.range(0) y0, y1 = self.p.y_range or element.range(1) bounds = bounds_to_poly((x0, y0, x1, y1)) # Initialize or lookup cache with STRTree if element._plot_id in self._cache: cache = self._cache[element._plot_id] domain, tree, geom_dicts, geom_cache, area_cache = cache else: if isinstance(element, Polygons): geom_dicts = polygons_to_geom_dicts(element) elif isinstance(element, Path): geom_dicts = path_to_geom_dicts(element) geoms = [g['geometry'] for g in geom_dicts] tree = STRtree(geoms) domain = bounds geom_cache, area_cache = {}, {} self._cache.clear() cache = (domain, tree, geom_dicts, geom_cache, area_cache) self._cache[element._plot_id] = cache area = bounds.area current_zoom = compute_zoom_level(bounds, domain, self.p.zoom_levels) tol = np.sqrt(bounds.area) * self.p.tolerance_factor # Query RTree, then cull and simplify polygons new_geoms, gdict = [], {} for g in tree.query(bounds): garea = area_cache.get(id(g)) if garea is None: is_poly = 'Polygon' in g.geom_type garea = g.area if is_poly else bounds_to_poly(g.bounds).area area_cache[id(g)] = garea # Skip if geometry area is below display threshold or # does not intersect with viewport if ((self.p.display_threshold is not None and (garea/area) < self.p.display_threshold) or not g.intersects(bounds)): continue # Try to look up geometry in cache by zoom level cache_id = (id(g), current_zoom) if cache_id in geom_cache and not self.p.clip: geom_dict = geom_cache[cache_id] else: if element.vdims: gidx = find_geom(tree._geoms, g) gdict = geom_dicts[gidx] g = g.simplify(tol, self.p.preserve_topology) if not g: continue # Skip if geometry empty geom_dict = dict(gdict, geometry=g) if self.p.cache: geom_cache[cache_id] = geom_dict if self.p.clip: geom_dict = dict(geom_dict, geometry=g.intersection(bounds)) new_geoms.append(geom_dict) return element.clone(new_geoms)