hannobraun / fornjot

Early-stage b-rep CAD kernel, written in the Rust programming language.
https://www.fornjot.app/
Other
2.03k stars 116 forks source link

Simplify object graph around `HalfEdge` #1525

Closed hannobraun closed 1 year ago

hannobraun commented 1 year ago

(This issue is part of a larger cleanup effort. See https://github.com/hannobraun/Fornjot/issues/1589.)

Arguably the most important part of the Fornjot kernel's code base are the core data structures that store the objects that make up shapes. Those objects reference each other. For example, a Cycle is made up HalfEdges and references those. Through these references, objects form a graph.

The objects and the graph they form have evolved over time, always in response to specific problems that I had to solve. The further evolution of this code is something that I think about a lot, due to the importance of the object graph to the Fornjot kernel. Everything in the kernel deals with those objects, in one way or another.

In recent weeks, I've been playing around with lots of ideas on how to simplify the object graph. Some of these ideas are vague and require further thought and experimentation. One of them has reached a stage, where it has become concrete enough to open an issue about. (And you're reading it!)

Specifically, this is a concept for how to simplify the object graph around HalfEdge. I've already started working on this, so the some of the items in this list are already checked off. I plan to keep this list updated as I'm going forward:

This is it! This plan, if it works out, would remove two types of objects, simplifying the object graph. This would in turn make existing of code that operates on this part of the object graph simpler, and new code easier to write.

I have already started working on this, and plan to continue until I hit a hurdle that makes it necessary to delay or stop the rest of the plan.

hannobraun commented 1 year ago

I've been actively working on this issue, as the list of referencing pull request above this comment shows. The list in the original issue description is up-to-date. The current focus is to only reference a single SurfaceVertex in HalfEdge, but that requires some deeper surgery than previously expected.

I've already removed a lot of references to HalfEdge::surface_vertices, but the remaining ones are a bit harder to deal with. The one I'm currently working on is in HalfEdge's Reverse implementation. There's no good way to adapt that code without it, I think, but there's a different solution: Just remove that implementation, which would mean only Cycles can be reversed, not single HalfEdges.

I think this would be fine, but unfortunately the sweep code relies on reversing single HalfEdges. But that code could use some cleanup anyway, so I'm currently rewriting the problematic parts of it.

hannobraun commented 1 year ago

The rewrite of (some of) the sweep code has been causing more trouble than expected. It already felt 95% done when I posted my previous comment here, but unfortunately some of the building blocks the rewritten code uses (mostly in the builder API) are too limited to support this new use case. I've been successful in addressing some of that (see the pull requests that have referenced this issue since my previous comment), but in other cases, I've hit some hard problems.

These hard problems are mostly caused by the complexity of the object graph. Which is quite ironic, since this is an attempt to simplify the object graph. But this shows how important this work is.

For now, I'll keep at it. I don't think any of the problems I've hit are impossible. It's just a lot of complicated "I need this data here to do A, but the data won't be available until later when I do B, so where do I get it now". The devil's in the details, as usual. I think it's acceptable to find some ugly hacks to paper over these problems, if necessary. If that allows me to advance the cause of object graph simplification, I can circle back later and fix these hacks, once the simplified object graph makes stuff like that easier.

If I can't find solutions, I might need to pause work on this issue and try to start another simplification attempt in a different place. I have lots of ideas, but unfortunately some are quite radical, meaning they would be larger changes and not sure to work out. This issue, on the other hand, is a series of rather incremental improvements that I can build on later, when it comes to working on the more radical solutions.

hannobraun commented 1 year ago

I've made a lot of progress since my last update here. The rewrite of the sweep code is finished. Since then, I've made some more specific plans to simplify the object graph (see #1589) and started picking off some of the lower-hanging fruit. This has also made the outstanding work on this issue a bit easier.

I've landed two more pull requests (see references above this comment) that made some progress here, but I'm again starting to hit hurdles. I will probably focus on #1586 for the time being, as I suspect that I can make some progress there, and that this progress will in turn help with the hurdles I'm hitting here.

hannobraun commented 1 year ago

Turns out I was able to return to this issue much faster than I expected. The next item on the list, referencing only a single SurfaceVertex in HalfEdge is done! List updated.