1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 21:30:03 -04:00

epaint: Introduce ArcPieShape for Simplified Arc and Pie Rendering

Enables straightforward painting of arcs and pies using specified start and end angles.
This commit is contained in:
Varphone Wong
2024-07-17 16:41:26 +08:00
parent 8d5b013dcb
commit 7c2967bd7c
7 changed files with 353 additions and 10 deletions

View File

@@ -0,0 +1,107 @@
use crate::*;
/// A arc or pie slice with a given start and end angle.
#[derive(Clone, Debug, PartialEq)]
pub struct ArcPieShape {
pub center: Pos2,
pub radius: f32,
pub start_angle: f32,
pub end_angle: f32,
pub closed: bool,
pub fill: Color32,
pub stroke: PathStroke,
}
impl ArcPieShape {
/// Create a new arc or pie shape.
///
/// # Arguments
///
/// * `center` - The center of the arc or pie.
/// * `radius` - The radius of the arc or pie.
/// * `start_angle` - The start angle of the arc or pie, in radians.
/// * `end_angle` - The end angle of the arc or pie, in radians.
/// * `closed` - If true, connect the center with the start and end points.
/// * `fill` - The fill color of the arc or pie.
/// * `stroke` - The stroke of the arc or pie.
pub fn new(
center: Pos2,
radius: f32,
start_angle: f32,
end_angle: f32,
closed: bool,
fill: impl Into<Color32>,
stroke: impl Into<PathStroke>,
) -> Self {
Self {
center,
radius,
start_angle,
end_angle,
closed,
fill: fill.into(),
stroke: stroke.into(),
}
}
/// Create a new arc shape.
///
/// # Arguments
///
/// * `center` - The center of the arc.
/// * `radius` - The radius of the arc.
/// * `start_angle` - The start angle of the arc, in radians.
/// * `end_angle` - The end angle of the arc, in radians.
/// * `stroke` - The stroke of the arc.
pub fn arc(
center: Pos2,
radius: f32,
start_angle: f32,
end_angle: f32,
stroke: impl Into<PathStroke>,
) -> Self {
Self::new(
center,
radius,
start_angle,
end_angle,
false,
Color32::TRANSPARENT,
stroke,
)
}
/// Create a new pie shape.
///
/// # Arguments
///
/// * `center` - The center of the pie.
/// * `radius` - The radius of the pie.
/// * `start_angle` - The start angle of the pie, in radians.
/// * `end_angle` - The end angle of the pie, in radians.
/// * `fill` - The fill color of the pie.
/// * `stroke` - The stroke of the pie.
pub fn pie(
center: Pos2,
radius: f32,
start_angle: f32,
end_angle: f32,
fill: impl Into<Color32>,
stroke: impl Into<PathStroke>,
) -> Self {
Self::new(center, radius, start_angle, end_angle, true, fill, stroke)
}
/// The visual bounding rectangle (includes stroke width)
pub fn visual_bounding_rect(&self) -> Rect {
if self.fill == Color32::TRANSPARENT && self.stroke.is_empty() {
Rect::NOTHING
} else {
let rect = Rect::from_center_size(self.center, vec2(self.radius, self.radius));
let start =
self.center + vec2(self.start_angle.cos(), self.start_angle.sin()) * self.radius;
let end = self.center + vec2(self.end_angle.cos(), self.end_angle.sin()) * self.radius;
rect.union(Rect::from_two_pos(start, end))
}
}
}

View File

