Skip to content

Instantly share code, notes, and snippets.

@zeffii
Forked from anonymous/cad_module.py
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeffii/9913188 to your computer and use it in GitHub Desktop.
Save zeffii/9913188 to your computer and use it in GitHub Desktop.
import bpy
import bmesh
from mathutils import Vector, geometry
from geometry import intersect_line_line as LineIntersect
from geometry import intersect_point_line as PtLineIntersect
class CAD_prefs:
VTX_PRECISION = 1.0e-5
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)
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)
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
'''
k = lambda v, w: bm.edges[edge_tuple[v]].verts[w].index
return [k(i >> 1, i % 2) for i in range(4)]
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(pt, idx1, idx2):
'''
> pt: Vector
> idx1, ix2: edge indices,
< returns the list of edge indices where pt is on those edges
'''
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment