Steps forward to assembly infrastructure

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
yorik
Founder
Posts: 13640
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Steps forward to assembly infrastructure

Post by yorik »

Thanks for the detailed explanation DeepSOIC... Understanding better now. This is a more specific issue than I thought, sorry about the noise... I don't have a very strong or useful opinion... Seems to me someone could need both ways, depending on the situation...
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Steps forward to assembly infrastructure

Post by ickby »

DeepSoic, I think I start seeing where your idea is heading. So basically you still build the graph structure, but with the introduction of a Instance you try to achieve the following two points:
1. Hide that complexity from the user by showing him a tree only
2. Making a clear object hierarchy with the master object and its instances

In regards to your picture with the Instance (Clone) I see the graph in the following situation: Part and Instance are again in a another Part. What you mean when talking from a tree is that from every Instance there is only one path to the graph top, not many possible.
ickby wrote:2. ... Getting the global position of a shape? Not possible.
I already said how it is to be done: Selection object should include the list of instances, through which the object was selected. Nothing impossible.
Having this information in selection only is not enough. One needs an API to query a objects positions in the document on App level, even if it forms a graph in reality. Initially I thought you try to prevent that with a tree structure, but I think I misunderstood you there, as you only hide the graph from the user. So such an API is easily possible, one would add a few functions to DocumentObject like "getAllInstances()" or "getAllPathsToObject()" which allow to handle the graph, with instances or without doesn't matter much.
This also means that you still would do a lot of "bottom-up" searching of the graph (e.g. from object to all objects linking to that object) where the current document object model is not well suited for. Hence jriegels adoptions are still valuable for speeding this up.

DeepSOIC: there is a master Part, that is editable, and instances of the Part, that aren't editable. Deleting master part will delete actual geometry, and break all its instances.
vs.
ickby: there is no master part. Any "instance" of part is just another part re-using some objects. Any "instance" can be deleted with no consequences; only when the very last instance that uses the objects is deleted, the actual objects (geometry) will get lost
I thought about this today too, this is a clear advantage of your approach. No need for reference counting.

A advantage of mine is that we need no control if a object already belongs to another Coordinate system, and things like "instance of instance" must also be forbidden. But that is nothing impossible.

So honestly after I think I fully got your idea it does look pretty good. I would still like to think a few days about it, you know, I'm a marked child regarding failed assembly structures and want to be sure there is not a show stopper we miss.
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Steps forward to assembly infrastructure

Post by ickby »

Ok a few more thoughts, as always open for discussion and for proving me wrong :)

1. My assumption " from every Instance there is only one path to the graph top" is wrong. As one can stack assemblies and parts wildly the following is easily achived. A simplified example, where Instance1 is at 2 places, but many more complex things are possible (e.g. nut is 10 times in motor which is 5 times in machine):

Code: Select all

     CS2           CS3
       |              |
Instance2       Instance3
        \           /
          \       /
            CS1
              |
          Instance1
              |
            CS0
This means even with instances full graph handling is needed. The only valid identifier is a full Path from toplevel to object. Hence the implementation of the CS structure cannot be simplyfied with instances. DeepSOICs and my approach would lead to nearly the same graph handling code.

2. A objects location cannot be determined by its instances only. There may be no instance of a object and still it may be 100 times in the document. That happens if an assembly it is in has instances. If one wants to know all occurences one must hence not search the objects instances but all paths from this object to the graph toplevel. Each occurance can only be described by a path of stacked CS's. This means the DocumentObject API for handling this must allow retreiving all Paths to this object. Hence it is exactly the same for DeepSOICs and Ickbys approach.

3. Instance must be of type GeoFeatureGroup. Considering the two points above I think the Instance object must be of this type to allow building CS paths as simple lists of GeoFeatureGroups. It would than seamlessly integrate into other types of GeoFeatureGroups like the current Part or coming Assemblies. If it would be of any other type a tremeandous amount of extra type checking and handling would need to be introduced.

