Steps forward to assembly infrastructure

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
ickby
Posts: 2457
Joined: Wed Oct 05, 2011 7:36 am

Steps forward to assembly infrastructure

Postby ickby » Sat Oct 08, 2016 11:46 am

Hello all,

after an epic underestimation of needed time and quite some headaches today the extension code has been merged, and with this yet another large step for the assembly infrastructure has been taken. I like to talk a bit about the next steps as I think they are needed, and hope to get some guys to hepl me out on this (*hust* deepsoic *hust*). So here is what I belive should be done next:

  1. PartDesign adoptions. Here the extension code started and we should finalize our goals
    1. Port PartDesign Body to use OriginExtension so that it can be recognized as a local CS in a uniform manner.
    2. Move the Body specific "linear Group" features to the Group extension. I think this special behaviour with a defined (and changable) order is needed at many places, having it in the extension and being able to choose the behavior by developers is worth it
  2. App adoptions
    1. Prevent links into different coordinate systems. There should be a special link property which allows this, but in all default cases this should be forbidden.
    2. Port tools to recognize local coordinate systems. Thinks like duplicate for example should add the new object to the same CS as the initial one
  3. Document dependencies
    1. Port Jriegels adoption of the document graph to master, as it is better suited for the now often needed bottom-to-top traversal
    2. Extend Document/DocumentObject API for stacked coordinate systems, e.g. add methods to get all possible paths to the object (as it can be used multiple times), calculate global placement, calculate placement in other CS etc. . This all needs enhanced graph handling.
    3. Extend Selection to also store path of selected object (as it can be used multiple times and the multiple instances only differ in the CS)
    4. Adopt importing/exporting to use the CS
  4. Gui adoptions
    1. Enable the tree to show a object multiple times

Any additional input for needed code? Personally I like to work on point 3 next and have already started to port jregels code over. . DeepSOIC, you already have done quite some work on point 1. Would you like to help out there?
User avatar
NormandC
Posts: 12262
Joined: Sat Feb 06, 2010 9:52 pm
Location: Québec, Canada

Re: Steps forward to assembly infrastructure

Postby NormandC » Sat Oct 08, 2016 11:33 pm

That's great news ickby. :)
ickby wrote:(*hust* deepsoic *hust*)

Had to look it up. Take your syrup and stop coughing in German, ickby! :D
DeepSOIC
Posts: 4670
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Steps forward to assembly infrastructure

Postby DeepSOIC » Sat Oct 08, 2016 11:51 pm

OK, now I saw this!

As for 1, all I've done is not what you want - I have another body aimed at non-linear things like Part features. I don't know what else is this linear stuff is needed for (Path?), but I now will include that linear layer to structure.
Without extensions, I see it like:
Part::BodyBase: a container that has shape, Tip property, and maybe origin. Not to be used directly.
Part::Body: the general-purpose body container aimed at Part features, Draft, etc.
Part::SequenceBody: the body to support/manage linear part-design-like sequences
PartDesign::Body: PartDesign's specialization of Part::SequenceBody
How to deal with extensions here I'm not yet sure...

As for 2, I have a quite big plan, I will try to post it soon to start a discussion, as it potentially influences other stuff.

As for 3, I have a strong opinion against having a feature in multiple containers at once. I think an instance object should be used instead, to have one object displayed in multiple places. I think this needs discussion.
ickby
Posts: 2457
Joined: Wed Oct 05, 2011 7:36 am

Re: Steps forward to assembly infrastructure

Postby ickby » Sun Oct 09, 2016 6:10 am

Ok I'm looking forward to your ideas. I'm postponing all work on that till then.

If the work you done on bodies is not easily transferable to the new System it is of course also ok to Split work differently if you are more interrested in the other points. I'm rather indifferent to what I'm Work on next.
triplus
Posts: 4988
Joined: Mon Dec 12, 2011 4:45 pm

Re: Steps forward to assembly infrastructure

Postby triplus » Sun Oct 09, 2016 12:29 pm

