Пример #1
0
    def edge_midpoint(self, u, v):
        """Return the location of the midpoint of an edge.

        Parameters
        ----------
        u : hashable
            The key of the start node.
        v : hashable
            The key of the end node.

        Returns
        -------
        list
            The XYZ coordinates of the midpoint.
        """
        a, b = self.edge_coordinates(u, v)
        return midpoint_line((a, b))
Пример #2
0
    def edge_midpoint(self, u, v):
        """Return the location of the midpoint of an edge.

        Parameters
        ----------
        u : int
            The key of the start vertex.
        v : int
            The key of the end vertex.

        Returns
        -------
        list[float]
            The XYZ coordinates of the midpoint.

        """
        a, b = self.edge_coordinates(u, v)
        return midpoint_line((a, b))
Пример #3
0
def draw_graph(vertices, edges, loop_size=1.0, spindle_size=1.0, node_radius=0.0, line_radius=0.0, key_to_colour={}):
	"""Draw a graph in Rhino as grouped points and lines with optional element size and node colouring.
	Loops for edges (u, u) and parallel edges for multiple edges (u, v) and/or (v, u) are allowed.

	Parameters
	----------
	vertices : dict
		A dictionary of vertex keys pointing to point coordinates.
	edges : list
		A list of tuples of pairs of vertex indices.
	loop_size : float, optional
		Rough size of the loops due to edges (u, u).
		Default value is 1.0.
	spindle_size : float, optional
		Rough size of the spindles due to mutiple edges (u, v) and/or (v, u).
		Default value is 1.0.
	node_radius : float, optional
		Node radius representing the vertices. If equal to 0.0, a point is added, else a sphere.
		Default value is 1.0.
	line_radius : float, optional
		Line radius representing the edges. If equal to 0.0, a line is added, else a pipe.
		Default value is 1.0.
	key_to_colour : dict, optional
		An optional dictonary with vertex keys pointing to RGB colours.

	Returns
	-------
	group : Rhino group
		A Rhino group with the list of points or sphere surfaces of the vertices, and the list of the list of curves or pipe surfaces of the edges.
	"""


	# nodes as points or spheres with optional colours
	nodes = []
	for key, xyz in vertices.items():
		nodes.append(rs.AddPoint(xyz) if node_radius == 0.0 else rs.AddSphere(xyz, node_radius))
		if key in key_to_colour:
			rs.ObjectColor(nodes[-1], key_to_colour[key])

	# curves
	curves = []
	while len(edges) > 0:
		crvs = []
		u0, v0 = edges.pop()
		# count occurences in case of multiple parallel edges
		n = 1
		for u, v in edges:
			if (u == u0 and v == v0) or (u == v0 and v == u0):
				edges.remove((u, v))
				n += 1
		# if not loop edge
		if u0 != v0:
			start = vertices[u0]
			end = vertices[v0]
			# rough spindle of parallel edges based on third offset point
			mid = midpoint_line([start, end])
			direction = cross_vectors(normalize_vector(subtract_vectors(end, start)), [0.0, 0.0, 1.0])
			for i in range(n):
				k = (float(i) / float(n) * spindle_size) - spindle_size / 2.0 * (float(n) - 1.0) / float(n)
				dir_mid = add_vectors(mid, scale_vector(direction, k))
				crvs.append(rs.AddInterpCurve([start, dir_mid, end], degree=3))
		
		# if loop edge
		else:
			xyz0 = vertices[u0]
			x0, y0, z0 = xyz0
			# rough loop based on three additional points
			xyz1 = [x0 + loop_size / 2.0, y0 - loop_size / 2.0, z0]
			xyz2 = [x0 + loop_size, y0, z0]
			xyz3 = [x0 + loop_size / 2.0, y0 + loop_size / 2.0, z0]
			crvs += [rs.AddInterpCurve([xyz0, xyz1, xyz2, xyz3, xyz0], degree=3) for i in range(n)]
			# spread if multiple loops
			for i, crv in enumerate(crvs):
				rs.RotateObject(crv, [x0, y0, z0], 360 * float(i) / float(n))

		# pipe if non-null radius is specified
		if line_radius != 0.0:
			pipes = [rs.AddPipe(crv, 0, line_radius) for crv in crvs]
			rs.DeleteObjects(crvs)
			crvs = pipes

		curves += crvs

	# output group
	group = rs.AddGroup()
	rs.AddObjectsToGroup(nodes + curves, group)
	return group
