Back in 2012, jrheinlaender started a thread whereby he suggested an approach to solving the topological naming issue that FreeCAD currently has. I revived this post a few weeks again, and have since then spent a considerable amount of time researching this topic and reading my way through both the existing FreeCAD code base (roughly version 0.17 as of the time of tis post) as well as ickby's tnaming branch in which he had begun to incorporate some of jrheinlaender's original code into the FreeCAD code base.
I am starting this new thread for a few reasons:
1) I want a place to gather some of the information I've found, to make it easier for anyone else that may join me on this journey
2) I want a place to discuss current progress (or lack thereof) on this issue
3) I want to bring my current work - limited though it is right now - to the attention of the main devs.
I find it very unfortunate that jrheinlaender made so much progress and produced so much code only to be met at the end with a bit of resistance to to his approach. In all fairness, a do agree with jriegal that this topological naming approach should not reside in the Part Design module but rather in the Part module, but I want to avoid this type of issue by discussing upfront my plans, and what I want to do.
First, a word about 'Geometry' and 'Topology' for those that, like me, are completely new to all this. As far as I can tell, 'Geometry' of a shape are points (represented by coordinates), lines (defined by two points), planes (defined by three points), and volumes (defines by...not sure) that define the shape. In other words, the typical things we're used to from Geometry class, i.e. y=mx+b to define a line and whatnot.
The 'Topology' of a shape, on the other, is distinct from the geometry in that it is more general. It refers to vertices, edges, surfaces, and solids rather than points, lines, planes, and volumes. The difference is that an edge is essentially a portion of an underlying line, a surface a portion of an underlying plane, etc...
To be fair, I don't 100% understand the difference, but I am led to believe that there is a preference to deal with 'Topology' rather than 'Geometry' when it comes to modeling, because of, like, memory usage and stuff.
That being said, here's what I know so far:
Per ickby, here is a recommended roadmap for moving forward:
As far as I can tell, ickby's branch that I list above has completed 1.1, begun 1.2, very minimally started 1.3, and hasn't done anything else.ickby wrote:items in RED are not from ickby's original post
The general way for this topic undependend of the exact topological naming implementation is like that:
- Extend TopoShape with possibility for robust references
- Add data structure for saving history of elements
- Extend all algorithms to build up the element history
- Add methods to query elements robustly by some reference or by construction method
- Move all occ algorithms that modiy the 3D model and are in PartDesign or anywhere else in FreeCAD into TopoShape and make them work with the robust reference system
- Make all Workbenches use the new TopoShape Methods and hence support robust references
- Rewrite all Gui tools so that they build up robust references instead of the current weak once
- Add a Gui for the user in case references get lost so that he can assign new ones
I am going to try to write up a protoype in pure python, maybe python-occ, since I'm most comfortable coding in python. I won't spend too much time on this, but I figure if I can whip something together that it will help wrap my mind around what needs to happen, and I can post it here and it may spark some discussion.
Other stuff - as far as I can tell, the following is the current state of topological naming/reference in FreeCAD. Please feel free to correct me here if I'm wrong as my experience with the codebase is minimal and I may be misunderstanding things:
- TopoShape is the base class which is used (mostly) for interfacing with the opencascade topological libary (i.e. BRepBuilder and friends)
- TopoShape depends on ComplexGeoData
- There are currently other Modules (i.e. Part Design) that do not do all of their opencascade interface through TopoShape, hence ickby's item 2 above
- TopoShape includes methods such as 'makePipe', 'cut' (booleon substract), 'fuse' (boolean add), 'transformGeometry', and notably 'getSubShape'
- As far as I can tell, Modules such as 'Part Design' are intended to use TopoShape as follows:
- User creates a geometry (i.e. a closed loop of lines)
- Module uses geometry to create a Topological Shape using TopoShape
- User modifies geometry (i.e. extrudes sketch or creates pocket in solid)
- Module uses relevant TopoShape method. In the case of extrude, this would be 'makePrism' I think. In the case of pocket, it would be 'cut' I think. Of note is that the 'cut' method accepts a geometry which is used to operate on the existing TopoShape. In other words, a shape (let's say a cylinder) is passed into the 'cut' metod of an existing TopoShape, let's say it's a cube. TopoShape then subtracts the cylinder from the cube and creates an entirely new Topological Shape.
- Module saves the resulting Topological Shape as the new shape that the user interacts with
- As far as 'Topological Naming', the way this is currently done is that the opencascade class 'TopExp_Explorer' 'TopExp::MapShapes' is used to 'explore' the Topological Structer stored in TopoShape. As the TopoShape is explored, each edge and vertex is assigned an increasing number, i.e. 'Edge1', 'Edge2', etc...
- When the Module requires to perform an action on a particular Topological Entity (i.e., 'Face1' on a cube), it specifies the name, literally 'Face1', and then TopoShape iterates over the Topological Face until it finds a 'Face' that has index 1. I'm a bit confused as to how the Module currently keeps track of which face is which, but suffice to say this is the root of the Topological Naming problem
- TopoShape depends on ComplexGeoData as above
- ALL topological shapes are managed through TopoShape - no other modules make calls to 'BRepBuilderApi' from opencascade
- As methods are called on TopoShape, i.e. 'cut', 'makePrism', 'fuse' and friends, TopoShape keeps track of the changes
- By keeping track of these changes, a 'Robust Reference' to topological entities will be created. Rather the module referring to 'Face1' it will refer to 'The Face resulting from the Edge that is between the two Vertexes that are furthest from the origin in the Shape that was passed to the consrtuctor'. Of course, the syntax would be more concise,
- Anytime something 'catastrophic' happens, i.e. an edge wit a Fillet is deleted, the TopoShape alerts the Module - or rather, provides a method that allows the Module to check before making changes - so that the Module can alert the user
This is all I have so far! Please, help me to fill in the gaps. Like I said, I'm still working on reading code and understanding things. But this is a big project, and in all my years of working on projects (both academically and professionally), the bigger the project, the more time that must be spent planning in order to avoid failure. Thus, I'm trying to spend an appropriate amount of time on recon and planning before diving into contributing more code.