├── Abroller.py ├── Animation.py ├── AnimationControlPanel.py ├── Assembly2Controller.py ├── Collision.py ├── Combiner.py ├── Diagram.py ├── EditWidget.py ├── Gearing.py ├── Init.py ├── InitGui.py ├── Kartan.py ├── Keyboard.py ├── LICENSE ├── Miki.py ├── Pather.py ├── Placer.py ├── README.md ├── Scaler.py ├── Snapshot.py ├── Speeder.py ├── Toucher.py ├── Tracker.py ├── Trackreader.py ├── VertexTracker.py ├── animationlib.py ├── animationwb ├── __init__.py └── compounds.py ├── animplacement.py ├── flowNode.py ├── flowlib.py ├── icons ├── abroller.png ├── adjuster.png ├── animation.png ├── assembly2SolveConstraints.png ├── assembly2SolveConstraints.svg ├── billboard.png ├── bounder.png ├── caseaction.png ├── collider.png ├── combiner.png ├── comp_add.png ├── comp_add.svg ├── comp_create.png ├── comp_create.svg ├── comp_delete.png ├── comp_delete.svg ├── connector.png ├── controlpanel.png ├── delta.png ├── diagram.png ├── extruder.png ├── falseaction.png ├── filler.png ├── followme.png ├── gearing.png ├── icon1.svg ├── icon2.svg ├── icon3.svg ├── kardan.png ├── loopaction.png ├── manager.png ├── mover.png ├── moviescreen.png ├── pather.png ├── photographer.png ├── placer.png ├── plugger.png ├── queryaction.png ├── repeataction.png ├── reset.png ├── rotator.png ├── scaler.png ├── scriptaction.png ├── snapshot.png ├── snapshotviewer.png ├── speeder.png ├── styler.png ├── sum.png ├── toucher.png ├── tracker.png ├── trackreader.png ├── tranq.png ├── trueaction.png ├── viewpoint.png └── whileaction.png ├── mathplotlibNode.py ├── numpyNode.py ├── say.py ├── testcases ├── TestAnim.py ├── numpy+mathplotlib.py ├── run_all_tests.py ├── test_diagram-py ├── test_diagram.py ├── test_flow1.py ├── test_flow2.py ├── test_flow3.py ├── test_keyboard.py ├── test_manager.py ├── test_manager2.py ├── test_pather.py ├── test_placer.py ├── test_scaler.py ├── test_snapshot.py ├── test_speeder.py ├── test_speeder2.py ├── test_tracker.py ├── test_trackreader.py └── test_vertextracker.py └── transform.py /Abroller.py: -------------------------------------------------------------------------------- 1 | import FreeCAD 2 | import FreeCADGui 3 | import PySide 4 | from PySide import QtGui 5 | import os 6 | 7 | App=FreeCAD 8 | Gui=FreeCAD.Gui 9 | 10 | 11 | import numpy as np 12 | import Draft 13 | import Part 14 | import time 15 | 16 | def updateData(obj,sk=None): 17 | 18 | if sk != None: obj.path=sk 19 | 20 | sk=obj.path 21 | sk.Placement.Rotation.Angle=0 22 | 23 | w=sk.Shape 24 | # assert (abs(w.Vertexes[0].Point.y) <10**-2) 25 | if obj.countPoints<5:obj.countPoints=5 26 | if obj.densityPoints<1:obj.densityPoints=1 27 | 28 | c=w.Edges[0].Curve 29 | 30 | anz=obj.countPoints 31 | pts=w.discretize(anz+1) 32 | # pts=[FreeCAD.Vector(p.y,p.x,p.z) for p in pts] 33 | 34 | obj.pathName=sk.Name+'_Path' 35 | 36 | cyy=App.ActiveDocument.getObject(obj.pathName) 37 | if cyy==None: 38 | cyy=App.ActiveDocument.addObject('Part::Feature',obj.pathName) 39 | 40 | 41 | ##pol=Part.makePolygon(w.discretize(anz+1)) 42 | pol=Part.makePolygon(pts) 43 | # obj.pola=w.discretize(200) 44 | cyy.Shape=pol 45 | 46 | 47 | ##obj.pola=w.discretize(anz+1) 48 | obj.pola=pts 49 | pol=Part.makePolygon(obj.pola) 50 | 51 | alphaq=[np.arctan2(p.y,p.x) for p in pts] 52 | ns=np.arange(anz+1) 53 | alpha=[] 54 | 55 | for a in alphaq[:-1]: 56 | if a <0: a += 2*np.pi 57 | alpha += [a] 58 | 59 | alpha += [2*np.pi] 60 | 61 | # jetzt die Animationsschritte 62 | anz2=10 63 | anz2=4 64 | 65 | rra=np.arange(2*anz2+1)*np.pi*2/(2*anz2+1) 66 | # pos=np.interp(rra, alpha, ns)/(anz) 67 | 68 | # if 0: 69 | # import scipy 70 | # from scipy.interpolate import interp1d 71 | # 72 | # fx = interp1d(alpha,ns,kind="cubic",bounds_error=False) 73 | # pos=fx(rra) 74 | # pos /=anz 75 | # 76 | # kk=[] 77 | # for p in pos: 78 | # kk += [c.value(p),FreeCAD.Vector()] 79 | 80 | 81 | of=App.ActiveDocument.getObject(sk.Name+"_Offset") 82 | if of==None: 83 | of=App.ActiveDocument.addObject("Part::Offset2D",sk.Name+"_Offset") 84 | of.Source = obj.path 85 | of.Value = obj.offsetValue 86 | obj.offset=of 87 | 88 | 89 | 90 | App.activeDocument().recompute() 91 | Gui.updateGui() 92 | w2=of.Shape.Wires[0] 93 | 94 | ptsa=[] 95 | for e in w2.Edges: 96 | #print "Wire ---",e 97 | dian=int(round(e.Length*obj.densityPoints)) 98 | print(dian) 99 | if dian<1: dian=1 100 | try: 101 | ptsa += e.discretize(dian+1)[:-1] 102 | except: 103 | print( "kann kante nicht discretize") 104 | 105 | ptsa.reverse() 106 | # print "ptsa" 107 | # for p in ptsa:print p 108 | 109 | alphaq=[np.arctan2(p.y,p.x) for p in ptsa] 110 | 111 | # print "alphaq" 112 | # for a in alphaq: print a 113 | 114 | alpha=[] 115 | 116 | for a in alphaq[:-1]: 117 | if a <0: a += 2*np.pi 118 | alpha += [a] 119 | 120 | alpha += [2*np.pi+alpha[0]] 121 | 122 | 123 | 124 | anz=len(alpha) 125 | ns=np.arange(len(alpha)) 126 | 127 | #if obj.useBSpline: 128 | bc=Part.BSplineCurve() 129 | bc.approximate(ptsa,DegMin=1,DegMax=obj.degreeBSpline,Tolerance=obj.approxTolerance) 130 | 131 | 132 | obj.polb=ptsa 133 | 134 | if 0: 135 | cww=App.ActiveDocument.getObject(obj.pathName+"_OFFSET") 136 | if cww== None: 137 | cww=App.ActiveDocument.addObject('Part::Feature',obj.pathName+'_OFFSET') 138 | 139 | 140 | pol=Part.makePolygon(ptsa) 141 | cww.Shape=pol 142 | if obj.useBSpline: 143 | cww.Shape=bc.toShape() 144 | 145 | App.ActiveDocument.ActiveObject.ViewObject.LineColor=(1.,0.,0.) 146 | App.ActiveDocument.ActiveObject.ViewObject.LineWidth=8 147 | 148 | Gui.updateGui() 149 | 150 | 151 | # jetzt die Animationsschritte 152 | anz2=50 153 | print("Interpolation anz, anz2",anz,anz2) 154 | 155 | rra=np.arange(2*anz2+1)*np.pi*2/(2*anz2+1) 156 | pos=np.interp(rra, alpha, ns)/(anz) 157 | 158 | #- 159 | 160 | # import scipy 161 | # from scipy.interpolate import interp1d 162 | 163 | # fx = interp1d(alpha,ns,kind="cubic",bounds_error=True) 164 | # #fx = interp1d(alpha[2:-2],ns[2:-2],kind="linear",bounds_error=False) 165 | # pos=fx(rra[2:-2]) 166 | # pos /=anz 167 | 168 | #-- 169 | 170 | kk=[] 171 | kka=[] 172 | 173 | # print "pos --" 174 | # for p in pos: 175 | # print p 176 | 177 | for p in pos: 178 | pp=bc.value(p) 179 | pp2=bc.value(p) 180 | pp2.normalize() 181 | 182 | kk += [pp,FreeCAD.Vector()] 183 | kka += [pp] 184 | 185 | 186 | Gui.updateGui() 187 | if obj.circle==None: 188 | obj.circle=Draft.makeCircle(obj.offsetValue) 189 | obj.circle.Label="dummy Scooter" 190 | if obj.circle2==None: 191 | obj.circle2=Draft.makeCircle(1) 192 | obj.circle2.Label="dummy Scooter center" 193 | 194 | obj.kka=[FreeCAD.Vector(p) for p in kka] 195 | obj.kka=ptsa 196 | # Draft.makeWire(kk) 197 | 198 | return pol 199 | 200 | 201 | def runAnimation(obj=None,loop=False): 202 | 203 | cww=App.ActiveDocument.getObject(obj.path.Name+"_Path") 204 | cyy=App.ActiveDocument.getObject(obj.pathName) 205 | 206 | if loop: ixs=obj.kka 207 | else: 208 | ixs=[obj.kka[obj.anim]] 209 | ixs=[obj.kka[obj.anim-1]] 210 | 211 | ll=len(obj.kka) 212 | posl=int(round(obj.anim*ll*0.01)) 213 | ixs=[obj.kka[posl]] 214 | 215 | # print "obj.kka", 216 | # for k in obj.kka: print k 217 | 218 | for i,p in enumerate(ixs): 219 | 220 | pp=Part.Point(FreeCAD.Vector(p)) 221 | # print ("run Anim",i,pp) 222 | 223 | if 0: 224 | w=App.ActiveDocument.Sketch.Shape 225 | dist=w.distToShape(pp.toShape()) 226 | print(dist[0]) 227 | 228 | 229 | testmode=True 230 | 231 | # obj.circle.Placement.Base=p 232 | # obj.circle.Radius=1 233 | 234 | # kkxx=App.ActiveDocument.Compound001 235 | kkxx=obj.scooter 236 | #print kkxx.Label 237 | if kkxx != None: 238 | kkxx.Placement.Base=FreeCAD.Vector(p.Length,0,0) 239 | 240 | 241 | alpha=np.arctan2(p.y,p.x)*180/np.pi 242 | 243 | try:pos=obj.path.Shape.Curve.parameter(p) 244 | except: pos=obj.path.Shape.Edge1.Curve.parameter(p) 245 | 246 | arc2=-pos/obj.offsetValue/np.pi/2*180 247 | 248 | #print ("rot",arc2,alpha) 249 | 250 | if obj.mode=='rotate camshaft': 251 | #print "circle ",alpha 252 | obj.circle.Placement=FreeCAD.Placement(FreeCAD.Vector(),FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-alpha)).multiply(FreeCAD.Placement(p,FreeCAD.Rotation(FreeCAD.Vector(0,0,1),arc2+alpha))) 253 | obj.circle2.Placement=obj.circle.Placement 254 | if kkxx != None: 255 | kkxx.Placement=obj.circle.Placement 256 | else: 257 | obj.circle.Placement=FreeCAD.Placement(p,FreeCAD.Rotation(FreeCAD.Vector(0,0,1),arc2+alpha)) 258 | obj.circle2.Placement=obj.circle.Placement 259 | if kkxx != None: 260 | kkxx.Placement=obj.circle.Placement 261 | 262 | 263 | 264 | if obj.mode=='rotate camshaft': 265 | cww.Shape=Part.makePolygon(obj.pola) 266 | cww.Placement.Rotation=FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-alpha) 267 | 268 | cyy.Shape=Part.makePolygon(obj.polb) 269 | cyy.Placement.Rotation=FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-alpha) 270 | 271 | # App.ActiveDocument.DWire.Placement.Rotation=FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-alpha) 272 | 273 | 274 | # kkyy=App.ActiveDocument.Compound 275 | kkyy=obj.camshaft 276 | # print kkyy.Label 277 | if kkyy != None: 278 | kkyy.Placement.Rotation=FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-alpha) 279 | 280 | # print cyy.Placement 281 | 282 | if loop: 283 | App.activeDocument().recompute() 284 | Gui.updateGui() 285 | time.sleep(0.1) 286 | if i>10: return 287 | 288 | 289 | def step(self,now): 290 | self.obj2.time=float(now) 291 | 292 | 293 | class Abroller: 294 | ''' basic defs''' 295 | 296 | def __init__(self, obj): 297 | obj.Proxy = self 298 | self.Object = obj 299 | 300 | def attach(self, vobj): 301 | self.Object = vobj.Object 302 | 303 | def __getstate__(self): 304 | return None 305 | 306 | def __setstate__(self, state): 307 | return None 308 | 309 | def execute(self,obj): 310 | pass 311 | 312 | # def attach(self,vobj): 313 | # self.Object = vobj.Object 314 | 315 | def onChanged(self,obj,prop): 316 | # print "prop ",prop 317 | if prop=='anim': 318 | runAnimation(obj) 319 | if prop in ['offsetValue','path','densityPoints','countPoints','degreeBSpline','useBSpline']: 320 | updateData(obj) 321 | if prop == "mode": 322 | obj.camshaft.Placement.Rotation=FreeCAD.Rotation() 323 | obj.offset.Placement.Rotation=FreeCAD.Rotation() 324 | 325 | def step(self,now): 326 | self.Object.anim=int(round(now)) 327 | 328 | def initialize(self): 329 | pass 330 | 331 | def onDocumentRestored(self, fp): 332 | self.Object=fp 333 | 334 | 335 | class ViewProvider: 336 | ''' basic defs ''' 337 | 338 | def __init__(self, obj): 339 | obj.Proxy = self 340 | self.Object = obj 341 | 342 | def __getstate__(self): 343 | return None 344 | 345 | def __setstate__(self, state): 346 | return None 347 | 348 | def getIcon(self): 349 | __dir__ = os.path.dirname(__file__) 350 | return __dir__+ '/icons/abroller.png' 351 | 352 | #------------------------------- 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | def createAbroller(): 361 | 362 | obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","MeinAbroller") 363 | obj.addProperty("App::PropertyLink", "circle", "_aux", "dummy scooter") 364 | obj.addProperty("App::PropertyLink", "circle2", "_aux", "center of scooter") 365 | 366 | obj.addProperty("App::PropertyLink", "scooter", "", "scooter") 367 | obj.addProperty("App::PropertyLink", "camshaft", "", "camshaft") 368 | 369 | obj.addProperty("App::PropertyLink", "offset", "_aux", "end") 370 | obj.addProperty("App::PropertyLink", "path", "Base", "closed single wire path for the scooter") 371 | obj.addProperty("App::PropertyInteger", "anim", "Base", "displayed frame number") 372 | obj.addProperty("App::PropertyInteger", "countPoints", "_aux", "number of points of the path to interpolate").countPoints=40 373 | obj.addProperty("App::PropertyInteger", "densityPoints", "_aux", "number of points of the generated curves per mm").densityPoints=4 374 | 375 | obj.addProperty("App::PropertyFloat", "offsetValue", "Base", "size of the scooter").offsetValue=10.5 376 | obj.addProperty("App::PropertyFloat", "approxTolerance", "_aux", "tolerance for BSpline Approximation").approxTolerance=1. 377 | obj.addProperty("App::PropertyInteger", "degreeBSpline", "_aux", "degree of the BSpline ").degreeBSpline=3 378 | 379 | obj.addProperty("App::PropertyBool", "useBSpline", "_aux", "use BSpline Approx for offset curve").useBSpline=True 380 | 381 | # helper data 382 | obj.addProperty("App::PropertyVectorList", "kka", "_comp", "end") 383 | obj.addProperty("App::PropertyVectorList", "pola", "_comp", "end") 384 | obj.addProperty("App::PropertyVectorList", "polb", "_comp", "end") 385 | obj.addProperty("App::PropertyString", "pathName", "_aux", "label for the path") 386 | 387 | obj.addProperty("App::PropertyEnumeration","mode","","Animation mode").mode=['rotate camshaft','roll scooter'] 388 | 389 | print("create abroller") 390 | 391 | try: sk=Gui.Selection.getSelection()[0] 392 | except: sk= None 393 | try: m=Gui.Selection.getSelection()[1] 394 | except: m=None 395 | try: m2=Gui.Selection.getSelection()[2] 396 | except: m2=None 397 | 398 | shape=updateData(obj,sk) 399 | Abroller(obj) 400 | # obj.Proxy.Shape=shape 401 | obj.Shape=Part.Shape() 402 | 403 | 404 | ViewProvider(obj.ViewObject) 405 | obj.scooter=m 406 | obj.camshaft=m2 407 | # obj.scooter=App.ActiveDocument.Compound001 408 | # obj.camshaft=App.ActiveDocument.Compound 409 | #if m != None: 410 | # obj.setExpression('anim', m.Name+'.step') 411 | 412 | # runAnimation(obj,True) 413 | for prop in ["approxTolerance","degreeBSpline","densityPoints","useBSpline"]: 414 | obj.setEditorMode(prop, 2) 415 | 416 | 417 | 418 | ''' 419 | fuer das motor projekt 420 | # drehen 421 | dann spline 422 | 423 | obj=App.ActiveDocument.Part__Feature086 424 | 425 | 426 | 427 | import Draft 428 | obj=App.ActiveDocument.Wire 429 | 430 | pts=obj.Shape.discretize(40) 431 | pts=[FreeCAD.Vector(p.y,p.x,p.z) for p in pts] 432 | Draft.makeBSpline(pts) 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | ''' 441 | -------------------------------------------------------------------------------- /AnimationControlPanel.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- Animation workbench 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | import math,os, time 11 | 12 | import FreeCAD, FreeCADGui, Animation, PySide 13 | from Animation import say,sayErr,sayexc 14 | from EditWidget import EditWidget 15 | from PySide import QtCore, QtGui 16 | 17 | 18 | __vers__= '0.1' 19 | __dir__ = os.path.dirname(__file__) 20 | 21 | 22 | Gui=FreeCADGui 23 | App=FreeCAD 24 | 25 | 26 | def createAnimationControlPanel(name='My_AnimationControlPanel',line1=[],line2=[],line3=[]): 27 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 28 | 29 | obj.addProperty("App::PropertyStringList","line1","Lines","").line1=line1 30 | obj.addProperty("App::PropertyStringList","line2","Lines","").line2=line2 31 | obj.addProperty("App::PropertyStringList","line3","Lines","").line3=line3 32 | 33 | # hide info 34 | #obj.setEditorMode("expressiontrafo", 2) 35 | _AnimationControlPanel(obj) 36 | _ViewProviderAnimationControlPanel(obj.ViewObject) 37 | return obj 38 | 39 | class _AnimationControlPanel(Animation._Actor): 40 | 41 | def update(self): 42 | pass 43 | 44 | def step(self,now): 45 | pass 46 | 47 | 48 | def controlPanelWidget(obj): 49 | 50 | w=QtGui.QWidget() 51 | w.setStyleSheet("QWidget { background-color: lightblue}\ 52 | QDial { background-color: white}\ 53 | QLabel { color: ;}\ 54 | QPushButton { margin-right:0px;margin-left:0px;margin:0 px;padding:0px;;\ 55 | background-color: lightblue;text-align:left;;padding:6px;padding-left:4px;color:brown; }") 56 | 57 | w.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) 58 | 59 | label=QtGui.QLabel("
*** Animation Control Panel ***
") 60 | layout = QtGui.QVBoxLayout() 61 | layout.addWidget(label) 62 | 63 | Wid= QtGui.QWidget() 64 | l2 = QtGui.QGridLayout() 65 | layout.addLayout(l2) 66 | 67 | lc=1 68 | rc=1 69 | for r in obj.line1: 70 | t= Gui.activeDocument().getObject(r) 71 | dd=t.Proxy.dialog(True) 72 | # dd.setStyleSheet("QLabel { color: #0000ff;}") 73 | l2.addWidget(dd,lc,rc) 74 | rc += 1 75 | lc=2 76 | rc=1 77 | for r in obj.line2: 78 | t= Gui.activeDocument().getObject(r) 79 | dd=t.Proxy.dialog(True) 80 | l2.addWidget(dd,lc,rc) 81 | rc += 1 82 | lc=3 83 | rc=1 84 | for r in obj.line3: 85 | t= Gui.activeDocument().getObject(r) 86 | dd=t.Proxy.dialog(True) 87 | l2.addWidget(dd,lc,rc) 88 | rc += 1 89 | 90 | pushButton02 = QtGui.QPushButton("close") 91 | pushButton02.clicked.connect(w.hide) 92 | layout.addWidget(pushButton02) 93 | w.setLayout(layout) 94 | return w 95 | 96 | class _ViewProviderAnimationControlPanel(Animation._ViewProviderActor): 97 | 98 | def attach(self,vobj): 99 | say("VO attach " + str(vobj.Object.Label)) 100 | vobj.Proxy = self 101 | self.Object = vobj.Object 102 | self.obj2=self.Object 103 | self.Object.Proxy.Lock=False 104 | self.Object.Proxy.Changed=False 105 | icon='/icons/controlpanel.png' 106 | self.iconpath = __dir__ + icon 107 | self.vers=__vers__ 108 | return 109 | 110 | def setupContextMenu(self, obj, menu): 111 | cl=self.Object.Proxy.__class__.__name__ 112 | action = menu.addAction("About " + cl) 113 | action.triggered.connect(self.showVersion) 114 | action = menu.addAction("Edit ...") 115 | action.triggered.connect(self.edit) 116 | 117 | def edit(self): 118 | say(self) 119 | self.dialog=controlPanelWidget(self.Object) 120 | self.dialog.show() 121 | 122 | -------------------------------------------------------------------------------- /Assembly2Controller.py: -------------------------------------------------------------------------------- 1 | import FreeCAD 2 | import Animation 3 | from Animation import say,sayErr,sayexc 4 | 5 | 6 | import os 7 | 8 | __vers__= '0.1' 9 | __dir__ = os.path.dirname(__file__) 10 | 11 | 12 | 13 | #--------------------------------------------------------------- 14 | # Assembly2 15 | #--------------------------------------------------------------- 16 | 17 | class _Assembly2Controller(Animation._Actor): 18 | ''' solve assemby2 constraints ''' 19 | 20 | def update(self): 21 | pass 22 | 23 | def step(self,now): 24 | try: 25 | # https://github.com/hamish2014/FreeCAD_assembly2/issues/73 26 | import assembly2lib 27 | assembly2lib.debugPrint.level = 0 #the default is 2 28 | assembly2lib.debugPrint.level = self.obj2.debugLevel 29 | import assembly2solver 30 | try: 31 | constraintSystem = assembly2solver.solveConstraints( 32 | FreeCAD.ActiveDocument, showFailureErrorDialog=False, 33 | printErrors=self.obj2.printErrors) 34 | if constraintSystem == None: 35 | sayErr('Solver failed to satisfy specified constraints') 36 | else: 37 | say("Solver step done " + str(now)) 38 | except: 39 | sayErr("problem assembly2solver.solveConstraints(App.ActiveDocument)") 40 | except: 41 | sayErr("problem no assembly2 available") 42 | pass 43 | 44 | class _ViewProviderAssembly2Controller(Animation._ViewProviderActor): 45 | 46 | def getIcon(self): 47 | return __dir__ + '/icons/assembly2SolveConstraints.svg' 48 | 49 | def createAssembly2Controller(name='Assembly2'): 50 | ''' createToucher(name,target,targets=None) returns an animation node for one target or a list of targets 51 | target: single object, targets: list of objects 52 | ''' 53 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 54 | obj.addProperty("App::PropertyFloat","time","Base","").time=0 55 | obj.addProperty("App::PropertyInteger","debugLevel","Assemby2","").debugLevel=0 56 | obj.addProperty("App::PropertyBool","printErrors","Assemby2","").printErrors=False 57 | 58 | _Assembly2Controller(obj) 59 | _ViewProviderAssembly2Controller(obj.ViewObject) 60 | return obj 61 | 62 | 63 | if False: 64 | s=createAssembly2Controller() 65 | s.Proxy.step(6) 66 | 67 | -------------------------------------------------------------------------------- /Collision.py: -------------------------------------------------------------------------------- 1 | import FreeCAD 2 | 3 | from say import * 4 | 5 | __dir__ = os.path.dirname(__file__) 6 | 7 | #----------------------------------------- 8 | 9 | #-------------------------------------------- 10 | 11 | def col(actor,obstacles): 12 | 13 | av=actor.Shape.BoundBox 14 | for obl in obstacles: 15 | ov=obl.Shape.BoundBox 16 | if ov.XMin < av.XMax and ov.XMax > av.XMin and ov.YMin <= av.YMax and ov.YMax >= av.YMin and ov.ZMin <= av.ZMax and ov.ZMax >= av.ZMin: 17 | print(obl.Label) 18 | obl.ViewObject.DiffuseColor=(1.0,0.0,0.0) 19 | else: 20 | obl.ViewObject.DiffuseColor=(1.0,1.0,0.0) 21 | 22 | #-------------------------------------------- 23 | 24 | 25 | import Part 26 | 27 | 28 | def say(a): 29 | FreeCAD.Console.PrintMessage(a) 30 | 31 | import FreeCAD,os,FreeCADGui,time,sys,traceback 32 | def sayexc(mess=''): 33 | exc_type, exc_value, exc_traceback = sys.exc_info() 34 | ttt=repr(traceback.format_exception(exc_type, exc_value,exc_traceback)) 35 | lls=eval(ttt) 36 | l=len(lls) 37 | l2=lls[(l-3):] 38 | FreeCAD.Console.PrintError(mess + "\n" +"--> ".join(l2)) 39 | 40 | class _ViewProvider(object): 41 | 42 | def getIcon(self): 43 | 44 | return __dir__ + '/icons/collider.png' 45 | 46 | def __init__(self,vobj): 47 | vobj.Proxy = self 48 | 49 | 50 | def attach(self,vobj): 51 | self.Object = vobj.Object 52 | return 53 | 54 | def claimChildren(self): 55 | return self.Object.Group 56 | 57 | def __getstate__(self): 58 | return None 59 | 60 | def __setstate__(self,state): 61 | return None 62 | 63 | 64 | class Detector(): 65 | 66 | def __init__(self,obj): 67 | obj.Proxy = self 68 | self.obj2=obj 69 | self.Type = "_Manager" 70 | self.Lock=False 71 | if obj.s1==None: 72 | obj.s1=FreeCAD.ActiveDocument.addObject("Part::Sphere","s1") 73 | if obj.s2==None: 74 | obj.s2=FreeCAD.ActiveDocument.addObject("Part::Sphere","s2") 75 | if obj.s3==None: 76 | obj.s3=FreeCAD.ActiveDocument.addObject("Part::Sphere","s3") 77 | # self.comm=FreeCAD.activeDocument().addObject("Part::MultiCommon","Common") 78 | # self.comm.Shapes = [obj.traveller,obj.stator] 79 | if obj.comm==None: 80 | obj.comm = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",'Collision') 81 | obj.comm.ViewObject.Proxy=object() 82 | try: 83 | s=obj.traveller.Shape 84 | s2=obj.stator.Shape 85 | # obj.Shape=s.fuse(s2) 86 | obj.comm.Shape=s.common(s2) 87 | for t in self.comm.Shapes: 88 | t.ViewObject.Visibility=True 89 | except: pass 90 | if obj.offs==None: 91 | obj.offs=FreeCAD.ActiveDocument.addObject("Part::Offset","Offset") 92 | try: obj.offs.Source = obj.comm 93 | except: pass 94 | for s in [obj.comm,obj.offs]: 95 | s.ViewObject.ShapeColor = (1.00,0.00,0.00) 96 | s.ViewObject.Transparency = 30 97 | obj.addObject(s) 98 | for s in [obj.s1, obj.s2]: 99 | s.Radius=1 100 | s.ViewObject.ShapeColor = (1.00,0.00,0.00) 101 | s.ViewObject.Transparency = 80 102 | obj.addObject(s) 103 | s=obj.s3 104 | s.Radius=10 105 | s.ViewObject.ShapeColor = (0.00,1.00,0.00) 106 | s.ViewObject.Transparency = 80 107 | obj.addObject(s) 108 | 109 | 110 | def die(self): 111 | try: 112 | print("DIE") 113 | for k in [self.offs,self.comm,self.s1,self.s2,self.s3,self.obj2]: 114 | print(k,str(k.Name)) 115 | FreeCAD.ActiveDocument.removeObject(str(k.Name)) 116 | except: 117 | sayexc() 118 | 119 | def execute(self,obj): 120 | #say(obj.Label) 121 | #say(obj.ViewObject.Visibility) 122 | try: self.Lock 123 | except: 124 | self.Lock= False 125 | self.obj2=obj 126 | 127 | if not obj.ViewObject.Visibility: return 128 | if not self.Lock: 129 | self.Lock=True 130 | try: 131 | self.findCollision() 132 | say("findCollision done\n") 133 | except: 134 | sayexc("except Fehler beim execute") 135 | self.Lock=False 136 | 137 | def findCollision(self): 138 | obj=self.obj2 139 | 140 | C=self.obj2.stator 141 | B=self.obj2.traveller 142 | d=C.Shape.distToShape(B.Shape) 143 | 144 | dist=d[0] 145 | points=d[1] 146 | for poipair in points: 147 | #print poipair 148 | pass 149 | 150 | # process only one near point 151 | p1=poipair[0] 152 | p2=poipair[1] 153 | 154 | m=FreeCAD.Vector((p1[0]+p2[0])/2,(p1[1]+p2[1])/2,(p1[2]+p2[2])/2) 155 | obj.s3.Placement.Base=m 156 | obj.s1.Placement.Base=p1 157 | obj.s2.Placement.Base=p2 158 | 159 | pl=[] 160 | for poipair in points: 161 | pl.append(poipair[0]) 162 | 163 | if dist<0.001: 164 | s=B.Shape 165 | s2=C.Shape 166 | 167 | if obj.mode==1: 168 | obj.comm.Shape=s.common(s2) 169 | if obj.mode==2: 170 | try: 171 | s3=obj.comm.Shape 172 | t=s3.fuse(s.common(s2)) 173 | obj.comm.Shape=t.removeSplitter() 174 | except: 175 | obj.comm.Shape=s.common(s2) 176 | if obj.hidemode == 1: 177 | obj.comm.ViewObject.Visibility=True 178 | obj.offs.ViewObject.Visibility=True 179 | 180 | obj.s3.ViewObject.Visibility=False 181 | obj.s1.ViewObject.Visibility=False 182 | obj.s2.ViewObject.Visibility=False 183 | # wire.ViewObject.Visibility=True 184 | else: 185 | #print "Abstand" 186 | #print d 187 | if obj.hidemode == 1: 188 | obj.comm.ViewObject.Visibility=False 189 | obj.offs.ViewObject.Visibility=False 190 | if dist<5: 191 | obj.s3.ViewObject.Visibility=True 192 | else: 193 | obj.s3.ViewObject.Visibility=False 194 | if dist<40: 195 | obj.s1.ViewObject.Visibility=True 196 | obj.s2.ViewObject.Visibility=True 197 | else: 198 | obj.s1.ViewObject.Visibility=False 199 | obj.s2.ViewObject.Visibility=False 200 | 201 | # wire.ViewObject.Visibility=False 202 | return 203 | 204 | def createCollision(name='MyCollisionDetector',stator=None,traveller=None): 205 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 206 | obj.addProperty("App::PropertyLink","stator","Base","stator").stator=stator 207 | obj.addProperty("App::PropertyLink","traveller","Base","traveller").traveller=traveller 208 | obj.addProperty("App::PropertyFloat","near1","Base","nearDistance ").near1=10 209 | obj.addProperty("App::PropertyFloat","near2","Base","nearDistance green").near2=5 210 | obj.addProperty("App::PropertyFloat","offset","Base","Tickness of the Colliosion offset").offset=1 211 | 212 | obj.addProperty("App::PropertyLink","s1","helper","s1") 213 | obj.addProperty("App::PropertyLink","s2","helper","s2") 214 | obj.addProperty("App::PropertyLink","s3","helper","s3") 215 | obj.addProperty("App::PropertyLink","comm","helper","common") 216 | obj.addProperty("App::PropertyLink","offs","helper","offset") 217 | obj.addProperty("App::PropertyInteger","mode","helper","1 only common, 2 additive commons ").mode=1 218 | obj.addProperty("App::PropertyInteger","hidemode","helper","1 auto, 2 off").hidemode=1 219 | 220 | _ViewProvider(obj.ViewObject) 221 | t=Detector(obj) 222 | 223 | return t 224 | 225 | 226 | 227 | if __name__ == '__main__' and True: 228 | C=App.ActiveDocument.Cone 229 | B=App.ActiveDocument.Box 230 | t=createCollision("My Col",B,C) 231 | t.Proxy.Lock=False 232 | App.activeDocument().recompute() 233 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /Combiner.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- Animation workbench 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | from say import * 11 | import math,os, time 12 | 13 | from EditWidget import EditWidget 14 | 15 | __vers__= '0.2' 16 | __dir__ = os.path.dirname(__file__) 17 | 18 | 19 | def createCombiner(name='My_Combiner',target=None,src=None): 20 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 21 | obj.addProperty("App::PropertyLink","source","Base","") 22 | obj.addProperty("App::PropertyLink","source2","Base","") 23 | obj.addProperty("App::PropertyLink","source3","Base","") 24 | obj.addProperty("App::PropertyLink","source4","Base","") 25 | obj.addProperty("App::PropertyLink","target","Base","") 26 | obj.addProperty("App::PropertyLink","target2","Base","") 27 | obj.addProperty("App::PropertyLink","target3","Base","") 28 | obj.addProperty("App::PropertyLink","target4","Base","") 29 | obj.target=target 30 | obj.addProperty("App::PropertyLinkList","targets","Base","") 31 | obj.addProperty("App::PropertyLinkList","followers","Base","") 32 | 33 | obj.addProperty("App::PropertyFloat","out","Results","") 34 | obj.addProperty("App::PropertyFloat","out2","Results","") 35 | obj.addProperty("App::PropertyFloat","out3","Results","") 36 | obj.addProperty("App::PropertyFloat","out4","Results","") 37 | 38 | obj.addProperty("App::PropertyFloat","time","Base","") 39 | obj.time=0 40 | 41 | obj.addProperty("App::PropertyString","trafo","Functions","") 42 | obj.addProperty("App::PropertyString","trafo2","Functions","") 43 | obj.addProperty("App::PropertyString","trafo3","Functions","") 44 | obj.addProperty("App::PropertyString","trafo4","Functions","") 45 | obj.trafo="time" 46 | obj.trafo2="2*time" 47 | obj.trafo3="30*time" 48 | obj.trafo4="400*time" 49 | 50 | obj.addProperty("App::PropertyFloat","a","FunctionParameter","") 51 | obj.addProperty("App::PropertyFloat","b","FunctionParameter","") 52 | obj.addProperty("App::PropertyFloat","c","FunctionParameter","") 53 | obj.addProperty("App::PropertyFloat","d","FunctionParameter","") 54 | 55 | obj.a=200 56 | obj.b=0.5 57 | obj.c=50 58 | 59 | _Combiner(obj) 60 | _ViewProviderCombiner(obj.ViewObject) 61 | obj.Proxy.updater=True 62 | return obj 63 | 64 | class _Combiner(Animation._Actor): 65 | 66 | def update(self): 67 | time=self.obj2.time 68 | try: 69 | say("update time=" + str(time) + ", "+ self.obj2.Label) 70 | except: 71 | say("update (ohne Label)") 72 | 73 | time=self.obj2.time 74 | a=self.obj2.a 75 | b=self.obj2.b 76 | c=self.obj2.c 77 | d=self.obj2.d 78 | source=self.obj2.source 79 | source2=self.obj2.source2 80 | source3=self.obj2.source3 81 | source4=self.obj2.source4 82 | 83 | out=eval(self.obj2.trafo) 84 | out2=eval(self.obj2.trafo2) 85 | out3=eval(self.obj2.trafo3) 86 | out4=eval(self.obj2.trafo4) 87 | say([time,out,out2,out3,out4]) 88 | 89 | self.obj2.out=out 90 | self.obj2.out2=out2 91 | self.obj2.out3=out3 92 | self.obj2.out4=out4 93 | 94 | tl=[self.obj2.target,self.obj2.target2,self.obj2.target3,self.obj2.target4] 95 | outl=[out,out2,out3,out4] 96 | for t in range(4): 97 | try: 98 | tl[t].Proxy.step(outl[t]) 99 | tl[t].Proxy.update() 100 | say("combiner update " + str(tl[t].Label) + " wert: " + str(outl[t])) 101 | except: 102 | pass 103 | 104 | def step(self,now): 105 | self.obj2.time=float(now)/100 106 | 107 | 108 | class _ViewProviderCombiner(Animation._ViewProviderActor): 109 | 110 | 111 | def attach(self,vobj): 112 | vobj.Proxy = self 113 | self.Object = vobj.Object 114 | self.obj2=self.Object 115 | self.Object.Proxy.Lock=False 116 | self.Object.Proxy.Changed=False 117 | icon='/icons/combiner.png' 118 | self.iconpath = __dir__ + icon 119 | self.vers=__vers__ 120 | return 121 | 122 | def doubleClicked(self,vobj): 123 | return 124 | 125 | def setupContextMenu(self, obj, menu): 126 | return 127 | 128 | 129 | if __name__ == '__main__': 130 | 131 | App.ActiveDocument.addObject("Part::Box","Box") 132 | App.ActiveDocument.addObject("Part::Box","Box") 133 | App.ActiveDocument.addObject("Part::Box","Box") 134 | App.ActiveDocument.addObject("Part::Box","Box") 135 | App.ActiveDocument.addObject("Part::Cone","Cone") 136 | 137 | import Placer 138 | 139 | s1=Placer.createPlacer("B1") 140 | s1.target=App.ActiveDocument.Box001 141 | 142 | s2=Placer.createPlacer("B2") 143 | s2.target=App.ActiveDocument.Box002 144 | s2.y="10" 145 | 146 | s3=Placer.createPlacer("B3") 147 | s3.target=App.ActiveDocument.Box003 148 | s3.y="20" 149 | 150 | 151 | c=createCombiner("cmb") 152 | c.source=App.ActiveDocument.Cone 153 | 154 | c.trafo="source.Radius1.Value" 155 | c.target=s1 156 | 157 | c.trafo2="source.Radius2.Value" 158 | c.target2=s2 159 | 160 | c.trafo3="max(source.Radius1.Value,source.Radius2.Value)" 161 | c.target3=s3 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /Diagram.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- Animation workbench 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | from say import * 11 | import math 12 | 13 | from EditWidget import EditWidget 14 | 15 | __vers__= '0.2' 16 | __dir__ = os.path.dirname(__file__) 17 | 18 | def _creategraphs(obj): 19 | 20 | obj.Proxy.data={} 21 | obj.Proxy.data2={} 22 | obj.Proxy.data3={} 23 | obj.Proxy.data4={} 24 | obj.Proxy.data5={} 25 | obj.Proxy.data6={} 26 | obj.Proxy.data7={} 27 | obj.Proxy.data8={} 28 | obj.Proxy.data9={} 29 | 30 | if obj.trafo!='' and obj.graph == None: 31 | w=Part.makeSphere(0.1) 32 | Part.show(w) 33 | obj.graph=FreeCAD.activeDocument().ActiveObject 34 | obj.graph.ViewObject.LineColor=(1.0,0.0,.0) 35 | obj.graph.Label="Graph 1 " 36 | 37 | if obj.trafo2!='' and obj.graph2 == None: 38 | w=Part.makeSphere(0.1) 39 | Part.show(w) 40 | obj.graph2=FreeCAD.activeDocument().ActiveObject 41 | obj.graph2.ViewObject.LineColor=(.0,1.0,.0) 42 | obj.graph2.Label="Graph 2 " 43 | 44 | if obj.trafo3!='' and obj.graph3 == None: 45 | w=Part.makeSphere(0.1) 46 | Part.show(w) 47 | obj.graph3=FreeCAD.activeDocument().ActiveObject 48 | obj.graph3.ViewObject.LineColor=(.0,.0,1.0) 49 | obj.graph3.Label="Graph 3 " 50 | if obj.trafo4!='' and obj.graph4 == None: 51 | w=Part.makeSphere(0.1) 52 | Part.show(w) 53 | obj.graph4=FreeCAD.activeDocument().ActiveObject 54 | obj.graph4.ViewObject.LineColor=(1.0,1.0,.0) 55 | obj.graph4.Label="Graph 4 " 56 | 57 | if obj.trafo5!='' and obj.graph5 == None: 58 | w=Part.makeSphere(0.1) 59 | Part.show(w) 60 | obj.graph5=FreeCAD.activeDocument().ActiveObject 61 | obj.graph5.ViewObject.LineColor=(1.0,.0,1.0) 62 | obj.graph5.Label="Graph 5 " 63 | 64 | if obj.trafo6!='' and obj.graph6 == None: 65 | w=Part.makeSphere(0.1) 66 | Part.show(w) 67 | obj.graph6=FreeCAD.activeDocument().ActiveObject 68 | obj.graph6.ViewObject.LineColor=(.0,1.0,1.0) 69 | obj.graph6.Label="Graph 6 " 70 | 71 | if obj.trafo7!='' and obj.graph6 == None: 72 | w=Part.makeSphere(0.1) 73 | Part.show(w) 74 | obj.graph7=FreeCAD.activeDocument().ActiveObject 75 | obj.graph7.ViewObject.LineColor=(.0,1.0,1.0) 76 | obj.graph7.Label="Graph 7 " 77 | 78 | if obj.trafo8!='' and obj.graph8 == None: 79 | w=Part.makeSphere(0.1) 80 | Part.show(w) 81 | obj.graph8=FreeCAD.activeDocument().ActiveObject 82 | obj.graph8.ViewObject.LineColor=(.0,1.0,1.0) 83 | obj.graph8.Label="Graph 8 " 84 | 85 | if obj.trafo9!='' and obj.graph9 == None: 86 | w=Part.makeSphere(0.1) 87 | Part.show(w) 88 | obj.graph9=FreeCAD.activeDocument().ActiveObject 89 | obj.graph9.ViewObject.LineColor=(.0,1.0,1.0) 90 | obj.graph9.Label="Graph 9 " 91 | 92 | 93 | 94 | def createDiagram(name='My_Diagram',trafo='',trafo2='',trafo3='',trafo4='',trafo5='',trafo6=''): 95 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 96 | obj.addProperty("App::PropertyLink","source","Base","") 97 | obj.addProperty("App::PropertyLink","source2","Base","") 98 | obj.addProperty("App::PropertyLink","source3","Base","") 99 | obj.addProperty("App::PropertyLink","source4","Base","") 100 | 101 | obj.addProperty("App::PropertyPlacement","graphPlacement","Base","") 102 | obj.addProperty("App::PropertyLink","graph","Base","") 103 | obj.addProperty("App::PropertyLink","graph2","Base","") 104 | obj.addProperty("App::PropertyLink","graph3","Base","") 105 | obj.addProperty("App::PropertyLink","graph4","Base","") 106 | obj.addProperty("App::PropertyLink","graph5","Base","") 107 | obj.addProperty("App::PropertyLink","graph6","Base","") 108 | obj.addProperty("App::PropertyLink","graph7","Base","") 109 | obj.addProperty("App::PropertyLink","graph8","Base","") 110 | obj.addProperty("App::PropertyLink","graph9","Base","") 111 | 112 | obj.addProperty("App::PropertyFloat","out","Results","") 113 | obj.addProperty("App::PropertyFloat","out2","Results","") 114 | obj.addProperty("App::PropertyFloat","out3","Results","") 115 | obj.addProperty("App::PropertyFloat","out4","Results","") 116 | obj.addProperty("App::PropertyFloat","out5","Results","") 117 | obj.addProperty("App::PropertyFloat","out6","Results","") 118 | obj.addProperty("App::PropertyFloat","out7","Results","") 119 | obj.addProperty("App::PropertyFloat","out8","Results","") 120 | obj.addProperty("App::PropertyFloat","out9","Results","") 121 | 122 | obj.addProperty("App::PropertyFloat","time","Base","") 123 | obj.time=0 124 | 125 | obj.addProperty("App::PropertyString","timeExpression","Functions","") 126 | obj.addProperty("App::PropertyString","trafo","Functions","") 127 | obj.addProperty("App::PropertyString","trafo2","Functions","") 128 | obj.addProperty("App::PropertyString","trafo3","Functions","") 129 | obj.addProperty("App::PropertyString","trafo4","Functions","") 130 | obj.addProperty("App::PropertyString","trafo5","Functions","") 131 | obj.addProperty("App::PropertyString","trafo6","Functions","") 132 | obj.addProperty("App::PropertyString","trafo7","Functions","") 133 | obj.addProperty("App::PropertyString","trafo8","Functions","") 134 | obj.addProperty("App::PropertyString","trafo9","Functions","") 135 | 136 | obj.trafo=trafo 137 | obj.trafo2=trafo2 138 | obj.trafo3=trafo3 139 | obj.trafo4=trafo4 140 | obj.trafo5=trafo5 141 | obj.trafo6=trafo6 142 | 143 | obj.addProperty("App::PropertyFloat","a","FunctionParameter","") 144 | obj.addProperty("App::PropertyFloat","b","FunctionParameter","") 145 | obj.addProperty("App::PropertyFloat","c","FunctionParameter","") 146 | obj.addProperty("App::PropertyFloat","d","FunctionParameter","") 147 | 148 | obj.a=200 149 | obj.b=0.5 150 | obj.c=50 151 | 152 | _Diagram(obj) 153 | _ViewProviderDiagram(obj.ViewObject) 154 | obj.Proxy.updater=True 155 | _creategraphs(obj) 156 | return obj 157 | 158 | class _Diagram(Animation._Actor): 159 | 160 | def update(self): 161 | 162 | time=self.obj2.time 163 | try: 164 | say("update time=" + str(time) + ", "+ self.obj2.Label) 165 | except: 166 | say("update (ohne Label)") 167 | 168 | time=self.obj2.time 169 | 170 | a=self.obj2.a 171 | b=self.obj2.b 172 | c=self.obj2.c 173 | d=self.obj2.d 174 | 175 | source=self.obj2.source 176 | source2=self.obj2.source2 177 | source3=self.obj2.source3 178 | source4=self.obj2.source4 179 | 180 | if self.obj2.timeExpression!="": 181 | say(["eval time Expression",time]) 182 | time=eval(self.obj2.timeExpression) 183 | say(["time== ",time,self.obj2.timeExpression]) 184 | 185 | out=0 186 | out1=0 187 | out2=0 188 | out3=0 189 | out4=0 190 | out5=0 191 | out6=0 192 | out7=0 193 | out8=0 194 | out9=0 195 | 196 | if self.obj2.trafo: out=eval(self.obj2.trafo) 197 | if self.obj2.trafo2: out2=eval(self.obj2.trafo2) 198 | if self.obj2.trafo3: out3=eval(self.obj2.trafo3) 199 | if self.obj2.trafo4: out4=eval(self.obj2.trafo4) 200 | if self.obj2.trafo5: out5=eval(self.obj2.trafo5) 201 | if self.obj2.trafo6: out6=eval(self.obj2.trafo6) 202 | if self.obj2.trafo7: out7=eval(self.obj2.trafo7) 203 | if self.obj2.trafo8: out8=eval(self.obj2.trafo8) 204 | if self.obj2.trafo9: out9=eval(self.obj2.trafo9) 205 | 206 | # say([time,out,out2,out3,out4]) 207 | self.obj2.out=out 208 | self.obj2.out2=out2 209 | self.obj2.out3=out3 210 | self.obj2.out4=out4 211 | self.obj2.out5=out5 212 | self.obj2.out6=out6 213 | self.obj2.out7=out7 214 | self.obj2.out8=out8 215 | self.obj2.out9=out9 216 | 217 | if self.obj2.trafo: 218 | self.register(time,self.data,out,self.obj2.graph) 219 | 220 | if self.obj2.trafo2: 221 | self.register(time,self.data2,out2,self.obj2.graph2) 222 | 223 | if self.obj2.trafo3: 224 | self.register(time,self.data3,out3,self.obj2.graph3) 225 | 226 | if self.obj2.trafo4: 227 | self.register(time,self.data4,out4,self.obj2.graph4) 228 | 229 | if self.obj2.trafo5: 230 | self.register(time,self.data5,out5,self.obj2.graph5) 231 | 232 | if self.obj2.trafo6: 233 | self.register(time,self.data6,out6,self.obj2.graph6) 234 | 235 | if self.obj2.trafo7: 236 | self.register(time,self.data7,out7,self.obj2.graph7) 237 | 238 | if self.obj2.trafo8: 239 | self.register(time,self.data8,out8,self.obj2.graph8) 240 | 241 | if self.obj2.trafo9: 242 | self.register(time,self.data9,out9,self.obj2.graph9) 243 | 244 | 245 | 246 | 247 | def register(self,time,data,out,graph): 248 | 249 | data[time]=out 250 | ts=data.keys() 251 | ts.sort() 252 | pl=[] 253 | # say("points") 254 | for t in ts: 255 | pl.append((t,data[t],1)) 256 | # say(pl) 257 | if len(pl)>1: 258 | w=Part.makePolygon(pl) 259 | else: 260 | w=Part.makeSphere(0.1) 261 | try: 262 | graph.Shape=w 263 | graph.Placement=self.obj2.graphPlacement 264 | except: 265 | pass 266 | 267 | 268 | def step(self,now): 269 | self.obj2.time=float(now)/100 270 | 271 | def onChanged(self,obj,prop): 272 | if prop in ['trafo','trafo2','trafo3','trafo4','trafo5','trafo6','trafo7','trafo8','trafo9']: 273 | _creategraphs(obj) 274 | 275 | 276 | 277 | class _ViewProviderDiagram(Animation._ViewProviderActor): 278 | 279 | 280 | def attach(self,vobj): 281 | vobj.Proxy = self 282 | self.Object = vobj.Object 283 | self.obj2=self.Object 284 | self.Object.Proxy.Lock=False 285 | self.Object.Proxy.Changed=False 286 | _creategraphs(self.Object) 287 | icon='/icons/diagram.png' 288 | self.iconpath = __dir__ + icon 289 | self.vers=__vers__ 290 | return 291 | 292 | def doubleClicked(self,vobj): 293 | return 294 | 295 | def setupContextMenu(self, obj, menu): 296 | return 297 | 298 | 299 | if __name__ == '__main__': 300 | 301 | from Diagram import * 302 | 303 | App.setActiveDocument("Unnamed") 304 | App.ActiveDocument=App.getDocument("Unnamed") 305 | Gui.ActiveDocument=Gui.getDocument("Unnamed") 306 | import Animation 307 | Animation.createManager() 308 | 309 | App.ActiveDocument.addObject("Part::Box","Box") 310 | App.ActiveDocument.addObject("Part::Box","Box") 311 | App.ActiveDocument.addObject("Part::Box","Box") 312 | App.ActiveDocument.addObject("Part::Box","Box") 313 | App.ActiveDocument.addObject("Part::Cone","Cone") 314 | 315 | 316 | import Placer 317 | 318 | s1=Placer.createPlacer("B1") 319 | s1.target=App.ActiveDocument.Box001 320 | 321 | s2=Placer.createPlacer("B2") 322 | s2.target=App.ActiveDocument.Box002 323 | s2.y="10" 324 | 325 | s3=Placer.createPlacer("B3") 326 | s3.target=App.ActiveDocument.Box003 327 | s3.y="20" 328 | 329 | import Diagram 330 | c=Diagram.createDiagram("dia","0.200*time","0.2*(0.01*time-0.5)**2","10+time+1","-10*time") 331 | c.source=s1 332 | c.trafo="source.Placement.Rotation.Angle*100" 333 | c.timeExpression="source.time*10000" 334 | c.graphPlacement.Base.z=10 335 | 336 | m=App.ActiveDocument.My_Manager 337 | m.addObject(c) 338 | -------------------------------------------------------------------------------- /EditWidget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- Animation workbench 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | from PySide import QtCore, QtGui 10 | from say import * 11 | 12 | class _EditWidget(QtGui.QWidget): 13 | '''double clicked dialog''' 14 | def __init__(self, dialer,obj,menu,noclose,*args): 15 | QtGui.QWidget.__init__(self, *args) 16 | obj.widget=self 17 | self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) 18 | self.vollabel =QtGui.QLabel( ""+obj.Object.Label+"") 19 | self.obj=obj 20 | 21 | if dialer: 22 | dial = QtGui.QDial() 23 | dial.setNotchesVisible(True) 24 | self.dial=dial 25 | dial.setMaximum(100) 26 | 27 | edi = QtGui.QLineEdit() 28 | edi.setText("50") 29 | dial.valueChanged.connect(lambda: edi.setText(str(dial.value()))) 30 | edi.textChanged.connect(lambda:dial.setValue(int(edi.text()))) 31 | dial.valueChanged.connect(obj.dialer) 32 | 33 | 34 | layout = QtGui.QVBoxLayout() 35 | layout.addWidget(self.vollabel) 36 | 37 | for m in menu: 38 | bt=QtGui.QPushButton(m[0]) 39 | bt.clicked.connect(m[1]) 40 | layout.addWidget(bt) 41 | 42 | if dialer: 43 | layout.addWidget(dial) 44 | layout.addWidget(edi) 45 | 46 | if not noclose: 47 | self.pushButton02 = QtGui.QPushButton("close") 48 | self.pushButton02.clicked.connect(self.close2) 49 | layout.addWidget(self.pushButton02) 50 | 51 | self.setLayout(layout) 52 | try: 53 | self.setWindowTitle(obj.Object.target.Label) 54 | except: 55 | pass 56 | 57 | def close2(self): 58 | sayErr("close2") 59 | self.hide() 60 | say("2") 61 | say(self.obj) 62 | FreeCAD.tt=self.obj 63 | self.obj.Object.ViewObject.Visibility=False 64 | say("done") 65 | 66 | class EditWidget(_EditWidget): 67 | def __init__(self, obj,menu,noclose,*args): 68 | _EditWidget.__init__(self, True, obj,menu,noclose,*args) 69 | 70 | class EditNoDialWidget(_EditWidget): 71 | def __init__(self, obj,menu,noclose,*args): 72 | _EditWidget.__init__(self, False, obj,menu,noclose,*args) 73 | -------------------------------------------------------------------------------- /Gearing.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- Animation workbench 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | import math,os 11 | import numpy 12 | from numpy import pi,cos,tan,arctan 13 | 14 | import FreeCAD, FreeCADGui, Animation, PySide 15 | from Animation import say,sayErr,sayexc 16 | from EditWidget import EditWidget 17 | 18 | __vers__= '0.2' 19 | __dir__ = os.path.dirname(__file__) 20 | 21 | 22 | 23 | def createGearing(name='My_Gearing'): 24 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 25 | obj.addProperty("App::PropertyInteger","start","Base","start").start=10 26 | obj.addProperty("App::PropertyInteger","end","Base","end").end=110 27 | obj.addProperty("App::PropertyInteger","duration","Base","end").duration=100 28 | obj.addProperty("App::PropertyLink","obj","Base","Sketch") 29 | obj.addProperty("App::PropertyLink","objStar","Base","Sketch") 30 | obj.addProperty("App::PropertyLink","objPlanet","Base","Sketch") 31 | obj.addProperty("App::PropertyLink","objMoon","Base","Sketch") 32 | 33 | obj.addProperty("App::PropertyFloat","dayStar","Config","ve").dayStar=100 34 | obj.addProperty("App::PropertyFloat","dayPlanet","Config","ve").dayPlanet=-50 35 | obj.addProperty("App::PropertyFloat","dayMoon","Config","ve").dayMoon=10 36 | obj.addProperty("App::PropertyFloat","distStarPlanet","Config","ve").distStarPlanet=60 37 | obj.addProperty("App::PropertyFloat","distPlanetMoon","Config","ve").distPlanetMoon=30 38 | 39 | obj.addProperty("App::PropertyColor","color","Config","ve").color=(1.0,1.0,0.0) 40 | 41 | App=FreeCAD 42 | sp=App.activeDocument().addObject("Part::Compound","Ge_sp") 43 | s=App.activeDocument().addObject("Part::Compound","Ge_s") 44 | pm=App.activeDocument().addObject("Part::Compound","Ge_pm") 45 | p=App.activeDocument().addObject("Part::Compound","Ge_p") 46 | m=App.activeDocument().addObject("Part::Compound","Ge_m") 47 | b=App.ActiveDocument.addObject("Part::Box","Box") 48 | b1=App.ActiveDocument.addObject("Part::Box","Box") 49 | b2=App.ActiveDocument.addObject("Part::Box","Box") 50 | b.Placement.Base=FreeCAD.Vector(-5.0,-5.0,0.0) 51 | b1.Placement.Base=FreeCAD.Vector(-5.0,-5.0,0.0) 52 | b2.Placement.Base=FreeCAD.Vector(-5.0,-5.0,0.0) 53 | m.Placement.Base=FreeCAD.Vector(30,0,0.0) 54 | pm.Placement.Base=FreeCAD.Vector(60,0,0.0) 55 | p.Links=[b] 56 | s.Links=[b1] 57 | m.Links=[b2] 58 | pm.Links=[p,m] 59 | sp.Links=[s,pm] 60 | obj.obj=sp 61 | obj.objStar=b1 62 | obj.objPlanet=b 63 | obj.objMoon=b2 64 | 65 | _Gearing(obj) 66 | _ViewProviderGearing(obj.ViewObject) 67 | return obj 68 | 69 | 70 | 71 | def rotstep(s,day): 72 | an= s.Placement.Rotation.Angle 73 | say("rotstep" + s.Label) 74 | say(an*180/math.pi) 75 | say("step" +str(360/day)) 76 | if s.Placement.Rotation.Axis.z==-1 : 77 | an= s.Placement.Rotation.Angle - math.pi * 2/day 78 | say("minus") 79 | else: 80 | an= s.Placement.Rotation.Angle + math.pi * 2/day 81 | say("plus") 82 | if an <0: 83 | an += 2*math.pi 84 | say("add 360") 85 | if an > 2*math.pi: 86 | an -= 2*math.pi 87 | say("minus 360") 88 | 89 | s.Placement.Rotation.Angle = an 90 | say(an*180/math.pi) 91 | 92 | 93 | class _Gearing(Animation._Actor): 94 | 95 | def __init__(self,obj): 96 | obj.Proxy = self 97 | self.Type = "Gearing" 98 | self.obj2 = obj 99 | # for the recursive execute problem 100 | # - see http://forum.freecadweb.org/viewtopic.php?f=3&t=1894 101 | self.ignore=False 102 | 103 | 104 | def step(self,now): 105 | say("Gearing step!" + str(now)) 106 | FreeCAD.R=self 107 | self.ignore=True 108 | 109 | if nowself.obj2.end: 110 | sayd("ausserhalb") 111 | pass 112 | else: 113 | if not self.obj2.obj: 114 | errorDialog("kein Sketch zugeordnet") 115 | raise Exception(' self.obj2.obj nicht definiert') 116 | sys=self.obj2.obj 117 | s=sys.Links[0] 118 | pm=sys.Links[1] 119 | p=pm.Links[0] 120 | m=pm.Links[1] 121 | #say("sonne "+ s.Label) 122 | #say("planet "+ p.Label) 123 | #say("moinde" + m.Label) 124 | 125 | if now==self.obj2.start: 126 | s.Placement.Rotation.Axis=FreeCAD.Vector(0,0,1) 127 | p.Placement.Rotation.Axis=FreeCAD.Vector(0,0,1) 128 | m.Placement.Rotation.Axis=FreeCAD.Vector(0,0,1) 129 | 130 | # Eigenachsen Rotationen 131 | print(s.Placement.Rotation.Angle) 132 | an=s.Placement.Rotation.Angle 133 | ax=s.Placement.Rotation.Axis 134 | day_star=self.obj2.dayStar 135 | day_planet=self.obj2.dayPlanet 136 | day_moon=self.obj2.dayMoon 137 | 138 | rotstep(s,day_star) 139 | rotstep(p,day_planet) 140 | rotstep(m,day_moon) 141 | #p.Placement.Rotation.Angle += math.pi * 2/day_planet 142 | #m.Placement.Rotation.Angle += math.pi * 2/day_moon 143 | 144 | # Schenkel Rotationen 145 | sys.Placement.Rotation.Angle += 0 146 | pm.Placement.Rotation.Angle += 0 147 | 148 | FreeCAD.activeDocument().recompute() 149 | 150 | 151 | self.ignore=False 152 | 153 | 154 | 155 | def onChanged(self,obj,prop): 156 | say("** onChanged ") 157 | if hasattr(FreeCAD,"animationLock"): 158 | if FreeCAD.animationLock: 159 | return 160 | 161 | FreeCAD.animationLock=True 162 | say("------------------------------***Lock EIN") 163 | # say(obj) 164 | say(obj.Label + " " + prop) 165 | FreeCAD.mytoc=[self,obj,prop] 166 | oldval=FreeCAD.animation['changed'][2] 167 | val=obj.getPropertyByName(prop) 168 | say("old:" + str(oldval) + " new:" + str(val)) 169 | 170 | 171 | # g=FreeCAD.getDocument("getriebe").getObject("My_Gearing") 172 | g=obj 173 | 174 | 175 | sys=g.obj 176 | 177 | s=sys.Links[0] 178 | pm=sys.Links[1] 179 | p=pm.Links[0] 180 | m=pm.Links[1] 181 | 182 | # lage planet-stern 183 | if prop=='distStarPlanet': 184 | pm.Placement.Base.x=obj.distStarPlanet 185 | 186 | # age moond stren 187 | if prop=='distPlanetMoon': 188 | m.Placement.Base.x=obj.distPlanetMoon 189 | 190 | if prop=='end': 191 | obj.end=obj.start+obj.duration 192 | 193 | say("begonnen") 194 | if prop=='objMoon': 195 | m.Links=[obj.objMoon] 196 | if prop=='objStar': 197 | s.Links=[obj.objStar] 198 | if prop=='objPlanet': 199 | p.Links=[obj.objPlanet] 200 | FreeCAD.animationLock=False 201 | FreeCAD.activeDocument().recompute() 202 | say("******************************Lock aus") 203 | say("fertig") 204 | 205 | 206 | 207 | def onBeforeChange(self,obj,prop): 208 | say("** on Before Changed " ) 209 | FreeCAD.animationLock=False 210 | # say(obj) 211 | say(prop) 212 | FreeCAD.animation={} 213 | oldval=obj.getPropertyByName(prop) 214 | FreeCAD.animation['changed'] =[obj,prop,oldval] 215 | pass 216 | 217 | 218 | def execute(self,obj): 219 | # obj.end=obj.start+obj.duration 220 | obj.setEditorMode("end", 1) #ro 221 | # obj.setEditorMode("obj", 1) #ro 222 | obj.setEditorMode("color", 2) #hidden 223 | say("execute _Gearing") 224 | if hasattr(self,'ignore'): 225 | if self.ignore: 226 | say("ignore") 227 | return 228 | 229 | 230 | # wenn noch keine zuordnung erfolgt ist 231 | App=FreeCAD 232 | 233 | 234 | 235 | class _ViewProviderGearing(Animation._ViewProviderActor): 236 | 237 | def getIcon(self): 238 | return __dir__ + '/icons/gearing.png' 239 | 240 | 241 | 242 | 243 | #--------------------- 244 | 245 | 246 | 247 | if __name__ == '__main__' : 248 | pass 249 | -------------------------------------------------------------------------------- /Init.py: -------------------------------------------------------------------------------- 1 | #*************************************************************************** 2 | #* * 3 | #* Copyright (c) 2014 * 4 | #* * 5 | #* * 6 | #* This program is free software; you can redistribute it and/or modify * 7 | #* it under the terms of the GNU Lesser General Public License (LGPL) * 8 | #* as published by the Free Software Foundation; either version 2 of * 9 | #* the License, or (at your option) any later version. * 10 | #* for detail see the LICENCE text file. * 11 | #* * 12 | #* This program is distributed in the hope that it will be useful, * 13 | #* but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | #* GNU Library General Public License for more details. * 16 | #* * 17 | #* You should have received a copy of the GNU Library General Public * 18 | #* License along with this program; if not, write to the Free Software * 19 | #* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * 20 | #* USA * 21 | #* * 22 | #*************************************************************************** 23 | 24 | # Get the Parameter Group of this module 25 | ParGrp = App.ParamGet("System parameter:Modules").GetGroup("Animation") 26 | 27 | # Set the needed information 28 | ParGrp.SetString("HelpIndex", "http://www.freecadweb.org") 29 | ParGrp.SetString("WorkBenchName", "Animation") 30 | 31 | -------------------------------------------------------------------------------- /Kartan.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- Animation workbench 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | import math,os 11 | import numpy 12 | from numpy import pi,cos,tan,arctan 13 | 14 | import FreeCAD, FreeCADGui, Animation, PySide 15 | from Animation import say,sayErr,sayexc 16 | from EditWidget import EditWidget 17 | 18 | __vers__= '0.2' 19 | __dir__ = os.path.dirname(__file__) 20 | 21 | 22 | 23 | def createKartan(name='My_Kartan'): 24 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 25 | 26 | obj.addProperty("App::PropertyInteger","start","Base","start").start=10 27 | obj.addProperty("App::PropertyInteger","end","Base","end").end=110 28 | obj.addProperty("App::PropertyInteger","duration","Base","end").duration=100 29 | obj.addProperty("App::PropertyLink","obj","Base","Sketch") 30 | obj.addProperty("App::PropertyLink","objAxis1","Base","Sketch") 31 | obj.addProperty("App::PropertyLink","objAxis2","Base","Sketch") 32 | obj.addProperty("App::PropertyLink","objCross","Base","Sketch") 33 | 34 | obj.addProperty("App::PropertyEnumeration","mode","Config","einheit").mode=['none','parallel','arc'] 35 | obj.addProperty("App::PropertyLink","objAxis3","Base","Sketch") 36 | obj.addProperty("App::PropertyLink","objCross2","Base","Sketch") 37 | 38 | obj.addProperty("App::PropertyFloat","angleRotation","Config","ve").angleRotation=360 39 | obj.addProperty("App::PropertyFloat","angleZenit","Config","ve").angleZenit=30 40 | obj.addProperty("App::PropertyFloat","distance","Config","ve").distance=100 41 | 42 | kart=FreeCAD.activeDocument().addObject("Part::Compound","Kartan") 43 | k1=FreeCAD.activeDocument().addObject("Part::Compound","Ka_x1") 44 | k2=FreeCAD.activeDocument().addObject("Part::Compound","Ka_x2") 45 | c1=FreeCAD.activeDocument().addObject("Part::Compound","Ka_c1") 46 | k3=FreeCAD.activeDocument().addObject("Part::Compound","Ka_x3") 47 | c2=FreeCAD.activeDocument().addObject("Part::Compound","Ka_c2") 48 | 49 | b=FreeCAD.ActiveDocument.addObject("Part::Box","Box") 50 | b1=FreeCAD.ActiveDocument.addObject("Part::Box","Box") 51 | b2=FreeCAD.ActiveDocument.addObject("Part::Box","Box") 52 | 53 | b.Placement.Base=FreeCAD.Vector(-5.0,-5.0,0.0) 54 | b1.Placement.Base=FreeCAD.Vector(-5.0,-5.0,0.0) 55 | b2.Placement.Base=FreeCAD.Vector(-5.0,-5.0,0.0) 56 | 57 | k1.Links=[b] 58 | k2.Links=[b1] 59 | c1.Links=[b2] 60 | obj.obj=kart 61 | obj.objAxis1=k1 62 | obj.objAxis2=k2 63 | obj.objCross=c1 64 | 65 | _Kartan(obj) 66 | _ViewProviderKartan(obj.ViewObject) 67 | return obj 68 | 69 | 70 | 71 | def rotcross(part,alpha,phi): 72 | phi2=math.atan(math.cos(alpha*math.pi/180)*math.tan(phi*math.pi/180))*180/math.pi 73 | print(phi,phi2) 74 | 75 | rot = App.Rotation(App.Vector(0,0,1), phi) 76 | wy=rot.multVec(App.Vector(0,1,0)) 77 | 78 | rot2 = App.Rotation(App.Vector(0,0,1), phi2) 79 | wx1=rot2.multVec(App.Vector(1,0,0)) 80 | if phi <90 or phi>270: 81 | alpha=-alpha 82 | rotalpha=FreeCAD.Rotation(App.Vector(0,1,0), alpha) 83 | wx=rotalpha.multVec(wx1) 84 | 85 | r=(wx.x**2+wx.y**2)**0.5 86 | beta=math.acos(r)*180/math.pi 87 | 88 | p1=FreeCAD.Placement() 89 | phi2=phi 90 | p1.Rotation=FreeCAD.Rotation(App.Vector(0,0,1),phi2) 91 | p2=FreeCAD.Placement() 92 | if 90=self.obj2.end: 112 | say("ausserhalb") 113 | pass 114 | else: 115 | if not self.obj2.obj: 116 | errorDialog("kein Sketch zugeordnet") 117 | raise Exception(' self.obj2.obj nicht definiert') 118 | 119 | # alpha=60 120 | alpha=self.obj2.angleZenit 121 | phi=1 122 | 123 | # testfall 124 | phi=10 125 | 126 | # achse 1 127 | fa1=self.obj2.objAxis1 128 | p0=fa1.Placement 129 | phi0=p0.Rotation.Angle/pi*180 130 | # say("phi0 Basis " + str(phi0)) 131 | p1=FreeCAD.Placement(App.Vector(0,0,0),App.Rotation(App.Vector(0,0,1),phi)) 132 | r1=p1.multiply(p0) 133 | fa1.Placement=r1 134 | 135 | 136 | phi20=arctan(tan(phi0*pi/180)*cos(alpha*pi/180))*180/pi 137 | phi21=arctan(tan((phi0+phi)*pi/180)*cos(alpha*pi/180))*180/pi 138 | say("phi20 "+str(phi20)) 139 | say("phi21 "+str(phi21)) 140 | 141 | # achse 2 142 | timepos=now-self.obj2.start 143 | if 90/phi-1<=timepos and timepos<270/phi-1: 144 | phi21=180+phi21 145 | say("*************** ! phi21 ="+str(phi21) + " now:" + str(now)) 146 | 147 | fa2=self.obj2.objAxis2 148 | p1=FreeCAD.Placement(App.Vector(0,0,0),App.Rotation(App.Vector(0,0,1),phi21)) 149 | p2=FreeCAD.Placement(App.Vector(0,0,0),App.Rotation(App.Vector(0,1,0),alpha)) 150 | r3=p2.multiply(p1) 151 | fa2.Placement=r3 152 | 153 | # kreuz 154 | f=self.obj2.objCross 155 | rotcross(f,alpha,phi0+phi) 156 | FreeCAD.activeDocument().recompute() 157 | 158 | 159 | 160 | 161 | def onChanged(self,obj,prop): 162 | say("** onChanged " +str(obj.Label) + " " + prop) 163 | if prop=="Proxy": 164 | FreeCAD.animataionInit=True 165 | say("animation Init start!!!!!!!!!!!!!!!") 166 | if prop=="Label": 167 | FreeCAD.animataionInit=False 168 | say("Animation init beendet ---------------!!") 169 | if FreeCAD.animataionInit: 170 | say("erster Durchlauf - nix machen") 171 | return 172 | if hasattr(FreeCAD,"animationLock"): 173 | say(FreeCAD.animationLock) 174 | if FreeCAD.animationLock: 175 | say("Ende wegen Lock") 176 | return 177 | else: 178 | say("noch kein animation Lock") 179 | 180 | FreeCAD.animationLock=True 181 | say("------------------------------***Lock EIN") 182 | FreeCAD.mytoc=[self,obj,prop] 183 | if hasattr(FreeCAD,"animation"): 184 | oldval=FreeCAD.animation['changed'][2] 185 | val=obj.getPropertyByName(prop) 186 | say(prop + " old:" + str(oldval) + " new:" + str(val)) 187 | 188 | if prop=='obj': 189 | obj.obj.Links=[obj.objAxis1,obj.objAxis2,obj.objCross] 190 | if prop=='duration' or prop=='start': 191 | obj.end=obj.start+obj.duration 192 | if prop=='angleZenit': 193 | obj.objAxis2.Placement.Rotation.Angle=obj.angleZenit/180*math.pi 194 | 195 | FreeCAD.animationLock=False 196 | FreeCAD.activeDocument().recompute() 197 | say("******************************Lock aus") 198 | 199 | def onBeforeChange(self,obj,prop): 200 | say("** on Before Changed " + str(obj.Label) + " " + prop) 201 | FreeCAD.animation={} 202 | oldval=obj.getPropertyByName(prop) 203 | FreeCAD.animation['changed'] =[obj,prop,oldval] 204 | 205 | def execute(self,obj): 206 | say("execute _Kardan") 207 | 208 | 209 | class _ViewProviderKartan(Animation._ViewProviderActor): 210 | 211 | def getIcon(self): 212 | return __dir__ + '/icons/kardan.png' 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /Keyboard.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- animation workbench keyboard sensor 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | import FreeCAD,PySide,os,FreeCADGui 11 | from PySide import QtCore, QtGui, QtSvg 12 | from PySide.QtGui import * 13 | import Part 14 | 15 | from EditWidget import EditNoDialWidget 16 | 17 | 18 | import math,os 19 | 20 | import FreeCAD, Animation, PySide 21 | from Animation import say,sayErr,sayexc 22 | 23 | __vers__='0.1 5.12.2015' 24 | __dir__ = os.path.dirname(__file__) 25 | 26 | 27 | #---------------------- 28 | 29 | 30 | from PySide import QtGui,QtCore 31 | import FreeCAD,tools,sys 32 | from tools import * 33 | 34 | 35 | App=FreeCAD 36 | Gui=FreeCADGui 37 | 38 | class EventFilter(QtCore.QObject): 39 | 40 | def __init__(self,ctl=None): 41 | QtCore.QObject.__init__(self) 42 | self.V=ctl.src 43 | self.ctl=ctl 44 | 45 | self.keypressed=False 46 | self.stack=[] 47 | self.editmode=False 48 | self.pos=None 49 | #self.debug=False 50 | self.debug=FreeCAD.ParamGet('User parameter:Plugins').GetBool('EventFilterDebug') 51 | self.debug=True 52 | 53 | def eventFilter(self, o, e): 54 | z=str(e.type()) 55 | try: 56 | # not used events 57 | if z == 'PySide.QtCore.QEvent.Type.ChildAdded' or \ 58 | z == 'PySide.QtCore.QEvent.Type.ChildRemoved'or \ 59 | z == 'PySide.QtCore.QEvent.Type.User' or \ 60 | z == 'PySide.QtCore.QEvent.Type.Paint' or \ 61 | z == 'PySide.QtCore.QEvent.Type.LayoutRequest' or\ 62 | z == 'PySide.QtCore.QEvent.Type.UpdateRequest' : 63 | return QtGui.QWidget.eventFilter(self, o, e) 64 | 65 | if z == 'PySide.QtCore.QEvent.Type.HoverMove' : 66 | self.pos=e.pos() 67 | if z == 'PySide.QtCore.QEvent.Type.KeyPress': 68 | # ignore editors 69 | if self.editmode: 70 | return QtGui.QWidget.eventFilter(self, o, e) 71 | 72 | # only first time key pressed 73 | if not self.keypressed: 74 | text=e.text() 75 | if 0 or text !='': 76 | self.keypressed=True 77 | key='' 78 | if e.modifiers() & QtCore.Qt.SHIFT: 79 | #FreeCAD.Console.PrintMessage("SHIFT ") 80 | key +="SHIFT+" 81 | if e.modifiers() & QtCore.Qt.CTRL: 82 | #FreeCAD.Console.PrintMessage("CTRL ") 83 | key +="CTRL+" 84 | if e.modifiers() & QtCore.Qt.ALT: 85 | #FreeCAD.Console.PrintMessage("ALT ") 86 | key +="ALT+" 87 | key +=PySide.QtGui.QKeySequence(e.key()).toString() 88 | FreeCAD.Console.PrintMessage(" "+str(key) +" \n" ) 89 | 90 | pos=self.pos 91 | #if e.key()== QtCore.Qt.Key_F10: 92 | # key += "F10#" 93 | 94 | if pos: 95 | if self.debug: FreeCAD.Console.PrintMessage( key + " at mouse position: " +str(pos) + "\n") 96 | say(pos.x()) 97 | say(pos.y()) 98 | step=1 99 | if key == 'F': 100 | self.V.Placement.Base.x -= step 101 | elif key == 'G': 102 | self.V.Placement.Base.x += step 103 | elif key == 'T': 104 | self.V.Placement.Base.y += step 105 | elif key == 'V': 106 | self.V.Placement.Base.y -= step 107 | elif key == 'Z': 108 | self.V.Placement.Base.x += step 109 | self.V.Placement.Base.y += step 110 | elif key == 'R': 111 | self.V.Placement.Base.x -= step 112 | self.V.Placement.Base.y += step 113 | elif key == 'B': 114 | self.V.Placement.Base.x += step 115 | self.V.Placement.Base.y -= step 116 | elif key == 'C': 117 | self.V.Placement.Base.x -= step 118 | self.V.Placement.Base.y -= step 119 | 120 | 121 | elif key == 'H': 122 | s=Gui.Selection.getSelection() 123 | try: 124 | ll=Gui.Selection.getSelectionEx() 125 | pts=ll[0].PickedPoints 126 | V.Placement.Base.x=pts[0].x 127 | V.Placement.Base.y=pts[0].y 128 | except: 129 | try: 130 | say("error 11") 131 | self.V.Placement.Base.x=s[0].Placement.Base.x 132 | self.V.Placement.Base.y=s[0].Placement.Base.y 133 | except: 134 | say("error 2") 135 | pass 136 | self.ctl.Placement=self.V.Placement 137 | App.ActiveDocument.recompute() 138 | else: 139 | self.keypressed=False 140 | if z == 'PySide.QtCore.QEvent.Type.KeyRelease': 141 | if self.keypressed: 142 | pass 143 | self.keypressed=False 144 | except: 145 | sayexc() 146 | try: 147 | return QtGui.QWidget.eventFilter(self, o, e) 148 | except: 149 | return None 150 | 151 | def start(V=None): 152 | mw=QtGui.qApp 153 | ef=EventFilter(V) 154 | FreeCAD.keyfilter=ef 155 | mw.installEventFilter(ef) 156 | 157 | def stop(): 158 | mw=QtGui.qApp 159 | ef=FreeCAD.keyfilter 160 | mw.removeEventFilter(ef) 161 | 162 | #------------------------ 163 | 164 | def createKeyboard(name,src=None): 165 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 166 | obj.addProperty("App::PropertyLink","src","Base","").src=src 167 | obj.addProperty("App::PropertyFloat","time","Base","").time=0 168 | obj.addProperty("App::PropertyLinkList","followers","Base","") 169 | obj.addProperty("App::PropertyPlacement","Placement","Results","") 170 | 171 | _Keyboard(obj) 172 | _ViewProviderKeyboard(obj.ViewObject) 173 | return obj 174 | 175 | class _Keyboard(Animation._Actor): 176 | 177 | def update(self): 178 | return 179 | 180 | def step(self,now): 181 | return 182 | 183 | class _ViewProviderKeyboard(Animation._ViewProviderActor): 184 | 185 | def getIcon(self): 186 | return __dir__ +'/icons/icon1.svg' 187 | 188 | def attach(self,vobj): 189 | self.emenu=[["start",self.start],["stop",self.stop]] 190 | self.cmenu=self.emenu 191 | say("attach " + str(vobj.Object.Label)) 192 | self.Object = vobj.Object 193 | self.obj2=self.Object 194 | self.Object.Proxy.Lock=False 195 | self.Object.Proxy.Changed=False 196 | return 197 | 198 | def edit(self): 199 | self.dialog=EditNoDialWidget(self,self.emenu) 200 | self.dialog.show() 201 | 202 | def showVersion(self): 203 | cl=self.Object.Proxy.__class__.__name__ 204 | PySide.QtGui.QMessageBox.information(None, "About ", "Animation" + cl +" Node\nVersion " + __vers__ ) 205 | 206 | def dialer(self): 207 | self.obj2.time=float(self.widget.dial.value())/100 208 | FreeCAD.ActiveDocument.recompute() 209 | 210 | def start(self): 211 | say("start sensor") 212 | mw=QtGui.qApp 213 | 214 | ef=EventFilter(self.obj2) 215 | FreeCAD.keyfilter=ef 216 | mw.installEventFilter(ef) 217 | 218 | def stop(self): 219 | say("stop sensor") 220 | 221 | mw=QtGui.qApp 222 | ef=FreeCAD.keyfilter 223 | mw.removeEventFilter(ef) 224 | say("stopped") 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /Miki.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- miki - my kivy like creation tools 4 | #-- 5 | #-- microelly 2016 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | 11 | 12 | 13 | def creatorFunction(name): 14 | if name.startswith('Part::'): 15 | return "App.activeDocument().addObject(name,label)" 16 | if name.startswith('So'): 17 | return "coin."+name+'()' 18 | if name.startswith('QtGui'): 19 | return name+"()" 20 | 21 | if name in ['Plugger','Manager']: 22 | return 'Animation.create'+name+'()' 23 | return name+'()' 24 | 25 | 26 | 27 | import FreeCAD,Animation,FreeCADGui 28 | import re 29 | import pivy 30 | from pivy import coin 31 | 32 | App=FreeCAD 33 | 34 | import PySide 35 | from PySide import QtCore, QtGui, QtSvg 36 | 37 | import traceback,sys 38 | def sayexc(mess=''): 39 | exc_type, exc_value, exc_traceback = sys.exc_info() 40 | ttt=repr(traceback.format_exception(exc_type, exc_value,exc_traceback)) 41 | lls=eval(ttt) 42 | l=len(lls) 43 | l2=[lls[(l-3)],lls[(l-1)]] 44 | FreeCAD.Console.PrintError(mess + "\n" +"--> ".join(l2)) 45 | print(mess + "\n" +"--> ".join(l2)) 46 | 47 | 48 | 49 | #*************** 50 | YourSpecialCreator=Animation.createManager 51 | 52 | def fv(name="vertical"): 53 | w=QtGui.QWidget() 54 | 55 | w.setStyleSheet("QWidget { font: bold 18px;color:brown;border-style: outset;border-width: 3px;border-radius: 10px;border-color: blue;}") 56 | layout = QtGui.QVBoxLayout() 57 | layout.setAlignment(QtCore.Qt.AlignTop) 58 | w.setLayout(layout) 59 | 60 | pB= QtGui.QLabel(name) 61 | layout.addWidget(pB) 62 | w.setWindowTitle("Testfenster") 63 | w.show() 64 | w.layout=layout 65 | return w 66 | 67 | def fh(name="horizontal"): 68 | w=QtGui.QWidget() 69 | w.setStyleSheet("QWidget { font: bold 18px;color:blue;border-style: outset;border-width: 3px;border-radius: 10px;border-color: blue;}") 70 | layout = QtGui.QHBoxLayout() 71 | layout.setAlignment(QtCore.Qt.AlignLeft) 72 | w.setLayout(layout) 73 | pB= QtGui.QLabel(name) 74 | pB.setStyleSheet("QWidget { font: bold 18px;color:red;border-style: outset;border-width: 3px;border-radius: 10px;border-color: blue;}") 75 | layout.addWidget(pB) 76 | w.show() 77 | w.layout=layout 78 | return w 79 | 80 | 81 | VerticalLayout=fv 82 | HorzontalLayout=fh 83 | 84 | #*************** 85 | 86 | 87 | class Miki(): 88 | def __init__(self): 89 | self.objects=[] 90 | self.anchors={} 91 | self.indents=[] 92 | self.olistref=[] 93 | self.indpos=-1 94 | self.roots=[] 95 | self.app=None 96 | self.ids={} 97 | 98 | 99 | 100 | def parse2(self,s): 101 | app=self.app 102 | 103 | ls=s.splitlines() 104 | line=0 105 | depth=0 106 | d=[0,0,0,0,0,0,0,0,0,0] 107 | ln=[0,0,0,0,0,0,0,0,0,0] 108 | refs={} 109 | rs=[] 110 | r=None 111 | r=[-1,0,0,''] 112 | for l in ls: 113 | if r: 114 | rs.append(r) 115 | r=[-1,0,0,''] 116 | line += 1 117 | if l.startswith('#:'): 118 | res=re.search("#:\s*(\S.*)",l) 119 | r=[l,line,-1,'cmd',res.group(1)] 120 | continue 121 | 122 | if l.startswith('#'): 123 | continue 124 | 125 | res=re.search("(\s*)(\S.*)",l) 126 | if res: 127 | l=len(res.group(1)) 128 | if l==0: 129 | depth=0 130 | if d[depth]l: 133 | depth -= 1 134 | d[depth]=l 135 | ln[depth]=line 136 | parent=ln[depth-1] 137 | 138 | r=[l,line,parent,res.group(2)] 139 | st=res.group(2) 140 | 141 | res=re.search("(\S+):\s*\*(\S+)",st) 142 | if res: 143 | r=[l,line,parent,'link',res.group(1),res.group(2),refs[res.group(2)]] 144 | continue 145 | 146 | res=re.search("(\S+):\s*&(\S+)\s+(\S.*)",st) 147 | if res: 148 | r=[l,line,parent,"anchor attr",res.group(1),res.group(2),res.group(3)] 149 | refs[res.group(2)]=line 150 | continue 151 | 152 | res=re.search("(\S+):\s*&(\S+)",st) 153 | if res: 154 | r=[l,line,parent,"anchor",res.group(1),res.group(2)] 155 | refs[res.group(2)]=line 156 | continue 157 | 158 | res=re.search("(\S+[^:]):\s*([^:]\S.*)",st) 159 | if res: 160 | r=[l,line,parent,"att val",res.group(1),eval(res.group(2))] 161 | if res.group(1) =='Name': 162 | rs[parent].append(res.group(2)) 163 | else: 164 | res=re.search("(\S+):",st) 165 | if res: 166 | r=[l,line,parent,"obj", res.group(1),'no anchor'] 167 | 168 | self.lines=rs 169 | 170 | 171 | 172 | def build(self): 173 | for l in self.lines: 174 | if l[3]=='cmd': 175 | try: 176 | exec(l[4]) 177 | except: 178 | sayexc(str(["Error exec:",l[4]])) 179 | continue 180 | if l[3]=='obj' or l[3]=='anchor': 181 | name=l[4] 182 | f=creatorFunction(l[4]) 183 | if len(l)<7: # no name for object 184 | l.append('') 185 | label=l[6] 186 | 187 | h=eval(f) 188 | if len(l)<7: 189 | l.append(None) 190 | l.append(h) 191 | if l[2] != 0: 192 | if l[4]=='Name': continue 193 | if l[3]=='obj' or l[3]=='anchor': 194 | parent=self.lines[l[2]][7] 195 | self.addChild(parent,l[7]) 196 | if l[3]=='link': 197 | parent=self.lines[l[2]][7] 198 | try: 199 | child=self.lines[l[6]][7] 200 | self.addChild(parent,child) 201 | except: 202 | # link eines attribs 203 | method=l[4] 204 | v=self.lines[l[6]][6] 205 | kk=eval("parent."+l[4]) 206 | cnkk=kk.__class__.__name__ 207 | if cnkk.startswith('So'): 208 | ex="parent."+method+".setValue(" +str(v) + ")" 209 | exec(ex) 210 | continue 211 | if cnkk =='builtin_function_or_method': 212 | # qt 2... 213 | kk(v) 214 | continue 215 | cn=v.__class__.__name__ 216 | if cn=='int' or cn=='float': 217 | ex="parent."+l[4]+"="+str(v) 218 | elif cn=='str': 219 | ex="parent."+l[4]+"='"+v+"'" 220 | else: 221 | print( "nicht implementierter typ") 222 | ex='' 223 | print( "*** "+ex) 224 | exec(ex) 225 | #----------------------------------- 226 | if l[3]=='att val' or l[3]=='anchor attr': 227 | parent=self.lines[l[2]][7] 228 | method=l[4] 229 | 230 | if l[3]=='att val': 231 | v=l[5] 232 | else: 233 | v=l[6] 234 | if method=='id': 235 | self.ids[v]=parent 236 | continue 237 | 238 | kk=eval("parent."+l[4]) 239 | cnkk=kk.__class__.__name__ 240 | 241 | if cnkk.startswith('So'): 242 | ex="parent."+method+".setValue(" +str(v) + ")" 243 | exec(ex) 244 | continue 245 | 246 | if cnkk =='builtin_function_or_method': 247 | # qt 3... 248 | kk(v) 249 | continue 250 | 251 | cn=v.__class__.__name__ 252 | if cn=='int' or cn=='float': 253 | ex="parent."+l[4]+"="+str(v) 254 | elif cn=='str': 255 | ex="parent."+l[4]+"='"+v+"'" 256 | else: 257 | print("nicht implementierter typ") 258 | ex='' 259 | print("*** "+ex) 260 | exec(ex) 261 | 262 | 263 | def showSo(self): 264 | for l in self.lines: 265 | if l[2] == 0 and l[0] !=-1: 266 | r=l[7] 267 | if r.__class__.__name__.startswith('So'): 268 | sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() 269 | sg.addChild(r) 270 | 271 | 272 | 273 | def showSo2(self,dokname): 274 | for l in self.lines: 275 | if l[2] == 0 and l[0] !=-1: 276 | r=l[7] 277 | if r.__class__.__name__.startswith('So'): 278 | dok = FreeCADGui.getDocument(dokname) 279 | sg=dok.ActiveView.getSceneGraph() 280 | sg.addChild(r) 281 | 282 | 283 | 284 | def addChild(self,p,c): 285 | cc=c.__class__.__name__ 286 | 287 | if str(c.__class__).startswith("Rotation ..." + str(rot.Axis) + "winkel " + str(rot.Angle)) 136 | 137 | pl=FreeCAD.Placement(FreeCAD.Vector(xv,yv,zv),rot,self.obj2.RotCenter) 138 | #say(pl) 139 | if self.obj2.target!=None: 140 | if self.obj2.target.__class__.__name__ == 'GroupExtension': 141 | for t in self.obj2.target.Group: 142 | if str(t.TypeId) == 'App::Annotation': 143 | t.Position=(xv,yv,zv) 144 | else: 145 | pl2=pl.multiply(self.obj2.prePlacement) 146 | t.Placement=pl2 147 | else: 148 | if str(self.obj2.target.TypeId) == 'App::Annotation': 149 | self.obj2.target.Position=(xv,yv,zv) 150 | else: 151 | pl2=pl.multiply(self.obj2.prePlacement) 152 | self.obj2.target.Placement=pl2 153 | 154 | for t in self.obj2.Group: 155 | if str(t.TypeId) == 'App::Annotation': 156 | t.Position=(xv,yv,zv) 157 | else: 158 | pl2=pl.multiply(self.obj2.prePlacement) 159 | t.Placement=pl2 160 | 161 | 162 | 163 | self.obj2.Placement=pl 164 | if self.obj2.followers: 165 | for f in self.obj2.followers: 166 | # FreeCAD.ActiveDocument.Ergebnis.Proxy.execute(FreeCAD.ActiveDocument.Ergebnis) 167 | f.Proxy.execute(f) 168 | 169 | def step(self,now): 170 | # say("step "+str(now) + str(self)) 171 | self.obj2.time=float(now)/100 172 | 173 | class _ViewProviderPlacer(Animation._ViewProviderActor): 174 | 175 | def __init__(self,vobj): 176 | say(self) 177 | Animation._ViewProviderActor.__init__(self,vobj) 178 | self.attach(vobj) 179 | 180 | def attach(self,vobj): 181 | # items for edit dialog and contextmenue 182 | self.emenu=[['A',self.funA],['B',self.funB]] 183 | self.cmenu=[['AC',self.funA],['BC',self.funB]] 184 | 185 | say("VO attach " + str(vobj.Object.Label)) 186 | vobj.Proxy = self 187 | self.Object = vobj.Object 188 | self.obj2=self.Object 189 | self.Object.Proxy.Lock=False 190 | self.Object.Proxy.Changed=False 191 | self.touchTarget=True 192 | icon='/icons/placer.png' 193 | self.iconpath = __dir__ + icon 194 | return 195 | 196 | def setupContextMenu(self, obj, menu): 197 | cl=self.Object.Proxy.__class__.__name__ 198 | action = menu.addAction("About " + cl) 199 | action.triggered.connect(self.showVersion) 200 | 201 | action = menu.addAction("Edit ...") 202 | action.triggered.connect(self.edit) 203 | 204 | for m in self.cmenu: 205 | action = menu.addAction(m[0]) 206 | action.triggered.connect(m[1]) 207 | 208 | def showVersion(self): 209 | cl=self.Object.Proxy.__class__.__name__ 210 | PySide.QtGui.QMessageBox.information(None, "About ", "Animation" + cl +" Node\nVersion " + __vers__ ) 211 | 212 | def dialer(self): 213 | inlist=self.obj2.InList 214 | vlist=[] 215 | for v in inlist: 216 | vlist.append(v.ViewObject.Visibility) 217 | v.ViewObject.Visibility=False 218 | self.obj2.time=float(self.widget.dial.value())/100 219 | FreeCAD.ActiveDocument.recompute() 220 | self.obj2.target.touch() 221 | FreeCAD.ActiveDocument.recompute() 222 | n=0 223 | for v in inlist: 224 | v.ViewObject.Visibility=vlist[n] 225 | n +=1 226 | 227 | 228 | def funA(self): 229 | say("ich bin FunA touch target") 230 | FreeCAD.ActiveDocument.recompute() 231 | self.obj2.target.touch() 232 | FreeCAD.ActiveDocument.recompute() 233 | say("ich war FunA") 234 | 235 | 236 | def funB(self): 237 | say("ich bin FunB tozch target") 238 | self.touchTarget=not self.touchTarget 239 | say(self.touchTarget) 240 | 241 | 242 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Animation Toolkit for FreeCAD 2 | 3 | This Workbench can be used to create sequences of pictures. 4 | 5 | It is still under construction - all contributions welcomed .. 6 | 7 | #Linux Installation Instructions 8 | 9 | To use this workbench clone this git repository under your FreeCAD MyScripts directory. On a Linux Debian based system such as Ubuntu, installation can be done through BASH as follows 10 | 11 | $ mkdir ~/.FreeCAD/Mod 12 | 13 | $ cd ~/.FreeCAD/Mod 14 | 15 | $ git clone https://github.com/microelly2/Animation.git 16 | 17 | Once installed, use git to easily update to the latest version: 18 | 19 | $ cd ~/.FreeCAD/Mod/Animation 20 | 21 | $ git pull 22 | 23 | #Windows Installation Instructions 24 | 25 | Tested with 0.16.5005 Development Snapshot on a Windows 7 64bit-System (thanks BPLRFE ) 26 | 27 | - download the git repository as ZIP 28 | - assuming FreeCAD is installed in "C:\PortableApps\FreeCAD 0_16", go to "C:\PortableApps\FreeCAD 0_16\Mod" within Windows Explorer 29 | - create new directory named "Animation" 30 | - unzip downloaded repository in "C:\PortableApps\FreeCAD 0_16\Mod\Animation" 31 | 32 | Within FreeCAD you will now have a new workbench-entry called "Animation". 33 | 34 | #Mac Installation Instructions 35 | 36 | Copy or unzip the drawing dimensioning folder to the directory FreeCAD.app/Contents/Mod 37 | 38 | where FreeCAD.app is the folder where FreeCAD is installed. 39 | 40 | 41 | -------------------------------------------------------------------------------- /Scaler.py: -------------------------------------------------------------------------------- 1 | import math,os 2 | import FreeCAD, FreeCADGui, Animation, PySide 3 | from Animation import say,sayErr,sayexc,sayd 4 | from EditWidget import EditWidget 5 | 6 | __vers__= '0.1' 7 | __dir__ = os.path.dirname(__file__) 8 | 9 | 10 | def createScaler(name='My_Scaler'): 11 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 12 | 13 | obj.addProperty("App::PropertyInteger","start","Base","start").start=0 14 | obj.addProperty("App::PropertyInteger","end","Base","") 15 | obj.addProperty("App::PropertyInteger","duration","Base","") 16 | 17 | obj.addProperty("App::PropertyFloat","xScale","Scale","Rotationsachse Zentrum relativ").xScale=0 18 | obj.addProperty("App::PropertyFloat","xVa","Scale","Rotationsachse Zentrum relativ").xVa=1 19 | obj.addProperty("App::PropertyFloat","xVe","Scale","Rotationsachse Zentrum relativ").xVe=2 20 | 21 | obj.addProperty("App::PropertyFloat","yScale","Scale","Rotationsachse Zentrum relativ").yScale=0 22 | obj.addProperty("App::PropertyFloat","yVa","Scale","Rotationsachse Zentrum relativ").yVa=1 23 | obj.addProperty("App::PropertyFloat","yVe","Scale","Rotationsachse Zentrum relativ").yVe=2 24 | 25 | obj.addProperty("App::PropertyFloat","zScale","Scale","Rotationsachse Zentrum relativ").zScale=1 26 | obj.addProperty("App::PropertyFloat","zVa","Scale","Rotationsachse Zentrum relativ").zVa=1 27 | obj.addProperty("App::PropertyFloat","zVe","Scale","Rotationsachse Zentrum relativ").zVe=2 28 | 29 | obj.addProperty("App::PropertyLink","obj2","Object","rotating object ") 30 | 31 | _Scaler(obj) 32 | _ViewProviderScaler(obj.ViewObject) 33 | return obj 34 | 35 | 36 | 37 | class _Scaler(Animation._Actor): 38 | 39 | def __init__(self,obj): 40 | obj.Proxy = self 41 | self.Type = "_Scaler" 42 | self.obj2=obj 43 | 44 | def execute(self,obj): 45 | sayd("execute _Scaler") 46 | if hasattr(obj,'obj2'): 47 | #say(obj.obj2) 48 | pass 49 | obj.setEditorMode("end", 1) #ro 50 | obj.end=obj.start+obj.duration 51 | 52 | def step(self,now): 53 | FreeCAD.yy=self 54 | 55 | if now<=self.obj2.start or now>self.obj2.end: 56 | pass 57 | else: 58 | relativ=1.00/(self.obj2.end-self.obj2.start)*(now-self.obj2.start) 59 | sc=self.obj2.obj2.Scale 60 | relativbase=self.obj2.xVe/self.obj2.xVa*relativ 61 | if relativ==0: 62 | nwx=self.obj2.xVa 63 | nwy=self.obj2.yVa 64 | nwz=self.obj2.zVa 65 | else: 66 | nwx=relativbase**self.obj2.xScale*self.obj2.xVe 67 | nwy=relativbase**self.obj2.yScale*self.obj2.yVe 68 | nwz=relativbase**self.obj2.zScale*self.obj2.zVe 69 | newScale=(nwx,nwy,nwz) 70 | self.obj2.obj2.Scale=newScale 71 | FreeCAD.ActiveDocument.recompute() 72 | FreeCADGui.Selection.clearSelection() 73 | 74 | 75 | class _ViewProviderScaler(Animation._ViewProviderActor): 76 | 77 | def getIcon(self): 78 | return __dir__ + '/icons/scaler.png' 79 | -------------------------------------------------------------------------------- /Snapshot.py: -------------------------------------------------------------------------------- 1 | import FreeCAD 2 | import Animation 3 | from Animation import say,sayErr,sayexc 4 | import os 5 | 6 | __vers__= '0.2' 7 | __dir__ = os.path.dirname(__file__) 8 | 9 | 10 | #--------------------------------------------------------------- 11 | # Snapshot 12 | #--------------------------------------------------------------- 13 | 14 | class _Snapshot(Animation._Actor): 15 | ''' creat a simple copy of the animated object each step ''' 16 | 17 | def step(self,now): 18 | if now==0: 19 | self.g=FreeCAD.activeDocument().addObject("App::DocumentObjectGroup","Snapshots_"+ self.obj2.seqname) 20 | ss=FreeCAD.ActiveDocument.addObject('Part::Feature',self.obj2.seqname) 21 | ss.Shape=self.obj2.target.Shape 22 | ss.ViewObject.ShapeColor=(1.0,0.0,0.0) 23 | ss.ViewObject.Visibility=False 24 | self.g.addObject(ss) 25 | 26 | def update(self): 27 | pass 28 | 29 | class _ViewProviderSnapshot(Animation._ViewProviderActor): 30 | 31 | def getIcon(self): 32 | icon='/icons/snapshot.png' 33 | return __dir__ + icon 34 | 35 | def createSnapshot(name='My_Snapshot',seqname='S',target=None,targets=[]): 36 | '''createSnapshot(name,seqname='S',target=None,targets=[]) returns an animation node for one target or a list of targets 37 | target: single object, targets: list of objects 38 | ''' 39 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 40 | obj.addProperty("App::PropertyLink","target","Base","") 41 | obj.addProperty("App::PropertyLinkList","targets","Base","") 42 | obj.addProperty("App::PropertyString","seqname","Base","").seqname=seqname 43 | obj.target=target 44 | if targets: 45 | obj.targets=targets 46 | _Snapshot(obj) 47 | _ViewProviderSnapshot(obj.ViewObject) 48 | return obj 49 | 50 | 51 | #--------------------------------------------------------------- 52 | # View Sequence 53 | #--------------------------------------------------------------- 54 | 55 | class _ViewSequence(Animation._Actor): 56 | ''' shows a numbered list of parts''' 57 | 58 | def step(self,now): 59 | if now==0: 60 | sufi='' 61 | else: 62 | sufi= "%03d" % (now) 63 | if now > 0: 64 | try: 65 | ob=self.last 66 | ob.ViewObject.Visibility=False 67 | except: 68 | pass 69 | ob=FreeCAD.activeDocument().getObject(self.obj2.seqname + sufi) 70 | say(ob.Name) 71 | ob.ViewObject.Visibility=True 72 | self.last=ob 73 | 74 | class _ViewProviderViewSequence(Animation._ViewProviderActor): 75 | 76 | def getIcon(self): 77 | return __dir__ + '/icons/snapshotviewer.png' 78 | 79 | def createViewSequence(name='My_ViewSequence',seqname='S'): 80 | ''' createViewSequence(name,sequencename) returns an animation node for a sequence list''' 81 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 82 | obj.addProperty("App::PropertyString","seqname","Base","").seqname=seqname 83 | _ViewSequence(obj) 84 | _ViewProviderViewSequence(obj.ViewObject) 85 | return obj 86 | 87 | -------------------------------------------------------------------------------- /Speeder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- Animation workbench 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | from say import * 11 | import math 12 | 13 | __vers__= '0.2' 14 | __dir__ = os.path.dirname(__file__) 15 | 16 | 17 | def createSpeeder(name='My_Speeder',target=None,src=None): 18 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 19 | 20 | obj.addProperty("App::PropertyLink","target","Base","") 21 | obj.target=target 22 | obj.addProperty("App::PropertyLinkList","targets","Base","") 23 | obj.addProperty("App::PropertyLinkList","followers","Base","") 24 | 25 | obj.addProperty("App::PropertyFloat","time","Base","") 26 | obj.time=0 27 | obj.addProperty("App::PropertyEnumeration","mode","Functions","").mode=['forward','backward','quadratic','sine wave','fade','ping pong','expression'] 28 | obj.mode='expression' 29 | 30 | obj.addProperty("App::PropertyString","trafo","Functions","") 31 | obj.addProperty("App::PropertyFloat","a","FunctionParameter","") 32 | obj.addProperty("App::PropertyFloat","b","FunctionParameter","") 33 | obj.addProperty("App::PropertyFloat","c","FunctionParameter","") 34 | obj.addProperty("App::PropertyFloat","d","FunctionParameter","") 35 | obj.addProperty("App::PropertyFloat","m","FunctionParameter","") 36 | obj.addProperty("App::PropertyFloat","g","FunctionParameter","") 37 | 38 | obj.a=200 39 | obj.b=0.5 40 | obj.c=50 41 | obj.m=5 42 | obj.g=1 43 | 44 | obj.addProperty("App::PropertyString","expressiontrafo","Functions","") 45 | # ping pong 46 | obj.expressiontrafo="100*2*time if time <0.5 else 100 - 100*2*(time-0.5)" 47 | # quadradic 48 | obj.expressiontrafo="a*(time-b)**2 + c" 49 | 50 | # hide info 51 | obj.setEditorMode("expressiontrafo", 2) 52 | _Speeder(obj) 53 | _ViewProviderSpeeder(obj.ViewObject) 54 | obj.Proxy.updater=True 55 | return obj 56 | 57 | class _Speeder(Animation._Actor): 58 | 59 | def update(self): 60 | time=self.obj2.time 61 | try: 62 | say("update time=" + str(time) + ", "+ self.obj2.Label) 63 | except: 64 | say("update (ohne Label)") 65 | time==self.obj2.time 66 | 67 | a=self.obj2.a 68 | b=self.obj2.b 69 | c=self.obj2.c 70 | d=self.obj2.d 71 | newtime=eval(self.obj2.trafo) 72 | self.obj2.target.Proxy.step(newtime) 73 | self.obj2.target.Proxy.update() 74 | 75 | def t2nt(self,time): 76 | a=self.obj2.a 77 | b=self.obj2.b 78 | c=self.obj2.c 79 | d=self.obj2.d 80 | m=self.obj2.m 81 | g=self.obj2.g 82 | 83 | newtime=eval(self.obj2.trafo) 84 | say(str(time) +" " +self.obj2.trafo +" " + str(newtime)) 85 | return newtime 86 | 87 | def t2ntderive(self,time): 88 | a=self.obj2.a 89 | b=self.obj2.b 90 | c=self.obj2.c 91 | d=self.obj2.d 92 | m=self.obj2.m 93 | g=self.obj2.g 94 | 95 | newtime1=eval(self.obj2.trafo) 96 | time += 0.01 97 | newtime2=eval(self.obj2.trafo) 98 | newtime=(newtime2-newtime1)*m 99 | 100 | say(str(time) +" " +self.obj2.trafo +" derive " + str(newtime)) 101 | say(str(newtime1)) 102 | say(str(newtime2)) 103 | return newtime 104 | 105 | def t2ntforce(self,time): 106 | a=self.obj2.a 107 | b=self.obj2.b 108 | c=self.obj2.c 109 | d=self.obj2.d 110 | m=self.obj2.m 111 | g=self.obj2.g 112 | newtime1=eval(self.obj2.trafo) 113 | time += 0.01 114 | newtime2=eval(self.obj2.trafo) 115 | time -= 2*0.01 116 | newtime0=eval(self.obj2.trafo) 117 | 118 | newtime=(newtime2-2*newtime1+newtime0)/0.01*g 119 | 120 | say(str(time) +" " +self.obj2.trafo +" force " + str(newtime)) 121 | return newtime 122 | 123 | 124 | 125 | def step(self,now): 126 | # say("step "+str(now) + str(self)) 127 | self.obj2.time=float(now)/100 128 | 129 | def onChanged(self,obj,prop): 130 | if prop=='mode': 131 | say("onChanged mode" + str(self)) 132 | say(obj.mode) 133 | # hier formel tauschen 134 | if obj.mode== 'ping pong': 135 | obj.trafo="a*time/b if time ".join(l2)) 45 | 46 | def interpol2(filename,show=True): 47 | ''' interpolate data from filename_out.txt to filename_post.txt''' 48 | 49 | filename2=filename + "_out.txt" 50 | tv=[] 51 | xv=[] 52 | yv=[] 53 | zv=[] 54 | 55 | rx=[] 56 | ry=[] 57 | rz=[] 58 | ra=[] 59 | 60 | for line in open(filename + "_out.txt", "r"): 61 | line=line.rstrip('\r\n') 62 | ll= line.split(' ') 63 | if ll[0] == '#': 64 | continue 65 | llf=[] 66 | for z in ll: 67 | llf.append(float(z)) 68 | 69 | tv.append(llf[0]) 70 | xv.append(llf[1]) 71 | yv.append(llf[2]) 72 | zv.append(llf[3]) 73 | 74 | rx.append(llf[4]) 75 | ry.append(llf[5]) 76 | rz.append(llf[6]) 77 | ra.append(llf[7]) 78 | 79 | # interpolate 80 | import numpy as np 81 | import scipy 82 | from scipy.interpolate import interp1d 83 | #import matplotlib.pyplot as plt 84 | 85 | fx = interp1d(tv, xv, ) 86 | fy = interp1d(tv, yv, ) 87 | fz = interp1d(tv, zv, ) 88 | frx = interp1d(tv, rx,) 89 | fry = interp1d(tv, ry, ) 90 | frz = interp1d(tv, rz, ) 91 | fra = interp1d(tv, ra, ) 92 | 93 | xnew = np.linspace(0, 0.99, num=100, endpoint=True) 94 | #try: 95 | if show: 96 | plt.plot(tv, xv, 'o',tv,yv,'+',tv,zv,'*') 97 | plt.plot( xnew, fx(xnew), '-', xnew, fy(xnew), '--',xnew, fz(xnew), '.-', ) 98 | # plt.legend(['aaa','x','y','z'], loc='best') 99 | plt.title('Placement Interpolation Data') 100 | plt.xlabel('time relative') 101 | plt.ylabel('Placement Base') 102 | plt.savefig(filename +'.png') 103 | # plt.show() 104 | import ImageGui 105 | ImageGui.open(filename +'.png') 106 | #except: 107 | # pass 108 | 109 | # export data 110 | fout = open(filename + "_post.txt",'w') 111 | for t in xnew: 112 | try: 113 | l=' '.join(str(k) for k in [t,fx(t),fy(t),fz(t),frx(t),fry(t),frz(t),fra(t)]) 114 | fout.write(l+'\n') 115 | except: 116 | pass 117 | fout.close() 118 | #return [fx,fy,fz] 119 | 120 | 121 | 122 | def createTrackReader(name,target,filename): 123 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 124 | 125 | obj.addProperty("App::PropertyLink","target","Base","") 126 | obj.target=target 127 | obj.addProperty("App::PropertyString","filename","Base","") 128 | obj.filename=filename 129 | obj.addProperty("App::PropertyFloat","time","Base","") 130 | obj.time=0.0 131 | obj.addProperty("App::PropertyPlacement","Placement","Results","") 132 | obj.Placement=FreeCAD.Placement() 133 | 134 | _TrackReader(obj) 135 | _ViewProviderTrackReader(obj.ViewObject) 136 | return obj 137 | 138 | class _TrackReader(Animation._Actor): 139 | 140 | def __init__(self,obj): 141 | obj.Proxy = self 142 | self.obj2 = obj 143 | self.Lock=False 144 | self.Changed=False 145 | self.path={} 146 | self.loadtrack() 147 | 148 | 149 | 150 | def loadtrack(self): 151 | interpol2(self.obj2.filename,False) 152 | for line in open(self.obj2.filename + "_post.txt", "r"): 153 | line=line.rstrip('\r\n') 154 | ll= line.split(' ') 155 | self.path[float(ll[0])]=FreeCAD.Placement( 156 | FreeCAD.Vector(float(ll[1]),float(ll[2]),float(ll[3])), 157 | FreeCAD.Vector(float(ll[4]),float(ll[5]),float(ll[6])), 158 | float(ll[7])*180/math.pi) 159 | print(self.path) 160 | 161 | def showtrack(self): 162 | interpol2(self.obj2.filename,True) 163 | for line in open(self.obj2.filename + "_post.txt", "r"): 164 | line=line.rstrip('\r\n') 165 | ll= line.split(' ') 166 | self.path[float(ll[0])]=FreeCAD.Placement( 167 | FreeCAD.Vector(float(ll[1]),float(ll[2]),float(ll[3])), 168 | FreeCAD.Vector(float(ll[4]),float(ll[5]),float(ll[6])), 169 | float(ll[7])*180/math.pi) 170 | print(self.path) 171 | 172 | 173 | def showtrack(self): 174 | interpol2(self.obj2.filename,True) 175 | for line in open(self.obj2.filename + "_post.txt", "r"): 176 | line=line.rstrip('\r\n') 177 | ll= line.split(' ') 178 | self.path[float(ll[0])]=FreeCAD.Placement( 179 | FreeCAD.Vector(float(ll[1]),float(ll[2]),float(ll[3])), 180 | FreeCAD.Vector(float(ll[4]),float(ll[5]),float(ll[6])), 181 | float(ll[7])*180/math.pi) 182 | print(self.path) 183 | 184 | 185 | def execute(self,obj): 186 | 187 | if self.Changed: 188 | say("self changed") 189 | self.Changed=False 190 | return 191 | if not self.Lock: 192 | self.obj2=obj 193 | self.Lock=True 194 | try: 195 | self.update() 196 | except: 197 | sayexc('update') 198 | self.Lock=False 199 | 200 | # 201 | # main execution detail 202 | # 203 | def update(self): 204 | say("update ") 205 | import math 206 | time=self.obj2.time 207 | say(str(time)) 208 | pl=self.path[time] 209 | self.obj2.target.Placement=pl 210 | self.obj2.Placement=pl 211 | 212 | def __getstate__(self): 213 | return None 214 | 215 | def __setstate__(self,state): 216 | return None 217 | 218 | def onChanged(self,obj,prop): 219 | pass 220 | 221 | def onBeforeChange(self,obj,prop): 222 | pass 223 | 224 | def initialize(self): 225 | pass 226 | 227 | def step(self,now): 228 | self.obj2.time=float(now)/100 229 | 230 | class _ViewProviderTrackReader(Animation._ViewProviderActor): 231 | 232 | def getIcon(self): 233 | return __dir__ +'/icons/icon3.svg' 234 | 235 | def attach(self,vobj): 236 | say("attach " + str(vobj.Object.Label)) 237 | self.emenu=[["Reload Track",self.loadtrack],["Show Track",self.showtrack]] 238 | self.cmenu=[] 239 | self.Object = vobj.Object 240 | self.obj2=self.Object 241 | self.Object.Proxy.Lock=False 242 | self.Object.Proxy.Changed=False 243 | return 244 | 245 | def setupContextMenu(self, obj, menu): 246 | action = menu.addAction("About ") 247 | action.triggered.connect(self.showVersion) 248 | action = menu.addAction("Track Reader ...") 249 | action.triggered.connect(self.edit) 250 | 251 | def edit(self): 252 | self.dialog=EditWidget(self,self.emenu) 253 | self.dialog.show() 254 | 255 | def showVersion(self): 256 | QtGui.QMessageBox.information(None, "About ", "Animation Track Reader Node\n2015 microelly\nVersion " + __vers__ ) 257 | 258 | def loadtrack(self): 259 | self.obj2.Proxy.loadtrack() 260 | 261 | def showtrack(self): 262 | self.obj2.Proxy.showtrack() 263 | 264 | def dialer(self): 265 | ''' shows the position at the dialer time''' 266 | self.obj2.time=float(self.widget.dial.value())/100 267 | say("dialer self time:" + str(self.obj2.time)) 268 | try: 269 | say(self.obj2.Proxy.path[round(self.obj2.time,2)]) 270 | self.obj2.target.Placement=self.obj2.Proxy.path[round(self.obj2.time,2)] 271 | except: 272 | pass 273 | FreeCAD.ActiveDocument.recompute() 274 | 275 | 276 | 277 | 278 | class _Function(Animation._Actor): 279 | 280 | def __init__(self,obj): 281 | obj.Proxy = self 282 | self.obj2 = obj 283 | self.Lock=False 284 | self.Changed=False 285 | self.path={} 286 | self.loadtrack() 287 | 288 | 289 | def loadtrack(self): 290 | 291 | # interpolate 292 | import numpy as np 293 | import scipy 294 | from scipy.interpolate import interp1d 295 | #import matplotlib.pyplot as plt 296 | 297 | wire=self.obj2.source.Shape 298 | 299 | 300 | 301 | if self.obj2.target==None: 302 | self.obj2.target=Draft.makeCircle(5) 303 | self.obj2.target.Label ="anim target for "+ self.obj2.source.Label 304 | 305 | # hier andere modi einbauen z. B. Endpunkte der edges #+# 306 | 307 | if self.obj2.usePoints: 308 | w=wire 309 | pts=[v.Point for v in w.Vertexes] 310 | else: 311 | pts=wire.discretize(self.obj2.count) 312 | 313 | tx=[p.x for p in pts] 314 | ty=[p.y for p in pts] 315 | tz=[p.z for p in pts] 316 | self.obj2.xlist=tx 317 | self.obj2.ylist=ty 318 | self.obj2.zlist=tz 319 | xmin=min(tx) 320 | tx=(np.array(tx)-xmin) 321 | xmax=max(tx) 322 | tx /= xmax 323 | 324 | # zmin=min(tz) 325 | # tz=(np.array(tz)-zmin) 326 | # zmax=max(tz) 327 | # tz /= zmax 328 | 329 | # siehe https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.interp1d.html 330 | 331 | 332 | fx = interp1d(tx,ty,kind=self.obj2.kindInterpolation) 333 | fz = interp1d(tx,tz,kind=self.obj2.kindInterpolation) 334 | 335 | self.fx=fx 336 | self.xmin=xmin 337 | self.xmax=xmax 338 | ptsa=[FreeCAD.Vector((0.01*i*(xmax))+xmin,self.obj2.a*fx(0.01*i)+self.obj2.b, 339 | self.obj2.a*fz(0.01*i)+self.obj2.b,) for i in range(101)] 340 | #Draft.makeWire(ptsa) 341 | pol=Part.makePolygon(ptsa) 342 | try: self.k1.Shape=pol 343 | except: 344 | Part.show(pol) 345 | self.k1=App.ActiveDocument.ActiveObject 346 | self.k1.Label="cartesian Map for "+ self.obj2.source.Label 347 | 348 | 349 | # polare Darstellung 350 | ptsa=[FreeCAD.Vector(np.cos(np.pi*i/180),np.sin(np.pi*i/180),0)*(self.obj2.a*fx(1.0/360*i)+self.obj2.b) for i in range(361)] 351 | #Draft.makeWire(ptsa) 352 | pol=Part.makePolygon(ptsa) 353 | try: self.k2.Shape=pol 354 | except: 355 | Part.show(pol) 356 | self.k2=App.ActiveDocument.ActiveObject 357 | self.k2.Label="polar Map for "+ self.obj2.source.Label 358 | 359 | 360 | 361 | 362 | def execute(self,obj): 363 | 364 | if self.Changed: 365 | say("self changed") 366 | self.Changed=False 367 | return 368 | if not self.Lock: 369 | self.obj2=obj 370 | self.Lock=True 371 | try: 372 | self.update() 373 | except: 374 | sayexc('update') 375 | self.Lock=False 376 | 377 | def onChanged(self,obj,prop): 378 | if prop in ['source','count','a','b']: 379 | self.loadtrack() 380 | if prop in ['time','count']: 381 | self.update() 382 | 383 | # 384 | # main execution detail 385 | # 386 | def update(self): 387 | say("update ") 388 | import math 389 | time=self.obj2.time/100 390 | say(str(time)) 391 | if self.obj2.mode=='cartesian': 392 | pl=FreeCAD.Vector((time*self.xmax)+self.xmin,self.obj2.a*self.fx(time)+self.obj2.b) 393 | if self.obj2.mode=='polar': 394 | # pl=FreeCAD.Vector((time*self.xmax)+self.xmin,self.fx(time)) 395 | pl=FreeCAD.Vector(np.cos(np.pi*time*2),np.sin(np.pi*time*2),0)*(self.obj2.a*self.fx(time)+self.obj2.b) 396 | if self.obj2.target != None: 397 | self.obj2.target.Placement.Base=pl 398 | self.obj2.target.purgeTouched() 399 | #self.obj2.Placement=pl 400 | 401 | def __getstate__(self): 402 | return None 403 | 404 | def __setstate__(self,state): 405 | return None 406 | 407 | 408 | 409 | def onBeforeChange(self,obj,prop): 410 | pass 411 | 412 | def initialize(self): 413 | pass 414 | 415 | def step(self,now): 416 | self.obj2.time=float(now) 417 | 418 | class _ViewProviderFunction(Animation._ViewProviderActor): 419 | 420 | def getIcon(self): 421 | return __dir__ +'/icons/icon3.svg' 422 | 423 | def attach(self,vobj): 424 | say("attach " + str(vobj.Object.Label)) 425 | self.emenu=[["Reload Track",self.loadtrack],["Show Track",self.showtrack]] 426 | self.cmenu=[] 427 | self.Object = vobj.Object 428 | self.obj2=self.Object 429 | self.Object.Proxy.Lock=False 430 | self.Object.Proxy.Changed=False 431 | return 432 | 433 | def setupContextMenu(self, obj, menu): 434 | action = menu.addAction("About ") 435 | action.triggered.connect(self.showVersion) 436 | action = menu.addAction("Update Graph ...") 437 | action.triggered.connect(self.Object.Proxy.loadtrack) 438 | 439 | def edit(self): 440 | self.dialog=EditWidget(self,self.emenu) 441 | self.dialog.show() 442 | 443 | def showVersion(self): 444 | QtGui.QMessageBox.information(None, "About ", "Animation Track Reader Node\n2015 microelly\nVersion " + __vers__ ) 445 | 446 | def loadtrack(self): 447 | self.obj2.Proxy.loadtrack() 448 | 449 | def showtrack(self): 450 | self.obj2.Proxy.showtrack() 451 | 452 | def dialer(self): 453 | ''' shows the position at the dialer time''' 454 | self.obj2.time=float(self.widget.dial.value())/100 455 | say("dialer self time:" + str(self.obj2.time)) 456 | try: 457 | say(self.obj2.Proxy.path[round(self.obj2.time,2)]) 458 | self.obj2.target.Placement=self.obj2.Proxy.path[round(self.obj2.time,2)] 459 | except: 460 | pass 461 | FreeCAD.ActiveDocument.recompute() 462 | 463 | 464 | def runTA(): 465 | print("I'm TA") 466 | name="MyFunction" 467 | 468 | 469 | #def createTrackReader(name,target,filename): 470 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 471 | 472 | target=None 473 | obj.addProperty("App::PropertyLink","target","Base","") 474 | obj.addProperty("App::PropertyLink","source","Base","") 475 | 476 | #obj.source=App.ActiveDocument.Sketch 477 | obj.source=Gui.Selection.getSelection()[0] 478 | # obj.addProperty("App::PropertyLink","circle","Base","") 479 | obj.target=target 480 | # obj.addProperty("App::PropertyString","filename","Base","") 481 | #obj.filename=filename 482 | obj.addProperty("App::PropertyFloat","time","Base","") 483 | obj.time=0.0 484 | obj.addProperty("App::PropertyFloat","a","F=a*f+b","").a=1 485 | obj.addProperty("App::PropertyFloat","b","F=a*f+b","").b=0 486 | obj.addProperty("App::PropertyInteger","count","","").count=40 487 | 488 | obj.addProperty("App::PropertyPlacement","Placement","_comp","") 489 | obj.Placement=FreeCAD.Placement() 490 | obj.addProperty("App::PropertyEnumeration","mode","Base").mode=["cartesian","polar"] 491 | obj.addProperty("App::PropertyFloatList", "xlist", "_comp", "end") 492 | obj.addProperty("App::PropertyFloatList", "ylist", "_comp", "end") 493 | obj.addProperty("App::PropertyFloatList", "zlist", "_comp", "end") 494 | obj.addProperty("App::PropertyBool", "usePoints", "", "interpolate points").usePoints=True 495 | obj.addProperty("App::PropertyEnumeration","kindInterpolation","Base").kindInterpolation=['cubic','linear', 'nearest', 'zero', 'slinear', 'quadratic', ] 496 | 497 | 498 | 499 | _Function(obj) 500 | _ViewProviderFunction(obj.ViewObject) 501 | obj.Label="Interpolator for "+ obj.source.Label 502 | return obj 503 | -------------------------------------------------------------------------------- /VertexTracker.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- animation workbench vertex tracker 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | import FreeCAD,PySide,os,FreeCADGui 11 | from PySide import QtCore, QtGui, QtSvg 12 | from PySide.QtGui import * 13 | import Part 14 | import Draft 15 | 16 | 17 | #---------- 18 | 19 | 20 | import math,os 21 | 22 | import FreeCAD, Animation, PySide 23 | from Animation import say,sayErr,sayexc 24 | from EditWidget import EditNoDialWidget 25 | import Toucher 26 | reload(Toucher) 27 | 28 | __vers__='0.1 06.12.2015' 29 | __dir__ = os.path.dirname(__file__) 30 | 31 | 32 | def createVertexTracker(name,src=None,filename="/tmp/tracker"): 33 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 34 | obj.addProperty("App::PropertyString","filename","Base","").filename=filename 35 | obj.addProperty("App::PropertyLink","src","Base","").src=src 36 | obj.addProperty("App::PropertyFloat","time","Base","").time=0 37 | 38 | _VertexTracker(obj) 39 | _ViewProviderVertexTracker(obj.ViewObject) 40 | return obj 41 | 42 | class _VertexTracker(Animation._Actor): 43 | ''' track the time/placement of src to filename ''' 44 | 45 | def update(self): 46 | print("update VERTEX Tracker ") 47 | self.run(self.obj2.src) 48 | 49 | def step(self,now): 50 | say("step "+str(now) + str(self)) 51 | self.obj2.time=float(now)/100 52 | 53 | 54 | #----------------------------------------- 55 | 56 | def addpoint(self,point): 57 | try: 58 | self.threads 59 | except: 60 | self.threads={} 61 | fcount=len(self.threads) 62 | dist=1.5 63 | for f in self.threads: 64 | print(f, self.threads[f]) 65 | t=self.threads[f] 66 | if point.distanceToPoint(t[-1]) < dist: 67 | print( "found") 68 | self.threads[f].append(point) 69 | return self.threads[f] 70 | print("not found") 71 | self.threads[fcount]=[point] 72 | return self.threads[fcount] 73 | 74 | 75 | def run(self,s): 76 | say(s.Label) 77 | print(s.Shape) 78 | say(s.Shape.Vertexes) 79 | i=0 80 | for v in s.Shape.Vertexes: 81 | i += 1 82 | if i > 5: break 83 | say(["Point: ", v.Point]) 84 | FreeCADGui.updateGui() 85 | self.addpoint(v.Point) 86 | 87 | def show(self): 88 | for f in self.threads: 89 | print(f) 90 | for p in self.threads[f]: 91 | print(" ",p) 92 | 93 | def gen(self): 94 | for f in self.threads: 95 | print(f) 96 | if self.isOnePoint(self.threads[f]): 97 | p=FreeCAD.ActiveDocument.addObject("Part::Vertex","Vertex") 98 | p.Placement.Base=self.threads[f][0] 99 | else: 100 | Draft.makeWire(self.threads[f]) 101 | 102 | def isOnePoint(self,f): 103 | if len(f)==0: 104 | return False 105 | sp=f[0] 106 | for p in f: 107 | if p != sp: 108 | return False 109 | return True 110 | 111 | #---------------------------------------- 112 | 113 | 114 | 115 | 116 | class _ViewProviderVertexTracker(Animation._ViewProviderActor): 117 | 118 | def __init__(self,vobj): 119 | say(self) 120 | Animation._ViewProviderActor.__init__(self,vobj) 121 | self.attach(vobj) 122 | 123 | def getIcon(self): 124 | return '/usr/lib/freecad/Mod/Animation/' +'/icons/icon2.svg' 125 | return __dir__ +'/icons/icon2.svg' 126 | 127 | def attach(self,vobj): 128 | self.emenu=[["Show Path Data",self.Object.Proxy.show],["Generate Path",self.Object.Proxy.gen]] 129 | self.cmenu=self.emenu 130 | say("attach " + str(vobj.Object.Label)) 131 | self.Object = vobj.Object 132 | self.obj2=self.Object 133 | self.Object.Proxy.Lock=False 134 | self.Object.Proxy.Changed=False 135 | return 136 | 137 | def edit(self): 138 | self.dialog=EditNoDialWidget(self,self.emenu) 139 | self.dialog.show() 140 | 141 | def showVersion(self): 142 | cl=self.Object.Proxy.__class__.__name__ 143 | PySide.QtGui.QMessageBox.information(None, "About ", "Animation" + cl +" Node\nVersion " + __vers__ ) 144 | 145 | def showpath(self): 146 | ''' path as Part.polygon ''' 147 | FreeCAD.s=self 148 | points=self.Object.Proxy.path 149 | for p in self.Object.Proxy.path: 150 | say(str(p)) 151 | pp=Part.makePolygon(points) 152 | Part.show(pp) 153 | FreeCAD.ActiveDocument.recompute() 154 | return FreeCAD.activeDocument().ActiveObject 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /animationlib.py: -------------------------------------------------------------------------------- 1 | import numpy, os 2 | import FreeCAD 3 | import FreeCADGui 4 | from PySide import QtGui 5 | 6 | __dir__ = os.path.dirname(__file__) -------------------------------------------------------------------------------- /animationwb/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/animationwb/__init__.py -------------------------------------------------------------------------------- /animationwb/compounds.py: -------------------------------------------------------------------------------- 1 | import FreeCAD 2 | import FreeCADGui 3 | 4 | 5 | 6 | def run(): 7 | print "animationwb.compounds.run" 8 | 9 | 10 | 11 | 12 | def delete(): 13 | s=FreeCADGui.Selection.getSelection() 14 | comp=s[-1] 15 | unlinks=s[:-1] 16 | links=comp.Links 17 | linksnew=[] 18 | for l in links: 19 | if l not in unlinks: 20 | linksnew += [l] 21 | comp.Links=linksnew 22 | 23 | 24 | def add(): 25 | s=FreeCADGui.Selection.getSelection() 26 | comp=s[-1] 27 | addlinks=s[:-1] 28 | links=comp.Links 29 | for l in addlinks: 30 | if l not in links: 31 | links += [l] 32 | comp.Links=links 33 | 34 | 35 | 36 | def create(): 37 | s=FreeCADGui.Selection.getSelection() 38 | comp=FreeCAD.ActiveDocument.addObject("Part::Compound","Compound") 39 | comp.Links=s 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /animplacement.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- 4 | #-- 5 | #-- microelly 2015 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | 11 | import FreeCAD,PySide,os,FreeCADGui 12 | from PySide import QtCore, QtGui, QtSvg 13 | from PySide.QtGui import * 14 | 15 | __vers__='0.1' 16 | 17 | try: 18 | __dir__ = os.path.dirname(__file__) 19 | say(__dir__) 20 | except: 21 | __dir__='/usr/lib/freecad/Mod/mylib' 22 | 23 | def say(s): 24 | FreeCAD.Console.PrintMessage(str(s)+"\n") 25 | 26 | def saye(s): 27 | FreeCAD.Console.PrintError(str(s)+"\n") 28 | 29 | import FreeCAD,os,time,sys,traceback 30 | 31 | def sayexc(mess=''): 32 | exc_type, exc_value, exc_traceback = sys.exc_info() 33 | ttt=repr(traceback.format_exception(exc_type, exc_value,exc_traceback)) 34 | lls=eval(ttt) 35 | l=len(lls) 36 | l2=lls[(l-3):] 37 | FreeCAD.Console.PrintError(mess + "\n" +"--> ".join(l2)) 38 | 39 | classname='AnimPlacement' 40 | 41 | def create(name,target,src=None): 42 | obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) 43 | c3=obj 44 | 45 | c3.addProperty("App::PropertyLink","target","Base","") 46 | c3.target=target 47 | c3.addProperty("App::PropertyLink","src","Base","") 48 | c3.src=src 49 | c3.addProperty("App::PropertyFloat","time","Base","") 50 | c3.time=0.3 51 | 52 | c3.addProperty("App::PropertyPlacement","Placement","Results","") 53 | c3.Placement=FreeCAD.Placement() 54 | 55 | 56 | # parameter 57 | c3.addProperty("App::PropertyFloat","x0","Parameter","") 58 | c3.x0=0 59 | c3.addProperty("App::PropertyFloat","x1","Parameter","") 60 | c3.x1=200 61 | 62 | c3.addProperty("App::PropertyFloat","y0","Parameter","") 63 | c3.y0=0 64 | c3.addProperty("App::PropertyFloat","y1","Parameter","") 65 | c3.y1=0 66 | 67 | c3.addProperty("App::PropertyFloat","z0","Parameter","") 68 | c3.z0=0 69 | c3.addProperty("App::PropertyFloat","z1","Parameter","") 70 | c3.z1=0 71 | 72 | c3.addProperty("App::PropertyFloat","arc0","Parameter","") 73 | c3.arc0=0 74 | c3.addProperty("App::PropertyFloat","arc1","Parameter","") 75 | c3.arc1=90 76 | 77 | c3.addProperty("App::PropertyVector","RotCenter","Parameter","") 78 | c3.RotCenter=FreeCAD.Vector(5,5,0) 79 | 80 | c3.addProperty("App::PropertyVector","RotAxis","Parameter","") 81 | c3.RotAxis=FreeCAD.Vector(0,0,1) 82 | 83 | # functions 84 | c3.addProperty("App::PropertyString","x","Functions","") 85 | c3.x="x0+(x1-x0)*time" 86 | c3.addProperty("App::PropertyString","y","Functions","") 87 | c3.y="0" 88 | c3.addProperty("App::PropertyString","z","Functions","") 89 | c3.z="0" 90 | c3.addProperty("App::PropertyString","arc","Functions","") 91 | c3.arc="time*360" 92 | 93 | _AnimPlacement(obj) 94 | _ViewProviderAnimPlacement(obj.ViewObject) 95 | c3.Proxy.updater=True 96 | return obj 97 | 98 | class _AnimPlacement(): 99 | 100 | def __init__(self,obj): 101 | obj.Proxy = self 102 | self.Type = "_AnimPlacement" 103 | self.obj2 = obj 104 | self.Lock=False 105 | self.Changed=False 106 | 107 | def execute(self,obj): 108 | if self.obj2.ViewObject.Visibility == False: 109 | return 110 | 111 | if self.Changed: 112 | say("self changed") 113 | # ignore self changes 114 | self.Changed=False 115 | return 116 | if not self.Lock: 117 | say("set Lock ----- " +str(obj.Label)) 118 | self.obj2=obj 119 | self.Lock=True 120 | try: 121 | self.update() 122 | except: 123 | sayexc('update') 124 | self.Lock=False 125 | say("unset Lock +++ " +str(self.obj2.Label)) 126 | 127 | def update(self): 128 | say("update ") 129 | import math 130 | time=self.obj2.time 131 | say(str(time)) 132 | x0=self.obj2.x0 133 | x1=self.obj2.x1 134 | y0=self.obj2.y0 135 | y1=self.obj2.y1 136 | z0=self.obj2.z0 137 | z1=self.obj2.z1 138 | arc0=self.obj2.arc0 139 | arc1=self.obj2.arc1 140 | 141 | try: 142 | sx=self.obj2.src.Placement.Base.x 143 | sy=self.obj2.src.Placement.Base.y 144 | sz=self.obj2.src.Placement.Base.z 145 | 146 | srx=self.obj2.src.Placement.Rotation.Axis.x 147 | sry=self.obj2.src.Placement.Rotation.Axis.y 148 | srz=self.obj2.src.Placement.Rotation.Axis.z 149 | sarc=self.obj2.src.Placement.Rotation.Angle 150 | except: 151 | saye("keine src festgelegt") 152 | 153 | xv=eval(self.obj2.x) 154 | yv=eval(self.obj2.y) 155 | zv=eval(self.obj2.z) 156 | arcv=eval(self.obj2.arc) 157 | 158 | rot=FreeCAD.Rotation(self.obj2.RotAxis,arcv) 159 | pl=FreeCAD.Placement(FreeCAD.Vector(xv,yv,zv),rot,self.obj2.RotCenter) 160 | say(pl) 161 | if str(self.obj2.target.TypeId) == 'App::Annotation': 162 | self.obj2.target.Position=(xv,yv,zv) 163 | else: 164 | self.obj2.target.Placement=pl 165 | self.obj2.Placement=pl 166 | 167 | def __getstate__(self): 168 | say("getstate " + str(self)) 169 | return None 170 | 171 | def __setstate__(self,state): 172 | say("setstate " + str(self) + str(state)) 173 | return None 174 | 175 | def onChanged(self,obj,prop): 176 | pass 177 | # say("on Changed") 178 | # say(obj) 179 | # say(prop) 180 | 181 | def onBeforeChange(self,obj,prop): 182 | pass 183 | # say("on before change") 184 | 185 | def initialize(self): 186 | say("initialize") 187 | 188 | 189 | def step(self,now): 190 | say("step XX") 191 | say(now) 192 | self.obj2.time=float(now)/100 193 | say(self) 194 | 195 | class _ViewProviderAnimPlacement(object): 196 | 197 | def getIcon(self): 198 | return __dir__ +'/icons/sun.png' 199 | 200 | def __init__(self,vobj): 201 | say("__init__" + str(self)) 202 | self.Object = vobj.Object 203 | vobj.Proxy = self 204 | 205 | def attach(self,vobj): 206 | say("attach " + str(vobj.Object.Label)) 207 | self.Object = vobj.Object 208 | self.obj2=self.Object 209 | # if not hasattr(self.Object.Proxy,"Lock"): 210 | # self.Object.Proxy.Lock=False 211 | # say("lock gesetzt") 212 | self.Object.Proxy.Lock=False 213 | self.Object.Proxy.Changed=False 214 | return 215 | 216 | def claimChildren(self): 217 | return self.Object.Group 218 | 219 | def __getstate__(self): 220 | say("getstate " + str(self)) 221 | return None 222 | 223 | def __setstate__(self,state): 224 | say("setstate " + str(self) + str(state)) 225 | return None 226 | 227 | def setEdit(self,vobj,mode=0): 228 | s=TimeWidget(self) 229 | self.dialog=s 230 | self.dialog.show() 231 | say("set Edit") 232 | return True 233 | 234 | def unsetEdit(self,vobj,mode=0): 235 | return False 236 | 237 | def doubleClicked(self,vobj): 238 | say("double clicked") 239 | self.setEdit(vobj,1) 240 | 241 | def setupContextMenu(self, obj, menu): 242 | # action = menu.addAction("About VertexPlugger") 243 | # action.triggered.connect(self.showVersion) 244 | 245 | action = menu.addAction("Animate ...") 246 | action.triggered.connect(self.edit) 247 | 248 | def edit(self): 249 | self.dialog=TimeWidget(self) 250 | self.dialog.show() 251 | 252 | def showVersion(self): 253 | QtGui.QMessageBox.information(None, "About ", "Animation Placement Node\n2015 microelly\nVersion " + __vers__ +"\nstill alpha") 254 | 255 | def dreher(self): 256 | self.obj2.time=float(self.widget.dial.value())/100 257 | FreeCAD.ActiveDocument.recompute() 258 | 259 | 260 | class TimeWidget(QtGui.QWidget): 261 | def __init__(self, obj,*args): 262 | QtGui.QWidget.__init__(self, *args) 263 | obj.widget=self 264 | self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) 265 | self.vollabel = QtGui.QLabel(obj.Object.Label) 266 | 267 | self.pushButton02 = QtGui.QPushButton() 268 | self.pushButton02.setText("close") 269 | self.pushButton02.clicked.connect(self.hide) 270 | 271 | dial = QDial() 272 | dial.setNotchesVisible(True) 273 | self.dial=dial 274 | dial.setMaximum(100) 275 | dial.valueChanged.connect(obj.dreher); 276 | layout = QHBoxLayout() 277 | 278 | layout = QtGui.QGridLayout() 279 | layout.addWidget(self.vollabel, 0, 0) 280 | 281 | layout.addWidget(self.pushButton02, 15, 0,1,4) 282 | layout.addWidget(dial,3,0) 283 | 284 | self.setLayout(layout) 285 | self.setWindowTitle(obj.Object.target.Label) 286 | 287 | 288 | ''' 289 | 290 | The next generation of animation tools will support formulas and 291 | allow to move the timeline forward an backward by hand 292 | 293 | ''' 294 | 295 | if __name__ == "__main__": 296 | 297 | # All examples from top view to the xy-plane 298 | 299 | # Example 1 300 | box=App.ActiveDocument.addObject("Part::Box","Bax") 301 | t=create("Anim "+box.Label,box) 302 | box.ViewObject.ShapeColor=(.0,1.0,.0) 303 | # linear function - left upper corner to right bottom 304 | t.x0=-150 305 | t.x1=150 306 | t.y0=150 307 | t.y1=-150 308 | t.y="y0+(y1-y0)*time" 309 | t.z="100 - 400 * (0.5-time)**2" 310 | 311 | 312 | 313 | # Example 2 314 | box1=App.ActiveDocument.addObject("Part::Cone","Bux") 315 | box1.ViewObject.ShapeColor=(1.0,.0,.0) 316 | t1=create("Anim "+box1.Label,box1) 317 | t1.x0=-150 318 | t1.x1=150 319 | t1.y0=-150 320 | t1.y1=150 321 | # parabel - left bottom to right top 322 | t1.y="y0+(y1-y0)*time**2" 323 | t1.y 324 | t1.x 325 | 326 | 327 | 328 | # Example 3 329 | box3=App.ActiveDocument.addObject("Part::Cylinder","Circler") 330 | box3.ViewObject.ShapeColor=(1.0,.0,1.0) 331 | t3=create("Anim "+box3.Label,box3) 332 | # ellipse 333 | t3.y="80 * math.sin(math.pi*2*time)" 334 | t3.x="80 * math.cos(math.pi*2*time)" 335 | # t3.z="400 * (0.5-time)**2" 336 | t3.z="0" 337 | 338 | 339 | box3=App.ActiveDocument.addObject("Part::Sphere","Circler-helper") 340 | box3.ViewObject.ShapeColor=(1.0,.0,1.0) 341 | tt3=create("Anim "+box3.Label,box3,t3) 342 | # ellipse 343 | tt3.y="sx" 344 | tt3.x="sx" 345 | tt3.z="sz" 346 | 347 | # Example 4 348 | box4=App.ActiveDocument.addObject("Part::Cylinder","T1") 349 | box4.ViewObject.ShapeColor=(1.0,1.0,.0) 350 | t1=create("Anim "+box4.Label,box4,t3) 351 | # ellipse 352 | t1.y="87" 353 | t1.x="-50" 354 | t1.z="math.sqrt(195**2 - (sx+50)**2 - (sy-87)**2-5)" 355 | 356 | # Example 4 357 | box4=App.ActiveDocument.addObject("Part::Cylinder","T2") 358 | box4.ViewObject.ShapeColor=(1.0,1.0,.0) 359 | t1=create("Anim "+box4.Label,box4,t3) 360 | # ellipse 361 | t1.y="-87" 362 | t1.x="-50" 363 | t1.z="math.sqrt(195**2 - (sx+50)**2 - (sy+87)**2)-5" 364 | 365 | # Example 4 366 | box4=App.ActiveDocument.addObject("Part::Cylinder","T3") 367 | box4.ViewObject.ShapeColor=(1.0,1.0,.0) 368 | t1=create("Anim "+box4.Label,box4,t3) 369 | # ellipse 370 | t1.y="0" 371 | t1.x="100" 372 | t1.z="math.sqrt(195**2 - (sx-100)**2 - (sy)**2)-5" 373 | 374 | 375 | #math.sqrt(195**2 - (sx-100)**2 - (sy)**2) 376 | #math.sqrt(195**2 - (sx+50)**2 - (sy-87)**2) 377 | #math.sqrt(195**2 - (sx+50)**2 - (sy+87)**2) 378 | 379 | 380 | 381 | 382 | 383 | ''' 384 | # to use 385 | # 1. install latest version of animation workbench 386 | 387 | # 2. create objects (still without gui support) 388 | 389 | import animplacement 390 | 391 | box=App.ActiveDocument.addObject("Part::Box","My Box") 392 | animator=animplacement.create("A"+box.Label,box) 393 | animator.x ="time *100 + math.pi " # formula as string with math support 394 | 395 | # 3. double click the animator icon ... 396 | # and change time value with the dialer from 0 to 1 397 | 398 | ''' 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | -------------------------------------------------------------------------------- /flowlib.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | 4 | def force1(x,y,z,p,t=0): 5 | ''' force on place x,y,z under velocity p at time t ''' 6 | # no force if the speed is more than 5 7 | if np.max(np.abs(p))>5: 8 | return [0,0,0] 9 | 10 | return [0,0,0.5] 11 | 12 | 13 | 14 | def force2(x,y,z,p,t=0): 15 | 16 | # test force 17 | if t>70: 18 | return (0,0,0) 19 | 20 | if z>200 and x200 and x>=y: 24 | return (4,2,4) 25 | 26 | return (0,0,0.3) 27 | 28 | 29 | def damperX(x,y,z,p,t=0): 30 | alpha=np.arctan2(x,y) 31 | 32 | if alpha>0 and alpha1 and alpha<1.4: return(1,1,0.1) 34 | if z>20: 35 | return(0.4,0.4,0) 36 | 37 | return (0.99,1.0,0.99) 38 | 39 | 40 | def damper2(x,y,z,p,t=0): 41 | alpha=np.arctan2(x,y) 42 | 43 | if alpha>np.pi*1/3: return(1,1,0.5) 44 | if alpha<-np.pi*1/2: return(1,1,0.01) 45 | 46 | return (1,1,1) 47 | 48 | 49 | # drehen 50 | def force3(x,y,z,p,t=0): 51 | k=0.002 52 | m=0.0005 53 | #if x**2+y**2 >3600: 54 | if x**2+y**2 >100: 55 | return(k*y-m*x,-k*x-m*y,-0.5) 56 | else: 57 | return(k*y,-k*x,-0.2) 58 | return (0,0,-1) 59 | 60 | 61 | # ausbreiten und schnell fallen 62 | def force4(x,y,z,p,t=0): 63 | #return(0.,0,-1) 64 | return(0.01*y,0.01*x,-1) 65 | 66 | 67 | def nodamper(x,y,z,p,t=0): 68 | return (0.9,0.9,1) 69 | 70 | def simpleforce(x,y,z,p,t=0): 71 | if z<-20 and z>-50: 72 | return (-0.01*x, -0.01*y,-0.5) 73 | if z<=-70: 74 | return (0.01*np.sin(z*np.pi/20)*x, 0.01*np.sin(z*np.pi/20)*y,-0.1) 75 | return (0,0,-1) 76 | 77 | 78 | #------------------------- 79 | # mail vom 10.07. 80 | # angepasst auf negative hoehen 81 | 82 | def force4(x,y,z,p,t=0): 83 | if z<-10 and z>-30: 84 | return (0.1*x, 0.1*y,-0.1) 85 | if z<=-30 and z>-130: 86 | return (0,0,-0.5) 87 | if z<=-130 and z>-220: 88 | return (-0.1*x,-0.1*y,-0.1) 89 | return (0,0,-1) 90 | 91 | 92 | def nodamper(x,y,z,p,t=0): 93 | if z<-300: 94 | return (0,0,0) 95 | return (0.9,0.9,1) 96 | 97 | 98 | 99 | 100 | 101 | 102 | force=force4 103 | myforce=force4 104 | mydamper=damper2 105 | -------------------------------------------------------------------------------- /icons/abroller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/abroller.png -------------------------------------------------------------------------------- /icons/adjuster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/adjuster.png -------------------------------------------------------------------------------- /icons/animation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/animation.png -------------------------------------------------------------------------------- /icons/assembly2SolveConstraints.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/assembly2SolveConstraints.png -------------------------------------------------------------------------------- /icons/billboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/billboard.png -------------------------------------------------------------------------------- /icons/bounder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/bounder.png -------------------------------------------------------------------------------- /icons/caseaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/caseaction.png -------------------------------------------------------------------------------- /icons/collider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/collider.png -------------------------------------------------------------------------------- /icons/combiner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/combiner.png -------------------------------------------------------------------------------- /icons/comp_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/comp_add.png -------------------------------------------------------------------------------- /icons/comp_add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 23 | 25 | 29 | 33 | 34 | 45 | 56 | 58 | 62 | 66 | 67 | 78 | 85 | 96 | 103 | 110 | 112 | 116 | 120 | 121 | 132 | 139 | 150 | 152 | 156 | 160 | 161 | 168 | 179 | 181 | 185 | 189 | 190 | 197 | 199 | 203 | 207 | 208 | 219 | 226 | 237 | 239 | 243 | 247 | 248 | 255 | 266 | 268 | 272 | 276 | 277 | 288 | 295 | 297 | 301 | 305 | 306 | 317 | 319 | 323 | 327 | 328 | 335 | 342 | 343 | 363 | 370 | 371 | 373 | 374 | 376 | image/svg+xml 377 | 379 | 380 | 381 | 382 | [wmayer] 383 | 384 | 385 | Part_RuledSurface 386 | 2011-10-21 387 | http://www.freecadweb.org/wiki/index.php?title=Artwork 388 | 389 | 390 | FreeCAD 391 | 392 | 393 | FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_RuledSurface.svg 394 | 395 | 396 | FreeCAD LGPL2+ 397 | 398 | 399 | https://www.gnu.org/copyleft/lesser.html 400 | 401 | 402 | [agryson] Alexander Gryson 403 | 404 | 405 | 406 | 407 | 408 | 412 | 414 | 419 | 424 | 429 | 430 | 431 | 432 | -------------------------------------------------------------------------------- /icons/comp_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/comp_create.png -------------------------------------------------------------------------------- /icons/comp_create.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 23 | 25 | 29 | 33 | 34 | 45 | 56 | 58 | 62 | 66 | 67 | 78 | 85 | 96 | 103 | 110 | 112 | 116 | 120 | 121 | 132 | 139 | 150 | 152 | 156 | 160 | 161 | 168 | 179 | 181 | 185 | 189 | 190 | 197 | 199 | 203 | 207 | 208 | 219 | 226 | 237 | 239 | 243 | 247 | 248 | 255 | 266 | 268 | 272 | 276 | 277 | 288 | 295 | 297 | 301 | 305 | 306 | 317 | 319 | 323 | 327 | 328 | 335 | 342 | 343 | 363 | 370 | 371 | 373 | 374 | 376 | image/svg+xml 377 | 379 | 380 | 381 | 382 | [wmayer] 383 | 384 | 385 | Part_RuledSurface 386 | 2011-10-21 387 | http://www.freecadweb.org/wiki/index.php?title=Artwork 388 | 389 | 390 | FreeCAD 391 | 392 | 393 | FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_RuledSurface.svg 394 | 395 | 396 | FreeCAD LGPL2+ 397 | 398 | 399 | https://www.gnu.org/copyleft/lesser.html 400 | 401 | 402 | [agryson] Alexander Gryson 403 | 404 | 405 | 406 | 407 | 408 | 412 | 414 | 419 | 424 | 429 | 430 | 431 | 432 | -------------------------------------------------------------------------------- /icons/comp_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/comp_delete.png -------------------------------------------------------------------------------- /icons/connector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/connector.png -------------------------------------------------------------------------------- /icons/controlpanel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/controlpanel.png -------------------------------------------------------------------------------- /icons/delta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/delta.png -------------------------------------------------------------------------------- /icons/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/diagram.png -------------------------------------------------------------------------------- /icons/extruder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/extruder.png -------------------------------------------------------------------------------- /icons/falseaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/falseaction.png -------------------------------------------------------------------------------- /icons/filler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/filler.png -------------------------------------------------------------------------------- /icons/followme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/followme.png -------------------------------------------------------------------------------- /icons/gearing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/gearing.png -------------------------------------------------------------------------------- /icons/icon1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 59 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /icons/icon2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 59 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /icons/icon3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 59 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /icons/kardan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/kardan.png -------------------------------------------------------------------------------- /icons/loopaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/loopaction.png -------------------------------------------------------------------------------- /icons/manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/manager.png -------------------------------------------------------------------------------- /icons/mover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/mover.png -------------------------------------------------------------------------------- /icons/moviescreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/moviescreen.png -------------------------------------------------------------------------------- /icons/pather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/pather.png -------------------------------------------------------------------------------- /icons/photographer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/photographer.png -------------------------------------------------------------------------------- /icons/placer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/placer.png -------------------------------------------------------------------------------- /icons/plugger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/plugger.png -------------------------------------------------------------------------------- /icons/queryaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/queryaction.png -------------------------------------------------------------------------------- /icons/repeataction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/repeataction.png -------------------------------------------------------------------------------- /icons/reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/reset.png -------------------------------------------------------------------------------- /icons/rotator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/rotator.png -------------------------------------------------------------------------------- /icons/scaler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/scaler.png -------------------------------------------------------------------------------- /icons/scriptaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/scriptaction.png -------------------------------------------------------------------------------- /icons/snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/snapshot.png -------------------------------------------------------------------------------- /icons/snapshotviewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/snapshotviewer.png -------------------------------------------------------------------------------- /icons/speeder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/speeder.png -------------------------------------------------------------------------------- /icons/styler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/styler.png -------------------------------------------------------------------------------- /icons/sum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/sum.png -------------------------------------------------------------------------------- /icons/toucher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/toucher.png -------------------------------------------------------------------------------- /icons/tracker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/tracker.png -------------------------------------------------------------------------------- /icons/trackreader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/trackreader.png -------------------------------------------------------------------------------- /icons/tranq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/tranq.png -------------------------------------------------------------------------------- /icons/trueaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/trueaction.png -------------------------------------------------------------------------------- /icons/viewpoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/viewpoint.png -------------------------------------------------------------------------------- /icons/whileaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/whileaction.png -------------------------------------------------------------------------------- /mathplotlibNode.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- animation workbench 4 | #-- 5 | #-- microelly 2016 v 0.1 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | from __future__ import unicode_literals 10 | 11 | __vers__="08.04.2016 0.4" 12 | 13 | import sys 14 | import os 15 | import random 16 | import numpy as np 17 | import time 18 | 19 | __dir__ = os.path.dirname(__file__) 20 | 21 | 22 | #import matplotlib 23 | 24 | #matplotlib.use('Qt4Agg') 25 | #matplotlib.rcParams['backend.qt4']='PySide' 26 | 27 | #from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 28 | #from matplotlib.figure import Figure 29 | 30 | 31 | import say 32 | reload(say) 33 | from say import * 34 | 35 | import reconstruction 36 | reload (reconstruction.projectiontools) 37 | from reconstruction.projectiontools import * 38 | 39 | import reconstruction.miki as miki 40 | reload(miki) 41 | 42 | import Animation 43 | 44 | class _MPL(Animation._Actor): 45 | 46 | def __init__(self,obj): 47 | obj.Proxy = self 48 | self.Type = self.__class__.__name__ 49 | self.obj2 = obj 50 | self.vals={} 51 | _ViewProviderMPL(obj.ViewObject) 52 | 53 | 54 | def onChanged(self,obj,prop): 55 | # say(["onChanged " + str(self),obj,prop,obj.getPropertyByName(prop)]) 56 | if prop == 'countSources': 57 | for i in range(obj.countSources): 58 | try: 59 | obj.getPropertyByName('source'+str(i+1)+'Object') 60 | except: 61 | obj.addProperty('App::PropertyLink','source'+str(i+1)+'Object',"Source " + str(i+1)) 62 | obj.addProperty('App::PropertyString','source'+str(i+1)+'Data',"Source " + str(i+1)) 63 | obj.addProperty('App::PropertyFloatList','source'+str(i+1)+'Values',"Source " + str(i+1)) 64 | obj.addProperty('App::PropertyBool','source'+str(i+1)+'Off',"Source " + str(i+1)) 65 | exec("self.vals"+str(i+1)+"={}") 66 | for i in range(10): 67 | if i ".join(l2)) 74 | -------------------------------------------------------------------------------- /testcases/TestAnim.py: -------------------------------------------------------------------------------- 1 | 2 | import FreeCAD, os, unittest, FreeCADGui 3 | 4 | def isequal(a,b): 5 | return abs(a-b)<1e-6 6 | 7 | 8 | from Animation import * 9 | reload(Animation) 10 | 11 | import Placer 12 | reload(Placer) 13 | 14 | 15 | class AnimationTest(unittest.TestCase): 16 | 17 | def setUp(self): 18 | # setting a new document to hold the tests 19 | if FreeCAD.ActiveDocument: 20 | if FreeCAD.ActiveDocument.Name != "AnimTest": 21 | FreeCAD.newDocument("AnimTest") 22 | else: 23 | FreeCAD.newDocument("AnimTest") 24 | FreeCAD.setActiveDocument("AnimTest") 25 | 26 | def tearDown(self): 27 | FreeCAD.closeDocument("AnimTest") 28 | pass 29 | 30 | def testPlacer(self): 31 | FreeCAD.Console.PrintLog ('Checking Placer...\n') 32 | b=App.activeDocument().addObject("Part::Box","Box") 33 | r=Placer.createPlacer("BoxPlacer",b) 34 | m=createManager() 35 | m.intervall = 10 36 | m.sleeptime = 0.01 37 | m.addObject(r) 38 | m.Proxy.run() 39 | self.failUnless(isequal(b.Placement.Rotation.Angle,0.5654866776461628),"Rotation error") 40 | self.failUnless(isequal(b.Placement.Base.x,21.45749434738491),"Move error") 41 | 42 | 43 | 44 | 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /testcases/numpy+mathplotlib.py: -------------------------------------------------------------------------------- 1 | 2 | import numpyNode 3 | reload(numpyNode) 4 | 5 | t=numpyNode.createNP() 6 | #t.sourceObject= App.ActiveDocument.Plot001 7 | #t.expression2="4* np.arctan2(in2,in3)" 8 | 9 | 10 | 11 | import mathplotlibNode 12 | from mathplotlibNode import createMPL 13 | 14 | t=createMPL() 15 | t.sourceObject= App.ActiveDocument.My_Manager 16 | t.countSources=4 17 | t.sourceData="step" 18 | 19 | t.source1Object= App.ActiveDocument.Box001 20 | t.source1Data="Placement.Rotation.Angle" 21 | 22 | 23 | t.source2Object= App.ActiveDocument.Box001 24 | t.source2Data="Placement.Base.x" 25 | 26 | t.source3Object= App.ActiveDocument.Box001 27 | t.source3Data="Placement.Base.y" 28 | 29 | # t.expression2="2* np.arctan2(in2,in3)" 30 | 31 | t.record=True 32 | 33 | t.source2Values=[1,2,3,4] 34 | t.source3Values=[1,3,2,5] 35 | App.ActiveDocument.Numpy.sourceObject=t 36 | 37 | 38 | t2=createMPL() 39 | t2.sourceObject= App.ActiveDocument.My_Manager 40 | t2.sourceData="step" 41 | 42 | t2.source1Object= App.ActiveDocument.Box001 43 | t2.source1Data="Placement.Rotation.Angle" 44 | 45 | 46 | t2.sourceObject= App.ActiveDocument.My_Manager 47 | t2.useNumpy=True 48 | t2.sourceNumpy=App.ActiveDocument.Numpy 49 | t2.useOut0=True 50 | t2.useOut1=True 51 | t2.useOut2=True 52 | t2.record=True 53 | 54 | 55 | -------------------------------------------------------------------------------- /testcases/run_all_tests.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | ll=['test_manager','test_placer'] 4 | 5 | for fkn in ll: 6 | print fkn," ##################################" 7 | fn='/usr/lib/freecad/Mod/Animation/testcases/' + fkn +'.py' 8 | d={}; 9 | exec("import FreeCAD,FreeCADGui;App=FreeCAD;\n" + open(fn).read() + "\n\n",d,d) 10 | 11 | -------------------------------------------------------------------------------- /testcases/test_diagram-py: -------------------------------------------------------------------------------- 1 | 2 | 3 | App.setActiveDocument("Unnamed") 4 | App.ActiveDocument=App.getDocument("Unnamed") 5 | Gui.ActiveDocument=Gui.getDocument("Unnamed") 6 | import Animation 7 | Animation.createManager() 8 | 9 | App.ActiveDocument.addObject("Part::Box","Box") 10 | App.ActiveDocument.addObject("Part::Box","Box") 11 | App.ActiveDocument.addObject("Part::Box","Box") 12 | App.ActiveDocument.addObject("Part::Box","Box") 13 | App.ActiveDocument.addObject("Part::Cone","Cone") 14 | 15 | 16 | import Placer 17 | 18 | s1=Placer.createPlacer("B1") 19 | s1.target=App.ActiveDocument.Box001 20 | 21 | s2=Placer.createPlacer("B2") 22 | s2.target=App.ActiveDocument.Box002 23 | s2.y="10" 24 | 25 | s3=Placer.createPlacer("B3") 26 | s3.target=App.ActiveDocument.Box003 27 | s3.y="20" 28 | 29 | 30 | import Diagram 31 | c=Diagram.createDiagram("dia","0.200*time","0.2*(0.01*time-0.5)**2","10+time+1","-10*time") 32 | c.source=s1 33 | c.trafo="source.Placement.Rotation.Angle" 34 | c.timeExpression="source.time*100" 35 | c.graphPlacement.Base.z=10 36 | 37 | 38 | m=App.ActiveDocument.My_Manager 39 | m.addObject(c) 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /testcases/test_diagram.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | App.setActiveDocument("Unnamed") 4 | App.ActiveDocument=App.getDocument("Unnamed") 5 | Gui.ActiveDocument=Gui.getDocument("Unnamed") 6 | import Animation 7 | Animation.createManager() 8 | 9 | App.ActiveDocument.addObject("Part::Box","Box") 10 | App.ActiveDocument.addObject("Part::Box","Box") 11 | App.ActiveDocument.addObject("Part::Box","Box") 12 | App.ActiveDocument.addObject("Part::Box","Box") 13 | App.ActiveDocument.addObject("Part::Cone","Cone") 14 | 15 | 16 | import Placer 17 | 18 | s1=Placer.createPlacer("B1") 19 | s1.target=App.ActiveDocument.Box001 20 | 21 | s2=Placer.createPlacer("B2") 22 | s2.target=App.ActiveDocument.Box002 23 | s2.y="10" 24 | 25 | s3=Placer.createPlacer("B3") 26 | s3.target=App.ActiveDocument.Box003 27 | s3.y="20" 28 | 29 | 30 | import Diagram 31 | c=Diagram.createDiagram("dia","0.200*time","0.2*(0.01*time-0.5)**2","10+time+1","-10*time") 32 | c.source=s1 33 | c.trafo="source.Placement.Rotation.Angle" 34 | c.timeExpression="source.time*100" 35 | c.graphPlacement.Base.z=10 36 | 37 | 38 | m=App.ActiveDocument.My_Manager 39 | m.addObject(c) 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /testcases/test_flow1.py: -------------------------------------------------------------------------------- 1 | 2 | import flowNode 3 | reload (flowNode) 4 | 5 | 6 | 7 | if App.ActiveDocument==None: 8 | App.newDocument("Unnamed") 9 | App.setActiveDocument("Unnamed") 10 | App.ActiveDocument=App.getDocument("Unnamed") 11 | Gui.ActiveDocument=Gui.getDocument("Unnamed") 12 | 13 | 14 | # initialize scene 15 | Gui.ActiveDocument.ActiveView.setAnimationEnabled(False) 16 | App.ActiveDocument.addObject("Part::Cylinder","Cylinder") 17 | App.ActiveDocument.ActiveObject.Label = "Cylinder" 18 | App.ActiveDocument.ActiveObject.Height=800 19 | App.ActiveDocument.ActiveObject.Radius=40 20 | App.ActiveDocument.ActiveObject.ViewObject.Transparency=70 21 | App.ActiveDocument.ActiveObject.Placement.Base=App.Vector(-0,-0,-800) 22 | App.ActiveDocument.ActiveObject.ViewObject.Selectable = False 23 | # App.ActiveDocument.ActiveObject.ViewObject.hide() 24 | c=App.ActiveDocument.ActiveObject 25 | 26 | ''' 27 | b=App.ActiveDocument.addObject("Part::Box","Box") 28 | b.Length=100 29 | b.Width=40 30 | b.Height=200 31 | b.Placement.Base=App.Vector(-50,-20,-200) 32 | b.ViewObject.Transparency=70 33 | b.ViewObject.Selectable = False 34 | ''' 35 | 36 | 37 | Gui.activeDocument().activeView().viewAxonometric() 38 | App.activeDocument().recompute() 39 | 40 | f=flowNode.createFlow() 41 | 42 | f.boundMode='Bound Cylinder' 43 | 44 | f.dimU=30 45 | f.dimV=30 46 | 47 | # f.deltaPosition.Rotation=FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-5) 48 | 49 | 50 | try:f.boundBox=App.ActiveDocument.Cylinder 51 | except: pass 52 | 53 | Gui.SendMsgToActiveView("ViewFit") 54 | f.countSlices=300 55 | f.count2Slides=2 56 | f.count3Slides=6 57 | f.count4Slides=14 58 | 59 | f.period=30 60 | f.sleep=0. 61 | f.noise=0 62 | f.Proxy.main() 63 | 64 | 65 | 66 | 67 | # run() 68 | 69 | -------------------------------------------------------------------------------- /testcases/test_flow2.py: -------------------------------------------------------------------------------- 1 | import flowNode 2 | reload (flowNode) 3 | 4 | 5 | if App.ActiveDocument==None: 6 | App.newDocument("Unnamed") 7 | App.setActiveDocument("Unnamed") 8 | App.ActiveDocument=App.getDocument("Unnamed") 9 | Gui.ActiveDocument=Gui.getDocument("Unnamed") 10 | 11 | 12 | b=App.ActiveDocument.addObject("Part::Box","Box") 13 | b.Length=130 14 | b.Width=100 15 | b.Height=200 16 | b.Placement.Base=App.Vector(-65,-50,-200) 17 | b.ViewObject.Transparency=70 18 | b.ViewObject.Selectable = False 19 | 20 | Gui.activeDocument().activeView().viewAxonometric() 21 | App.activeDocument().recompute() 22 | 23 | f=flowNode.createFlow() 24 | 25 | f.boundMode='Bound Box' 26 | f.startFace = "Rectangle" 27 | 28 | f.boundMode = "Bound Cylinder" 29 | f.startFace = "Circle" 30 | 31 | 32 | f.dimU=12 33 | f.dimV=100 34 | f.noise=0 35 | 36 | 37 | 38 | try:f.boundBox=App.ActiveDocument.Box 39 | except: pass 40 | 41 | Gui.SendMsgToActiveView("ViewFit") 42 | f.countSlices=400 43 | f.count2Slides=2 44 | f.count3Slides=6 45 | f.count4Slides=14 46 | 47 | f.lengthStartCloud = 130 48 | f.widthStartCloud = 100 49 | 50 | f.sleep=0.1 51 | #f.Proxy.main() 52 | -------------------------------------------------------------------------------- /testcases/test_flow3.py: -------------------------------------------------------------------------------- 1 | 2 | import flowNode 3 | reload (flowNode) 4 | 5 | 6 | 7 | if App.ActiveDocument==None: 8 | App.newDocument("Unnamed") 9 | App.setActiveDocument("Unnamed") 10 | App.ActiveDocument=App.getDocument("Unnamed") 11 | Gui.ActiveDocument=Gui.getDocument("Unnamed") 12 | 13 | 14 | # initialize scene 15 | Gui.ActiveDocument.ActiveView.setAnimationEnabled(False) 16 | App.ActiveDocument.addObject("Part::Cylinder","Cylinder") 17 | App.ActiveDocument.ActiveObject.Label = "Cylinder" 18 | App.ActiveDocument.ActiveObject.Height=800 19 | App.ActiveDocument.ActiveObject.Radius=40 20 | App.ActiveDocument.ActiveObject.ViewObject.Transparency=70 21 | App.ActiveDocument.ActiveObject.Placement.Base=App.Vector(-0,-0,-800) 22 | App.ActiveDocument.ActiveObject.ViewObject.Selectable = False 23 | # App.ActiveDocument.ActiveObject.ViewObject.hide() 24 | c=App.ActiveDocument.ActiveObject 25 | 26 | 27 | b=App.ActiveDocument.addObject("Part::Box","Box") 28 | b.Length=100 29 | b.Width=100 30 | b.Height=10 31 | b.Placement.Base=App.Vector(-50,-50,-2) 32 | b.ViewObject.Transparency=0 33 | b.ViewObject.Selectable = False 34 | 35 | 36 | 37 | Gui.activeDocument().activeView().viewAxonometric() 38 | App.activeDocument().recompute() 39 | 40 | f=flowNode.createFlow() 41 | 42 | f.boundMode='Bound Cylinder' 43 | 44 | f.dimU=40 45 | f.dimV=40 46 | 47 | f.deltaPosition.Rotation=FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-2) 48 | f.startPosition.Base=FreeCAD.Vector(-200,-200,0) 49 | 50 | try:f.boundBox=App.ActiveDocument.Cylinder 51 | except: pass 52 | 53 | Gui.SendMsgToActiveView("ViewFit") 54 | f.countSlices=100 55 | f.count2Slides=8 56 | f.count3Slides=18 57 | f.count4Slides=24 58 | 59 | f.period=50 60 | f.sleep=0.05 61 | f.noise=0 62 | f.Proxy.main() 63 | 64 | 65 | 66 | 67 | # run() 68 | 69 | -------------------------------------------------------------------------------- /testcases/test_keyboard.py: -------------------------------------------------------------------------------- 1 | import Keyboard, Placer 2 | reload(Keyboard) 3 | 4 | App.newDocument("Keybord Sensor") 5 | App.setActiveDocument("Keybord Sensor") 6 | App.ActiveDocument=App.getDocument("Keybord Sensor") 7 | 8 | # visualization point 9 | V=App.ActiveDocument.addObject("Part::Vertex","Keybord Control Point") 10 | V.ViewObject.PointSize=10 11 | V.ViewObject.PointColor=(1.0,.0,.0) 12 | 13 | # slaves 14 | s=App.ActiveDocument.addObject("Part::Sphere","Sphere") 15 | b=App.ActiveDocument.addObject("Part::Box","Box") 16 | t=App.ActiveDocument.addObject("Part::Torus","Torus") 17 | 18 | s.ViewObject.ShapeColor=(1.0,1.0,.0) 19 | b.ViewObject.ShapeColor=(.0,1.0,1.0) 20 | t.ViewObject.ShapeColor=(1.0,.0,1.0) 21 | 22 | # ACTOR # 23 | 24 | # move the sphere relative (10,-5,0) to the control point 25 | p=Placer.createPlacer("Sphere Mover",s) 26 | p.src=V 27 | p.x="sx+10" 28 | p.y="sy-5" 29 | 30 | # rotate the cube with rotation arc 20*sx along the default z-axis 31 | p2=Placer.createPlacer("Box Rotator",b) 32 | p2.src=V 33 | p2.x="-50" 34 | p2.y="-5" 35 | p2.arc="20*sx" 36 | 37 | # rotate the donat with rotation arc 10*sy along the x-axis 38 | p3=Placer.createPlacer("Torus Rotator",t) 39 | p3.src=V 40 | p3.x="50" 41 | p3.y="0" 42 | p3.arc="10*sy" 43 | p3.RotAxis=FreeCAD.Vector(1,0,0) 44 | 45 | # SENSOR # 46 | 47 | kb=Keyboard.createKeyboard("Keybord",V) 48 | 49 | 50 | # start up 51 | kb.ViewObject.Proxy.edit() 52 | App.activeDocument().recompute() 53 | Gui.SendMsgToActiveView("ViewFit") 54 | -------------------------------------------------------------------------------- /testcases/test_manager.py: -------------------------------------------------------------------------------- 1 | 2 | # testcase manager 3 | 4 | 5 | def isequal(a,b): 6 | return abs(a-b)<1e-6 7 | 8 | 9 | from Animation import * 10 | 11 | App.newDocument("Unbenannt") 12 | b=App.activeDocument().addObject("Part::Box","Box") 13 | 14 | r=createRotator() 15 | r.duration = 10 16 | r.obj2=b 17 | 18 | m=createManager() 19 | m.intervall = 10 20 | m.sleeptime = 0.01 21 | m.addObject(r) 22 | m.Proxy.run() 23 | 24 | assert(isequal(b.Placement.Rotation.Angle,5.65486677646)) 25 | 26 | App.closeDocument("Unbenannt") 27 | -------------------------------------------------------------------------------- /testcases/test_manager2.py: -------------------------------------------------------------------------------- 1 | 2 | # testcase manager 2 3 | 4 | 5 | def isequal(a,b): 6 | return abs(a-b)<1e-6 7 | 8 | import FreeCAD 9 | import Animation 10 | import Placer 11 | 12 | FreeCAD.newDocument("Unbenannt") 13 | 14 | # zwei zu animierende Objekte erzeugen und 15 | # ihrer Plazierer festlegen 16 | b=FreeCAD.activeDocument().addObject("Part::Torus","Torus") 17 | r=Placer.createPlacer("Torus Placer",b) 18 | r.x='100' 19 | r.RotAxis=FreeCAD.Vector(1.0,0,0) 20 | 21 | b2=FreeCAD.activeDocument().addObject("Part::Box","Box") 22 | k=Placer.createPlacer("Box Placer",b2) 23 | 24 | m=Animation.createManager() 25 | m.intervall = 100 26 | m.sleeptime = 0.01 27 | 28 | # die beiden Plazierer durch den Manager verwalten lassen 29 | m.addObject(r) 30 | m.addObject(k) 31 | 32 | # den Manager starten 33 | m.Proxy.run() 34 | 35 | 36 | #FreeCAD.closeDocument("Unbenannt") 37 | -------------------------------------------------------------------------------- /testcases/test_pather.py: -------------------------------------------------------------------------------- 1 | 2 | # pather testcase 3 | 4 | import Animation,Draft, Pather, Placer 5 | 6 | box=App.ActiveDocument.addObject("Part::Box","Box") 7 | points=[FreeCAD.Vector(22.0,6.0,0.0), 8 | FreeCAD.Vector(8.,60.5,0.0), 9 | FreeCAD.Vector(-20,-27.3,0.0), 10 | FreeCAD.Vector(16.32,-41.3,0.0)] 11 | bspline=Draft.makeBSpline(points) 12 | 13 | pa=Pather.createPather('BSpline as Path') 14 | pa.src=bspline 15 | 16 | pl=Placer.createPlacer('Placer for Box',box) 17 | pl.x='sx-5' 18 | pl.y='sy-5' 19 | pl.arc='0' 20 | pl.src=pa 21 | 22 | m=Animation.createManager() 23 | m.addObject(pa) 24 | m.addObject(pl) 25 | 26 | m.Proxy.run() 27 | -------------------------------------------------------------------------------- /testcases/test_placer.py: -------------------------------------------------------------------------------- 1 | 2 | # testcase manager and placer 3 | 4 | 5 | def isequal(a,b): 6 | return abs(a-b)<1e-6 7 | 8 | 9 | import Animation 10 | from Animation import * 11 | reload(Animation) 12 | 13 | import Placer 14 | reload(Placer) 15 | 16 | d=App.newDocument("Unbenannt") 17 | b=App.activeDocument().addObject("Part::Box","Box") 18 | 19 | 20 | r=Placer.createPlacer("BoxPlacer",b) 21 | 22 | m=createManager() 23 | m.intervall = 10 24 | m.sleeptime = 0.01 25 | m.addObject(r) 26 | m.Proxy.run() 27 | 28 | assert(isequal(b.Placement.Rotation.Angle,0.5654866776461628)) 29 | assert(isequal(b.Placement.Base.x,21.45749434738491)) 30 | 31 | #App.closeDocument("Unbenannt") 32 | -------------------------------------------------------------------------------- /testcases/test_scaler.py: -------------------------------------------------------------------------------- 1 | import Part, Draft 2 | App=FreeCAD 3 | 4 | App.newDocument("Unnamed") 5 | App.setActiveDocument("Unnamed") 6 | App.ActiveDocument=App.getDocument("Unnamed") 7 | b=App.ActiveDocument.addObject("Part::Box","Box") 8 | 9 | c=Draft.clone(b) 10 | import Animation 11 | 12 | 13 | m=Animation.createManager("Skaler Manager") 14 | 15 | import Scaler 16 | reload(Scaler) 17 | 18 | s=Scaler.createScaler("Mein Skalierer") 19 | s.obj2=c 20 | s.duration=80 21 | 22 | m.addObject(s) 23 | m.Proxy.run() 24 | 25 | -------------------------------------------------------------------------------- /testcases/test_snapshot.py: -------------------------------------------------------------------------------- 1 | 2 | # testcase manager 3 | 4 | 5 | def isequal(a,b): 6 | return abs(a-b)<1e-6 7 | 8 | import Animation 9 | from Animation import * 10 | # reload(Animation) 11 | 12 | import Placer 13 | reload(Placer) 14 | 15 | import Snapshot 16 | reload(Snapshot) 17 | 18 | import Toucher 19 | reload(Toucher) 20 | 21 | 22 | d=App.newDocument("Unbenannt") 23 | b=App.activeDocument().addObject("Part::Box","Box") 24 | b.ViewObject.Visibility=False 25 | t=App.ActiveDocument.addObject("Part::Torus","Torus") 26 | t.Radius1=50 27 | 28 | c=App.ActiveDocument.addObject("Part::Cone","Cone") 29 | c.Radius1=50 30 | c.Radius2=3 31 | c.Placement.Base.x=14 32 | c.ViewObject.Visibility=False 33 | 34 | ss=App.activeDocument().addObject("Part::MultiCommon","Common") 35 | ss.Shapes = [b,c] 36 | ss.ViewObject.Visibility=False 37 | 38 | FreeCADGui.ActiveDocument.ActiveView.setAnimationEnabled(False) 39 | FreeCAD.ActiveDocument.recompute() 40 | FreeCADGui.SendMsgToActiveView("ViewFit") 41 | FreeCADGui.updateGui() 42 | 43 | 44 | r=Placer.createPlacer("BoxPlacer",b) 45 | to=Toucher.createToucher("Touch Common",b) 46 | 47 | s=Snapshot.createSnapshot("Snaps ",'T',ss) 48 | v=Snapshot.createViewSequence('VS','T') 49 | 50 | m=createManager() 51 | m2=createManager() 52 | 53 | m.intervall = 30 54 | m.sleeptime = 0 55 | m.addObject(r) 56 | m.addObject(to) 57 | m.addObject(s) 58 | m.Proxy.run() 59 | 60 | 61 | m2.intervall = 30 62 | m2.sleeptime = 0.1 63 | m2.addObject(v) 64 | m2.Proxy.run() 65 | App.ActiveDocument.ActiveObject.ViewObject.Visibility=False 66 | 67 | #App.closeDocument("Unbenannt") 68 | -------------------------------------------------------------------------------- /testcases/test_speeder.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4 | # 5 | # testcase Speeder 6 | # 7 | # 8 | 9 | import Animation 10 | from Animation import * 11 | reload(Animation) 12 | 13 | import Placer 14 | reload(Placer) 15 | 16 | import Speeder 17 | reload(Speeder) 18 | 19 | 20 | 21 | # d=App.newDocument("Unbenannt") 22 | r=Draft.makeRectangle(length=200,height=100.,placement=pl,face=True,support=None) 23 | r.Placement.Base.z=-0.01 24 | 25 | 26 | b=App.activeDocument().addObject("Part::Box","PingPong Box") 27 | b.ViewObject.ShapeColor=(1.0,.0,.0) 28 | r=Placer.createPlacer("BoxPlacer ping pong",b) 29 | r.arc="0" 30 | 31 | s=Speeder.createSpeeder("Speeder Ping Pong") 32 | s.mode='ping pong' 33 | s.target=r 34 | 35 | 36 | b1=App.activeDocument().addObject("Part::Box","Reverse moving Box") 37 | b1.ViewObject.ShapeColor=(1.0,1.0,.0) 38 | r1=Placer.createPlacer("BoxPlacer reverse",b1) 39 | r1.arc="0" 40 | r1.y="10" 41 | s1=Speeder.createSpeeder("Speeder backward") 42 | s1.mode='backward' 43 | s1.target=r1 44 | 45 | 46 | b2=App.activeDocument().addObject("Part::Box","Forced forward moving Box") 47 | b2.ViewObject.ShapeColor=(1.0,.0,1.0) 48 | r2=Placer.createPlacer("BoxPlacer quad",b2) 49 | r2.arc="0" 50 | r2.y="20" 51 | 52 | s2=Speeder.createSpeeder("Speeder quadratic") 53 | s2.expressiontrafo="100*time**2" 54 | s2.mode='expression' 55 | s2.target=r2 56 | 57 | 58 | b3=App.activeDocument().addObject("Part::Box","Forward moving Box") 59 | b3.ViewObject.ShapeColor=(.0,1.0,1.0) 60 | r3=Placer.createPlacer("BoxPlacer normal",b3) 61 | r3.arc="0" 62 | r3.y="30" 63 | 64 | s3=Speeder.createSpeeder("Speeder forward") 65 | s3.mode='forward' 66 | s3.target=r3 67 | 68 | 69 | 70 | m=createManager() 71 | m.intervall = 101 72 | m.sleeptime = 0.01 73 | 74 | m.addObject(s) 75 | m.addObject(s1) 76 | m.addObject(s2) 77 | m.addObject(s3) 78 | 79 | 80 | # 81 | # 82 | # testcase AnimationControlPanel 83 | # 84 | # 85 | 86 | import AnimationControlPanel 87 | reload(AnimationControlPanel) 88 | 89 | w=AnimationControlPanel.createAnimationControlPanel() 90 | w.line1=["Speeder_Ping_Pong","Speeder_quadratic"] 91 | w.line2=["Speeder_forward","Speeder_backward"] 92 | w.line3=["BoxPlacer_normal","BoxPlacer_quad","BoxPlacer_reverse"] 93 | 94 | 95 | App.activeDocument().recompute() 96 | Gui.SendMsgToActiveView("ViewFit") 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | m.Proxy.run() 105 | w.ViewObject.Proxy.edit() 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /testcases/test_speeder2.py: -------------------------------------------------------------------------------- 1 | 2 | import Animation 3 | from Animation import * 4 | reload(Animation) 5 | 6 | import Placer 7 | reload(Placer) 8 | 9 | import Speeder 10 | reload(Speeder) 11 | 12 | 13 | # d=App.newDocument("Unbenannt") 14 | import Draft 15 | #r=Draft.makeRectangle(length=200,height=200) 16 | #r.Placement.Base.z=-0.02 17 | 18 | if False: 19 | for x in range(101): 20 | points=[FreeCAD.Vector(2*x,-200,-0.1),FreeCAD.Vector(2*x,200,-0.1)] 21 | w=Draft.makeWire(points) 22 | w.ViewObject.LineWidth=1.0 23 | w.ViewObject.LineColor=(.0,1.0,.0) 24 | 25 | for y in range(101): 26 | points=[FreeCAD.Vector(0,2*y,-0.1),FreeCAD.Vector(200,2*y,-0.1)] 27 | w=Draft.makeWire(points) 28 | w.ViewObject.LineWidth=1.0 29 | w.ViewObject.LineColor=(1.0,.0,.0) 30 | 31 | 32 | 33 | b=App.activeDocument().addObject("Part::Box","Box") 34 | b.ViewObject.ShapeColor=(1.0,.0,.0) 35 | r=Placer.createPlacer("Placer",b) 36 | r.arc="0" 37 | 38 | s=Speeder.createSpeeder("Speeder Ping Pong") 39 | s.mode='ping pong' 40 | s.m=50 41 | 42 | s.target=r 43 | 44 | 45 | s=Speeder.createSpeeder("Speeder Fade") 46 | s.mode='fade' 47 | s.b=0.3 48 | s.c=0.8 49 | s.m=50 50 | s.g=0.5 51 | s.target=r 52 | 53 | 54 | s=Speeder.createSpeeder("Speeder Sine") 55 | s.mode='sine wave' 56 | s.b=3 57 | s.c=0 58 | s.m=10 59 | s.target=r 60 | 61 | -------------------------------------------------------------------------------- /testcases/test_tracker.py: -------------------------------------------------------------------------------- 1 | 2 | # testcase manager and placer, tracker 3 | 4 | 5 | def isequal(a,b): 6 | return abs(a-b)<1e-6 7 | 8 | 9 | import Animation 10 | from Animation import * 11 | reload(Animation) 12 | 13 | import Placer 14 | reload(Placer) 15 | 16 | import Tracker 17 | reload(Tracker) 18 | 19 | 20 | d=App.newDocument("Unbenannt") 21 | b=App.activeDocument().addObject("Part::Box","Box") 22 | 23 | 24 | r=Placer.createPlacer("BoxPlacer",b) 25 | 26 | t=Tracker.createTracker("BoxTracker",r) 27 | 28 | m=createManager() 29 | m.intervall = 100 30 | m.sleeptime = 0.01 31 | m.addObject(r) 32 | m.addObject(t) 33 | m.Proxy.run() 34 | 35 | 36 | uu=t.ViewObject.Proxy.showpath() 37 | 38 | assert(isequal(uu.Shape.Length,21.5495896498609)) 39 | 40 | #App.closeDocument("Unbenannt") 41 | -------------------------------------------------------------------------------- /testcases/test_trackreader.py: -------------------------------------------------------------------------------- 1 | 2 | # testcase manager and placer, tracker, trackreader 3 | 4 | 5 | def isequal(a,b): 6 | return abs(a-b)<1e-6 7 | 8 | 9 | import Animation 10 | #from Animation import * 11 | reload(Animation) 12 | 13 | import Placer 14 | reload(Placer) 15 | 16 | import Tracker 17 | reload(Tracker) 18 | 19 | import Trackreader 20 | reload(Trackreader) 21 | 22 | 23 | d=App.newDocument("Unbenannt") 24 | b=App.activeDocument().addObject("Part::Box","Box") 25 | 26 | 27 | r=Placer.createPlacer("BoxPlacer",b) 28 | 29 | t=Tracker.createTracker("BoxTracker",r,"/tmp/tracker") 30 | 31 | m=Animation.createManager() 32 | 33 | m.intervall = 100 34 | m.sleeptime = 0.01 35 | m.addObject(r) 36 | m.addObject(t) 37 | m.Proxy.run() 38 | 39 | 40 | path=t.ViewObject.Proxy.showpath() 41 | 42 | 43 | import Trackreader 44 | reload(Trackreader) 45 | tr=Trackreader.createTrackReader("TrackReader",b,"/tmp/tracker") 46 | 47 | #App.closeDocument("Unbenannt") 48 | -------------------------------------------------------------------------------- /testcases/test_vertextracker.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | import FreeCAD 5 | import Animation, Placer,Toucher, VertexTracker 6 | 7 | 8 | 9 | FreeCAD.newDocument("Unbenannt") 10 | 11 | box=FreeCAD.activeDocument().addObject("Part::Box","Static") 12 | box.Height=40 13 | box.Length=100 14 | 15 | box2=FreeCAD.activeDocument().addObject("Part::Box","Animated") 16 | box2.Placement.Base=FreeCAD.Vector(.0,.0,0.) 17 | 18 | toucher=Toucher.createToucher("Force the Common",box) 19 | 20 | # 21 | # Example: track the vertexes of a changing fusion 22 | # 23 | 24 | placer=Placer.createPlacer("Box Placer",box2) 25 | placer.x="100*time-10" 26 | placer.y=" -5 if time< 0.5 else 7" 27 | placer.z="5+30*(0.5-time)**2" 28 | placer.arc="0" 29 | placer.time=0 30 | 31 | manager=Animation.createManager() 32 | manager.intervall = 100 33 | manager.sleeptime = 0.0 34 | 35 | fuse=App.activeDocument().addObject("Part::MultiFuse","Fusion") 36 | fuse.Shapes = [box,box2] 37 | fuse.ViewObject.ShapeColor=(1.0,1.0,.5) 38 | fuse.ViewObject.Transparency=70 39 | 40 | vertextracker=VertexTracker.createVertexTracker("Track of the Fusion") 41 | vertextracker.src=fuse 42 | 43 | manager.addObject(placer) 44 | manager.addObject(toucher) 45 | manager.addObject(vertextracker) 46 | 47 | # run the manager 48 | manager.Proxy.run() 49 | 50 | # show track data 51 | 52 | vertextracker.Proxy.show() 53 | 54 | # generate pathes for the tracks 55 | vertextracker.Proxy.gen() 56 | 57 | 58 | --------------------------------------------------------------------------------