summaryrefslogtreecommitdiff
path: root/crates/typst-library/src/visualize
diff options
context:
space:
mode:
authorReid Johnson <92353079+arj0019@users.noreply.github.com>2023-08-31 02:51:00 -0500
committerGitHub <noreply@github.com>2023-08-31 09:51:00 +0200
commit5c1db0c4b8f6422d5dfaaf27b5a0342a78b4a2ce (patch)
tree850af535ed92530fcf73f8fb1b3dcb6f2df4e36d /crates/typst-library/src/visualize
parentbcab77052422baaa29b57b62f14a19af8cc87225 (diff)
Add regular polygons to visualize (#1215)
Diffstat (limited to 'crates/typst-library/src/visualize')
-rw-r--r--crates/typst-library/src/visualize/polygon.rs74
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()
+}