Offset Face

blobfish

CAD community veteran
What is your current focus on OpenCascade? Just curious.
I have come across a few simple models that the offset api just 'chokes' on, so I started into it. Test code is below, attached a picture showing face to offset, attached brep file. After many hours: The first thing I learned is that every face gets extended and re-trimmed regardless of offset values. I found that surprising, but I can see how that would help alleviate hidden conditions. Then I found out that the face intersections get cached and re-used as the algo iterates around the face edges. The problem is .... I should say ONE problem is .... the caching of intersections doesn't consider a condition where the face intersection produces to independent curves like the cylinder and the 'left' face producing 2 different lines. One piece of evidence for this theory was: The exact same model, with the exception being the cylinder seam edge was present in the subraction creating 2 cylindrical faces insted of one, works as expected. The final piece of evidence for that theory is: I broke into the execution with gdb and dumped out all the intersection curves and one of the expected cylinder to planar intersection curves was missing. As I was hacking away trying to add support for this condition, I found a different bug that sent me off in a different direction for days/weeks. I did find the problem and fixed that second bug. Back to the missing intersection: I got to the point where I felt confident I had the extra intersection curve handled for the intersection portion of the algo. That wasn't enough and the boundary detection portion was suffering from the same lack of support of the condition. I had to step away from that code, as a padded room was being prepared especially for me.

While I was working on that offset problem, I had a thought I wanted to explore: "What if we untrimmed all the faces and just dumped everything into BOPAlgo_MakerVolume. Can we interpret those results to get the expected offset face result?". That is what I have been doing the last few weeks.



C++:
TEST_CASE("000026", "[known]")
{
  path inputPath = getTestPath() / "000026/offsetBugPlaneFail.brep";
  REQUIRE(std::filesystem::exists(inputPath));
  auto inputShape = ocs::readBRep(inputPath.string());
  REQUIRE(!inputShape.IsNull());
  ocs::Solids inputSolids = ocs::getTypedIndexed<ocs::Solids>(inputShape);
  REQUIRE(inputSolids.size() == 1);
 
  auto inputFaces = ocs::getTypedIndexed<ocs::Faces>(inputSolids.front(), {2});
  REQUIRE(inputFaces.size() == 1);
 
  BRepOffset_MakeOffset builder;
  builder.Initialize
  (
    inputSolids.front(),
    0.0,
    1.0e-06,
    BRepOffset_Skin, //offset mode
    Standard_False, //intersection
    Standard_False, //self intersection
    GeomAbs_Intersection, //join type.
    Standard_False, //thickening.
    Standard_False //remove internal edges
  );
  builder.SetOffsetOnFace(TopoDS::Face(inputFaces.front()), 0.1);
  builder.MakeOffsetShape();
  CHECK(builder.IsDone());
  CHECK(builder.Error() == BRepOffset_NoError);
  REQUIRE(!builder.Shape().IsNull());
  BRepCheck_Analyzer checker(builder.Shape());
  CHECK(checker.IsValid());
  ocs::writeBRep(builder.Shape(), "offsetTestOut.brep");
}
 

Attachments

  • offsetBugPlaneFail.png
    offsetBugPlaneFail.png
    38.6 KB · Views: 1
  • offsetBugPlaneFail.brep
    13.3 KB · Views: 2

Quaoar

Administrator
Staff member
I always tried to avoid offsets, as this part of the modeling API leaves the impression that someone started implementing it and then just gave up. There's one topology-preserving variation of offsets ("simple offsets") that we used more or less successfully for ship hull plates. But it's too limited for normal usage.

Don't you have a feeling that it would probably be easier to develop a new offset algo from scratch? Does the existing one work for other cases you have?
 

Attachments

  • offset.gif
    offset.gif
    3.9 MB · Views: 3

blobfish

CAD community veteran
I always tried to avoid offsets, as this part of the modeling API leaves the impression that someone started implementing it and then just gave up.
You mean like the rest of the API. ;) I shouldn't say that .... I have just been spoiled by years of running UG with Parasolid.

There's one topology-preserving variation of offsets ("simple offsets") that we used more or less successfully for ship hull plates. But it's too limited for normal usage.
And that is not really the behavior that I am after. I want to 'push' around individual faces at a distance on an existing solid.

Does the existing one work for other cases you have?
I have had mixed results. That part I posted would be at the extreme for simple failures. At the other end for complex successes, I modeled a 'clam shell' part in cadseer. See picture, picture. I made this by hacking away at a box until I had one side of metal. I took the one side shell and thickened it into a solid to make the part. The whole time I was modelling it, I kept saying to myself, 'This is never going to thicken'. but somehow It did.

Don't you have a feeling that it would probably be easier to develop a new offset algo from scratch?
Sure and that is basically what I started to do when I was talking about using BOPAlgo_MakerVolume. Now ask me if I think I will be successful in making something useful. :)
 

