1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use alga::general::Real;
use alga::linear::Similarity;
use na;
use num_traits::{Float, FloatConst};
use {BoundingBox, Object, PrimitiveParameters};
#[derive(Clone, Debug)]
pub struct Bender<S: Real> {
object: Box<Object<S>>,
width_scaler: S,
bbox: BoundingBox<S>,
}
impl<S: Real + From<f32> + Float + ::num_traits::FloatConst> Object<S> for Bender<S> {
fn approx_value(&self, p: &na::Point3<S>, slack: S) -> S {
let approx = self.bbox.distance(p);
if approx <= slack {
let mut obj_p = self.to_polar(p);
let r = obj_p.y;
let center_to_bbox = self.object.bbox().min.y - r;
if center_to_bbox > slack {
return center_to_bbox;
}
let x_scale = r / self.width_scaler;
let x_scaler = Float::min(x_scale, From::from(1f32));
obj_p.x *= self.width_scaler;
self.object.approx_value(&obj_p, slack / x_scaler) * x_scaler
} else {
approx
}
}
fn bbox(&self) -> &BoundingBox<S> {
&self.bbox
}
fn set_parameters(&mut self, p: &PrimitiveParameters<S>) {
self.object.set_parameters(p);
}
fn normal(&self, p: &na::Point3<S>) -> na::Vector3<S> {
let polar_p = self.to_polar(p);
let mut obj_p = polar_p;
obj_p.x *= self.width_scaler;
self.bend_normal(self.object.normal(&obj_p), polar_p)
}
}
impl<S: Real + Float + FloatConst + From<f32>> Bender<S> {
pub fn new(o: Box<Object<S>>, w: S) -> Box<Bender<S>> {
let bbox = BoundingBox::new(
&na::Point3::new(-o.bbox().max.y, -o.bbox().max.y, o.bbox().min.z),
&na::Point3::new(o.bbox().max.y, o.bbox().max.y, o.bbox().max.z),
);
let _2pi: S = S::PI() * From::from(2.);
Box::new(Bender {
object: o,
width_scaler: w / _2pi,
bbox: bbox,
})
}
fn to_polar(&self, p: &na::Point3<S>) -> na::Point3<S> {
let phi = Float::atan2(p.x, -p.y);
let r = Float::hypot(p.x, p.y);
na::Point3::new(phi, r, p.z)
}
fn tilt_normal(&self, mut normal: na::Vector3<S>, polar_p: na::Point3<S>) -> na::Vector3<S> {
let r = polar_p.y;
let _2pi: S = S::PI() * From::from(2.);
let circumference = _2pi * r;
let width_for_one_full_rotation = self.width_scaler * _2pi;
let scale_along_x = circumference / width_for_one_full_rotation;
normal.x /= scale_along_x;
normal.normalize()
}
fn bend_normal(&self, v: na::Vector3<S>, polar_p: na::Point3<S>) -> na::Vector3<S> {
let v = self.tilt_normal(v, polar_p);
let phi = polar_p.x + S::PI();
let v2 = ::na::Vector2::new(v.x, v.y);
let trans = ::na::Rotation2::new(phi);
let rv2 = trans.rotate_vector(&v2);
na::Vector3::new(rv2.x, rv2.y, v.z)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn empty() {
assert!(true);
}
}