[](https://crates.io/crates/sepax2d)
[](./LICENSE)
# sepax2d
A safe Rust crate for finding and resolving collisions of convex shapes using the Separating Axis Theorem (SAT) in two dimensions.
### Usage
Add the following to the `[dependencies]` section of your `Cargo.toml`:
```toml
sepax2d = "0.3"
```
Import the types of shapes you'd like to use and create some new shapes:
```rust
use sepax2d::prelude::*;
let rectangle = AABB::new(top_left, width, height);
let circle = Circle::new(center, radius);
let capsule = Capsule::new(center, arm, radius);
//The vertices of a polygon are position vectors
//relative to the shape's position, i.e. if position
//is (1, 2), then the absolute location of the
//first vertex is (1, 0).
let triangle = Polygon::from_vertices
(
position,
vec![(0.0, -2.0), (-1.0, 2.0), (1.0, 2.0)]
);
```
Use the `sat_overlap(&left, &right)` method to get a `bool` indicating whether or not the two given shapes overlap.
Any struct implementing the `Shape` trait can be used.
```rust
assert!(sat_overlap(&circle, &capsule));
assert!(sat_overlap(&triangle, &rectangle));
```
Use the `sat_collision(&left, &right)` method to get a `(f32, f32)` which represents the shift needed to add to `right`'s
position in order to resolve the overlap of the two shapes.
```rust
let resolution = sat_overlap(&circle, &triangle);
let position = triangle.position();
triangle.set_position((position.0 + resolution.0, position.1 + resolution.1));
assert!(!sat_overlap(&circle, &triangle));
```
Use the `contains_point(&shape, point)` method to get a `bool` indicating whether or not the specified point
is inside the given shape.
```rust
let rectangle = AABB::new((0.0, 0.0), 5.0, 2.0);
assert!(contains_point(&rect, (1.0, 1.0)));
assert!(!contains_point(&rect, (10.0, -1.0)));
```
`Polygon`, `Circle`, `Capsule`, and `Parallelogram` shapes implement the `Rotate` trait, which allows you to rotate them
around their `position`.
```rust
# use sepax2d::prelude::*;
# let position = (-1.0, -1.0);
let mut triangle = Polygon::from_vertices
(
position,
vec![(-1.0, 0.0), (0.0, 2.0), (1.0, 0.0)]
);
triangle.rotate(std::f32::consts::FRAC_PI_2)
//New vertices: [(0.0, -1.0), (-2.0, 0.0), (0.0, 1.0)]
```
You can use the `intersects_line`, `intersects_ray`, and `intersects_segment` methods to
check whether a shape intersects with the corresponding type of line.
```rust
# use sepax2d::prelude::*;
let triangle = Polygon::from_vertices((0.0, vec![(0.0, 0.0), (1.0, 1.0), (-1.0, 1.0)]));
assert!(intersects_segment(&triangle, (2.0, 0.5), (-2.0, 0.5)));
```
### Considerations
The Separating Axis Theorem only holds for convex shapes. If a concave shape is passed in, it is possible
for overlap to be missed and false overlap to be detected.
Convexity is not a problem for `Circle`, `AABB`, `Parallelogram`, or `Capsule` as those are convex by definition. For
polygons, it is possible to define a concave shape. Polygon convexity can be tested using the
`polygon.is_convex()` method. Alternatively, the `Polygon::convex_from_vertices(position, vertices)`
constructor returns an `Option(Polygon)`, which is `None` if you try to make a concave polygon.
### Features
Enable the `serde` feature for (De)Serialization of supported shapes!
### Examples
The repository includes two example applications built with [ggez](https://crates.io/crates/ggez)
which show off the overlap and collision functionality. They can be run from the repo via:
```sh
cargo run --example overlap
cargo run --example collision
```
### Contribution
Please feel free to suggest additional features, bug fixes, or optimizations. Thanks!