Topological Naming (another take)

Realthunder recently posted a potential solution for the Topological Naming problem. It is very impressive and, in my opinion, shows a lot of potential. I have posted previously a a potential solution (mostly a proof of concept) in python (though upon further inspection, there are some bugs in that code that I should fix…), as well as an approach (attempting to) utilizing OCC’s built-in TNaming functionality.

This post is to showcase a c++ implementation (and improvement) of the python topo namer that I linked above. without further ado, here’s a (very crude) gif showing it in action!
freecadTopoFix.gif
And here’s a (equally crude) gif showing the current FreeCAD behaviour:
freeCadCurrent.gif
(If anyone can tell me how to resize these on the forum I can make them a bit smaller)

I’m very excited to show this! I originally wanted to also post a gif of the current behaviour (i.e. the fillet moves when the cylinder is made shorter) but my ‘vanilla’ version of FreeCAD isn’t done compiling yet.(it finished) I also wanted to do a fancy screencast gif, but I wasn’t able to make the screencast thing work, so I just took some screenshots and used gimp to make the gif.

Anyway, let me explain (briefly, and at a high level) how this works. I’ve created a library that (for now) I’m calling TopoManagers which describes a Topological Manager interface (ISolidManager) as well as two concrete implementations of this interface: PrimitiveSolidManager and CompoundSolidManager. This line in a test for the PrimitiveSolidManager shows how the manager can be used to obtain a “constant reference” to a topological edge. Note that this reference is a simple integer, but it is guaranteed to always return the same edge.

I have a TopoManager branch of FreeCAD that shows these managers in action (I have not rebased against master in a week or two, please excuse my excitement to post this as soon as possible.) In particular, notice that I’ve added a new member variable to Part::PropertyPartShape, as well as a getter and setter for that variable.

The use of this variable (a unique_ptr to an ISolidManager) is easiest shown in Part::Box. You can see that we retreive the ISolidManager, then either initialize it or update it as appropriate. The update is done using a helper class “Occ::ModifiedSolid” which carries information needed to keep track of which faces have changed (or been deleted or generated).

It’s that simple! You can also look at Part::Cylinder for another (almost identical) use-case, as well as Part::Boolean for a more complicated use-case (this one uses CompoundSolidManager).

I don’t want to get too deep into the technical details of how this works on this post for two reasons: one, my wife is hungry and I need to cook dinner :laughing: And two…actually, that’s the only reason. I will give a little bit of detail though.

The way this works is essentially by using the method whereby each Edge is described by the two faces that make it up. As such, as long as we know how each Face changes, we can consistently refer to a given edge as “the common edge between FaceX and FaceY”. It’s that simple! My library simply provides facilities for (more) easily keeping track of these face changes.

I will also briefly mention that the TopoManagers library uses another small (and incomplete) library that I’ve named OccWrapper. This library provides a set of wrapper classes to Opencascade, namely (currently) TopoDS_Shape and it’s derived classes, as well as some helper classes. The helper classes fall in two categories: specialized Occ::Solids (Occ::Box, Occ::Cylinder, Occ::BooleanSolid) that provide facilities for (more) easily keeping track of faces. And then factory classes: Occ::SolidMaker and Occ::SolidModifier (I’m considering merging these into one).

I wrote this wrapper library because I didn’t want to keep using BRep_Explorer all the time. The library is imperfect, and wasteful (it makes tons of copies of TopoDS_Shape’s). I mostly wrote it to make the writing of TopoManagers easier, but I also feel that it can be improved and extended for more general use in FreeCAD. That’s a separate topic though.

So, please, let me know your thoughts, comments, (constructive) critiques and anything else! I can post instructions on how to build the two libraries as well as my FreeCAD branch if anyone is interested.

How to Compile my TopoManagers Branch of FreeCAD

  1. Download the OccWrapper library. I’ll refer to this downloaded directory as ${OccWrapperDir}
  2. Download the TopoManagers library. I’ll refer to this downloaded directory as ${TopoManagersDir}
  3. Download my TopoManager Branch of FreeCAD. I’ll refer to this downloaded directory as ${EzzieyFreeCADDir}
  4. Compile OccWrapper
  5. Compile TopoManagers
  6. Update FreeCAD with OccWrapper and TopoManagers locations
  7. Compile FreeCAD

