-
-
Notifications
You must be signed in to change notification settings - Fork 119
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
Shell and Solid validation #1695
Conversation
Thank you, @A-Walrus! I'll take a closer look on Monday. For now, some comments.
No, I think that should be correct! At least it matches what I've been thinking.
Yes, that is definitely wrong. Unless there's a problem with the new validation code, this is likely a bug in the sweep code. I'm pretty sure that the sweep code creates the correct vertices (I've had problems with exactly that recently, and I'm pretty sure that's dealt with), but it might be creating duplicate So yeah, totally plausible you exposed a bug! |
I've taken a look at the sweep code, and I think I've found a bug: This is missing a call to Problem is though, if I add the call, validation still fails. I don't know what that means. Either there are more cases like this (I couldn't find any), or something weird is going on. |
Here's the change I made to the code I quoted in my previous comment: --- a/crates/fj-kernel/src/builder/cycle.rs
+++ b/crates/fj-kernel/src/builder/cycle.rs
@@ -44,9 +44,10 @@ impl CycleBuilder {
let half_edges = edges
.into_iter()
.circular_tuple_windows()
- .map(|((prev, _, _), (_, curve, boundary))| {
+ .map(|((prev, _, _), (half_edge, curve, boundary))| {
HalfEdgeBuilder::new(curve, boundary)
.with_start_vertex(prev.start_vertex().clone())
+ .with_global_form(half_edge.global_form().clone())
})
.collect(); |
There seems to have been a couple problems:
|
/// Cache for global edges | ||
pub global_edge: BTreeMap<ObjectId, Handle<GlobalEdge>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should have a more general caching solution. This seems to work for now but IDK if it's ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, this seems fine to me. If you come up with something better, feel free to suggest it of course, but I think we can keep it as-is.
@@ -75,7 +75,7 @@ impl Face { | |||
self.interiors.iter() | |||
} | |||
|
|||
/// Access all cycles of the face | |||
/// Access all cycles of the face (both exterior and interior) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the unrelated change to the docs, just wanted to clear it up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine! In general, I prefer to have unrelated changes in different commits, as I think that makes things a bit clearer overall, but that is a weak preference. We can leave it as-is.
Attempt to validate `Shell`'s by making sure that each half-edge in a shell refers to a global-edge that is referred to by another half-edge in that same shell. My logic says that each edge in a shell should be a part of exactly two faces but I may be wrong. This validation check currently fails with `cargo run --package export- validator`, but I'm not sure if this is a bug in my validation checks, or whether I exposed a bug in existing code. For example looking at the cuboid example, many global edges are referred to by only one half_edge, which seems wrong to me...
Validate whether coincident HalfEdges refer to the same GlobalEdge. This should resolve: hannobraun#1594. Checks whether they coincide by sampling.
Currently there are no tests for valid cases
This allows us to easily check whether some object raises some validation error, without requiring it to be the first. Switched to this macro whenever there was an assertion that the **first** validation error matches some pattern.
Simplify code to only sample 3 points, since that is enough for cicrcles and lines.
Fixed cycle builder like you commented, global_edge order, and added an edge cache. PS: We might want to make the `SweepCache` more general
Before it was in shell. This partially addresses hannobraun#1689, holding off on validating sketches until we figure out sketch-face relationship: hannobraun#1691
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @A-Walrus, this is great!
There seems to have been a couple problems:
- What you found about
with_global_form
- Incorrect order in
global_edges
- Needing to cache edges like we do vertices
This is some nice debugging. Well done!
I left some comments, but there's nothing critical. There's one suggestion that I will apply myself after submitting this review. This is good to merge!
Some additional comments:
- In general, I'd prefer if the final order of commits were such, that every single commit works (that means moving the fixes before the validations that require them). This doesn't matter most of the time, but if you're using
git bisect
, then a commit that has build errors or test failures can be inconvenient. - As you mention, the test cases only cover failure. This would be hard to fix right now, as we don't have good tools to build
Shell
s andSolid
s. But since I'm going to focus on APIs to build shapes for the foreseeable future, those test cases are probably a good testing ground for those new APIs.
@@ -75,7 +75,7 @@ impl Face { | |||
self.interiors.iter() | |||
} | |||
|
|||
/// Access all cycles of the face | |||
/// Access all cycles of the face (both exterior and interior) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine! In general, I prefer to have unrelated changes in different commits, as I think that makes things a bit clearer overall, but that is a weak preference. We can leave it as-is.
/// Cache for global edges | ||
pub global_edge: BTreeMap<ObjectId, Handle<GlobalEdge>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, this seems fine to me. If you come up with something better, feel free to suggest it of course, but I think we can keep it as-is.
let global_edge = GlobalEdge::new().insert(objects); | ||
let global_edge = cache | ||
.global_edge | ||
.entry(self.id()) | ||
.or_insert_with(|| GlobalEdge::new().insert(objects)) | ||
.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I swear, I was looking for exactly this code yesterday. I found the vertex caching code instead, and my brain was like "oh, so we do have the required caching". I'm pretty stupid sometimes 😄
In any case, good find!
Attempt to validate
Shell
's by making sure that each half-edge in a shell refers to a global-edge that is referred to by another half-edge in that same shell. My logic says that each edge in a shell should be a part of exactly two faces but I may be wrong.This validation check currently fails with
cargo run --package export- validator
, but I'm not sure if this is a bug in my validation checks, or whether I exposed a bug in existing code.For example looking at the cuboid example, many global edges are referred to by only one half_edge, which seems wrong to me...
edit by @hannobraun:
Close #1594