Merge branch 'blender-v2.92-release'
[blender-addons.git] / precision_drawing_tools / pdt_cad_module.py
blobfc1d46337b143a1761be3d8a6088027dbebb5c49
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your ointersect_pointion) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
21 # ----------------------------------------------------------
22 # Author: Zeffii
23 # Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
24 # ----------------------------------------------------------
26 import bmesh
27 from mathutils import Vector
28 from mathutils.geometry import intersect_line_line, intersect_point_line
29 from .pdt_functions import debug
32 def point_on_edge(point, edge):
33 """Find Point on Edge.
35 Args:
36 point: vector
37 edge: tuple containing 2 vectors.
39 Returns:
40 True if point happens to lie on the edge, False otherwise.
41 """
43 intersect_point, _percent = intersect_point_line(point, *edge)
44 on_line = (intersect_point - point).length < 1.0e-5
45 return on_line and (0.0 <= _percent <= 1.0)
48 def line_from_edge_intersect(edge1, edge2):
49 """Get New Line from Intersections.
51 Note:
52 Prepares input for sending to intersect_line_line
54 Args:
55 edge1, edge2: tuples containing 2 vectors.
57 Returns:
58 Output of intersect_line_line.
59 """
61 [intersect_point1, intersect_point2], [intersect_point3, intersect_point4] = edge1, edge2
62 return intersect_line_line(
63 intersect_point1, intersect_point2, intersect_point3, intersect_point4
67 def get_intersection(edge1, edge2):
68 """Get Intersections of 2 Edges.
70 Args:
71 edge1, edge2: tuples containing 2 vectors.
73 Returns:
74 The point halfway on line. See intersect_line_line.
75 """
77 line = line_from_edge_intersect(edge1, edge2)
78 if line:
79 return (line[0] + line[1]) / 2
80 return None
83 def test_coplanar(edge1, edge2):
84 """Test 2 Edges are Co-planar.
86 Note:
87 The line that describes the shortest line between the two edges would be short if the
88 lines intersect mathematically. If this line is longer than 1.0e-5 then they are either
89 coplanar or parallel
91 Args:
92 edge1, edge2: tuples containing 2 vectors.
94 Returns:
95 True if edge1 and edge2 or coplanar, False otherwise.
96 """
98 line = line_from_edge_intersect(edge1, edge2)
99 if line:
100 return (line[0] - line[1]).length < 1.0e-5
101 return None
104 def closest_idx(intersect_point, edge):
105 """Get Closest Vertex to input point.
107 Note:
108 If both points in edge are equally far from intersect_point, then v1 is returned.
110 Args:
111 intersect_point: vector
112 edge: bmesh edge
114 Returns:
115 Index of vertex closest to intersect_point.
118 if isinstance(edge, bmesh.types.BMEdge):
119 edge_verts = edge.verts
120 vector_a = edge_verts[0].co
121 vector_b = edge_verts[1].co
122 distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
123 return edge_verts[0].index if distance_test else edge_verts[1].index
125 debug(f"Received {edge}, check expected input in docstring ")
126 return None
129 def closest_vector(intersect_point, edge):
130 """Return Closest Vector to input Point.
132 Note:
133 If both points in e are equally far from intersect_point, then v1 is returned.
135 Args:
136 intersect_point: vector
137 edge: tuple containing 2 vectors
139 Returns:
140 Vector closest to intersect_point.
143 if isinstance(edge, tuple) and all([isinstance(co, Vector) for co in edge]):
144 vector_a, vector_b = edge
145 distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
146 return vector_a if distance_test else vector_b
148 debug(f"Received {edge}, check expected input in docstring ")
149 return None
152 def coords_tuple_from_edge_idx(bm, idx):
153 """Return Tuple from Vertices.
155 Args:
156 bm: Object Bmesh
157 idx: Index of chosen Edge
159 Returns:
160 Tuple from Edge Vertices.
163 return tuple(v.co for v in bm.edges[idx].verts)
166 def vectors_from_indices(bm, raw_vert_indices):
167 """Return List of vectors from input Vertex Indices.
169 Args:
170 bm: Object Bmesh
171 raw_vert_indices: List of Chosen Vertex Indices
173 Returns:
174 List of Vertex coordinates.
177 return [bm.verts[i].co for i in raw_vert_indices]
180 def vertex_indices_from_edges_tuple(bm, edge_tuple):
181 """Return List of vertices.
183 Args:
184 bm: Active object's Bmesh
185 edge_tuple: contains 2 edge indices.
187 Returns:
188 The vertex indices of edge_tuple as an Integer list.
191 def find_verts(ind_v, ind_w):
192 return bm.edges[edge_tuple[ind_v]].verts[ind_w].index
194 return [find_verts(i >> 1, i % 2) for i in range(4)]
197 def get_vert_indices_from_bmedges(edges):
198 """Return List of Edges for evaluation.
200 Args:
201 edges: a list of 2 bm edges
203 Returns:
204 The vertex indices of edge_tuple as a flat list.
207 temp_edges = []
208 debug(edges)
209 for e in edges:
210 for v in e.verts:
211 temp_edges.append(v.index)
212 return temp_edges
215 def num_edges_point_lies_on(intersect_point, edges):
216 """Returns the number of edges that a point lies on.
218 Args:
219 intersection_point: Vector describing 3D coordinates of intersection point
220 edges: List of Bmesh edges
222 Returns:
223 Number of Intersecting Edges (Integer).
226 res = [point_on_edge(intersect_point, edge) for edge in [edges[:2], edges[2:]]]
227 return len([i for i in res if i])
230 def find_intersecting_edges(bm, intersect_point, idx1, idx2):
231 """Find Intercecting Edges.
233 Args:
234 intersect_point: Vector describing 3D coordinates of intersection point
235 idx1, idx2: edge indices
237 Returns:
238 The list of edge indices where intersect_point is on those edges.
241 if not intersect_point:
242 return []
243 idxs = [idx1, idx2]
244 edges = [coords_tuple_from_edge_idx(bm, idx) for idx in idxs]
245 return [idx for edge, idx in zip(edges, idxs) if point_on_edge(intersect_point, edge)]
248 def vert_idxs_from_edge_idx(bm, idx):
249 """Find Vertex Indices form Edge Indices.
251 Args:
252 bm: Object's Bmesh
253 idx: Selection Index
255 Returns:
256 Vertex Indices of Edge.
259 edge = bm.edges[idx]
260 return edge.verts[0].index, edge.verts[1].index