Exemple #1
0
def _face_adjacency(xyz, faces, nmax=10, radius=2.0):
    points = [centroid_points([xyz[index] for index in face]) for face in faces]
    tree = KDTree(points)
    closest = [tree.nearest_neighbors(point, nmax) for point in points]
    closest = [[index for _, index, _ in nnbrs] for nnbrs in closest]
    adjacency = {}
    for face, vertices in enumerate(faces):
        nbrs = []
        found = set()
        nnbrs = set(closest[face])
        for u, v in pairwise(vertices + vertices[0:1]):
            for nbr in nnbrs:
                if nbr == face:
                    continue
                if nbr in found:
                    continue
                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if v == a and u == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break
                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if u == a and v == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break
        adjacency[face] = nbrs
    return adjacency
Exemple #2
0
 def is_point_close(self, point, objs, distance, exclude=None, d_out=False):
     try:
         tree = KDTree(objs)
         nnbr, label, dst = tree.nearest_neighbour(point, exclude)
         if dst is not None:
             if dst <= distance:
                 # print('distance is {}'.format(dst))
                 if d_out is True:
                     return (True, dst)
                 else:
                     return True
             else:
                 if d_out is True:
                     return (False, dst)
                 else:
                     return False
     except Exception:
         return None
     return None
Exemple #3
0
def _mesh_face_adjacency(mesh, nmax=10, radius=2.0):
    fkey_index = {fkey: index for index, fkey in enumerate(mesh.faces())}
    index_fkey = {index: fkey for index, fkey in enumerate(mesh.faces())}
    points     = [mesh.face_centroid(fkey) for fkey in mesh.faces()]

    k = min(mesh.number_of_faces(), nmax)

    try:
        from scipy.spatial import cKDTree

        tree = cKDTree(points)
        _, closest = tree.query(points, k=k, n_jobs=-1)

    except Exception:
        try:
            import Rhino

        except Exception:
            from compas.geometry import KDTree

            tree = KDTree(points)
            closest = [tree.nearest_neighbors(point, k) for point in points]
            closest = [[index for xyz, index, d in nnbrs] for nnbrs in closest]

        else:
            from Rhino.Geometry import RTree
            from Rhino.Geometry import Sphere
            from Rhino.Geometry import Point3d

            tree = RTree()
            for i, point in enumerate(points):
                tree.Insert(Point3d(* point), i)

            def callback(sender, e):
                data = e.Tag
                data.append(e.Id)

            closest = []
            for i, point in enumerate(points):
                sphere = Sphere(Point3d(* point), radius)
                data = []
                tree.Search(sphere, callback, data)
                closest.append(data)

    adjacency  = {}

    for fkey in mesh.faces():
        nbrs  = []
        index = fkey_index[fkey]
        found = set()

        nnbrs = set(closest[index])

        for u, v in mesh.face_halfedges(fkey):
            for index in nnbrs:
                nbr = index_fkey[index]

                if nbr == fkey:
                    continue
                if nbr in found:
                    continue

                for a, b in mesh.face_halfedges(nbr):
                    if v == a and u == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break

                for a, b in mesh.face_halfedges(nbr):
                    if u == a and v == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break

        adjacency[fkey] = nbrs

    return adjacency
Exemple #4
0
def face_adjacency(mesh):
    """Build a face adjacency dict.

    Parameters
    ----------
    mesh : Mesh
        A mesh object.

    Returns
    -------
    dict
        A dictionary mapping face identifiers (keys) to lists of neighbouring faces.

    Notes
    -----
    This algorithm is used primarily to unify the cycle directions of a given mesh.
    Therefore, the premise is that the topological information of the mesh is corrupt
    and cannot be used to construct the adjacency structure. The algorithm is thus
    purely geometrical, but uses a spatial indexing tree to speed up the search.

    """
    fkey_index = {fkey: index for index, fkey in enumerate(mesh.faces())}
    index_fkey = {index: fkey for index, fkey in enumerate(mesh.faces())}
    points = [mesh.face_centroid(fkey) for fkey in mesh.faces()]

    try:
        from scipy.spatial import cKDTree

        tree = cKDTree(points)
        _, closest = tree.query(points, k=10, n_jobs=-1)

    except Exception:
        try:
            import Rhino

        except Exception:
            from compas.geometry import KDTree

            tree = KDTree(points)
            closest = [tree.nearest_neighbours(point, 10) for point in points]
            closest = [[index for xyz, index, d in nnbrs] for nnbrs in closest]

        else:
            from Rhino.Geometry import RTree
            from Rhino.Geometry import Sphere
            from Rhino.Geometry import Point3d

            tree = RTree()
            for i, point in enumerate(points):
                tree.Insert(Point3d(*point), i)

            def callback(sender, e):
                data = e.Tag
                data.append(e.Id)

            closest = []
            for i, point in enumerate(points):
                sphere = Sphere(Point3d(*point), 2.0)
                data = []
                tree.Search(sphere, callback, data)
                closest.append(data)

    adjacency = {}

    for fkey in mesh.faces():
        nbrs = []
        index = fkey_index[fkey]
        found = set()

        nnbrs = closest[index]

        for u, v in mesh.face_halfedges(fkey):
            for index in nnbrs:
                nbr = index_fkey[index]

                if nbr == fkey:
                    continue
                if nbr in found:
                    continue

                for a, b in mesh.face_halfedges(nbr):
                    if v == a and u == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break

                for a, b in mesh.face_halfedges(nbr):
                    if u == a and v == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break

        adjacency[fkey] = nbrs

    return adjacency