You can download these three projects using git and bash with the following commands:

~> git clone --recurse-submodules https://github.com/ezzieyguywuf/OccWrapper
~> git clone --recurse-submodules https://github.com/ezzieyguywuf/TopoManagers
~> git clone -b TopoManager https://github.com/ezzieyguywuf/FreeCAD-1/

The following will compile OccWrapper using bash and CMake. Please note, for the cMake find_package to work, these three projects must be located in the same folder. If you ran all three “git clone” commands in the same folder you should be good:

~> cd ${OccWrapperDir}
~> mkdir build
~> cd build
~> cmake ..
~> make

The following will compile TopoManagers:

~> cd ${TopoManagersDir}
~> mkdir build
~> cd build
~> cmake ..
~> make

The following will compile FreeCAD

~> cd ${EzzieyFreeCADDir}
~> git checkout TopoManager
~> mkdir build
~> cd build
~> cmake ..
~> make

I’ve updated my TopoManager implementation to deal with split edges. Here is the current behaviour in FreeCAD:
cutFilletCurrent.gif
And here is the behaviour with my TopoManager being used:
cutFilletFix.gif
The TopoManager branch of my FreeCAD github repo is up-to-date with this fix. I’ll admit that my FreeCAD integration is a bit hackey: in particular, I could not figure out how use FreeCAD’s Placement to update my solid manager so I just did it without Placement. I realize I could add some code to the appropriate place in Part::Feature, but the return value on this->getManager() is a constant reference, and since it returns a reference to an abstract base class, Part::Feature doesn’t have enough information to make a new one.

This is a limitation in my own understanding of good programming design.

Any way, my FreeCAD integration was not intended to be complete or necessarily elegant. It was intended as a proof-of-concept, or maybe a proof-of-solution. My topological naming solution works irrespective of FreeCAD (though it does need more work, of course), and I merely wanted to show an example of how it could be integrated into FreeCAD to solve this issue that is so near and dear to all of our hearts.

My intent is to generate some conversation about:

a) Is this a good approach? Is this solution one that we feel could be integrated into the FreeCAD code base?
b) If so, what would be the correct way to do this? For now I’ve tapped into individual Part::Feature’s (i.e. Part::Box, Part::Boolean, etc..) but would it make sense to implement my solution more generally?
c) If not, what doesn’t work? What could be better/different?

It seems that perhaps there is not a lot of interest in this topic right now (due to the low level of commentary on my original post). I will hold off on future development until others have a chance to review and critique my work. I want to be sure that whatever I work on could eventually be accepted as a permanent fix in the FreeCAD code base, and at this point if I go much further along the path I’m on I feel it’d be too difficult to turn back and make any big changes to my approach.

Low interest might be only on the deveopers side. From a users point of view the whole topo naming stuff seems to be the biggest issue in FreeCAD - although improvements are at reach with the new Part Design concepts.

Can you elaborate on this? Perhaps my time would be better spent getting the Part Design solution “over the finish line” rather than trying to implement something completely new from scratch.

I am interested in topological naming as a developer, but I’m currently trying to get the mac builds ready for the 0.17 release. I’ll have time to review your approach in the coming weeks.

The question on my mind right now is how your approach fits in with what realthunder is doing and with what ickby proposed. I also wonder if your “method whereby each Edge is described by the two faces that make it up” is too simple. I guess then we would also a need a separate facility for making robust references to elements of a sketch.

<3 these are exactly the sorts of conversations I’d like to have. Perhaps I am just being a bit impatient.

I think the “method whereby each Edge is described by the two faces that make it up” should be sufficient: topologically speaking, in a valid solid, any Edge should have precisely two faces which share that Edge. If this is not the case, then you have an invalid solid.

You are correct. This would be the first step towards creating a “SweptSolidManager”, we would first need a “ParametricSurfaceManager” or “PlanarSurfaceManager” or some such. I’ve already considered this and have a few ideas on how to accomplish this, but again I wanted to take a timeout from further development until I had a chance to discuss my approach with the broader community.

