Feature Python questions

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Feature Python questions

Postby jreinhardt » Sat Apr 26, 2014 9:23 am

Hi,

I played around a bit with Python features for BOLTS. The idea was to explore the possibility of encapsulating the parts from BOLTS in a feature and exposing the parameters as properties, to allow to change them afterwards. So instead of deleting a M3 washer and adding a M4 washer one could just select the M3 washer and change the size by changing a property.
BOLTSFeature.png
BOLTSFeature.png (304.6 KiB) Viewed 2465 times
It was surprisingly easy to get some very rough proof of concept working, but there is something that I could not figure out. If you have a App::PropertyEnumeration, you can set the possible choices by assigning a list to the property:

Code: Select all

obj.addProperty("App::PropertyEnumeration","Sizes,"BOLTSFeature","Size of the washer")
setattr(obj,"Sizes",["M3","M4","M5"])# or obj.Sizes = ["M3", "M4", "M5"]
But how do you set the currently selected choice from python?

And then I am not sure, whether having the parts from BOLTS in form of a Python feature is a good idea anyway. On the one hand it is nice to be able to change the parameters of a part via the standard property mechanism, but on the other hand I fear the interoperability problems that arise. If I understand correctly, BOLTS would need to be available to be able to open fcstd files containing such parts, and one would need to be careful to preserve backwards compatibility. This seems like a lot of complications for a relatively small gain.

What do you think?

OS: Ubuntu 13.10
Platform: 64-bit
Version: 0.14.3468 (Git)
Branch: master
Hash: 79efe68e2581b350e04fdaebbd4a65ce3105a54a
Python version: 2.7.5+
Qt version: 4.8.4
Coin version: 4.0.0a
SoQt version: 1.5.0
OCC version: 6.7.0
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
wmayer
Site Admin
Posts: 15490
Joined: Thu Feb 19, 2009 10:32 am

Re: Feature Python questions

Postby wmayer » Sat Apr 26, 2014 4:01 pm

But how do you set the currently selected choice from python?
To get the currently active value of the enum you write:

Code: Select all

obj.Sizes
which returns the value as string.

To set a value you can either write:

Code: Select all

obj.Sizes="M4"
or

Code: Select all

obj.Sizes=1
If I understand correctly, BOLTS would need to be available to be able to open fcstd files containing such parts, and one would need to be careful to preserve backwards compatibility. This seems like a lot of complications for a relatively small gain.
For me this is too generally spoken. What exact problems do you fear?
User avatar
yorik
Site Admin
Posts: 11700
Joined: Tue Feb 17, 2009 9:16 pm
Location: São Paulo, Brazil
Contact:

Re: Feature Python questions

Postby yorik » Sat Apr 26, 2014 4:58 pm

jreinhardt wrote: And then I am not sure, whether having the parts from BOLTS in form of a Python feature is a good idea anyway. On the one hand it is nice to be able to change the parameters of a part via the standard property mechanism, but on the other hand I fear the interoperability problems that arise. If I understand correctly, BOLTS would need to be available to be able to open fcstd files containing such parts, and one would need to be careful to preserve backwards compatibility. This seems like a lot of complications for a relatively small gain.
Yes. That's one of the limitations of it. You cannot embed code inside a .FcStd file, for security reasons. That means that if you create a parametric object that depends on BOLTS, that object cannot be opened on a machine that doesn't have BOLTS installed.

But think further of it, if you can come up with a kind of "generic" BOLTS object (or several), we could maybe include it in the freecad source code...

Another connected idea that might be worth exploring: Find a way so that you can modify an existing object via the BOLTS interface... So you could have for example a dead-simple parametric object, that contains one additional property, a PropertyMap or PropertyStringList that contains the parameters needed by BOLTS to recognize what object it is...
triplus
Posts: 9278
Joined: Mon Dec 12, 2011 4:45 pm

Re: Feature Python questions

Postby triplus » Sat Apr 26, 2014 5:28 pm

So instead of deleting a M3 washer and adding a M4 washer one could just select the M3 washer and change the size by changing a property.
I did something like that in spreadsheet already:

viewtopic.php?f=9&t=4359

Only one washer has to be modelled and after that everything can be set up to only input for example 4 (M4) in predefined cell for the model to change based on conditions set. ATM i am only able to control property of features like Length of Pad and not constraints in sketcher.

But as i understand devs where a bit upset because that was done in a way it "bypassed" document solver? You will probably have to do something that will use document solver to do the job in the right way.
But think further of it, if you can come up with a kind of "generic" BOLTS object (or several), we could maybe include it in the freecad source code...

Another connected idea that might be worth exploring: Find a way so that you can modify an existing object via the BOLTS interface... So you could have for example a dead-simple parametric object, that contains one additional property, a PropertyMap or PropertyStringList that contains the parameters needed by BOLTS to recognize what object it is...
How about if FreeCAD would have an interface that would allow inserted feature to expose its properties in sidebar? For example to insert a part from BOLTS into FreeCAD and for BOLTS not to be involved anymore? That way you would not need BOLTS to open the file and when changing inserted part property like M4 -> M5 FreeCAD would know what to do?

In a way putting "spreadsheet" in the sidebar and part in BOLTS library to already have the info on how to fill the cells with labels and math expressions and input fields!
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Re: Feature Python questions

Postby jreinhardt » Sat Apr 26, 2014 6:06 pm

wmayer wrote:
But how do you set the currently selected choice from python?
To get the currently active value of the enum you write:

Code: Select all

obj.Sizes
which returns the value as string.

To set a value you can either write:

Code: Select all

obj.Sizes="M4"
or

Code: Select all

obj.Sizes=1
Thanks, that works.
If I understand correctly, BOLTS would need to be available to be able to open fcstd files containing such parts, and one would need to be careful to preserve backwards compatibility. This seems like a lot of complications for a relatively small gain.
For me this is too generally spoken. What exact problems do you fear?
BOLTS tries to build a part library consisting of python functions that create the shape of a part from parameters and tables of these parameters. At the moment I just insert the shape into a Part::Feature at creation time. The problems I see with a FeaturePython are:
  • A fcstd file containing such a part would need to have BOLTS install to open properly. Even if BOLTS is distributed with FreeCAD at some point, this is not the case for older versions of FreeCAD.
  • It might happen, that the underlying function or data for a part changes between versions of BOLTS, because someone found an error, provides a better geometry function or adds more parameters (e.g. not only the size of a bolt, but also its material). If I understand correctly, one would need to take care of these cases, otherwise loading the part will fail, as some properties could be missing, or have invalid values or are not existing anymore. One would also need to handle the case of someone with an older version of BOLTS loading a file with a part from a newer version.
Just having the shape in a Part::Feature (like I do it at the moment) would avoid all this.
yorik wrote: But think further of it, if you can come up with a kind of "generic" BOLTS object (or several), we could maybe include it in the freecad source code...

Another connected idea that might be worth exploring: Find a way so that you can modify an existing object via the BOLTS interface... So you could have for example a dead-simple parametric object, that contains one additional property, a PropertyMap or PropertyStringList that contains the parameters needed by BOLTS to recognize what object it is...
I am not sure if I understand exactly what you mean. Maybe it is just what I was trying. I wrote a class "BOLTSFeature", that gets a set of parameters and a bit more info about the kind of part it is. The parameters (e.g. diameter and length of a bolt like in the picture) get automatically exposed as properties, with the proper names, types and set to the right values. We know these things from the "a bit more info". Then the shape of the part is created by calling the corresponding function with the right parameters.

@triplus:

I am aware of the efforts with the spreadsheet module. I think SolidWorks has a similar mechanism.

I believe that by using a Python feature there should be no problems with dependencies. But I have no proper overview over the structure of FreeCAD, so I might be wrong.
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Re: Feature Python questions

Postby jreinhardt » Mon Apr 28, 2014 11:32 am

I think I made up my mind, I will stay with the current system, so no python features. This is simpler, more flexible and more robust.

Another, only slightly related question: a while ago jriegel stated that he is interested in integrating BOLTS more closely into FreeCAD in the long run:

He mentions that it should be a module, but I am not sure what that means. There are modules mentioned in the developers documentation but this seems to be something else. I rather suspect that a module is something that lives in the "src/Mod" directory. Is this true?

I do not claim that BOLTS is ready for integration yet, but I will soon have to rewrite parts of the code and would prefer to know beforehand if I have to take additional requirements into accont. So I want to do some research and maybe a few experiments before starting the rewrite.
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
User avatar
yorik
Site Admin
Posts: 11700
Joined: Tue Feb 17, 2009 9:16 pm
Location: São Paulo, Brazil
Contact:

Re: Feature Python questions

Postby yorik » Mon Apr 28, 2014 2:32 pm

Honestly I find it cool that BOLTS is independent from its host software... This is very "open source spirit" :) Actually the only difference if BOLTS becomes a freecad module, is that it would reside in src/Mod, and be loaded at freecad startup. Other than that, everything you do in a freecad module can be done from anywhere else too, so there would be not much to change.