Exemple #5
0
def face_adjacency(xyz, faces):
    """"""
    points = [
        centroid_points([xyz[index] for index in face]) for face in faces
    ]

    try:
        from scipy.spatial import cKDTree

        tree = cKDTree(points)
        _, closest = tree.query(points, k=10, n_jobs=-1)

    except Exception:
        try:
            import Rhino

        except Exception:
            from compas.geometry import KDTree

            tree = KDTree(points)
            closest = [tree.nearest_neighbors(point, 10) for point in points]
            closest = [[index for _, index, _ in nnbrs] for nnbrs in closest]

        else:
            from Rhino.Geometry import RTree
            from Rhino.Geometry import Sphere
            from Rhino.Geometry import Point3d

            tree = RTree()
            for i, point in enumerate(points):
                tree.Insert(Point3d(*point), i)

            def callback(sender, e):
                data = e.Tag
                data.append(e.Id)

            closest = []
            for i, point in enumerate(points):
                sphere = Sphere(Point3d(*point), 2.0)
                data = []
                tree.Search(sphere, callback, data)
                closest.append(data)

    adjacency = {}

    for face, vertices in enumerate(faces):
        nbrs = []
        found = set()

        nnbrs = set(closest[face])

        for u, v in pairwise(vertices + vertices[0:1]):
            for nbr in nnbrs:

                if nbr == face:
                    continue
                if nbr in found:
                    continue

                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if v == a and u == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break

                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if u == a and v == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break

        adjacency[face] = nbrs

    return adjacency
Exemple #6
0
from compas.geometry import Pointcloud, KDTree
from compas.datastructures import Network

cloud = Pointcloud.from_bounds(10, 5, 3, 200)
tree = KDTree(cloud)

network = Network()

for point in cloud:
    network.add_node(x=point[0], y=point[1], z=point[2])

for node in network.nodes():
    point = network.node_coordinates(node)
    for nbr in tree.nearest_neighbors(point, 4, distance_sort=True):
        if nbr[2] < 1e-6:
            continue
        if not network.has_edge(node, nbr[1], directed=False):
            network.add_edge(node, nbr[1])