Пример #4
0
 def edge_midpoint(self, u, v):
     """Return the location of the midpoint of an edge."""
     a, b = self.edge_coordinates(u, v)
     return midpoint_line((a, b))
Пример #5
0
    def from_skeleton(cls, lines, radius=1):

        network = Network.from_lines(lines)

        tube_extremities = {}

        nodes = []
        for vkey in network.vertices():
            if len(network.vertex_neighbors(vkey)) > 1:

                points = [
                    network.edge_point(vkey,
                                       nbr,
                                       t=float(radius) /
                                       network.edge_length(vkey, nbr))
                    for nbr in network.vertex_neighbors(vkey)
                ]
                faces = convex_hull(points)
                mesh = cls.from_vertices_and_faces(points, faces)

                meshes = []

                for fkey in mesh.faces():
                    vertices = [
                        mesh.edge_midpoint(u, v)
                        for u, v in mesh.face_halfedges(fkey)
                    ]
                    faces = [[0, 1, 2]]
                    meshes.append(cls.from_vertices_and_faces(vertices, faces))

                for vkey_2 in mesh.vertices():
                    tops = []
                    bottoms = []
                    n = normalize_vector(
                        subtract_vectors(mesh.vertex_coordinates(vkey_2),
                                         network.vertex_coordinates(vkey)))
                    for i in range(len(mesh.vertex_neighbors(vkey_2))):
                        pt_0 = mesh.edge_midpoint(
                            vkey_2,
                            mesh.vertex_neighbors(vkey_2, ordered=True)[i - 1])
                        bottoms.append(pt_0)
                        pt_1 = mesh.edge_midpoint(
                            vkey_2,
                            mesh.vertex_neighbors(vkey_2, ordered=True)[i])
                        pt_2 = midpoint_line([pt_0, pt_1])
                        pt_2 = add_vectors(
                            scale_vector(n, distance_point_point(pt_0, pt_1)),
                            pt_2)
                        tops.append(pt_2)
                        vertices = [pt_0, pt_2, pt_1]
                        faces = [[0, 1, 2]]
                        meshes.append(
                            cls.from_vertices_and_faces(vertices, faces))
                    for i in range(len(tops)):
                        vertices = [tops[i - 1], tops[i], bottoms[i]]
                        faces = [[0, 1, 2]]
                        meshes.append(
                            cls.from_vertices_and_faces(vertices, faces))
                    #print network.vertex_neighbors(vkey), network.vertex_neighbors(vkey)[vkey_2]
                    tube_extremities[(
                        vkey, network.vertex_neighbors(vkey)[vkey_2])] = tops

                mesh = meshes_join_and_weld(meshes)

                #dense_mesh = trimesh_subdivide_loop(mesh, k = 3)

                nodes.append(mesh)

        return nodes[0]

        meshes_2 = []
        for u, v in network.edges():
            if len(network.vertex_neighbors(u)) > 1 and len(
                    network.vertex_neighbors(v)) > 1:
                #print len(tube_extremities[(u, v)])
                #print len(tube_extremities[(v, u)])
                if len(tube_extremities[(u, v)]) == len(tube_extremities[(v,
                                                                          u)]):
                    n = len(tube_extremities[(u, v)])
                    l = network.edge_length(u, v) - 2 * radius
                    m = math.floor(l / radius) + 1
                    pt_uv = tube_extremities[(u, v)]
                    pt_vu = list(reversed(tube_extremities[(v, u)]))
                    dmin = -1
                    imin = None
                    for i in range(n):
                        distance = sum([
                            distance_point_point(pt_uv[j],
                                                 pt_vu[i + j - len(pt_vu)])
                            for j in range(n)
                        ])
                        if dmin < 0 or distance < dmin:
                            dmin = distance
                            imin = i
                    pt_vu = [pt_vu[imin + j - len(pt_vu)] for j in range(n)]
                    array = [pt_uv]
                    for i in range(int(m)):
                        polygon = []
                        for j in range(int(n)):
                            u = pt_uv[j]
                            v = pt_vu[j]
                            polygon.append(
                                add_vectors(
                                    scale_vector(u, (float(m) - 1 - float(i)) /
                                                 float(m - 1)),
                                    scale_vector(v,
                                                 float(i) / float(m - 1))))
                        array.append(polygon)
                    array.append(pt_vu)
                    #print len(array), len(array[0]), len(array[1]), len(array[2]), len(array[3])
                    for i in range(int(n)):
                        for j in range(int(m)):
                            vertices = [
                                array[i - 1][j - 1], array[i - 1][j],
                                array[i][j]
                            ]
                            faces = [[0, 1, 2]]
                            meshes_2.append(
                                Mesh.from_vertices_and_faces(vertices, faces))

        vertices, faces = join_and_weld_meshes(meshes_2)

        #meshes_2 = rs.AddMesh(vertices, faces)

        meshes = []
        for node in nodes:
            vertices, faces = node.to_vertices_and_faces()
            meshes.append(rs.AddMesh(vertices, faces))
