简体   繁体   中英

how to update Spreadsheet values using FreeCAD python module

Let's say I have a FreeCAD model that defines a certain geometry with dimensions height, width, and length that are defined in cells of the model's spreadsheet. I want to build an automation pipeline in a stand-alone Python script using the FreeCAD module that - reads that model - sets the spreadsheet cells to values provided by the client - recomputes the model accordingly - generates geometry by tessellating the model's parts for further processing outside of FreeCAD (irrelevant with regard to this question)

The script is working except that it fails to change the parameter values that are used to compute the model. The resulting geometry always reflects the original values that were saved with the model.

I've added an assert command (line 44). geometry[0][0][2] is a Vector whose x coordinate happens to equal the value of the width parameter in spreadsheet cell A5.

If one invokes the script as

python so.py so_example.FCStd 10 5 3 6

the assert fails because the geometry gets generated based on the spreadsheet's original values ( width=2 ) and not the overwritten ones ( width=3 ).

How can I effectively overwrite those spreadsheet cell values?

Script 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 example model

Finally I found out how to make it work: The key to changing cell values in the spreadsheet seems to be to use

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

This is different from doing

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

which has no effect on the model geometry. These Spreadsheet properties seem to be read-only copies of the actual cell values. However, by invoking Spreadsheet.recompute(), these properties get updated as well.

UPDATE:

To make the actual model geometry change after updating the Spreadsheet properties, one also needs to call touch() on each model object and then doc.recompute().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM