"Robust References" Redux

Minor Update: I’ve updated my TNaming Writeup it include some info about TNaming_Selector and how it works. If anyone’s been following along and wondering about TNaming_Selector I recommend taking a look.

Also, I’m open to any feedback/criticism on the whole Writeup document itself. I realize that the occ TNaming stuff can be a bit complicated, so I want to be sure that this Writeup document can be used as an entry point into understanding how it works and how to use it.

Time for another update: I’ve refactored the TopoNamingHelper class quite a bit. I’ve also re-organized my github repo a bit: tnaming_ezziey_00 contains most of the work to-date. The tnaming_ezziey_01 squashes all the tnaming_ezziey_00 commits into a single commit and then rebases over master. This was necessary b/c master commit 7f4ad37 resulted in too many recurring merge conflicts to allow for an easy rebase with the original tnaming_ezziey branch.

The refactor to TopoNamingHelper was mostly getting rid of specialized TrackXXXShape methods, i.e. TrackBoxShape, and creating a generic TrackShape method. This is helped by the TopoData struct, which is described, along with some other helper data structures, in TopoNamingData.h.

I ran into a huge roadblock when I had TopoNamingHelper working fine when testing outside of FreeCAD but ran into errors when running within FreeCAD. I had a huge breakthrough last night when I realized this is because recompute() in Part::Feature calls TopoShape::setTransform(), even if the TopoShape has not moved. For now, I’ve added a simple check: if the transform matrix is not different, it does not perform a transform. Down the line, I’ll need to add a method to TopoNamingHelper to account for transformations.

All that being said, I’m super duper close to resolving this bug now! I need to finish writing some createCylinder and updateCyilnder methods as well as createFuse and updateFuse methods. This should be relatively straightforward, as they’ll be along the same vein as the createBox, updateBox, createFillet, and updateFillet methods that I’ve already written. Stay tuned!

Awesome! Thanks, and keep up the good work! -Ian-

Thanks for your work on this issue, ezzieyguywuf.

Do you mean the specific use case detailed in the bug report, or the more general issue of any PartDesign-based projects?

I mean the specific case that applies to boxes, cylinders, fuses, and fillets.

A bit underwhelming I know, but a big milestone nonetheless. My idea was to use the bug fix as a final “proof of concept” as well as to provide a template for implementing topological naming freecad-wide.

I will probably be able to make all the changes to the Part workbench needed for topological naming, but I think hitting all the other workbenches is a bit too ambitious. I’m hoping that once I’ve resolved this bug, I can merge some of my code into master and recruit other folks to help with other work benches.

I suppose we’ll see, lol.

No-no, I do consider it a big deal, sorry if I didn’t sound enthusiastic. It’s the first effort in solving this issue that may actually see use so I’m all for it! :slight_smile:

That would really be great, because the topological naming issue has been crippling FreeCAD for far too long IMHO… :frowning:

I did not take your original post as un-enthusiastic, merely as curious. Thank you nonetheless for your apology.

Indeed. The main reason I chose to take this on as my first big contribution to FreeCAD is that as I looked through bug reports and chatted with folks, it seemed that there were many issues related to topological naming, and that thet attitude was “whelp, it’s a problem and it will always be a problem, oh well…”

Thank you for this!

I think more that a very brave soul must take on the task :slight_smile: Any improvement in this respect is great, and if your work can serve as a template for further work this makes your contribution even more valuable.
I suspect there’s a lot of us following this topic with great interest, even if the details are over our heads. Keep up the great work.

Guilty as charged :smiley:

Don’t be intimidated y’all. I’m probably making this stuff sound more complicated than it really is. Perhaps I n should take another stab at that tnaming writeup and see if I can’t make it easier to understand.

Update: hopefully this isn’t premature, but here is a teaser:
freecad.png
This is showing three imported BREP files. These files were generated using my TopoNamingHelper class outside of freecad, using an external tester program I’ve written for development. It looks promising, though, as it appears to have resolved [u]this bug[/u]! The Three shapes, in order, are:

  1. Original fused shape
  2. re-computed fused-shape when making cylinder smaller
  3. re-computed fused-shape when making cylinder taller

I’ve only been able to replicate the bug in FreeCAD v0.17 by making the cylinder shorter, not taller.

Again, hopefully this isn’t too premature, I now have to integrate this into FreeCAD and ensure that the bug fix still holds true there. Even after that, though, there is still a lot of work left to do for topo naming, not the least of which is:

  1. Figure out how to serialize/deserialize the topo naming data tree
  2. Add topo naming for other BOPs, and other primitives
  3. Update legacy FreeCAD code to use topo naming functions in TopoShape

This is still pretty exciting though!

