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

Use flexible object selectors in update and replace operations #2164

Open
hannobraun opened this issue Jan 17, 2024 · 0 comments
Open

Use flexible object selectors in update and replace operations #2164

hannobraun opened this issue Jan 17, 2024 · 0 comments
Labels
topic: core Issues relating to core geometry, operations, algorithms type: feature New features and improvements to existing features

Comments

@hannobraun
Copy link
Owner

Current Situation

Currently, many of the methods that are part of update and replace operations act on specifically one object, identified by a Handle. How specifically they do that is a bit inconsistent: Some accept an argument for the updated/replaced object, others accept a closure that returns the updated/replaced object.

Here are examples of that:

pub trait UpdateCycle {
    // ...

    fn update_half_edge(
        &self,
        handle: &Handle<HalfEdge>,
        update: impl FnOnce(&Handle<HalfEdge>) -> Handle<HalfEdge>,
    ) -> Self;

    // ...
}

pub trait ReplaceCurve: Sized {
    // ...

    fn replace_curve(
        &self,
        original: &Handle<Curve>,
        replacement: Handle<Curve>,
        services: &mut Services,
    ) -> ReplaceOutput<Self, Self::BareObject>;
}

This approach is not very flexible, which leads to some cumbersome code. The inconsistency is also not great. A consistent design should be found, and followed where applicable.

It's possible to use methods of ObjectSet to acquire the handle of an object that is not yet known to the caller. Those are designed to be used in conjunction with methods like the ones presented above, for example to select the only object in a set (e.g. cycle.update_half_edge(cycle.half_edges().only(), ...)), or select an object based on its index (e.g. cycle.update_half_edge(cycle.half_edges().nth(2), ...)).

This approach leads to a minor problem, where code isn't as compact as it could be, because the object needs to be kept in a variable to be used multiple times. For example:

let cuboid = cuboid::model([size, size, size], services);

cuboid.update_shell(cuboid.shells().only(), |shell| {
// ...

Concept

Selection can be made more flexible, by accepting a selector argument that can select a specific object, or one or more objects based on query properties encoded into the selector. All applicable methods need to accept closures that return the updated/replaced object, as a closure can be called one or more times, depending on the selector.

Selector

We can define a trait Selector, which can then be accepted by all applicable methods as selector: impl Selector<SomeObject>. Selector would be implemented for multiple types:

  • Handle<T>, to select one specific object.
  • Select, and enum with variants for straight-forward selections. See below.
  • In the future, any number of more complex selectors. For example geometrical selectors, to do stuff like select the bottom face, or the front-most face that also has a specific orientation, or whatever else is required.

I'm not totally clear on what the actual interface of Selector would be, but for a start, we should keep it simple. Maybe something like fn select(object_set: &ObjectSet) -> impl Iterator<&Handle>;, roughly.

Select

In addition to paving the way for more complex selectors, as described above, this issue would also include a simplification of the current system in the form of a Select enum. Select would be used to replace the aforementioned ObjectSet methods, for example like Select::Only or Select::Nth(2).

This would have the advantage of not requiring access to the object, allowing some minor simplifications. The example above could be written as this:

cuboid::model([size, size, size], services)
    .update_shell(Select::Only, |shell| {
// ...

Next Steps

I believe this is pretty much ready for implementation (but of course, that implementation might provide some surprising problems and insights that could change the design). I don't have firm plans to work on this, so somebody could pick this up, if they wanted. Otherwise, I might do this in between other tasks at some point, as I don't believe it's that big of a job.

@hannobraun hannobraun added type: feature New features and improvements to existing features topic: core Issues relating to core geometry, operations, algorithms labels Jan 17, 2024
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: feature New features and improvements to existing features
Projects
None yet
Development

No branches or pull requests

1 participant