Basically you will need an Init.py file (executed at freecad startup, always) and InitGui.py file (executed only when freecad starts in GUI mode). In InitGui.py normally we define a workbench, and add some commands to it (a command is a python object that contains a name, an icon, and code to be executed when activated. Commands can then be added to toolbars or menus). That's about it.
jreinhardt wrote:I am not sure if I understand exactly what you mean. Maybe it is just what I was trying. I wrote a class "BOLTSFeature", that gets a set of parameters and a bit more info about the kind of part it is. The parameters (e.g. diameter and length of a bolt like in the picture) get automatically exposed as properties, with the proper names, types and set to the right values. We know these things from the "a bit more info". Then the shape of the part is created by calling the corresponding function with the right parameters.
This is more or less what I had in mind, with a difference: In your example, the code that produces the shape is inside the boltsfeature. Which means, the code of that feature must be available on all the machines where you want to open such a file. This is the problem we were trying to avoid.

But consider this: You have one, very simple, empty boltsfeature. It is derived from Part::FeaturePython, and it has only one hidden property, that contains all the parameters needed by BOLTS to recreate the shape. But it has no other functionality, nothing inside its execute() function. Then, from BOLTS, if such an object is selected, you could easily detect its type, and recreate its shape if needed. This would be like a middle-term solution, a "dumb" object (not parametric), but controllable and modifiable from BOLTS.

