├── 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 |
432 |
--------------------------------------------------------------------------------
/icons/comp_create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microelly2/Animation/a91437046debe9c556945294c2d4880187690d78/icons/comp_create.png
--------------------------------------------------------------------------------
/icons/comp_create.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
69 |
--------------------------------------------------------------------------------
/icons/icon2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
69 |
--------------------------------------------------------------------------------
/icons/icon3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
--------------------------------------------------------------------------------