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 option) 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 #####
24 from mathutils
import Vector
, geometry
25 from mathutils
.geometry
import intersect_line_line
as LineIntersect
26 from mathutils
.geometry
import intersect_point_line
as PtLineIntersect
30 VTX_PRECISION
= 1.0e-5
31 VTX_DOUBLES_THRSHLD
= 0.0001
34 def point_on_edge(p
, edge
):
37 > edge: tuple of 2 vectors
38 < returns: True / False if a point happens to lie on an edge
40 pt
, _percent
= PtLineIntersect(p
, *edge
)
41 on_line
= (pt
- p
).length
< CAD_prefs
.VTX_PRECISION
42 return on_line
and (0.0 <= _percent
<= 1.0)
45 def line_from_edge_intersect(edge1
, edge2
):
47 > takes 2 tuples, each tuple contains 2 vectors
48 - prepares input for sending to intersect_line_line
49 < returns output of intersect_line_line
51 [p1
, p2
], [p3
, p4
] = edge1
, edge2
52 return LineIntersect(p1
, p2
, p3
, p4
)
55 def get_intersection(edge1
, edge2
):
57 > takes 2 tuples, each tuple contains 2 vectors
58 < returns the point halfway on line. See intersect_line_line
60 line
= line_from_edge_intersect(edge1
, edge2
)
62 return (line
[0] + line
[1]) / 2
65 def test_coplanar(edge1
, edge2
):
67 the line that describes the shortest line between the two edges
68 would be short if the lines intersect mathematically. If this
69 line is longer than the VTX_PRECISION then they are either
72 line
= line_from_edge_intersect(edge1
, edge2
)
74 return (line
[0] - line
[1]).length
< CAD_prefs
.VTX_PRECISION
77 def closest_idx(pt
, e
):
81 < returns: returns index of vertex closest to pt.
83 if both points in e are equally far from pt, then v1 is returned.
85 if isinstance(e
, bmesh
.types
.BMEdge
):
89 distance_test
= (v1
- pt
).length
<= (v2
- pt
).length
90 return ev
[0].index
if distance_test
else ev
[1].index
92 print("received {0}, check expected input in docstring ".format(e
))
95 def closest_vector(pt
, e
):
100 pt, 2 vector tuple: returns closest vector to pt
102 if both points in e are equally far from pt, then v1 is returned.
104 if isinstance(e
, tuple) and all([isinstance(co
, Vector
) for co
in e
]):
106 distance_test
= (v1
- pt
).length
<= (v2
- pt
).length
107 return v1
if distance_test
else v2
109 print("received {0}, check expected input in docstring ".format(e
))
112 def coords_tuple_from_edge_idx(bm
, idx
):
113 ''' bm is a bmesh representation '''
114 return tuple(v
.co
for v
in bm
.edges
[idx
].verts
)
117 def vectors_from_indices(bm
, raw_vert_indices
):
118 ''' bm is a bmesh representation '''
119 return [bm
.verts
[i
].co
for i
in raw_vert_indices
]
122 def vertex_indices_from_edges_tuple(bm
, edge_tuple
):
124 > bm: is a bmesh representation
125 > edge_tuple: contains two edge indices.
126 < returns the vertex indices of edge_tuple
129 return bm
.edges
[edge_tuple
[v
]].verts
[w
].index
131 return [k(i
>> 1, i
% 2) for i
in range(4)]
134 def get_vert_indices_from_bmedges(edges
):
136 > bmedges: a list of two bm edges
137 < returns the vertex indices of edge_tuple as a flat list.
143 temp_edges
.append(v
.index
)
147 def num_edges_point_lies_on(pt
, edges
):
148 ''' returns the number of edges that a point lies on. '''
149 res
= [point_on_edge(pt
, edge
) for edge
in [edges
[:2], edges
[2:]]]
150 return len([i
for i
in res
if i
])
153 def find_intersecting_edges(bm
, pt
, idx1
, idx2
):
156 > idx1, ix2: edge indices
157 < returns the list of edge indices where pt is on those edges
162 edges
= [coords_tuple_from_edge_idx(bm
, idx
) for idx
in idxs
]
163 return [idx
for edge
, idx
in zip(edges
, idxs
) if point_on_edge(pt
, edge
)]
166 def duplicates(indices
):
167 return len(set(indices
)) < 4
170 def vert_idxs_from_edge_idx(bm
, idx
):
172 return edge
.verts
[0].index
, edge
.verts
[1].index