This script aligns a long bone to the world coordinate system based on 5 landmark points: an origin, proximal, distal, left and right point.
#This script aligns a long bone to the world coordinate system based on 5 landmark points: an origin, proximal, distal, left and right point. The distal-proximal direction defines the Z direction. The X direction is defined based on the right-left direction ( lateral-medial or medial-lateral, depending on whether it's the right or the left side).
#Input: bone_name: string with name of bone part
# orig_name: string with name of origin point
# pt_prox_name: string with name of proximal point
# pt_dist_name: string with name of distal point
# pt_right_name: string with name of right point
# pt_left_name: string with name of left point
# Output: repositioned long bone along with input landmarks and calculated landmarks (x axis,
# z axis, projected point, etc).
# Author: Julien Deckx (Materialise)
# Version: 1.0. (June 21 2018)
import trimatic
def AlignLongBone(bone_name, orig_name, pt_prox_name, pt_dist_name, pt_right_name, pt_left_name):
# find all entities
bone = trimatic.find_part(bone_name)
orig = trimatic.find_point(orig_name)
pt_prox = trimatic.find_point(pt_prox_name)
pt_dist = trimatic.find_point(pt_dist_name)
pt_left = trimatic.find_point(pt_left_name)
pt_right = trimatic.find_point(pt_right_name)
# the z direction is defined as distal to proximal
z_line = trimatic.create_line(pt_dist, pt_prox)
z_line.name = "z_line"
# create a plane perpendicular to z, with pt_right as origin
z_plane = trimatic.analyze.create_plane_normal_origin(origin=pt_right, normal=z_line.direction)
z_plane.name = "z_plane"
# extend z_plane and convert to part to allow projection of pt_left
lr_distance = trimatic.measure.create_distance_measurement(pt_left, pt_right)
z_plane.delta_x = lr_distance.value+1
z_plane.delta_y = lr_distance.value+1
z_plane_part = trimatic.convert_analytical_primitive_to_part(z_plane)
# project pt_left in z_plane (try both +z and -z direction)
plusZ_direction = z_line.direction
minZ_direction = tuple([-x for x in plusZ_direction])
try:
pt_left_proj = trimatic.project_point(direction = plusZ_direction, parts = z_plane_part, point_to_project = pt_left)
except:
pt_left_proj = trimatic.project_point(direction = minZ_direction, parts = z_plane_part, point_to_project = pt_left)
pt_left_proj = trimatic.create_point(pt_left_proj[0])
pt_left_proj.name = "pt_left_proj"
# the direction is defined as the projection of the line from right to left
x_line = trimatic.create_line(pt_right, pt_left_proj)
# create planes for plane-to-plane align
orig_x = trimatic.translate(entities = orig, translation_vector = x_line.direction, number_of_copies = 1)
orig_z = trimatic.translate(entities = orig, translation_vector = z_line.direction, number_of_copies = 1)
plane_moving = trimatic.create_plane_3_points(orig, orig_x, orig_z)
plane_fixed = trimatic.create_plane_3_points((0,0,0), (1,0,0), (0,0,1))
trimatic.delete(orig_x)
trimatic.delete(orig_z)
# plane-to-plane align
trimatic.plane_to_plane_align(plane_on_fixed_entity=plane_fixed,plane_on_moving_entity=plane_moving,move_along_entities=(bone, pt_prox, pt_dist, pt_left, pt_right, orig, z_line,z_plane,lr_distance, pt_left_proj, x_line),coincident=True)