Пример #6
0
def trimesh_skeleton(cls, lines, radius=1):

    network = Network.from_lines(lines)

    tube_extremities = {}

    nodes = []
    for vkey in network.nodes():
        if len(network.adjacency[vkey]) > 1:

            points = {
                nbr: network.edge_point(vkey,
                                        nbr,
                                        t=float(radius) /
                                        network.edge_length(vkey, nbr))
                for nbr in network.adjacency[vkey]
            }
            idx_to_key = {
                i: key
                for i, key in enumerate(network.adjacency[vkey])
            }
            faces = convex_hull(list(points.values()))
            faces = [[idx_to_key[idx] for idx in face] for face in faces]
            mesh = cls.from_vertices_and_faces(points, faces)
            nodes.append(mesh)

            meshes = []

            for fkey in mesh.faces():
                vertices = [
                    mesh.edge_midpoint(u, v)
                    for u, v in mesh.face_halfedges(fkey)
                ]
                faces = [[0, 1, 2]]
                meshes.append(cls.from_vertices_and_faces(vertices, faces))

            for vkey_2 in mesh.vertices():
                tops = []
                bottoms = []
                n = normalize_vector(
                    subtract_vectors(mesh.vertex_coordinates(vkey_2),
                                     network.node_coordinates(vkey)))
                for i in range(len(mesh.vertex_neighbors(vkey_2))):
                    pt_0 = mesh.edge_midpoint(
                        vkey_2,
                        mesh.vertex_neighbors(vkey_2, ordered=True)[i - 1])
                    bottoms.append(pt_0)
                    pt_1 = mesh.edge_midpoint(
                        vkey_2,
                        mesh.vertex_neighbors(vkey_2, ordered=True)[i])
                    pt_2 = midpoint_line([pt_0, pt_1])
                    pt_2 = add_vectors(
                        scale_vector(n, distance_point_point(pt_0, pt_1)),
                        pt_2)
                    tops.append(pt_2)
                    vertices = [pt_0, pt_2, pt_1]
                    faces = [[0, 1, 2]]
                    meshes.append(cls.from_vertices_and_faces(vertices, faces))
                for i in range(len(tops)):
                    vertices = [tops[i - 1], tops[i], bottoms[i]]
                    faces = [[0, 1, 2]]
                    meshes.append(cls.from_vertices_and_faces(vertices, faces))

                tube_extremities[(vkey, vkey_2)] = tops

            mesh = meshes_join_and_weld(meshes)

            nodes.append(mesh)

    all_nodes = meshes_join_and_weld(nodes)

    # leaf node ring
    for u in network.nodes():
        if len(network.adjacency[u]) == 1:
            v = next(iter(network.adjacency[u].keys()))
            ring_v = tube_extremities[(v, u)]
            ring_u = [
                add_vectors(pt, network.edge_vector(v, u))
                for pt in ring_v[::-1]
            ]
            tube_extremities[(u, v)] = ring_u

    beams = []
    for u, v in network.edges():

        geom_key_map = {
            geometric_key(all_nodes.vertex_coordinates(vkey)): vkey
            for vkey in all_nodes.vertices()
        }
        if len(tube_extremities[(u, v)]) != len(tube_extremities[(v, u)]):
            if len(tube_extremities[(u, v)]) < len(tube_extremities[(v, u)]):
                a, b = u, v
            else:
                a, b = v, u
            n = len(tube_extremities[(b, a)]) - len(tube_extremities[(a, b)])
            for i in range(n):
                bdry_vkey = geom_key_map[geometric_key(
                    tube_extremities[(a, b)][0])]
                nbr_vkey = None
                for nbr in all_nodes.vertex_neighbors(bdry_vkey):
                    if not all_nodes.is_edge_on_boundary(bdry_vkey, nbr):
                        nbr_vkey = nbr
                k = tube_extremities[(a, b)].index(
                    all_nodes.vertex_coordinates(bdry_vkey))
                new_vkey = insert_triface_on_boundary(all_nodes, bdry_vkey,
                                                      nbr_vkey)
                tube_extremities[(a, b)].insert(
                    k + 1 - len(tube_extremities[(a, b)]),
                    all_nodes.vertex_coordinates(new_vkey))

        if len(tube_extremities[(u, v)]) == len(tube_extremities[(v, u)]):
            n = len(tube_extremities[(u, v)])
            l = network.edge_length(u, v) - 2 * radius
            m = (floor(l / radius) + 1) * 2
            pt_uv = tube_extremities[(u, v)]
            pt_vu = list(reversed(tube_extremities[(v, u)]))
            dmin = -1
            imin = None
            for i in range(n):
                distance = sum([
                    distance_point_point(pt_uv[j], pt_vu[i + j - len(pt_vu)])
                    for j in range(n)
                ])
                if dmin < 0 or distance < dmin:
                    dmin = distance
                    imin = i
            pt_vu = [pt_vu[imin + j - len(pt_vu)] for j in range(n)]

            # ab = pt_uv# + pt_uv[0:]
            # dc = pt_vu# + pt_vu[0:]
            # line = Polyline([ab[0], dc[0]])
            # ad = [line.point(i / (m - 1)) for i in range(m)]
            # bc = ad
            # vertices, faces = discrete_coons_patch(ab, bc, dc, ad)
            # tri_faces = []
            # for (a, b, c, d) in faces:
            # 	tri_faces += [[a, b, c], [a, c, d]] # reverse?
            # beams.append(Mesh.from_vertices_and_faces(vertices, tri_faces))

            array = [pt_uv]
            for i in range(int(m)):
                polygon = []
                for j in range(int(n)):
                    u = pt_uv[j]
                    v = pt_vu[j]
                    polygon.append(
                        add_vectors(
                            scale_vector(u, (float(m) - 1 - float(i)) /
                                         float(m - 1)),
                            scale_vector(v,
                                         float(i) / float(m - 1))))
                array.append(polygon)
            array.append(pt_vu)
            for i in range(1, int(m + 2)):
                for j in range(int(n)):
                    vertices = [
                        array[i - 1][j - 1], array[i - 1][j], array[i][j - 1],
                        array[i][j]
                    ]  # create staggered pattern?
                    faces = [[3, 1, 0], [2, 3, 0]]
                    beams.append(cls.from_vertices_and_faces(vertices, faces))

    # return all_nodes
    # #return meshes_join_and_weld(beams)
    return meshes_join_and_weld([all_nodes] + beams)