Quaoar

Administrator
Staff member
I want to 'push' around individual faces at a distance on an existing solid.
Is it for a push/pull-like operation? My experiments did not go further than extruding a local prism and fusing it back to the solid. Kinda kiddish functionality, but sometimes helpful for direct editing of simple prismatic shapes.

Now ask me if I think I will be successful in making something useful.
Well, what do you think, will you be successful in making something useful out of Booleans?😁 Actually, Booleans are not that bad, and I think they can serve as a sound foundation for trickier algorithms. OCC invested far more in Booleans than in other modeling APIs. I would love to work on some sort of push/pull in the future. Also, defeaturing should be improved, but here I hope to reuse what these guys are going to publish (if they ever publish their fork).
 

blobfish

CAD community veteran
Is it for a push/pull-like operation? My experiments did not go further than extruding a local prism and fusing it back to the solid. Kinda kiddish functionality, but sometimes helpful for direct editing of simple prismatic shapes.
Yeah basically a push/pull in most cases. However, that model I posted is not able to be hollowed/MakeThickSolid either, so thinking about other operations also. I have had those "extrusion + unite" thoughts too. I can see that working in a user interactive, non-parametric kind of way. That way the algo would only be working on one moved/offset face at a time. In a parametric feature where multiple, adjacent faces are being offset, gives me pause. see picture. I guess the parametric feature could just do one face at a time, keep track of previously modified faces.....Now I am thinking about this again. Referencing the picture: Given these 3 solids united and we know the 'perimeter' faces from the extrusions, What if we ran the solid through remove BRepAlgoAPI_Defeaturing passing it those perimeter faces. I am sure a simple case like this will work, but I wonder how well it works as shapes get more complicated?


Also, defeaturing should be improved, but here I hope to reuse what these guys are going to publish (if they ever publish their fork).
I cloned their repo a while back and 'git fetch' every once and a while, but I have never seen anything other than updates to the readme file. What have you seen that makes you think they have something more? I see they have a CLA also.



2faceOffset.png
 

Quaoar

Administrator
Staff member
What if we ran the solid through remove BRepAlgoAPI_Defeaturing passing it those perimeter faces. I am sure a simple case like this will work, but I wonder how well it works as shapes get more complicated?
I wouldn't ground any custom logic on Defeaturing because of two reasons:

1. We know it sometimes hangs and destroys your shape.
2. We know that nobody's going to maintain and fix it in OCC.

As for original Booleans, they are kind of Ok, i.e., they work reasonably well for simple cases and OCC had enough time to debug it. So any push-pull-like functionality I would base on the original Booleans, avoiding derived algorithms that I cannot debug myself, and I know that nobody's going to help me.

I cloned their repo a while back and 'git fetch' every once and a while, but I have never seen anything other than updates to the readme file. What have you seen that makes you think they have something more? I see they have a CLA also.
I did not clone their repos, but I am in contact with a couple of folks from their team (all former OCC employees). They have an appetite to challenge the official OCC and largely just take the whole project over. I heard from them that they have some useful patches here and there and they were going to release in 2024, so I'm waiting impatiently.
 

blobfish

CAD community veteran
I wouldn't ground any custom logic on Defeaturing because of two reasons:

1. We know it sometimes hangs and destroys your shape.
2. We know that nobody's going to maintain and fix it in OCC.

As for original Booleans, they are kind of Ok, i.e., they work reasonably well for simple cases and OCC had enough time to debug it. So any push-pull-like functionality I would base on the original Booleans, avoiding derived algorithms that I cannot debug myself, and I know that nobody's going to help me.

Thanks for all the inside information. Being on the outside, I didn't realize the extent of that last 'shake up'. I figured the more recent algos like defeaturing would still be maintained. So, the OpenCasCade 'soap opera' continues. It is so hard to remain hopeful for open source solid modelling, and now I am having an existential crisis.

Thought experiment: Without the bounds of reality, what is the way forward for an open source solid modeling kernel?

My ignorant response/rant:
A fresh data structure, all the implicit sharing has to go! I have watched bugs in occ algos, or my use of such algos, alter shape tolerances all they way up my feature tree/DAG. Some of these shapes are 'dumb', meaning they are not regenerated, so they get permanently altered without warning. The modeling algos themselves are big and complicated and the data sharing compounds that, exponentially. See my post about tracking down a unify same domain bug. Shared data is also a 'diesease' to any asynchronous/multithreading code. I just don't think I could ever be convinced of a recursive data structure like the one that exists between TopoDS_Shape and TopoDS_TShape. Most performace tuning these days has to do with cache misses, so it would be interesting to see some profiling of working with TopoDS_Shape and all of it's pointer indirection, vs just coping raw data. I digress. I think it would be wise to design this new data structure to be converted to and from TopoDS_Shape, to 'piggy back' onto what does work in opencascade. In short, we need to come up from underneath, instead of trying to build on top.

