18 template<
typename InputIt>
22 template<
typename ParamT =
float>
23 PointT evaluate(ParamT t)
const {
31 size_t degree =
points.size() - 1;
32 std::vector<PointT> d =
points;
34 for(
size_t i = 1; i <= degree; ++i) {
35 for(
size_t j = degree; j > i - 1; --j)
36 d[j] = interpolate_linear(d[j - 1], d[j], t);
54 quadratic_bezier_curve(
const PointT&
p0,
const PointT&
p1,
const PointT&
p2) :
p0(
p0),
p1(
p1),
p2(
p2) {}
56 template<
typename ParamT =
float>
57 PointT evaluate(ParamT t)
const {
58 return interpolate_quadratic_bezier(
p0,
p1,
p2, t);
61 template<
typename ParamT =
float>
62 PointT derivative(ParamT t)
const {
63 return interpolate_linear(PointT(2) * (
p1 -
p0), PointT(2) * (
p2 -
p1), t);
66 std::pair<PointT, PointT> axis_aligned_bounding_box()
const {
67 PointT mi = per_component_min(
p0,
p2);
68 PointT ma = per_component_max(
p0,
p2);
70 if(is_outside_bounds(
p1, mi, ma)) {
71 PointT t = clamp((
p0 -
p1) / (
p0 - PointT(2) *
p1 +
p2), PointT(0), PointT(1));
72 PointT s = PointT(1) - t;
73 PointT q = s * s *
p0 + PointT(2) * s * t *
p1 + t * t *
p2;
74 mi = per_component_min(mi, q);
75 ma = per_component_max(ma, q);
83 T per_component_min(
const T& a,
const T& b)
const {
84 return std::min(a, b);
87 template<
typename T, cgv::type::u
int32_type N>
88 fvec<T, N> per_component_min(
const fvec<T, N>& a,
const fvec<T, N>& b)
const {
93 T per_component_max(
const T& a,
const T& b)
const {
94 return std::max(a, b);
97 template<
typename T, cgv::type::u
int32_type N>
98 fvec<T, N> per_component_max(
const fvec<T, N>& a,
const fvec<T, N>& b)
const {
103 bool is_outside_bounds(
const T& p,
const T& min,
const T& max)
const {
104 return p < min || p > max;
107 template<
typename T, cgv::type::u
int32_type N>
108 bool is_outside_bounds(
const fvec<T, N>& p,
const fvec<T, N>& min,
const fvec<T, N>& max)
const {
110 if(p[i] < min[i] || p[i] > max[i])
130 cubic_bezier_curve(
const PointT&
p0,
const PointT&
p1,
const PointT&
p2,
const PointT&
p3) :
p0(
p0),
p1(
p1),
p2(
p2),
p3(
p3) {}
132 template<
typename ParamT =
float>
133 PointT evaluate(ParamT t)
const {
134 return interpolate_cubic_bezier(
p0,
p1,
p2,
p3, t);
137 template<
typename ParamT =
float>
138 PointT derivative(ParamT t)
const {
139 return interpolate_quadratic_bezier(PointT(3) * (
p1 -
p0), PointT(3) * (
p2 -
p1), PointT(3) * (
p3 -
p2), t);
142 std::pair<PointT, PointT> axis_aligned_bounding_box()
const {
143 return compute_bounds(
p0,
p1,
p2,
p3);
148 std::pair<T, T> compute_bounds(
const T&
p0,
const T&
p1,
const T&
p2,
const T&
p3)
const {
149 T mi = std::min(
p0,
p3);
150 T ma = std::max(
p0,
p3);
152 T c = T(-1) *
p0 + T(1) *
p1;
153 T b = T(1) *
p0 - T(2) *
p1 + T(1) *
p2;
154 T a = T(-1) *
p0 + T(3) *
p1 - T(3) *
p2 + T(1) *
p3;
161 if(t > T(0) && t < T(1)) {
163 T q = s * s * s *
p0 + T(3) * s * s * t *
p1 + T(3) * s * t * t *
p2 + t * t * t *
p3;
164 mi = std::min(mi, q);
165 ma = std::max(ma, q);
168 if(t > T(0) && t < T(1)) {
170 T q = s * s * s *
p0 + T(3) * s * s * t *
p1 + T(3) * s * t * t *
p2 + t * t * t *
p3;
171 mi = std::min(mi, q);
172 ma = std::max(ma, q);
179 template<
typename T, cgv::type::u
int32_type N>
180 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 {
181 std::pair<fvec<T, N>, fvec<T, N>> bounds;
183 std::pair<T, T> coord_bounds = compute_bounds(
p0[i],
p1[i],
p2[i],
p3[i]);
184 bounds.first[i] = coord_bounds.first;
185 bounds.second[i] = coord_bounds.second;