Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add node that creates Arc shape #2470

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ pub(crate) fn property_from_type(
Some("Percentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(0.)).max(max(100.)), true).into(),
Some("SignedPercentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(-100.)).max(max(100.)), true).into(),
Some("Angle") => number_widget(document_node, node_id, index, name, number_input.mode_range().min(min(-180.)).max(max(180.)).unit("°"), true).into(),
Some("AngularDistance") => number_widget(document_node, node_id, index, name, number_input.mode_range().min(min(0.)).max(max(360.)).unit("°"), true).into(),
Some("PixelLength") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)).unit(" px"), true).into(),
Some("Length") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)), true).into(),
Some("Fraction") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)).max(max(1.)), true).into(),
Expand Down
37 changes: 37 additions & 0 deletions libraries/bezier-rs/src/subpath/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,43 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
Self::new(manipulator_groups, true)
}

/// Constructs an arc by a `radius`, `angle_start` and `angle_size`. Angles must be in radians. Slice option makes it look like pie or pacman.
pub fn new_arc(radius: f64, angle_start: f64, angle_size: f64, closed: bool, slice: bool) -> Self {
let center = DVec2::new(0., 0.);
let segments = (angle_size.abs() / (std::f64::consts::PI / 4.)).ceil() as usize;
let step = angle_size / segments as f64;
let half_step = step / 2.;
let factor = 4. / 3. * half_step.sin() / (1. + half_step.cos());

let mut manipulator_groups = Vec::with_capacity(segments);
let mut prev_in_handle = None;
let mut prev_end = DVec2::new(0., 0.);

for i in 0..segments {
let start_angle = angle_start + step * i as f64;
let end_angle = start_angle + step;
let start_vec = DVec2::from_angle(start_angle);
let end_vec = DVec2::from_angle(end_angle);

let start = center + radius * start_vec;
let end = center + radius * end_vec;

let handle_start = start + start_vec.perp() * radius * factor;
let handle_end = end - end_vec.perp() * radius * factor;

manipulator_groups.push(ManipulatorGroup::new(start, prev_in_handle, Some(handle_start)));
prev_in_handle = Some(handle_end);
prev_end = end;
}
manipulator_groups.push(ManipulatorGroup::new(prev_end, prev_in_handle, None));

if slice {
manipulator_groups.push(ManipulatorGroup::new(center, None, None));
}

Self::new(manipulator_groups, closed || slice)
}

/// Constructs a regular polygon (ngon). Based on `sides` and `radius`, which is the distance from the center to any vertex.
pub fn new_regular_polygon(center: DVec2, sides: u64, radius: f64) -> Self {
let sides = sides.max(3);
Expand Down
2 changes: 2 additions & 0 deletions node-graph/gcore/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub mod types {
pub type SignedPercentage = f64;
/// -180° - 180°
pub type Angle = f64;
/// 0° - 360°
pub type AngularDistance = f64;
/// Non-negative integer with px unit
pub type PixelLength = f64;
/// Non-negative
Expand Down
12 changes: 12 additions & 0 deletions node-graph/gcore/src/vector/generator_nodes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::Ctx;
use crate::registry::types::{Angle, AngularDistance};
use crate::vector::{HandleId, VectorData, VectorDataTable};
use bezier_rs::Subpath;
use glam::DVec2;
Expand Down Expand Up @@ -40,6 +41,17 @@ fn circle(_: impl Ctx, _primary: (), #[default(50.)] radius: f64) -> VectorDataT
VectorDataTable::new(VectorData::from_subpath(Subpath::new_ellipse(DVec2::splat(-radius), DVec2::splat(radius))))
}

#[node_macro::node(category("Vector: Shape"))]
fn arc(_: impl Ctx, _primary: (), #[default(50.)] radius: f64, start_angle: Angle, #[default(90.)] angle_size: AngularDistance, closed: bool, slice: bool) -> VectorDataTable {
VectorDataTable::new(VectorData::from_subpath(Subpath::new_arc(
radius,
start_angle / 360. * std::f64::consts::TAU,
angle_size / 360. * std::f64::consts::TAU,
closed,
slice,
)))
}

#[node_macro::node(category("Vector: Shape"))]
fn ellipse(_: impl Ctx, _primary: (), #[default(50)] radius_x: f64, #[default(25)] radius_y: f64) -> VectorDataTable {
let radius = DVec2::new(radius_x, radius_y);
Expand Down