Links

Discussion about the development of the Assembly workbench.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Links

Post by realthunder »

Ahhh... how come I am always later for the party. I am really bugging with the current behavior of App::Part, but I was too late to make my opinion matter. Hope this time it is not too late. I have almost completely re-write App::Link. And I have solved all the technical problems, and I am now aiming for a PR. It is huge, over 5K lines of code spanning more than 80 files. And is likely to require months to sort out all the potential bugs. But I think the benefits out weights the trouble. Basically, I've introduced to FC a new concept similar to symbolic links on unix system, or shortcuts for Windows. When an object is liked, its 3D view representation gets shared, with seemly separate identify in FC, you have separate placement, scale, and visibility. The tree view item of the link shares the linked objects icon and claimed children. When an App::Part is linked, all its children, and sub parts, and children of those sub parts (if the sub part is also linked) will have full qualified name access. This is the critical part, that I am really hoping I am not too late. I think geometry modeling and assembling should be separated. And App::Link is the link between them. All objects should by default be linked before adding to an App::Part. And App::Part should be linked also. I've even implemented tree item hiding feature to better organize the tree. The actual App::Part can be hidden by default. Some highlights of the feature

* App::Link supports inter document object linking. I added PropertXLink which is derived from PropertyLink. It can handle both internal and external linking. External referenced document will be automatically opened along with the document containing PropertyXLink.
* App::Link'ed object has independent placement, scale, and visibility. The linked object's placement can be either overridden or combined.
* App::Link tree view item shares the linked object's icon and claimed children. When selected, the property view merges the link and the linked objects property for easy editing. If multi-level linking is used, it will merge the final linked object.
* App::Link has python method getSubObjects to retrieve selected sub object or subelement (Face, Edge, Vertex) that are fully transformed and scaled.
* App::Link'ed object in 3D view supports hierarchy selection. When you click an already selected item, it will automatically selects its parent object, with full tree view synchronization to help navigate through complex hierarchies. You need enable selection sync in tree view context menu first. See the demo below.
* There is also Part::Link. which I've added an icon to Part workbench, that supports geometry modeling, meaning you can use it with other Part operations. This feature is still experimental at the moment. The benefits over Draft.Clone is that no geometry data is saved, and no duplicates in 3D representation, and fully utilize OCC's internal geometry data sharing. The shape linking can be turned off with LinkShape property, which will then makes it behave just like App::Link.
* You can now freely hide any items in the tree, and toggle those hidden items, all through tree view context menu. It can also be done in script.
* SceneInspector is upgraded to show linking nodes, you can check out how the coin nodes are shared.

You can try it with my branch at https://github.com/realthunder/FreeCAD/tree/Link
@DeepSOIC you may need to checkout a new one because I just rebased it.

Now some demo here. It makes heavy use of multi-level linking, which I think would really benefits assembly use cases. What you are seeing is 400 cubes, divided into 4 groups (App::Part). Each group contains 100 links to the same typelink containing in other App::Part. The purpose of those type links is so that you can change individual group of the objects, which I haven't shown in the demo. All typelinks are link to rootLink, which cross link to another document partDoc containing and actual cube object. Now, if I change the rootLink to point to a sphere, you can see instant change of all objects in the 3D view. Mind you that all objects in the 3D view actually shares the Coin node, but as you can see they are fully independent here. You can select, move, hide/show independently. Next I point rootLink to a self taping screw with full threading details. Again the change is instant. Finally, I point rootLink to partGroup inside the same document. partGroup contains four external screw links. Now you have 1.6K screws on screen, and again the change is almost instant, although my PC without dedicated graphics card is skipping frame here.
Image
The component document size is 189KB, while the assembly file is only 24KB. The files are attached. The loading time is a bit slow, about 10 second on my PC because of the number items. Need optimization here. Assuming you had the component file, the code to produce the assembly is

Code: Select all

