#![warn(missing_docs)]
extern crate alga;
#[cfg(test)]
#[macro_use]
extern crate approx;
extern crate bbox;
extern crate nalgebra as na;
extern crate num_traits;
extern crate stl_io;
use alga::general::RealField;
pub use bbox::BoundingBox;
use num_traits::Float;
use std::fmt::Debug;
mod transformer;
pub use self::transformer::AffineTransformer;
mod twister;
pub use self::twister::Twister;
mod bender;
pub use self::bender::Bender;
mod boolean;
pub use self::boolean::{Intersection, Union};
mod sphere;
pub use self::sphere::Sphere;
mod cylinder;
pub use self::cylinder::{Cone, Cylinder};
mod plane;
pub use self::plane::{NormalPlane, PlaneNegX, PlaneNegY, PlaneNegZ, PlaneX, PlaneY, PlaneZ};
mod mesh;
pub use self::mesh::Mesh;
#[cfg(test)]
mod test;
pub struct PrimitiveParameters<S> {
pub fade_range: S,
pub r_multiplier: S,
}
const ALWAYS_PRECISE: f32 = 1.;
const EPSILON: f32 = 1e-10;
fn normal_from_object<S: Debug + RealField + Float + From<f32>>(
f: &dyn Object<S>,
p: &na::Point3<S>,
) -> na::Vector3<S> {
let null: S = From::from(0.0);
let e: S = From::from(EPSILON);
let a: S = From::from(ALWAYS_PRECISE);
let epsilon_x = na::Vector3::<S>::new(e, null, null);
let epsilon_y = na::Vector3::<S>::new(null, e, null);
let epsilon_z = na::Vector3::<S>::new(null, null, e);
let center = f.approx_value(p, a);
let dx = f.approx_value(&(p + epsilon_x), a) - center;
let dy = f.approx_value(&(p + epsilon_y), a) - center;
let dz = f.approx_value(&(p + epsilon_z), a) - center;
na::Vector3::<S>::new(dx, dy, dz).normalize()
}
pub trait Object<S: RealField + Float + From<f32>>: ObjectClone<S> + Debug + Sync + Send {
fn bbox(&self) -> &BoundingBox<S>;
fn set_bbox(&mut self, _: &BoundingBox<S>) {
unimplemented!();
}
fn set_parameters(&mut self, _: &PrimitiveParameters<S>) {}
fn approx_value(&self, _: &na::Point3<S>, _: S) -> S {
unimplemented!();
}
fn normal(&self, _: &na::Point3<S>) -> na::Vector3<S> {
unimplemented!();
}
fn translate(&self, v: &na::Vector3<S>) -> Box<dyn Object<S>> {
AffineTransformer::new_translate(self.clone_box(), v)
}
fn rotate(&self, r: &na::Vector3<S>) -> Box<dyn Object<S>> {
AffineTransformer::new_rotate(self.clone_box(), r)
}
fn scale(&self, s: &na::Vector3<S>) -> Box<dyn Object<S>> {
AffineTransformer::new_scale(self.clone_box(), s)
}
}
pub trait ObjectClone<S> {
fn clone_box(&self) -> Box<dyn Object<S>>;
}
impl<S: RealField + Float + From<f32>, T> ObjectClone<S> for T
where
T: 'static + Object<S> + Clone,
{
fn clone_box(&self) -> Box<dyn Object<S>> {
Box::new(self.clone())
}
}
impl<S> Clone for Box<dyn Object<S>> {
fn clone(&self) -> Box<dyn Object<S>> {
self.clone_box()
}
}
impl<S> PartialEq for Box<dyn Object<S>> {
fn eq(&self, _: &Box<dyn Object<S>>) -> bool {
false
}
}
impl<S> PartialOrd for Box<dyn Object<S>> {
fn partial_cmp(&self, _: &Box<dyn Object<S>>) -> Option<::std::cmp::Ordering> {
None
}
}