Add Area and Centroid nodes (#1749)

* initial attempt for area node

* allow node preview for more types

* make AreaNode sync and add CentroidNode

* cargo fmt

* preview of DVec2

* make the nodes async again

* use segment domain instead of region domain

* modify the check for linearity

* create a limit for area in centroid calculation

* cargo fmt

* reverse unnecessary changes

* add threshold to area calculation too.

* handle zero area edge case

* add todo comment

* implement 1D centroid and use it as fallback

* formatting floats to skip last zero

* add Centroid Type radio button to Centroid Node

* rename docs to use area and perimeter centroid

* add web demos for perimeter centroid

* add tests for perimeter centroid

* add fallback to use average of points

* Fix for broken area

* missing fixes

* Code review and rename Perimeter Centroid to Length Centroid

* Use dummy footprint in Area and Centroid nodes

* add doc and todo to clarify when `is_linear` fails

* use epsilon instead of zero

---------

Co-authored-by: 0hypercube <0hypercube@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
Elbert Ronnie
2024-05-22 13:11:11 -07:00
committed by GitHub
co-authored by 0hypercube Keavon Chambers Dennis Kobert
parent 4587457bfa
commit 5a1c171fc3
18 changed files with 443 additions and 43 deletions
+7 -1
View File
@@ -404,7 +404,13 @@ impl Bezier {
/// - `error` - For intersections where the provided bezier is non-linear, `error` defines the threshold for bounding boxes to be considered an intersection point.
pub fn unfiltered_intersections(&self, other: &Bezier, error: Option<f64>) -> Vec<[f64; 2]> {
let error = error.unwrap_or(0.5);
if other.handles == BezierHandles::Linear {
// TODO: This implementation does not handle the case of line-like bezier curves properly. Two line-like bezier curves which have the same slope
// should not return any intersection points but the current implementation returns many of them. This results in the area of line not being zero.
// Using `is_linear` does prevent it but only in cases where the line-like cubic bezier has it handles at exactly the same position as the start
// and end points. In future, the below algorithm needs to be changed to account for all possible cases.
if other.is_linear() {
// Rotate the bezier and the line by the angle that the line makes with the x axis
let line_directional_vector = other.end - other.start;
let angle = line_directional_vector.angle_between(DVec2::new(0., 1.));