Skip to content

Commit 8001050

Browse files
committed
Feat: Add support for rounded and inward-rounded Bevel options
1 parent 220d629 commit 8001050

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

node-graph/gcore/src/vector/vector_nodes.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,7 @@ async fn morph<F: 'n + Send + Copy>(
10911091
VectorDataTable::new(result)
10921092
}
10931093

1094-
fn bevel_algorithm(mut vector_data: VectorData, distance: f64) -> VectorData {
1094+
fn bevel_algorithm(mut vector_data: VectorData, distance: f64, roundness: f64) -> VectorData {
10951095
// Splits a bézier curve based on a distance measurement
10961096
fn split_distance(bezier: bezier_rs::Bezier, distance: f64, length: f64) -> bezier_rs::Bezier {
10971097
const EUCLIDEAN_ERROR: f64 = 0.001;
@@ -1365,16 +1365,31 @@ fn bevel_algorithm(mut vector_data: VectorData, distance: f64) -> VectorData {
13651365
new_segments
13661366
}
13671367

1368-
fn insert_new_segments(vector_data: &mut VectorData, new_segments: &[[usize; 2]]) {
1368+
fn insert_new_segments(vector_data: &mut VectorData, new_segments: &[[usize; 2]], roundness: f64) {
13691369
let mut next_id = vector_data.segment_domain.next_id();
1370+
13701371
for &[start, end] in new_segments {
1371-
vector_data.segment_domain.push(next_id.next_id(), start, end, bezier_rs::BezierHandles::Linear, StrokeId::ZERO);
1372+
let start_pos = vector_data.point_domain.positions()[start];
1373+
let end_pos = vector_data.point_domain.positions()[end];
1374+
1375+
let direction = start_pos - end_pos;
1376+
let perpendicular = DVec2::new(-direction.y, direction.x).normalize();
1377+
1378+
let curve_amount = direction.length() * roundness; // 50% of line length
1379+
let midpoint = (start_pos + end_pos) / 2.0;
1380+
let control_point = midpoint + perpendicular * curve_amount;
1381+
1382+
let handles = bezier_rs::BezierHandles::Quadratic { handle: control_point };
1383+
1384+
vector_data.segment_domain.push(next_id.next_id(), start, end, handles, StrokeId::ZERO);
13721385
}
13731386
}
13741387

1375-
let mut segments_connected = segments_connected_count(&vector_data);
1376-
let new_segments = update_existing_segments(&mut vector_data, distance, &mut segments_connected);
1377-
insert_new_segments(&mut vector_data, &new_segments);
1388+
if distance > 1.0 {
1389+
let mut segments_connected = segments_connected_count(&vector_data);
1390+
let new_segments = update_existing_segments(&mut vector_data, distance, &mut segments_connected);
1391+
insert_new_segments(&mut vector_data, &new_segments, roundness);
1392+
}
13781393

13791394
vector_data
13801395
}
@@ -1392,11 +1407,14 @@ async fn bevel<F: 'n + Send + Copy>(
13921407
)]
13931408
source: impl Node<F, Output = VectorDataTable>,
13941409
#[default(10.)] distance: Length,
1410+
#[default(0.)]
1411+
#[range((-1.0, 1.0))]
1412+
roundness: f64,
13951413
) -> VectorDataTable {
13961414
let source = source.eval(footprint).await;
13971415
let source = source.one_item();
13981416

1399-
let result = bevel_algorithm(source.clone(), distance);
1417+
let result = bevel_algorithm(source.clone(), distance, roundness);
14001418

14011419
VectorDataTable::new(result)
14021420
}
@@ -1639,7 +1657,7 @@ mod test {
16391657
#[tokio::test]
16401658
async fn bevel_rect() {
16411659
let source = Subpath::new_rect(DVec2::ZERO, DVec2::ONE * 100.);
1642-
let beveled = super::bevel(Footprint::default(), &vector_node(source), 5.).await;
1660+
let beveled = super::bevel(Footprint::default(), &vector_node(source), 5., 0.).await;
16431661
let beveled = beveled.one_item();
16441662

16451663
assert_eq!(beveled.point_domain.positions().len(), 8);
@@ -1662,7 +1680,7 @@ mod test {
16621680
async fn bevel_open_curve() {
16631681
let curve = Bezier::from_cubic_dvec2(DVec2::ZERO, DVec2::new(10., 0.), DVec2::new(10., 100.), DVec2::X * 100.);
16641682
let source = Subpath::from_beziers(&[Bezier::from_linear_dvec2(DVec2::X * -100., DVec2::ZERO), curve], false);
1665-
let beveled = super::bevel(Footprint::default(), &vector_node(source), 5.).await;
1683+
let beveled = super::bevel(Footprint::default(), &vector_node(source), 5., 0.).await;
16661684
let beveled = beveled.one_item();
16671685

16681686
assert_eq!(beveled.point_domain.positions().len(), 4);
@@ -1684,7 +1702,7 @@ mod test {
16841702
let mut vector_data = VectorData::from_subpath(source);
16851703
let transform = DAffine2::from_scale_angle_translation(DVec2::splat(10.), 1., DVec2::new(99., 77.));
16861704
vector_data.transform = transform;
1687-
let beveled = super::bevel(Footprint::default(), &FutureWrapperNode(VectorDataTable::new(vector_data)), 5.).await;
1705+
let beveled = super::bevel(Footprint::default(), &FutureWrapperNode(VectorDataTable::new(vector_data)), 5., 0.).await;
16881706
let beveled = beveled.one_item();
16891707

16901708
assert_eq!(beveled.point_domain.positions().len(), 4);
@@ -1703,7 +1721,7 @@ mod test {
17031721
#[tokio::test]
17041722
async fn bevel_too_high() {
17051723
let source = Subpath::from_anchors([DVec2::ZERO, DVec2::new(100., 0.), DVec2::new(100., 100.), DVec2::new(0., 100.)], false);
1706-
let beveled = super::bevel(Footprint::default(), &vector_node(source), 999.).await;
1724+
let beveled = super::bevel(Footprint::default(), &vector_node(source), 999., 0.).await;
17071725
let beveled = beveled.one_item();
17081726

17091727
assert_eq!(beveled.point_domain.positions().len(), 6);
@@ -1724,7 +1742,7 @@ mod test {
17241742
let curve = Bezier::from_cubic_dvec2(DVec2::ZERO, DVec2::new(10., 0.), DVec2::new(10., 100.), DVec2::X * 100.);
17251743
let point = Bezier::from_cubic_dvec2(DVec2::ZERO, DVec2::ZERO, DVec2::ZERO, DVec2::ZERO);
17261744
let source = Subpath::from_beziers(&[Bezier::from_linear_dvec2(DVec2::X * -100., DVec2::ZERO), point, curve], false);
1727-
let beveled = super::bevel(Footprint::default(), &vector_node(source), 5.).await;
1745+
let beveled = super::bevel(Footprint::default(), &vector_node(source), 5., 0.).await;
17281746
let beveled = beveled.one_item();
17291747

17301748
assert_eq!(beveled.point_domain.positions().len(), 6);

0 commit comments

Comments
 (0)