Ejemplo n.º 1
0
def convex_hull_inflation(ch: ss.ConvexHull,
                          inflation_ratio: float = 0.2,
                          vertices_only: bool = True) -> ss.ConvexHull:
    """

    TODO: consider the choice of "center_of_mass"

    Parameters
    ----------
    to write

    Returns
    -------
    to write
    """
    ch_vertices = ch.points[ch.vertices]
    center_of_mass = np.mean(ch.points, axis=0)
    ch_vertices = ch_vertices - center_of_mass  # relative coord.
    ch_vertices = ch_vertices * (1 + inflation_ratio)
    ch_vertices = ch_vertices + center_of_mass
    if vertices_only:
        inflated_ch = ss.ConvexHull(ch_vertices)
    else:
        inflated_ch = ss.ConvexHull(ch_vertices, incremental=True)
        inflated_ch.add_points(ch.points[is_in_hull(ch.points, inflated_ch)])
        inflated_ch.close()
    return inflated_ch
Ejemplo n.º 2
0
    def plot(self, axis=-1, coords=[], label="", **kwargs):
        """
        Plots the polytope on the given axis.
        """
        if self.isLowerDimensional() or self.isEmpty():
            # Will not plot empty or lower-dimensional polytopes
            return

        num_coords = len(coords)
        if num_coords > 1 and num_coords <= 3:
            vertices = self.project(coords)

        if num_coords == 1 or num_coords > 3:
            raise AssertionError("Cannot plot projection onto more than 3 "
                                 "dimensions or onto 1 dimension")
        if self.n > 3 and num_coords == 0:
            raise AssertionError("Cannot plot higher dimensional polytope than"
                                 "3D")

        no_axis = axis == -1
        if no_axis:
            # Axis not passed in, create a new figure
            fig = plt.figure()
            if self.n == 2 or num_coords == 2:
                axis = fig.add_subplot(111)
            if self.n == 3 or num_coords == 3:
                axis = fig.add_subplot(111, projection='3d')

        # TODO plotting for self.n == 1
        if self.n == 2 or num_coords == 2:
            # 2D plot
            if num_coords == 0:
                # The polytope is 2D and we plot it as such
                vertices = self.vrep(return_as_matrix=True)
            co = ss.ConvexHull(vertices)
            # Filled region
            axis.fill(vertices[co.vertices, 0],
                      vertices[co.vertices, 1],
                      label=label,
                      **kwargs)
        if self.n == 3 or num_coords == 3:
            # 3D plot
            if num_coords == 0:
                # The polytope is 3D and we plot is as such
                vertices = self.vrep(return_as_matrix=True)
            co = ss.ConvexHull(vertices)
            tri = matplotlib.tri.Triangulation(vertices[:, 0],
                                               vertices[:, 1],
                                               triangles=co.simplices)
            axis.plot_trisurf(vertices[:, 0],
                              vertices[:, 1],
                              vertices[:, 2],
                              triangles=tri.triangles,
                              **kwargs)

        if no_axis:
            plt.show()
Ejemplo n.º 3
0
def get_orientation_features(mask):
    if type(mask) == sitk.SimpleITK.Image:
        mask = sitk.GetArrayFromImage(mask)

    # Get nonzero point indices if convex hull for memory reduction
    data = np.transpose(np.nonzero(mask))
    try:
        points = sp.ConvexHull(data).points

        success = False
        while not success:
            try:
                center, radii, evecs, v = of.ellipsoid_fit(points)
                success = True
            except np.linalg.linalg.LinAlgError:
                print(
                    "Encountered singular matrix, segmentation too small, dilating."
                )
                elem = morphology.ball(2)
                mask = morphology.binary_dilation(mask, elem)
                data = np.transpose(np.nonzero(mask))
                points = sp.ConvexHull(data).points
                points = of.data_regularize(points, divs=8)

        # Convert evecs to angles
        X = evecs[:, 0]
        Y = evecs[:, 1]
        Z = evecs[:, 2]

        alpha = np.arctan2(Z[0], Z[1])
        beta = np.arccos(Z[2])
        gamma = np.arctan2(X[2], Y[2])

    except sp.qhull.QhullError:
        # TODO: 2D ellipse fit
        alpha = 0
        beta = 0
        gamma = 0

    panda_labels = ['of_theta_x', 'of_theta_y', 'of_theta_z']
    orientation_features = [alpha, beta, gamma]

    panda_dict = dict(zip(panda_labels, orientation_features))

    orientation_dict = dict()
    orientation_dict['all'] = pd.Series(panda_dict)

    orientation_features = pd.Series(orientation_dict)

    return orientation_features
