AnimAll: rename the "Animate" tab back to "Animation"
[blender-addons.git] / precision_drawing_tools / pdt_cad_module.py
blob48cd41d1400b02a7b903ec54f6e23a111c50459e
1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 # ----------------------------------------------------------
7 # Author: Zeffii
8 # Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
9 # ----------------------------------------------------------
11 import bmesh
12 from mathutils import Vector
13 from mathutils.geometry import intersect_line_line, intersect_point_line
14 from .pdt_functions import debug
17 def point_on_edge(point, edge):
18 """Find Point on Edge.
20 Args:
21 point: vector
22 edge: tuple containing 2 vectors.
24 Returns:
25 True if point happens to lie on the edge, False otherwise.
26 """
28 intersect_point, _percent = intersect_point_line(point, *edge)
29 on_line = (intersect_point - point).length < 1.0e-5
30 return on_line and (0.0 <= _percent <= 1.0)
33 def line_from_edge_intersect(edge1, edge2):
34 """Get New Line from Intersections.
36 Note:
37 Prepares input for sending to intersect_line_line
39 Args:
40 edge1, edge2: tuples containing 2 vectors.
42 Returns:
43 Output of intersect_line_line.
44 """
46 [intersect_point1, intersect_point2], [intersect_point3, intersect_point4] = edge1, edge2
47 return intersect_line_line(
48 intersect_point1, intersect_point2, intersect_point3, intersect_point4
52 def get_intersection(edge1, edge2):
53 """Get Intersections of 2 Edges.
55 Args:
56 edge1, edge2: tuples containing 2 vectors.
58 Returns:
59 The point halfway on line. See intersect_line_line.
60 """
62 line = line_from_edge_intersect(edge1, edge2)
63 if line:
64 return (line[0] + line[1]) / 2
65 return None
68 def test_coplanar(edge1, edge2):
69 """Test 2 Edges are Co-planar.
71 Note:
72 The line that describes the shortest line between the two edges would be short if the
73 lines intersect mathematically. If this line is longer than 1.0e-5 then they are either
74 coplanar or parallel
76 Args:
77 edge1, edge2: tuples containing 2 vectors.
79 Returns:
80 True if edge1 and edge2 or coplanar, False otherwise.
81 """
83 line = line_from_edge_intersect(edge1, edge2)
84 if line:
85 return (line[0] - line[1]).length < 1.0e-5
86 return None
89 def closest_idx(intersect_point, edge):
90 """Get Closest Vertex to input point.
92 Note:
93 If both points in edge are equally far from intersect_point, then v1 is returned.
95 Args:
96 intersect_point: vector
97 edge: bmesh edge
99 Returns:
100 Index of vertex closest to intersect_point.
103 if isinstance(edge, bmesh.types.BMEdge):
104 edge_verts = edge.verts
105 vector_a = edge_verts[0].co
106 vector_b = edge_verts[1].co
107 distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
108 return edge_verts[0].index if distance_test else edge_verts[1].index
110 debug(f"Received {edge}, check expected input in docstring ")
111 return None
114 def closest_vector(intersect_point, edge):
115 """Return Closest Vector to input Point.
117 Note:
118 If both points in e are equally far from intersect_point, then v1 is returned.
120 Args:
121 intersect_point: vector
122 edge: tuple containing 2 vectors
124 Returns:
125 Vector closest to intersect_point.
128 if isinstance(edge, tuple) and all([isinstance(co, Vector) for co in edge]):
129 vector_a, vector_b = edge
130 distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
131 return vector_a if distance_test else vector_b
133 debug(f"Received {edge}, check expected input in docstring ")
134 return None
137 def coords_tuple_from_edge_idx(bm, idx):
138 """Return Tuple from Vertices.
140 Args:
141 bm: Object Bmesh
142 idx: Index of chosen Edge
144 Returns:
145 Tuple from Edge Vertices.
148 return tuple(v.co for v in bm.edges[idx].verts)
151 def vectors_from_indices(bm, raw_vert_indices):
152 """Return List of vectors from input Vertex Indices.
154 Args:
155 bm: Object Bmesh
156 raw_vert_indices: List of Chosen Vertex Indices
158 Returns:
159 List of Vertex coordinates.
162 return [bm.verts[i].co for i in raw_vert_indices]
165 def vertex_indices_from_edges_tuple(bm, edge_tuple):
166 """Return List of vertices.
168 Args:
169 bm: Active object's Bmesh
170 edge_tuple: contains 2 edge indices.
172 Returns:
173 The vertex indices of edge_tuple as an Integer list.
176 def find_verts(ind_v, ind_w):
177 return bm.edges[edge_tuple[ind_v]].verts[ind_w].index
179 return [find_verts(i >> 1, i % 2) for i in range(4)]
182 def get_vert_indices_from_bmedges(edges):
183 """Return List of Edges for evaluation.
185 Args:
186 edges: a list of 2 bm edges
188 Returns:
189 The vertex indices of edge_tuple as a flat list.
192 temp_edges = []
193 debug(edges)
194 for e in edges:
195 for v in e.verts:
196 temp_edges.append(v.index)
197 return temp_edges
200 def num_edges_point_lies_on(intersect_point, edges):
201 """Returns the number of edges that a point lies on.
203 Args:
204 intersection_point: Vector describing 3D coordinates of intersection point
205 edges: List of Bmesh edges
207 Returns:
208 Number of Intersecting Edges (Integer).
211 res = [point_on_edge(intersect_point, edge) for edge in [edges[:2], edges[2:]]]
212 return len([i for i in res if i])
215 def find_intersecting_edges(bm, intersect_point, idx1, idx2):
216 """Find Intercecting Edges.
218 Args:
219 intersect_point: Vector describing 3D coordinates of intersection point
220 idx1, idx2: edge indices
222 Returns:
223 The list of edge indices where intersect_point is on those edges.
226 if not intersect_point:
227 return []
228 idxs = [idx1, idx2]
229 edges = [coords_tuple_from_edge_idx(bm, idx) for idx in idxs]
230 return [idx for edge, idx in zip(edges, idxs) if point_on_edge(intersect_point, edge)]
233 def vert_idxs_from_edge_idx(bm, idx):
234 """Find Vertex Indices form Edge Indices.
236 Args:
237 bm: Object's Bmesh
238 idx: Selection Index
240 Returns:
241 Vertex Indices of Edge.
244 edge = bm.edges[idx]
245 return edge.verts[0].index, edge.verts[1].index