Beispiel #1
0
    def draw_geometry(self, geometry, name=None, color=None):
        # Imported colors take priority over a the parameter color
        if 'mesh_color.diffuse' in geometry.attributes:
            color = geometry.attributes['mesh_color.diffuse']

        key_index = geometry.key_index()
        vertices = geometry.vertices_attributes('xyz')
        faces = [[key_index[key] for key in geometry.face_vertices(fkey)]
                 for fkey in geometry.faces()]
        new_faces = []
        for face in faces:
            f = len(face)
            if f == 3:
                new_faces.append(face + face[-1:])
            elif f == 4:
                new_faces.append(face)
            elif f > 4:
                centroid = len(vertices)
                vertices.append(
                    centroid_polygon([vertices[index] for index in face]))
                for a, b in pairwise(face + face[0:1]):
                    new_faces.append([centroid, a, b, b])
            else:
                continue

        mesh = Rhino.Geometry.Mesh()

        if name:
            mesh.UserDictionary.Set('MeshName', name)

        if color:
            r, g, b, a = color
            mesh.UserDictionary.Set('MeshColor.R', r)
            mesh.UserDictionary.Set('MeshColor.G', g)
            mesh.UserDictionary.Set('MeshColor.B', b)
            mesh.UserDictionary.Set('MeshColor.A', a)

        for v in vertices:
            mesh.Vertices.Add(*v)
        for face in new_faces:
            mesh.Faces.AddFace(*face)

        mesh.Normals.ComputeNormals()
        mesh.Compact()

        # Try to fix invalid meshes
        if not mesh.IsValid:
            mesh.FillHoles()

        return mesh
Beispiel #2
0
    def face_center(self, fkey):
        """Compute the location of the center of mass of a face.

        Parameters
        ----------
        fkey : int
            The identifier of the face.

        Returns
        -------
        list
            The coordinates of the center of mass.
        """
        return centroid_polygon(self.face_coordinates(fkey))
Beispiel #3
0
    def draw_mesh(self, color=(0, 0, 0), disjoint=False):
        """Draw the mesh as a consolidated RhinoMesh.

        Parameters
        ----------
        color : tuple, optional
            The color of the mesh.
            Default is black, ``(0, 0, 0)``.
        disjoint : bool, optional
            Draw the faces of the mesh with disjoint vertices.
            Default is ``False``.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        Notes
        -----
        The mesh should be a valid Rhino Mesh object, which means it should have only triangular or quadrilateral faces.
        Faces with more than 4 vertices will be triangulated on-the-fly.
        """
        vertex_index = self.mesh.key_index()
        vertex_xyz = self.vertex_xyz
        vertices = [vertex_xyz[vertex] for vertex in self.mesh.vertices()]
        faces = [[vertex_index[vertex] for vertex in self.mesh.face_vertices(face)] for face in self.mesh.faces()]
        new_faces = []
        for face in faces:
            f = len(face)
            if f == 3:
                new_faces.append(face + face[-1:])
            elif f == 4:
                new_faces.append(face)
            elif f > 4:
                centroid = len(vertices)
                vertices.append(centroid_polygon([vertices[index] for index in face]))
                for a, b in pairwise(face + face[0:1]):
                    new_faces.append([centroid, a, b, b])
            else:
                continue
        layer = self.layer
        name = "{}".format(self.mesh.name)
        guid = compas_rhino.draw_mesh(vertices, new_faces, layer=layer, name=name, color=color, disjoint=disjoint)
        return [guid]
