From a4075f8b9b387f4e0aea9cc0ee11ca62c99a648d Mon Sep 17 00:00:00 2001 From: Pg Biel <9021226+PgBiel@users.noreply.github.com> Date: Fri, 21 Apr 2023 06:28:46 -0300 Subject: [PATCH] Implement math `cancel` function (#793) --- library/src/math/cancel.rs | 169 +++++++++++++++++++++++++++++++++++++ library/src/math/mod.rs | 3 + src/geom/point.rs | 5 ++ tests/ref/math/cancel.png | Bin 0 -> 24698 bytes tests/typ/math/cancel.typ | 34 ++++++++ 5 files changed, 211 insertions(+) create mode 100644 library/src/math/cancel.rs create mode 100644 tests/ref/math/cancel.png create mode 100644 tests/typ/math/cancel.typ diff --git a/library/src/math/cancel.rs b/library/src/math/cancel.rs new file mode 100644 index 000000000..0ea7b1d29 --- /dev/null +++ b/library/src/math/cancel.rs @@ -0,0 +1,169 @@ +use super::*; + +/// Displays a diagonal line over a part of an equation. +/// +/// ## Example +/// ```example +/// Here, we can simplify: +/// $ (a dot.c b dot.c cancel(x)) / cancel(x) $ +/// ``` +/// +/// Display: Cancel +/// Category: math +#[element(LayoutMath)] +pub struct CancelElem { + /// The content over which the line should be placed. + #[required] + pub body: Content, + + /// The length of the line, relative to the length of the diagonal spanning + /// the whole element being "cancelled". A value of `{100%}` would then have + /// the line span precisely the element's diagonal. + /// + /// Defaults to `{100% + 3pt}`. + /// + /// ```example + /// $ a + cancel(x, length: #200%) - b - cancel(x, length: #200%) $ + /// ``` + #[default(Rel::new(Ratio::one(), Abs::pt(3.0).into()))] + pub length: Rel, + + /// If the cancel line should be inverted (heading northwest instead of + /// northeast). + /// + /// Defaults to `{false}`. + /// + /// ```example + /// $ (a cancel((b + c), inverted: #true)) / cancel(b + c, inverted: #true) $ + /// ``` + #[default(false)] + pub inverted: bool, + + /// If two opposing cancel lines should be drawn, forming a cross over the + /// element. Overrides `inverted`. + /// + /// Defaults to `{false}`. + /// + /// ```example + /// $ cancel(x, cross: #true) $ + /// ``` + #[default(false)] + pub cross: bool, + + /// Rotate the cancel line by a certain angle. See the + /// [line's documentation]($func/line.angle) for more details. + /// + /// ```example + /// $ cancel(x, rotation: #30deg) $ + /// ``` + #[default(Angle::zero())] + pub rotation: Angle, + + /// How to stroke the cancel line. See the + /// [line's documentation]($func/line.stroke) for more details. + /// + /// ```example + /// $ cancel(x, stroke: #{red + 1.5pt}) $ + /// ``` + #[resolve] + #[fold] + pub stroke: PartialStroke, +} + +impl LayoutMath for CancelElem { + fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> { + let mut body = ctx.layout_frame(&self.body())?; + + let styles = ctx.styles(); + let body_size = body.size(); + let span = self.span(); + let length = self.length(styles).resolve(styles); + + // Default stroke has 0.5pt for better visuals. + let stroke = self.stroke(styles).unwrap_or(Stroke { + paint: TextElem::fill_in(styles), + thickness: Abs::pt(0.5), + ..Default::default() + }); + + let invert = self.inverted(styles); + let cross = self.cross(styles); + let angle = self.rotation(styles); + + let invert_first_line = !cross && invert; + let first_line = draw_cancel_line( + length, + stroke.clone(), + invert_first_line, + angle, + body_size, + span, + ); + + // The origin of our line is the very middle of the element. + let center = body_size.to_point() / 2.0; + body.push_frame(center, first_line); + + if cross { + // Draw the second line. + let second_line = + draw_cancel_line(length, stroke, true, angle, body_size, span); + + body.push_frame(center, second_line); + } + + ctx.push(FrameFragment::new(ctx, body)); + + Ok(()) + } +} + +/// Draws a cancel line. +fn draw_cancel_line( + length: Rel, + stroke: Stroke, + invert: bool, + angle: Angle, + body_size: Size, + span: Span, +) -> Frame { + // B + // /| + // diagonal / | height + // / | + // / | + // O ---- + // width + let diagonal = body_size.to_point().hypot(); + let length = length.relative_to(diagonal); + let (width, height) = (body_size.x, body_size.y); + let mid = body_size / 2.0; + + // Scale the amount needed such that the cancel line has the given 'length' + // (reference length, or 100%, is the whole diagonal). + // Scales from the center. + let scale = length.to_raw() / diagonal.to_raw(); + + // invert horizontally if 'invert' was given + let scale_x = scale * if invert { -1.0 } else { 1.0 }; + let scale_y = scale; + let scales = Axes::new(scale_x, scale_y); + + // Draw a line from bottom left to top right of the given element, where the + // origin represents the very middle of that element, that is, a line from + // (-width / 2, height / 2) with length components (width, -height) (sign is + // inverted in the y-axis). After applying the scale, the line will have the + // correct length and orientation (inverted if needed). + let start = Axes::new(-mid.x, mid.y).zip(scales).map(|(l, s)| l * s); + let delta = Axes::new(width, -height).zip(scales).map(|(l, s)| l * s); + + let mut frame = Frame::new(body_size); + frame.push( + start.to_point(), + FrameItem::Shape(Geometry::Line(delta.to_point()).stroked(stroke), span), + ); + + // Having the middle of the line at the origin is convenient here. + frame.transform(Transform::rotate(angle)); + frame +} diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs index 9c8a9cdf3..48fe52d21 100644 --- a/library/src/math/mod.rs +++ b/library/src/math/mod.rs @@ -5,6 +5,7 @@ mod ctx; mod accent; mod align; mod attach; +mod cancel; mod delimited; mod frac; mod fragment; @@ -20,6 +21,7 @@ mod underover; pub use self::accent::*; pub use self::align::*; pub use self::attach::*; +pub use self::cancel::*; pub use self::delimited::*; pub use self::frac::*; pub use self::matrix::*; @@ -71,6 +73,7 @@ pub fn module() -> Module { math.define("overbrace", OverbraceElem::func()); math.define("underbracket", UnderbracketElem::func()); math.define("overbracket", OverbracketElem::func()); + math.define("cancel", CancelElem::func()); // Fractions and matrix-likes. math.define("frac", FracElem::func()); diff --git a/src/geom/point.rs b/src/geom/point.rs index b31ea2965..e7811e1e6 100644 --- a/src/geom/point.rs +++ b/src/geom/point.rs @@ -45,6 +45,11 @@ impl Point { Self { x: self.x.max(other.x), y: self.y.max(other.y) } } + /// The distance between this point and the origin. + pub fn hypot(self) -> Abs { + Abs::raw(self.x.to_raw().hypot(self.y.to_raw())) + } + /// Transform the point with the given transformation. pub fn transform(self, ts: Transform) -> Self { Self::new( diff --git a/tests/ref/math/cancel.png b/tests/ref/math/cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..96b29c45f3e7026fd34f23938588165dadff5d8b GIT binary patch literal 24698 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