def voronoi( points: Union[FeatureCollection, List], bbox: Optional[list] = None ) -> Feature: """Takes a FeatureCollection of points, and a bounding box, and returns a FeatureCollection of Voronoi polygons. :param points: To find the Voronoi polygons around. Points should be either FeatureCollection of points or list of points. :param bbox: A bounding box to clip. :return: A GeoJSON Feature. Example: >>> from turfpy.transformation import voronoi >>> points = [ ... [-66.9703, 40.3183], ... [-63.7763, 40.4500], ... [-65.4196, 42.13985310302137], ... [-69.5813, 43.95405461286195], ... [-65.66337553550034, 55.97088945355232], ... [-60.280418548905, 56.240669185466146], ... [-68.5129561347689, 50.12984589640148], ... [-64.2393519226657, 59.66235385923687], ... ] >>> bbox = [-70, 40, -60, 60] >>> voronoi(points, bbox) """ if isinstance(points, FeatureCollection): coords = [] for feature in points["features"]: coords.append(feature["features"][0]["geometry"]["coordinates"]) points = np.array(coords) elif isinstance(points, list): points = np.array(points) else: raise ValueError( "points should be either FeatureCollection of points of List of Points" ) vor = Voronoi(points) lines = [ ShapelyLineString(vor.vertices[line]) for line in vor.ridge_vertices if -1 not in line ] convex_hull = MultiPoint([Point(i) for i in points]).convex_hull.buffer(2) result = MultiPolygon([poly.intersection(convex_hull) for poly in polygonize(lines)]) result = MultiPolygon( [p for p in result] + [p for p in convex_hull.difference(unary_union(result))] ) if bbox is not None: w, s, e, n = bbox cliped_result = clip_by_rect(result, w, s, e, n) return Feature(geometry=cliped_result) return Feature(geometry=result)
def is_visible(player: Coordinates, tile: Coordinates, blocking_tiles: List[Coordinates]) -> bool: # take the convex hull of the player's eyes and the corners of the tile fov_polygon = MultiPoint([ (player.x + 0.5, player.y + 0.5), (tile.x, tile.y), (tile.x + 1, tile.y), (tile.x + 1, tile.y + 1), (tile.x, tile.y + 1), ]).convex_hull # carve out all the blocking tiles for bt in blocking_tiles: blocking_box = box(bt.x, bt.y, bt.x + 1, bt.y + 1) fov_polygon = fov_polygon.difference(blocking_box) if isinstance(fov_polygon, MultiPolygon): return False return True
x.get_string(sortby="Distância Euclidiana", reversesort=True)) export_to_pdf(header, data, currentProvider.name) vor = Voronoi(np.array(points)) lines = [ LineString(vor.vertices[line]) for line in vor.ridge_vertices if -1 not in line ] convex_hull = MultiPoint([Point(i) for i in points]).convex_hull.buffer(2) result = MultiPolygon( [poly.intersection(convex_hull) for poly in polygonize(lines)]) result = MultiPolygon( [p for p in result] + [p for p in convex_hull.difference(unary_union(result))]) plt.plot(float(currentProvider.longitude), float(currentProvider.latitude), 'ko') plt.text(float(currentProvider.longitude), float(currentProvider.latitude) + 0.01, 'Fornecedor ' + currentProvider.name, horizontalalignment='left', color='black') plt.axis('equal') plt.xlim(vor.min_bound[0] + 0.01, vor.max_bound[0] + 0.01) plt.ylim(vor.min_bound[1] + 0.01, vor.max_bound[1] + 0.01) for r in result: plt.fill(*zip(*np.array( list(
#0.23s vor = Voronoi(low_points) #0.85s #CUTTING the global Voronoi tassellation to avoid divergences #TO DO: it works but I don't know what it really does lines = [ LineString(vor.vertices[line]) for line in vor.ridge_vertices if -1 not in line ] convex_hull = MultiPoint([Point(i) for i in low_points]).convex_hull.buffer(2) tassel = MultiPolygon( [poly.intersection(convex_hull) for poly in polygonize(lines)]) tassel = MultiPolygon([p for p in tassel] + [p for p in convex_hull.difference(unary_union(tassel))]) #14.52 s #%% CREATING THE CIRCLES AND PLOTTING THE VORONOI TASSELLATION WITH INTERECTIONS ~ 300 s #Dictionary with the identity of all the circles in the image circles_id = [{ 'r': 10, 'c': (40, 30) }, { 'r': 5, 'c': (70, 90) }, { 'r': 15, 'c': (20, 60) }, { 'r': 13,
print('TILE 1') # tile we want to check for visibility - should be blocked tile1_x, tile1_y = 7.0, 7.0 # take the convex hull of the player's eyes and the corners of the tile tile1_fov_polygon = MultiPoint([ (eyes_x, eyes_y), (tile1_x, tile1_y), (tile1_x + 1, tile1_y), (tile1_x + 1, tile1_y + 1), (tile1_x, tile1_y + 1), ]).convex_hull print(tile1_fov_polygon) # find all of the blocking boxes that intersect that convex hull polygon print(blocking_box.intersects(tile1_fov_polygon)) # take the difference of the convex hull and the intersecting boxes print(tile1_fov_polygon.difference(blocking_box)) # you know the tile is blocked as soon as you wind up with a multipolygon print(type(tile1_fov_polygon.difference(blocking_box))) # which is already the case here print( 'is_visible?', is_visible(Coordinates(player_x, player_y), Coordinates(tile1_x, tile1_y), [Coordinates(blocking_x, blocking_y)])) print('\nTILE 2') # another tile to check for visibility - should be visible tile2_x, tile2_y = 5.0, 6.0 # take the convex hull of the player's eyes and the corners of the tile tile2_fov_polygon = MultiPoint([ (eyes_x, eyes_y), (tile2_x, tile2_y),
def draw(self, vsk: vsketch.Vsketch) -> None: print(os.getcwd()) vsk.size("a6", landscape=False, center=False) vsk.scale(1) vsk.penWidth(self.pen_width) glyph_poly = load_glyph(self.font, self.glyph, self.face_index) # normalize glyph size bounds = glyph_poly.bounds scale_factor = min( (vsk.width - 2 * self.glyph_margin) / (bounds[2] - bounds[0]), (vsk.height - 2 * self.glyph_margin) / (bounds[3] - bounds[1]), ) glyph_poly = scale(glyph_poly, scale_factor, scale_factor) bounds = glyph_poly.bounds glyph_poly = translate( glyph_poly, vsk.width / 2 - bounds[0] - (bounds[2] - bounds[0]) / 2, vsk.height / 2 - bounds[1] - (bounds[3] - bounds[1]) / 2 + self.glyph_voffset, ) if self.draw_glyph: vsk.strokeWeight(self.glyph_weight) if self.fill_glyph: vsk.fill(1) vsk.geometry(glyph_poly) if self.fill_glyph and self.glyph_chroma: angle = self.glyph_chroma_angle / 180.0 * math.pi glyph_poly_chroma1 = translate( glyph_poly, -self.glyph_chroma_offset * math.cos(angle), -self.glyph_chroma_offset * math.sin(angle), ).difference(glyph_poly) glyph_poly_chroma2 = translate( glyph_poly, self.glyph_chroma_offset * math.cos(angle), self.glyph_chroma_offset * math.sin(angle), ).difference(glyph_poly) vsk.strokeWeight(1) vsk.stroke(2) vsk.fill(2) vsk.geometry(glyph_poly_chroma1) vsk.stroke(3) vsk.fill(3) vsk.geometry(glyph_poly_chroma2) glyph_poly = unary_union( [glyph_poly, glyph_poly_chroma1, glyph_poly_chroma2]) vsk.strokeWeight(1) vsk.stroke(1) vsk.noFill() glyph_shadow = None if self.glyph_shadow: angle = self.glyph_chroma_angle / 180.0 * math.pi glyph_shadow = translate( glyph_poly, self.glyph_chroma_offset * math.cos(angle), self.glyph_chroma_offset * math.sin(angle), ).difference(glyph_poly) vsk.fill(3) vsk.stroke(3) vsk.geometry(glyph_shadow) vsk.noFill() vsk.stroke(1) glyph_poly = glyph_poly.union(glyph_shadow) if self.glyph_weight == 1: glyph_poly_ext = glyph_poly.buffer( self.glyph_space, join_style=JOIN_STYLE.mitre, ) glyph_poly_int = glyph_poly.buffer( -self.glyph_space_inside, join_style=JOIN_STYLE.mitre, ) else: buf_len = (self.glyph_weight - 1) / 2 * self.pen_width glyph_poly_ext = glyph_poly.buffer( buf_len * 2 + self.glyph_space, join_style=JOIN_STYLE.mitre, ) glyph_poly_int = glyph_poly.buffer( -buf_len - self.glyph_space_inside, join_style=JOIN_STYLE.mitre, ) if glyph_shadow is not None: glyph_poly_int = glyph_poly_int.difference(glyph_shadow) # horizontal stripes if self.draw_h_stripes: count = round( (vsk.height - 2 * self.margin) / self.h_stripes_pitch) corrected_pitch = (vsk.height - 2 * self.margin) / count hstripes = MultiLineString([[ (self.margin, self.margin + i * corrected_pitch), (vsk.width - self.margin, self.margin + i * corrected_pitch), ] for i in range(count + 1)]) vsk.geometry(hstripes.difference(glyph_poly_ext)) if self.h_stripes_inside: inside_stripes = translate(hstripes, 0, corrected_pitch / 2).intersection(glyph_poly_int) vsk.geometry(inside_stripes) if self.h_stripes_inside_chroma: chroma_offset = math.sqrt(2) * self.pen_width vsk.stroke(2) vsk.geometry( translate(inside_stripes, -chroma_offset, -chroma_offset)) vsk.stroke(3) vsk.geometry( translate(inside_stripes, chroma_offset, chroma_offset)) vsk.stroke(1) # concentric if self.draw_concentric: circle_count = int( math.ceil( math.hypot(vsk.width, vsk.height) / 2 / self.concentric_pitch)) circles = unary_union([ Point(vsk.width / 2, vsk.height / 2).buffer( (i + 1) * self.concentric_pitch, resolution=int(1 * (i + 1) * self.concentric_pitch), ).exterior for i in range(circle_count) ]) vsk.geometry( circles.difference(glyph_poly_ext).intersection( box( self.margin, self.margin, vsk.width - self.margin, vsk.height - self.margin, ))) # dots vsk.fill(1) if self.draw_dots or self.draw_cut_circles: v_pitch = self.pitch * math.tan(math.pi / 3) / 2 h_count = int((vsk.width - 2 * self.margin) // self.pitch) v_count = int((vsk.height - 2 * self.margin) // v_pitch) h_offset = (vsk.width - h_count * self.pitch) / 2 v_offset = (vsk.height - v_count * v_pitch) / 2 dot_array = [] for j in range(v_count + 1): odd_line = j % 2 == 1 for i in range(h_count + (0 if odd_line else 1)): dot = Point( h_offset + i * self.pitch + (self.pitch / 2 if odd_line else 0), v_offset + j * v_pitch, ).buffer(self.thickness / 2) if self.draw_dots: if not dot.buffer( self.thickness / 2).intersects(glyph_poly_ext): dot_array.append(dot) else: dot_array.append(dot) dots = unary_union(dot_array) if self.draw_dots: vsk.geometry(dots) if self.draw_cut_circles: if self.cut_circles_inside: op_func = lambda geom: geom.intersection(glyph_poly_int) else: op_func = lambda geom: geom.difference(glyph_poly_ext) vsk.geometry(op_func(dots)) if self.cut_circle_chroma: angle = math.pi / 6 dist = self.pitch * 0.1 vsk.fill(2) vsk.stroke(2) vsk.geometry( op_func( translate(dots, -dist * math.cos(angle), -dist * math.sin(angle)).difference(dots))) vsk.fill(3) vsk.stroke(3) vsk.geometry( op_func( translate(dots, dist * math.cos(angle), dist * math.sin(angle)).difference(dots))) vsk.fill(1) vsk.stroke(1) vsk.stroke(4) # apply line sort, see finalize() if self.draw_dot_matrix: h_count = int( (vsk.width - 2 * self.margin) // self.dot_matrix_pitch) + 1 v_count = int( (vsk.height - 2 * self.margin) // self.dot_matrix_pitch) + 1 h_pitch = (vsk.width - 2 * self.margin) / (h_count - 1) v_pitch = (vsk.height - 2 * self.margin) / (v_count - 1) mp = MultiPoint([ (self.margin + i * h_pitch, self.margin + j * v_pitch) for i, j in itertools.product(range(h_count), range(v_count)) if vsk.random(1) < self.dot_matrix_density ]) if self.draw_dot_matrix_inside: mp = mp.intersection(glyph_poly_int) else: mp = mp.difference(glyph_poly_ext) vsk.geometry(mp) vsk.vpype("color -l4 black") vsk.vpype("color -l1 black color -l2 cyan color -l3 magenta")
#how to connect some more LKFs #calculate area of each polygon and select only the small ones #calculate distance from centroid to all vertex, select top 10% vertex #make buffers around these selected vertexes, one by one #check if there is another polygon in that buffer (small or big) #if yes: connect the vertex to closest point in that buffer, draw a line, make buffer around that line, make that into a polygon, unify all 3 polygons #add a small frame (500m) along the edges of the region #this will close any floes that run accros the region edge frame = region.boundary.buffer(500) poly4 = poly_lkf.union(frame) #get difference of both = floes! floes = region.difference(poly4) #add holes (as floes) holes = unary_union(holes) floes = floes.union(holes) #save this polygons with open(outpath+'afs_poly_'+date+'_'+file_name_end, "wb") as poly_file: pickle.dump(floes, poly_file, pickle.HIGHEST_PROTOCOL) #simplify polygons #break to lines #calculate angles between them #Plotting
def along_wall( polygons: Union[Polygon, MultiPolygon], walls: GeometryCollection, known_wall_points: np.ndarray, known_waypoints: np.ndarray, wall_pts_dist: float, inner_pts_dist: float, to_wall_dist: float, min_len: float, angle_support_dist: float, slack_lower: float, slack_upper: float, consider_wall_dist: float, wall_point_distance_multiplier: float, inner_point_distance_multiplier: float, generate_corner_waypoints: bool = True, plot: bool = False, min_item_count: int = 4, max_dist_to_consider_local: float = 40.0, ) -> Tuple[MultiPoint, MultiPoint, MultiPoint]: assert isinstance(polygons, (Polygon, MultiPolygon, GeometryCollection)) if isinstance(polygons, GeometryCollection): polygons = [poly for poly in polygons if isinstance(poly, Polygon)] not_poly = [poly for poly in polygons if not isinstance(poly, Polygon)] assert all(item.length < 2.0 for item in not_poly), f"{[type(item) for item in not_poly]}" if isinstance(polygons, Polygon): polygons = [polygons] known_waypoints_mp = MultiPoint(known_waypoints) known_wallpoints_mp = MultiPoint(known_wall_points) rings: List[LinearRing] = [ interior for poly in polygons for interior in poly.interiors ] rings.extend(poly.exterior for poly in polygons) corner_points = [] wall_points = [] inner_points = [] for r in rings: if r.length < min_len: continue if generate_corner_waypoints: corner_arr = locate_corners_linear( r, slack_lower=slack_lower, slack_upper=slack_upper) corner_mp = MultiPoint(corner_arr) else: corner_mp = MultiPoint(np.zeros(shape=(0, 2))) distance_to_wall = np.array([pt.distance(r) for pt in known_wallpoints_mp]) wall_mask = distance_to_wall < consider_wall_dist current_wall_points = known_wall_points[wall_mask] current_known_wallpoints_mp = MultiPoint(current_wall_points) typical_inner_pt_dist = inner_pts_dist if len(current_known_wallpoints_mp) > 1: rest_kps = known_waypoints_mp.difference(current_known_wallpoints_mp) if (len(maybe_to_array(rest_kps)) >= min_item_count and len(maybe_to_array(current_known_wallpoints_mp)) > min_item_count): distances = nearest_dists(current_known_wallpoints_mp, rest_kps) distances = distances[(distances > 1.2) & (distances < 12.0)] if len(distances) > min_item_count: median_nearest_dist = np.median(distances) median_nearest_dist *= inner_point_distance_multiplier typical_inner_pt_dist = median_nearest_dist linear_dists = [r.project(pt) for pt in current_known_wallpoints_mp] linear_dists.append(r.length + min(linear_dists)) linear_dists = np.array(linear_dists) sort_inds = np.argsort(linear_dists) wall_dists = [ r.interpolate(wpd).distance(pt) for wpd, pt in zip(linear_dists, current_known_wallpoints_mp) ] wall_dists.append(wall_dists[0]) wall_dists = np.array(wall_dists) linear_dists = linear_dists[sort_inds] wall_dists = wall_dists[sort_inds] else: linear_dists = np.array([0.0, r.length]) wall_dists = np.array([to_wall_dist, to_wall_dist]) pt_dists = np.diff(linear_dists) mask = (pt_dists > 1.2) & (pt_dists < 20.0) if len(pt_dists[mask]) < min_item_count: typical_wall_pt_dist = wall_pts_dist else: typical_wall_pt_dist = np.median(pt_dists[mask]) gen_dist = wall_point_distance_multiplier * typical_wall_pt_dist gen_mask = pt_dists > 2 * gen_dist gen_inds = np.arange(len(linear_dists))[:-1][gen_mask] wn_sz = 4 linear_corner_dists = [r.project(pt) for pt in corner_mp] corner_inds = np.searchsorted(linear_dists, linear_corner_dists) corner_to_wall_dists = [] for i, ind in enumerate(corner_inds): local_dist_to_wall = to_wall_dist if len(wall_dists) > min_item_count: local_wall_dists = window_circular(wall_dists, ind - wn_sz, ind + 1 + wn_sz) local_linear_dists = window_circular(linear_dists, ind - wn_sz, ind + 1 + wn_sz) mask = ( abs(local_linear_dists - linear_corner_dists[i]) < max_dist_to_consider_local) local_wall_dists = local_wall_dists[mask] if len(local_wall_dists) > min_item_count: local_dist_to_wall = np.median(local_wall_dists) corner_to_wall_dists.append(local_dist_to_wall) corner_to_wall_dists = np.array(corner_to_wall_dists) for start, w_dist in zip(linear_corner_dists, corner_to_wall_dists): corner_pts, inner_pts = wall_inner_outer_linear( line=r, walls=walls, start=start, inner_dist=typical_inner_pt_dist, angle_support_dist=angle_support_dist * 0.67, from_wall_dist=w_dist, ) corner_points.extend(corner_pts) inner_points.extend(inner_pts) if len(gen_inds) > 0: gen_locs: List[np.ndarray] = [] to_wall_dists: List[np.ndarray] = [] for i in gen_inds: local_dist_to_wall = to_wall_dist if len(wall_dists) > min_item_count: local_wall_dists = window_circular(wall_dists, i - wn_sz, i + 1 + wn_sz) local_linear_dists = window_circular(linear_dists, i - wn_sz, i + 1 + wn_sz) mask = (abs(local_linear_dists - linear_dists[i]) < max_dist_to_consider_local) | ( abs(local_linear_dists - linear_dists[i + 1]) < max_dist_to_consider_local) local_wall_dists = local_wall_dists[mask] if len(local_wall_dists) > min_item_count: local_dist_to_wall = np.median(local_wall_dists) first = linear_dists[i] last = linear_dists[i + 1] open_dist = last - first n_points = round(open_dist / gen_dist) dist = open_dist / n_points tmp = np.arange(first + dist, last - dist / 2, dist) to_wall_dists.append( np.full(shape=tmp.shape, fill_value=local_dist_to_wall)) gen_locs.append(tmp) to_wall_dists = np.concatenate(to_wall_dists) gen_locs = np.concatenate(gen_locs) if plot: plot_polygon(Polygon(r), data_1=to_array(known_waypoints_mp)) plot_polygon(Polygon(r), data_1=to_array(known_wallpoints_mp)) plot_polygon(Polygon(r), data_1=to_array(current_known_wallpoints_mp)) plot_polygon( Polygon(r), data_1=to_array(MultiPoint([r.interpolate(l) for l in gen_locs])), ) plot_polygon( Polygon(r), data_1=to_array(MultiPoint([r.interpolate(l) for l in gen_locs])), data_2=to_array( MultiPoint([r.interpolate(l) for l in linear_dists])), ) gen_locs[gen_locs > r.length] -= r.length for start, w_dist in zip(gen_locs, to_wall_dists): if (not corner_mp.is_empty and r.interpolate(start).distance(corner_mp) < gen_dist): continue wall_pts, inner_pts = wall_inner_outer_linear( line=r, walls=walls, start=start, inner_dist=typical_inner_pt_dist, angle_support_dist=angle_support_dist, from_wall_dist=w_dist, ) wall_points.extend(wall_pts) inner_points.extend(inner_pts) corner_points = MultiPoint(corner_points) inner_points = MultiPoint(inner_points) wall_points = MultiPoint(wall_points) return corner_points, wall_points, inner_points
def near_wall_stats( polygons: Union[Polygon, MultiPolygon], known_wall_points: np.ndarray, known_waypoints: np.ndarray, min_len: float, maybe_wall_dist: float, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: assert isinstance(polygons, (Polygon, MultiPolygon, GeometryCollection, list)) if isinstance(polygons, (GeometryCollection, list)): polygons = [poly for poly in polygons if isinstance(poly, Polygon)] not_poly = [poly for poly in polygons if not isinstance(poly, Polygon)] assert all(item.length < 2.0 for item in not_poly), f"{[type(item) for item in not_poly]}" if isinstance(polygons, Polygon): polygons = [polygons] known_waypoints_mp = MultiPoint(known_waypoints) known_wallpoints_mp = MultiPoint(known_wall_points) rings: List[LinearRing] = [ interior for poly in polygons for interior in poly.interiors ] rings.extend(poly.exterior for poly in polygons) to_wall_distances = [] along_wall_distances = [] near_wall_to_rest_distances = [] for r in rings: if r.length < min_len: continue distance_to_wall = np.array([pt.distance(r) for pt in known_wallpoints_mp]) wall_mask = distance_to_wall < maybe_wall_dist current_wall_points = known_wall_points[wall_mask] current_known_wallpoints_mp = MultiPoint(current_wall_points) if len(current_known_wallpoints_mp) <= 1: continue rest_kps = known_waypoints_mp.difference(current_known_wallpoints_mp) if (len(maybe_to_array(current_known_wallpoints_mp)) == 0 or len(maybe_to_array(rest_kps)) == 0): near_dists = np.zeros(shape=(0, 2)) else: near_dists = nearest_dists(current_known_wallpoints_mp, rest_kps) linear_dists = [r.project(pt) for pt in current_known_wallpoints_mp] linear_dists.append(r.length + min(linear_dists)) linear_dists = np.array(linear_dists) sort_inds = np.argsort(linear_dists) to_wall_dists = [ r.interpolate(wpd).distance(pt) for wpd, pt in zip(linear_dists, current_known_wallpoints_mp) ] to_wall_dists.append(to_wall_dists[0]) to_wall_dists = np.array(to_wall_dists) linear_dists = linear_dists[sort_inds] to_wall_dists = to_wall_dists[sort_inds] wall_pts_dists = np.diff(linear_dists) to_wall_distances.append(to_wall_dists) along_wall_distances.append(wall_pts_dists) near_wall_to_rest_distances.append(near_dists) to_wall_distances = maybe_concat(to_wall_distances) along_wall_distances = maybe_concat(along_wall_distances) near_wall_to_rest_distances = maybe_concat(near_wall_to_rest_distances) return to_wall_distances, along_wall_distances, near_wall_to_rest_distances