Your work is as valuable as ever!
What I was talking about is the possibility in PDN to use DatumPlanes and Sketches for external references. That makes a model much more robust by design. The problem which you are tackling still exists as before.

In creo They say as external references

  1. planes
  2. faces
  3. edges

Just because in that way it is far more stable. By selecting a external reference (model) in sketch when possible Creo tries to get faces.

this looks really good. datum planes and other reference features outside of bodies and sketches help a lot and should be used, but they don’t deal with filleting an edge in an obvious way. a lot of the reference features i use for production models (not FreeCAD) are based on existing Brep body features. so if the body features don’t track, the reference planes and such won’t track either.

i wish i knew more to help. good luck

Whatever PDN has achieved will never fix what you are trying to fix. It may prevent it in some (many) situations. That said, this topic is one of the most important milestones FC is facing ATM. If you want more convincing, go to the bug tracker and search for toponaming issues.

I do not think you are being impatient. I think you are being very smart. Nobody wants to work for long and then not have it merged. Long-term development in forks, while extremely valid approach, runs a very high risk of never being merged as time without “syncs” goes on. Eventually development will stop because one on its own is not the same. A big share of the work, if not all, would be somehow lost. You wanting to discuss your ideas, get feedback and find a path that will be acceptable is the most common sense thing to do.

With respect to the feedback, the timing is not helping:

  1. Major development, other than bug fixing is frozen since January.
  2. ickby is missed in action (hopefully with a return date :wink: )
  3. DeepSOIC is busy with other things
  4. Other developments have already indicated they would like to contribute, but they are… in release mode or otherwise unavailable.
  5. Even for code reviews, should something be in relative shape, even if it is a concept, Werner is rather busy with release and already has some PRs for v0.18.

You are very much familiar with all the previous efforts on Toponaming. I think you can get an advantage by discussing with those who have made other efforts. If I were you, I will ping them or PM them. At least we would know their availability, even if it is only for discussions on the approach.

My knowledge about Toponaming is negligible (just not to appear too stupid if I say the truth, i.e. that it is null). I do not think I can make a meaningful contribution on this topic. :blush:

I will keep an eye on the thread though.

If you are the linux kind, “Peek” has worked quite well for me.

Abdullah, thanks for all your kind words they are quite uplifting and very encouraging. I feel much better about the approach I am taking now!

Regarding Peek, I am on Linux and I ha e I stalled it. however I believe it requires a compositing window manager to work correctly (for transparency) which I’m not currently using. I just need to update my KDE installation and give it another go, but since I run gentoo and haven’t updated in a while, I’ve been procrastinating :stuck_out_tongue:



freecad-heini-1, what do you use for creating animated gifs?

I use Peek:
https://en.wikipedia.org/wiki/Peek_(software)
https://www.omgubuntu.co.uk/2016/08/peek-desktop-gif-screen-recorder-linux

I have pointed it out once that it isn’t quite true.
Leaving alone some non-manifold meshes and other weird stuff that a few of us actually use, here are some simple solids where you can’t identify an edge JUST by two faces:
toponaming edge by two faces.png
Just make sure you have some fallback for cases like this.

For now I am ignoring seam edges - mostly because it seems (HAH!) that they are mostly used for the construction of the solid. What would we need a reference to a seam edge for? Maybe for the angular location of something? Nonetheless, adding support for seam edges should be trivial.

I don’t understand what I’m looking at in your third solid, sorry.

Someone else has pointed out the case where you take a revolved solid. You can have four distinct edges between three faces. You could modify the solid such that two of the faces are now a single face. This should be manageable in a RevolvedSolidManager by taking care of the special case where AngleOfRevolution is 180 degrees.

If I understand him correctly, he means that an edge cannot be unambiguously derived from two faces. His example shows 4 different edges that are defined by the same two faces.

It is a pillow-like thingy.
Catch the project. I have not bothered to assemble it into a proper solid with shapebuilder, I hope you get the idea.
toponaming edge by two faces.FCStd (23.9 KB)

One more example…
toponaming edge by two faces 2.png