It's great to see that the matrix works well for Freedman's needs. I concur with Ed that the matrix has its limitations and the Placement API is more suitable for complex rotations.
Regarding the sclerp code, it's certainly an interesting topic. However, it seems to have a quirk when crossing 180 degrees as it takes the shortest distance and rotates in the opposite direction.
I may have gotten carried away playing with/learning the Draft workbench in this code:
Code: Select all
import Part, time, Draft
# Set final rotation angle - CCW<180 CW>180
finAng = 180
# Set dim text size
txSize = 2
doc = App.ActiveDocument
fDoc= FreeCADGui.ActiveDocument
try:
if fDoc.Box:
doc.removeObject('Box')
doc.removeObject('Link')
doc.removeObject('Dimension')
doc.removeObject('Dimension001')
doc.removeObject('Dimension002')
except: pass
# Add box
box_obj = doc.addObject('Part::Box', 'Box')
box_obj.recompute()
# Color box - RGB
red, green, blue = (1.,0.,0.,0.), (0.,1.,0.,0.), (0.,0.,1.,0.)
box_obj.ViewObject.DiffuseColor = [red, (0.,0.,0.,1.),green ,(0.,0.,0.,1.),blue ,(0.,0.,0.,1.)]
#reposition Box, -5 is default Box center
box_pl_start = App.Placement(App.Vector(20,10.0,-25.0), App.Rotation())
box_obj.Placement = box_pl_start
box_pl_end = App.Placement(App.Vector(-20.0,-10.0,25.0), App.Rotation(App.Vector(0, 0, 1), finAng))
# Add XYZ dimensions
xDim = Draft.make_linear_dimension(App.Vector(0,0,0),App.Vector(0,0,0))
yDim = Draft.make_linear_dimension(App.Vector(0,0,0),App.Vector(0,0,0))
zDim = Draft.make_linear_dimension(App.Vector(0,0,0),App.Vector(0,0,0))
# set dim normals - best viewed from ISO
xDim.Normal, yDim.Normal, zDim.Normal = (0,0,1), (0,0,1), (1,0,0)
# Format dimensions
xD = fDoc.Dimension
yD = fDoc.Dimension001
zD = fDoc.Dimension002
dRed, dGreen, dBlue = (1.,0.,0.), (0.,1.,0.), (0.,0.,1.)
xD.ArrowType, xD.LineColor, xD.TextColor, xD.FontSize = u"Arrow", dRed, dRed, str(txSize)
yD.ArrowType, yD.LineColor, yD.TextColor, yD.FontSize = u"Arrow", dGreen, dGreen, str(txSize)
zD.ArrowType, zD.LineColor, zD.TextColor, zD.FontSize = u"Arrow", dBlue, dBlue, str(txSize)
#use Box placement to update dim lengths via expression
xDim.setExpression('.End.x', u'Box.Placement.Base.x')
yDim.setExpression('.End.y', u'Box.Placement.Base.y')
zDim.setExpression('.End.z', u'Box.Placement.Base.z')
def updateDims():
#Flip dimension text on +/- side of coord
xD.FlipText = doc.Box.Placement.Base.x < 0
yD.FlipText = doc.Box.Placement.Base.y < 0
zD.FlipText = doc.Box.Placement.Base.z < 0
#use Box placement to update dim line positions
yDim.Dimline = (doc.Box.Placement.Base.x,0,0)
zDim.Dimline = (doc.Box.Placement.Base.x, doc.Box.Placement.Base.y,0)
Gui.Selection.clearSelection()
link = doc.addObject('App::Link','Link')
link.setLink(doc.Box)
link.Label = 'FinalBox'
link.Placement = box_pl_end
nsteps = 100
secs = 5
for i in range(nsteps+1):
inc = i/nsteps
time.sleep(secs/nsteps)
box_obj.Placement = box_pl_start.sclerp(box_pl_end, inc)
updateDims()
App.Gui.updateGui()
doc.recompute()