chrisb wrote: ↑Sat Jun 26, 2021 11:15 pm
I think the whole problem with topological naming is to get this very information that solid1.edge3 is mapped to solid33.edge1.
I don't think that's the issue about topological naming, because design history doesn't play a role in it: if I attach a datum object to
solid1.edge3, and this edge is replaced-by / renemed-to
solid33.edge1 then the attachment will fail, even if there is a scripted way to retrieve that that has happened. Now, you can say that we'll change the attacher too so that it's aware of this new mechanism, but we will add another level of complexity meaning more future errors.
No, the real issue about topological naming is that
solid1.edge3 keeps its name whatever design modifications happen. But that is not entirely possible, as I will show you here. What we can do is to reduce such renaming, but it's impossible to 100% solve it for any parametric CAD program.
This post will be quite long, and I'm not sure it's the bets place for it, but at least all concerned people are in this thread.
SITUATION IN 3D
The topological naming question is different in 3D than in 2D. I created a very simple design in PartDesign, with 2 rectangles on the XY plane and extruded in the Z+ and Z- directions.
- Topology.png (274.57 KiB) Viewed 5273 times
I then modified the dimensions of these 2 rectangles, in the property panels, without editing the sketches, and got the following resulting geometries:
- topo_all.png (58.51 KiB) Viewed 5273 times
As you can see, with the exact same topology - 2 extruded rectangles - we can get completely different geometries. And what's important is that these geometries don't always have corresponding edges. And since the sketches themselves where not edited, there isn't any notion of "history" or "modification" or "transformation". If you create a fillet on the visible edge of geom6 and then change the dimensions to make it geom4 : where will the fillet apply ? Where
should it apply ?
Of course, this example was designed as a trap to foul the system, but it will do so with any parametric 3D CAD software, be it CATIA or NX. Any real-world design that grows in complexity will at some point reach a state to foul the system, there is
NOTHING that can be done to completely prevent this. What
CAN be done is to improve the result, reduce the likelyhood of such traps to happen, but we can't suppress it. And therefore I thing that we should not only look into reducing the likelyhood of toponaming problems, but we should aim to do so in the simplest and most robust of the ways, and not by doing some unmaintainable black-magic that nobody understands.
SITUATION IN 2D
The situation in 2D is completely different: conceptually, you can't foul the system, meaning that you can't create, even on purpose, a design that will lead to the same topological naming problem as in 3D: to a topology corresponds a single geometry, you cannot create many different geometries with a single 2D topology.
I created a similar geometry in sketcher as the 3D example above, and changed the dimensions to try to fouls the system:
- 2D_all.png (395.88 KiB) Viewed 5273 times
When I set the dimensions to equal to suppress the small line, the system detects an error: it doesn't let itself be fouled. A line segment with 0 length isn't allowed ... which is good. The situation is not completely identical in other 2D drawing programs, as you can have segments with 0 length is Inkscape for example. But FreeCAD's behaviour is logical and consistent.
I've also drawn another example of 2 lines with varying angles:
- sketch_all.png (33.51 KiB) Viewed 5273 times
When the 2 segments are in line, they remain 2 segments, and this is mathematically correct. While the fusion of inline faces is ISO-compliant, you cannot invoke the "
then don't do the refine thing".
BUT THEN, WHY DO WE STILL HAVE THE TOPO-NAMING PROBLEM WITH SKETCHER ?
In this case, it's FreeCAD's "fault", this problem doesn't need to exist, it is mathematically solvable. There are 2 different issues:
- sketcher's internal naming: when I delete Line4, then what was Line5 becomes the new Line4 ... which is actually inconsistent with FreeCAD's convention that an object's name is immutable: Line5 should remain Line5 independently whether other elements where deleted or not.
- during export to 3D, when sketcher's internal geometries are converted to external OCC geometries. Since this happens in some order, when rotating a sketch the same Line can become a different Edge.
Therefore, the 2D and 3D problems are conceptually different, and should be treated differently.
abdullah wrote: ↑Sat Jun 26, 2021 5:37 am
In very general terms the RT's approach is to use this index a black box "Toponaming" and a modified algorithm to sort the edges of the profile that is generated when going out of edit mode.
The black box is not specific to the sketcher, but a general component.
This also means that if this is true, I think this is a wrong approach. Most 3D design begins with a sketch, therefore we should first solve Sketcher's topological naming, and only then try to improve - not solve because it's impossible - the 3D topological naming.
SOLVING SKETCHER4S INTERNAL NAMING
The first step to solve sketcher's topological naming is to have immutable internal names for internal geometries. I tried to read the source-code but I cant' do C++ coding therefore I might be wrong.
I think it's the
std::vector<int> GeoIdList that holds these references ... or may-be
std::vector<PointPos> PosIdList, not sure. Or
std::vector<Part::Geometry *> &geoList ?
One solution could be, as I mentioned before, that deleting a geometry in sketcher doesn't actually remove it but only sets it state to removed. There is an index that could be a good candidate for this state, it's the GeometryMode in SketchGeometryExtension.h:
Code: Select all
namespace GeometryMode {
enum GeometryMode {
Blocked = 0,
Construction = 1,
NumGeometryMode // Must be the last
};
We could adda new state:
then, if I read it correctly, in Sketcher.cpp:
Code: Select all
int SketchObject::delGeometry(int GeoId, bool deleteinternalgeo)
{
...
const std::vector< Part::Geometry * > &vals = getInternalGeometry();
...
std::vector< Part::Geometry * > newVals(vals);
newVals.erase(newVals.begin()+GeoId);
this
newVals.erase() is the culprit: instead of erasing an element from the vector, we should flip the
GeometryMode of the corresponding
GeoId to "
Deleted". And then, getInternalGeometry() needs to be adapted to ignore geometries that have the "Deleted" state.
Does this make sense ?