GSoC 2017 Dev Log: jnxd

There will eventually have to be heuristics involved in this project. However, if we want to limit to just elements that can be identified solely using faces and their intersections, a sound technique is available. This will force us to use wires instead of edges in many cases. Of course, there is a problem of what to do when the faces themselves are split/merged.

@jnxd, I know you’ve tried reaching out to me a few times regarding the work I did on this last year and that I have not been very helpful. I would like to apologize for that. I do have a few comments on your list that I’ve quoted above.

Where to create history objects?

I think the proper place to store this data is as a private member of Part::TopoShape. I also believe that the proper place to create this data is within the various Part::Feature::execute methods.

To your point, this method tends to get called multiple times. On the one hand, a part of me feels that the larger FreeCAD project itself can do a better job managing when/if this execute method must be called. On the other hand, perhaps there are good, sound design reasons why Execute is called as often as it is.

Either way, as often as Execute is called, the history object must be created/updated. The reason for this is because (as far as I can tell) each Part::Feature::execute physically changes the TopoDS_Shape that is stored it TopoShape. Any time that TopoDS_Shape changes, the history object needs to be updated. The history object itself should have some mechanism whereby it can check whether or not anything in the tracked shape has actually changed, thereby minimizing (or eliminating) any redundant data.

TNaming does not work well for Generations and Deletions

I’m not sure if I agree with this. If you take a look at the documentation for TNaming_Builder, you’ll notice that it has “Generated”, “Deleted” and “Modify” methods. These are each intended to create the appropriate nodes in occ’s “OCAF” data framework. Admittedly, I’m not a big fan of OCAF, as I find it cumbersome and annoying, but I have been able to successfully test the “Generated” and “Modify” methods of this TNaming_Builder class and they both seem to work fine when used appropriately.

What happens when there are multiple Edges in common between the same Face?

I assume you mean what happens when an Edge which is shared by two Faces all of a sudden becomes a “split Edge”. In other words, if “Edge001” is described as “The edge between Face001 and Face002”, what happens when a slot is added such that there are now two Edges between Face001 and Face002.

In my opinion, this is not a problem for the “Topological Namer” to deal with - this must be dealt with in the client code. Rather, the Topological Namer must simply provide the pertinent data. For example, in my python prototype you’ll notice that the “getEdgeByName” method returns a list of Edges rather than a single Edge. In my opinion, this is sufficient to deal with the question at hand - it is now incumbent upon the client code to check whether an expected number of Edges is returned, and if not to choose what to do.

Let me provide a concrete example. Say we have simple Cube and a single Edge is filleted. Next, this filleted Edge is split in two. The client code now goes to rebuild the filleted Cube, and in doing so uses the “history object” to perform some equivalent of:

edgesToFillet = historyObject.getEdgeByName(filletedEdgeName);

The client code may “know” that originally it filleted a single edge (maybe it stored this data somewhere). It also now knows that there are two Edges where before there was one. In my opinion, it would be perfectly logical for the client code to now fillet both Edges.

What if this was the other way around? Originally, there are two edges between “Face001” and “Face002” and only one of them is filleted. Now, a change is made and suddenly there is only one Edge there. What will happen?

When the “getEdgeByName” method is called, a single Edge will be returned when before there were two. In my opinion, the client code should now prompt the user as to whether or not this Edge should be filleted. Again, though ,this is not a problem for the “history object” to deal with.

In closing

I do not intend for any of my commentary to be definitive or inflammatory. I am merely trying to maintain an open discussion regarding my thoughts, views, and understanding of these topological naming issues.

In my opinion, in this situation, no face will get the same number as before. However, I do think it makes sense to allow for a sort of Topological Inheritance.

In other words, in your example, if “Face001” is split into two, then the resulting solid may have “Face001a” and “Face001b”, both of which will internally store data that flags them as “children” of the original “Face001”. In this way, per my previous post, the client code can make intelligent decision about what to do in these circumstances.