Browse Source

Math: make Bezier::subdivide() return a pair and test it.

pull/175/merge
Vladimír Vondruš 10 years ago
parent
commit
b59b8d431e
  1. 16
      src/Magnum/Math/Bezier.h
  2. 51
      src/Magnum/Math/Test/BezierTest.cpp

16
src/Magnum/Math/Bezier.h

@ -96,21 +96,19 @@ template<UnsignedInt order, UnsignedInt dimensions, class T> class Bezier {
template<class U> constexpr explicit Bezier(const Bezier<order, dimensions, U>& other) noexcept: Bezier{typename Implementation::GenerateSequence<order + 1>::Type(), other} {}
/**
* @brief Subdivide the curve
* @param t The interpolation factor
* @brief Subdivide the curve at given position
*
* Divides the curve into two Bézier curves of same order having their
* own control points. Uses the [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm).
* Returns two Bézier curves following the original curve, split at
* given interpolation factor. Uses the [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm).
* @see @ref value()
*/
std::array<Bezier<order, dimensions, T>, 2> subdivide(Float t) const {
std::pair<Bezier<order, dimensions, T>, Bezier<order, dimensions, T>> subdivide(Float t) const {
const auto iPoints = calculateIntermediatePoints(t);
Bezier<order, dimensions, T> left, right;
for(std::size_t i = 0; i <= order; ++i) {
for(std::size_t i = 0; i <= order; ++i)
left[i] = iPoints[0][i];
}
for(std::size_t i = 0, j = order; i <= order; --j, ++i) {
for(std::size_t i = 0, j = order; i <= order; --j, ++i)
right[i] = iPoints[i][j];
}
return {left, right};
}

51
src/Magnum/Math/Test/BezierTest.cpp

@ -57,6 +57,9 @@ struct BezierTest : Corrade::TestSuite::Tester {
void valueLinear();
void valueQuadratic();
void valueCubic();
void subdivideLinear();
void subdivideQuadratic();
void subdivideCubic();
void debug();
void configuration();
@ -76,6 +79,9 @@ BezierTest::BezierTest() {
&BezierTest::valueLinear,
&BezierTest::valueQuadratic,
&BezierTest::valueCubic,
&BezierTest::subdivideLinear,
&BezierTest::subdivideQuadratic,
&BezierTest::subdivideCubic,
&BezierTest::debug,
&BezierTest::configuration});
@ -172,6 +178,51 @@ void BezierTest::valueCubic() {
CORRADE_VERIFY(bezier.value(0.2f) != Math::lerp(bezier[0], bezier[3], 0.2f));
}
void BezierTest::subdivideLinear() {
LinearBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{20.0f, 4.0f}};
LinearBezier2D left, right;
std::tie(left, right) = bezier.subdivide(0.25f);
CORRADE_COMPARE(left[0], bezier[0]);
CORRADE_COMPARE(left[1], right[0]);
CORRADE_COMPARE(right[1], bezier[1]);
CORRADE_COMPARE(left.value(0.8f), bezier.value(0.2f));
CORRADE_COMPARE(right.value(0.33333f), bezier.value(0.5f));
CORRADE_COMPARE(left, (LinearBezier2D{Vector2{0.0f, 0.0f}, Vector2{5.0f, 1.0f}}));
CORRADE_COMPARE(right, (LinearBezier2D{Vector2{5.0f, 1.0f}, Vector2{20.0f, 4.0f}}));
}
void BezierTest::subdivideQuadratic() {
QuadraticBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}};
QuadraticBezier2D left, right;
std::tie(left, right) = bezier.subdivide(0.25f);
CORRADE_COMPARE(left[0], bezier[0]);
CORRADE_COMPARE(left[2], right[0]);
CORRADE_COMPARE(right[2], bezier[2]);
CORRADE_COMPARE(left.value(0.8f), bezier.value(0.2f));
CORRADE_COMPARE(right.value(0.33333f), bezier.value(0.5f));
CORRADE_COMPARE(left, (QuadraticBezier2D{Vector2{0.0f, 0.0f}, Vector2{2.5f, 3.75f}, Vector2{5.0f, 5.875f}}));
CORRADE_COMPARE(right, (QuadraticBezier2D{Vector2{5.0f, 5.875f}, Vector2{12.5f, 12.25f}, Vector2{20.0f, 4.0f}}));
}
void BezierTest::subdivideCubic() {
CubicBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}, Vector2{5.0f, -20.0f}};
CubicBezier2D left, right;
std::tie(left, right) = bezier.subdivide(0.25f);
CORRADE_COMPARE(left[0], bezier[0]);
CORRADE_COMPARE(left[3], right[0]);
CORRADE_COMPARE(right[3], bezier[3]);
CORRADE_COMPARE(left.value(0.8f), bezier.value(0.2f));
CORRADE_COMPARE(right.value(0.33333f), bezier.value(0.5f));
CORRADE_COMPARE(left, (CubicBezier2D{Vector2{0.0f, 0.0f}, Vector2{2.5f, 3.75f}, Vector2{5.0f, 5.875f}, Vector2{7.10938f, 6.57812f}}));
CORRADE_COMPARE(right, (CubicBezier2D{Vector2{7.10938f, 6.57812f}, Vector2{13.4375f, 8.6875f}, Vector2{16.25f, -2.0f}, Vector2{5.0f, -20.0f}}));
}
void BezierTest::debug() {
std::ostringstream out;
Debug(&out) << CubicBezier2D{Vector2{0.0f, 1.0f}, Vector2{1.5f, -0.3f}, Vector2{2.1f, 0.5f}, Vector2{0.0f, 2.0f}};

Loading…
Cancel
Save