Now, if you intent to turn BOLTS into a freecad module, then all this becomes of course much less important...
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Re: Feature Python questions

Postby jreinhardt » Mon Apr 28, 2014 3:27 pm

yorik wrote: But consider this: You have one, very simple, empty boltsfeature. It is derived from Part::FeaturePython, and it has only one hidden property, that contains all the parameters needed by BOLTS to recreate the shape. But it has no other functionality, nothing inside its execute() function. Then, from BOLTS, if such an object is selected, you could easily detect its type, and recreate its shape if needed. This would be like a middle-term solution, a "dumb" object (not parametric), but controllable and modifiable from BOLTS.

Now, if you intent to turn BOLTS into a freecad module, then all this becomes of course much less important...
I see. I wasn't aware that a execute function is not mandatory. This would solve the problems of interoperability, as this is basically a fallback to a dumb object, so everybody would at least get this behaviour.
Actually the only difference if BOLTS becomes a freecad module, is that it would reside in src/Mod, and be loaded at freecad startup. Other than that, everything you do in a freecad module can be done from anywhere else too, so there would be not much to change.

Basically you will need an Init.py file (executed at freecad startup, always) and InitGui.py file (executed only when freecad starts in GUI mode). In InitGui.py normally we define a workbench, and add some commands to it (a command is a python object that contains a name, an icon, and code to be executed when activated. Commands can then be added to toolbars or menus). That's about it.
That sounds surprisingly easy. I am not sure how I missed this before. I guess I would not want a separate workbench, just a command that opens the widget?
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
User avatar
yorik
Site Admin
Posts: 11700
Joined: Tue Feb 17, 2009 9:16 pm
Location: São Paulo, Brazil
Contact:

Re: Feature Python questions

Postby yorik » Mon Apr 28, 2014 3:35 pm

jreinhardt wrote:That sounds surprisingly easy. I am not sure how I missed this before. I guess I would not want a separate workbench, just a command that opens the widget?
It is really easy indeed, all the complex stuff you have done already ;)
Yes, I suppose it would make no sense to have a workbench with only one command. It is probably better to add it to another existing workbench, probably PartDesign...
abdullah
Posts: 3259
Joined: Sun May 04, 2014 3:16 pm

Re: Feature Python questions

Postby abdullah » Fri May 30, 2014 3:02 pm

yorik wrote:Yes, I suppose it would make no sense to have a workbench with only one command. It is probably better to add it to another existing workbench, probably PartDesign...
I found this thread very interesting!

And without intending to hijack it... notwithstanding the possible problems with backward compatibility and distribution of the code, would it be possible to locally extend an existing Workbench (e.g. Part Workbench) with a new command (for example from ~/.FreeCAD/Mod/)?

(I know a new workbench can be created, as in the cura plugin, but I mean just extend it with let's say a FeaturePython object)