cgv
Loading...
Searching...
No Matches
bezier_tube.h
1#pragma once
2
3#include "bezier.h"
4#include "distance.h"
5#include "oriented_box.h"
6
7namespace cgv {
8namespace math {
9
10template<typename T>
11struct sphere {
12 fvec<T, 3> pos = T(0);
13 T rad = T(0);
14};
15
16template<typename T>
18 fvec<T, 3> pos = T(0);
19 T rad = T(0);
20};
21
22template<typename T>
24public:
25 using vec_type = fvec<T, 3>;
28 using sample_type = sphere<T>;
29
30 // the start node
31 node_type n0;
32 // the middle node
33 node_type n1;
34 // the end node
35 node_type n2;
36
37 template<typename ParamT = float>
38 sample_type evaluate(ParamT t) const {
40 n.pos = interpolate_quadratic_bezier(n0.pos, n1.pos, n2.pos, t);
41 n.rad = interpolate_quadratic_bezier(n0.rad, n1.rad, n2.rad, t);
42 return n;
43 }
44
45 template<typename ParamT = float>
46 sample_type derivative(ParamT t) const {
48 n.pos = interpolate_linear(point_type(2) * (n1.pos - n0.pos), point_type(2) * (n2.pos - n1.pos), t);
49 n.rad = interpolate_linear(point_type(2) * (n1.rad - n0.rad), point_type(2) * (n2.rad - n1.rad), t);
50 return n;
51 }
52
53 template<typename ParamT = float>
54 std::vector<sample_type> sample(size_t num_segments) const {
55 std::vector<sample_type> points;
56 points.reserve(num_segments + 1);
57 sequence_transform<ParamT>(std::back_inserter(points), [this](ParamT t) { return evaluate(t); }, num_segments + 1);
58 return points;
59 }
60
61 std::pair<vec_type, vec_type> axis_aligned_bounding_box() const {
63 curve.p0 = n0.pos - n0.rad;
64 curve.p1 = n1.pos - n1.rad;
65 curve.p2 = n2.pos - n2.rad;
66
67 auto box_min = curve.axis_aligned_bounding_box();
68
69 curve.p0 = n0.pos + n0.rad;
70 curve.p1 = n1.pos + n1.rad;
71 curve.p2 = n2.pos + n2.rad;
72 auto box_max = curve.axis_aligned_bounding_box();
73
74 return { min(box_min.first, box_max.first), max(box_min.second, box_max.second) };
75 }
76
77 oriented_box3<T> oriented_bounding_box() const {
78 const fvec<T, 4> corners[4] = {
79 { T(-0.5), T(-0.5), T(-0.5), T(1.0) },
80 { T(+0.5), T(-0.5), T(-0.5), T(1.0) },
81 { T(-0.5), T(+0.5), T(-0.5), T(1.0) },
82 { T(-0.5), T(-0.5), T(+0.5), T(1.0) }
83 };
84
85 cgv::mat4 M = calculate_transformation_matrix();
86
87 vec_type p000 = vec_type(M * corners[0]);
88 vec_type p100 = vec_type(M * corners[1]);
89 vec_type p010 = vec_type(M * corners[2]);
90 vec_type p001 = vec_type(M * corners[3]);
91
92 vec_type dx = p100 - p000;
93 vec_type dy = p010 - p000;
94 vec_type dz = p001 - p000;
95
96 T lx = length(dx);
97 T ly = length(dy);
98 T lz = length(dz);
99
100 fmat<T, 3, 3> R({ dx / lx, dy / ly, dz / lz });
101
103 box.center = M.col(3);
104 box.extent = cgv::vec3(lx, ly, lz);
105 box.rotation = cgv::quat(R);
106 return box;
107 }
108
109 std::pair<T, T> signed_distance(const vec_type& pos) const {
110 quadratic_bezier_curve<vec_type> curve = { n0.pos, n1.pos, n2.pos };
111 std::pair<T, T> res = point_quadratic_bezier_distance(pos, n0.pos, n1.pos, n2.pos);
112
113 T rc[3];
114 control_points_to_poly_coeffs(n0.rad, n1.rad, n2.rad, rc);
115 T radius = eval_poly_d0(res.second, rc);
116
117 res.first -= radius;
118 return res;
119 }
120
121 matrix_type calculate_transformation_matrix() const {
122 vec_type x, y, z;
123
124 T xl, yl;
125 bool xq = false;
126 bool yq = false;
127 {
128 x = n2.pos - n0.pos;
129 xl = length(x);
130
131 if(xl < T(0.0001)) {
132 y = n1.pos - n0.pos;
133 yl = length(y);
134
135 if(yl < T(0.0001)) {
136 x = vec_type(T(1), T(0), T(0));
137 y = vec_type(T(0), T(1), T(0));
138 z = vec_type(T(0), T(0), T(1));
139
140 xl = T(1); xq = true;
141 yl = T(1); yq = true;
142 } else {
143 x = normalize(ortho(x));
144 xl = T(1); xq = true;
145
146 z = cross(x, y);
147 }
148 } else {
149 y = cgv::math::project_to_plane(n1.pos - n0.pos, x);
150 yl = length(y);
151
152 if(yl < T(0.0001)) {
153 y = normalize(ortho(x));
154 yl = T(1); yq = true;
155 }
156
157 z = cross(x, y);
158 }
159 }
160
161 vec_type xd = x / xl;
162 vec_type yd = y / yl;
163 vec_type zd = normalize(z);
164
165 T xm, xp, ym, yp, zm;
166 {
167 T xyl = dot(n1.pos - n0.pos, xd);
168
169 T cx[3];
170 control_points_to_poly_coeffs(T(0), xyl, xl, cx);
171
172 T cy[3];
173 control_points_to_poly_coeffs(T(0), yl, T(0), cy);
174
175 T rc[3];
176 control_points_to_poly_coeffs(n0.rad, n1.rad, n2.rad, rc);
177
178 T c_xm[3];
179 c_xm[0] = cx[0] - rc[0]; c_xm[1] = cx[1] - rc[1]; c_xm[2] = cx[2] - rc[2];
180
181 T c_xp[3];
182 c_xp[0] = cx[0] + rc[0]; c_xp[1] = cx[1] + rc[1]; c_xp[2] = cx[2] + rc[2];
183
184 xm = std::min(-n0.rad, std::min(xl - n2.rad, eval_poly_d0(saturate(-c_xm[1] / c_xm[2] * T(0.5)), c_xm)));
185 xp = std::max(+n0.rad, std::max(xl + n2.rad, eval_poly_d0(saturate(-c_xp[1] / c_xp[2] * T(0.5)), c_xp)));
186
187 T c_ym[3];
188 c_ym[0] = cy[0] - rc[0]; c_ym[1] = cy[1] - rc[1]; c_ym[2] = cy[2] - rc[2];
189
190 T c_yp[3];
191 c_yp[0] = cy[0] + rc[0]; c_yp[1] = cy[1] + rc[1]; c_yp[2] = cy[2] + rc[2];
192
193 ym = std::min(-n0.rad, std::min(-n2.rad, eval_poly_d0(saturate(-c_ym[1] / c_ym[2] * T(0.5)), c_ym)));
194 yp = std::max(+n0.rad, std::max(+n2.rad, eval_poly_d0(saturate(-c_yp[1] / c_yp[2] * T(0.5)), c_yp)));
195
196 zm = std::max(n0.rad, std::max(n2.rad, eval_poly_d0(saturate(-rc[1] / rc[2] * T(0.5)), rc)));
197
198 if(xq) { xm = -zm; xp = zm; }
199 if(yq) { ym = -zm; yp = zm; }
200 }
201
202 vec_type center = n0.pos + 0.5f * (xd * (xm + xp) + yd * (ym + yp));
203
204 return {
205 { (xp - xm) * xd, T(0) },
206 { (yp - ym) * yd, T(0) },
207 { T(2) * zm * zd, T(0) },
208 { center, T(1) }
209 };
210 }
211
212private:
213 void control_points_to_poly_coeffs(T p0, T h, T p1, T o_c[3]) const {
214 o_c[0] = p0;
215 o_c[1] = T(-2) * p0 + T(2) * h;
216 o_c[2] = p0 + p1 - T(2) * h;
217 }
218
219 T eval_poly_d0(T x, T c[3]) const {
220 return x * (x * c[2] + c[1]) + c[0];
221 }
222};
223
224} // namespace math
225} // namespace cgv
matrix of fixed size dimensions
Definition fmat.h:23
fvec< T, N > & col(unsigned j)
reference a column of the matrix as a vector
Definition fmat.h:209
A vector with zero based index.
Definition fvec.h:29
PointT p2
the end control point
Definition bezier.h:51
PointT p0
the start control point
Definition bezier.h:47
PointT p1
the middle control point
Definition bezier.h:49
this header is dependency free
Definition print.h:11
cgv::math::quaternion< float > quat
declare type of quaternion
Definition quaternion.h:370
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
Definition fvec.h:694