30 template<
typename ParamT =
float>
33 n.pos = interpolate_quadratic_bezier(n0.pos, n1.pos, n2.pos, t);
34 n.rad = interpolate_quadratic_bezier(n0.rad, n1.rad, n2.rad, t);
38 template<
typename ParamT =
float>
41 n.pos = interpolate_linear(point_type(2) * (n1.pos - n0.pos), point_type(2) * (n2.pos - n1.pos), t);
42 n.rad = interpolate_linear(point_type(2) * (n1.rad - n0.rad), point_type(2) * (n2.rad - n1.rad), t);
46 template<
typename ParamT =
float>
47 std::vector<node_type> sample(
size_t num_segments)
const {
48 std::vector<node_type> points;
49 points.reserve(num_segments + 1);
50 sample_steps_transform<ParamT>(std::back_inserter(points), [
this](ParamT t) {
return evaluate(t); }, num_segments);
54 std::pair<vec_type, vec_type> axis_aligned_bounding_box()
const {
56 curve.
p0 = n0.pos - n0.rad;
57 curve.
p1 = n1.pos - n1.rad;
58 curve.
p2 = n2.pos - n2.rad;
60 auto box_min = curve.axis_aligned_bounding_box();
62 curve.
p0 = n0.pos + n0.rad;
63 curve.
p1 = n1.pos + n1.rad;
64 curve.
p2 = n2.pos + n2.rad;
65 auto box_max = curve.axis_aligned_bounding_box();
67 return { min(box_min.first, box_max.first), max(box_min.second, box_max.second) };
72 { T(-0.5), T(-0.5), T(-0.5), T(1.0) },
73 { T(+0.5), T(-0.5), T(-0.5), T(1.0) },
74 { T(-0.5), T(+0.5), T(-0.5), T(1.0) },
75 { T(-0.5), T(-0.5), T(+0.5), T(1.0) }
78 cgv::mat4 M = calculate_transformation_matrix();
96 box.center = M.
col(3);
102 std::pair<T, T> signed_distance(
const vec_type& pos)
const {
104 std::pair<T, T> res = point_quadratic_bezier_distance(pos, n0.pos, n1.pos, n2.pos);
107 control_points_to_poly_coeffs(n0.rad, n1.rad, n2.rad, rc);
108 T radius = eval_poly_d0(res.second, rc);
114 matrix_type calculate_transformation_matrix()
const {
133 xl = T(1); xq =
true;
134 yl = T(1); yq =
true;
136 x = normalize(ortho(x));
137 xl = T(1); xq =
true;
142 y = project_to_plane(n1.pos - n0.pos, x);
146 y = normalize(ortho(x));
147 yl = T(1); yq =
true;
158 T xm, xp, ym, yp, zm;
160 T xyl = dot(n1.pos - n0.pos, xd);
163 control_points_to_poly_coeffs(T(0), xyl, xl, cx);
166 control_points_to_poly_coeffs(T(0), yl, T(0), cy);
169 control_points_to_poly_coeffs(n0.rad, n1.rad, n2.rad, rc);
172 c_xm[0] = cx[0] - rc[0]; c_xm[1] = cx[1] - rc[1]; c_xm[2] = cx[2] - rc[2];
175 c_xp[0] = cx[0] + rc[0]; c_xp[1] = cx[1] + rc[1]; c_xp[2] = cx[2] + rc[2];
177 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)));
178 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)));
181 c_ym[0] = cy[0] - rc[0]; c_ym[1] = cy[1] - rc[1]; c_ym[2] = cy[2] - rc[2];
184 c_yp[0] = cy[0] + rc[0]; c_yp[1] = cy[1] + rc[1]; c_yp[2] = cy[2] + rc[2];
186 ym = std::min(-n0.rad, std::min(-n2.rad, eval_poly_d0(saturate(-c_ym[1] / c_ym[2] * T(0.5)), c_ym)));
187 yp = std::max(+n0.rad, std::max(+n2.rad, eval_poly_d0(saturate(-c_yp[1] / c_yp[2] * T(0.5)), c_yp)));
189 zm = std::max(n0.rad, std::max(n2.rad, eval_poly_d0(saturate(-rc[1] / rc[2] * T(0.5)), rc)));
191 if(xq) { xm = -zm; xp = zm; }
192 if(yq) { ym = -zm; yp = zm; }
195 vec_type center = n0.pos + 0.5f * (xd * (xm + xp) + yd * (ym + yp));
198 { (xp - xm) * xd, T(0) },
199 { (yp - ym) * yd, T(0) },
200 { T(2) * zm * zd, T(0) },
208 return vec - n * dot(
vec, n) / dot(n, n);
211 void control_points_to_poly_coeffs(T p0, T h, T p1, T o_c[3])
const {
213 o_c[1] = T(-2) * p0 + T(2) * h;
214 o_c[2] = p0 + p1 - T(2) * h;
217 T eval_poly_d0(T x, T c[3])
const {
218 return x * (x * c[2] + c[1]) + c[0];