Ejemplo n.º 4
0
def generate_image_and_stats(data, cluster_coords, regions_image,
                             optional_params, axes):
    """Adds cluster shape to shapes image and also returns regionprops of that shape"""
    one_region_image = np.zeros((data["dimensions"][0], data["dimensions"][1]),
                                np.uint8)
    concave_hull = alphashape.alphashape(cluster_coords)
    border_points = concave_hull.exterior.coords
    list_array = []
    for coord in border_points:
        list_array.append(coord)
    # border_points = cluster_coords[spatial.ConvexHull(cluster_coords).vertices]
    hull = spatial.ConvexHull(cluster_coords)
    border_points = np.array(list_array, dtype='int32')

    regions_image = cv2.fillPoly(regions_image, np.int32([border_points]),
                                 (255, 255, 255))
    one_region_image = cv2.fillPoly(one_region_image,
                                    np.int32([border_points]), 255)

    labeled_image = label(one_region_image, background=0)
    properties = regionprops(labeled_image)
    degrees = math.degrees(properties[0].orientation)
    parameters = ((properties[0].centroid[1], properties[0].centroid[0]),
                  (int(properties[0].major_axis_length),
                   int(properties[0].minor_axis_length)), float(degrees))
    regions_image = cv2.ellipse(regions_image, parameters, (0, 0, 255))
    add_outline(border_points, axes, optional_params, properties)
    ellipticity = compute_ellipticity_area_based(data, border_points)
    return regions_image, properties, ellipticity, hull.area, hull.volume
Ejemplo n.º 5
0
def get_hulls(exp, ts):
    hulls = []
    for t in ts:
        nx_graph = exp.nx_graph[t]
        threshold = 0.1
        S = [
            nx_graph.subgraph(c).copy()
            for c in nx.connected_components(nx_graph)
        ]
        selected = [
            g for g in S
            if g.size(weight="weight") * len(g.nodes) / 10**6 >= threshold
        ]
        polys = Polygon()
        if len(selected) >= 0:
            area_max = 0
            for g in selected:
                nodes = np.array([
                    node.pos(t) for node in exp.nodes if node.is_in(t)
                    and np.all(is_in_study_zone(node, t, 1000, 150)) and (
                        node.label in g.nodes)
                ])

                if len(nodes) > 3:
                    hull = spatial.ConvexHull(nodes)
                    poly = Polygon(
                        [nodes[vertice] for vertice in hull.vertices])
                    area_hull = poly.area * 1.725**2 / (1000**2)
                    polys = polys.union(poly)
        print(t, len(selected), polys.area)
        hulls.append(polys)
    return hulls
Ejemplo n.º 6
0
def planar_hull(points, normal, origin=None, input_convex=False):
    '''
    Find the convex outline of a set of points projected to a plane.

    Arguments
    -----------
    points: (n,3) float, input points
    normal: (3) float vector, normal vector of plane
    origin: (3) float, location of plane origin
    input_convex: bool, if True we assume the input points are already from
                  a convex hull which provides a speedup.

    Returns
    -----------
    hull_lines: (n,2,2) set of unordered line segments
    T:          (4,4) float, transformation matrix
    '''
    from .points import project_to_plane

    if origin is None:
        origin = np.zeros(3)
    if not input_convex:
        pass
    planar, T = project_to_plane(points,
                                 plane_normal=normal,
                                 plane_origin=origin,
                                 return_planar=False,
                                 return_transform=True)
    hull_edges = spatial.ConvexHull(planar[:, 0:2]).simplices
    hull_lines = planar[hull_edges]
    planar_z = planar[:, 2]
    height = np.array([planar_z.min(),
                       planar_z.max()])
    return hull_lines, T, height