@@ -1,3 +1,4 @@
mod arc_pie_shape;
mod bezier_shape;
mod circle_shape;
mod ellipse_shape;
@@ -8,6 +9,7 @@ mod shape;
mod text_shape;
pub use self::{
arc_pie_shape::ArcPieShape,
bezier_shape::{CubicBezierShape, QuadraticBezierShape},
circle_shape::CircleShape,
ellipse_shape::EllipseShape,

View File

@@ -11,8 +11,8 @@ use crate::{
};
use super::{
CircleShape, CubicBezierShape, EllipseShape, PaintCallback, PathShape, QuadraticBezierShape,
RectShape, TextShape,
ArcPieShape, CircleShape, CubicBezierShape, EllipseShape, PaintCallback, PathShape,
QuadraticBezierShape, RectShape, TextShape,
};
/// A paint primitive such as a circle or a piece of text.
@@ -32,6 +32,9 @@ pub enum Shape {
/// For performance reasons it is better to avoid it.
Vec(Vec<Shape>),
/// An arc or pie with a given start and end angle.
ArcPie(ArcPieShape),
/// Circle with optional outline and fill.
Circle(CircleShape),
@@ -255,6 +258,80 @@ impl Shape {
Self::Path(PathShape::convex_polygon(points, fill, stroke))
}
/// Generates an arc with a given start and end angle.
///
/// This function creates an arc centered at a specified point, with a specified radius.
/// The arc starts at the `start_angle` and ends at the `end_angle`.
/// Angles are specified in radians, with positive angles indicating clockwise rotation and negative angles indicating counterclockwise rotation.
///
/// # Arguments
///
/// * `center` - The center point of the arc.
/// * `radius` - The radius of the arc.
/// * `start_angle` - The start angle of the arc, in radians.
/// * `end_angle` - The end angle of the arc, in radians.
/// * `stroke` - The stroke of the arc.
///
/// # Example
///
/// ```no_run
/// # use epaint::{pos2, Color32, Shape, Stroke};
/// let arc = Shape::arc(pos2(100.0, 100.0), 50.0, 0.0, std::f32::consts::PI, Stroke::new(3.0, Color32::RED));
/// ```
pub fn arc(
center: Pos2,
radius: f32,
start_angle: f32,
end_angle: f32,
stroke: impl Into<PathStroke>,
) -> Self {
Self::ArcPie(ArcPieShape::arc(
center,
radius,
start_angle,
end_angle,
stroke,
))
}
/// Generates an pie with a given start and end angle.
///
/// This function creates an arc centered at a specified point, with a specified radius.
/// The pie starts at the `start_angle` and ends at the `end_angle`.
/// Angles are specified in radians, with positive angles indicating clockwise rotation and negative angles indicating counterclockwise rotation.
///
/// # Arguments
///
/// * `center` - The center point of the pie.
/// * `radius` - The radius of the pie.
/// * `start_angle` - The start angle of the pie, in radians.
/// * `end_angle` - The end angle of the pie, in radians.
/// * `stroke` - The stroke of the pie.
///
/// # Example
///
/// ```no_run
/// # use epaint::{pos2, Color32, Shape, Stroke};
/// let pie = Shape::pie(pos2(100.0, 100.0), 50.0, 0.0, std::f32::consts::PI, Color32::BLUE, Stroke::new(3.0, Color32::RED));
/// ```
pub fn pie(
center: Pos2,
radius: f32,
start_angle: f32,
end_angle: f32,
fill: impl Into<Color32>,
stroke: impl Into<PathStroke>,
) -> Self {
Self::ArcPie(ArcPieShape::pie(
center,
radius,
start_angle,
end_angle,
fill,
stroke,
))
}
#[inline]
pub fn circle_filled(center: Pos2, radius: f32, fill_color: impl Into<Color32>) -> Self {
Self::Circle(CircleShape::filled(center, radius, fill_color))
@@ -366,6 +443,7 @@ impl Shape {
}
rect
}
Self::ArcPie(arc_pie_shape) => arc_pie_shape.visual_bounding_rect(),
Self::Circle(circle_shape) => circle_shape.visual_bounding_rect(),
Self::Ellipse(ellipse_shape) => ellipse_shape.visual_bounding_rect(),
Self::LineSegment { points, stroke } => {
@@ -427,6 +505,11 @@ impl Shape {
shape.transform(transform);
}
}
Self::ArcPie(arc_pie_shape) => {
arc_pie_shape.center = transform * arc_pie_shape.center;
arc_pie_shape.radius *= transform.scaling;
arc_pie_shape.stroke.width *= transform.scaling;
}
Self::Circle(circle_shape) => {
circle_shape.center = transform * circle_shape.center;
circle_shape.radius *= transform.scaling;