anl/
implicit_gradient.rs

1/// The documentation is taken from original [C++ library by Joshua Tippetts](http://accidentalnoise.sourceforge.net/docs.html).
2
3use super::implicit_base::ImplicitModuleBase;
4use super::ImplicitModule;
5
6/// Gradient has the effect of allowing you to specify a line segment in N-dimensional space by setting endpoints. The endpoints are set via [`set_gradient()`](struct.ImplicitGradient.html) and the segment extends from P1=(x1,y1,z1,w1,u1,v1) to P2=(x2,y2,z2,w2,u2,v2). Only the coordinates pertinent to the dimensionality of the function being called are used, however. A gradient field is aligned with this segment such that any input coordinate is projected onto the line formed by the segment, and a value is assigned based on where on the line the projected point lies. If it lies on or beyond P1, the value is assigned as 0. If it lies on or beyond P2 the value is assigned as 1. Anything in between is assigned as a linear interpolation between 0 and 1. (This behavior may be changing; I may remove the clamping aspect, and allow values to go infinitely depending on distance from the "origin" point. Some useful things could be done in this fashion.) The result is a smooth gradient field oriented along an axis.
7pub struct ImplicitGradient {
8    base: ImplicitModuleBase,
9    gx1: f64,
10    gy1: f64,
11    gz1: f64,
12    gw1: f64,
13    gu1: f64,
14    gv1: f64,
15    gx2: f64,
16    gy2: f64,
17    gz2: f64,
18    gw2: f64,
19    gu2: f64,
20    gv2: f64,
21    x: f64,
22    y: f64,
23    z: f64,
24    w: f64,
25    u: f64,
26    v: f64,
27    vlen: f64,
28}
29
30impl Default for ImplicitGradient {
31    fn default() -> Self {
32        ImplicitGradient {
33            gx1: 0.0,
34            gy1: 0.0,
35            gz1: 0.0,
36            gw1: 0.0,
37            gu1: 0.0,
38            gv1: 0.0,
39            gx2: 0.0,
40            gy2: 0.0,
41            gz2: 0.0,
42            gw2: 0.0,
43            gu2: 0.0,
44            gv2: 0.0,
45            x: 0.0,
46            y: 0.0,
47            z: 0.0,
48            w: 0.0,
49            u: 0.0,
50            v: 0.0,
51            vlen: 0.0,
52            base: Default::default(),
53        }
54    }
55}
56
57impl ImplicitGradient {
58    pub fn new() -> ImplicitGradient {
59        let mut g: ImplicitGradient = Default::default();
60        g.set_gradient(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
61        g
62    }
63
64    pub fn set_gradient(&mut self, x1: f64, x2: f64, y1: f64, y2: f64, z1: f64, z2: f64, w1: f64, w2: f64, u1: f64, u2: f64, v1: f64, v2: f64) {
65        self.gx1 = x1;
66        self.gx2 = x2;
67        self.gy1 = y1;
68        self.gy2 = y2;
69        self.gz1 = z1;
70        self.gz2 = z2;
71        self.gw1 = w1;
72        self.gw2 = w2;
73        self.gu1 = u1;
74        self.gu2 = u2;
75        self.gv1 = v1;
76        self.gv2 = v2;
77
78        self.x = x2 - x1;
79        self.y = y2 - y1;
80        self.z = z2 - z1;
81        self.w = w2 - w1;
82        self.u = u2 - u1;
83        self.v = v2 - v1;
84
85        self.vlen = self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w + self.u * self.u + self.v * self.v;
86    }
87}
88
89impl ImplicitModule for ImplicitGradient {
90    fn set_seed(&mut self, _: u32) {}
91
92    fn get_2d(&mut self, x: f64, y: f64) -> f64 {
93        // Subtract from (1) and take dotprod
94        let dx = x - self.gx1;
95        let dy = y - self.gy1;
96        let mut dp = dx * self.x + dy * self.y;
97        dp /= self.vlen;
98        // dp=clamp(dp/self.vlen,0.0,1.0);
99        // return lerp(dp,1.0,-1.0);
100        dp
101    }
102    fn get_3d(&mut self, x: f64, y: f64, z: f64) -> f64 {
103        let dx = x - self.gx1;
104        let dy = y - self.gy1;
105        let dz = z - self.gz1;
106        let mut dp = dx * self.x + dy * self.y + dz * self.z;
107        dp /= self.vlen;
108        // dp=clamp(dp/self.vlen,0.0,1.0);
109        // return lerp(dp,1.0,-1.0);
110        dp
111    }
112    fn get_4d(&mut self, x: f64, y: f64, z: f64, w: f64) -> f64 {
113        let dx = x - self.gx1;
114        let dy = y - self.gy1;
115        let dz = z - self.gz1;
116        let dw = w - self.gw1;
117        let mut dp = dx * self.x + dy * self.y + dz * self.z + dw * self.w;
118        dp /= self.vlen;
119        // dp=clamp(dp/self.vlen,0.0,1.0);
120        // return lerp(dp,1.0,-1.0);
121        dp
122    }
123    fn get_6d(&mut self, x: f64, y: f64, z: f64, w: f64, u: f64, v: f64) -> f64 {
124        let dx = x - self.gx1;
125        let dy = y - self.gy1;
126        let dz = z - self.gz1;
127        let dw = w - self.gw1;
128        let du = u - self.gu1;
129        let dv = v - self.gv1;
130        let mut dp = dx * self.x + dy * self.y + dz * self.z + dw * self.w + du * self.u + dv * self.v;
131        dp /= self.vlen;
132        // dp=clamp(dp/self.vlen,0.0,1.0);
133        // return lerp(clamp(dp,0.0,1.0),1.0,-1.0);
134        dp
135    }
136
137    fn spacing(&self) -> f64 {
138        self.base.spacing
139    }
140
141    fn set_deriv_spacing(&mut self, s: f64) {
142        self.base.spacing = s;
143    }
144}