Ejemplo n.º 7
0
 def __init__(self,
              list_hulls,
              name="unnamed",
              mask=None,
              check_mask_outofbounds=True):
     """
     Initializes a bounding convex hull around a list of bounding
     convex hulls or series of points.
     A unity-weighted mask is computed for the region that
     falls within this convex hull
     if a mask of (y, x) coordinates is not provided.
     Otherwise if a mask is provided and the
     check_mask_outofbounds value is set the
     masked coordinates are not verified to fall within
     the hull. The latter should thus be used with some
     caution by the user, but can potentially
     significantly speed up the mask creation process for
     axis aligned regions.
     """
     self._name = name
     self._check_mask_outofbounds = check_mask_outofbounds
     self._cached_filled_mask = None
     self._vertices = points = np.vstack([
         b.corners if hasattr(b, "corners") else [b[0], b[1]]
         for b in list_hulls
     ])
     self._hull = spat.ConvexHull(points)
     if mask is None:
         self._mask, self._mask_weights = self.init_mask()
     else:
         self.sparse_mask = mask
Ejemplo n.º 8
0
def max_dist(point_list):
    """
    Find the maximum distance between two points in a point list using convex hull.
    """

    # Find the convex hull of the point set
    conv_hull = spatial.ConvexHull(point_list)

    # Find the vertices on the convex hull
    vertices = np.vstack(point_list[conv_hull.vertices])

    # Find the pairwise distances
    dists = spatial.distance.pdist(vertices)
    dists = spatial.distance.squareform(dists)

    # Find the indices of the furthest points
    idx = np.unravel_index(np.argmax(dists), dists.shape)
    idx = list(idx)

    idx1, idx2 = conv_hull.vertices[idx]
    p1, p2 = vertices[idx]

    print('The furthest points are:')
    print('Index: {}, coordinates: {}'.format(idx1, tuple(p1)))
    print('Index: {}, coordinates: {}'.format(idx2, tuple(p2)))

    return np.max(dists)
Ejemplo n.º 9
0
def get_pareto_frontier(pts):
    """
    Iteratively filter points based on the convex hull heuristic
    """
    pareto_groups = []

    # loop while there are points remaining
    while pts.shape[0]:
        # brute force if there are few points:
        if pts.shape[0] < 10:
            pareto_groups.append(get_pareto_undominated_by(pts))
            break

        # compute vertices of the convex hull
        hull_vertices = spatial.ConvexHull(pts).vertices

        # get corresponding points
        hull_pts = pts[hull_vertices]

        # get points in pts that are not convex hull vertices
        nonhull_mask = np.ones(pts.shape[0], dtype=bool)
        nonhull_mask[hull_vertices] = False
        pts = pts[nonhull_mask]

        # get points in the convex hull that are on the Pareto frontier
        pareto = get_pareto_undominated_by(hull_pts)
        pareto_groups.append(pareto)

        # filter remaining points to keep those not dominated by
        # Pareto points of the convex hull
        pts = get_pareto_undominated_by(pts, pareto)

    return np.vstack(pareto_groups)
