Ejemplo n.º 1
0
def smooth_mesh_centerofmass(mesh,
                             fixed=None,
                             kmax=1,
                             d=1.0,
                             callback=None,
                             callback_args=None):
    """"""

    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}

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

            p = key_xyz[key]

            nbrs = mesh.vertex_neighbours(key, ordered=True)
            c = center_of_mass_polygon([key_xyz[nbr] for nbr in nbrs])

            # update
            attr = mesh.vertex[key]
            attr['x'] += d * (c[0] - p[0])
            attr['y'] += d * (c[1] - p[1])
            attr['z'] += d * (c[2] - p[2])

        if callback:
            callback(mesh, k, callback_args)
Ejemplo n.º 2
0
def _face_to_max_quad(points, face):
    faces = []
    c = len(points)
    points.append(center_of_mass_polygon(points))
    for i in range(-1, len(face) - 1):
        a = face[i]
        b = face[i + 1]
        faces.append([c, a, b, b])
    return faces
Ejemplo n.º 3
0
 def face_center(self, fkey):
     """Return the location of the center of mass of a face."""
     return center_of_mass_polygon(self.face_coordinates(fkey))
Ejemplo n.º 4
0
 def center(self):
     """The center (of mass) of the polygon."""
     return Point(* center_of_mass_polygon(self.points))
Ejemplo n.º 5
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 neighbouring 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.plotters import MeshPlotter
        from compas.geometry import mesh_smooth_centerofmass

        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()

    See Also
    --------
    * :func:`mesh_smooth_area`

    """
    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 = center_of_mass_polygon(
                [key_xyz[nbr] for nbr in mesh.vertex_neighbours(key)])

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

        if callback:
            callback(k, callback_args)
Ejemplo n.º 6
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 neighbouring 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 neighbours 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')
        neighbours = [mesh.vertex_neighbours(key) 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, neighbours, 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()

    See Also
    --------
    * :func:`smooth_centroid`
    * :func:`smooth_area`

    """
    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

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

            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)
Ejemplo n.º 7
0
def network_smooth_mass(network,
                        fixed=None,
                        kmax=1,
                        d=0.5,
                        callback=None,
                        callback_args=None):
    """Smooth a network using per vertex the center of mass of the polygon formed by the neighbouring vertices.

    Parameters:
        network (compas.datastructures.network.Network): The network object.
        fixed (list): Optional.
            The fixed vertices of the network. Default is ``None``.
        kmax (int): Optional.
            The maximum number of iterations. Default is ``1``.
        d (float): Optional.
            The damping factor. Default is ``0.5``.
        callback (callable): Optional.
            A user-defined callback function to be executed after every iteration.
            Default is ``None``.

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

    Example:

        .. plot::
            :include-source:

            import compas
            from compas.datastructures.network import Network
            from compas.visualization.plotters import NetworkPlotter
            from compas.datastructures.network.algorithms import network_find_faces
            from compas.datastructures.network.algorithms import network_smooth_mass

            network  = Network.from_obj(compas.get_data('grid_irregular.obj'))

            network_find_faces(network, network.leaves())
            network_smooth_mass(network, fixed=network.leaves(), kmax=10)

            plotter = NetworkPlotter(network)

            plotter.draw_vertices()
            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):
        key_xyz = {
            key: network.vertex_coordinates(key)
            for key in network.vertices()
        }

        for key in network:
            if key in fixed:
                continue

            nbrs = network.vertex_neighbours(key, ordered=True)
            points = [key_xyz[nbr] for nbr in nbrs]
            cx, cy, cz = center_of_mass_polygon(points)
            x, y, z = key_xyz[key]
            attr = network.vertex[key]
            attr['x'] += d * (cx - x)
            attr['y'] += d * (cy - y)
            attr['z'] += d * (cz - z)

        if callback:
            callback(network, k, callback_args)