Cleanup: remove "Tweak" event type
[blender-addons.git] / precision_drawing_tools / pdt_cad_module.py
blobb68660ad8f511596e88c6b7435a64f3960b450c5
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # <pep8 compliant>
5 # ----------------------------------------------------------
6 # Author: Zeffii
7 # Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
8 # ----------------------------------------------------------
10 import bmesh
11 from mathutils import Vector
12 from mathutils.geometry import intersect_line_line, intersect_point_line
13 from .pdt_functions import debug
16 def point_on_edge(point, edge):
17 """Find Point on Edge.
19 Args:
20 point: vector
21 edge: tuple containing 2 vectors.
23 Returns:
24 True if point happens to lie on the edge, False otherwise.
25 """
27 intersect_point, _percent = intersect_point_line(point, *edge)
28 on_line = (intersect_point - point).length < 1.0e-5
29 return on_line and (0.0 <= _percent <= 1.0)
32 def line_from_edge_intersect(edge1, edge2):
33 """Get New Line from Intersections.
35 Note:
36 Prepares input for sending to intersect_line_line
38 Args:
39 edge1, edge2: tuples containing 2 vectors.
41 Returns:
42 Output of intersect_line_line.
43 """
45 [intersect_point1, intersect_point2], [intersect_point3, intersect_point4] = edge1, edge2
46 return intersect_line_line(
47 intersect_point1, intersect_point2, intersect_point3, intersect_point4
51 def get_intersection(edge1, edge2):
52 """Get Intersections of 2 Edges.
54 Args:
55 edge1, edge2: tuples containing 2 vectors.
57 Returns:
58 The point halfway on line. See intersect_line_line.
59 """
61 line = line_from_edge_intersect(edge1, edge2)
62 if line:
63 return (line[0] + line[1]) / 2
64 return None
67 def test_coplanar(edge1, edge2):
68 """Test 2 Edges are Co-planar.
70 Note:
71 The line that describes the shortest line between the two edges would be short if the
72 lines intersect mathematically. If this line is longer than 1.0e-5 then they are either
73 coplanar or parallel
75 Args:
76 edge1, edge2: tuples containing 2 vectors.
78 Returns:
79 True if edge1 and edge2 or coplanar, False otherwise.
80 """
82 line = line_from_edge_intersect(edge1, edge2)
83 if line:
84 return (line[0] - line[1]).length < 1.0e-5
85 return None
88 def closest_idx(intersect_point, edge):
89 """Get Closest Vertex to input point.
91 Note:
92 If both points in edge are equally far from intersect_point, then v1 is returned.
94 Args:
95 intersect_point: vector
96 edge: bmesh edge
98 Returns:
99 Index of vertex closest to intersect_point.
102 if isinstance(edge, bmesh.types.BMEdge):
103 edge_verts = edge.verts
104 vector_a = edge_verts[0].co
105 vector_b = edge_verts[1].co
106 distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
107 return edge_verts[0].index if distance_test else edge_verts[1].index
109 debug(f"Received {edge}, check expected input in docstring ")
110 return None
113 def closest_vector(intersect_point, edge):
114 """Return Closest Vector to input Point.
116 Note:
117 If both points in e are equally far from intersect_point, then v1 is returned.
119 Args:
120 intersect_point: vector
121 edge: tuple containing 2 vectors
123 Returns:
124 Vector closest to intersect_point.
127 if isinstance(edge, tuple) and all([isinstance(co, Vector) for co in edge]):
128 vector_a, vector_b = edge
129 distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
130 return vector_a if distance_test else vector_b
132 debug(f"Received {edge}, check expected input in docstring ")
133 return None
136 def coords_tuple_from_edge_idx(bm, idx):
137 """Return Tuple from Vertices.
139 Args:
140 bm: Object Bmesh
141 idx: Index of chosen Edge
143 Returns:
144 Tuple from Edge Vertices.
147 return tuple(v.co for v in bm.edges[idx].verts)
150 def vectors_from_indices(bm, raw_vert_indices):
151 """Return List of vectors from input Vertex Indices.
153 Args:
154 bm: Object Bmesh
155 raw_vert_indices: List of Chosen Vertex Indices
157 Returns:
158 List of Vertex coordinates.
161 return [bm.verts[i].co for i in raw_vert_indices]
164 def vertex_indices_from_edges_tuple(bm, edge_tuple):
165 """Return List of vertices.
167 Args:
168 bm: Active object's Bmesh
169 edge_tuple: contains 2 edge indices.
171 Returns:
172 The vertex indices of edge_tuple as an Integer list.
175 def find_verts(ind_v, ind_w):
176 return bm.edges[edge_tuple[ind_v]].verts[ind_w].index
178 return [find_verts(i >> 1, i % 2) for i in range(4)]
181 def get_vert_indices_from_bmedges(edges):
182 """Return List of Edges for evaluation.
184 Args:
185 edges: a list of 2 bm edges
187 Returns:
188 The vertex indices of edge_tuple as a flat list.
191 temp_edges = []
192 debug(edges)
193 for e in edges:
194 for v in e.verts:
195 temp_edges.append(v.index)
196 return temp_edges
199 def num_edges_point_lies_on(intersect_point, edges):
200 """Returns the number of edges that a point lies on.
202 Args:
203 intersection_point: Vector describing 3D coordinates of intersection point
204 edges: List of Bmesh edges
206 Returns:
207 Number of Intersecting Edges (Integer).
210 res = [point_on_edge(intersect_point, edge) for edge in [edges[:2], edges[2:]]]
211 return len([i for i in res if i])
214 def find_intersecting_edges(bm, intersect_point, idx1, idx2):
215 """Find Intercecting Edges.
217 Args:
218 intersect_point: Vector describing 3D coordinates of intersection point
219 idx1, idx2: edge indices
221 Returns:
222 The list of edge indices where intersect_point is on those edges.
225 if not intersect_point:
226 return []
227 idxs = [idx1, idx2]
228 edges = [coords_tuple_from_edge_idx(bm, idx) for idx in idxs]
229 return [idx for edge, idx in zip(edges, idxs) if point_on_edge(intersect_point, edge)]
232 def vert_idxs_from_edge_idx(bm, idx):
233 """Find Vertex Indices form Edge Indices.
235 Args:
236 bm: Object's Bmesh
237 idx: Selection Index
239 Returns:
240 Vertex Indices of Edge.
243 edge = bm.edges[idx]
244 return edge.verts[0].index, edge.verts[1].index