Exemple #1
0
    def face_flatness(self, face, maxdev=0.02):
        """Compute the flatness of a face.

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

        Returns
        -------
        float
            The flatness.

        Note
        ----
        compas.geometry.mesh_flatness function currently only works for quadrilateral faces.
        This function uses the distance between each face vertex and its projected point
        on the best-fit plane of the face as the flatness metric.

        """
        deviation = 0
        polygon = self.face_coordinates(face)
        plane = bestfit_plane(polygon)
        for pt in polygon:
            pt_proj = project_point_plane(pt, plane)
            dev = distance_point_point(pt, pt_proj)
            if dev > deviation:
                deviation = dev
        return deviation
Exemple #2
0
    def face_curvature(self, fkey):
        """Dimensionless face curvature.

        Face curvature is defined as the maximum face vertex deviation from
        the best-fit plane of the face vertices divided by the average lengths of
        the face vertices to the face centroid.

        Parameters
        ----------
        fkey : int
            The face key.

        Returns
        -------
        float
            The dimensionless curvature.

        """
        vertices = self.face_vertices(fkey)
        points = [self.vertex_coordinates(key) for key in vertices]
        centroid = self.face_centroid(fkey)
        plane = bestfit_plane(points)
        max_deviation = max(
            [distance_point_plane(point, plane) for point in points])
        average_distances = vector_average(
            [distance_point_point(point, centroid) for point in points])
        return max_deviation / average_distances
Exemple #3
0
def polygon_flatness(polygon):
    """Comput the flatness of a polygon.

    Parameters
    ----------
    polygon : list of lists
        A list of polygon point coordinates.

    Returns
    -------
    float
        The flatness.

    Note
    ----
    compas.geometry.mesh_flatness function currently only works for quadrilateral faces.
    This function uses the distance between each face vertex and its projected point on the best-fit plane of the face as the flatness metric.

    """
    deviation = 0

    plane     = bestfit_plane(polygon)

    for pt in polygon:
        pt_proj = project_point_plane(pt, plane)
        dev     = distance_point_point(pt, pt_proj)
        if dev > deviation:
            deviation = dev

    return deviation
Exemple #4
0
def planarize_faces(vertices,
                    faces,
                    fixed=None,
                    kmax=100,
                    callback=None,
                    callback_args=None):
    """Planarise a set of connected faces.

    Planarisation is implemented as a two-step iterative procedure. At every
    iteration, faces are first individually projected to their best-fit plane,
    and then the vertices are projected to the centroid of the disconnected
    corners of the faces.

    Parameters
    ----------
    vertices : list
        The vertex coordinates.
    faces : list
        The vertex indices per face.
    fixed : list, optional [None]
        A list of fixed vertices.
    kmax : int, optional [100]
        The number of iterations.
    callback : callable, optional [None]
        A user-defined callback that is called after every iteration.
    callback_args : list, optional [None]
        A list of arguments to be passed to the callback function.

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

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

    for k in range(kmax):

        positions = [[] for _ in range(len(vertices))]

        for face in iter(faces):
            points = [vertices[index] for index in face]
            plane = bestfit_plane(points)
            projections = project_points_plane(points, plane)

            for i, index in enumerate(face):
                positions[index].append(projections[i])

        for index, vertex in enumerate(vertices):
            if index in fixed:
                continue

            x, y, z = centroid_points(positions[index])
            vertex[0] = x
            vertex[1] = y
            vertex[2] = z

        if callback:
            callback(k, callback_args)
Exemple #5
0
def mesh_planarize_faces(mesh,
                         fixed=None,
                         kmax=100,
                         callback=None,
                         callback_args=None):
    """Planarise a set of connected faces.

    Planarisation is implemented as a two-step iterative procedure. At every
    iteration, faces are first individually projected to their best-fit plane,
    and then the vertices are projected to the centroid of the disconnected
    corners of the faces.

    Parameters
    ----------
    mesh : :class:`compas.datastructures.Mesh`
        A mesh object.
    fixed : list[int], optional
        A list of fixed vertices.
    kmax : int, optional
        The number of iterations.
    d : float, optional
        A damping factor.
    callback : callable, optional
        A user-defined callback that is called after every iteration.
    callback_args : list[Any], optional
        A list of arguments to be passed to the callback function.

    Returns
    -------
    None

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

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

    for k in range(kmax):

        positions = {key: [] for key in mesh.vertices()}

        for fkey in mesh.faces():
            vertices = mesh.face_vertices(fkey)
            points = [mesh.vertex_coordinates(key) for key in vertices]
            plane = bestfit_plane(points)
            projections = project_points_plane(points, plane)

            for index, key in enumerate(vertices):
                positions[key].append(projections[index])

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

            x, y, z = centroid_points(positions[key])
            attr['x'] = x
            attr['y'] = y
            attr['z'] = z

        if callback:
            callback(k, callback_args)