Good to see this progressing and i guess more discussion will be needed in the future around point 1. To align different views better. Likely once the debate will go further it will be easier to diagnose if there is fundamental difference in views or just specific details. Hopefully it is only about specific details and single solution will prevail.

As we can hardly cope with things like having one new container. Having 2 of them would further add to the complexity and what would be next? Building docker for all this containers? ;)
DeepSOIC
Posts: 4670
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Steps forward to assembly infrastructure

Postby DeepSOIC » Sun Oct 09, 2016 6:20 pm

Here's my proposal, mostly relevant to point 2. Many elements of this proposal have been influenced by my experiment called Part-o-magic.

0. Container tree or container graph?
With tree, it is easy to figure out the container path to an object given just the object. That makes things simpler, because otherwise we must implement link type that will track changes to container tree. And in general, I think this makes things simpler and easier to manage overall.

As for full graph support for containers, it's not clear to me, what it should be used for. Multiple instances of same part? Like:

Code: Select all

Part
    solid1
    solid2
Part001
    solid1
    solid2

If that is supposed to present two instances of the same part, it's unclear how would we add another solid to both parts. Multiple active containers at once? I don't know.

So I would like to see Part - Instance pair. However, that has problems too. For example, how do I make a derivative of a Part, which is slightly different (e.g. has a number engraved onto some surface)? That will require another kind of object, something like "DerivedPart" container, and I'm not sure how to organize it.

1. Single active container.
There should be exactly one active container, because dealing with current situation that allows two active containers, one of type Body and one of type Part, doesn't make any sense IMO. What if we have active body that doesn't belong to active part, what is it for?

It's enough to have only one, because from it, we can easily figure out all upper level containers in case we need them.

If container structure is to support graphs, active container has to store the whole path, not just pointer to object.

2. Introduce ActiveContainer as member of App, so that we can use "App.ActiveContainer.addObject('class','name')". And then, replace all "App.ActiveDocument.addObject(..)" with calls to ActiveContainer, in all other workbenches.
That will allow object type filtering on container side. For example, if I try to add a Part Cube when I have a PartDesign Body active, App.ActiveContainer.addObject is to throw an error that this container doesn't accept this object.

A more ugly approach to this problem is to re-use App.ActiveDocument for App.ActiveContainer. This will have a benefit that no porting of other code is necessary, but is ugly because the attribute is named not according to what it actually is.
A compromise approach is to make App.ActiveDocument.addObject(...) act as if it is App.ActiveContainer.addObject. Again, no porting of other workbenches is necessary, and there is no terribly wrong naming.

3. Selection
I think, this is the easiest way to ban cross-container links: make getSelection and getSelectionEx, by default, only return selected objects from active container. And make it return more only when supplied with additional argument, like so: Gui.Selection.getSelection(App.ActiveDocument)

Next tricky part is selection of objects in instances. This is definitely needed for assemblies, and I don't know how technically easy it is to do that. Maybe, for each selection object, provide a Path attribute, something similar to coin's SoPath.

This will require specialized link type. If we are not dealing with graph container structure, but with tree, then it's enough to provide the actual object and the list of instance objects to use when resolving placement. If we go for full graph, then it becomes necessary (I think) to include the whole container path into the link, and track/update it as the container structure changes. I think this tracking is very tricky, and this is the main reason to stick with container tree rather than graph. If you have a solution to that, then we can go for full graph of course, as it is more flexible.

I think that's it for now.

summary (my preferred way).
* Container structure must form a tree. Multiple instantiations of objects are to be realized with Instance object, which is NOT a container. Instance object is to have special meaning for new propertylink type.
* only one active container. Expose it in very accessible App.ActiveContainer (not hidden as some attribute of viewer), and it must work without Gui.
* App.ActiveDocument.addObject is to act as if it were App.ActiveContainer.addObject (and there must be a way to suppress it, maybe extra argument). -> no porting of other workbenches required
* Gui.Selection.getSelection() should return the selection limited to active container. Gui.Selection.getSelection(App.ActiveDocument) should be required to get full selection. This automatically provides the general ban for cross-container links.
* Selection is to be able to provide path by listing instance objects the actual selected object is to be reached through.
* new PropertyLink type, to store list of instances through which the linked object is to be reached. All container-related transformations can be computed on the fly, so they should not be stored by the property.


