mirror of
https://github.com/blender/blender-addons.git
synced 2025-07-23 00:48:26 +00:00

Move copyright text to SPDX-FileCopyrightText or set to the Blender Foundation so "make check_licenses" now runs without warnings.
157 lines
4.3 KiB
Python
157 lines
4.3 KiB
Python
# SPDX-FileCopyrightText: 2016-2022 Blender Foundation
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
import bmesh
|
|
|
|
from mathutils import Vector, geometry
|
|
from mathutils.geometry import intersect_line_line as LineIntersect
|
|
from mathutils.geometry import intersect_point_line as PtLineIntersect
|
|
|
|
|
|
class CAD_prefs:
|
|
VTX_PRECISION = 1.0e-5
|
|
VTX_DOUBLES_THRSHLD = 0.0001
|
|
|
|
|
|
def point_on_edge(p, edge):
|
|
'''
|
|
> p: vector
|
|
> edge: tuple of 2 vectors
|
|
< returns: True / False if a point happens to lie on an edge
|
|
'''
|
|
pt, _percent = PtLineIntersect(p, *edge)
|
|
on_line = (pt - p).length < CAD_prefs.VTX_PRECISION
|
|
return on_line and (0.0 <= _percent <= 1.0)
|
|
|
|
|
|
def line_from_edge_intersect(edge1, edge2):
|
|
'''
|
|
> takes 2 tuples, each tuple contains 2 vectors
|
|
- prepares input for sending to intersect_line_line
|
|
< returns output of intersect_line_line
|
|
'''
|
|
[p1, p2], [p3, p4] = edge1, edge2
|
|
return LineIntersect(p1, p2, p3, p4)
|
|
|
|
|
|
def get_intersection(edge1, edge2):
|
|
'''
|
|
> takes 2 tuples, each tuple contains 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):
|
|
'''
|
|
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 the VTX_PRECISION then they are either
|
|
coplanar or parallel.
|
|
'''
|
|
line = line_from_edge_intersect(edge1, edge2)
|
|
if line:
|
|
return (line[0] - line[1]).length < CAD_prefs.VTX_PRECISION
|
|
|
|
|
|
def closest_idx(pt, e):
|
|
'''
|
|
> pt: vector
|
|
> e: bmesh edge
|
|
< returns: returns index of vertex closest to pt.
|
|
|
|
if both points in e are equally far from pt, then v1 is returned.
|
|
'''
|
|
if isinstance(e, bmesh.types.BMEdge):
|
|
ev = e.verts
|
|
v1 = ev[0].co
|
|
v2 = ev[1].co
|
|
distance_test = (v1 - pt).length <= (v2 - pt).length
|
|
return ev[0].index if distance_test else ev[1].index
|
|
|
|
print("received {0}, check expected input in docstring ".format(e))
|
|
|
|
|
|
def closest_vector(pt, e):
|
|
'''
|
|
> pt: vector
|
|
> e: 2 vector tuple
|
|
< returns:
|
|
pt, 2 vector tuple: returns closest vector to pt
|
|
|
|
if both points in e are equally far from pt, then v1 is returned.
|
|
'''
|
|
if isinstance(e, tuple) and all([isinstance(co, Vector) for co in e]):
|
|
v1, v2 = e
|
|
distance_test = (v1 - pt).length <= (v2 - pt).length
|
|
return v1 if distance_test else v2
|
|
|
|
print("received {0}, check expected input in docstring ".format(e))
|
|
|
|
|
|
def coords_tuple_from_edge_idx(bm, idx):
|
|
''' bm is a bmesh representation '''
|
|
return tuple(v.co for v in bm.edges[idx].verts)
|
|
|
|
|
|
def vectors_from_indices(bm, raw_vert_indices):
|
|
''' bm is a bmesh representation '''
|
|
return [bm.verts[i].co for i in raw_vert_indices]
|
|
|
|
|
|
def vertex_indices_from_edges_tuple(bm, edge_tuple):
|
|
'''
|
|
> bm: is a bmesh representation
|
|
> edge_tuple: contains two edge indices.
|
|
< returns the vertex indices of edge_tuple
|
|
'''
|
|
def k(v, w):
|
|
return bm.edges[edge_tuple[v]].verts[w].index
|
|
|
|
return [k(i >> 1, i % 2) for i in range(4)]
|
|
|
|
|
|
def get_vert_indices_from_bmedges(edges):
|
|
'''
|
|
> bmedges: a list of two bm edges
|
|
< returns the vertex indices of edge_tuple as a flat list.
|
|
'''
|
|
temp_edges = []
|
|
print(edges)
|
|
for e in edges:
|
|
for v in e.verts:
|
|
temp_edges.append(v.index)
|
|
return temp_edges
|
|
|
|
|
|
def num_edges_point_lies_on(pt, edges):
|
|
''' returns the number of edges that a point lies on. '''
|
|
res = [point_on_edge(pt, edge) for edge in [edges[:2], edges[2:]]]
|
|
return len([i for i in res if i])
|
|
|
|
|
|
def find_intersecting_edges(bm, pt, idx1, idx2):
|
|
'''
|
|
> pt: Vector
|
|
> idx1, ix2: edge indices
|
|
< returns the list of edge indices where pt is on those edges
|
|
'''
|
|
if not pt:
|
|
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(pt, edge)]
|
|
|
|
|
|
def duplicates(indices):
|
|
return len(set(indices)) < 4
|
|
|
|
|
|
def vert_idxs_from_edge_idx(bm, idx):
|
|
edge = bm.edges[idx]
|
|
return edge.verts[0].index, edge.verts[1].index
|