Beispiel #4
0
    def draw_mesh(self, color=None, disjoint=False):
        """Draw the mesh as a consolidated RhinoMesh.

        Parameters
        ----------
        color : 3-tuple, optional
            RGB color components in integer format (0-255).
        disjoint : bool, optional
            Draw the faces of the mesh with disjoint vertices.
            Default is ``False``.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        Notes
        -----
        The mesh should be a valid Rhino Mesh object, which means it should have
        only triangular or quadrilateral faces.
        Faces with more than 4 vertices will be triangulated on-the-fly.
        """
        key_index = self.mesh.key_index()
        vertices = self.mesh.vertices_attributes('xyz')
        faces = [[key_index[key] for key in self.mesh.face_vertices(fkey)] for fkey in self.mesh.faces()]
        new_faces = []
        for face in faces:
            f = len(face)
            if f == 3:
                new_faces.append(face + face[-1:])
            elif f == 4:
                new_faces.append(face)
            elif f > 4:
                centroid = len(vertices)
                vertices.append(centroid_polygon([vertices[index] for index in face]))
                for a, b in pairwise(face + face[0:1]):
                    new_faces.append([centroid, a, b, b])
            else:
                continue
        layer = self.layer
        name = "{}.mesh".format(self.mesh.name)
        guid = compas_rhino.draw_mesh(vertices, new_faces, layer=layer, name=name, color=color, disjoint=disjoint)
        self.guids += [guid]
        return [guid]
Beispiel #5
0
 def draw_mesh(self, color=None):
     key_index = self.mesh.key_index()
     vertices = self.mesh.vertices_attributes('xyz')
     faces = [[key_index[key] for key in self.mesh.face_vertices(fkey)]
              for fkey in self.mesh.faces()]
     new_faces = []
     for face in faces:
         f = len(face)
         if f == 3:
             new_faces.append(face + [face[-1]])
         elif f == 4:
             new_faces.append(face)
         elif f > 4:
             centroid = len(vertices)
             vertices.append(
                 centroid_polygon([vertices[index] for index in face]))
             for a, b in pairwise(face + face[0:1]):
                 new_faces.append([centroid, a, b, b])
         else:
             continue
     return compas_ghpython.draw_mesh(vertices, new_faces, color)
Beispiel #6
0
    def draw_mesh(self, color=None, disjoint=False):
        """Draw the mesh as a consolidated RhinoMesh.

        Notes
        -----
        The mesh should be a valid Rhino Mesh object, which means it should have
        only triangular or quadrilateral faces.

        """
        key_index = self.mesh.key_index()
        vertices = self.mesh.get_vertices_attributes('xyz')
        faces = [[key_index[key] for key in self.mesh.face_vertices(fkey)]
                 for fkey in self.mesh.faces()]
        new_faces = []
        for face in faces:
            f = len(face)
            if f == 3:
                new_faces.append(face + face[-1:])
            elif f == 4:
                new_faces.append(face)
            elif f > 4:
                centroid = len(vertices)
                vertices.append(
                    centroid_polygon([vertices[index] for index in face]))
                for a, b in pairwise(face + face[0:1]):
                    new_faces.append([centroid, a, b, b])
            else:
                continue
        layer = self.layer
        name = "{}.mesh".format(self.mesh.name)
        return compas_rhino.draw_mesh(vertices,
                                      new_faces,
                                      layer=layer,
                                      name=name,
                                      color=color,
                                      disjoint=disjoint)
Beispiel #7
0
def get_area_convex_2d_polygon(polygon):
    """ Computes the area of a convex 2d polygon by using cross product
    """

    area = 0

    centroid = centroid_polygon(polygon)
    centroid_vect = Vector(centroid[0], centroid[1], centroid[2])

    for i in range(len(polygon)):
        pt1 = Vector(polygon[i][0], polygon[i][1], polygon[i][2])
        pt2 = Vector(polygon[i-1][0], polygon[i-1][1], polygon[i-1][2])

        vect_side1 = pt1 - centroid_vect
        vect_side2 = pt2 - centroid_vect

        cross = cross_vectors(vect_side1, vect_side2)
        cross_length = length_vector(cross)
        face_area = cross_length / 2

        area += face_area

    print(area)
    return area
Beispiel #8
0
 def centroid(self):
     """int : The centroid of the polygon."""
     point = centroid_polygon(self.points)
     return Point(*point)
