Manipulating InList and OutList

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Manipulating InList and OutList

Post by onekk »

with some example code the things are much clear, when dealing with coding, sources are "the foundation" on other people could work on.

As said abstract question like yours are "abstract" if they are "real code" someone could recreate the .py file and test some solutions.

But maybe I'm wrong, but as the answer you are searching is based on code.

see as an example:

https://forum.freecadweb.org/viewtopic.php?f=22&t=56308

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Manipulating InList and OutList

Post by wmayer »

Hermit wrote: Thu Mar 11, 2021 9:14 am Hello wmayer, Thank you for your prompt reply.

I was also looking at the link properties and wasn't sure what role they played in the dependency graph.
The link properties are used to model the DAG (Directed Acyclic Graph) of the features. This is mainly needed for the recompute of the document so that touched features that don't depend on other features are recomputed first and then the dependent features.
I will experiment with these a bit more. Where's the best place to find documentation for them? I find the wiki and forums to be a bit sparse at best, and these seem like core features...
Strange, I had a quick look at the documentation and I couldn't find anything.
Would you allow a relative newcomer like me to help update the documentation or contribute a mini-tutorial once I've uncovered a solution?
Sorry but I don't have the time any more to also contribute to the documentation. But I can quickly describe the basic principles of FreeCAD:
  • In FreeCAD application logic and GUI logic are strictly separated which affects the core system and all extension modules. So, application logic is e..g done in FreeCADApp or the extensions Part, PartDesign, Mesh, ... There you have access to classes like App::Application that manages the App::Document's. An App::Document manages the App::DocumentObject's what we call features. The App::Document is the central point where we manage the DAG, the recompute logic, the undo/redo and so on.

    On GUI side we have the class Gui::Application to handle the Gui::Document's. A Gui::Document handles the visual representation of a feature and we call it ViewProvider. All this is then implemented in modules like FreeCADGui, PartGui, PartDesignGui, MeshGui, ...
  • The classes DocumentObject and ViewProvider have properties to control their behaviour. So, e.g. a box feature has properties to control its length,width or height while its GUI counterpart has properties like color, transparency, ... to affect the visual representation.
  • Whenever you modify the value of a property of a feature then also the App::Document is notified. Thanks to the MVC (Model View Controller) pattern the Gui::Document is directly notified so that it can forward the change to the associated view provider. So, if e.g. the shape of the box has changed the view provider can re-tessellate the new shape.
  • We have a huge list of property types to handle text, numbers, physical quantities, materials, colors, transparencies, .... A special category are the link properties. As said above they are the central point to describe the dependencies among the features of a document.
The most important link property types are:
  • PropertyLink -- this allows a feature to link a single feature within the same document.
  • PropertyLinkList -- this allows a feature to link several features
  • PropertyLinkSub -- this allows a feature to link a single feature and additionally reference sub-elements.
    Example: If you want to model a pocket then for the needed sketch it's important to know on which sub-element (e.g. Face6) of the linked feature it must be mapped to.
  • PropertyLinkSubList -- this allows a feature to link to several sub-elements of several features.
  • PropertyXLink, PropertyXLinkSub, PropertyXLinkSubList, PropertyXLinkList or PropertyXLinkContainer -- they allow to link features of different documents. This is the core part for assemblies.
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Manipulating InList and OutList

Post by wmayer »

Hermit wrote: Thu Mar 11, 2021 8:04 am I have two FeaturePython classes: Box and BoxDimensions.

I'd like to make BoxDimensions part of Box's InList. I've search high and low for a method of doing this in the Wiki, API docs, and forums, and have only found ways to read and iterate InList/OutList, but not how to write/insert/append to these lists.
I assume you want to have a Box feature that depends on a BoxDimension feature. The BoxDimension has the properties to control length, width and height of the Box feature.

So, the Box feature class must have a link property of the type App::PropertyLink to link to the BoxDimension. The BoxDimension class must have three App::PropertyLength to handle length, width and height.
Hermit wrote: Thu Mar 11, 2021 10:15 am I have two FeaturePython classes, Box and BoxDimension. I would like BoxDimension's InList to contain a Box object. Similarly, I would like Box's OutList to contain the corresponding BoxDimension object.
If you have two features A and B and if A is part of B's InList then B is automatically part of A's OutList. So, there is nothing special you have to worry about.

The implementation can look like this:

Code: Select all

import FreeCAD
import Part

class BoxDimension:
  def __init__(self, obj):
    obj.addProperty("App::PropertyLength", "Length").Length = 1
    obj.addProperty("App::PropertyLength", "Width").Width = 1
    obj.addProperty("App::PropertyLength", "Height").Height = 1
    obj.Proxy = self

class Box:
  def __init__(self, obj):
    obj.addProperty("App::PropertyLink", "Link").Link = None
    obj.Proxy = self
  def execute(self, obj):
    if obj.Link is None:
      return
    l = obj.Link.Length
    w = obj.Link.Width
    h = obj.Link.Height
    obj.Shape = Part.makeBox(l, w, h)



