52 quadratic_bezier_curve(
const PointT&
p0,
const PointT&
p1,
const PointT&
p2) :
p0(
p0),
p1(
p1),
p2(
p2) {}
54 template<
typename ParamT =
float>
55 PointT evaluate(ParamT t)
const {
56 return interpolate_quadratic_bezier(
p0,
p1,
p2, t);
59 template<
typename ParamT =
float>
60 PointT derivative(ParamT t)
const {
61 return interpolate_linear(PointT(2) * (
p1 -
p0), PointT(2) * (
p2 -
p1), t);
64 std::pair<PointT, PointT> axis_aligned_bounding_box()
const {
65 PointT mi = per_component_min(
p0,
p2);
66 PointT ma = per_component_max(
p0,
p2);
68 if(is_outside_bounds(
p1, mi, ma)) {
69 PointT t = clamp((
p0 -
p1) / (
p0 - PointT(2) *
p1 +
p2), PointT(0), PointT(1));
70 PointT s = PointT(1) - t;
71 PointT q = s * s *
p0 + PointT(2) * s * t *
p1 + t * t *
p2;
72 mi = per_component_min(mi, q);
73 ma = per_component_max(ma, q);
81 T per_component_min(
const T& a,
const T& b)
const {
82 return std::min(a, b);
85 template<
typename T, cgv::type::u
int32_type N>
86 fvec<T, N> per_component_min(
const fvec<T, N>& a,
const fvec<T, N>& b)
const {
91 T per_component_max(
const T& a,
const T& b)
const {
92 return std::max(a, b);
95 template<
typename T, cgv::type::u
int32_type N>
96 fvec<T, N> per_component_max(
const fvec<T, N>& a,
const fvec<T, N>& b)
const {
101 bool is_outside_bounds(
const T& p,
const T& min,
const T& max)
const {
102 return p < min || p > max;
105 template<
typename T, cgv::type::u
int32_type N>
106 bool is_outside_bounds(
const fvec<T, N>& p,
const fvec<T, N>& min,
const fvec<T, N>& max)
const {
108 if(p[i] < min[i] || p[i] > max[i])
128 cubic_bezier_curve(
const PointT&
p0,
const PointT&
p1,
const PointT&
p2,
const PointT&
p3) :
p0(
p0),
p1(
p1),
p2(
p2),
p3(
p3) {}
130 template<
typename ParamT =
float>
131 PointT evaluate(ParamT t)
const {
132 return interpolate_cubic_bezier(
p0,
p1,
p2,
p3, t);
135 template<
typename ParamT =
float>
136 PointT derivative(ParamT t)
const {
137 return interpolate_quadratic_bezier(PointT(3) * (
p1 -
p0), PointT(3) * (
p2 -
p1), PointT(3) * (
p3 -
p2), t);
140 std::pair<PointT, PointT> axis_aligned_bounding_box()
const {
141 return compute_bounds(
p0,
p1,
p2,
p3);
146 std::pair<T, T> compute_bounds(
const T&
p0,
const T&
p1,
const T&
p2,
const T&
p3)
const {
147 T mi = std::min(
p0,
p3);
148 T ma = std::max(
p0,
p3);
150 T c = T(-1) *
p0 + T(1) *
p1;
151 T b = T(1) *
p0 - T(2) *
p1 + T(1) *
p2;
152 T a = T(-1) *
p0 + T(3) *
p1 - T(3) *
p2 + T(1) *
p3;
159 if(t > T(0) && t < T(1)) {
161 T q = s * s * s *
p0 + T(3) * s * s * t *
p1 + T(3) * s * t * t *
p2 + t * t * t *
p3;
162 mi = std::min(mi, q);
163 ma = std::max(ma, q);
166 if(t > T(0) && t < T(1)) {
168 T q = s * s * s *
p0 + T(3) * s * s * t *
p1 + T(3) * s * t * t *
p2 + t * t * t *
p3;
169 mi = std::min(mi, q);
170 ma = std::max(ma, q);
177 template<
typename T, cgv::type::u
int32_type N>
178 std::pair<fvec<T, N>, fvec<T, N>> compute_bounds(
const fvec<T, N>&
p0,
const fvec<T, N>&
p1,
const fvec<T, N>&
p2,
const fvec<T, N>&
p3)
const {
179 std::pair<fvec<T, N>, fvec<T, N>> bounds;
181 std::pair<T, T> coord_bounds = compute_bounds(
p0[i],
p1[i],
p2[i],
p3[i]);
182 bounds.first[i] = coord_bounds.first;
183 bounds.second[i] = coord_bounds.second;