Beispiel #9
0
def smooth_centerofmass(vertices,
                        adjacency,
                        fixed=None,
                        kmax=1,
                        damping=0.5,
                        callback=None,
                        callback_args=None):
    """Smooth a connected set of vertices by moving each vertex to
    the center of mass of the polygon formed by the neighboring vertices.

    Parameters
    ----------
    verticses : dict
        A dictionary of vertex coordinates.
    adjacency : dict
        Adjacency information for each of the vertices.
    fixed : list, optional
        The fixed vertices of the mesh.
    kmax : int, optional
        The maximum number of iterations.
    d : float, optional
        The damping factor.
    callback : callable, optional
        A user-defined callback function to be executed after every iteration.
    callback_args : list, optional
        A list of arguments to be passed to the callback.

    Raises
    ------
    Exception
        If a callback is provided, but it is not callable.

    Notes
    -----
    When using this algorithm in combination with one of the datastructures (as in the example below),
    note that the neighbors of each vertex have to be listed in order, i.e. they have to form a polygon
    without self-intersections.

    Examples
    --------
    .. plot::
        :include-source:

        import compas
        from compas.datastructures import Mesh
        from compas.geometry import smooth_centerofmass
        from compas.plotters import MeshPlotter

        mesh = Mesh.from_obj(compas.get('faces.obj'))

        vertices  = mesh.get_vertices_attributes('xyz')
        adjacency = [mesh.vertex_neighbors(key, ordered=True) for key in mesh.vertices()]
        fixed     = [key for key in mesh.vertices() if mesh.vertex_degree(key) == 2]

        lines = []
        for u, v in mesh.edges():
            lines.append({
                'start': mesh.vertex_coordinates(u, 'xy'),
                'end'  : mesh.vertex_coordinates(v, 'xy'),
                'color': '#cccccc',
                'width': 1.0,
            })

        smooth_centerofmass(vertices, adjacency, fixed=fixed, kmax=100)

        for key, attr in mesh.vertices(True):
            attr['x'] = vertices[key][0]
            attr['y'] = vertices[key][1]
            attr['z'] = vertices[key][2]

        plotter = MeshPlotter(mesh)

        plotter.draw_lines(lines)
        plotter.draw_vertices(facecolor={key: '#ff0000' for key in fixed})
        plotter.draw_edges()

        plotter.show()

    """
    fixed = fixed or []
    fixed = set(fixed)

    if callback:
        if not callable(callback):
            raise Exception('The callback is not callable.')

    for k in range(kmax):
        xyz_0 = [xyz[:] for xyz in vertices]

        for index, point in enumerate(xyz_0):
            if index in fixed:
                continue

            com = centroid_polygon([xyz_0[nbr] for nbr in adjacency[index]])

            vertices[index][0] += damping * (com[0] - point[0])
            vertices[index][1] += damping * (com[1] - point[1])
            vertices[index][2] += damping * (com[2] - point[2])

        if callback:
            callback(k, callback_args)
Beispiel #10
0
def mesh_smooth_centerofmass(mesh,
                             fixed=None,
                             kmax=100,
                             damping=0.5,
                             callback=None,
                             callback_args=None):
    """Smooth a mesh by moving every free vertex to the center of mass of the polygon formed by the neighboring vertices.

    Parameters
    ----------
    mesh : Mesh
        A mesh object.
    fixed : list, optional
        The fixed vertices of the mesh.
    kmax : int, optional
        The maximum number of iterations.
    damping : float, optional
        The damping factor.
    callback : callable, optional
        A user-defined callback function to be executed after every iteration.
    callback_args : list, optional
        A list of arguments to be passed to the callback.

    Raises
    ------
    Exception
        If a callback is provided, but it is not callable.

    Examples
    --------
    >>>

    """
    if callback:
        if not callable(callback):
            raise Exception('Callback is not callable.')

    fixed = fixed or []
    fixed = set(fixed)

    for k in range(kmax):
        key_xyz = {
            key: mesh.vertex_coordinates(key)
            for key in mesh.vertices()
        }

        for key, attr in mesh.vertices(True):
            if key in fixed:
                continue

            x, y, z = key_xyz[key]

            cx, cy, cz = centroid_polygon([
                key_xyz[nbr]
                for nbr in mesh.vertex_neighbors(key, ordered=True)
            ])

            attr['x'] += damping * (cx - x)
            attr['y'] += damping * (cy - y)
            attr['z'] += damping * (cz - z)

        if callback:
            callback(k, callback_args)