More minor points:
* ShapeBinder should become the tool to make cross-container shape links. I propose to move it to Part module.
User avatar
yorik
Site Admin
Posts: 8651
Joined: Tue Feb 17, 2009 9:16 pm
Location: São Paulo, Brazil
Contact:

Re: Steps forward to assembly infrastructure

Postby yorik » Sun Oct 09, 2016 9:56 pm

Great plans guys!

My 2 cents:

ickby wrote:App adoptions
Prevent links into different coordinate systems. There should be a special link property which allows this, but in all default cases this should be forbidden.


This seems very PartDesign-centric for me, I think many parts of freecad will still work totally outside local CS infrastructure... And there are probably a lot of external workbenches that would need to have their code changed.

ickby wrote:defined (and changable) order

I made already some experiments with changeable Group order in the Path WB (the Path Compound object), indeed that would be useful in many places. Would be a good example for an extension :)

DeepSOIC wrote:0. Container tree or container graph?

This is not too obvious for me either... The tree is indeed something super simple and clear to the user. Graphs can be quickly really messy and not understandable. On the other hand, since a long time models are not purely linear anymore in FreeCAD, and the tree doesn't reflect that at the moment. I don't like the object appearing multiple times in the tree either, this is hard to solve... :|

DeepSOIC wrote:A more ugly approach to this problem is to re-use App.ActiveDocument for App.ActiveContainer.


DeepSOIC wrote:I think, this is the easiest way to ban cross-container links: make getSelection and getSelectionEx, by default, only return selected objects from active container. And make it return more only when supplied with additional argument, like so: Gui.Selection.getSelection(App.ActiveDocument)


Wouldn't that more or less impose PartDesign style to the whole FreeCAD? I think we should take care to avoid that. For ex, I'm not convinced yet that working with containers is appropriate in Arch... There are just too many independent objects that don't really fit into a same structure. I didn't really make my mind yet, but I think it might be safe to consider that many workbenches will not adopt the whole PartDesign/Body/Container paradigm.
DeepSOIC
Posts: 4670
Joined: Fri Aug 29, 2014 12:45 am
Location: Saint-Petersburg, Russia

Re: Steps forward to assembly infrastructure

Postby DeepSOIC » Sun Oct 09, 2016 10:16 pm

yorik wrote:
DeepSOIC wrote:A more ugly approach to this problem is to re-use App.ActiveDocument for App.ActiveContainer.


DeepSOIC wrote:I think, this is the easiest way to ban cross-container links: make getSelection and getSelectionEx, by default, only return selected objects from active container. And make it return more only when supplied with additional argument, like so: Gui.Selection.getSelection(App.ActiveDocument)


Wouldn't that more or less impose PartDesign style to the whole FreeCAD? I think we should take care to avoid that. For ex, I'm not convinced yet that working with containers is appropriate in Arch... There are just too many independent objects that don't really fit into a same structure. I didn't really make my mind yet, but I think it might be safe to consider that many workbenches will not adopt the whole PartDesign/Body/Container paradigm.
I don't know what do you mean by "PartDesign style". Containers are here to isolate things. This isolation is needed because containers have placement, but that placement is not directly applied to contained objects. Placement leads to:
* the object that links to object in another container in geometric manner must take care of the difference in placements explicitly. It can simply ignore placements of containers, which is how things happen now. This is very counterintuitive, but I also find it very useful.
* the Placements of all containers crossed by link thus becomes something your feature is implicitly depending on. If handled simply, by declaring these dependencies as OutList, this will very likely cause a dependency loop.
So, the isolation is here to solve it by avoiding it, and special tools (like PartDesign ShapeBinder) are going to be needed for crossing container boundaries. Then, a slow process of porting many many tools to directly support cross-container links will take place.

But. We can have unmoveable containers (like DocumentObjectGroup), that won't be isolated.

