Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Useful functions to manage coordinates. Some things are for MODO, but others are absolutely common to any app
#python
# ----------------------------------------------------------------------------------------------------------------------
# NAME: etr_usefulCoordsFunctions.py
# VERS: Version 1.1
# DATE: October 29, 2014
#
# MADE: Cristobal Vila, etereaestudios.com
#
# USES: Useful functions to manage coordinates. Some things are for MODO, but others are absolutely common to any app
# ----------------------------------------------------------------------------------------------------------------------
# Query the Absolute World Position for a given vert
def fn_abs(vert):
return lx.evalN('query layerservice vert.wpos ? %s' % vert)
# Detect the sign of a number, returning -1 or +1
def fn_sign(number):
return cmp(number, 0)
# Convert Degrees to Radians
def fn_deg2rad(deg):
return deg/57.2957795131
# Convert Radians to Degrees
def fn_rad2deg(rad):
return rad*57.2957795131
# Substract two coordinates pos1-pos2 (useful to calculate Relative Position from 1 to 2)
def fn_subtract(pos1, pos2):
return [i-j for i, j in zip(pos1, pos2)]
# Add two coordinates pos1+pos2 (useful to revert 1 to Absolute Position from Relative in respect to 2)
def fn_add(pos1, pos2):
return [i+j for i, j in zip(pos1, pos2)]
# Multiply our position coordinates by a given value
def fn_multiply(value, pos):
return [i*value for i in pos]
# Calculate Distance for a Vector (or Point to origin) using Pythagoras Theorem
def fn_vectorDist(vect):
return math.sqrt(vect[0]**2 + vect[1]**2 + vect[2]**2)
# Calculate Distance between two points positions using Pythagoras Theorem
def fn_distance(pos1, pos2):
distX = pos1[0] - pos2[0]
distY = pos1[1] - pos2[1]
distZ = pos1[2] - pos2[2]
return math.sqrt(distX**2 + distY**2 + distZ**2)
# Calculate the Unit Vector between 2 points, using absolute coordinates
def fn_unitVect(pos1, pos2):
subt = fn_subtract(pos2, pos1)
dist = fn_distance(pos2, pos1)
return [i/dist for i in subt]
# Normalize a Vector
def fn_normalize(vect):
dist = math.sqrt(vect[0]**2 + vect[1]**2 + vect[2]**2)
return [i/dist for i in vect]
# Calculate the Normal Vector to a triangle formed by 3 verts, using absolute coordinates
# Big thanks to Luis Randez for helping to improve this one
def fn_normVect(pos1, pos2, pos3):
vA = fn_unitVect(pos1, pos2)
vB = fn_unitVect(pos2, pos3)
signo = cmp(vA[0]*vB[1] - vA[1]*vB[0], 0)
return fn_multiply(signo, [vA[1]*vB[2] - vA[2]*vB[1], vA[2]*vB[0] - vA[0]*vB[2], vA[0]*vB[1] - vA[1]*vB[0]])
# Average two vectors, and normalize result
def fn_average(vect1, vect2):
sumVects = fn_add(vect1, vect2)
return fn_normalize(sumVects)
# Calculate Dot Product (Scalar Product) between two vectors
def fn_dotProduct(vect1, vect2):
return sum(i*j for i, j in zip(vect1, vect2))
# Change position for a selected vert using new pos coordinates ('false true' is for Absolute Position)
def fn_vertSetPosition(vert, pos):
lx.eval('select.element %s vertex set %s' % (currentLayer, vert))
lx.eval('vert.set x %s false true' % pos[0])
lx.eval('vert.set y %s false true' % pos[1])
lx.eval('vert.set z %s false true' % pos[2])
# ----------------------------------------------------------------------------------------------------------------------
# Calculate position for a D point to form an planar Isosceles Trapezoid with 3 given ABC points
# Big thanks to my friend Albert Alomar for his great help with this
# ----------------------------------------------------------------------------------------------------------------------
def fn_isoTrapezoid_align(vertA, vertB, vertC, vertD):
absA = fn_abs(vertA)
absB = fn_abs(vertB)
absC = fn_abs(vertC)
vectorBA = fn_subtract(absA, absB)
vectorBC = fn_subtract(absC, absB)
lenBC = fn_vectorDist(vectorBC)
normVectBA = fn_normalize(vectorBA)
normVectBC = fn_normalize(vectorBC)
angleB = math.acos(fn_dotProduct(normVectBA, normVectBC))
modBCproy = lenBC * math.cos(angleB)
# We finally need to calculate: D = A + C - B - (2 * modBCproy * normVectBA)
# Lets do this in two steps
# 1. First we will calculate: M = 2 * modBCproy * normVectBA
M = [i*modBCproy*2 for i in normVectBA]
# 2. Now we can calculate: A + C - B - M
absD = [h+i-j-k for h, i, j, k in zip(absA, absC, absB, M)]
fn_vertSetPosition(vertD, absD)
# ----------------------------------------------------------------------------------------------------------------------
# Calculate position for a D point to be aligned with AC and at 1/3 distance from A
# ----------------------------------------------------------------------------------------------------------------------
def fn_triangle_align(vertA, vertC, vertD):
absA = fn_abs(vertA)
absC = fn_abs(vertC)
relCA = fn_subtract(absC, absA)
relCAmul = fn_multiply(0.333333333333, relCA)
absD = fn_add(relCAmul, absA)
fn_vertSetPosition(vertD, absD)
# ----------------------------------------------------------------------------------------------------------------------
# Calculate the Unit Vector Direction for each X, Y, Z axis on a Rotated Workplane
# Thanks to Dongju for this: http://community.thefoundry.co.uk/discussion/topic.aspx?f=119&t=93337
# ----------------------------------------------------------------------------------------------------------------------
def fn_wplaneAxis_toVect(axis):
# Determine X,Y,Z angles for your workplane
wpRX = lx.eval('workPlane.edit rotX:?')
wpRY = lx.eval('workPlane.edit rotY:?')
wpRZ = lx.eval('workPlane.edit rotZ:?')
# Store both Sin and Cos for each value
cx = math.cos(wpRX)
sx = math.sin(wpRX)
cy = math.cos(wpRY)
sy = math.sin(wpRY)
cz = math.cos(wpRZ)
sz = math.sin(wpRZ)
# Apply the magical rotation matrix
if axis == 'x':
return [-sy*sx*sz + cy*cz, sy*sx*cz + cy*sz, -sy*cx]
elif axis == 'y':
return [-cx*sz, cx*cz, sx]
elif axis == 'z':
return [cy*sx*sz + sy*cz, sy*sz - cy*sx*cz, cy*cx]
# ----------------------------------------------------------------------------------------------------------------------
# Rotate vert P a predefined angle around vert C, using a vector normal as axis direction
# Based on "Rotate a point about an arbitrary axis (3 dimensions)" by Paul Burke and Bruce Vaughan
# http://paulbourke.net/geometry/rotate/
# ----------------------------------------------------------------------------------------------------------------------
def fn_pointRotate3D(absP, absC, axis, angle):
# Calculate coordinates of P relatives to C
PR = fn_subtract(absP, absC)
# Factors for matrix operations
c = cos(angle)
t = (1-c)
s = sin(angle)
x = axis[0]
y = axis[1]
z = axis[2]
# Define matrix 'M'
D11 = t*x**2 + c
D12 = t*x*y - s*z
D13 = t*x*z + s*y
D21 = t*x*y + s*z
D22 = t*y**2 + c
D23 = t*y*z - s*x
D31 = t*x*z - s*y
D32 = t*y*z + s*x
D33 = t*z**2 + c
# |PR[0]|
# Calculate 'M'*|PR[1]|
# |PR[2]|
R0 = D11*PR[0] + D12*PR[1] + D13*PR[2]
R1 = D21*PR[0] + D22*PR[1] + D23*PR[2]
R2 = D31*PR[0] + D32*PR[1] + D33*PR[2]
# Determine the new relative coordinates for P --> R
R = [R0, R1, R2]
# Convert relative coords to absolute ones
return fn_add(R, absC)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.