Beispiel #11
0
def draw_mesh(vertices, faces, name=None, color=None, disjoint=False, **kwargs):
    """Draw a mesh and optionally set individual name, color, and layer properties.

    Parameters
    ----------
    vertices : :obj:`list` of point
        A list of point locations.
    faces : :obj:`list` of :obj:`list` of :obj:`int`
        A list of faces as lists of indices into ``vertices``.
    name : :obj:`str`, optional
    color : RGB :obj:`tuple`, optional
    disjoint : :obj:`bool`, optional
        Draw the mesh with disjoint faces.
        Default is ``False``.

    Returns
    -------
    str or GUID

    """
    mesh = RhinoMesh()
    if disjoint:
        for face in faces:
            f = len(face)
            if f < 3:
                continue
            if f == 3:
                a = mesh.Vertices.Add(* vertices[face[0]])
                b = mesh.Vertices.Add(* vertices[face[1]])
                c = mesh.Vertices.Add(* vertices[face[2]])
                mesh.Faces.AddFace(a, b, c)
            elif f == 4:
                a = mesh.Vertices.Add(* vertices[face[0]])
                b = mesh.Vertices.Add(* vertices[face[1]])
                c = mesh.Vertices.Add(* vertices[face[2]])
                d = mesh.Vertices.Add(* vertices[face[3]])
                mesh.Faces.AddFace(a, b, c, d)
            else:
                if MeshNgon:
                    points = [vertices[vertex] for vertex in face]
                    centroid = centroid_polygon(points)
                    indices = []
                    for point in points:
                        indices.append(mesh.Vertices.Add(* point))
                    c = mesh.Vertices.Add(* centroid)
                    facets = []
                    for i, j in pairwise(indices + indices[:1]):
                        facets.append(mesh.Faces.AddFace(i, j, c))
                    ngon = MeshNgon.Create(indices, facets)
                    mesh.Ngons.AddNgon(ngon)
    else:
        for x, y, z in vertices:
            mesh.Vertices.Add(x, y, z)
        for face in faces:
            f = len(face)
            if f < 3:
                continue
            if f == 3:
                mesh.Faces.AddFace(*face)
            elif f == 4:
                mesh.Faces.AddFace(*face)
            else:
                if MeshNgon:
                    centroid = centroid_polygon([vertices[index] for index in face])
                    c = mesh.Vertices.Add(* centroid)
                    facets = []
                    for i, j in pairwise(face + face[:1]):
                        facets.append(mesh.Faces.AddFace(i, j, c))
                    ngon = MeshNgon.Create(face, facets)
                    mesh.Ngons.AddNgon(ngon)

    mesh.Normals.ComputeNormals()
    mesh.Compact()

    guid = add_mesh(mesh)

    if guid != System.Guid.Empty:
        obj = find_object(guid)
        if obj:
            attr = obj.Attributes
            if color:
                attr.ObjectColor = FromArgb(*color)
                attr.ColorSource = ColorFromObject
            else:
                attr.ColorSource = ColorFromLayer
            if name:
                attr.Name = name
            obj.CommitChanges()
        return guid