Edit: Here’s what the topological history data tree looks like after the third operation:

0:1 Name: Selection Root Node
--0:1:1 Name: A selected edge. Sub-node is the context Shape, Evolution = SELECTED
----0:1:1:1 , Evolution = SELECTED
------0:1:1:1:1 , Evolution = SELECTED
--------0:1:1:1:1:1 , Evolution = SELECTED
0:2 Name: Base Shape(s)
--0:2:1 Name: Tracked Shape #1
----0:2:1:2 Name: Base Shape(s)
------0:2:1:2:1 Name: Tracked Shape #1
--------0:2:1:2:1:1 Name: Result Shape(s)
----------0:2:1:2:1:1:1 Name: Created Box, Evolution = PRIMITIVE
------------0:2:1:2:1:1:1:1 Name: Generated faces
--------------0:2:1:2:1:1:1:1:1 Name: Top Face, Evolution = PRIMITIVE
--------------0:2:1:2:1:1:1:1:2 Name: Bottom Face, Evolution = PRIMITIVE
--------------0:2:1:2:1:1:1:1:3 Name: Left Face, Evolution = PRIMITIVE
--------------0:2:1:2:1:1:1:1:4 Name: Right Face, Evolution = PRIMITIVE
--------------0:2:1:2:1:1:1:1:5 Name: Front Face, Evolution = PRIMITIVE
--------------0:2:1:2:1:1:1:1:6 Name: Back Face, Evolution = PRIMITIVE
----0:2:1:3 Name: Tool Shapes(s)
------0:2:1:3:1 Name: Tracked Shape #1
--------0:2:1:3:1:1 Name: Result Shape(s)
----------0:2:1:3:1:1:1 Name: Created Cylinder, Evolution = PRIMITIVE
------------0:2:1:3:1:1:1:1 Name: Generated faces
--------------0:2:1:3:1:1:1:1:1 Name: Top Face, Evolution = PRIMITIVE
--------------0:2:1:3:1:1:1:1:2 Name: Lateral Face, Evolution = PRIMITIVE
--------------0:2:1:3:1:1:1:1:3 Name: Bottom Face, Evolution = PRIMITIVE
----0:2:1:4 Name: Result Shape(s)
------0:2:1:4:1 Name: Created Fuse Shape, Evolution = MODIFY
--------0:2:1:4:1:1 Name: Modified faces
----------0:2:1:4:1:1:1 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:2 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:3 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:4 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:5 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:6 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:7 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:8 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:9 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:10 Name: , Evolution = MODIFY
----------0:2:1:4:1:1:11 Name: , Evolution = MODIFY
------0:2:1:4:2 Name: Updated Fuse Shape, Evolution = MODIFY
--------0:2:1:4:2:1 Name: Modified faces
----------0:2:1:4:2:1:1 Name: , Evolution = MODIFY
----------0:2:1:4:2:1:2 Name: , Evolution = MODIFY
----------0:2:1:4:2:1:3 Name: , Evolution = MODIFY
----------0:2:1:4:2:1:4 Name: , Evolution = MODIFY
----------0:2:1:4:2:1:5 Name: , Evolution = MODIFY
----------0:2:1:4:2:1:6 Name: , Evolution = MODIFY
----------0:2:1:4:2:1:7 Name: , Evolution = MODIFY
----------0:2:1:4:2:1:8 Name: , Evolution = MODIFY
--0:2:2 Name: Tracked Shape #2
----0:2:2:2 Name: Base Shape(s)
------0:2:2:2:1 Name: Tracked Shape #1
--------0:2:2:2:1:1 Name: Result Shape(s)
----------0:2:2:2:1:1:1 Name: Created Box, Evolution = PRIMITIVE
------------0:2:2:2:1:1:1:1 Name: Generated faces
--------------0:2:2:2:1:1:1:1:1 Name: Top Face, Evolution = PRIMITIVE
--------------0:2:2:2:1:1:1:1:2 Name: Bottom Face, Evolution = PRIMITIVE
--------------0:2:2:2:1:1:1:1:3 Name: Left Face, Evolution = PRIMITIVE
--------------0:2:2:2:1:1:1:1:4 Name: Right Face, Evolution = PRIMITIVE
--------------0:2:2:2:1:1:1:1:5 Name: Front Face, Evolution = PRIMITIVE
--------------0:2:2:2:1:1:1:1:6 Name: Back Face, Evolution = PRIMITIVE
------0:2:2:2:2 Name: Tracked Shape #2
--------0:2:2:2:2:1 Name: Result Shape(s)
----------0:2:2:2:2:1:1 Name: Created Box, Evolution = PRIMITIVE
------------0:2:2:2:2:1:1:1 Name: Generated faces
--------------0:2:2:2:2:1:1:1:1 Name: Top Face, Evolution = PRIMITIVE
--------------0:2:2:2:2:1:1:1:2 Name: Bottom Face, Evolution = PRIMITIVE
--------------0:2:2:2:2:1:1:1:3 Name: Left Face, Evolution = PRIMITIVE
--------------0:2:2:2:2:1:1:1:4 Name: Right Face, Evolution = PRIMITIVE
--------------0:2:2:2:2:1:1:1:5 Name: Front Face, Evolution = PRIMITIVE
--------------0:2:2:2:2:1:1:1:6 Name: Back Face, Evolution = PRIMITIVE
----0:2:2:3 Name: Tool Shapes(s)
------0:2:2:3:1 Name: Tracked Shape #1
--------0:2:2:3:1:1 Name: Result Shape(s)
----------0:2:2:3:1:1:1 Name: Created Cylinder, Evolution = PRIMITIVE
------------0:2:2:3:1:1:1:1 Name: Generated faces
--------------0:2:2:3:1:1:1:1:1 Name: Top Face, Evolution = PRIMITIVE
--------------0:2:2:3:1:1:1:1:2 Name: Lateral Face, Evolution = PRIMITIVE
--------------0:2:2:3:1:1:1:1:3 Name: Bottom Face, Evolution = PRIMITIVE
----------0:2:2:3:1:1:2 Name: Updated Cylinder, Evolution = MODIFY
------------0:2:2:3:1:1:2:1 Name: Modified faces
--------------0:2:2:3:1:1:2:1:1 Name: Top Face, Evolution = MODIFY
--------------0:2:2:3:1:1:2:1:2 Name: Lateral Face, Evolution = MODIFY
--------------0:2:2:3:1:1:2:1:3 Name: Bottom Face, Evolution = MODIFY
------0:2:2:3:2 Name: Tracked Shape #2
--------0:2:2:3:2:1 Name: Result Shape(s)
----------0:2:2:3:2:1:1 Name: Created Cylinder, Evolution = PRIMITIVE
------------0:2:2:3:2:1:1:1 Name: Generated faces
--------------0:2:2:3:2:1:1:1:1 Name: Top Face, Evolution = PRIMITIVE
--------------0:2:2:3:2:1:1:1:2 Name: Lateral Face, Evolution = PRIMITIVE
--------------0:2:2:3:2:1:1:1:3 Name: Bottom Face, Evolution = PRIMITIVE
----------0:2:2:3:2:1:2 Name: Updated Cylinder, Evolution = MODIFY
------------0:2:2:3:2:1:2:1 Name: Modified faces
--------------0:2:2:3:2:1:2:1:1 Name: Top Face, Evolution = MODIFY
--------------0:2:2:3:2:1:2:1:2 Name: Lateral Face, Evolution = MODIFY
--------------0:2:2:3:2:1:2:1:3 Name: Bottom Face, Evolution = MODIFY
----------0:2:2:3:2:1:3 Name: Updated Cylinder, Evolution = MODIFY
------------0:2:2:3:2:1:3:1 Name: Modified faces
--------------0:2:2:3:2:1:3:1:1 Name: Top Face, Evolution = MODIFY
--------------0:2:2:3:2:1:3:1:2 Name: Lateral Face, Evolution = MODIFY
--------------0:2:2:3:2:1:3:1:3 Name: Bottom Face, Evolution = MODIFY
----0:2:2:4 Name: Result Shape(s)
------0:2:2:4:1 Name: Created Fuse Shape, Evolution = MODIFY
--------0:2:2:4:1:1 Name: Modified faces
----------0:2:2:4:1:1:1 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:2 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:3 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:4 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:5 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:6 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:7 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:8 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:9 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:10 Name: , Evolution = MODIFY
----------0:2:2:4:1:1:11 Name: , Evolution = MODIFY
------0:2:2:4:2 Name: Updated Fuse Shape, Evolution = MODIFY
--------0:2:2:4:2:1 Name: Modified faces
----------0:2:2:4:2:1:1 Name: , Evolution = MODIFY
----------0:2:2:4:2:1:2 Name: , Evolution = MODIFY
----------0:2:2:4:2:1:3 Name: , Evolution = MODIFY
----------0:2:2:4:2:1:4 Name: , Evolution = MODIFY
----------0:2:2:4:2:1:5 Name: , Evolution = MODIFY
----------0:2:2:4:2:1:6 Name: , Evolution = MODIFY
----------0:2:2:4:2:1:7 Name: , Evolution = MODIFY
----------0:2:2:4:2:1:8 Name: , Evolution = MODIFY
------0:2:2:4:3 Name: Updated Fuse Shape, Evolution = MODIFY
--------0:2:2:4:3:1 Name: Modified faces
----------0:2:2:4:3:1:1 Name: , Evolution = MODIFY
----------0:2:2:4:3:1:2 Name: , Evolution = MODIFY
----------0:2:2:4:3:1:3 Name: , Evolution = MODIFY
----------0:2:2:4:3:1:4 Name: , Evolution = MODIFY
----------0:2:2:4:3:1:5 Name: , Evolution = MODIFY
----------0:2:2:4:3:1:6 Name: , Evolution = MODIFY
----------0:2:2:4:3:1:7 Name: , Evolution = MODIFY
----------0:2:2:4:3:1:8 Name: , Evolution = MODIFY
0:4 Name: Result Shape(s)
--0:4:1 Name: Created Fillet Node, Evolution = MODIFY
----0:4:1:1 Name: Modified faces
------0:4:1:1:1 Name: Modified Faces, Evolution = MODIFY
------0:4:1:1:2 Name: Modified Faces, Evolution = MODIFY
------0:4:1:1:3 Name: Modified Faces, Evolution = MODIFY
------0:4:1:1:4 Name: Modified Faces, Evolution = MODIFY
----0:4:1:2 Name: Faces generated from Edge
------0:4:1:2:1 Name: Generated from Edge, Evolution = GENERATED
--0:4:2 Name: Updated Fillet Node, Evolution = MODIFY
----0:4:2:1 Name: Modified faces
------0:4:2:1:1 Name: Modified Faces, Evolution = MODIFY
------0:4:2:1:2 Name: Modified Faces, Evolution = MODIFY
------0:4:2:1:3 Name: Modified Faces, Evolution = MODIFY
------0:4:2:1:4 Name: Modified Faces, Evolution = MODIFY
----0:4:2:2 Name: Faces generated from Edge
------0:4:2:2:1 Name: Generated from Edge, Evolution = GENERATED
--0:4:3 Name: Updated Fillet Node, Evolution = MODIFY
----0:4:3:1 Name: Modified faces
------0:4:3:1:1 Name: Modified Faces, Evolution = MODIFY
------0:4:3:1:2 Name: Modified Faces, Evolution = MODIFY
------0:4:3:1:3 Name: Modified Faces, Evolution = MODIFY
------0:4:3:1:4 Name: Modified Faces, Evolution = MODIFY
----0:4:3:2 Name: Faces generated from Edge
------0:4:3:2:1 Name: Generated from Edge, Evolution = GENERATED

