Skip to main content

oxiphysics_geometry/
lib.rs

1// Copyright 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3
4//! Geometric shape types for collision detection and physics simulation.
5//!
6//! Provides primitives (sphere, box, capsule, cylinder, cone) and complex
7//! shapes (convex hull, triangle mesh, compound, height field) with support
8//! point queries, volume/inertia computation, and ray casting.
9#![warn(missing_docs)]
10#![allow(ambiguous_glob_reexports)]
11#![allow(dead_code)]
12
13mod error;
14pub use error::*;
15
16pub mod shape;
17pub use shape::{RayHit, Shape};
18
19pub mod sphere;
20pub use sphere::Sphere;
21
22pub mod box_shape;
23pub use box_shape::BoxShape;
24
25pub mod capsule;
26pub use capsule::Capsule;
27
28pub mod cylinder;
29pub use cylinder::Cylinder;
30
31pub mod cone;
32pub use cone::Cone;
33
34pub mod convex_hull;
35pub use convex_hull::*;
36
37pub mod triangle_mesh;
38pub use triangle_mesh::TriangleMesh;
39
40pub mod heightfield;
41pub use heightfield::HeightField;
42
43pub mod compound;
44pub use compound::Compound;
45
46pub mod torus;
47pub use torus::Torus;
48
49pub mod mesh_ops;
50pub use mesh_ops::TriMesh;
51
52pub mod quickhull;
53pub use quickhull::ConvexHull3DVec;
54
55pub mod swept;
56
57pub mod csg;
58
59pub mod parametric;
60
61pub mod mesh_repair;
62
63pub mod spatial_hash;
64
65pub mod voronoi;
66
67pub mod decimation;
68
69pub mod offset_surface;
70pub use offset_surface::*;
71
72pub mod point_cloud;
73pub use point_cloud::*;
74
75pub mod mesh_quality;
76
77pub mod remesh;
78
79pub mod boolean_ops;
80
81pub mod geodesic;
82
83pub mod subdivision;
84
85pub mod mesh_param;
86pub use mesh_param::{
87    LscmParameterization, ParamTriMesh, TutteParameterization, boundary_vertices, build_halfedge,
88    fill_holes, is_boundary_vertex, loop_subdivision, midpoint_subdivision,
89    remove_duplicate_vertices, texture_distortion, uv_overlap_check, uv_stretch, vertex_neighbors,
90};
91
92pub use voronoi::{
93    DelaunayTriangle, DelaunayTriangulation, LegacyVoronoiCell, Point2D, VoronoiCell,
94    VoronoiDiagram, VoronoiSite, bowyer_watson, circumcircle, delaunay_to_voronoi, in_circumcircle,
95    is_delaunay, lloyd_relaxation, nearest_site, power_diagram, voronoi_area,
96};
97
98#[cfg(test)]
99mod prop_tests {
100    use super::*;
101    use oxiphysics_core::math::Vec3;
102    use proptest::prelude::*;
103
104    fn positive_f64() -> impl Strategy<Value = f64> {
105        0.01_f64..50.0_f64
106    }
107
108    fn coord_f64() -> impl Strategy<Value = f64> {
109        -50.0_f64..50.0_f64
110    }
111
112    proptest! {
113        #[test]
114        fn prop_sphere_bbox_contains_center(radius in positive_f64()) {
115            let sphere = Sphere::new(radius);
116            let bb = sphere.bounding_box();
117            prop_assert!(
118                bb.contains_point(&Vec3::zeros()),
119                "sphere bbox does not contain center for radius={}", radius
120            );
121        }
122
123        #[test]
124        fn prop_box_support_within_extents(
125            hx in positive_f64(),
126            hy in positive_f64(),
127            hz in positive_f64(),
128            dx in coord_f64(),
129            dy in coord_f64(),
130            dz in coord_f64(),
131        ) {
132            let half_extents = Vec3::new(hx, hy, hz);
133            let b = BoxShape::new(half_extents);
134            let dir = Vec3::new(dx, dy, dz);
135            let sp = b.support_point(&dir);
136            let eps = 1e-9;
137            prop_assert!(sp.x.abs() <= hx + eps, "|sp.x|={} > hx={}", sp.x.abs(), hx);
138            prop_assert!(sp.y.abs() <= hy + eps, "|sp.y|={} > hy={}", sp.y.abs(), hy);
139            prop_assert!(sp.z.abs() <= hz + eps, "|sp.z|={} > hz={}", sp.z.abs(), hz);
140        }
141
142        #[test]
143        fn prop_sphere_volume_positive(radius in positive_f64()) {
144            let sphere = Sphere::new(radius);
145            prop_assert!(sphere.volume() > 0.0, "sphere volume not positive for radius={}", radius);
146        }
147
148        #[test]
149        fn prop_sphere_inertia_symmetric(
150            radius in positive_f64(),
151            mass in positive_f64(),
152        ) {
153            let sphere = Sphere::new(radius);
154            let it = sphere.inertia_tensor(mass);
155            for i in 0..3 {
156                for j in 0..3 {
157                    let diff = (it[(i, j)] - it[(j, i)]).abs();
158                    prop_assert!(diff < 1e-9, "inertia not symmetric at ({},{})={} vs ({},{})={}", i, j, it[(i,j)], j, i, it[(j,i)]);
159                }
160            }
161        }
162
163        #[test]
164        fn prop_sphere_raycast_hit_on_surface(
165            radius in positive_f64(),
166            // Ray from far away along X axis
167            offset in 1.01_f64..50.0_f64,
168        ) {
169            let sphere = Sphere::new(radius);
170            let origin = Vec3::new(-(offset + radius + 1.0), 0.0, 0.0);
171            let dir = Vec3::new(1.0, 0.0, 0.0);
172            if let Some(hit) = sphere.ray_cast(&origin, &dir, 1000.0) {
173                let dist_from_center = hit.point.norm();
174                prop_assert!(
175                    (dist_from_center - radius).abs() < 1e-6,
176                    "hit point not on sphere surface: dist={}, radius={}", dist_from_center, radius
177                );
178            }
179        }
180
181        #[test]
182        fn prop_capsule_volume_ge_sphere(
183            radius in positive_f64(),
184            half_height in positive_f64(),
185        ) {
186            let capsule = Capsule::new(radius, half_height);
187            let sphere = Sphere::new(radius);
188            prop_assert!(
189                capsule.volume() >= sphere.volume() - 1e-9,
190                "capsule volume {} < sphere volume {}", capsule.volume(), sphere.volume()
191            );
192        }
193    }
194}
195pub mod bspline;
196pub mod implicit;
197pub mod implicit_surfaces;
198pub mod level_set;
199pub mod mesh_processing;
200pub mod origami;
201pub mod sphere_packing;
202pub mod topology;
203
204pub mod architectural_geometry;
205
206pub mod fractal_geometry;
207
208pub mod computational_geometry;
209
210pub mod implicit_geometry;
211
212pub mod robot_geometry;
213
214pub mod medical_geometry;
215
216pub mod procedural_geometry;
217
218pub mod spline_geometry;
219
220pub mod discrete_geometry;
221
222pub mod terrain_processing;
223
224pub mod cell_complex;
225pub mod convex_decomposition;
226pub mod geodesic_geometry;
227pub mod medial_axis;
228pub mod mesh_boolean;
229pub mod mesh_repair_ext;
230pub mod mesh_simplification;
231pub mod nurbs_geometry;
232pub mod offset_geometry;
233pub mod signed_distance_field;
234pub mod topology_geometry;