mirror of
https://github.com/blender/blender-addons.git
synced 2025-07-25 16:05:20 +00:00
244 lines
6.1 KiB
Python
244 lines
6.1 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#
|
|
# ----------------------------------------------------------
|
|
# Author: Zeffii
|
|
# Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
|
|
# ----------------------------------------------------------
|
|
#
|
|
import bmesh
|
|
from mathutils import Vector
|
|
from mathutils.geometry import intersect_line_line, intersect_point_line
|
|
from .pdt_functions import debug
|
|
|
|
|
|
def point_on_edge(point, edge):
|
|
"""Find Point on Edge.
|
|
|
|
Args:
|
|
point: vector
|
|
edge: tuple containing 2 vectors.
|
|
|
|
Returns:
|
|
True if point happens to lie on the edge, False otherwise.
|
|
"""
|
|
|
|
intersect_point, _percent = intersect_point_line(point, *edge)
|
|
on_line = (intersect_point - point).length < 1.0e-5
|
|
return on_line and (0.0 <= _percent <= 1.0)
|
|
|
|
|
|
def line_from_edge_intersect(edge1, edge2):
|
|
"""Get New Line from Intersections.
|
|
|
|
Note:
|
|
Prepares input for sending to intersect_line_line
|
|
|
|
Args:
|
|
edge1, edge2: tuples containing 2 vectors.
|
|
|
|
Returns:
|
|
Output of intersect_line_line.
|
|
"""
|
|
|
|
[intersect_point1, intersect_point2], [intersect_point3, intersect_point4] = edge1, edge2
|
|
return intersect_line_line(
|
|
intersect_point1, intersect_point2, intersect_point3, intersect_point4
|
|
)
|
|
|
|
|
|
def get_intersection(edge1, edge2):
|
|
"""Get Intersections of 2 Edges.
|
|
|
|
Args:
|
|
edge1, edge2: tuples containing 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
|
|
return None
|
|
|
|
|
|
def test_coplanar(edge1, edge2):
|
|
"""Test 2 Edges are Co-planar.
|
|
|
|
Note:
|
|
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 1.0e-5 then they are either
|
|
coplanar or parallel
|
|
|
|
Args:
|
|
edge1, edge2: tuples containing 2 vectors.
|
|
|
|
Returns:
|
|
True if edge1 and edge2 or coplanar, False otherwise.
|
|
"""
|
|
|
|
line = line_from_edge_intersect(edge1, edge2)
|
|
if line:
|
|
return (line[0] - line[1]).length < 1.0e-5
|
|
return None
|
|
|
|
|
|
def closest_idx(intersect_point, edge):
|
|
"""Get Closest Vertex to input point.
|
|
|
|
Note:
|
|
If both points in edge are equally far from intersect_point, then v1 is returned.
|
|
|
|
Args:
|
|
intersect_point: vector
|
|
edge: bmesh edge
|
|
|
|
Returns:
|
|
Index of vertex closest to intersect_point.
|
|
"""
|
|
|
|
if isinstance(edge, bmesh.types.BMEdge):
|
|
edge_verts = edge.verts
|
|
vector_a = edge_verts[0].co
|
|
vector_b = edge_verts[1].co
|
|
distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
|
|
return edge_verts[0].index if distance_test else edge_verts[1].index
|
|
|
|
debug(f"Received {edge}, check expected input in docstring ")
|
|
return None
|
|
|
|
|
|
def closest_vector(intersect_point, edge):
|
|
"""Return Closest Vector to input Point.
|
|
|
|
Note:
|
|
If both points in e are equally far from intersect_point, then v1 is returned.
|
|
|
|
Args:
|
|
intersect_point: vector
|
|
edge: tuple containing 2 vectors
|
|
|
|
Returns:
|
|
Vector closest to intersect_point.
|
|
"""
|
|
|
|
if isinstance(edge, tuple) and all([isinstance(co, Vector) for co in edge]):
|
|
vector_a, vector_b = edge
|
|
distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length
|
|
return vector_a if distance_test else vector_b
|
|
|
|
debug(f"Received {edge}, check expected input in docstring ")
|
|
return None
|
|
|
|
|
|
def coords_tuple_from_edge_idx(bm, idx):
|
|
"""Return Tuple from Vertices.
|
|
|
|
Args:
|
|
bm: Object Bmesh
|
|
idx: Index of chosen Edge
|
|
|
|
Returns:
|
|
Tuple from Edge Vertices.
|
|
"""
|
|
|
|
return tuple(v.co for v in bm.edges[idx].verts)
|
|
|
|
|
|
def vectors_from_indices(bm, raw_vert_indices):
|
|
"""Return List of vectors from input Vertex Indices.
|
|
|
|
Args:
|
|
bm: Object Bmesh
|
|
raw_vert_indices: List of Chosen Vertex Indices
|
|
|
|
Returns:
|
|
List of Vertex coordinates.
|
|
"""
|
|
|
|
return [bm.verts[i].co for i in raw_vert_indices]
|
|
|
|
|
|
def vertex_indices_from_edges_tuple(bm, edge_tuple):
|
|
"""Return List of vertices.
|
|
|
|
Args:
|
|
bm: Active object's Bmesh
|
|
edge_tuple: contains 2 edge indices.
|
|
|
|
Returns:
|
|
The vertex indices of edge_tuple as an Integer list.
|
|
"""
|
|
|
|
def find_verts(ind_v, ind_w):
|
|
return bm.edges[edge_tuple[ind_v]].verts[ind_w].index
|
|
|
|
return [find_verts(i >> 1, i % 2) for i in range(4)]
|
|
|
|
|
|
def get_vert_indices_from_bmedges(edges):
|
|
"""Return List of Edges for evaluation.
|
|
|
|
Args:
|
|
edges: a list of 2 bm edges
|
|
|
|
Returns:
|
|
The vertex indices of edge_tuple as a flat list.
|
|
"""
|
|
|
|
temp_edges = []
|
|
debug(edges)
|
|
for e in edges:
|
|
for v in e.verts:
|
|
temp_edges.append(v.index)
|
|
return temp_edges
|
|
|
|
|
|
def num_edges_point_lies_on(intersect_point, edges):
|
|
"""Returns the number of edges that a point lies on.
|
|
|
|
Args:
|
|
intersection_point: Vector describing 3D coordinates of intersection point
|
|
edges: List of Bmesh edges
|
|
|
|
Returns:
|
|
Number of Intersecting Edges (Integer).
|
|
"""
|
|
|
|
res = [point_on_edge(intersect_point, edge) for edge in [edges[:2], edges[2:]]]
|
|
return len([i for i in res if i])
|
|
|
|
|
|
def find_intersecting_edges(bm, intersect_point, idx1, idx2):
|
|
"""Find Intercecting Edges.
|
|
|
|
Args:
|
|
intersect_point: Vector describing 3D coordinates of intersection point
|
|
idx1, idx2: edge indices
|
|
|
|
Returns:
|
|
The list of edge indices where intersect_point is on those edges.
|
|
"""
|
|
|
|
if not intersect_point:
|
|
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(intersect_point, edge)]
|
|
|
|
|
|
def vert_idxs_from_edge_idx(bm, idx):
|
|
"""Find Vertex Indices form Edge Indices.
|
|
|
|
Args:
|
|
bm: Object's Bmesh
|
|
idx: Selection Index
|
|
|
|
Returns:
|
|
Vertex Indices of Edge.
|
|
"""
|
|
|
|
edge = bm.edges[idx]
|
|
return edge.verts[0].index, edge.verts[1].index
|