Beispiel #1
0
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
Beispiel #2
0
    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)
Beispiel #3
0
 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)
Beispiel #4
0
    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)
Beispiel #5
0
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
Beispiel #6
0
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)
Beispiel #7
0
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)
Beispiel #8
0
    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
Beispiel #9
0
    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)
Beispiel #10
0
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
Beispiel #12
0
    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
Beispiel #13
0
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
Beispiel #14
0
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")
Beispiel #15
0
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
Beispiel #16
0
 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)
Beispiel #17
0
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])
Beispiel #18
0
    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))
Beispiel #19
0
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)]])
Beispiel #20
0
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
Beispiel #21
0
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
Beispiel #22
0
    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
Beispiel #25
0
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
Beispiel #26
0
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))
Beispiel #29
0
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
Beispiel #30
0
    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