Ok I am going to spend the rest of the day working on that ... or drinking. Either way, I will be back to reality tomorrow. :)
 

Quaoar

Administrator
Staff member
I figured the more recent algos like defeaturing would still be maintained
Well, I suppose it would be maintained to some extent, similarly to how the prior OCC team maintained fillets, chamfers, and offsets (that is, they kept the algorithms compilable and regression-free). I'd desire to be strongly mistaken, but here are the facts. Matra initially developed highly advanced algorithms for approximation (AdvApprox), piping, skinning, some incomplete tools for offsets, thickening, and even local operations (whatever you call it). Then they sold their business, and the modeling part was taken over by another team that was not the original developers of any of the above tools. So the modeling algorithms got mostly abandoned, which is why fillets, chamfers, and offsets have never seen any improvements, while mysterious things like "local ops" or BRepFeat have been largely eliminated. I don't want to pick on the team, also because I was part of it, and I must say that this second wave of developers introduced many other things to the modeling core: brand new Booleans, new handles based on templates, all sorts of non-manifold processing. Then, let's not forget all of the data exchange tools that the 2-nd wave team has been developing since the beginning (so it was the 1-st wave for data exchange).

Now that the second wave is gone, the third wave is on its way (is it?). It effectively means that the new Booleans, data exchange, and other features created by the second wave will be abandoned if OCC does not take very serious and expensive steps to preserve the lost expertise. Can they restore their lost knowledge? In theory, yes. Will they do that? I do not think so.

I think it's all objective. If you don't maintain continuous expertise propagation from the former generation of developers to the newcomers, you'll get a black hole at the end.

So, the OpenCasCade 'soap opera' continues. It is so hard to remain hopeful for open source solid modelling, and now I am having an existential crisis.
I have been having the same sort of crisis for quite some years and, when I was much younger, even started to put together Yet Another Modeling Kernel. That has been very romantic but absolutely unrealistic, as you can guess. Now we have this Chinese team that inherited the 2-nd wave developers and took over the OCC development. I'm going to sit down with a basket of popcorn and see how this opera is going to unfold.

I just don't think I could ever be convinced of a recursive data structure like the one that exists between TopoDS_Shape and TopoDS_TShape.
Well, what is your opinion on ACIS and Parasolid data structures? Don't you find them quite similar to what we have in OpenCascade? I can say that I'm not happy with HOW "Object-TObject" architecture was implemented in OpenCascade, but I think they tried to express B-rep more or less in the same way as in Romulus-based kernels. A simple example where I already have some confusion is a function accepting a TopoDS_Edge:

Code:
void foo(const TopoDS_Edge& edge)
{
  // whatever
}

What does this edge actually represent? Is it the shared curve between faces (i.e., an edge) or rather the occurrence of an edge in a face (i.e., a coedge/fin)? When you're working on low-level algorithms (e.g., Euler ops), you normally have to guess what this edge actually is because:
  • If this is a real edge, how do you interpret its orientation, which is normally relevant w.r.t. the owner's face?
  • If this is a coedge, why is it called an edge?
I guess this example might look a bit synthetic, but I really don't think that exposing CoEdges (TopoDS_Edge), CoFaces (TopoDS_Face) instead of shared edges (TEdge) and faces (TFace) was such a brilliant idea.

I think it would be wise to design this new data structure to be converted to and from TopoDS_Shape, to 'piggy back' onto what does work in opencascade. In short, we need to come up from underneath, instead of trying to build on top.
My opinion on this has been slightly different. Even if OpenCascade's topological model is "broken" from the beginning, I feel the library's main issue is the reliability of its higher-level API. Many of the library's modeling functions (for example, offset) appear to be prototypes, meaning that they were developed without a solid design in mind and have never been thoroughly tested. To be pragmatic, I would rather invest in developing new algorithms for offsets, fillets, chamfers, and so on, allowing these new ones to coexist with the old versions until they begin to outperform the legacy ones. And each such algorithm should be thoroughly documented, ideally with a scientific paper, to ensure that the core idea behind an algorithm is consistent with the present state-of-the-art and does not become buried under thousands of code lines. From my perspective, the primary issue to address with OpenCascade is "knowledge engineering," whereas the fundamentals may remain untouched. Having said that, I agree with you that the low-level data structure requires careful examination for efficiency.
 

blobfish