def test6(count=(10,10), groupCount=(2,2)):
    partDoc = None
    try:
        partDoc = FreeCAD.getDocument('partDoc')
    except Exception:
        partDoc = FreeCAD.openDocument('partDoc.fcstd')

    doc = FreeCAD.newDocument('partLink')
    doc.saveAs('partLink.fcstd')

    partGroup = doc.addObject('App::Part', 'partGroup')
    partGroup.ViewObject.Visibility = False
    partGroup.ViewObject.ShowInTree = False
    partRoot = doc.addObject('App::Link','partRoot')
    partRoot.LinkedObject = partDoc.Compound
    partRoot.ViewObject.Visibility = False
    for i in range(groupCount[0]):
        for j in range(groupCount[1]):
            link = doc.addObject('App::Link','partLink')
            link.LinkedObject = partRoot
            link.LinkPlacement.Base.x = i*2
            link.LinkPlacement.Base.y = j*2
            partGroup.addObject(link)

    part = doc.addObject('App::Part', 'part')
    part.ViewObject.Visibility = False

    rootLink = doc.addObject('App::Link','rootLink')
    rootLink.LinkedObject = partDoc.Box
    rootLink.ViewObject.Visibility = False

    groups = doc.addObject('App::Part', 'groups')
    groups.ViewObject.Visibility = False
    groups.ViewObject.ShowInTree = False
    linkGroups = doc.addObject('App::Link', 'linkGroups')
    linkGroups.LinkedObject = groups

    for i in range(groupCount[0]):
        for j in range(groupCount[1]):
            link = doc.addObject('App::Link','typeLink')
            link.LinkedObject = rootLink
            link.LinkPlacement.Base.x = i*4
            link.LinkPlacement.Base.y = j*4
            part.addObject(link)
            group = doc.addObject('App::Part','group')
            group.ViewObject.Visibility = False
            group.ViewObject.ShowInTree = False
            linkGroup = doc.addObject('App::Link','linkGroup')
            linkGroup.LinkedObject = group
            groups.addObject(linkGroup)
            for x in range(count[0]):
                for y in range(count[1]):
                    l = doc.addObject('App::Link','link')
                    l.LinkedObject = link
                    l.LinkPlacement.Base.x = count[0]*4*i + x*4
                    l.LinkPlacement.Base.y = count[1]*4*j + y*4
                    group.addObject(l)

    doc.recompute()
Attachments
partDoc.fcstd
(184.71 KiB) Downloaded 98 times
partLink.fcstd
(24.01 KiB) Downloaded 100 times
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: [s]Test[/s] PULL! request: App.ActiveContainer

Post by DeepSOIC »

realthunder wrote:When an App::Part is linked, all its children, and sub parts, and children of those sub parts (if the sub part is also linked) will have full qualified name access
Can this be joined with the Container thing I'm trying to get merged, or one of them has to go away? I haven't looked into your code (well, it's a lot of changes at once, that is hard).

Your post is quite hard to understand, as it describes serious changes with little words. You said you don't like how App::Part works, but you didn't describe what exactly you don't like about it, and what you changed, and why is it better.
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: [s]Test[/s] PULL! request: App.ActiveContainer

Post by triplus »

The way i understand it what @realthunder is proposing is not directly related to Part Design Container effort but is more about a separate piece of functionality. On how to reuse the same geometry in FreeCAD more efficiently. For example reusing the same bolt in Assembly 100 times. And doing that efficiently.

This is important piece of functionality that will need to get done at some point. Topic was discussed on multiple occasions here on the forum in the past. And therefore i do imagine it deserves a separate thread?

P.S. @realthunder just a small remark.

What you call an assembly is in my opinion an array. For real assembly some assembly relations will need to be added first! ;)
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: [s]Test[/s] PULL! request: App.ActiveContainer

Post by realthunder »

DeepSOIC wrote:
realthunder wrote:When an App::Part is linked, all its children, and sub parts, and children of those sub parts (if the sub part is also linked) will have full qualified name access
Can this be joined with the Container thing I'm trying to get merged, or one of them has to go away? I haven't looked into your code (well, it's a lot of changes at once, that is hard).

Your post is quite hard to understand, as it describes serious changes with little words. You said you don't like how App::Part works, but you didn't describe what exactly you don't like about it, and what you changed, and why is it better.
No, I didn't change App::Part at all. That's the point. App::Link is just a compliment. App::Part still has the problem that an object can only be inside one of them, and object inside controls their own visibility (one of my complaints). But with App::Link, now this restriction is kind of lifted. You can simply create a link and added to the part. That particular link still obeys the rule of only inside one App::Part. The benefit is that now the original object can be freely used without affecting the one inside App::Part, or the other way round.

Although my code changes is wild spreading, I do try to make sure that it has minimum impact only existing stuff.
Last edited by realthunder on Thu May 04, 2017 2:52 am, edited 1 time in total.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: [s]Test[/s] PULL! request: App.ActiveContainer

Post by realthunder »

triplus wrote:What you call an assembly is in my opinion an array. For real assembly some assembly relations will need to be added first! ;)
Sure, I intend this to be the building block for assembly. In additional to what you've said, App::Link is also very helpful for building part hierarchies, which IMO is one of weakness of the current App::Part. It provides a very import method, getSubObjects, so that you can bind to a sub object or subelement with ease no matter how deep this actual object is within the hierarchy. For example, with my sample code,