start = network.get_any_node()
goal = network.get_any_node()
path = network.shortest_path(start, goal)
def plot_2d(
        filename,
        draw_vector_fields=False,
        draw_streamlines=False,
        draw_boundary_edges=True,
        draw_faces=True,
        draw_faces_centroids=False,
        color_faces=None,
        draw_colorbar=True,
        draw_edges=False,
        comb_fields=False,
        align_field_1_to=None,
        align_field_2_to=None,
        streamlines_density=0.75,  # 0.55 for 4ps
        streamlines_lw=None,
        vector_fields_scale=0.03,
        vector_fields_same_scale=True,
        save_img=True,
        pad_inches=0.0,
        show_img=False):
    """
    Makes a 3d plot of a mesh with a vector field.

    Parameters
    ----------
    filename : `str`
        The name of the JSON file that stores the clustering resultes w.r.t certain
        \n mesh, attribute, alglrithm and number of clusters.
    """

    # load a mesh from a JSON file
    name_in = filename + ".json"
    json_in = os.path.abspath(os.path.join(JSON, name_in))

    mesh = MeshPlus.from_json(json_in)

    # ClusterPlotter is a custom wrapper around a COMPAS MeshPlotter
    plotter = MeshPlusPlotter(mesh, figsize=(16, 9), dpi=600)
    if draw_boundary_edges:
        plotter.draw_edges(keys=list(mesh.edges_on_boundary()))

    # draw mesh edges
    if draw_edges:
        plotter.draw_edges()

    # color up the faces of the mesh according to their cluster
    if draw_faces or draw_faces_centroids:
        cmap = None
        data = np.zeros(mesh.number_of_faces())
        sorted_fkeys = sorted(list(mesh.faces()))

        if color_faces == "clusters":
            # cmap = "Paired"
            labels = mesh.cluster_labels("cluster")
            for fkey, label in labels.items():
                data[fkey] = label

            # plot stuff
            cbar_label = "Directional Clusters"
            n_clusters = int(
                input("Please input the number of clusters here: "))
            cmap = plt.cm.get_cmap('rainbow', n_clusters)  # plasma or rainbow

            ticks = np.linspace(0, n_clusters - 1, n_clusters +
                                1) + 0.5 * (n_clusters - 1) / n_clusters
            ticks = ticks[:-1]
            ticks_labels = list(range(1, n_clusters + 1))
            extend = "neither"

        elif color_faces == "angles" or color_faces == "cosine_distance" or color_faces == "abs_cosine_distance":

            available_vf = mesh.vector_fields()
            print("Avaliable vector fields on the mesh are:\n", available_vf)

            vf_names = []
            while len(vf_names) < 2:
                vf_name = input(
                    "Please select the two vector fields to compare: ")
                if vf_name in available_vf:
                    if vf_name not in vf_names:
                        vf_names.append(vf_name)
                else:
                    print(
                        "This vector field is not available. Please try again."
                    )

            vf_name_a, vf_name_b = vf_names
            vf_a = mesh.vector_field(vf_name_a)
            vf_b = mesh.vector_field(vf_name_b)

            clm = COLOR_LABEL_MAP[color_faces]
            func = clm["func"]
            cmap = clm["cmap"]
            cbar_label = clm["cbar_label"]

            for fkey in mesh.faces():
                data[fkey] = func(vf_a[fkey], vf_b[fkey])

            ticks = np.linspace(data.min(), data.max(), 7)
            ticks_labels = [np.round(x, 2) for x in ticks]
            extend = "both"

        if draw_faces:

            collection = plotter.draw_faces(keys=sorted_fkeys)

        elif draw_faces_centroids:

            points = []
            for fkey in sorted_fkeys:
                point = {}
                point["pos"] = mesh.face_centroid(fkey)
                point["radius"] = 0.03
                point["edgewidth"] = 0.10
                points.append(point)

            collection = plotter.draw_points(points)

        if cmap:
            collection.set(array=data, cmap=cmap)
            collection.set_linewidth(lw=0.0)

            if draw_colorbar:
                colorbar = plt.colorbar(collection,
                                        shrink=0.9,
                                        pad=0.01,
                                        extend=extend,
                                        extendfrac=0.05,
                                        ax=plotter.axes,
                                        aspect=30,
                                        orientation="vertical")

                colorbar.set_ticks(ticks)
                colorbar.ax.set_yticklabels(ticks_labels)
                colorbar.set_label(cbar_label, fontsize="large")

    # plot vector fields on mesh as lines
    if draw_vector_fields or draw_streamlines:
        # supported vector field attributes
        available_vf = mesh.vector_fields()
        print("Avaliable vector fields on the mesh are:\n", available_vf)

        # the name of the vector field to cluster.
        vf_names = []
        while True:
            vf_name = input(
                "Please select the vector fields to draw. Type 'ok' to stop adding vector fields: "
            )
            if vf_name in available_vf:
                if vf_name not in vf_names:
                    vf_names.append(vf_name)
            elif vf_name == "ok":
                break
            else:
                print("This vector field is not available. Please try again.")

        if draw_vector_fields:
            # colors for all vector related matters
            colors = cycle([(0, 0, 255), (255, 0, 0), (0, 255, 0), (0, 0, 0)])
            # colors = cycle([(235, 45, 125), (0, 165, 0), (0, 0, 255), (0, 0, 0)])

            # vector field drawing parameters -- better of being exposed?
            width = 0.5
            scale = vector_fields_scale
            same_scale = vector_fields_same_scale

            for vf_name in vf_names:
                vf = mesh.vector_field(vf_name)

                if comb_fields:
                    vf = comb_vector_field(vf, mesh)

                color = next(colors)
                plotter.draw_vector_field(vf, color, same_scale, scale, width)

        if draw_streamlines:
            colors = cycle([(0, 0, 255), (255, 0, 0), (0, 255, 0), (0, 0, 0)])

            # get bounding box for all the mesh vertices
            vx = []
            vy = []
            for vkey in mesh.vertices():
                vx.append(mesh.vertex_attribute(vkey, name="x"))
                vy.append(mesh.vertex_attribute(vkey, name="y"))

            vxmin = min(vx)
            vxmax = max(vx)
            vymin = min(vy)
            vymax = max(vy)

            # create linear spaces on x and y
            # offset inwards by 1%
            pe = 0.01
            vxdiff = vxmax - vxmin
            vydiff = vymax - vymin

            X = np.linspace(vxmin + pe * vxdiff, vxmax - pe * vxdiff,
                            len(set(vx)))
            Y = np.linspace(vymin + pe * vydiff, vymax - pe * vydiff,
                            len(set(vy)))
            XX, YY = np.meshgrid(X, Y)

            # gather gkey maps
            gkey_fkey = {}
            gkey_xyz = {}
            xyz = []
            for fkey in mesh.faces():
                xyz.append(mesh.face_centroid(fkey))
                gkey = geometric_key_xy(mesh.face_centroid(fkey))
                gkey_xyz[gkey] = mesh.face_centroid(fkey)
                gkey_fkey[gkey] = fkey

            # build search tree
            search_tree = KDTree(objects=xyz)

            # select vectors for dot product alignment
            alignment_vectors = []
            alignment_map_xy = {"X": [1.0, 0.0, 0.0], "Y": [0.0, 1.0, 0.0]}
            for align_to in (align_field_1_to, align_field_2_to):
                if align_to in alignment_map_xy:
                    alignment_vectors.append(alignment_map_xy[align_to])

            if len(alignment_vectors) > 0:
                alignment_vectors_cycle = cycle(alignment_vectors)

            # do for every vector field
            for vf_name in vf_names:

                vf = mesh.vector_field(vf_name)

                # comb the line field prior to streamlines tracing
                if comb_fields:
                    vf = comb_vector_field(vf, mesh)

                if len(alignment_vectors) > 0:
                    alignment_vector = next(alignment_vectors_cycle)
                    align_vector_field(vf, alignment_vector)

                # query vectors from vector field
                U = []
                V = []
                LV = []

                if streamlines_lw is not None:
                    streamlines_lw = float(streamlines_lw)

                for xx, yy in zip(XX.flatten(), YY.flatten()):
                    # strictly 2d
                    test_xyz = [xx, yy, 0.0]
                    near_xyz, _, _ = search_tree.nearest_neighbor(test_xyz)

                    # generate grid gkey
                    gkey = geometric_key_xy(near_xyz)
                    fkey = gkey_fkey[gkey]
                    u, v = vf[fkey][:2]

                    U.append(u)
                    V.append(v)

                    # compute lineweights
                    LV.append(length_vector(vf[fkey]))

                U = np.reshape(U, XX.shape)
                V = np.reshape(V, XX.shape)

                LW = []
                if streamlines_lw:

                    for value in LV:
                        centered_val = (value - min(LV)
                                        )  # in case min is not 0
                        ratio = centered_val / max(LV)
                        ratio = streamlines_lw * ratio
                        LW.append(ratio +
                                  1)  # add one to not have invisible lines

                    LW = np.reshape(LW, XX.shape)

                # filter lineweights for match streamplot's signature
                if len(LW) == 0:
                    LW = None

                # plot streamlines
                plt.streamplot(XX,
                               YY,
                               U,
                               V,
                               color=[i / 255.0 for i in next(colors)],
                               arrowsize=0.2,
                               maxlength=20.0,
                               minlength=0.1,
                               density=streamlines_density,
                               linewidth=LW)

    # save image
    if save_img:
        dt = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
        img_name = filename.split("/")[-1] + "_" + dt + ".png"
        img_path = os.path.abspath(os.path.join(DATA, "images", img_name))
        plt.tight_layout()
        plotter.save(img_path, bbox_inches='tight', pad_inches=pad_inches)
        print("Saved image to : {}".format(img_path))

    # show to screen
    if show_img:
        plotter.show()