Skip to content

Commit 91a8355

Browse files
Axis-aware coordinate helpers on Point, Vec2, Size, and Rect
1 parent 838b69e commit 91a8355

5 files changed

Lines changed: 175 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ You can find its changes [documented below](#0131-2026-05-13).
1515

1616
This release has an [MSRV][] of 1.85.
1717

18+
## Added
19+
20+
- Axis-aware coordinate helpers on `Point`, `Vec2`, `Size`, and `Rect`. ([#592][] by [@waywardmonkeys][])
21+
1822
## [0.13.1][] (2026-05-13)
1923

2024
This release has an [MSRV][] of 1.85.
@@ -313,6 +317,7 @@ Note: A changelog was not kept for or before this release
313317
[#575]: https://github.com/linebender/kurbo/pull/575
314318
[#580]: https://github.com/linebender/kurbo/pull/580
315319
[#585]: https://github.com/linebender/kurbo/pull/585
320+
[#592]: https://github.com/linebender/kurbo/pull/592
316321

317322
[Unreleased]: https://github.com/linebender/kurbo/compare/v0.13.1...HEAD
318323
[0.13.1]: https://github.com/linebender/kurbo/releases/tag/v0.13.1

kurbo/src/point.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,25 @@ impl Point {
229229
Axis::Vertical => self.y = value,
230230
}
231231
}
232+
233+
/// Return a new `Point` with the member matching the given axis set to
234+
/// the given value.
235+
///
236+
/// # Examples
237+
///
238+
/// ```
239+
/// use kurbo::{Axis, Point};
240+
///
241+
/// let point = Point::new(2.0, 3.0).with_coord(Axis::Vertical, 5.0);
242+
/// assert_eq!(point, Point::new(2.0, 5.0));
243+
/// ```
244+
#[inline]
245+
pub const fn with_coord(self, axis: Axis, value: f64) -> Point {
246+
match axis {
247+
Axis::Horizontal => Point::new(value, self.y),
248+
Axis::Vertical => Point::new(self.x, value),
249+
}
250+
}
232251
}
233252

234253
impl From<(f32, f32)> for Point {

kurbo/src/rect.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,93 @@ impl Rect {
641641
self.x0.is_nan() || self.y0.is_nan() || self.x1.is_nan() || self.y1.is_nan()
642642
}
643643

644+
/// Return the extent of this rectangle on the given axis.
645+
///
646+
/// This is equivalent to [`Rect::width`] for [`Axis::Horizontal`] and
647+
/// [`Rect::height`] for [`Axis::Vertical`].
648+
///
649+
/// Note: nothing forbids negative width or height.
650+
///
651+
/// # Examples
652+
///
653+
/// ```
654+
/// use kurbo::{Axis, Rect};
655+
///
656+
/// let rect = Rect::new(1.0, 2.0, 4.0, 7.0);
657+
/// assert_eq!(rect.extent(Axis::Horizontal), 3.0);
658+
/// assert_eq!(rect.extent(Axis::Vertical), 5.0);
659+
/// ```
660+
#[inline]
661+
pub const fn extent(&self, axis: Axis) -> f64 {
662+
match axis {
663+
Axis::Horizontal => self.width(),
664+
Axis::Vertical => self.height(),
665+
}
666+
}
667+
668+
/// Return the minimum coordinate on the given axis.
669+
///
670+
/// This returns the lesser endpoint even if this rectangle has negative
671+
/// width or height.
672+
///
673+
/// # Examples
674+
///
675+
/// ```
676+
/// use kurbo::{Axis, Rect};
677+
///
678+
/// let rect = Rect::new(8.0, 2.0, 4.0, 7.0);
679+
/// assert_eq!(rect.min_coord(Axis::Horizontal), 4.0);
680+
/// assert_eq!(rect.min_coord(Axis::Vertical), 2.0);
681+
/// ```
682+
#[inline]
683+
pub const fn min_coord(&self, axis: Axis) -> f64 {
684+
match axis {
685+
Axis::Horizontal => self.min_x(),
686+
Axis::Vertical => self.min_y(),
687+
}
688+
}
689+
690+
/// Return the maximum coordinate on the given axis.
691+
///
692+
/// This returns the greater endpoint even if this rectangle has negative
693+
/// width or height.
694+
///
695+
/// # Examples
696+
///
697+
/// ```
698+
/// use kurbo::{Axis, Rect};
699+
///
700+
/// let rect = Rect::new(8.0, 2.0, 4.0, 7.0);
701+
/// assert_eq!(rect.max_coord(Axis::Horizontal), 8.0);
702+
/// assert_eq!(rect.max_coord(Axis::Vertical), 7.0);
703+
/// ```
704+
#[inline]
705+
pub const fn max_coord(&self, axis: Axis) -> f64 {
706+
match axis {
707+
Axis::Horizontal => self.max_x(),
708+
Axis::Vertical => self.max_y(),
709+
}
710+
}
711+
712+
/// Return the center coordinate on the given axis.
713+
///
714+
/// # Examples
715+
///
716+
/// ```
717+
/// use kurbo::{Axis, Rect};
718+
///
719+
/// let rect = Rect::new(1.0, 2.0, 4.0, 8.0);
720+
/// assert_eq!(rect.center_coord(Axis::Horizontal), 2.5);
721+
/// assert_eq!(rect.center_coord(Axis::Vertical), 5.0);
722+
/// ```
723+
#[inline]
724+
pub const fn center_coord(&self, axis: Axis) -> f64 {
725+
match axis {
726+
Axis::Horizontal => 0.5 * (self.x0 + self.x1),
727+
Axis::Vertical => 0.5 * (self.y0 + self.y1),
728+
}
729+
}
730+
644731
/// Get the members matching the given axis.
645732
#[inline]
646733
pub const fn get_coords(self, axis: Axis) -> (f64, f64) {
@@ -667,6 +754,32 @@ impl Rect {
667754
Axis::Vertical => (self.y0, self.y1) = (v0, v1),
668755
}
669756
}
757+
758+
/// Return a new `Rect` with the members matching the given axis set to
759+
/// the given values.
760+
///
761+
/// This sets the raw endpoints for the axis and does not reorder or
762+
/// normalize them.
763+
///
764+
/// # Examples
765+
///
766+
/// ```
767+
/// use kurbo::{Axis, Rect};
768+
///
769+
/// let rect = Rect::new(1.0, 2.0, 4.0, 7.0).with_coords(
770+
/// Axis::Horizontal,
771+
/// 10.0,
772+
/// 3.0,
773+
/// );
774+
/// assert_eq!(rect, Rect::new(10.0, 2.0, 3.0, 7.0));
775+
/// ```
776+
#[inline]
777+
pub const fn with_coords(self, axis: Axis, v0: f64, v1: f64) -> Rect {
778+
match axis {
779+
Axis::Horizontal => Rect::new(v0, self.y0, v1, self.y1),
780+
Axis::Vertical => Rect::new(self.x0, v0, self.x1, v1),
781+
}
782+
}
670783
}
671784

672785
impl From<(Point, Point)> for Rect {

kurbo/src/size.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,25 @@ impl Size {
333333
Axis::Vertical => self.height = value,
334334
}
335335
}
336+
337+
/// Return a new `Size` with the member matching the given axis set to
338+
/// the given value.
339+
///
340+
/// # Examples
341+
///
342+
/// ```
343+
/// use kurbo::{Axis, Size};
344+
///
345+
/// let size = Size::new(2.0, 3.0).with_coord(Axis::Vertical, 5.0);
346+
/// assert_eq!(size, Size::new(2.0, 5.0));
347+
/// ```
348+
#[inline]
349+
pub const fn with_coord(self, axis: Axis, value: f64) -> Size {
350+
match axis {
351+
Axis::Horizontal => Size::new(value, self.height),
352+
Axis::Vertical => Size::new(self.width, value),
353+
}
354+
}
336355
}
337356

338357
impl fmt::Debug for Size {

kurbo/src/vec2.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,25 @@ impl Vec2 {
371371
Axis::Vertical => self.y = value,
372372
}
373373
}
374+
375+
/// Return a new `Vec2` with the member matching the given axis set to
376+
/// the given value.
377+
///
378+
/// # Examples
379+
///
380+
/// ```
381+
/// use kurbo::{Axis, Vec2};
382+
///
383+
/// let vec = Vec2::new(2.0, 3.0).with_coord(Axis::Horizontal, 5.0);
384+
/// assert_eq!(vec, Vec2::new(5.0, 3.0));
385+
/// ```
386+
#[inline]
387+
pub const fn with_coord(self, axis: Axis, value: f64) -> Vec2 {
388+
match axis {
389+
Axis::Horizontal => Vec2::new(value, self.y),
390+
Axis::Vertical => Vec2::new(self.x, value),
391+
}
392+
}
374393
}
375394

376395
impl From<(f64, f64)> for Vec2 {

0 commit comments

Comments
 (0)