CAD community veteran
Well, I suppose it would be maintained to some extent, similarly to how the prior OCC team maintained fillets, chamfers, and offsets (that is, they kept the algorithms compilable and regression-free) ...
'maintained' was a poor choice of words. I should have said something like 'actively developed'. I agree, high turnover will create black holes that suck. 😉 I think this is true everywhere, but it is proportional to complexity of the problem domain. I am sure most problems stem from organizational and not the individuals. IMHO: I am not sure there is a business path forward to an open source modeling kernel at this point, as the proprietary vendors are just too far ahead for most people to care. At the other end, I don't think there are enough qualified people willing to volunteer their time. Maybe the only way forward is a nonprofit foundation that can court big money.....Just let me have some hope. :)


... when I was much younger, even started to put together Yet Another Modeling Kernel. That has been very romantic but absolutely unrealistic, as you can guess.
That must be a 'right of passage'. I bet you mine was worse than yours. 😄


Well, what is your opinion on ACIS and Parasolid data structures? Don't you find them quite similar to what we have in OpenCascade?
This is where my ignorance shines through, as I have never spent anytime with ACIS or Parasolid. IHMO: I would still be critical even though they 'pulled it off'. This is my opinion as a programmer, certainly not as an expert of solid modeling kernels. I think topology is expressed more naturally as a graph vs a recursive data structure. I realize that even if (big if) my criticism is valid, these kernels where started 30, 40 years ago where 'reality' was different.

... I guess this example might look a bit synthetic ...
I fully agree with this. I did some things with CGAL::SurfaceMesh and it has a clear separation of edge vs half_edge. I found that code easier to comprehend.


My opinion on this has been slightly different. Even if OpenCascade's topological model is "broken" from the beginning, I feel the library's main issue is the reliability of its higher-level API.
That was kind of my point. I am not sure reliability is feasible with all these shapes 'baked' together. BRep naturally has some sharing, connected faces of a shell share and edge, connected edges of a wire share a vertex ... etc.. Where I am critical of, is the sharing across separate shapes. For example: when a solid cube gets 1 edge blended away the output solid will share 2 faces with the input solid. This goes on throughout the API and creates a 'house of cards'. People, including myself, have added calls to BRepBuilderAPI_Copy to break the sharing to prevent algos from breaking shapes across the feature dependency graph. Just not sure such an in-depth sharing/COW is a net positive, it certainly isn't in the current state. Just to contrast: My intuition of working with UG tells me parasolid, with the previous example, that the input solid gets thrown away and the 2 faces belong, or get copied to the output solid. Meaning there are not multiple solids sharing the same face.
 

Quaoar

Administrator
Staff member
I am not sure there is a business path forward to an open source modeling kernel at this point, as the proprietary vendors are just too far ahead for most people to care.
I agree, the commercial kernels are light years away from open-source OpenCascade, but there is something that makes me feel optimistic. First off, many people are using OpenCascade and more are starting to use it. Recently, I came across yet another wrapper for OCC (occwl) and this time it's from Autodesk AI people. Autodesk is using OpenCascade, well, for a niche job, of course, but still.

OpenCascade has some strong points, like its data exchange (STEP translator), and this module does not require any active development, just maintenance should be fine enough. I bet OCC (as a company) is not willing to invest man-years into low-level math or participate in CAX-IF rallies (unlike Datakit, kudos to them), but they still HAVE TO maintain the kernel as they have their paying clients from industry, research, and even government (CEA/EDF and Salome is the example). Therefore, what I would like to expect from the kernel is stability. Personally, I don't want them to introduce anything new to the kernel, just maintain what exists and improve its a) robustness; b) accuracy; c) performance. That's the bare minimum, and if we have sufficiently good Booleans and stuff, we, as a community, can build our own push/pull on it.

I doubt OpenCascade can serve as a basis for a fully-fledged parametric CAD system, but it can in theory be good enough for a direct CAD editor. Well, actually, there's this new ondsel company that should inevitably face all these modeling traps on their way to commercialize FreeCAD. It's also a good sign to me, the same as this Huawei fork.

This is where my ignorance shines through, as I have never spent anytime with ACIS or Parasolid.
Same here. But I find it quite interesting that after 15 years spent in CAD software development, I have never been asked to develop something on ACIS/Parasolid/etc. Okay, 12 of these 15 I spent at OCC, but even now, what I see is that people are looking for flexible and open products. They don't want to get caught in walled commercial gardens.

Where I am critical of, is the sharing across separate shapes. For example: when a solid cube gets 1 edge blended away the output solid will share 2 faces with the input solid.
Okay, I see what you mean. Well, yes, reusing B-rep elements from the former states of geometry is dangerous. Naturally, it's enough to change the shared tolerance at some later stage in the modeling pipeline, and the previous states of the shape will get infected. OCC probably overengineered their approach to sharing: you can literally design a cube with just 1 face and 6 distinct locations. The problem is that it won't work later on, e.g., when you try to make a fillet.
 
Top