create structs lib, mimics tuple lib, but implements Tuple.
This allows for operator overloading. It will make it significantly easier to write code for Tuple objects.
This commit is contained in:
297
structs/src/lib.rs
Normal file
297
structs/src/lib.rs
Normal file
@@ -0,0 +1,297 @@
|
||||
#[macro_use]
|
||||
extern crate approx;
|
||||
|
||||
use std::ops;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Tuple {
|
||||
x: f32,
|
||||
y: f32,
|
||||
z: f32,
|
||||
w: f32,
|
||||
}
|
||||
|
||||
impl Tuple {
|
||||
fn new(x: f32, y: f32, z: f32, w: f32) -> Tuple {
|
||||
Tuple {
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
w,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn point(x: f32, y: f32, z: f32) -> Tuple {
|
||||
Tuple {
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
w: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn vector(x: f32, y: f32, z: f32) -> Tuple {
|
||||
Tuple {
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
w: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tuple {
|
||||
fn x(&self) -> f32 {
|
||||
self.x
|
||||
}
|
||||
|
||||
fn y(&self) -> f32 {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn z(&self) -> f32 {
|
||||
self.z
|
||||
}
|
||||
|
||||
fn is_point(&self) -> bool {
|
||||
self.w == 1.0
|
||||
}
|
||||
|
||||
fn is_vector(&self) -> bool {
|
||||
self.w == 0.0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl PartialEq for Tuple {
|
||||
fn eq(&self, _rhs: &Self) -> bool {
|
||||
relative_eq!(self.x, _rhs.x)
|
||||
&& relative_eq!(self.y, _rhs.y)
|
||||
&& relative_eq!(self.z, _rhs.z)
|
||||
&& relative_eq!(self.w, _rhs.w)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<Tuple> for Tuple {
|
||||
type Output = Tuple;
|
||||
|
||||
fn add(self, _rhs: Tuple) -> Tuple {
|
||||
Tuple::new(
|
||||
self.x + _rhs.x,
|
||||
self.y + _rhs.y,
|
||||
self.z + _rhs.z,
|
||||
self.w + _rhs.w,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub<Tuple> for Tuple {
|
||||
type Output = Tuple;
|
||||
|
||||
fn sub(self, _rhs: Tuple) -> Tuple {
|
||||
Tuple::new(
|
||||
self.x - _rhs.x,
|
||||
self.y - _rhs.y,
|
||||
self.z - _rhs.z,
|
||||
self.w - _rhs.w,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Neg for Tuple {
|
||||
type Output = Tuple;
|
||||
|
||||
fn neg(self) -> Tuple {
|
||||
Tuple::new(
|
||||
-self.x,
|
||||
-self.y,
|
||||
-self.z,
|
||||
-self.w,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Mul<f32> for Tuple {
|
||||
type Output = Tuple;
|
||||
|
||||
fn mul(self, _rhs: f32) -> Tuple {
|
||||
Tuple::new(
|
||||
self.x * _rhs,
|
||||
self.y * _rhs,
|
||||
self.z * _rhs,
|
||||
self.w * _rhs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Mul<Tuple> for f32 {
|
||||
type Output = Tuple;
|
||||
|
||||
fn mul(self, _rhs: Tuple) -> Tuple {
|
||||
Tuple::new(
|
||||
_rhs.x * self,
|
||||
_rhs.y * self,
|
||||
_rhs.z * self,
|
||||
_rhs.w * self,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Div<f32> for Tuple {
|
||||
type Output = Tuple;
|
||||
|
||||
fn div(self, _rhs: f32) -> Tuple {
|
||||
Tuple::new(
|
||||
self.x / _rhs,
|
||||
self.y / _rhs,
|
||||
self.z / _rhs,
|
||||
self.w / _rhs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn get_point() {
|
||||
let tuple = Tuple::new(4.3, -4.2, 3.1, 1.0);
|
||||
|
||||
assert_relative_eq!( 4.3, tuple.x);
|
||||
assert_relative_eq!(-4.2, tuple.y());
|
||||
assert_relative_eq!( 3.1, tuple.z());
|
||||
assert_eq!(true, tuple.is_point());
|
||||
assert_eq!(false, tuple.is_vector());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_point() {
|
||||
let tuple = Tuple::point(4.3, -4.2, 3.1);
|
||||
assert_eq!(true, tuple.is_point());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_vector() {
|
||||
let tuple = Tuple::new(4.3, -4.2, 3.1, 0.0);
|
||||
|
||||
assert_relative_eq!( 4.3, tuple.x());
|
||||
assert_relative_eq!(-4.2, tuple.y());
|
||||
assert_relative_eq!( 3.1, tuple.z());
|
||||
assert_eq!(false, tuple.is_point());
|
||||
assert_eq!(true, tuple.is_vector());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_vector() {
|
||||
let vector = Tuple::vector(4.0, -4.0, 3.0);
|
||||
assert_eq!(true, vector.is_vector());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuples_equal() {
|
||||
let lhs = Tuple::point(1.0, 2.0, 3.0);
|
||||
let rhs = Tuple::point(1.0, 2.0, 3.0);
|
||||
assert_eq!(lhs, rhs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuples_relative_equal() {
|
||||
let lhs = Tuple::point(1.0000001, 2.0, 3.0);
|
||||
let rhs = Tuple::point(1.0, 2.0, 3.0);
|
||||
assert_eq!(lhs, rhs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuples_not_equal() {
|
||||
let lhs = Tuple::point(1.0, 2.0, 3.0);
|
||||
let rhs = Tuple::vector(1.0, 2.0, 3.0);
|
||||
assert_ne!(lhs, rhs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_two_tuples() {
|
||||
let a1 = Tuple::point(3.0, -2.0, 5.0);
|
||||
let a2 = Tuple::vector(-2.0, 3.0, 1.0);
|
||||
|
||||
let result = Tuple::point(1.0, 1.0, 6.0);
|
||||
assert_eq!(result, a1 + a2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtract_two_points() {
|
||||
let a1 = Tuple::point(3.0, 2.0, 1.0);
|
||||
let a2 = Tuple::point(5.0, 6.0, 7.0);
|
||||
|
||||
let result = Tuple::vector(-2.0, -4.0, -6.0);
|
||||
assert_eq!(result, a1 - a2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subract_vector_from_point() {
|
||||
let a1 = Tuple::point(3.0, 2.0, 1.0);
|
||||
let a2 = Tuple::vector(5.0, 6.0, 7.0);
|
||||
|
||||
let result = Tuple::point(-2.0, -4.0, -6.0);
|
||||
assert_eq!(result, a1 - a2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subract_vector_from_vector() {
|
||||
let a1 = Tuple::vector(3.0, 2.0, 1.0);
|
||||
let a2 = Tuple::vector(5.0, 6.0, 7.0);
|
||||
|
||||
let result = Tuple::vector(-2.0, -4.0, -6.0);
|
||||
assert_eq!(result, a1 - a2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtract_vector_from_zero_vector() {
|
||||
let a1 = Tuple::vector(0.0, 0.0, 0.0);
|
||||
let a2 = Tuple::vector(5.0, 6.0, 7.0);
|
||||
|
||||
let result = Tuple::vector(-5.0, -6.0, -7.0);
|
||||
assert_eq!(result, a1 - a2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negate_tuple() {
|
||||
let a = Tuple::new(1.0, -2.0, 3.0, -4.0);
|
||||
let result = Tuple::new(-1.0, 2.0, -3.0, 4.0);
|
||||
|
||||
assert_eq!(result, -a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiply_tuple_by_scalar() {
|
||||
let a = Tuple::new(1.0, -2.0, 3.0, -4.0);
|
||||
let result = Tuple::new(3.5, -7.0, 10.5, -14.0);
|
||||
|
||||
assert_eq!(result, a * 3.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiply_scalar_by_tuple() {
|
||||
let a = Tuple::new(1.0, -2.0, 3.0, -4.0);
|
||||
let result = Tuple::new(3.5, -7.0, 10.5, -14.0);
|
||||
|
||||
assert_eq!(result, 3.5 * a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiply_tuple_by_fraction() {
|
||||
let a = Tuple::new(1.0, -2.0, 3.0, -4.0);
|
||||
let result = Tuple::new(0.5, -1.0, 1.5, -2.0);
|
||||
|
||||
assert_eq!(result, a * 0.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn divide_tuple() {
|
||||
let a = Tuple::new(1.0, -2.0, 3.0, -4.0);
|
||||
let result = Tuple::new(0.5, -1.0, 1.5, -2.0);
|
||||
|
||||
assert_eq!(result, a / 2.0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user