76 |
struct FilletSpan { |
struct FilletSpan { |
77 |
CircleFillet a, b; |
CircleFillet a, b; |
78 |
float aa, ab; |
float aa, ab; |
79 |
Vec ctr; |
float da, db; |
80 |
|
float za, zb; |
81 |
|
ZVec ctr; |
82 |
float r; |
float r; |
83 |
/** The three states of the two fillet edges |
/** The three states of the two fillet edges |
84 |
* involved here. Separate = no interaction, |
* involved here. Separate = no interaction, |
102 |
* @param ab Angle of fillet b. Always > aa |
* @param ab Angle of fillet b. Always > aa |
103 |
*/ |
*/ |
104 |
FilletSpan( |
FilletSpan( |
105 |
Vec ctr, |
ZVec ctr, |
106 |
float r, |
float r, |
107 |
float aa, |
float aa, |
108 |
float da, |
float da, |
109 |
float ta, |
float ta, |
110 |
|
float za, |
111 |
float ab, |
float ab, |
112 |
float db, |
float db, |
113 |
float tb |
float tb, |
114 |
|
float zb |
115 |
) { |
) { |
116 |
this->aa = aa; |
this->aa = aa; |
117 |
this->ab = ab; |
this->ab = ab; |
118 |
|
this->da = da; |
119 |
|
this->db = db; |
120 |
|
this->za = za; |
121 |
|
this->zb = zb; |
122 |
this->ctr = ctr; |
this->ctr = ctr; |
123 |
this->r = r; |
this->r = r; |
124 |
this->f = -1; |
this->f = -1; |
159 |
} |
} |
160 |
} |
} |
161 |
|
|
|
float rad_separate(Vec dir) { |
|
|
float ra = a.rad(dir); |
|
|
float rb = b.rad(dir); |
|
|
return ra >? rb; |
|
|
} |
|
|
|
|
|
template <class Blender> float rad_blended(Vec dir, const Blender &b) { |
|
|
float ra = this->a.rad(dir); |
|
|
float rb = this->b.rad(dir); |
|
|
return b(ra-r, rb-r) + r; |
|
|
} |
|
162 |
|
|
163 |
// If calls to point should be split |
// If calls to point should be split |
164 |
bool split() { return type == CLEAVE; } |
bool split() { return type == CLEAVE; } |
165 |
|
|
166 |
template <class Blender> Vec point(float fract, const Blender &b) { |
template <class Blender> ZVec point(float fract, const Blender &blend, ZVec *intern = 0) { |
167 |
if(type == CLEAVE) { |
if(type == CLEAVE) { |
168 |
|
if(intern) *intern = ctr; |
169 |
if(fract < .5) { |
if(fract < .5) { |
170 |
// Angle of real current sample |
// Angle of real current sample |
171 |
float ang = lerp(aa, aang, 2*fract); |
float ang = lerp(aa, aang, 2*fract); |
177 |
Vec db = dirVec(ab - fangle + fangle/2 * (2*fract)); |
Vec db = dirVec(ab - fangle + fangle/2 * (2*fract)); |
178 |
float ra = this->a.rad(da); |
float ra = this->a.rad(da); |
179 |
float rb = this->b.rad(db); |
float rb = this->b.rad(db); |
180 |
float curvfra = b(ra-r, rb-r) + r; |
float curvfra = blend(ra-r, rb-r) + r; |
181 |
|
|
182 |
Vec p = ctr + lerp( |
ZVec p = ctr + lerp( |
183 |
da * curvfra, |
da * curvfra, |
184 |
d * r0, |
d * r0, |
185 |
f); |
f); |
199 |
Vec da = dirVec(aa + fangle - fangle/2 * (2*fract)); |
Vec da = dirVec(aa + fangle - fangle/2 * (2*fract)); |
200 |
float rb = this->b.rad(db); |
float rb = this->b.rad(db); |
201 |
float ra = this->a.rad(da); |
float ra = this->a.rad(da); |
202 |
float curvfra = b(rb-r, ra-r) + r; |
float curvfra = blend(rb-r, ra-r) + r; |
203 |
|
|
204 |
Vec p = ctr + lerp( |
ZVec p = ctr + lerp( |
205 |
db * curvfra, |
db * curvfra, |
206 |
d * r0, |
d * r0, |
207 |
f); |
f); |
212 |
} else { |
} else { |
213 |
// Use angle |
// Use angle |
214 |
Vec d = dirVec(lerp(aa, ab, fract)); |
Vec d = dirVec(lerp(aa, ab, fract)); |
215 |
|
float ra = a.rad(d); |
216 |
|
float rb = b.rad(d); |
217 |
|
float z, resr; |
218 |
if(type == SEPARATE) { |
if(type == SEPARATE) { |
219 |
return ctr + d * rad_separate(d); |
if(ra > rb) { |
220 |
|
z = lerp(ctr.z, za, (ra - r) / (da-r)) ; |
221 |
|
resr = ra; |
222 |
|
} else { |
223 |
|
z = lerp(ctr.z, zb, (rb - r) / (db-r)) ; |
224 |
|
resr = rb; |
225 |
|
} |
226 |
} else { |
} else { |
227 |
return ctr + d * rad_blended(d, b); |
resr = blend(ra-r, rb-r) + r; |
228 |
|
z = blend(ra-r, rb-r, |
229 |
|
lerp(ctr.z, za, (ra - r) / (da-r)), |
230 |
|
lerp(ctr.z, zb, (rb - r) / (db-r)) |
231 |
|
); |
232 |
} |
} |
233 |
|
ZVec res = ctr + d * resr; |
234 |
|
if(intern) { |
235 |
|
if(ra > rb) { |
236 |
|
*intern = d*resr; |
237 |
|
*intern -= intern->dot(a.dirconn.cw90()) * a.dirconn.cw90(); |
238 |
|
intern->z = z; |
239 |
|
if(intern->length() <= r) *intern = ZVec(0,0,0); |
240 |
|
*intern += ctr; |
241 |
|
} else { |
242 |
|
*intern = d*resr; |
243 |
|
*intern -= intern->dot(b.dirconn.cw90()) * b.dirconn.cw90(); |
244 |
|
intern->z = z; |
245 |
|
if(intern->length() <= r) *intern = ZVec(0,0,0); |
246 |
|
*intern += ctr; |
247 |
|
} |
248 |
|
} |
249 |
|
res.z = z; |
250 |
|
return res; |
251 |
} |
} |
252 |
} |
} |
253 |
|
|
258 |
float operator()(float a, float b) const { |
float operator()(float a, float b) const { |
259 |
return a + b; |
return a + b; |
260 |
} |
} |
261 |
|
float operator()(float a, float b, float fa, float fb) const { |
262 |
|
return (a*fa + b*fb) / (a+b + .0001); |
263 |
|
} |
264 |
}; |
}; |
265 |
|
|
266 |
} |
} |