2

假设我有一个 FreeCAD 模型,它定义了某个几何图形,其高度、宽度和长度尺寸在模型电子表格的单元格中定义。我想使用 FreeCAD 模块在独立的 Python 脚本中构建自动化管道 - 读取该模型 - 将电子表格单元格设置为客户端提供的值 - 相应地重新计算模型 - 通过镶嵌模型的零件来生成几何图形以进行进一步处理在 FreeCAD 之外(与这个问题无关)

该脚本正在工作,只是它无法更改用于计算模型的参数值。生成的几何图形始终反映与模型一起保存的原始值。

我添加了一个断言命令(第 44 行)。geometry[0][0][2]是一个向量,其x坐标恰好等于width电子表格单元格 A5 中的参数值。

如果将脚本调用为

python so.py so_example.FCStd 10 5 3 6

断言失败,因为几何是根据电子表格的原始值 ( width=2) 而不是被覆盖的值 ( ) 生成的width=3

如何有效地覆盖这些电子表格单元格值?

脚本so.py:

FREECADPATH = '/usr/lib/freecad/lib'
import sys
sys.path.append(FREECADPATH)
from collections import defaultdict

def convert_model(filename, arclen, radius, width, height):
    try:
        import FreeCAD
        from FreeCAD import Vector
    except ValueError:
        print ('import error\n')
    else:
        FreeCAD.open(filename)

        doc = App.ActiveDocument

        sheet = doc.Spreadsheet
        print("mode = "+str(sheet.getEditorMode("A5")))
        sheet.setEditorMode("A5", 0)
        print("mode' = "+str(sheet.getEditorMode("A5")))
        print("arclen = "+str(sheet.arclen))
        print("radius = "+str(sheet.radius))
        print("angle = "+str(sheet.angle))
        print("width = "+str(sheet.width))
        print("height = "+str(sheet.height))
        sheet.set("arclen", str(arclen))
        sheet.set("radius", str(radius))
        sheet.set("width", str(width))
        sheet.set("height", str(height))
        sheet.recompute()
        # verify that the radius and also the dependent angle have changed after the recomputer
        print("arclen' = "+str(sheet.arclen))
        print("radius' = "+str(sheet.radius))
        print("angle' = "+str(sheet.angle))
        print("width' = "+str(sheet.width))
        print("height' = "+str(sheet.height))

        # recompute the model
        doc.recompute()

        geometry = generate_geometry(doc)
        print("generated geometry: "+str(geometry[0][0]))

        assert geometry[0][0][2] == Vector(width, 0, 0)

def generate_geometry(doc):
    objects = doc.Objects
    return [tessellate_shape(shaped) for shaped in objects if shaped.TypeId == 'PartDesign::Body']

def tessellate_shape(shaped):
    return shaped.Shape.tessellate(0.1)

def main():
    filename=sys.argv[1]
    arclen=float(sys.argv[2])
    radius=float(sys.argv[3])
    width=float(sys.argv[4])
    height=float(sys.argv[5])
    convert_model(filename, arclen, radius, width, height)

if __name__=='__main__':
   main()

FreeCAD 示例模型

4

1 回答 1

2

最后我发现了如何使它工作:在电子表格中更改单元格值的关键似乎是使用

sheet.set("radius", str(radius))
sheet.recompute()

这不同于做

sheet.radius = str(radius)
sheet.recompute()

这对模型几何形状没有影响。这些电子表格属性似乎是实际单元格值的只读副本。但是,通过调用 Spreadsheet.recompute(),这些属性也会得到更新。

更新:

要在更新电子表格属性后更改实际的模型几何形状,还需要在每个模型对象上调用 touch(),然后调用 doc.recompute()。

于 2020-04-14T06:11:34.223 回答