I've been working on this somehwat contrived example just to try to work it out and I'd appreciate some guidance. I assume an arbitrary line in 3D with an LCS attached to its endpoint (LastParameter). I'd like to rotate the LCS such that the z-axis is along the extension of the line. Secondarily, I'd then like to rotate the x-axis to lie in a plane parallel to the global xy-plane (not considered in example).
The angles below correspond to the projection of the line onto one of the xz, yz, or a plane along line perpendicular to the xy plane. Ideally, these are extrinsic Euler angles, but apparently not. Alternatively, the problem is that I'm rotating in the local coordinate system and don't know how to do the rotations relative to the global coordinate system. I'm also not clear on what order I would need (if there is one for these angles).
In any case, I'd appreciate any suggestions that can let me get back on track. Also, does FreeCAD have a more straightforward way to achieve what I'm trying to do or is it necessary to do it "by hand" as my code is attempting.
Thanks,
--Don
Code: Select all
def rotate_lcs_to_line(line):
"""Align LCS such that z-axis is along line, positive from start to end."""
line_start = line.Shape.Edges[0].Vertexes[0]
line_end =line.Shape.Edges[0].Vertexes[1]
lcs = FreeCAD.ActiveDocument.addObject('PartDesign::CoordinateSystem', "pos2_lcs")
lcs.Placement = line.Shape.Placement
lcs.Support = [(line, 'Vertex2')]
lcs.MapMode = 'Translate'
del_x = line_end.X - line_start.X
del_y = line_end.Y - line_start.Y
del_z = line_end.Z - line_start.Z
x_angle = np.arccos(del_z / np.sqrt(del_y ** 2 + del_z ** 2))
y_angle = np.arccos(del_z / np.sqrt(del_x ** 2 + del_z ** 2))
z_angle = np.pi /2 - np.arcsin(del_z / np.sqrt(del_x **2 + del_y **2 + del_z **2))
# Rotations are not independent, thus any combo fails
lcs.Placement.Matrix.rotateY(y_angle)
lcs.Placement.Matrix.rotateX(x_angle)
lcs.Placement.Matrix.rotateZ(z_angle)
return
start = FreeCAD.Vector(15, 40, 50)
end = FreeCAD.Vector(35, 60, 80)
ls = Part.makeLine(start, end)
s = FreeCAD.ActiveDocument.addObject("Part::Feature", "Line")
s.Shape = ls
rotate_lcs_to_line(s)
Code: Select all
OS: Ubuntu 22.04.1 LTS (ubuntu:GNOME/ubuntu)
Word size of FreeCAD: 64-bit
Version: 0.21.
Build type: Release
Branch: unknown
Hash: 1faf86c3da12c1712e1d5ec015721d9aa02f8672
Python 3.10.4, Qt 5.15.3, Coin 4.0.0, Vtk 9.1.0, OCC 7.5.1
Locale: English/United States (en_US)
Installed mods:
* Curves 0.5.2
* Assembly4 0.12.3
* Manipulator 1.4.9
* fasteners 0.3.50