EDIT: container is like a subdocument. Within a container, a regular graph of features can be established. If you don't use containers at all, FreeCAD would behave exactly as it did before.
triplus
Posts: 4988
Joined: Mon Dec 12, 2011 4:45 pm

Re: Steps forward to assembly infrastructure

Postby triplus » Sun Oct 09, 2016 10:33 pm

DeepSOIC wrote:If you don't use containers at all, FreeCAD would behave exactly as it did before.


And the movable geometry not being put in container will have basically the same assembly capabilities support as the one put in container? If yes good if no Yorik has a point.
ickby
Posts: 2457
Joined: Wed Oct 05, 2011 7:36 am

Re: Steps forward to assembly infrastructure

Postby ickby » Mon Oct 10, 2016 5:00 am

yorik wrote:
ickby wrote:App adoptions
Prevent links into different coordinate systems. There should be a special link property which allows this, but in all default cases this should be forbidden.


This seems very PartDesign-centric for me, I think many parts of freecad will still work totally outside local CS infrastructure... And there are probably a lot of external workbenches that would need to have their code changed.


I think we must get the terminology clear here, I think calling everything container is missleading as they include totally different behaviour. Thinking in coordinate systems is more appropriate. A normal Group as it is used now is not a local Coordinate system and hence links between those groups are of course possible. So current behavior does not change at all. But the newly introduced local coordinate systems (GeoFeatureGroup and OriginGroup) must not have links in between. The reason is simple: Their child position in the global CS depends on the local CS. Now imagine you have a boolean which has one tool in CS1 and annother in CS2. If one moves CS1 the boolean must change. Two reasons this is bad: It is completely strange for the user as he expects to have separated things and also nearly impossible to implement in FreeCAD, as it does not fit in the recomputation model.


0. Container tree or container graph?

Let's call it coordinate-System tree or coordinates-ystem path :). I think our both approaches are not that different. I think we agree that it must be possible to reuse objects and whole assemblies in an efficient manner. What I don't like about the InstanceObject.

1. This works well for individual DocumentObjects. But assemblies will reuse subassemblies multiple times (e.g. wheel assembly is used 4x in car). In your design you make a InstanceObject of a Subassembly. This gets IMHO confusing very quickly, as you can't open a subassembly in the tree to see what is inside etc.
2. The internal structure does only know exactly one position of a Object. Even if it is used in multiple instances and seen multiple times on the screen by the user, it is impossible to get more than the single original position. So what you have done is to virtually allow a object to be at multiple positions like my graph, at least the user see it like that, but deny that code wise and make it impossible to handle. Getting the global position of a shape? Not possible.
3. When selecting something in the 3d view, it must select the original object. Or the instance? A bit confusing.
4. What if document formats allow to reuse subassemblies at multiple positions? I think STEP does that (need to double check that) and so we would loose an easy import/export and must change the document structure
5. Operations would always be done on the orginal object in the 3d scene and not where the user selects it. For example the user selects a sketch in the Instance of a Part. Than he hits "edit". The edit mode would be at a totally different position in the 3d scene as it edits the original sketch. such behavior is strange.

My main argument is point 2. Assemblies will always reuse objects and whole assemblies at multiple positions. That is just how it works and how everyone want to use it. Not reflecting that in the code will bring all kind of problems. We should accept that fact and making handling it in the code work well by providing everything needed for the graph structure. An object just will be in multiple positions, we must be able to retrieve those and handle those.

1. Single active container.

I like this idea. I agree that the active Part/ active Body is not appropriate anymore. I think JRiegel envisioned the structure a bit different to what we are doing now, so IMHO we are free to change "active" stuff as needed.

2. Introduce ActiveContainer as member of App, so that we can use "App.ActiveContainer.addObject('class','name')". And then, replace all "App.ActiveDocument.addObject(..)" with calls to ActiveContainer, in all other workbenches.
That will allow object type filtering on container side. For example, if I try to add a Part Cube when I have a PartDesign Body active, App.ActiveContainer.addObject is to throw an error that this container doesn't accept this object.

I like the ActiveContainer object. The general Idea is very good, seem very "Freecad'ish".

3. Selection

Need to think about that stuff, seems good on first thought.