def alpha_shape(points, alpha, allow_holes=True): """ Compute the alpha shape (concave hull) of a set of points. @param points: Iterable container of points. @param alpha: alpha value to influence the gooeyness of the border. Smaller numbers don't fall inward as much as larger numbers. Too large, and you lose everything! """ if len(points) < 4: return geometry.MultiPoint(list(points)).convex_hull def add_edge(edges, edge_points, coords, i, j): if (i, j) not in edges and (j, i) not in edges: edges.add((i, j)) edge_points.append(coords[[i, j]]) coords = np.array([point.coords[0] for point in points]) tri = Delaunay(coords) edges = set() edge_points = [] hole_edges = set() hole_points = [] for ia, ib, ic in tri.vertices: pa = coords[ia] pb = coords[ib] pc = coords[ic] a = math.sqrt((pa[0] - pb[0])**2 + (pa[1] - pb[1])**2) b = math.sqrt((pb[0] - pc[0])**2 + (pb[1] - pc[1])**2) c = math.sqrt((pc[0] - pa[0])**2 + (pc[1] - pa[1])**2) s = (a + b + c) / 2.0 area = math.sqrt(s * (s - a) * (s - b) * (s - c)) circum_r = a * b * c / (4.0 * area) if circum_r < 1.0 / alpha: add_edge(edges, edge_points, coords, ia, ib) add_edge(edges, edge_points, coords, ib, ic) add_edge(edges, edge_points, coords, ic, ia) else: add_edge(hole_edges, hole_points, coords, ia, ib) add_edge(hole_edges, hole_points, coords, ib, ic) add_edge(hole_edges, hole_points, coords, ic, ia) m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) if allow_holes: for tr in triangles[:]: if len(tr.boundary.coords.xy[0]) > 4: triangles.remove(tr) return cascaded_union(triangles), edge_points
def to_shapely(self): """ Convert to shapely shape Returns: shapely MultiLineString shape """ import shapely.geometry as sg def to_numpy_2d(v): a = np.array(v.as_py(), dtype=self.numpy_dtype) return a.reshape(len(v) // 2, 2) line_arrays = [to_numpy_2d(line_coords) for line_coords in self.data] lines = [sg.LineString(line_array) for line_array in line_arrays] return sg.MultiLineString(lines=lines)
def lines(self): left = self.envelope.left right = self.envelope.right top = self.envelope.top lines = [] for ii, _spacing in enumerate(self.spacings): y = top - _spacing line = LineString(((left, y), (right, y))) lines.append(line) if self.alternate_direction: for i in range(len(lines)): if i % 2: lines[i] = reverse_LineString(lines[i]) return sg.MultiLineString(lines)
def to_alt(self, projection="identity"): """ Display as Altair visualization. Parameters ---------- projection : str Defines the projection of the visualization. Defaults to a non-geographic, Cartesian projection (known by Altair as `identity`). """ from ..utils import serialize_as_altair topo_object = copy.copy(self.output) topo_object = geometry.MultiLineString(topo_object["linestrings"]) return serialize_as_altair(topo_object, geo_interface=True)
def alpha_shape(coords, alpha): """ Create alpha shape in following Burgman and Fox paper. """ # Return empty geometry if not enough points if len(coords) < 3: return MultiPolygon(), None try: tri = Delaunay(coords) except: print coords raise alledges=set() #Use a set so lines are not duplicated for ia, ib, ic in tri.vertices: add_edge(alledges, coords, ia, ib) add_edge(alledges, coords, ib, ic) add_edge(alledges, coords, ic, ia) lengths=[] for i,j in alledges: startx,starty=coords[ [i, j] ][0] stopx,stopy=coords[ [i, j] ][1] #Use coordinates to get mean length lengths+=[np.sqrt(abs(startx-stopx)**2 + abs(starty-stopy)**2)] meanLengths=sum(lengths)/len(lengths) alphadistance = meanLengths*alpha # in meters' #print "meanlength=%f, alphadistance=%f" %(meanLengths, alphadistance) # all edges less than alpha distance edges=set() edge_points = [] for ia, ib, ic in tri.vertices: pa = coords[ia] pb = coords[ib] pc = coords[ic] a = math.sqrt((pa[0]-pb[0])**2 + (pa[1]-pb[1])**2) b = math.sqrt((pb[0]-pc[0])**2 + (pb[1]-pc[1])**2) c = math.sqrt((pc[0]-pa[0])**2 + (pc[1]-pa[1])**2) if (a+b+c)/3 < alphadistance: add_edge_points(edges, edge_points, coords, ia, ib) add_edge_points(edges, edge_points, coords, ib, ic) add_edge_points(edges, edge_points, coords, ic, ia) m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) return cascaded_union(triangles), edge_points
def hatchbox(rect, angle, spacing): """ returns a Shapely geometry (MULTILINESTRING, or more rarely, GEOMETRYCOLLECTION) for a simple hatched rectangle. args: rect - a Shapely geometry for the outer boundary of the hatch Likely most useful if it really is a rectangle angle - angle of hatch lines, conventional anticlockwise -ve spacing - spacing between hatch lines GEOMETRYCOLLECTION case occurs when a hatch line intersects with the corner of the clipping rectangle, which produces a point along with the usual lines. """ (llx, lly, urx, ury) = rect.bounds centre_x = (urx + llx) / 2 centre_y = (ury + lly) / 2 diagonal_length = ((urx - llx)**2 + (ury - lly)**2)**0.5 number_of_lines = 2 + int(diagonal_length / spacing) hatch_length = spacing * (number_of_lines - 1) # build a square (of side hatch_length) horizontal lines # centred on centroid of the bounding box, 'spacing' units apart coords = [] for i in range(number_of_lines): if i % 2: coords.extend([((centre_x - hatch_length / 2, centre_y - hatch_length / 2 + i * spacing), (centre_x + hatch_length / 2, centre_y - hatch_length / 2 + i * spacing))]) else: coords.extend([((centre_x + hatch_length / 2, centre_y - hatch_length / 2 + i * spacing), (centre_x - hatch_length / 2, centre_y - hatch_length / 2 + i * spacing))]) # turn array into Shapely object lines = sg.MultiLineString(coords) # Rotate by angle around box centre lines = sa.rotate(lines, angle, origin='centroid', use_radians=False) # return clipped array return rect.intersection(lines)
def EdgeSplitShapely(lst_edges): lines = [] for edge in lst_edges: t = Topo(edge) x_lst = [] y_lst = [] for vertex in t.vertices(): pnt = BRep_Tool().Pnt(vertex) x_lst.append(pnt.X()) y_lst.append(pnt.Y()) line = geometry.LineString([[x_lst[0],y_lst[0]],[x_lst[1],y_lst[1]]]) lines.append(line) multi_line = geometry.MultiLineString(lines) merge_line = ops.linemerge(multi_line) print(merge_line)
def polygons(self, bbox=None, assumewater=False): coastline = geo.MultiLineString(self.coastlinesegments) if bbox == None: bboxpolygon = coastline.envelope else: bboxpolygon = wkt.loads(Rec(*bbox).wkt) hydropolygons = coastline2polygon(bboxpolygon, coastline.geoms, assumewater=assumewater) for p in hydropolygons: exterior = tuple(p.exterior.coords) interiors = tuple( (tuple(interior.coords) for interior in p.interiors)) yield (exterior, ) + interiors
def flatten_beziers_with_rungs(self): input_paths = [self.flatten([path]) for path in self.csp] input_paths = [shgeo.LineString(path[0]) for path in input_paths] paths = input_paths[:] paths.sort(key=lambda path: path.length, reverse=True) # Imagine a satin column as a curvy ladder. # The two long paths are the "rails" of the ladder. The remainder are # the "rungs". rails = paths[:2] rungs = shgeo.MultiLineString(paths[2:]) # The rails should stay in the order they were in the original CSP. # (this lets the user control where the satin starts and ends) rails.sort(key=lambda rail: input_paths.index(rail)) result = [] for rail in rails: if not rail.is_simple: self.fatal( _("One or more rails crosses itself, and this is not allowed. Please split into multiple satin columns." )) # handle null intersections here? linestrings = shapely.ops.split(rail, rungs) print >> dbg, "rails and rungs", [str(rail) for rail in rails ], [str(rung) for rung in rungs] if len(linestrings.geoms) < len(rungs.geoms) + 1: self.fatal( _("satin column: One or more of the rungs doesn't intersect both rails." ) + " " + _("Each rail should intersect both rungs once.")) elif len(linestrings.geoms) > len(rungs.geoms) + 1: self.fatal( _("satin column: One or more of the rungs intersects the rails more than once." ) + " " + _("Each rail should intersect both rungs once.")) paths = [[inkstitch.Point(*coord) for coord in ls.coords] for ls in linestrings.geoms] result.append(paths) return zip(*result)
def get_ann_max_bound(parsed_data): # https://shapely.readthedocs.io/en/stable/manual.html#LineString # https://shapely.readthedocs.io/en/stable/manual.html#MultiLineString # https://shapely.readthedocs.io/en/stable/manual.html#object.bounds collection = [] for strokes in parsed_data["layers"]: for _, st_value in strokes["strokes"].items(): for _, sg_value in st_value["segments"].items(): for points in sg_value["points"]: line = geom.LineString([(float(p[0]), float(p[1])) for p in points]) collection.append(line) (minx, miny, maxx, maxy) = geom.MultiLineString(collection).bounds return (maxx, maxy)
def build_taxiway_areas(tile, airport_layer, dico_airports): for airport in dico_airports: wayid_list = dico_airports[airport]['taxiway'] taxiways = geometry.MultiLineString([ geometry.LineString( numpy.round( numpy.array([ airport_layer.dicosmn[nodeid] for nodeid in airport_layer.dicosmw[wayid] ]) - numpy.array([[tile.lon, tile.lat]]), 7)) for wayid in wayid_list ]) taxiways = VECT.ensure_MultiPolygon( VECT.improved_buffer(taxiways, 15, 3, 0.5)) dico_airports[airport]['taxiway'] = (taxiways, dico_airports[airport]['taxiway']) return
def alpha_shape(points, alpha): ''' Function optimizes ishorhone with alpha-shape algorythm and returns polgon ''' if len(points) < 4: return geometry.MultiPoint(list(points)).convex_hull def add_edge(edges, edge_points, coords, i, j): if (i, j) in edges or (j, i) in edges: return edges.add((i, j)) edge_points.append(coords[[i, j]]) coords = np.array([point for point in points]) tri = Delaunay(coords) edges = set() edge_points = [] for ia, ib, ic in tri.vertices: pa = coords[ia] pb = coords[ib] pc = coords[ic] a = math.sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2) b = math.sqrt((pb[0] - pc[0]) ** 2 + (pb[1] - pc[1]) ** 2) c = math.sqrt((pc[0] - pa[0]) ** 2 + (pc[1] - pa[1]) ** 2) s = (a + b + c) / 2.0 try: area = math.sqrt(s * (s - a) * (s - b) * (s - c)) except ValueError: area = 0.0001 if area == 0: area = 0.0001 circum_r = a * b * c / (4.0 * area) if circum_r < 1.0 / alpha: add_edge(edges, edge_points, coords, ia, ib) add_edge(edges, edge_points, coords, ib, ic) add_edge(edges, edge_points, coords, ic, ia) m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) return cascaded_union(triangles), edge_points
def concave_hull(points, alpha): """ from https://gist.github.com/dwyerk/10561690 Compute the alpha shape (concave hull) of a set of points. @param points: Iterable container of points. @param alpha: alpha value to influence the gooeyness of the border. Smaller numbers don't fall inward as much as larger numbers. Too large, and you lose everything! """ if len(points) < 4: # When you have a triangle, there is no sense # in computing an alpha shape. return geometry.MultiPoint(list(points)).convex_hull coords = np.array([point.coords[0] for point in points]) tri = Delaunay(coords) triangles = coords[tri.vertices] a = ((triangles[:, 0, 0] - triangles[:, 1, 0])**2 + (triangles[:, 0, 1] - triangles[:, 1, 1])**2)**0.5 b = ((triangles[:, 1, 0] - triangles[:, 2, 0])**2 + (triangles[:, 1, 1] - triangles[:, 2, 1])**2)**0.5 c = ((triangles[:, 2, 0] - triangles[:, 0, 0])**2 + (triangles[:, 2, 1] - triangles[:, 0, 1])**2)**0.5 s = (a + b + c) / 2.0 areas = (s * (s - a) * (s - b) * (s - c))**0.5 circums = a * b * c / (4.0 * areas) filtered = triangles[circums < (1.0 / alpha)] edge1 = filtered[:, (0, 1)] edge2 = filtered[:, (1, 2)] edge3 = filtered[:, (2, 0)] edge_points = np.unique(np.concatenate((edge1, edge2, edge3)), axis=0).tolist() m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) return cascaded_union(triangles), edge_points
def multigeom(geoms: Iterable[Geometry]) -> Geometry: """ Construct Multi{Polygon|LineString|Point} """ geoms = [g for g in geoms] # force into list src_type = {g.type for g in geoms} if len(src_type) > 1: raise ValueError("All Geometries must be of the same type") crs = common_crs(geoms) # will raise if some differ raw_geoms = [g.geom for g in geoms] src_type = src_type.pop() if src_type == 'Polygon': return Geometry(geometry.MultiPolygon(raw_geoms), crs) elif src_type == 'Point': return Geometry(geometry.MultiPoint(raw_geoms), crs) elif src_type == 'LineString': return Geometry(geometry.MultiLineString(raw_geoms), crs) raise ValueError("Only understand Polygon|LineString|Point")
def _ReadKmlBorder(kml_path, root_id='Placemark'): """Gets the border defined in a KML. Args: kml_path: The path name to the border file KML or KMZ. root_id_zone: The root id defininig a zone. Usually it is 'Placemark'. Returns: A dictionary of |shapely| LineString keyed by their names. """ if kml_path.endswith('kmz'): with zipfile.ZipFile(kml_path) as kmz: kml_name = [ info.filename for info in kmz.infolist() if os.path.splitext(info.filename)[1] == '.kml' ][0] with kmz.open(kml_name) as kml_file: root = parser.parse(kml_file).getroot() else: with open(kml_path, 'r') as kml_file: root = parser.parse(kml_file).getroot() tag = root.tag[:root.tag.rfind('}') + 1] linetrings_dict = {} for element in root.findall('.//' + tag + root_id): # Ignore nested root_id within root_id if element.find('.//' + tag + root_id) is not None: continue name = element.name.text linestrings = [ _GetLineString(l) for l in element.findall('.//' + tag + 'LineString') ] if not linestrings: continue if len(linestrings) == 1: linestring = linestrings[0] else: linestring = sgeo.MultiLineString(linestrings) linetrings_dict[name] = linestring return linetrings_dict
def lines(self): lines = [] for ii, curve in enumerate(self._interpolated_curves): spacing = self.spacings[ii] y = self._e.top - spacing _curve = curve.copy() _curve[:, 1] += y line = LineString(_curve) lines.append(line) if self.alternate_direction: for i in range(len(lines)): if i % 2: lines[i] = reverse_LineString(lines[i]) lines = [l for l in lines if l.length > 0] return sg.MultiLineString(lines)
def polygons_to_cross_section(polygons, cut_segment): cuts = [0., cut_segment.length] for polygon in polygons: for side in polygon_edges(polygon): intersection = cut_segment.project(cut_segment.intersection(side)) if intersection > cuts[0] and intersection < cuts[-1] \ and intersection not in cuts: index = (ii for ii, element in enumerate(cuts) if element > intersection).next() cuts.insert(index, intersection) present = [False] * (len(cuts) - 1) for polygon in polygons: for ii, already_present in enumerate(present): if not already_present: present[ii] |= polygon.contains( cut_segment.interpolate(.5 * (cuts[ii] + cuts[ii + 1]))) return geometry.MultiLineString([[ (cuts1, 0), (cuts2, 0) ] for cuts1, cuts2, present in zip(cuts[:-1], cuts[1:], present) if present])
def apply( self, binary: np.array, *args, **kwargs ) -> List[geometry.base.BaseGeometry]: theta_res = np.deg2rad(self.theta_res) center_angle = np.deg2rad(self.center_angle) angle_variance = np.deg2rad(self.angle_variance) lines = cv2.HoughLines( binary, self.rho_res, theta_res, self.vote_threshold, min_theta=center_angle - angle_variance, max_theta=center_angle + angle_variance, ) if lines is None or len(lines) <= 0: return [] lines = lines.reshape(-1, 2) lines = [line2coords(line, binary.shape[:2]) for line in lines] return list(geometry.MultiLineString(lines))
class TestData: crs_epsg = 31370 point = sh_geom.Point((0, 0)) multipoint = sh_geom.MultiPoint([(0, 0), (10, 10), (20, 20)]) linestring = sh_geom.LineString([(0, 0), (10, 10), (20, 20)]) multilinestring = sh_geom.MultiLineString( [linestring.coords, [(100, 100), (110, 110), (120, 120)]]) polygon_with_island = sh_geom.Polygon( shell=[(0, 0), (0, 10), (1, 10), (10, 10), (10, 0), (0, 0)], holes=[[(2, 2), (2, 8), (8, 8), (8, 2), (2, 2)]]) polygon_no_islands = sh_geom.Polygon(shell=[(100, 100), (100, 110), (110, 110), (110, 100), (100, 100)]) polygon_with_island2 = sh_geom.Polygon( shell=[(20, 20), (20, 30), (21, 30), (30, 30), (30, 20), (20,20)], holes=[[(22, 22), (22, 28), (28, 28), (28, 22), (22, 22)]]) multipolygon = sh_geom.MultiPolygon([polygon_no_islands, polygon_with_island2]) geometrycollection = sh_geom.GeometryCollection([ point, multipoint, linestring, multilinestring, polygon_with_island, multipolygon]) polygon_small_island = sh_geom.Polygon( shell=[(40, 40), (40, 50), (41, 50), (50, 50), (50, 40), (40, 40)], holes=[[(42, 42), (42, 43), (43, 43), (43, 42), (42, 42)]])
def st_multiline_array(draw, min_size=0, max_size=5, geoseries=False): n = draw(st.integers(min_size, max_size)) multilines = [] for i in range(n): m = draw(st.integers(1, 5)) lines = [] for j in range(m): line_len = draw(st.integers(2, 3)) x_mid = draw(st.floats(-50, 50)) y_mid = draw(st.floats(-50, 50)) points = np.cumsum(np.random.rand(line_len, 2) - 0.5, axis=0) points[:, 0] = points[:, 0] + x_mid points[:, 1] = points[:, 1] + y_mid lines.append(sg.LineString(points)) multilines.append(sg.MultiLineString(lines)) result = from_shapely(multilines) if geoseries: result = GeoSeries(result) return result
def alpha_shape(points, alpha=0.7): """ 0.7 seems work for adt, see tests usually the problem seems to be there're just too few points to get enough triangles, if we can add more points inside the rings we can get smaller concave hull https://gist.github.com/dwyerk/10561690 Compute the alpha shape (concave hull) of a set of 2D points. :param points: Iterable container of points. :param alpha: alpha value to influence the gooeyness of the border. Smaller numbers don't fall inward as much as larger numbers. Too large, and you lose everything! """ if len(points) < 4: # When you have a triangle, there is no sense # in computing an alpha shape. return geometry.MultiPoint(list(points)).convex_hull # coords = np.array([point[0] for point in points]) coords = np.array(points) tri = Delaunay(coords) triangles = coords[tri.simplices] a = ((triangles[:, 0, 0] - triangles[:, 1, 0])**2 + (triangles[:, 0, 1] - triangles[:, 1, 1])**2)**0.5 b = ((triangles[:, 1, 0] - triangles[:, 2, 0])**2 + (triangles[:, 1, 1] - triangles[:, 2, 1])**2)**0.5 c = ((triangles[:, 2, 0] - triangles[:, 0, 0])**2 + (triangles[:, 2, 1] - triangles[:, 0, 1])**2)**0.5 s = (a + b + c) / 2.0 areas = (s * (s - a) * (s - b) * (s - c))**0.5 circums = a * b * c / (4.0 * areas) filtered = triangles[circums < (1.0 / alpha)] edge1 = filtered[:, (0, 1)] edge2 = filtered[:, (1, 2)] edge3 = filtered[:, (2, 0)] edge_points = np.unique(np.concatenate((edge1, edge2, edge3)), axis=0).tolist() m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) return cascaded_union(triangles), edge_points
def _alpha_shape(self, coords, alpha): # Compute alpha shape def add_edge(edges, edge_points, coords, i, j): # Add line between i-th and j-th point if (i, j) in edges or (j, i) in edges: return edges.add((i, j)) edge_points.append(coords[[i, j]]) tri = Delaunay(coords) totalarea = 0 edges = set() edge_points = [] # loop over triangles for ia, ib, ic in tri.vertices: pa = coords[ia] pb = coords[ib] pc = coords[ic] # squared lengths of sides of triangle a2 = (pa[0] - pb[0])**2 + (pa[1] - pb[1])**2 b2 = (pb[0] - pc[0])**2 + (pb[1] - pc[1])**2 c2 = (pc[0] - pa[0])**2 + (pc[1] - pa[1])**2 # squared area with Heron's formula A2 = (1. / 16) * (4 * (a2 * b2 + a2 * c2 + b2 * c2) - (a2 + b2 + c2)**2) circum_r2 = a2 * b2 * c2 / (4.0 * A2) # radius filter if circum_r2 < 1.0 / (alpha**2): totalarea += math.sqrt(A2) add_edge(edges, edge_points, coords, ia, ib) add_edge(edges, edge_points, coords, ib, ic) add_edge(edges, edge_points, coords, ic, ia) m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) return cascaded_union(triangles), edge_points, totalarea
def add_edge(edges, edge_points, coords, i, j): """ Add a line between the i-th and j-th points, if not in the list already """ if (i, j) in edges or (j, i) in edges: # already added return edges.add((i, j)) edge_points.append(coords[i, j]) coords = np.array([point.coords[0] for point in points]) tri = Delaunay(coords) edges = set() edge_points = [] # loop over triangles: # ia, ib, ic = indices of corner points of the # triangle for ia, ib, ic in tri.vertices: pa = coords[ia] pb = coords[ib] pc = coords[ic] # Lengths of sides of triangle a = math.sqrt((pa[0] - pb[0])**2 + (pa[1] - pb[1])**2) b = math.sqrt((pb[0] - pc[0])**2 + (pb[1] - pc[1])**2) c = math.sqrt((pc[0] - pa[0])**2 + (pc[1] - pa[1])**2) # Semiperimeter of triangle s = (a + b + c) / 2.0 # Area of triangle by Heron's formula area = math.sqrt(s * (s - a) * (s - b) * (s - c)) circum_r = a * b * c / (4.0 * area) # Here's the radius filter. #print circum_r if circum_r < 1.0 / alpha: add_edge(edges, edge_points, coords, ia, ib) add_edge(edges, edge_points, coords, ib, ic) add_edge(edges, edge_points, coords, ic, ia) m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) return cascaded_union(triangles), edge_points
def to_polygon(self, alpha=1, drive_time_query=None): print(f'[{datetime.now()}] Starting polygon calc. Buckle up that RAM.') points = [loads(node.the_geom.wkt) for node in self.models] lens = [len(node.the_geom.wkt.encode('utf-8')) for node in self.models] print( f'message size in bytes: {sum(lens)}. too big? {sum(lens)>256000}') # Skip triangles if len(points) < 4: return geometry.MultiPoint(list(points)).convex_hull coords = np.array([point.coords[0] for point in points]) tri = Delaunay(coords) triangles = coords[tri.vertices] a = ((triangles[:, 0, 0] - triangles[:, 1, 0])**2 + (triangles[:, 0, 1] - triangles[:, 1, 1])**2)**0.5 b = (((triangles[:, 1, 0] - triangles[:, 2, 0])**2 + (triangles[:, 1, 1] - triangles[:, 2, 1])**2))**0.5 c = (((triangles[:, 2, 0] - triangles[:, 0, 0])**2 + (triangles[:, 2, 1] - triangles[:, 0, 1])**2))**0.5 s = (a + b + c) / 2.0 areas = (s * (s - a) * (s - b) * (s - c))**0.5 circums = a * b * c / (4.0 * areas) filtered = triangles[circums < (1.0 / alpha)] edge1 = filtered[:, (0, 1)] edge2 = filtered[:, (1, 2)] edge3 = filtered[:, (2, 0)] edge_points = np.unique(np.concatenate((edge1, edge2, edge3)), axis=0).tolist() m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) concave_hull = cascaded_union(triangles) self.drive_time_polygon = DriveTimePolygon.objects.create( drive_time_query=drive_time_query, the_geom=concave_hull.buffer(0.005).wkt) self.drive_time_polygon.save() print(f'[{datetime.now()}] I did it!') return self.drive_time_polygon
def convert_geometries(df, pkg='pysal', strict=False): first = df['geometry'].head(1).tolist()[0] if pkg.lower() == 'pysal': from pysal.cg.shapes import Chain, Point, asShape try: df['geometry'] = pd.Series([asShape(e) for e in df['geometry']]) except: if 'Polygon' in first['type']: df['geometry'] = pd.Series([parse_polygon_to_pysal(e)\ for e in df['geometry']]) elif 'Line' in first['type']: df['geometry'] = pd.Series([Chain(e['coordinates'])\ for e in df['geometry']]) elif 'MultiPoint' in first['type']: df['geometry'] = pd.Series([[Point(c) for c in e['coordinates']]\ for e in df['geometry']]) elif 'Point' in first['type']: df['geometry'] = pd.Series([Point(e['coordinates'][0])\ for e in df['geometry']]) elif pkg.lower() == 'shapely': from shapely import geometry as g try: df['geometry'] = pd.Series( [g.__dict__[e['type']](e) for e in df['geometry']]) except: if 'Polygon' in first['type']: df['geometry'] = pd.Series([parse_polygon_to_shapely(e, strict=strict)\ for e in df['geometry']]) elif 'MultiLine' in first['type']: df['geometry'] = pd.Series([g.MultiLineString(e['coordinates'])\ for e in df['geometry']]) elif 'MultiPoint' in first['type']: df['geometry'] = pd.Series( [g.MultiPoint(e['coordinates']) for e in df['geometry']]) elif 'Point' in first['type']: df['geometry'] = pd.Series([g.Point(e['coordinates'][0])\ for e in df['geometry']]) return df
def _convert_lines_to_multipolygon(lines): multi_line = geometry.MultiLineString(lines) merged_line = ops.linemerge(multi_line) if isinstance(merged_line, geometry.MultiLineString): polygons = [] for line in merged_line: try: poly = geometry.Polygon(line) if poly.is_valid: polygons.append(poly) else: polygons.append(poly.buffer(0)) except: # throw exception print('Failed to build polygon', line) return merge_polygons_to_multipolygon(polygons) try: poly = geometry.Polygon(merged_line) except Exception as e: print('Failed to convert lines to polygon', e) traceback.print_exc() return None return geometry.MultiPolygon([poly])
def to_shape(self, remove_interior=None): """ Convert the alpha shape to a Shapely polygon object. Parameters ---------- remove_interior : float or int If remove_interior parameter is set it will attempt to remove a possible interior of a alpha shape by detecting outlying polygons in 'triangles', since interiors are often way bigger than the actual triangles. Outliers detected using a Median Absolute Deviation (MAD). """ self.m = geometry.MultiLineString(self.edge_points) self.triangles = np.array(list(polygonize(self.m))) if remove_interior is not None: tri_area = np.array([t.area for t in self.triangles]) outliers = self._find_outliers(tri_area, m=remove_interior) if type(outliers) is bool: outliers = np.array([outliers]) self.triangles = self.triangles[outliers] self.shape = cascaded_union(self.triangles)
def ground_truth_utm2map(self): pose_stamped = PoseStamped() pose_trans = PoseStamped() for i in range(0, len(self.gt_utm)): # Skip the first row if it is a String pose_stamped.pose.position = Point(self.gt_utm[i][0], self.gt_utm[i][1], 0) pose_stamped.pose.orientation = Quaternion(0,0,0,1) # GPS orientation is meaningless, set to identity #print math.atan2(self.gt_utm[i][1],self.gt_utm[i][0]) pose_trans.header.stamp = rospy.Time.now() pose_trans = tf2_geometry_msgs.do_transform_pose(pose_stamped, self.map_trans) # Transform RTK values w.r.t to "Map" frame self.gt_map[i] = ([pose_trans.pose.position.x, pose_trans.pose.position.y]) lines = [] # Increment by parameter for multiple line segments along ground truth points for ind in range((self.increment/2),len(self.gt_utm),self.increment): self.line = geom.LineString(self.gt_map[ind-(self.increment/2):ind+(self.increment/2),:]) lines.append(self.line) # print ind-(self.increment/2), ind+(self.increment/2), self.line self.multilines.append(geom.MultiLineString(lines))
def alpha_shape_numpy(points: np.ndarray, alpha: float): from shapely import geometry from shapely.ops import polygonize """ Compute the alpha shape (concave hull) of a set of points. @param points: Iterable container of points. @param alpha: alpha value to influence the gooeyness of the border. Smaller numbers don't fall inward as much as larger numbers. Too large, and you lose everything! """ if len(points) < 4: # When you have a triangle, there is no sense # in computing an alpha shape. return geometry.MultiPoint(list(points)).convex_hull coords = np.array(points) tri = Delaunay(coords) triangles = coords[tri.vertices] a = ((triangles[:, 0, 0] - triangles[:, 1, 0]) ** 2 + (triangles[:, 0, 1] - triangles[:, 1, 1]) ** 2) ** 0.5 b = ((triangles[:, 1, 0] - triangles[:, 2, 0]) ** 2 + (triangles[:, 1, 1] - triangles[:, 2, 1]) ** 2) ** 0.5 c = ((triangles[:, 2, 0] - triangles[:, 0, 0]) ** 2 + (triangles[:, 2, 1] - triangles[:, 0, 1]) ** 2) ** 0.5 s = (a + b + c) / 2.0 areas = (s*(s-a)*(s-b)*(s-c)) ** 0.5 circums = a * b * c / (4.0 * areas) filtered = triangles[circums < (1.0 / alpha)] edge1 = filtered[:, (0, 1)] edge2 = filtered[:, (1, 2)] edge3 = filtered[:, (2, 0)] edge_points = np.unique(np.concatenate((edge1, edge2, edge3)), axis = 0).tolist() m = geometry.MultiLineString(edge_points) triangles = list(polygonize(m)) return edge_points, triangles
def _project_linear_ring(self, linear_ring, src_crs): """ Projects the given LinearRing from the src_crs into this CRS and returns the resultant LinearRing or MultiLineString. """ # 1) Resolve the initial lines into projected segments # 1abc # def23ghi # jkl41 multi_line_string = cartopy.trace.project_linear( linear_ring, src_crs, self) # 2) Simplify the segments where appropriate. result_geometry = multi_line_string n_lines = len(multi_line_string) # Check for a single ring if (n_lines == 1 and numpy.allclose(multi_line_string[0].coords[0], multi_line_string[0].coords[-1])): result_geometry = LinearRing(multi_line_string[0].coords[:-1]) elif n_lines > 1: # XXX Clumsy! (NB. multi_line_string[-1] causes a # MemoryFault from shapely) line_strings = list(multi_line_string) # Check if we should stitch together the two ends. # i.e. Does the first point of the first line match the # last point of the last line? # def23ghi # jkl41abc if numpy.allclose(line_strings[0].coords[0], line_strings[-1].coords[-1]): last_coords = list(line_strings[-1].coords) first_coords = list(line_strings[0].coords)[1:] line_strings[-1] = sgeom.LineString(last_coords + first_coords) result_geometry = sgeom.MultiLineString(line_strings[1:]) return result_geometry