Skip to content
Snippets Groups Projects
pdt_cad_module.py 6.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### BEGIN GPL LICENSE BLOCK #####
    #
    #  This program is free software; you can redistribute it and/or
    #  modify it under the terms of the GNU General Public License
    #  as published by the Free Software Foundation; either version 2
    
    #  of the License, or (at your ointersect_pointion) any later version.
    
    #
    #  This program is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU General Public License for more details.
    #
    #  You should have received a copy of the GNU General Public License
    #  along with this program; if not, write to the Free Software Foundation,
    #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    #
    # ##### END GPL LICENSE BLOCK #####
    #
    # <pep8 compliant>
    #
    # ----------------------------------------------------------
    # Author: Zeffii
    # Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
    # ----------------------------------------------------------
    #
    import bmesh
    from mathutils import Vector
    from mathutils.geometry import intersect_line_line, intersect_point_line
    from .pdt_functions import debug
    
    
    
    def point_on_edge(point, edge):
    
        """Find Point on Edge.
    
        Args:
    
            edge:     tuple containing 2 vectors.
    
        Returns:
    
            True if point happens to lie on the edge, False otherwise.
    
        intersect_point, _percent = intersect_point_line(point, *edge)
        on_line = (intersect_point - point).length < 1.0e-5
    
        return on_line and (0.0 <= _percent <= 1.0)
    
    
    def line_from_edge_intersect(edge1, edge2):
        """Get New Line from Intersections.
    
    
        Note:
            Prepares input for sending to intersect_line_line
    
    
        Args:
            edge1, edge2: tuples containing 2 vectors.
    
        Returns:
            Output of intersect_line_line.
        """
    
    
        [intersect_point1, intersect_point2], [intersect_point3, intersect_point4] = edge1, edge2
        return intersect_line_line(
            intersect_point1, intersect_point2, intersect_point3, intersect_point4
        )
    
    
    
    def get_intersection(edge1, edge2):
        """Get Intersections of 2 Edges.
    
        Args:
            edge1, edge2: tuples containing 2 vectors.
    
        Returns:
            The point halfway on line. See intersect_line_line.
        """
    
        line = line_from_edge_intersect(edge1, edge2)
        if line:
            return (line[0] + line[1]) / 2
    
    
    
    def test_coplanar(edge1, edge2):
        """Test 2 Edges are Co-planar.
    
    
        Note:
            The line that describes the shortest line between the two edges would be short if the
            lines intersect mathematically. If this line is longer than 1.0e-5 then they are either
            coplanar or parallel
    
    
        Args:
            edge1, edge2: tuples containing 2 vectors.
    
        Returns:
            True if edge1 and edge2 or coplanar, False otherwise.
        """
    
        line = line_from_edge_intersect(edge1, edge2)
        if line:
            return (line[0] - line[1]).length < 1.0e-5
    
    def closest_idx(intersect_point, edge):
    
        """Get Closest Vertex to input point.
    
    
        Note:
            If both points in edge are equally far from intersect_point, then v1 is returned.
    
            intersect_point:       vector
            edge:        bmesh edge
    
            Index of vertex closest to intersect_point.
    
        if isinstance(edge, bmesh.types.BMEdge):
            edge_verts = edge.verts
            vector_a = edge_verts[0].co
            vector_b = edge_verts[1].co
            distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
            return edge_verts[0].index if distance_test else edge_verts[1].index
    
        debug(f"Received {edge}, check expected input in docstring ")
        return None
    
    def closest_vector(intersect_point, edge):
    
        """Return Closest Vector to input Point.
    
    
        Note:
            If both points in e are equally far from intersect_point, then v1 is returned.
    
            intersect_point:       vector
            edge:        tuple containing 2 vectors
    
            Vector closest to intersect_point.
    
        if isinstance(edge, tuple) and all([isinstance(co, Vector) for co in edge]):
            vector_a, vector_b = edge
            distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
            return vector_a if distance_test else vector_b
    
        debug(f"Received {edge}, check expected input in docstring ")
        return None
    
    
    
    def coords_tuple_from_edge_idx(bm, idx):
    
        """Return Tuple from Vertices.
    
        Args:
            bm: Object Bmesh
            idx: Index of chosen Edge
    
        Returns:
            Tuple from Edge Vertices.
        """
    
    
        return tuple(v.co for v in bm.edges[idx].verts)
    
    
    def vectors_from_indices(bm, raw_vert_indices):
    
        """Return List of vectors from input Vertex Indices.
    
        Args:
            bm: Object Bmesh
            raw_vert_indices: List of Chosen Vertex Indices
    
        Returns:
            List of Vertex coordinates.
        """
    
    
        return [bm.verts[i].co for i in raw_vert_indices]
    
    
    def vertex_indices_from_edges_tuple(bm, edge_tuple):
        """Return List of vertices.
    
        Args:
    
            bm:           Active object's Bmesh
    
            edge_tuple:   contains 2 edge indices.
    
        Returns:
    
            The vertex indices of edge_tuple as an Integer list.
    
        def find_verts(ind_v, ind_w):
    
            return bm.edges[edge_tuple[ind_v]].verts[ind_w].index
    
        return [find_verts(i >> 1, i % 2) for i in range(4)]
    
    
    
    def get_vert_indices_from_bmedges(edges):
        """Return List of Edges for evaluation.
    
        Args:
    
            edges:      a list of 2 bm edges
    
    
        Returns:
            The vertex indices of edge_tuple as a flat list.
        """
    
        temp_edges = []
        debug(edges)
        for e in edges:
            for v in e.verts:
                temp_edges.append(v.index)
        return temp_edges
    
    
    
    def num_edges_point_lies_on(intersect_point, edges):
    
        """Returns the number of edges that a point lies on.
    
        Args:
            intersection_point: Vector describing 3D coordinates of intersection point
            edges: List of Bmesh edges
    
        Returns:
            Number of Intersecting Edges (Integer).
        """
    
    
        res = [point_on_edge(intersect_point, edge) for edge in [edges[:2], edges[2:]]]
    
        return len([i for i in res if i])
    
    
    
    def find_intersecting_edges(bm, intersect_point, idx1, idx2):
    
        """Find Intercecting Edges.
    
        Args:
    
            intersect_point: Vector describing 3D coordinates of intersection point
    
            idx1, idx2:    edge indices
    
            The list of edge indices where intersect_point is on those edges.
    
        if not intersect_point:
    
            return []
        idxs = [idx1, idx2]
        edges = [coords_tuple_from_edge_idx(bm, idx) for idx in idxs]
    
        return [idx for edge, idx in zip(edges, idxs) if point_on_edge(intersect_point, edge)]
    
    
    
    def vert_idxs_from_edge_idx(bm, idx):
    
        """Find Vertex Indices form Edge Indices.
    
        Args:
    
            bm: Object's Bmesh
            idx: Selection Index
    
    
        Returns:
            Vertex Indices of Edge.
        """
    
        edge = bm.edges[idx]
        return edge.verts[0].index, edge.verts[1].index