Beispiel #12
0
    def create_geometry(self, geometry, name=None, color=None):
        """Create a Rhino mesh corresponding to the geometry of the model.

        Parameters
        ----------
        geometry : :class:`compas.datastructures.Mesh`
            A COMPAS mesh data structure.
        name : str, optional
            Name of the mesh object.
        color : tuple[int, int, int], optional
            Color of the mesh object.

        Returns
        -------
        :rhino:`Rhino.Geometry.Mesh`

        """
        # Imported colors take priority over a the parameter color
        if 'mesh_color.diffuse' in geometry.attributes:
            color = geometry.attributes['mesh_color.diffuse']

        key_index = geometry.key_index()
        vertices = geometry.vertices_attributes('xyz')
        faces = [[key_index[key] for key in geometry.face_vertices(fkey)] for fkey in geometry.faces()]
        new_faces = []
        for face in faces:
            f = len(face)
            if f == 3:
                new_faces.append(face + face[-1:])
            elif f == 4:
                new_faces.append(face)
            elif f > 4:
                centroid = len(vertices)
                vertices.append(centroid_polygon([vertices[index] for index in face]))
                for a, b in pairwise(face + face[0:1]):
                    new_faces.append([centroid, a, b, b])
            else:
                continue

        mesh = Rhino.Geometry.Mesh()

        if name:
            mesh.UserDictionary.Set('MeshName', name)

        if color:
            r, g, b, a = color
            mesh.UserDictionary.Set('MeshColor.R', r)
            mesh.UserDictionary.Set('MeshColor.G', g)
            mesh.UserDictionary.Set('MeshColor.B', b)
            mesh.UserDictionary.Set('MeshColor.A', a)

        for v in vertices:
            mesh.Vertices.Add(*v)
        for face in new_faces:
            mesh.Faces.AddFace(*face)

        mesh.Normals.ComputeNormals()
        mesh.Compact()

        # Try to fix invalid meshes
        if not mesh.IsValid:
            mesh.FillHoles()

        return mesh
Beispiel #13
0
def mesh_smooth_centerofmass(mesh, fixed=None, kmax=100, damping=0.5, callback=None, callback_args=None):
    """Smooth a mesh by moving every free vertex to the center of mass of the polygon formed by the neighboring vertices.

    Parameters
    ----------
    mesh : Mesh
        A mesh object.
    fixed : list, optional
        The fixed vertices of the mesh.
    kmax : int, optional
        The maximum number of iterations.
    damping : float, optional
        The damping factor.
    callback : callable, optional
        A user-defined callback function to be executed after every iteration.
    callback_args : list, optional
        A list of arguments to be passed to the callback.

    Raises
    ------
    Exception
        If a callback is provided, but it is not callable.

    Examples
    --------
    .. plot::
        :include-source:

        import compas

        from compas.datastructures import Mesh
        from compas.datastructures import mesh_smooth_centerofmass
        from compas_plotters import MeshPlotter

        mesh = Mesh.from_obj(compas.get('faces.obj'))
        fixed = [key for key in mesh.vertices() if mesh.vertex_degree(key) == 2]

        mesh_smooth_centerofmass(mesh, fixed=fixed)

        plotter = MeshPlotter(mesh)

        plotter.draw_vertices(facecolor={key: '#ff0000' for key in fixed})
        plotter.draw_faces()
        plotter.draw_edges()

        plotter.show()

    """
    if callback:
        if not callable(callback):
            raise Exception('Callback is not callable.')

    fixed = fixed or []
    fixed = set(fixed)

    for k in range(kmax):
        key_xyz = {key: mesh.vertex_coordinates(key) for key in mesh.vertices()}

        for key, attr in mesh.vertices(True):
            if key in fixed:
                continue

            x, y, z = key_xyz[key]

            cx, cy, cz = centroid_polygon([key_xyz[nbr] for nbr in mesh.vertex_neighbors(key, ordered=True)])

            attr['x'] += damping * (cx - x)
            attr['y'] += damping * (cy - y)
            attr['z'] += damping * (cz - z)

        if callback:
            callback(k, callback_args)
Beispiel #14
0
 def face_center(self, fkey):
     """Return the location of the center of mass of a face."""
     return centroid_polygon(self.face_coordinates(fkey))
Beispiel #15
0
 def centroid(self):
     point = centroid_polygon(self.points)
     return Point(*point)