vector_traits/lib.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2023, 2025 lacklustr@protonmail.com https://github.com/eadf
3
4// This file is part of vector-traits.
5
6//! # Vector-Traits Crate
7//!
8//! `vector-traits` is a Rust crate designed to provide a limited set of traits for abstracting over different vector
9//! implementations and scalar types, offering a unified interface for a basic set of vector operations. This crate facilitates
10//! seamless transitions between different vector libraries and scalar precisions (e.g., `f32` and `f64`) without
11//! requiring significant code modifications.
12//!
13//! ## Features
14//!
15//! - Abstract over two-dimensional and three-dimensional vectors with `GenericVector2` and `GenericVector3` traits.
16//! - Generic scalar trait `GenericScalar` for flexible scalar type handling.
17//! - Basic vector traits `HasXY` and `HasXYZ` for low-level, custom vector storage types, e.g., FFI types.
18//! - Seamless transition between different vector libraries like `cgmath`, `glam`, and `nalgebra`.
19//! - Ability to switch between different scalar types (`f32`, `f64`) effortlessly.
20//!
21//! ## Design Philosophy
22//!
23//! This library is designed to be **agnostic** to whether the underlying type represents a **point** or a **vector**.
24//! For example, you can compute the distance between two points (`v0.distance(v1)`) or the magnitude of a vector (`v0.magnitude()`)
25//! regardless of how the underlying library differentiates between points and vectors. This approach simplifies interoperability
26//! and allows you to focus on the geometric operations rather than the semantic distinctions.
27//!
28//! While some libraries make a deliberate effort to differentiate between points and vectors (e.g., `nalgebra` and `cgmath`), this crate
29//! intentionally treats them uniformly to provide a consistent and flexible interface. This means that operations like
30//! `distance`, `magnitude`, and `normalize` are available on any type that implements the relevant traits, whether it
31//! represents a point or a vector in the underlying library.
32//!
33//! ## Supported Vector Implementations
34//!
35//! Currently, the following vector types from `cgmath`, `glam`, and `nalgebra` libraries are supported:
36//!
37//! - `glam::Vec2`, `glam::Vec3`, `glam::Mat3`, `glam::Mat4`
38//! - `glam::Vec3A`, `glam::Mat3A` (uses newtype wrappers: `Vec2A` & `Mat4A` for symmetry)
39//! - `glam::DVec2`, `glam::DVec3`, `glam::DMat3`, `glam::DMat4`
40//! - `cgmath::Vector2`, `cgmath::Vector3`
41//! - `nalgebra::Vector2`, `nalgebra::Vector3`
42//!
43//! ## Usage
44//!
45//! Add `vector-traits` to your `Cargo.toml` dependencies along with the desired features:
46//!
47//! ```toml
48//! [dependencies]
49//! vector-traits = { version = "0.4.0", features = ["glam", "cgmath", "nalgebra"] } # only use what you need
50//! ```
51//!
52//! ## Example
53//!
54//! In this example we use the linestring crate, that builds upon these traits, to calculate the
55//! convex hull of a `Vec` of coordinates and an RDP simplified linestring. It does this without any
56//! type conversions, but instead uses the specified vector type throughout.
57//!
58//! ```rust,ignore
59//! use vector_traits::prelude::GenericVector2;
60//! use linestring::prelude::LineString2;
61//!
62//! let point_cloud: Vec<glam::Vec2> = vec![/* your glam::Vec2 data */];
63//! let convex_hull = point_cloud.convex_hull();
64//!
65//! let linestring: Vec<nalgebra::Vector2<f64>> = vec![/* your nalgebra::Vector2<f64> data */];
66//! let simplified_linestring = linestring.simplify_rdp(0.001);
67//! ```
68//!
69//! ## Contributing
70//!
71//! Contributions are welcome! Feel free to open an issue or submit a pull request.
72//!
73//! ## License
74//!
75//! Licensed under either of
76//!
77//! - Apache License, Version 2.0 ([LICENSE-APACHE](https://example.com/your-apache-license-link))
78//! - MIT license ([LICENSE-MIT](https://example.com/your-mit-license-link))
79//!
80//! at your option.
81
82#![deny(
83 rust_2018_compatibility,
84 rust_2018_idioms,
85 rust_2021_compatibility,
86 nonstandard_style,
87 unused,
88 future_incompatible,
89 non_camel_case_types,
90 unused_parens,
91 non_upper_case_globals,
92 unused_qualifications,
93 unused_results,
94 unused_imports,
95 unused_variables,
96 bare_trait_objects,
97 ellipsis_inclusive_range_patterns,
98 elided_lifetimes_in_paths
99)]
100#![warn(clippy::explicit_into_iter_loop)]
101
102#[doc(hidden)]
103#[cfg(feature = "cgmath")]
104pub mod cgmath_impl;
105
106#[doc(hidden)]
107#[cfg(feature = "glam")]
108pub mod glam_impl;
109
110#[doc(hidden)]
111#[cfg(feature = "nalgebra")]
112pub mod nalgebra_impl;
113
114mod aabb;
115mod affine;
116mod plane;
117mod scalar;
118#[allow(clippy::just_underscores_and_digits)]
119#[allow(dead_code)]
120#[cfg(test)]
121mod tests;
122mod trait_impl;
123mod vector2;
124mod vector3;
125
126mod vector_constants;
127
128pub use approx;
129#[cfg(feature = "cgmath")]
130pub use cgmath;
131#[cfg(feature = "glam")]
132pub use glam;
133#[cfg(feature = "nalgebra")]
134pub use nalgebra;
135pub use num_traits;
136
137pub mod prelude {
138
139 pub use crate::vector_constants::VectorConstants;
140
141 #[cfg(feature = "glam")]
142 pub mod glam_ext {
143 pub use crate::glam_impl::{
144 Aabb3, Aabb3A, DAabb3,
145 mat4a::Mat4A,
146 vec2a::{Vec2A, vec2a},
147 };
148 }
149
150 #[cfg(feature = "cgmath")]
151 pub mod cgmath_ext {
152 pub use crate::cgmath_impl::{Aabb2, Aabb3};
153 }
154
155 #[cfg(feature = "nalgebra")]
156 pub mod nalgebra_ext {
157 pub use crate::nalgebra_impl::{Aabb2, Aabb3};
158 }
159
160 pub use crate::{
161 aabb::{Aabb2, Aabb3},
162 affine::{Affine2D, Affine3D},
163 plane::Plane,
164 scalar::GenericScalar,
165 vector2::{Approx, GenericVector2, HasXY},
166 vector3::{GenericVector3, HasXYZ},
167 };
168}