37 template<
typename ParamT =
float>
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);
45 template<
typename ParamT =
float>
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);
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);
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;
67 auto box_min = curve.axis_aligned_bounding_box();
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();
74 return { min(box_min.first, box_max.first), max(box_min.second, box_max.second) };
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) }
85 cgv::mat4 M = calculate_transformation_matrix();
103 box.center = M.
col(3);
109 std::pair<T, T> signed_distance(
const vec_type& pos)
const {
111 std::pair<T, T> res = point_quadratic_bezier_distance(pos, n0.pos, n1.pos, n2.pos);
114 control_points_to_poly_coeffs(n0.rad, n1.rad, n2.rad, rc);
115 T radius = eval_poly_d0(res.second, rc);
121 matrix_type calculate_transformation_matrix()
const {
140 xl = T(1); xq =
true;
141 yl = T(1); yq =
true;
143 x = normalize(ortho(x));
144 xl = T(1); xq =
true;
149 y = cgv::math::project_to_plane(n1.pos - n0.pos, x);
153 y = normalize(ortho(x));
154 yl = T(1); yq =
true;
165 T xm, xp, ym, yp, zm;
167 T xyl = dot(n1.pos - n0.pos, xd);
170 control_points_to_poly_coeffs(T(0), xyl, xl, cx);
173 control_points_to_poly_coeffs(T(0), yl, T(0), cy);
176 control_points_to_poly_coeffs(n0.rad, n1.rad, n2.rad, rc);
179 c_xm[0] = cx[0] - rc[0]; c_xm[1] = cx[1] - rc[1]; c_xm[2] = cx[2] - rc[2];
182 c_xp[0] = cx[0] + rc[0]; c_xp[1] = cx[1] + rc[1]; c_xp[2] = cx[2] + rc[2];
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)));
188 c_ym[0] = cy[0] - rc[0]; c_ym[1] = cy[1] - rc[1]; c_ym[2] = cy[2] - rc[2];
191 c_yp[0] = cy[0] + rc[0]; c_yp[1] = cy[1] + rc[1]; c_yp[2] = cy[2] + rc[2];
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)));
196 zm = std::max(n0.rad, std::max(n2.rad, eval_poly_d0(saturate(-rc[1] / rc[2] * T(0.5)), rc)));
198 if(xq) { xm = -zm; xp = zm; }
199 if(yq) { ym = -zm; yp = zm; }
202 vec_type center = n0.pos + 0.5f * (xd * (xm + xp) + yd * (ym + yp));
205 { (xp - xm) * xd, T(0) },
206 { (yp - ym) * yd, T(0) },
207 { T(2) * zm * zd, T(0) },
213 void control_points_to_poly_coeffs(T p0, T h, T p1, T o_c[3])
const {
215 o_c[1] = T(-2) * p0 + T(2) * h;
216 o_c[2] = p0 + p1 - T(2) * h;
219 T eval_poly_d0(T x, T c[3])
const {
220 return x * (x * c[2] + c[1]) + c[0];