Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple validation infrastructure from Shape #696

Closed
hannobraun opened this issue Jun 16, 2022 · 1 comment · Fixed by #715
Closed

Decouple validation infrastructure from Shape #696

hannobraun opened this issue Jun 16, 2022 · 1 comment · Fixed by #715
Assignees
Labels
topic: core Issues relating to core geometry, operations, algorithms type: development Work to ease development or maintenance, without direct effect on features or bugs

Comments

@hannobraun
Copy link
Owner

Shape is the data structure that represents 2D and 3D shapes in fj-kernel. It exists for several reasons, one of them being to support shape validation, which is code that makes sure certain properties about the shape, or the objects within, are upheld.

Shape comes with a lot of baggage though. Not least some heavyweight infrastructure with Store, Handle, and the like, but also auxiliary features like Mapping. Overall, there's a lot of complexity to make Shape work, and that complexity leaks into the rest of the kernel. Up until very recently, I considered this just a cost of doing business. But now I've had some ideas that, if they pan out, could make it possible to eliminate Shape outright, and use much simpler data structures in the Fornjot kernel.

One element of that is to decouple the validation infrastructure from Shape. Since validation is one of the main reasons for Shape's existence, that would be a big step toward getting rid of it. In the rest of this issue, I'm going to lay out a plan that I believe will make this possible.

Step 1: Rewrite validation infrastructure to work on top of Shape

Instead of having Shape validate each object as it is inserted, run validation once, once the Shape is complete. Access to the various iterator methods of Shape should be enough to implement this new validation infrastructure.

Step 2: Add infrastructure for iterating over objects

Add a trait ObjectIter, that looks something like this:

pub trait ObjectIter {
    fn vertices(&self) -> Iter<Vertex>;
    fn edges(&self) -> Iter<Edge>;

    // Methods to iterate over other types of objects go here.
}

Where Iter is a suitable iterator for this purpose. Maybe those will need to be associated types though, not sure.

This trait would be implemented for all types of objects. For example, Vertex would return itself from vertices, and only empty iterators from the other methods. Other object types would return themselves, and all objects they reference. Objects that reference other objects would use those other object's ObjectIter implementations for their own implementation.

What this provides, is a unified interface for iterating over the objects of a shape, or part of it, without being bound to Shape. This interface can then be used to completely decouple the validation infrastructure from Shape in a later step.

Step 3: Add new "entry point" object types

So far, there is no such thing as a top-level entry point into a Shape. Face comes closest, but any shape (2D or 3D) can consist of multiple faces.

I think we need two additional object types: Sketch, for 2D shapes, and Solid, for 3D shapes. Both of which would basically be a Vec<Face>, but would later be validated in different ways.

For the moment, we'd need to manage those objects alongside of Shape, but they wouldn't need to be inserted into it. I think in practice this would mean that ToShape (from fj-operations) would get an associated type to define which type of object it returns, and then return a tuple (basically (Self::Object, Shape)) from its to_shape method.

We can probably get away with simplifying this for the moment, and just use Vec<Face> instead of adding new object types.

Step 4: Use entry point objects for validation

Instead of using the Shape API in the validation code, use the entry point objects and their ObjectIter implementation instead. At this point, validation works completely independently of Shape.


If it's possible to abolish Shape, this plan should bring us much closer to it. I'm going to start working on this immediately, as this promises a great simplification of the kernel, which could pay substantial dividends going forward.

@hannobraun
Copy link
Owner Author

I've completed step 1 of this plan and have now started working on step 2. I have to say, making validation a one-time thing that works on top of Shape, instead of continually validating Shape as objects are inserted, has already let to some nice simplifications. I think the change has been worth it, even without the greater context of this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: core Issues relating to core geometry, operations, algorithms type: development Work to ease development or maintenance, without direct effect on features or bugs
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant