Expand description
§use-geometry
Small Euclidean 2D geometry primitives for direct, predictable Rust code.
Validated constructors, tolerance-aware helpers, and composable value types without a full geometry engine.
Surface · When to use it · Installation · Examples · Validation · Scope
use-geometry provides small, composable geometry building blocks rather than a large geometry engine. The crate keeps the model explicit: direct structs, standalone helpers, validated constructors for external input, and tolerance-aware APIs only where ambiguity needs to be made explicit.
Foundation typesPoint2, Vector2, and measurement helpers for direct coordinate math.
|
Shapes and boundsLine2, Segment2, Circle, Triangle, and Aabb2.
|
Explicit validation Use try_new and tolerance-aware helpers when inputs come from users, files, or networks.
|
§What this crate provides
| Area | Root exports | Best fit |
|---|---|---|
| Coordinates and vectors | Point2, Vector2 | Direct 2D value math |
| Distance and midpoint | distance_2d, distance_squared_2d, midpoint_2d | Common point-to-point calculations |
| Orientation | Orientation2, orientation_2d, try_orientation_2d, tolerance-aware variants | Winding and collinearity checks |
| Lines and segments | Line2, Segment2 | Directed 2D relationships and interpolation |
| Shapes and bounds | Circle, Triangle, Aabb2, aabb_from_points | Shape metrics, containment, and bounds checks |
| If you need to… | Start here |
|---|---|
| Validate coordinates and shapes from external input | try_new constructors |
| Work with trusted values in hot paths | Infallible constructors like Point2::new(...) |
| Build simple containment or broad-phase checks | Aabb2 |
| Choose exact vs approximate geometric tests explicitly | Tolerance-aware helpers |
§When to use it directly
Choose use-geometry directly when geometry is the only math surface your application needs, or when you want to avoid pulling a broader facade into the dependency graph.
| Scenario | Use use-geometry directly? | Why |
|---|---|---|
| You only need 2D primitives and measurements | Yes | The crate stays narrow and explicit |
| You want validated construction at the boundary of your app | Yes | try_new and tolerance helpers make failures explicit |
| You also need checked combinatorics | Usually no | use-math may be the better integration point |
| You need a broad geometry engine with intersections and polygons | No | This crate intentionally stops short of that scope |
§Installation
[dependencies]
use-geometry = "0.0.1"§Quick examples
§Validated construction from external input
use use_geometry::{
Aabb2, Circle, Orientation2, Point2, Segment2, Triangle, midpoint_2d, try_orientation_2d,
};
let a = Point2::try_new(0.0, 0.0)?;
let b = Point2::try_new(4.0, 0.0)?;
let c = Point2::try_new(0.0, 3.0)?;
let segment = Segment2::try_new(a, b)?;
let triangle = Triangle::try_new(a, b, c)?;
let circle = Circle::try_new(a, 3.0)?;
let bounds = Aabb2::from_points(a, c);
assert_eq!(segment.midpoint(), midpoint_2d(a, b));
assert_eq!(triangle.area(), 6.0);
assert_eq!(triangle.perimeter(), 12.0);
assert_eq!(try_orientation_2d(a, b, c)?, Orientation2::CounterClockwise);
assert_eq!(circle.center(), a);
assert_eq!(circle.radius(), 3.0);
assert!(bounds.contains_point(Point2::new(0.0, 1.5)));§Bounds and tolerance-aware orientation
use use_geometry::{Aabb2, Orientation2, Point2, orientation_2d_with_tolerance};
let bounds = Aabb2::from_points(Point2::new(4.0, 1.0), Point2::new(1.0, 3.0));
assert_eq!(bounds.min(), Point2::new(1.0, 1.0));
assert_eq!(bounds.max(), Point2::new(4.0, 3.0));
assert_eq!(bounds.center(), Point2::new(2.5, 2.0));
assert!(bounds.contains_point(Point2::new(2.0, 2.0)));
assert_eq!(
orientation_2d_with_tolerance(
Point2::new(0.0, 0.0),
Point2::new(1.0, 1.0),
Point2::new(2.0, 2.0 + 1.0e-12),
1.0e-11,
)?,
Orientation2::Collinear,
);§Shape metrics stay direct
use use_geometry::{Orientation2, Point2, Triangle, triangle_area, triangle_twice_signed_area};
let a = Point2::try_new(0.0, 0.0)?;
let b = Point2::try_new(4.0, 0.0)?;
let c = Point2::try_new(0.0, 3.0)?;
let triangle = Triangle::try_new(a, b, c)?;
assert_eq!(triangle.orientation(), Orientation2::CounterClockwise);
assert_eq!(triangle.twice_signed_area(), triangle_twice_signed_area(a, b, c));
assert_eq!(triangle.area(), triangle_area(a, b, c));
assert_eq!(triangle.sides(), [4.0, 5.0, 3.0]);
assert_eq!(triangle.perimeter(), 12.0);
assert_eq!(triangle.centroid(), Point2::new(4.0 / 3.0, 1.0));
assert!(!triangle.is_degenerate());§Degeneracy stays explicit
[!IMPORTANT] Exact degeneracy and tolerance-based degeneracy are different checks. In
use-geometry, callers should choose deliberately based on coordinate scale, input quality, and whether they care about mathematical collapse or practical numeric collapse.
Degeneracy occurs when a geometric value collapses into a lower-dimensional or invalid form. For triangles, exact degeneracy means the vertices are collinear and the signed twice-area is exactly zero.
f64::EPSILON is usually not a useful geometry tolerance. It is tied to floating-point precision around 1.0, not the coordinate scale of a triangle. Practical degeneracy checks should use a caller-provided tolerance chosen for the coordinate scale, input source, and expected numeric noise.
use use_geometry::{Point2, Triangle};
let triangle = Triangle::try_new(
Point2::try_new(0.0, 0.0)?,
Point2::try_new(4.0, 0.0)?,
Point2::try_new(8.0, 1.0e-13)?,
)?;
assert!(!triangle.is_degenerate());
assert!(triangle.is_degenerate_with_tolerance(1.0e-12)?);§Validation model
Use try_new when values may come from user input, files, network payloads, or other untrusted sources. Use infallible constructors like Point2::new(...), Vector2::new(...), Triangle::new(...), or Aabb2::from_points(...) when values are already trusted and you want direct assembly.
[!IMPORTANT] Tolerance-aware helpers reject negative and non-finite tolerances explicitly. This crate does not hide geometric ambiguity behind a global epsilon policy.
§Scope
- Small APIs are preferred over broad trait-heavy abstractions.
- Primitives are intended to compose cleanly with each other and with plain
f64values. - Built-in approximate equality policies and global epsilon choices are intentionally out of scope.
- Polygon, intersection, and spatial indexing APIs are intentionally deferred.
- Plane-oriented APIs are deferred until a later 3D geometry layer.
§Status
use-geometry is a concrete pre-1.0 crate in the RustUse docs surface. The API remains intentionally small, and the RustUse-hosted generated rustdocs stay canonical while external crates.io and docs.rs pages remain staged.
Small Euclidean 2D geometry primitives for RustUse.
Re-exports§
pub use aabb::Aabb2;pub use aabb::aabb_from_points;pub use circle::Circle;pub use distance::distance_2d;pub use distance::distance_squared_2d;pub use distance::midpoint_2d;pub use error::GeometryError;pub use line::Line2;pub use orientation::Orientation2;pub use orientation::orientation_2d;pub use orientation::orientation_2d_with_tolerance;pub use orientation::try_orientation_2d;pub use orientation::try_orientation_2d_with_tolerance;pub use point::Point2;pub use segment::Segment2;pub use triangle::Triangle;pub use triangle::triangle_area;pub use triangle::triangle_twice_area;pub use triangle::triangle_twice_signed_area;pub use vector::Vector2;