kurbo/
lib.rs

1// Copyright 2018 the Kurbo Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! 2D geometry, with a focus on curves.
5//!
6//! The kurbo library contains data structures and algorithms for curves and
7//! vector paths. It was designed to serve the needs of 2D graphics applications,
8//! but it is intended to be general enough to be useful for other applications.
9//! It can be used as "vocabulary types" for representing curves and paths, and
10//! also contains a number of computational geometry methods.
11//!
12//! # Examples
13//!
14//! Basic UI-style geometry:
15//! ```
16//! use kurbo::{Insets, Point, Rect, Size, Vec2};
17//!
18//! let pt = Point::new(10.0, 10.0);
19//! let vector = Vec2::new(5.0, -5.0);
20//! let pt2 = pt + vector;
21//! assert_eq!(pt2, Point::new(15.0, 5.0));
22//!
23//! let rect = Rect::from_points(pt, pt2);
24//! assert_eq!(rect, Rect::from_origin_size((10.0, 5.0), (5.0, 5.0)));
25//!
26//! let insets = Insets::uniform(1.0);
27//! let inset_rect = rect - insets;
28//! assert_eq!(inset_rect.size(), Size::new(3.0, 3.0));
29//! ```
30//!
31//! Finding the closest position on a [`Shape`]'s perimeter to a [`Point`]:
32//!
33//! ```
34//! use kurbo::{Circle, ParamCurve, ParamCurveNearest, Point, Shape};
35//!
36//! const DESIRED_ACCURACY: f64 = 0.1;
37//!
38//! /// Given a shape and a point, returns the closest position on the shape's
39//! /// perimeter, or `None` if the shape is malformed.
40//! fn closest_perimeter_point(shape: impl Shape, pt: Point) -> Option<Point> {
41//!     let mut best: Option<(Point, f64)> = None;
42//!     for segment in shape.path_segments(DESIRED_ACCURACY) {
43//!         let nearest = segment.nearest(pt, DESIRED_ACCURACY);
44//!         if best.map(|(_, best_d)| nearest.distance_sq < best_d).unwrap_or(true) {
45//!             best = Some((segment.eval(nearest.t), nearest.distance_sq))
46//!         }
47//!     }
48//!     best.map(|(point, _)| point)
49//! }
50//!
51//! let circle = Circle::new((5.0, 5.0), 5.0);
52//! let hit_point = Point::new(5.0, -2.0);
53//! let expectation = Point::new(5.0, 0.0);
54//! let hit = closest_perimeter_point(circle, hit_point).unwrap();
55//! assert!(hit.distance(expectation) <= DESIRED_ACCURACY);
56//! ```
57//!
58//! # Feature Flags
59//!
60//! The following crate [feature flags](https://doc.rust-lang.org/cargo/reference/features.html#dependency-features) are available:
61//!
62//! - `std` (enabled by default): Get floating point functions from the standard library
63//!   (likely using your target's libc).
64//! - `libm`: Use floating point implementations from [libm][].
65//!   This is useful for `no_std` environments.
66//!   However, note that the `libm` crate is not as efficient as the standard library.
67//! - `mint`: Enable `From`/`Into` conversion of Kurbo and [mint][] types, enabling interoperability
68//!   with other graphics libraries.
69//! - `euclid`: Enable `From`/`Into` conversion of Kurbo and [euclid][] types.
70//!   Note that if you're using both Kurbo and euclid at the same time, you *must*
71//!   also enable one of euclid's `std` or `libm` features.
72//! - `serde`: Implement `serde::Deserialize` and `serde::Serialize` on various types.
73//! - `schemars`: Add best-effort support for using Kurbo types in JSON schemas using [schemars][].
74//!
75//! At least one of `std` and `libm` is required; `std` overrides `libm`.
76//! Note that Kurbo does require that an allocator is available (i.e. it uses [alloc]).
77
78// LINEBENDER LINT SET - lib.rs - v1
79// See https://linebender.org/wiki/canonical-lints/
80// These lints aren't included in Cargo.toml because they
81// shouldn't apply to examples and tests
82#![cfg_attr(not(test), warn(unused_crate_dependencies))]
83#![warn(clippy::print_stdout, clippy::print_stderr)]
84// END LINEBENDER LINT SET
85#![cfg_attr(docsrs, feature(doc_auto_cfg))]
86#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
87#![allow(
88    clippy::unreadable_literal,
89    clippy::many_single_char_names,
90    clippy::excessive_precision,
91    clippy::bool_to_int_with_if
92)]
93// The following lints are part of the Linebender standard set,
94// but resolving them has been deferred for now.
95// Feel free to send a PR that solves one or more of these.
96#![allow(
97    missing_debug_implementations,
98    elided_lifetimes_in_paths,
99    single_use_lifetimes,
100    trivial_numeric_casts,
101    unnameable_types,
102    clippy::use_self,
103    clippy::return_self_not_must_use,
104    clippy::cast_possible_truncation,
105    clippy::wildcard_imports,
106    clippy::shadow_unrelated,
107    clippy::missing_assert_message,
108    clippy::missing_errors_doc,
109    clippy::missing_panics_doc,
110    clippy::exhaustive_enums,
111    clippy::match_same_arms,
112    clippy::partial_pub_fields,
113    clippy::unseparated_literal_suffix,
114    clippy::duplicated_attributes,
115    clippy::allow_attributes,
116    clippy::allow_attributes_without_reason
117)]
118
119#[cfg(not(any(feature = "std", feature = "libm")))]
120compile_error!("kurbo requires either the `std` or `libm` feature");
121
122// Suppress the unused_crate_dependencies lint when both std and libm are specified.
123#[cfg(all(feature = "std", feature = "libm"))]
124use libm as _;
125
126extern crate alloc;
127
128mod affine;
129mod arc;
130mod axis;
131mod bezpath;
132mod circle;
133pub mod common;
134mod cubicbez;
135mod ellipse;
136mod fit;
137mod insets;
138mod line;
139mod mindist;
140mod moments;
141pub mod offset;
142mod param_curve;
143mod point;
144mod quadbez;
145mod quadspline;
146mod rect;
147mod rounded_rect;
148mod rounded_rect_radii;
149mod shape;
150pub mod simplify;
151mod size;
152mod stroke;
153mod svg;
154mod translate_scale;
155mod triangle;
156mod vec2;
157
158#[cfg(feature = "euclid")]
159mod interop_euclid;
160
161pub use crate::affine::Affine;
162pub use crate::arc::{Arc, ArcAppendIter};
163pub use crate::axis::Axis;
164pub use crate::bezpath::{
165    flatten, segments, BezPath, LineIntersection, MinDistance, PathEl, PathSeg, PathSegIter,
166    Segments,
167};
168pub use crate::circle::{Circle, CirclePathIter, CircleSegment};
169pub use crate::cubicbez::{cubics_to_quadratic_splines, CubicBez, CubicBezIter, CuspType};
170pub use crate::ellipse::Ellipse;
171pub use crate::fit::{
172    fit_to_bezpath, fit_to_bezpath_opt, fit_to_cubic, CurveFitSample, ParamCurveFit,
173};
174pub use crate::insets::Insets;
175pub use crate::line::{ConstPoint, Line, LinePathIter};
176pub use crate::moments::{Moments, ParamCurveMoments};
177pub use crate::param_curve::{
178    Nearest, ParamCurve, ParamCurveArclen, ParamCurveArea, ParamCurveCurvature, ParamCurveDeriv,
179    ParamCurveExtrema, ParamCurveNearest, DEFAULT_ACCURACY, MAX_EXTREMA,
180};
181pub use crate::point::Point;
182pub use crate::quadbez::{QuadBez, QuadBezIter};
183pub use crate::quadspline::QuadSpline;
184pub use crate::rect::{Rect, RectPathIter};
185pub use crate::rounded_rect::{RoundedRect, RoundedRectPathIter};
186pub use crate::rounded_rect_radii::RoundedRectRadii;
187pub use crate::shape::Shape;
188pub use crate::size::Size;
189pub use crate::stroke::{
190    dash, stroke, stroke_with, Cap, Dashes, Join, Stroke, StrokeCtx, StrokeOptLevel, StrokeOpts,
191};
192pub use crate::svg::{SvgArc, SvgParseError};
193pub use crate::translate_scale::TranslateScale;
194pub use crate::triangle::{Triangle, TrianglePathIter};
195pub use crate::vec2::Vec2;