4. Placement considerations. In ickbys approach once a CS or object is added two times to anything both would have always the same placement. This would be unintuitive: If the user reproduces an assembly he expects to give it different placements. In ickby approach he must first introduce annother CS where he puts in the copied one and move this. This is strange. This step of an additional CS is automated by DeepSOICs approach, as the Instance object would be that extra CS by default. This is IMHO more intuitive.


So I think code wise both approaches are pretty equal, all the hard stuff definitely is. The differences come down to:

1. Tree: Showing all childs vs. Showing instance object
2. Master object vs one objeckt multiple times: difference in deletion and editing behaviour
3. Placement: Automated possibility of changed placement with Instances vs. user must add additional CS.

I think in all 3 of those points DeepSOICs idea wins, even in point 1 I changed my opinion after thinking more about it.
Marco_T
Posts: 262
Joined: Mon Jan 11, 2016 11:58 pm
Location: Di ca da l'aghe

Re: Steps forward to assembly infrastructure

Post by Marco_T »

NormandC wrote:Without pretending to understand the whole issue, I think this is where implementing specific file extensions would have a huge advantage: for example *.FCPart for a document containing a single part, *.FCAsm for an assembly file linked to other files. All the major commercial parametric CAD programs do that. They even have a separate file extension for drawings (*.FCDwg :D ).
[...]
Hi Normand,
I have used for some years that software (what it add a colon) and I like the philosophy to mark the various files with different extensions. But "that" software uses for every environment (draft, asm, part, sheet metal...) only specific workbenches. In my opinion it is useful because prevents to add a wrong feature to a specific and delicate object (sheet metal with different thickness, directly edit an assembly instead of a his part...) but I think this is "less freecadized" (against his philosophy) and more "solidedgeized" and we should rewrite many things to separate workbenches for each enviroment....
Editing the part would open the FCPart document separately. It could be done from any instance shown in the tree, not only from the "original" one.

Now that I think about it, it is exactly what the Assembly2 module does.
I confirm and I like that.

--
Marco_T
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Steps forward to assembly infrastructure

Post by triplus »

And what about performance. Having for example 1000 instances of the part (@DeepSOIC) vs. 1000 times reusing objects form the part (@ickby)?
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: Steps forward to assembly infrastructure

Post by DeepSOIC »

triplus wrote:And what about performance. Having for example 1000 instances of the part (@DeepSOIC) vs. 1000 times reusing objects form the part (@ickby)?
I think neither approach has advantage, as with so many objects, rendering/selection will be the bottleneck. Or.. maybe ickby's approach is at win here, because one could select an object in tree. With instances, assuming they don't allow to expand their content in tree view, only picking in 3d view will be possible.
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Steps forward to assembly infrastructure

Post by triplus »

DeepSOIC wrote:With instances, assuming they don't allow to expand their content in tree view...
If we really would want to achieve that it could happen with your approach couldn't it? Anyway if there isn't any fundamental difference good. But if one approach would have a clear advantage (performance) that would need to be acknowledged.

And what about using the assembly geometry after directly. To add additional feature to it (only to one "instance" and not all of them). Would any of the proposed approaches provide that?
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: Steps forward to assembly infrastructure

Post by DeepSOIC »

triplus wrote:And what about using the assembly geometry after directly. To add additional feature to it (only to one "instance" and not all of them). Would any of the proposed approaches provide that?
In ickby approach - yes, it is trivial. Just activate the "instance" (which is a Part container most likely), and add extra features to it. With my approach (instance objects) - no you can't. You must either edit the original Part, which will automatically propagate to all instances of the Part, or create another Part with the new features, and replace the instance.

This is probably the main big advantage for ickby approach. Yet at the same time it is a disadvantage, because updating all same parts at once becomes a problem.
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Steps forward to assembly infrastructure

Post by triplus »

I see therefore in your proposal instead of using the instance of the part 1000 times one would need to use it 999 times. And for that one instance that needs to have additional feature added. Basically a new part would be created with the added feature and that would be used instead.