Code: Select all

Part.show(App.ActiveDocument.linkGroups.getSubObject('linkGroup.link073.Face6'))
will show you the shape of that face at the correct location. The subname string is where you get when you select the face inside 3D view. The full string is partLink.linkGroups,linkGroup.link073.Face6, the first substring being document name, and the second the object name. The rest is sub object reference, or the content of SubElementName if you are using Gui.Selection.getSelectionEx(). In fact, you can simply use getSelectionEx()[0].SubObjects() to get the Face object.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Links

Post by triplus »

realthunder wrote:Sure, I intend this to be the building block for assembly.
And you plan to work on Assembly?

The way i see it such functionality will be needed. If your attempt is a good one or not i have no clue. It sounds like it is. That is reusing the same geometry can be done in a way file size is kept low. Geometry clones/copies expose geometry (as vertex, line and face) as a standalone entities to be used for further operations? There is assembly potential and all sort of arrays could be adopted? Gear likely could be made in a way file size would be kept low?
realthunder wrote:In additional to what you've said, App::Link is also very helpful for building part hierarchies, which IMO is one of weakness of the current App::Part. It provides a very import method, getSubObjects, so that you can bind to a sub object or subelement with ease no matter how deep this actual object is within the hierarchy. For example, with my sample code,

Code: Select all

Part.show(App.ActiveDocument.linkGroups.getSubObject('linkGroup.link073.Face6'))
will show you the shape of that face at the correct location. The subname string is where you get when you select the face inside 3D view. The full string is partLink.linkGroups,linkGroup.link073.Face6, the first substring being document name, and the second the object name. The rest is sub object reference, or the content of SubElementName if you are using Gui.Selection.getSelectionEx(). In fact, you can simply use getSelectionEx()[0].SubObjects() to get the Face object.
How does the document and object name look like in a real use case scenario? Or is this it?
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Links

Post by realthunder »

triplus wrote:And you plan to work on Assembly?
I wasn't planning on attacking assembly directly. App::Link is a result of my complain about App::Part, and the discussion with DeepSOIC and ickby, which you joined as well. I have some idea in mind of what the ultimate assembly workbench will look like. But haven't got time to really work on it. Besides, others have already started.
triplus wrote:How does the document and object name look like in a real use case scenario? Or is this it?
Well, the naming choice of my demo isn't good. Basically, the last part of the subname will be the sublement name referring to face, edge and vertex. The second last name is actual shape object containing the sublement. From then on the names are (sub)part group name. My original intention is to integrate App::Link's naming resolve capability into App::Part, but there were many technical problems to solve first, and I wasn't sure it's even possible. So I keep it intact, which means you'll have to link the part first, and add only linked sub parts in order to have full qualified naming access.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Links

Post by triplus »

realthunder wrote:I wasn't planning on attacking assembly directly.
Too bad. As we tried everything else in the past already. More direct approach should i guess therefore be tried out.
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Links

Post by ickby »

I'm with deepsoic here, my prefered modeling workflow is also within Parts, it is just way more flexible and easier to organize.

I started looking through the code, but man, this amount of stuff is really hard to go through. Could you split it up and make the code requests step by step? There are some changes that are not directly relevant for the links, like the log levels. Also making a different PR for the inner document and cross document links may be helpful.

Apart from that I need more time to get into it. In general I like it a lot, it basically works in many ways as deepsoics proposed Instances. But I'm not sure with the way of handling links, the API and selection etc.
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Links

Post by realthunder »

ickby wrote:I'm with deepsoic here, my prefered modeling workflow is also within Parts, it is just way more flexible and easier to organize.

I started looking through the code, but man, this amount of stuff is really hard to go through. Could you split it up and make the code requests step by step? There are some changes that are not directly relevant for the links, like the log levels. Also making a different PR for the inner document and cross document links may be helpful.

Apart from that I need more time to get into it. In general I like it a lot, it basically works in many ways as deepsoics proposed Instances. But I'm not sure with the way of handling links, the API and selection etc.
You can browse the change by commit. Each commit is for a different thing and the commit message summarised it. I intend to submit console log commit as separate PR. The rest is kind of locked in sequence order. I'll see if I can split it to separate PR. To get the selection right is the hardest part actually, and is the very part that I was afraid won't work at all. Luckily I pulled it off.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
Post Reply