diff options
| author | Reid Johnson <92353079+arj0019@users.noreply.github.com> | 2023-08-31 02:51:00 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-31 09:51:00 +0200 |
| commit | 5c1db0c4b8f6422d5dfaaf27b5a0342a78b4a2ce (patch) | |
| tree | 850af535ed92530fcf73f8fb1b3dcb6f2df4e36d /crates/typst-library/src/visualize | |
| parent | bcab77052422baaa29b57b62f14a19af8cc87225 (diff) | |
Add regular polygons to visualize (#1215)
Diffstat (limited to 'crates/typst-library/src/visualize')
| -rw-r--r-- | crates/typst-library/src/visualize/polygon.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/crates/typst-library/src/visualize/polygon.rs b/crates/typst-library/src/visualize/polygon.rs index d2d3132a..b244b2e9 100644 --- a/crates/typst-library/src/visualize/polygon.rs +++ b/crates/typst-library/src/visualize/polygon.rs @@ -1,3 +1,5 @@ +use std::f64::consts::PI; + use crate::prelude::*; /// A closed polygon. @@ -19,6 +21,10 @@ use crate::prelude::*; /// Display: Polygon /// Category: visualize #[element(Layout)] +#[scope( + scope.define("regular", polygon_regular_func()); + scope +)] pub struct PolygonElem { /// How to fill the polygon. See the /// [rectangle's documentation]($func/rect.fill) for more details. @@ -91,3 +97,71 @@ impl Layout for PolygonElem { Ok(Fragment::frame(frame)) } } + +/// A regular polygon, defined by its size and number of vertices. +/// +/// ## Example { #example } +/// ```example +/// #polygon.regular( +/// fill: blue.lighten(80%), +/// stroke: blue, +/// size: 30pt, +/// vertices: 3, +/// ) +/// ``` +/// +/// Display: Regular Polygon +/// Category: visualize +#[func] +pub fn polygon_regular( + /// How to fill the polygon. See the general + /// [polygon's documentation]($func/polygon.fill) for more details. + #[named] + fill: Option<Option<Paint>>, + + /// How to stroke the polygon. See the general + /// [polygon's documentation]($func/polygon.stroke) for more details. + #[named] + stroke: Option<Smart<Option<PartialStroke>>>, + + /// The diameter of the circumcircle of the regular polygon (https://en.wikipedia.org/wiki/Circumcircle). + #[named] + #[default(Em::one().into())] + size: Length, + + /// The number of vertices in the polygon. + #[named] + #[default(3)] + vertices: u64, +) -> Content { + let radius = size / 2.0; + let angle = |i: f64| { + 2.0 * PI * i / (vertices as f64) + PI * (1.0 / 2.0 - 1.0 / vertices as f64) + }; + let (horizontal_offset, vertical_offset) = (0..=vertices) + .map(|v| { + ( + (radius * angle(v as f64).cos()) + radius, + (radius * angle(v as f64).sin()) + radius, + ) + }) + .fold((radius, radius), |(min_x, min_y), (v_x, v_y)| { + (if min_x < v_x { min_x } else { v_x }, if min_y < v_y { min_y } else { v_y }) + }); + let vertices = (0..=vertices) + .map(|v| { + let x = (radius * angle(v as f64).cos()) + radius - horizontal_offset; + let y = (radius * angle(v as f64).sin()) + radius - vertical_offset; + Axes::new(x, y).map(Rel::from) + }) + .collect(); + + let mut elem = PolygonElem::new(vertices); + if let Some(fill) = fill { + elem.push_fill(fill); + } + if let Some(stroke) = stroke { + elem.push_stroke(stroke); + } + elem.pack() +} |