It is rather monstrous :-\ I’m a bit worried about what performance will look like on larger assemblies/parts, but I suppose time will tell…

Awesome! That’s looking really good.

I’ll take slow and correct behaviour over broken behaviour any day. Can usually speed up things later, or if that doesn’t work, just wait for computers to go faster :slight_smile:.

http://c2.com/cgi/wiki?RulesOfOptimization

Carry on! You’re doing great.

MichaelJackson used to say (when asked about optimization)

That’s the third ‘famous’ Michael Jackson I’ve heard about. There’s the singer, then the beer guy, and now this guy!

Update: Here it is ladies and gentleman, this gif shows the TopoNamingHelper implementation in FreeCAD showing the bug fix mentioned above:
image1.gif
As mentioned earlier, still a lot of work to do. In fact, I already found a bug: the fix does not work when shrinking the box. What’s more, my concerns about performance appear to have been well founded: when re-sizing the cylinder in the last step to Height = 10 mm, there was a noticeable lag/slowdown. I’ll worry about performance later, though.

Congratulations ezzieyguywuf, this is quite the milestone. Way to go :smiley:

Amazing ezzieguywuf! These progresses are mind-blowing…
This recurrent process of merging new features → slow down → optimization phase is something we are used to with FreeCAD, no worries there… It happened a lot of times already. But it might be wise to think of a way to disable it too.

I can probably do something compile-time pretty easily. Doing a runtime toggle would be a lot more difficult.

Edit: so when’s a good time to start taking about merging into master? There is still quite a way to go…

I think, as soon as you cover all Part Boolean operations (Fuse/cut/common). The rest isn’t nearly as essential, I think. You definitely shouldn’t spend great effort porting lots of stuff, before getting the general approval of the approach. (but I’m not wmayer, so it’s just an opinion - don’t take it too serious :wink: )

I like the fact this pioneer work was done! It represents an important milestone for sure.

I worry a bit about the performance penalty if it really becomes noticeable in the demonstration example above. Now as for having it as an option i feel that would likely result in incompatibility when opening the file in one or another mode and FreeCAD user should therefore i guess at least get some feedback on that when opening the file.