doc = App.newDocument()
dim = doc.addObject("App::FeaturePython", "BoxDimension")
box = doc.addObject("Part::FeaturePython", "Box")
dim_proxy = BoxDimension(dim)
box_proxy = Box(box)
box.ViewObject.Proxy = 0
box.Link = dim

dim.Length = 5
dim.Width = 3
dim.Height = 7
doc.recompute()
User avatar
Hermit
Posts: 27
Joined: Sat Sep 30, 2017 12:00 am
Location: Victoria, Canada
Contact:

Re: Manipulating InList and OutList

Post by Hermit »

wmayer wrote: Thu Mar 11, 2021 11:11 am
If you have two features A and B and if A is part of B's InList then B is automatically part of A's OutList. So, there is nothing special you have to worry about.

The implementation can look like this:
...
Thank you! Yes, this is what I am looking for.

So if I write some more examples of the other LinkXYZ properties, could I contribute it to the Wiki?
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Manipulating InList and OutList

Post by wmayer »

Hermit wrote: Thu Mar 11, 2021 11:21 am So if I write some more examples of the other LinkXYZ properties, could I contribute it to the Wiki?
Sure! If you don't already have write permission for the Wiki you should ping jmaustpc.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: Manipulating InList and OutList

Post by Kunda1 »

wmayer wrote: Thu Mar 11, 2021 11:24 am
Hermit wrote: Thu Mar 11, 2021 11:21 am So if I write some more examples of the other LinkXYZ properties, could I contribute it to the Wiki?
Sure! If you don't already have write permission for the Wiki you should ping jmaustpc.
@Hermit, DM me with a valid email and I'll set you up
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
User avatar
Hermit
Posts: 27
Joined: Sat Sep 30, 2017 12:00 am
Location: Victoria, Canada
Contact:

Re: Manipulating InList and OutList

Post by Hermit »

I have a related question. Once I have created my Box and BoxDimension as above, how do I make Box a parent of BoxDimension in the model tree?

Is this ViewProvider-specific? Or does it concern PropertyLink types again?

I am stuck searching/reading the source code for these answers but asking someone who knows would be much faster.
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Manipulating InList and OutList

Post by onekk »

Se this portion of the code posted above.

Code: Select all

doc = App.newDocument()
dim = doc.addObject("App::FeaturePython", "BoxDimension")
box = doc.addObject("Part::FeaturePython", "Box")
dim_proxy = BoxDimension(dim)
box_proxy = Box(box)
box.ViewObject.Proxy = 0
box.Link = dim
box.Link = dim

That is

you are using the documentobject dim and the documentobject box

and assign the cdocumentobject dim to the Property Link of the documentobject box.

Regards


Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Manipulating InList and OutList

Post by wmayer »

Hermit wrote: Fri Mar 12, 2021 10:47 am I have a related question. Once I have created my Box and BoxDimension as above, how do I make Box a parent of BoxDimension in the model tree?

Is this ViewProvider-specific? Or does it concern PropertyLink types again?

I am stuck searching/reading the source code for these answers but asking someone who knows would be much faster.
It's view provider specific. You have to implement the function claimChildren().

Code: Select all

import FreeCAD
import Part

class BoxDimension:
  def __init__(self, obj):
    obj.addProperty("App::PropertyLength", "Length").Length = 1
    obj.addProperty("App::PropertyLength", "Width").Width = 1
    obj.addProperty("App::PropertyLength", "Height").Height = 1
    obj.Proxy = self

class Box:
  def __init__(self, obj):
    obj.addProperty("App::PropertyLink", "Link").Link = None
    obj.Proxy = self
  def execute(self, obj):
    if obj.Link is None:
      return
    l = obj.Link.Length
    w = obj.Link.Width
    h = obj.Link.Height
    obj.Shape = Part.makeBox(l, w, h)

class ViewProviderBox:
  def __init__(self, vp):
    vp.Proxy = self
  def attach(self, vobj):
    self.Object = vobj.Object
  def claimChildren(self):
    return [self.Object.Link]
  def __getstate__(self):
    return None
  def __setstate__(self, value):
    return None


doc = App.newDocument()
dim = doc.addObject("App::FeaturePython", "BoxDimension")
box = doc.addObject("Part::FeaturePython", "Box")
dim_proxy = BoxDimension(dim)
box_proxy = Box(box)
box_view = ViewProviderBox(box.ViewObject)
box.Link = dim

dim.Length = 5
dim.Width = 3
dim.Height = 7
doc.recompute()
User avatar
Hermit
Posts: 27
Joined: Sat Sep 30, 2017 12:00 am
Location: Victoria, Canada
Contact:

Re: Manipulating InList and OutList

Post by Hermit »

Thank you again wmayer. I have wiki access now and will be updating the related pages so that others are aware.
Post Reply