forked from bartvdbraak/blender
143 lines
3.1 KiB
Python
143 lines
3.1 KiB
Python
"""Vector tools
|
|
|
|
Various vector tools, basing on vect.py"""
|
|
|
|
from vect import *
|
|
|
|
EPSILON = 0.0001
|
|
|
|
def vecarea(v, w):
|
|
"Computes area of the span of vector 'v' and 'w' in 2D (not regarding z coordinate)"
|
|
return v[0]*w[1] - v[1]*w[0]
|
|
|
|
def intersect(a1, b1, a2, b2):
|
|
"""Computes 2D intersection of edges ('a1' -> 'b1') and ('a2' -> 'b2'),
|
|
returning normalized intersection parameter 's' of edge (a1 -> b1).
|
|
If 0.0 < 's' <= 1.0,
|
|
the two edges intersect at the point::
|
|
|
|
v = a1 + s * (b1 - a1)
|
|
"""
|
|
v = (b1[0] - a1[0], b1[1] - a1[1])
|
|
w = (b2[0] - a2[0], b2[1] - a2[1])
|
|
d0 = (a2[0] - a1[0])
|
|
d1 = (a2[1] - a1[1])
|
|
|
|
det = w[0]*v[1] - w[1]*v[0]
|
|
if det == 0: return 0.0
|
|
t = v[0]*d1 - v[1]*d0
|
|
s = w[0]*d1 - w[1]*d0
|
|
s /= det
|
|
t /= det
|
|
if s > 1.0 or s < 0.0: return 0.0
|
|
if t > 1.0 or t < 0.0: return 0.0
|
|
return s
|
|
|
|
def insidetri(a, b, c, x):
|
|
"Returns 1 if 'x' is inside the 2D triangle ('a' -> 'b' -> 'c'), 0 otherwise"
|
|
v1 = norm3(sub3(b, a))
|
|
v2 = norm3(sub3(c, a))
|
|
v3 = norm3(sub3(x, a))
|
|
|
|
a1 = (vecarea(v1, v2))
|
|
a2 = (vecarea(v1, v3))
|
|
lo = min(0.0, a1)
|
|
hi = max(0.0, a1)
|
|
|
|
if a2 < lo or a2 > hi: return 0
|
|
|
|
v2 = norm3(sub3(b, c))
|
|
v3 = norm3(sub3(b, x))
|
|
|
|
a1 = (vecarea(v1, v2))
|
|
a2 = (vecarea(v1, v3))
|
|
|
|
lo = min(0.0, a1)
|
|
hi = max(0.0, a1)
|
|
|
|
if a2 < lo or a2 > hi: return 0
|
|
|
|
return 1
|
|
|
|
def plane_fromface(v1, v2, v3):
|
|
"Returns plane (normal, point) from 3 vertices 'v1', 'v2', 'v3'"
|
|
v = sub3(v2, v1)
|
|
w = sub3(v3, v1)
|
|
n = norm3(cross(v, w))
|
|
return n, v1
|
|
|
|
def inside_halfspace(vec, plane):
|
|
"Returns 1 if point 'vec' inside halfspace defined by 'plane'"
|
|
n, t = plane
|
|
n = norm3(n)
|
|
v = sub3(vec, t)
|
|
if dot(n, v) < 0.0:
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
def half_space(vec, plane, tol = EPSILON):
|
|
"""Determine whether point 'vec' is inside (return value -1), outside (+1)
|
|
, or lying in the plane 'plane' (return 0) of a numerical thickness
|
|
'tol' = 'EPSILON' (default)."""
|
|
n, t = plane
|
|
v = sub3(vec, t)
|
|
fac = len3(n)
|
|
|
|
d = dot(n, v)
|
|
if d < -fac * tol:
|
|
return -1
|
|
elif d > fac * tol:
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
|
|
def plane_edge_intersect(plane, edge):
|
|
"""Returns normalized factor 's' of the intersection of 'edge' with 'plane'.
|
|
The point of intersection on the plane is::
|
|
|
|
p = edge[0] + s * (edge[1] - edge[0])
|
|
|
|
"""
|
|
n, t = plane # normal, translation
|
|
mat = matfromnormal(n)
|
|
mat = transmat(mat) # inverse
|
|
v = matxvec(mat, sub3(edge[0], t)) #transformed edge points
|
|
w = matxvec(mat, sub3(edge[1], t))
|
|
w = sub3(w, v)
|
|
if w[2] != 0.0:
|
|
s = -v[2] / w[2]
|
|
return s
|
|
else:
|
|
return None
|
|
|
|
def insidecube(v):
|
|
"Returns 1 if point 'v' inside normalized cube, 0 otherwise"
|
|
if v[0] > 1.0 or v[0] < 0.0:
|
|
return 0
|
|
if v[1] > 1.0 or v[1] < 0.0:
|
|
return 0
|
|
if v[2] > 1.0 or v[2] < 0.0:
|
|
return 0
|
|
return 1
|
|
|
|
|
|
def flatproject(verts, up):
|
|
"""Projects a 3D set (list of vertices) 'verts' into a 2D set according to
|
|
an 'up'-vector"""
|
|
z, t = plane_fromface(verts[0], verts[1], verts[2])
|
|
y = norm3(up)
|
|
x = cross(y, z)
|
|
uvs = []
|
|
for v in verts:
|
|
w = (v[0] - t[0], v[1] - t[1], v[2] - t[2])
|
|
# this is the transposed 2x2 matrix * the vertex vector
|
|
uv = (dot(x, w), dot(y,w)) # do projection
|
|
uvs.append(uv)
|
|
return uvs
|
|
|
|
|
|
|
|
|