There is one thing i don't understand when it comes to @ickby proposal. In tree view there would be only one entry? Similar to using the Sketch multiple times and only one Sketch is listed in the tree view. How would that work? What is the actual geometry in the end? A copy/duplicate/clone or something else? As there are multiple solids of the same part in 3D View and only one Part feature tree in the Assembly tree view?
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: Steps forward to assembly infrastructure

Post by DeepSOIC »

ickby wrote:1. My assumption " from every Instance there is only one path to the graph top" is wrong. As one can stack assemblies and parts wildly the following is easily achived. A simplified example, where Instance1 is at 2 places, but many more complex things are possible (e.g. nut is 10 times in motor which is 5 times in machine):
Actually, your assumption is almost right. You should replace "graph top" with "top of the document", or "global CS", and "one path" with "container path".

The word "path" is also ambiguous. Let's define some terminology again.
PATH: sequence of objects to consider when resolving an object
RELATIVE PATH: similar to path, but we must clearly express what objects to leave and what objects to enter. Let's notate them with + and - signs: "+" means go into container, and "-" means leave container. + and - correspond to whether we take placement as inverse or not when computing transformation.
FULL PATH: includes plain containers, moveable containers, and instance objects
CS PATH: take full path, and keep only things that affect coordinate systems.
INSTANCE PATH: take full path and throw away everything but instance objects.
CONTAINER PATH: full path that has no instance objects involved (if full path has instances, it cannot be converted to container path).

With my approach:
* container path to top of the document is unique for each object. (document is also a kind of container, just a little bit of a special one)
* full path can be completely recovered from instance path and the context to where we are resolving it.
Since full path can be recovered from instance path, I propose to remember instance paths only, and recover full path on the fly.

Let's consider a reasonably complex example. This is how tree view will look like:

Code: Select all

Document
    Part
        Box
    Part001
        Cylinder
        SubPart
            Wedge
    SubAssembly
        instance(Part)
        instance001(Part)
        instance002(Part001)
        Part002
            sphere
        Torus
    FinalAssembly
        instance003(SubAssembly)
        instance004(Part002)
        Constraint
Container path of Wedge (unique): +Document +Part001 +SubPart

All possible full paths to Wedge (i.e. count how many times to render Wedge):
1. +Document +Part001 +SubPart +Wedge
2. +Document +SubAssembly +instance002 +SubPart (note: Part001 is not included on purpose, it is replaced by Instance)
3 +Document +FinalAssembly +instance003 +instance002 +SubPart
How to gather all these paths by code? 1 is container path, that always exists for any object and is unique. Next, find all instances of any object from the container path. Instances of Wedge? no. Instances of SubPart? no. Instances of Part001? yes, instance002. Now repeat this for finding all paths to instance002.

Let's recover path 3 given only instance path and target object: +instance003 +instance002 Wedge
* prepend container path to instance003: +FinalAssembly +instance003 +instance002
* instance003 is instance of SubAssembly. Insert container path from within SubSassembly to instance002. This path is trivial, so nothing to do (instance002 is already within SubAssembly). -> +FinalAssembly +instance003 +instance002
* instance002 is instance of Part001. Insert container path from within Part001 to Wedge. -> +Document +FinalAssembly +instance003 +instance002 +SubPart
Done.

Container path from Wedge to Box: -SubPart -Part001 +Part
Container path from Wedge to Sphere: -SubPart -Part001 +SubAssembly +Part002
There are other paths possible from Wedge to Sphere, but these other paths involve instances, so they are not container paths.

Let's try to recover broken path given only instance path and target object: +instance002 +instance003 Wedge
* prepend container path to instance002: +SubAssembly +instance002 +instance003
* instance002 is instance of Part001. Insert container path from within Part001 to instance003. This path is -Part001 +FinalAssembly. It contains something with minus sign -> ERROR!



Logic to test if direct linking from object A to object B is possible: Figure out relative container path to get from A to B. If there are containers with placement in that path <=> linking is impossible.
Post Reply