Skip to main content

Crate use_geometry

Crate use_geometry 

Source
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.

Rust 1.95.0+ Edition 2024 2D Euclidean API Validated constructors License MIT or Apache-2.0

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 types
Point2, Vector2, and measurement helpers for direct coordinate math.
Shapes and bounds
Line2, 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

AreaRoot exportsBest fit
Coordinates and vectorsPoint2, Vector2Direct 2D value math
Distance and midpointdistance_2d, distance_squared_2d, midpoint_2dCommon point-to-point calculations
OrientationOrientation2, orientation_2d, try_orientation_2d, tolerance-aware variantsWinding and collinearity checks
Lines and segmentsLine2, Segment2Directed 2D relationships and interpolation
Shapes and boundsCircle, Triangle, Aabb2, aabb_from_pointsShape metrics, containment, and bounds checks
If you need to…Start here
Validate coordinates and shapes from external inputtry_new constructors
Work with trusted values in hot pathsInfallible constructors like Point2::new(...)
Build simple containment or broad-phase checksAabb2
Choose exact vs approximate geometric tests explicitlyTolerance-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.

ScenarioUse use-geometry directly?Why
You only need 2D primitives and measurementsYesThe crate stays narrow and explicit
You want validated construction at the boundary of your appYestry_new and tolerance helpers make failures explicit
You also need checked combinatoricsUsually nouse-math may be the better integration point
You need a broad geometry engine with intersections and polygonsNoThis 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 f64 values.
  • 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;

Modules§

aabb
circle
distance
Distance and interpolation helpers for 2D points.
error
line
orientation
point
prelude
segment
triangle
vector