Ejemplo n.º 10
0
def find_vectors_in_matrix(data, graph: bool = False, file_name: str = ""):
    """ Finds and returns vectors in a 2D matrix """

    labeled_array, num_features = label(
        data, structure=[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
    )  # group and label
    print(f"Group count: {config.CC_OKCYAN}%d{config.CC_ENDC}" % num_features)

    if graph:
        np.savetxt(fna(file_name, "matrix_labeled", "txt"), labeled_array, fmt="%d")

    vectors = []
    for i in range(num_features):
        index = i + 1
        indices = np.argwhere(labeled_array == index)  # find the group
        if len(indices) < THRESHOLD:  # not an important line if under threshold
            continue
        candidates = indices[spatial.ConvexHull(indices).vertices]  # convex hull
        dist_mat = spatial.distance_matrix(candidates, candidates)  # distance btw
        points = np.unravel_index(dist_mat.argmax(), dist_mat.shape)  # furthest cands
        vectors.append(
            [
                candidates[points[0]][1],
                candidates[points[0]][0],
                candidates[points[1]][1],
                candidates[points[1]][0],
            ]
        )

    print(f"Vector count: {config.CC_OKCYAN}%d{config.CC_ENDC}" % len(vectors))

    return np.array(vectors)
Ejemplo n.º 11
0
def InROI(file, Coordinates, TMin, TMax):
    from matplotlib import path
    import numpy as np
    from scipy import spatial as sp

    K = sp.ConvexHull(Coordinates).vertices
    K = np.append(K, K[0])
    XVert = Coordinates[K, 0]
    YVert = Coordinates[K, 1]
    XY = np.stack((XVert, YVert), axis=1)

    data_in = [0] * len(file['T'])
    data_out = [0] * len(file['T'])
    for i in range(len(file['X'])):
        # is it in the prescribed interval
        if i >= TMin and i <= TMax:
            p = path.Path(XY)
            if p.contains_points([(file['X'][i], file['Y'][i])]):
                data_in[i] = 1
            else:
                data_out[i] = 1

    for i, number in enumerate(data_in):
        data_in[i] = number > 0
    for i, number in enumerate(data_out):
        data_out[i] = number > 0
    return data_in, data_out
Ejemplo n.º 12
0
    def plot(self, dim_proj=[0,1], largest_ball=False, **kwargs):
        """
        Plots a 2d projection of the polytope.

        INPUTS:
            dim_proj: dimensions in which to project the polytope
        """
        if self.empty:
            print('Cannot plot empty polytope')
            return
        if len(dim_proj) != 2:
            raise ValueError('Only 2d polytopes!')
        # extract vertices components
        vertices_proj = np.hstack(self.vertices).T[:,dim_proj]
        hull = spatial.ConvexHull(vertices_proj)
        verts = [hull.points[i].tolist() for i in hull.vertices]
        verts += [verts[0]]
        codes = [Path.MOVETO] + [Path.LINETO]*(len(verts)-2) + [Path.CLOSEPOLY]
        path = Path(verts, codes)
        ax = plt.gca()
        patch = patches.PathPatch(path, **kwargs)
        ax.add_patch(patch)
        plt.xlabel(r'$x_' + str(dim_proj[0]+1) + '$')
        plt.ylabel(r'$x_' + str(dim_proj[1]+1) + '$')
        ax.autoscale_view()
        if largest_ball:
            circle = plt.Circle((self.center[0], self.center[1]), self.radius, facecolor='white', edgecolor='black')
            ax.add_artist(circle)
        return
Ejemplo n.º 13
0
    def orthogonal_projection(self, residual_variables, method='convex_hull'):

        if method == 'convex_hull':
            A_proj, b_proj, v_proj = orthogonal_projection_CHM(self.lhs_min, self.rhs_min, residual_variables)
            p_proj = Polytope(A_proj, b_proj)
            p_proj.assemble(redundant=False, vertices=v_proj)

        # elif method == 'block_elimination':
        #     drop_variables = [i+1 for i in range(self.n_variables) if i not in residual_variables]
        #     M = np.hstack((self.rhs_min, -self.lhs_min))
        #     M = cdd.Matrix([list(m) for m in M])
        #     M.rep_type = cdd.RepType.INEQUALITY
        #     M_proj = M.block_elimination(drop_variables)
        #     M_proj.canonicalize()
        #     A_proj = - np.array([list(M_proj[i])[1:] for i in range(M_proj.row_size)])
        #     b_proj = np.array([list(M_proj[i])[:1] for i in range(M_proj.row_size)])
        #     p_proj = Polytope(A_proj, b_proj)
        #     p_proj.assemble()

        elif method == 'vertex_enumeration':
            v_proj = np.hstack(self.vertices).T[:,residual_variables]
            if len(residual_variables) > 1:
                hull = spatial.ConvexHull(v_proj)
                A_proj = np.array(hull.equations)[:, :-1]
                b_proj = - np.array(hull.equations)[:, -1:]
            else:
                A_proj = np.array([[1.],[-1.]])
                b_proj = np.array([[max(v_proj)[0]],[-min(v_proj)[0]]])
            p_proj = Polytope(A_proj, b_proj)
            p_proj.assemble()

        return p_proj
Ejemplo n.º 14
0
 def compute_empirical_nodal_width(self, mode='mean') -> float:
     r"""
     Compute the set's nodal width.
     """
     cvx_hull = sp.ConvexHull(self.vec.transpose())
     cols = np.roll(cvx_hull.simplices, shift=1, axis=-1).reshape(-1)
     rows = cvx_hull.simplices.reshape(-1)
     # Form sparse coo_matrix from extracted pairs
     affinity_matrix = sparse.coo_matrix((cols * 0 + 1, (rows, cols)), shape=(cvx_hull.points.shape[0],
                                                                              cvx_hull.points.shape[0]))
     # Symmetrize the matrix to obtain an undirected graph.
     extended_row = np.concatenate([affinity_matrix.row, affinity_matrix.col])
     extended_col = np.concatenate([affinity_matrix.col, affinity_matrix.row])
     affinity_matrix.row = extended_row
     affinity_matrix.col = extended_col
     affinity_matrix.data = np.concatenate([affinity_matrix.data, affinity_matrix.data])
     affinity_matrix = affinity_matrix.tocsr().tocoo()  # Delete potential duplicate pairs
     distance = np.linalg.norm(cvx_hull.points[affinity_matrix.row, :] - cvx_hull.points[affinity_matrix.col, :],
                               axis=-1)
     if mode is 'mean':
         nodal_distance = np.mean(distance)  # average distance to neighbors
     elif mode is 'max':
         nodal_distance = np.max(distance)
     elif mode is 'median':
         nodal_distance = np.median(distance)
     else:
         raise TypeError("Parameter mode must be one of ['mean', 'max', 'median']")
     return nodal_distance
Ejemplo n.º 15
0
def crown_from_points(pts):
    if len(pts) > 3:
        hull = spatial.ConvexHull(np.stack(pts))

        return hull.simplices, np.array(
            [[hull.points[f[0]], hull.points[f[1]], hull.points[f[2]]]
             for f in hull.simplices])
Ejemplo n.º 16
0
def _prepare_hull(coordinates, hull):
    """
    Construct a hull from the coordinates given a hull type
    Will either return:
        - a bounding box array of [xmin, ymin, xmax, ymax]
        - a scipy.spatial.ConvexHull object from the Qhull library
        - a shapely shape using alpha_shape_auto
    """
    if isinstance(hull, numpy.ndarray):
        assert len(
            hull
        ) == 4, f"bounding box provided is not shaped correctly! {hull}"
        assert hull.ndim == 1, f"bounding box provided is not shaped correctly! {hull}"
        return hull
    if (hull is None) or (hull == "bbox"):
        return _bbox(coordinates)
    if HAS_SHAPELY:  # protect the isinstance check if import has failed
        if isinstance(hull, (_ShapelyPolygon, _ShapelyMultiPolygon)):
            return hull
    if HAS_PYGEOS:
        if isinstance(hull, pygeos.Geometry):
            return hull
    if isinstance(hull, str):
        if hull.startswith("convex"):
            return spatial.ConvexHull(coordinates)
        elif hull.startswith("alpha") or hull.startswith("α"):
            return alpha_shape_auto(coordinates)
    elif isinstance(hull, spatial.qhull.ConvexHull):
        return hull
    raise ValueError(f"Hull type {hull} not in the set of valid options:"
                     f" (None, 'bbox', 'convex', 'alpha', 'α', "
                     f" shapely.geometry.Polygon, pygeos.Geometry)")
Ejemplo n.º 17
0
    def make(self, key):
        density = 110000  # per cubic mm
        xyz = np.stack((design.Geometry.EPixel() & key).fetch('e_loc'))
        margin = 75
        bounds_min = xyz.min(axis=0) - margin
        bounds_max = xyz.max(axis=0) + margin
        volume = (bounds_max - bounds_min).prod() * 1e-9
        npoints = int(volume * density + 0.5)

        # generate random points that aren't too close
        min_distance = 10.0  # cells aren't not allowed any closer
        points = np.empty((npoints, 3), dtype='float32')
        replace = np.r_[:npoints]
        while replace.size:
            points[replace, :] = np.random.rand(replace.size, 3) * (bounds_max - bounds_min) + bounds_min
            replace = spatial.cKDTree(points).query_pairs(min_distance, output_type='ndarray')[:, 0]

        # eliminate points that are too distant
        inner = (spatial.Delaunay(xyz).find_simplex(points)) != -1
        d, _ = spatial.cKDTree(points[inner, :]).query(points[~inner, :], distance_upper_bound=margin)
        points = np.vstack((points[inner, :], points[~inner, :][d < margin, :]))

        self.insert1(dict(
            key, margin=margin,
            density=density,
            npoints=points.shape[0], min_distance=min_distance,
            points=points,
            volume=spatial.ConvexHull(points).volume * 1e-9,
            inner_count=inner.sum()))
Ejemplo n.º 18
0
    def find_footprint(self, points):
        """This function will take in an numpy.array of points in 2D and create
		a convex polygon that encapsilates every point provided.\
		Arguments to pass in:
		points = 2D array of points numpy.array([:,:])
		Returns a Polygon"""
        footprint = Polygon()

        if self.halo_density:
            buffed_points = self.halo_buffer(points, self.halo_radius,
                                             self.halo_density)
        else:
            buffed_points = points

        if not points.size:
            pass
        else:
            hull = spatial.ConvexHull(buffed_points)
            for vertex in hull.vertices:
                point = Point32()
                point.x = buffed_points[vertex, 0]
                point.y = buffed_points[vertex, 1]
                point.z = 0.0
                footprint.points.append(point)
        return footprint
Ejemplo n.º 19
0
def overlap(rec1, rec2):
    if not collisionCheck(rec1, rec2): return 0.

    x1, y1, theta1, l1, w1 = rec1
    x2, y2, theta2, l2, w2 = rec2
    cos1 = np.cos(theta1)
    sin1 = np.sin(theta1)
    diffx = x2 - x1
    diffy = y2 - y1
    x2 = diffx * cos1 + diffy * sin1
    y2 = -diffx * sin1 + diffy * cos1
    cos2 = np.cos(theta2 - theta1)
    sin2 = np.sin(theta2 - theta1)

    A = np.array([[1, 0, 1], [-1, 0, 1], [0, 1, 1], [0, -1, 1],
                  [cos2, sin2, 1], [-cos2, -sin2, 1], [-sin2, cos2, 1],
                  [sin2, -cos2, 1]])
    b = np.array([
        l1, l1, w1, w1, l2 + cos2 * x2 + sin2 * y2, l2 - cos2 * x2 - sin2 * y2,
        w2 - sin2 * x2 + cos2 * y2, w2 + sin2 * x2 - cos2 * y2
    ])
    res = linprog(np.array([0, 0, -1]),
                  A_ub=A,
                  b_ub=b,
                  bounds=(-np.inf, np.inf))
    assert res.success
    interior = res.x[:2]

    halfspaces = np.append(A[:, :2], -b[:, None], axis=1)
    hs = spspatial.HalfspaceIntersection(halfspaces, interior).intersections
    return spspatial.ConvexHull(hs).volume
Ejemplo n.º 20
0
def plot_points(data, fig=None, ax=None, inp_color=None):
    # Takes as input all the points
    if fig is None:
        fig = plt.figure()
        # If no plot is defined
        ax = fig.gca(projection='3d')
    for i in range(len(data)):
        points = np.asarray(data[i])
        hull = sp.ConvexHull(points)
        # Plotting the points with scatter
        if not inp_color:
            ax.plot_trisurf(points[:, 0],
                            points[:, 1],
                            points[:, 2],
                            triangles=hull.simplices,
                            color='b')
        else:
            ax.plot_trisurf(points[:, 0],
                            points[:, 1],
                            points[:, 2],
                            triangles=hull.simplices,
                            color=inp_color)
        # Checking if there are a prismatic joint that needs to be denoted
    # Label the axis
    ax.set_xlabel('X'), ax.set_ylabel('Y'), ax.set_zlabel('Z')
    ax.set_xlim([-2, 5]), ax.set_ylim([-2.5, 1]), ax.set_zlim([-1, 1])
    plt.savefig("test.png")
    plt.show()

    return (fig, ax)
Ejemplo n.º 21
0
def hull_points(obj, qhull_options='QbB Pp'):
    """
    Try to extract a convex set of points from multiple input formats.

    Parameters
    ---------
    obj: Trimesh object
         (n,d) points
         (m,) Trimesh objects

    Returns
    --------
    points: (o,d) convex set of points
    """
    if hasattr(obj, 'convex_hull'):
        return obj.convex_hull.vertices

    initial = np.asanyarray(obj, dtype=np.float64)
    if len(initial.shape) != 2:
        raise ValueError('points must be (n, dimension)!')

    hull = spatial.ConvexHull(initial, qhull_options=qhull_options)
    points = hull.points[hull.vertices]

    return points
Ejemplo n.º 22
0
def get_convex_hull(locations):
    array = []
    for i in locations:
        array.append([i.x, i.y])
    hullArray = np.array(array)
    hull = sp.ConvexHull(hullArray)
    return hull.volume
Ejemplo n.º 23
0
def RandPolytope(n, m):
    import scipy.spatial as sp
    import random

    # Hyperspheroid coordinates take the form
    # x_1 = r*cos(t_1)
    # x_2 = r*sin(t_1)*cos(t_2)
    # x_3 = r*sin(t_1)*sin(t_2)*cos(t_3)
    # ...
    # x_n = r*sin(t_1)*...*sin(t_n-1)*cos(t_n)
    r = random.uniform(1.0, 10.0)
    arr = []
    for i in range(m):
        angles = [np.deg2rad(random.randint(1, 360)) for a in range(n - 1)]
        arr.append(nsphere_to_cartesian(r, angles))
        #arr.append([random.uniform(0.0,50.0) for a in range(n)])

    # For now we just have the point (0) as our guaranteed point
    arr.append(np.array([0 for a in range(n)]))
    hull = sp.ConvexHull(arr)

    A = hull.equations[:, 0:-1]
    b = hull.equations[:, -1]

    #return A, b
    return hull.points
Ejemplo n.º 24
0
 def _bresenham(self, faces, dx):
     r'''
     A Bresenham line function to generate points to fill in for the fibers
     '''
     line_points = []
     for face in faces:
         # Get in hull order
         fx = face[:, 0]
         fy = face[:, 1]
         fz = face[:, 2]
         # Find the axis with the smallest spread and remove it to make 2D
         if (np.std(fx) < np.std(fy)) and (np.std(fx) < np.std(fz)):
             f2d = np.vstack((fy, fz)).T
         elif (np.std(fy) < np.std(fx)) and (np.std(fy) < np.std(fz)):
             f2d = np.vstack((fx, fz)).T
         else:
             f2d = np.vstack((fx, fy)).T
         hull = sptl.ConvexHull(f2d, qhull_options='QJ Pp')
         face = np.around(face[hull.vertices].astype(float), 6)
         for i in range(len(face)):
             vec = face[i] - face[i - 1]
             vec_length = np.linalg.norm(vec)
             increments = np.ceil(vec_length / dx)
             check_p_old = np.array([-1, -1, -1])
             for x in np.linspace(0, 1, increments):
                 check_p_new = face[i - 1] + (vec * x)
                 if np.sum(check_p_new - check_p_old) != 0:
                     line_points.append(check_p_new)
                     check_p_old = check_p_new
     return np.asarray(line_points)
Ejemplo n.º 25
0
def planar_hull(points, normal, origin=None):
    """
    Find the convex outline of a set of points projected to a plane.

    Parameters
    -----------
    points: (n,3) float, input points
    normal: (3) float vector, normal vector of plane
    origin: (3) float, location of plane origin

    Returns
    -----------
    hull_lines: (n,2,2) set of unordered line segments
    T:          (4,4) float, transformation matrix
    height:     (2,) float, [Z min, Z max]
    """
    from .points import project_to_plane

    if origin is None:
        origin = np.zeros(3)

    planar, T = project_to_plane(points,
                                 plane_normal=normal,
                                 plane_origin=origin,
                                 return_planar=False,
                                 return_transform=True)
    hull_edges = spatial.ConvexHull(planar[:, 0:2]).simplices
    hull_lines = planar[hull_edges]
    planar_z = planar[:, 2]
    height = np.array([planar_z.min(), planar_z.max()])
    return hull_lines, T, height
Ejemplo n.º 26
0
 def compute_cell_diameter(self) -> float:
     cell_mask = self.get_cell_mask()
     cell_mask_points = np.argwhere(cell_mask == 1)
     convex_hull = spatial.ConvexHull(cell_mask_points)
     boundary_points = cell_mask_points[convex_hull.vertices]
     d = np.max(pairwise_distances(boundary_points))
     return d
Ejemplo n.º 27
0
def hull_points(obj):
    '''
    Try to extract a convex set of points from multiple input formats.

    Arguments
    ---------
    obj: Trimesh object
         (n,d) points
         (m,) Trimesh objects

    Returns
    --------
    points: (o,d) convex set of points
    '''
    if hasattr(obj, 'convex_hull'):
        points = obj.convex_hull.vertices
    elif util.is_sequence(obj):
        initial = np.asanyarray(obj)
        if len(initial.shape) != 2:
            raise ValueError('Points must be (n, dimension)!')
        hull = spatial.ConvexHull(initial, qhull_options='QbB Pp')
        points = hull.points[hull.vertices]
    else:
        raise ValueError('Can\'t extract hull points from %s',
                         obj.__class__.__name__)
    return points
Ejemplo n.º 28
0
 def _export_vor_fibres(self):
     r"""
     Run through the throat vertices, compute the convex hull order and save
     the vertices and ordered faces in a pickle dictionary to be used in
     blender
     """
     import pickle as pickle
     Indices = []
     for t in self.throats():
         indices = list(self["throat.vert_index"][t].keys())
         verts = self._vor.vertices[indices]
         # Need to order the indices in convex hull order
         # Compute the standard deviation in all coordinates and eliminate
         # the axis with the smallest to make 2d
         stds = [
             np.std(verts[:, 0]),
             np.std(verts[:, 1]),
             np.std(verts[:, 2])
         ]
         if np.argmin(stds) == 0:
             verts2d = np.vstack((verts[:, 1], verts[:, 2])).T
         elif np.argmin(stds) == 1:
             verts2d = np.vstack((verts[:, 0], verts[:, 2])).T
         else:
             verts2d = np.vstack((verts[:, 0], verts[:, 1])).T
         # 2d convexhull returns vertices in hull order
         hull2d = sptl.ConvexHull(verts2d, qhull_options='QJ Pp')
         # Re-order the vertices and save as list (blender likes them as lists)
         Indices.append(np.asarray(indices)[hull2d.vertices].tolist())
     # Create dictionary to pickle
     data = {}
     data["Verts"] = self._vor.vertices
     data["Indices"] = Indices
     pickle.dump(data, open("fibres.p", "wb"))
Ejemplo n.º 29
0
def hull(x, T, data):

    # getting minimal G for each x - solution phases
    Fgy = [fase.G(x, T) for fase in data if fase.kind == 'sol']
    Gmin = np.amin(Fgy, axis=0)
    Gmin = np.column_stack((x, Gmin))

    # adding stoichiometric phases
    for fase in data:
        if fase.kind == 'stq':
            point = [[fase.xB, fase.G(T)]]
            Gmin = np.append(Gmin, point, axis=0)

    # ordering array by composition
    Gmin = Gmin[np.argsort(Gmin[:, 0])]

    # getting convex hull for solution phases
    hull = spa.ConvexHull(Gmin)

    # shifting first position to end
    vertices = np.roll(hull.vertices, -1)

    # separating points belonging to hull
    points = hull.points[vertices, :]

    return Gmin, points, vertices
Ejemplo n.º 30
0
def find_ball(mask):
    contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    if contours:
        contour = max(contours, key=cv2.contourArea)
        if cv2.contourArea(contour) > BALL_MIN_AREA:
            test = np.array(contour.reshape(-1, 2))
            # two points which are fruthest apart will occur as vertices of the convex hull
            candidates = test[spatial.ConvexHull(test).vertices]

            # get distances between each pair of candidate points
            dist_mat = spatial.distance_matrix(candidates, candidates)

            # get indices of candidates that are furthest apart
            i, j = np.unravel_index(dist_mat.argmax(), dist_mat.shape)

            p1, p2 = candidates[i], candidates[j]

            delta_x = abs((p1[0] - p2[0]) / 2)
            delta_y = abs((p1[1] - p2[1]) / 2)

            x = int(min(p1[0], p2[0]) + delta_x)
            y = int(min(p1[1], p2[1]) + delta_y)

            dist = int(math.sqrt((x - p1[0])**2 + (y - p1[1])**2))

            return (x, y), dist
    return (0, 0), 0