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

Allow selection by clicking open shapes that are visibly filled #1711

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

slayyden
Copy link

@slayyden slayyden commented Mar 28, 2024

Allows for selection of open shapes by clicking on the filled region.

Closes #1736

@Keavon
Copy link
Member

Keavon commented Mar 30, 2024

!build

Copy link

📦 Build Complete for 5a97aff
https://d6aa6d2f.graphite.pages.dev

@Keavon
Copy link
Member

Keavon commented Apr 23, 2024

What's the latest status on this? It's still marked as a draft so I assume there's more to do?

@slayyden
Copy link
Author

This is feature complete and awaiting review for code quality and robustness.

@Keavon Keavon marked this pull request as ready for review April 24, 2024 07:02
@Keavon Keavon changed the title Select open shapes Allow selection by clicking open shapes that are visibly filled Apr 27, 2024
Comment on lines +272 to +298
if self.closed() {
// Winding number for a closed curve.
return self.iter().map(|bezier| bezier.winding(target_point)).sum::<i32>() != 0;
}

// The curve is not closed. Pretend that it is and compute the winding number
// change as if we had a segment from the last point back to the first.

// Position of first and last anchor points.
let first_anchor_point = self.manipulator_groups.first().map(|group| group.anchor);
let last_anchor_point = self.manipulator_groups.last().map(|group| group.anchor);
let endpoints = first_anchor_point.zip(last_anchor_point);

// Weight interpolating intersection location from last to first anchor point. Reject weights outside of [0, 1].
let t = endpoints.map(|(first, last)| (target_point.y - last.y) / (first.y - last.y)).filter(|t| (0.0..=1.).contains(t));
// Compute point of intersection.
// Reject points that are right of the click location since we compute winding numbers by ray-casting left.
let intersection_point = endpoints.zip(t).map(|((first, last), t)| t * first + (1. - t) * last).filter(|p| p.x <= target_point.x);
let winding_modification = first_anchor_point.zip(intersection_point).map_or_else(
// None variant implies no intersection and no modification to winding number.
|| 0,
// Clockwise (decrement winding number) and counterclockwise (increment winding number) intersection respectively.
|(first, intersection)| if first.y >= intersection.y { -1 } else { 1 },
);

// Add the winding modification to the winding number of the rest of the curve.
self.iter().map(|bezier| bezier.winding(target_point)).sum::<i32>() + winding_modification != 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this just involve temporarily closing the shape, calculating the value, then un-closing it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Keavon this would require the function to take the mutable shape which is unnecessarily restrictive and would involve cloning in some cases. Although I agree that this could be simplified to use the existing winding function instead of re-implementing it:

let modification = endpoints.map_or(0, |(p1, p2)| bezier_rs::Bezier::from_linear_dvec2(p1, p2).winding(target_point));

@@ -873,6 +873,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag

impl DocumentMessageHandler {
/// Runs an intersection test with all layers and a viewport space quad
/// TODO: properly check if layer is filled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this resolved?

@Keavon
Copy link
Member

Keavon commented May 8, 2024

Any updates about getting the two code review comments resolved? (The question and the suggestion to reuse the existing winding function instead of reimplementing it.) Thanks! (I'm also going to mark this as a draft for the moment until I hear more.)

@Keavon Keavon marked this pull request as draft May 8, 2024 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fill tool is unable to fill on Pencil created shapes
3 participants