A2plus Workbench/zh-hans: Difference between revisions

From FreeCAD Documentation
(Created page with "*'''启用对进口零件的递归更新'''<br/>递归打开所有子装配以更新它们。")
(Created page with "*“使用实验性的拓扑命名”<br/>将零件导入装配体时,算法会为导入形状的每个子元素生成拓扑名称。拓扑名称被写入{{PropertyData|mux...")
Line 176: Line 176:
*'''启用对进口零件的递归更新'''<br/>递归打开所有子装配以更新它们。
*'''启用对进口零件的递归更新'''<br/>递归打开所有子装配以更新它们。


*“使用实验性的拓扑命名”<br/>将零件导入装配体时,算法会为导入形状的每个子元素生成拓扑名称。拓扑名称被写入{{PropertyData|mux Info}}。当需要更新导入的零件时,这些拓扑名称用于更新约束的子元素。因此,程序集对FreeCAD的易失性子元素数变得更加健壮。<br/>“注意:'''这会增加导入部件期间的文件大小和计算时间。如果要使用拓扑命名,则必须在创建程序集之前激活它。
* '''Use experimental topological naming'''<br/> While importing parts to the assembly an algorithm generates topological names for each subelement of the imported shape. The topological names are written into the {{PropertyData|mux Info}}. When an imported part needs to be updated, these topological names are used to update the subelements of the constraints. So assemblies get more robust against volatile subelement numbers of FreeCAD.<br/> '''Note:''' This increases file sizes and calculation time during import of parts. If topological naming should be used it has to be activated before the assembly is created.


* '''Inherit per face transparency from parts and subassemblies'''<br/> Use colour and transparency settings from imported parts.<br/> '''Note:''' This feature is very experimental and not recommended for important projects.
* '''Inherit per face transparency from parts and subassemblies'''<br/> Use colour and transparency settings from imported parts.<br/> '''Note:''' This feature is very experimental and not recommended for important projects.

Revision as of 10:47, 29 December 2019

Other languages:

Introduction

A2plus工作台是外部工作台,用于在FreeCAD中的不同零件组装成一个装配体。

本文档介绍了A2plus 0.4.33或更高版本的使用。

Installing

A2plus工作台是FreeCAD的插件。 可以通过菜单工具→插件管理器轻松安装。 A2plus正在积极开发中,并将经常获得新功能。 因此,您还应该使用菜单工具→插件管理器定期对其进行更新。 A2plus代码是在GitHub上托管和开发的[1],也可以通过将其复制到FreeCAD的MOD目录中进行手动安装。

入门

首先,切换到FreeCAD中的A2plus工具栏。 要创建装配体,请在FreeCAD中创建一个新文件。 首先,该文件需要保存。 建议(但不是必需)将其保存在要装配的零件的同一文件夹中。

现在,可以使用工具栏按钮将零件添加到装配体中。 按钮将所选文件中的所有实体作为单个部分添加。 使用按钮时,您可以选择将文件的哪个实体作为零件导入。
默认情况下,第一个添加的零件会固定在一个固定位置。(您可以稍后通过零件属性Data固定位置对其位置进行改变。)
可以使用工具栏按钮复制装配中已经存在的零件。
要编辑部件中的零件,请在模型树中选择它,然后使用工具栏按钮。 这将在FreeCAD中将零件在新选项卡中打开,或者如果文件已经打开,则切换到其选项卡。
要将零件中的更改导入到部件中,请单击工具栏按钮

导入的零件将保留其外部依赖性,并且可以进行编辑。 但是,对于像螺丝这样定义明确的零件,阻止对其进行编辑很有用。 这可以通过工具栏按钮实现,该按钮可将所选零件转换为原始零件的静态副本。

要保存装配体并随后将其关闭,可以使用工具栏按钮

装配

通过在零件之间添加约束来完成零件的组装。 约束后,如果可能,A2plus将根据约束移动零件。
对于零件之间的复杂约束,A2plus可能无法解决约束。 因此,也可以参考故障排除部分中有关解决此类情况的策略。

通过按住Ctrl键并选择两个零件的边或面来添加零件之间的约束。 约束将附加在模型树中,并添加到受影响的零件。

保持追踪

添加的零件越多,跟踪就越重要。 因此,A2plus提供了以下工具来移动和查看零件:

  • 要在装配体中移动零件,请在模型树中选择它,然后使用工具栏按钮。将零件放置在所需位置时,用鼠标左键单击。如果移动的零件已经具有约束,则将通过按下工具栏按钮进行相应放置,因为这将触发以解决装配体的所有约束。
  • 要显示约束,请在模型树中将其选中,然后使用工具栏按钮。这将使整个装配透明,并突出显示通过约束连接的两个对象。要返回普通视图,请在组件中单击鼠标左键。
  • 要仅显示装配中的某些零件,请在模型树中选择这些零件,然后使用工具栏按钮。或者,您可以通过在模型树中选择某个零件并按Space来切换其可见性来隐藏该零件。
  • 要切换整个装配体的透明度视图,可以使用工具栏按钮
  • 使用正常的FreeCAD编辑可以使每个零件透明。但是,有时由于FreeCAD中的错误,在重新打开装配体时零件的透明度设置会丢失。解决方法是,可以使用工具栏按钮恢复透明度设置。

约束

创建约束时,按下约束工具栏按钮后将显示一个对话框:

对于某些约束,它允许您修改约束方向。 使用按钮 Solve 您可以预先检查是否可以用A2plus解决这个新约束。 如果不是,请查看故障排除部分。

A2plus提供下列约束:

点对点

在每个零件上选择一个顶点 (点)。点击工具栏按钮添加点标示约束,它将使顶点重合。

点对线

选择一个零件上的顶点(点)或圆形(将选择其中心点),或一个球面(也将选择其中心点),另一零件上的。工具栏按钮 添加点对线约束。它会把顶点移动到边的上面。

点对面

选择一个零件上的顶点(点)或圆形(将选择其中心点),或一个球面(也将选择其中心点)和另一个零件上的平面。点击工具栏按钮添加点对面约束。“约束”对话框允许您指定点和平面之间的偏移。此偏移也可以在平面的两侧之间翻转。如果偏移为零,则约束将顶点放置在平面上。

球面对球面

在两个部分上选择球形顶点(点)。 点击工具栏按钮添加sphereCenterIdent约束。 它将使球的中心,球的中心与顶点或顶点重合。

圆边对圆边

在两个零件上选择圆形。 点击工具栏按钮添加了圆形边约束。 约束对话框允许您指定边缘之间的偏移。 该偏移量也可以翻转。 您还可以设置约束方向并锁定零件的旋转。 如果偏移量为零,则约束将使边缘同心于同一平面。

轴约束

在两个部分上选择圆柱形或线性。点击工具栏按钮 添加了轴约束。 约束对话框允许您指定轴方向。 该对话框还允许您锁定零件的旋转。 约束将使轴或线重合。

轴平行

在两个零件上选择圆柱形或线性。 工具栏按钮添加了轴平行约束。 约束对话框允许您指定轴方向。 约束将使轴或线平行。

轴对面平行

在一个零件上选择圆柱或线性,在另一部分选择一个平面。 工具栏按钮添加了 axisPlaneParallel约束。 约束将使轴或线平行于平面。

轴对面法线

在一个零件上选择圆柱或线性,在另一零件选择一个平面。 工具栏按钮添加了 axisPlaneNormal约束。 约束将使轴或线垂直于平面。

面平行

在两个零件上选择一个平面。 按下工具栏按钮添加planesParallel约束。 约束对话框允许您指定约束方向。 约束将使平面平行。

面对面

在两个零件上选择一个平面。 按下工具栏按钮添加了planeCoincident约束。 约束对话框允许您指定约束方向和平面之间的偏移。 该偏移量也可以翻转。 如果偏移量为零,则约束将使平面重合。

平面角

在两个零件上选择一个平面。 点击工具栏按钮添加angledPlanes约束。 约束对话框允许您指定平面之间的角度。 约束将使平面首先平行,并设置指定的角度。

重合中心

在两个零件上选择闭合的或平面。 点击工具栏按钮添加centerOfMass约束。 约束对话框允许您指定边或平面之间的偏移。 该偏移量也可以翻转。 您还可以设置约束方向并锁定零件的旋转。 如果偏移量为零,则约束会将边或平面置于同一平面中。

子装配体

装配体可以包含其他装配体。 通过按下工具栏按钮,然后选择包含装配体的* .FCStd文件,可以像零件一样添加它们。 也可以使用工具栏按钮像零件一样编辑这些子装配体。请确保在更高的装配阶段中,当发生更改时,可以通过工具栏按钮更新装配。

约束处理

通过启用相应的按钮,可以选用的约束会高亮显示在工具栏和“约束工具”对话框中。 通过点击工具栏按钮24px打开“约束工具”对话框。 它旨在保持打开状态,以便能够快速向组件添加多个约束。

可以通过在模型树中选择现有约束来进行编辑,然后双击它或使用工具栏按钮。 这将打开“约束属性”对话框。

可以通过在模型树中选择约束并按Del或在模型树中选择带有约束的零件并使用工具栏按钮来删除约束。

使用工具栏按钮 可以随时解析所有约束。 如果工具栏按钮处于打开状态,则在每次编辑约束后都会自动完成解析。

工具栏按钮 影响最近添加的约束。 点击后将翻转约束方向。

零件清单

要创建部件的零件清单,部件的不同零件必须获取A2plus可以读取的零件信息。 这可以通过使用工具栏按钮编辑零件来完成。 在打开的部件中,按下工具栏按钮 ,并创建一个名称为#PARTINFO#电子表格 with the name #PARTINFO# is created.。

电子表格的结构如下:

在最终零件列表中,用您希望拥有的信息填写灰色字段。

In the assembly or subassembly use the toolbar button . It will ask you if you want to iterate recursively over all subassemblies. Click on Yes. This creates a new spreadsheet with the name #PARTSLIST#. It contains the info from the different #PARTSINFO# spreadsheets of the parts in a list like this:

位置(POS)根据模型树中零件的外观自动设置。 顶层零件将获得POS1。
数量(QTY)是自动从装配中计算得出的。 如果零件在装配中出现两次,则将得到数量2。

如果您更新了零件信息,则可以再次按下工具栏按钮来刷新零件列表。

对于子装配体,您还可以使用工具栏按钮创建信息电子表格。 当您创建或更新主装配体的零件清单时,如果您要对所有子装配体进行递归迭代,请单击“否”以使用此信息。 这样,不同的零件不在零件清单中,而仅在子装配中。

特殊功能

装配体结构

点击工具栏按钮将创建一个具有装配体结构的HTML文件。 默认情况下,将在装配体文件的文件夹中创建该文件。 结构看起来像这样:

自由度

按钮 用其自由度标记装配的每个零件。 此外,它输出包含所有部分及其依存关系的列表。 该列表输出到FreeCAD的小部件“报告视图”中。 如果当前不可见此小部件,则可以通过右键单击FreeCAD工具栏区域的空白部分,然后在出现的上下文菜单中或通过菜单 View → Panels → Report view
再次单击按钮可以删除自由度标签。

零件标签

点击按钮 用其名称标记三维视图中部件的每个部分。再次单击按钮可以删除零件标签

装配体整体形状

有时有必要将整个组件组合为一个形状。 然后,该形状可以用于网格工作台中的3D打印或技术图纸工作台中的图形。 使用工具栏按钮创建。 默认情况下,该形状不可见。 如果装配体发生更改,请使用相同的工具栏按钮来更新形状。

参考

可以通过FreeCAD的菜单Edit → Preferences访问A2plus首选项,并在“ A2plus”部分中进行访问。 您可以设置以下选项:

默认解析方法

  • '使用局部系统求解
    求解器以将属性Datafixed Position设置为“True”的零件以及受其约束的零件开始。 不计算所有其他部分。 如果可以找到解析方案,则将下一个约束部分添加到计算中,依此类推。
  • 使用“磁性”求解器,一次求解所有零件”'
    求解器尝试将所有零件一次定向移动到属性设置为Data'
    fixed Position
    的零件上 True。 请注意,在大多数情况下,这将需要更多时间来计算解决方案。
  • 强制固定位置
    它将装配中所有零件的属性Datafixed Position设置为“ true”。 由于所有零件将始终固定在其创建位置,因此实际上不执行任何计算。

默认求解器行为

  • '如果更改约束属性,则自动求解
    求解器将自动启动。 与打开工具栏按钮后的结果相同。

 

更新导入零件时的行为

  • ''在更新之前重新计算导入的零件
    将在FreeCAD中打开装配的所有零件,包括子装配,以便使用电子表格中的值进行重建。
    此功能旨在完全参数化构造。 注意:此功能是非常试验性的,不建议用于重要项目。
    已知问题:
    • 由于错误引用零件中的拓扑名称,可能会破坏装配体
    • 如果在已关闭参考零件文件的情况下进行编辑,则主电子表格可能会损坏。 这会使FreeCAD崩溃。
  • 启用对进口零件的递归更新
    递归打开所有子装配以更新它们。
  • “使用实验性的拓扑命名”
    将零件导入装配体时,算法会为导入形状的每个子元素生成拓扑名称。拓扑名称被写入Datamux Info。当需要更新导入的零件时,这些拓扑名称用于更新约束的子元素。因此,程序集对FreeCAD的易失性子元素数变得更加健壮。
    “注意:这会增加导入部件期间的文件大小和计算时间。如果要使用拓扑命名,则必须在创建程序集之前激活它。
  • Inherit per face transparency from parts and subassemblies
    Use colour and transparency settings from imported parts.
    Note: This feature is very experimental and not recommended for important projects.
  • Do not import invisible shapes
    This will hide invisible datum/construction shapes. Note: No constraints must be connected to datum/construction shapes in higher or other subassemblies. Otherwise you can break the assembly.
  • Use solid union for importing parts and subassemblies
    All imported parts will directly be put together as union.
    This feature is useful for FEM simulations or 3D-printing if only one solid is allowed. The alternative is to create a shape of the whole assembly later on.

User interface settings

  • Show constraints in toolbar
    If this option is not used, the toolbar buttons for the different constraints are not visible to save space in the toolbar. New constraints can still be set using the Constraint Tools dialog (toolbar button ).
  • Use native file manager of your OS
    If this option is used, you get the file dialog of your OS when selecting files for assemblies.

Storage of files

  • Use relative paths for imported parts
    Uses relative file paths to the part files.
  • Use absolute paths for imported parts
    Uses absolute file paths to the part files.
  • All files are in this project folder:
    All project files have to be in the specified folder. It doesn't matter if they are in subfolders of this folder. Note: No file is allowed to exist several times in the folder (e.g. in different subfolders).
    This option is helpful to work on different machines because then one only has to copy the project folder.

Troubleshooting

Sooner or later you will get the problem that A2plus cannot solve the constraints you set. To overcome this, there are different strategies:

Checking Constraint Direction

Sometimes constraints seem to be consistently defined but they can nevertheless not be solved. An example: Assume you have a planesParallel constraint set for two planes. Now you want to set for the same planes the planeCoincident constraint and A2plus cannot solve this. Then the constraint directions of planesParallel and planeCoincident are different. Use the same direction for both constraints to fix this.

Deleting Constraints

Most cases of unsolvable constraints occur directly when adding a new constraint. The solution is then to delete the constraint you added last. A2plus will propose this, too.

Sometimes the deletion strategy is the only one, for example when you edited a part in FreeCAD so that faces or edges connected to constraints are missing. You should then delete one constraint that is connected to the changed part at a time. Use the toolbar button after every deletion to see if you reached a solvable state.

When you got an assembly that can be solved, add step by step the constraints you need.

Moving Parts

In some cases the solver only needs better start values to solve the constraints. Take for example the case that you have an axle part and a wheel part. You add a axisCoincident constraint and get no info that the solver failed but the parts are not moved accordingly and in the Report view widget of FreeCAD you see "REACHED POS-ACCURACY :0.0". A solution for this is to move the parts closer to that position you like to get by the constraint.

Note: Assure that at least one part of the constraint has the property Datafixed Position set to false.

Setting the Tip Property

If you miss some features of your part after the import to an A2plus assembly, check the property DataTip.
A2plus imports bodies of parts with all their features up to the tip feature. This is sensible because setting the tip to a certain feature means that all features behind the tip should not appear in the final part. So if you miss a part feature in A2plus, open the part via the toolbar button , then select a body and look at its property DataTip. If the tip is not at the feature where you want it, right-click on the feature where the tip should be and choose Set tip. Finally save the part and reload the assembly using the toolbar button .

Repairing Assembly Tree

If you cannot see a clear reason why some constraints cannot be resolved, you can try to use the toolbar button . This will resolve all constraints and re-group then again under the different parts.

Avoiding Accented Characters

On some operating systems you can get problems if the file names or the file paths of parts or the assembly contain accented characters. Therefore avoid such characters and also special characters in general.

Fixing Position

This strategy is no longer necessary for assemblies created with A2plus 0.3.11 or newer because A2plus issues now a warning for missing fixed positions.

When you set a constraint between two parts and no part has the property Datafixed Position set to true or is connected by a constraint to a part with Datafixed Position set to true, the constraint cannot be solved. The same happens if both parts of the constraint have Datafixed Position set to true.

Then A2plus outputs the info about the failed solution, but sometimes you only see that the parts are not moved accordingly and in the Report view widget of FreeCAD you see "REACHED POS-ACCURACY :0.0". This means the solver finished without errors but it could actually not solve the constraints.

Therefore check that at least one of your parts in the assembly has Datafixed Position set to true. Then assure that you only set constraints to a part which is somehow connected to the fixed part. To visualise these dependencies, see section Assembly Structure.

Rotating Parts

This strategy is no longer necessary for assemblies created with A2plus 0.4.0 or newer because A2plus rotates the parts now automatically a bit in the background to get a sufficient start angle for the solver.

The solver often fails for the constraint angledPlanes if the two selected planes have currently an angle of 0° or 180°. (The parts are not moved accordingly and in the Report view widget of FreeCAD you see "REACHED POS-ACCURACY :0.0".) A solution for this is to rotate one part by a few degrees using FreeCAD's transform feature (right-click on the part in the model tree and select in the context menu Transform).

Note: Assure that at least one part of the constraint has the property Datafixed Position set to false.

Animation

A2plus offers animations via dragging and via Python scripts.

Dragging

Dragging animations are interactive since you trigger it by dragging a part of the assembly. To get these kind of animations:

  1. Fully constrain the part whose movement or rotation should be animated
  2. Click on the toolbar button . This enables the dragging mode.
  3. Click on the desired part in the assembly.
  4. Now you can move the mouse and the part will follow the movement of the mouse within the defined constraints.
  5. To end the dragging mode, left click in the assembly or press ESC.

Here is an example assembly to try out the dragging animation: A2p_example-for-dragging-animation.FCStd

This is the dragging animation using the example assembly:

Scripting

Despite the dragging mode offers nice interactive animations, they are sometimes not precise enough for screencasts or videos. Scripted animations have the advantage that they animate movements and rotations in a defined way. You can for example rotate a part by exactly 10° back and forth. The following examples use an assembly where a part should be rotated. If you try to animate this using the dragging mode, you will see how hard it is to get a back and forth rotation that you can e.g. show your boss in a presentation. With the interactive example script, however, this is an easy task.

A scripted animation works usually this way:

  1. The assembly is fully constrained
  2. The script changes a parameter, for example the position or rotation angle of a part
  3. After the parameter change, the assembly constraints are solved
  4. Step 2. and 3. are repeated to get the animation

It is also possible to change instead of a placement parameter a constraint, for example the distance between 2 planes.

Simple Script Example

The simplest way to script an animation is a non-interactive animation that follows a defined movement. Here is an example: First download this assembly file: A2p_animated-example.FCStd and also this Python script: A2p_animation-example-script.py.

This is the content of the script and the lines beginning with a '#' describe what the different script lines do:

# import libraries
import time, math, PySide
import A2plus.a2p_solversystem as a2p_solver

# we use steps of 1 degree
step = 1
# wait 1 ms between every step
timeout = 0.001
# initial angle is 0 degree
angle = 0
# we take the currently opened document
document = FreeCAD.activeDocument()
# we want later change the rotation angle of the part "star_wheel_001"
starWheel = document.getObject("star_wheel_001")
# define a progress dialog running from 0 to 360
progressDialog = PySide.QtGui.QProgressDialog(u"Animation progress", u"Stop", 0, 360)

# the while block is the main loop to change the angle and solve
# the assembly constraints subsequently
while angle < 360: # run this loop until we have one full turn (360 degrees)
    # increase the rotation angle
    angle += step
    # set the new angle to the progress dialog
    progressDialog.setValue(angle)
    # change the rotation angle of the part "star_wheel_001"
    starWheel.Placement.Rotation.Angle = math.radians(angle)
    # solve the constraints 
    a2p_solver.solveConstraints(document, useTransaction=True)
    # update the view after the solving ('Gui' stands for 'graphical user interface')
    FreeCADGui.updateGui()
    # bring the progress dialog to front
    PySide.QtGui.QWidget.raise_(progressDialog)
    # if 'Stop' was pressed in the dialog, exit the loop
    if progressDialog.wasCanceled():
        angle = 360
    # wait some time before performing the next step
    time.sleep(timeout)

To use the script to perform the animation, we must

  1. Open the assembly file in FreeCAD.
  2. Open the script file in FreeCAD.
  3. Click on the toolbar button to execute the script (also called macro).
  4. Change to the tab of the assembly to see the rotation.

To practice, just change something in the script and execute it afterwards. For example increase step to 5.

This is the result of the example animation:

Interactive Script Example

The first script example demonstrated how to create an animation without any user feedback. For most applications you need to interact with the animation. For example the interesting issue in the example is to see how the driving pins cross the center groove of the wheel. To have a closer look you might present this detail to your colleagues or boss. Therefore you need an interactive solution.

This can be done by using a custom animation dialog with a slider. By moving the slider you can set the rotation angle and therefore rotate back and forth at interesting position.

We use the same assembly file: A2p_animated-example.FCStd and this Python script: A2p_animation-example-script.py.

This is the content of the script to get the interactive animation dialog:

# import libraries
import time, math, PySide, sys
import FreeCAD.A2plus.a2p_solversystem as a2p_solver
from FreeCAD import Units
from PySide import QtCore, QtGui

# wait 1 ms after every calculation
timeout = 0.001
# we take the currently opened document
document = FreeCAD.activeDocument()
# we want later change the rotation angle of the part "star_wheel_001"
starWheel = document.getObject("star_wheel_001")

class AnimationDlg(QtGui.QWidget): # the animation dialog

    def __init__(self): # to initialize the dialog
        super(AnimationDlg, self).__init__()
        self.initUI()

    def initUI(self): # the definition of the dialog components
        self.setMinimumSize(self.minimumSizeHint()) # set the minimal dialog size to minimum
        self.setWindowTitle('Animation Dialog')
        # use a grid layout for the whole form
        self.mainLayout = QtGui.QGridLayout()
        self.lineNo = 0 # first dialog grid line
        # add description label
        DescriptionLabel = QtGui.QLabel(self)
        DescriptionLabel.setText("Change slider to change rotation angle")
        self.mainLayout.addWidget(DescriptionLabel,self.lineNo,0,1,4)
         # next dialog grid line
        self.lineNo += 1
        # add a label; there is no need for the "self." prefix because we don't want to change the label later
        LabelMin = QtGui.QLabel(self)
        LabelMin.setText("Min")
        LabelMin.setFixedHeight(32)
        self.mainLayout.addWidget(LabelMin,self.lineNo,0)
        # add a spin edit to define the slider minimum
        self.MinEdit = QtGui.QSpinBox(self)
        # get the angle unit as string
        self.MinEdit.setSuffix(" " + str(FreeCAD.Units.Quantity(1, FreeCAD.Units.Angle))[2:])
        self.MinEdit.setMaximum(999)
        self.MinEdit.setMinimum(0)
        self.MinEdit.setSingleStep(10)
        self.MinEdit.setValue(0)
        self.MinEdit.setFixedHeight(32)
        self.MinEdit.setToolTip("Minimal angle for the slider")
        QtCore.QObject.connect(self.MinEdit, QtCore.SIGNAL("valueChanged(int)"), self.setMinEdit)
        self.mainLayout.addWidget(self.MinEdit,self.lineNo,1)
        # add the slider
        self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.slider.setRange(0, 360)
        self.slider.setValue(0)
        self.slider.setFixedHeight(32)
        self.slider.setToolTip("Move the slider to change the rotation angle")
        QtCore.QObject.connect(self.slider, QtCore.SIGNAL("sliderMoved(int)"), self.handleSliderValue)
        self.mainLayout.addWidget(self.slider,self.lineNo,2)
        # add a label
        LabelMax = QtGui.QLabel(self)
        LabelMax.setText("Max")
        LabelMax.setFixedHeight(32)
        self.mainLayout.addWidget(LabelMax,self.lineNo,3)
        # add a spin edit to define the slider maximum
        self.MaxEdit = QtGui.QSpinBox(self)
        # get the angle unit as string
        self.MaxEdit.setSuffix(" " + str(FreeCAD.Units.Quantity(1, FreeCAD.Units.Angle))[2:])
        self.MaxEdit.setMaximum(999)
        self.MaxEdit.setMinimum(1)
        self.MaxEdit.setSingleStep(10)
        self.MaxEdit.setValue(360)
        self.MaxEdit.setFixedHeight(32)
        self.MaxEdit.setToolTip("Maximal angle for the slider")
        QtCore.QObject.connect(self.MaxEdit, QtCore.SIGNAL("valueChanged(int)"), self.setMaxEdit)
        self.mainLayout.addWidget(self.MaxEdit,self.lineNo,4)
         # next dialog grid line
        self.lineNo += 1
        # add a spacer
        self.mainLayout.addItem(QtGui.QSpacerItem(10,10), 0, 0)
        # add a label
        LabelCurrent = QtGui.QLabel(self)
        LabelCurrent.setText("Current angle:")
        LabelCurrent.setFixedHeight(32)
        self.mainLayout.addWidget(LabelCurrent,self.lineNo,1)
        # output the current angle
        self.CurrentAngle = QtGui.QLineEdit(self)
        self.CurrentAngle.setText(str(0))
        self.CurrentAngle.setFixedHeight(32)
        self.CurrentAngle.setToolTip("Current rotation angle")
        self.CurrentAngle.isReadOnly()
        self.mainLayout.addWidget(self.CurrentAngle,self.lineNo,2)
        # add label for the unit
        LabelUnit = QtGui.QLabel(self)
        LabelUnit.setText("deg")
        LabelUnit.setFixedHeight(32)
        self.mainLayout.addWidget(LabelUnit,self.lineNo,3)
        # button to close the dialog
        self.Close = QtGui.QPushButton(self)
        self.Close.setText("Close")
        self.Close.setFixedHeight(32)
        self.Close.setToolTip("Closes the dialog")
        QtCore.QObject.connect(self.Close, QtCore.SIGNAL("clicked()"), self.CloseClicked)
        self.mainLayout.addWidget(self.Close,self.lineNo,4)
        # place the defined grid layout to the dialog
        self.setLayout(self.mainLayout)
        self.update()

    def handleSliderValue(self):
        # set slider value as angle
        starWheel.Placement.Rotation.Angle = math.radians(self.slider.value())
        # output current angle
        self.CurrentAngle.setText(str(self.slider.value()))
        # solve the constraints 
        a2p_solver.solveConstraints(document)
        # update the view after the solving ('Gui' stands for 'graphical user interface')
        FreeCADGui.updateGui()
        # wait some time, important to give time to perform calculations
        time.sleep(timeout)

    def setMinEdit(self):
        # assure that the minimum is samller than the maximum
        if self.MinEdit.value() >=  self.MaxEdit.value():
            self.MaxEdit.setValue(self.MinEdit.value() + 1)
        self.slider.setRange(self.MinEdit.value(), self.MaxEdit.value())

    def setMaxEdit(self):
        # assure that the minimum is samller than the maximum
        if self.MinEdit.value() >=  self.MaxEdit.value():
            self.MinEdit.setValue(self.MaxEdit.value() - 1)
        self.slider.setRange(self.MinEdit.value(), self.MaxEdit.value())

    def CloseClicked(self):
        AnimationDialog.close()

# create and show the defined dialog
AnimationDialog = AnimationDlg()
AnimationDialog.show()

# run this loop when the dialog is visible
while AnimationDialog.isVisible():
    # update the view; important to give the OS feedback the dialog is alive
    FreeCADGui.updateGui()
    # bring the dialog to front, so that the dialog is always visible
    QtGui.QWidget.raise_(AnimationDialog)
    # output slider value here too because during the calculation the slider might have been moved
    AnimationDialog.CurrentAngle.setText(str(AnimationDialog.slider.value()))

The dialog defined in the script looks like this:

Script Commands

To understand the script syntax better, here is some command info:

The command

starWheel.Placement.Rotation.Angle = math.radians(angle)

means, we change the placement property Rotation.Angle of the part get got previously as "starWheel". This property gets the angle as radian. The function radians() from the library math converts the angle from degree to radian.


The property Rotation.Angle uses the current placement axis of the part (in our example the x-axis). To rotate the part e.g. around the z-axis one can set the rotation axis (before calling the rotation command) using the command

starWheel.Placement.Rotation.Axis = FreeCAD.Vector(0,0,1)

Instead of rotating, parts can also be moved. To change for example the placement in y-direction of the wheel, the command would be

starWheel.Placement.Base.y = PositionShift

In this case we would not define the variable angle but PositionShift that we change on every loop run.
There are different ways to set the placement of a part. Some are documented here. Unfortunately there is no list with all possible placement commands.


The command

a2p_solver.solveConstraints(document, useTransaction=False/True)

is a A2plus-specific command. It solves the assembly constraints of the assembly we previously got as "document". The option useTransaction specifies if FreeCAD should store every change in the undo/redo stack. For large animations you might therefore set it to False.