Teacup_Firmware/research/planes.py

109 lines
2.7 KiB
Python

#!/usr/bin/env python
# Experiments with coefficients of a geometric plane
# Resources:
# http://www.wolframalpha.com/input/?i=plane+through+(1,-2,0),(4,-2,-2),(4,1,4)&lk=3
# ==> 2 x - 6 y + 3 z + 14 == 0
# Translate a point relative to some origin
from __future__ import print_function
def translate(point, origin):
return tuple([a-b for a,b in zip(point, origin)])
# Given two points in 3d space, define a vector
def vector(p1, p2):
return tuple([b-a for a,b in zip(p1,p2)])
# Given two vectors in a plane, find the normal vector
def normal(u, v):
# A normal vector is the cross-product of two coplanar vectors
return tuple([
u[1]*v[2] - u[2]*v[1],
u[2]*v[0] - u[0]*v[2],
u[0]*v[1] - u[1]*v[0]
])
def plane_from_three_points(P, Q, R):
u = vector(P, Q)
v = vector(P, R)
n = normal(u, v)
# Find the coefficients
(A,B,C) = n
# The equation of the plane is thus Ax+By+Cz+K=0.
# Solve for K to get the final coefficient
(x,y,z) = P
K = -(A*x + B*y + C*z)
return (A, B, C, K)
# find the Z offset for any x,y
# z = -(Ax + By + K) / C
def calcz(x, y, plane, translation=(0,0,0)):
(A,B,C,K) = plane
(tx, ty, tz) = translation
return -(A*(x-tx) + B*(y-ty) + K) / C + tz
# Verify a point is on this plane
def validate(plane, point):
(A, B, C, K) = plane
(x, y, z) = point
return z == calcz(x, y, plane)
def verify_plane(points):
print(' ', '\n '.join([str(p) for p in points]))
plane = plane_from_three_points( *points)
print('Plane coordinates: ', plane)
if plane[2] == 0:
print(' Error: points are colinear')
return
valid = True
for p in points:
if not validate(plane, p):
print("Failed: sample point not on plane, ", p)
valid = False
print("Validation:", "Failed" if not valid else "Passed")
samples = [
# canonical example
[ (1,-2,0), (4,-2,-2), (4,1,4) ],
# three colinear points (infinite planes)
[ (2,2,2), (4,4,4), (10,10,10) ],
# Extreme tilt example in mm
[ (57,123,-5), (200,0,35), (0,207,2) ],
# Some more examples in um
[ (0, 0, 1300), (200000, 200000, 3500), (0, 150000, -1000) ],
[ (20000, 20000, -300), (220000, 120000, -1700), (120000, 220000, -700) ],
# some example in tenths of mm
[ (200, 200, -300), (2200, 1200, -1700), (1200, 2200, -700) ],
[ (20000, 20000 , -300 ), (220000, 120000 , -1700 ), (120000, 220000 , -700 ) ],
[ (200, 200, -300 ), (2200, 1200, -1700 ), (1200, 2200, -700 ) ]
]
for points in samples:
verify_plane(points)
print("====[Translated]=========")
# Translate plane to origin at P (simplifies by removing K coefficient)
# A*x' + B*y' + C*z' = 0
P = points[0]
T = translate((0,0,0), P)
xpoints = [translate(p, P) for p in points]
verify_plane(xpoints)
print("=========================\n")