15 #ifndef MOTIVE_MATH_CURVE_H_
16 #define MOTIVE_MATH_CURVE_H_
20 #include "motive/common.h"
21 #include "motive/math/range.h"
28 kCurveSecondDerivative,
29 kCurveThirdDerivative,
32 static const int kDefaultGraphWidth = 80;
33 static const int kDefaultGraphHeight = 30;
34 static const mathfu::vec2i kDefaultGraphSize(kDefaultGraphWidth,
38 static const float kEpsilonPrecision =
static_cast<float>(1 << 22);
39 static const float kEpsilonScale = 1.0f / kEpsilonPrecision;
47 const float start_derivative,
49 : start_y(start_y), start_derivative(start_derivative), end_y(end_y) {}
52 float start_derivative;
61 const float second_derivative)
62 : y(y), derivative(derivative), second_derivative(second_derivative) {}
66 float second_derivative;
74 const float derivative_at_x,
75 const float second_derivative)
78 derivative_at_x(derivative_at_x),
79 second_derivative(second_derivative) {}
83 float derivative_at_x;
84 float second_derivative;
92 static const int kNumCoeff = 3;
104 for (
int i = 0; i < kNumCoeff; ++i) {
105 c_[i] = y_scale * q.c_[i];
117 for (
int i = 0; i < kNumCoeff; ++i) {
125 for (
int i = 0; i < kNumCoeff; ++i) {
139 void ShiftUp(
const float y_offset) { c_[0] += y_offset; }
143 for (
int i = 0; i < kNumCoeff; ++i) {
151 return (c_[2] * x + c_[1]) * x + c_[0];
156 float Derivative(
const float x)
const {
return 2.0f * c_[2] * x + c_[1]; }
193 return x * kEpsilonScale;
203 return max(max(abs.c_[2], abs.c_[1]), abs.c_[0]);
208 float Discriminant()
const {
return c_[1] * c_[1] - 4.0f * c_[2] * c_[0]; }
220 return -(c_[1] / c_[2]) * 0.5f;
247 shifted_down.
Roots(roots);
270 float Coeff(
int i)
const {
return c_[i]; }
285 return QuadraticCurve(c_[2] * x_scale_reciprocal * x_scale_reciprocal,
286 c_[1] * x_scale_reciprocal, c_[0]);
306 std::string
Text()
const;
310 size_t Roots(
float roots[2])
const;
312 size_t RootsInRange(
const Range& x_limits,
float roots[2])
const;
314 Range matching[2])
const;
319 inline QuadraticCurve operator+(
const QuadraticCurve& a,
320 const QuadraticCurve& b) {
321 return QuadraticCurve(a.Coeff(2) + b.Coeff(2), a.Coeff(1) + b.Coeff(1),
322 a.Coeff(0) + b.Coeff(0));
325 inline QuadraticCurve operator-(
const QuadraticCurve& a,
326 const QuadraticCurve& b) {
327 return QuadraticCurve(a.Coeff(2) - b.Coeff(2), a.Coeff(1) - b.Coeff(1),
328 a.Coeff(0) - b.Coeff(0));
336 CubicInit(
const float start_y,
const float start_derivative,
337 const float end_y,
const float end_derivative,
const float width_x)
339 start_derivative(start_derivative),
341 end_derivative(end_derivative),
346 float start_derivative;
348 float end_derivative;
357 static const int kNumCoeff = 4;
359 CubicCurve(
const float c3,
const float c2,
const float c1,
const float c0) {
365 CubicCurve(
const float* c) { memcpy(c_, c,
sizeof(c_)); }
377 void ShiftUp(
float y_offset) { c_[0] += y_offset; }
381 for (
int i = 0; i < kNumCoeff; ++i) {
390 return ((c_[3] * x + c_[2]) * x + c_[1]) * x + c_[0];
396 return (3.0f * c_[3] * x + 2.0f * c_[2]) * x + c_[1];
402 return 6.0f * c_[3] * x + 2.0f * c_[2];
427 max(max(max(fabs(c_[3]), fabs(c_[2])), fabs(c_[1])), fabs(c_[0]));
428 return max_c * kEpsilonScale;
432 float Coeff(
int i)
const {
return c_[i]; }
435 void SetCoeff(
int i,
float coeff) { c_[i] = coeff; }
445 std::string
Text()
const;
454 std::string Graph2DPoints(
const mathfu::vec2* points,
const int num_points,
455 const mathfu::vec2i& size = kDefaultGraphSize);
460 float CurveValue(
const T& curve,
const float x,
461 const CurveValueType value_type) {
462 switch (value_type) {
464 return curve.Evaluate(x);
465 case kCurveDerivative:
466 return curve.Derivative(x);
467 case kCurveSecondDerivative:
468 return curve.SecondDerivative(x);
469 case kCurveThirdDerivative:
470 return curve.ThirdDerivative(x);
479 std::string GraphCurveOnXRange(
const T& curve,
const CurveValueType value_type,
480 const Range& x_range,
481 const mathfu::vec2i& size = kDefaultGraphSize) {
483 const int num_points = size.x;
484 std::vector<mathfu::vec2> points(num_points);
485 const float inc_x = x_range.Length() / (num_points - 1);
486 float x = x_range.start();
487 for (
int i = 0; i < num_points; ++i) {
488 points[i] = mathfu::vec2(x, CurveValue(curve, x, value_type));
493 return Graph2DPoints(&points[0], num_points, size);
498 std::string GraphCurve(
const T& curve,
const CurveValueType value_type,
499 const mathfu::vec2i& size = kDefaultGraphSize) {
500 return curve.Text() +
"\n" +
501 GraphCurveOnXRange(curve, value_type,
502 Range(curve.StartX(), curve.EndX()), size);
507 #endif // MOTIVE_MATH_CURVE_H_
float Derivative(const float x) const
Definition: curve.h:156
void ScaleUp(const float y_scale)
Scale the curve along the y-axis by a factor of y_scale.
Definition: curve.h:142
float ThirdDerivative(const float x) const
Definition: curve.h:171
Initialization parameters to create a cubic curve with start and end y-values and derivatives...
Definition: curve.h:335
float Coeff(int i) const
Returns the coefficient for x to the ith power.
Definition: curve.h:432
std::string Text() const
A string with the cubic equation. Useful for debugging.
QuadraticCurve ScaleInY(const float y_scale) const
Returns the curve y_scale * f(x).
Definition: curve.h:290
Initialization parameters to create a quaternion with start and end values, and start derivative...
Definition: curve.h:45
float Derivative(const float x) const
Definition: curve.h:395
void Roots(RootsArray *roots) const
Definition: curve.h:226
bool operator==(const CubicCurve &rhs) const
Equality. Checks for exact match. Useful for testing.
float SecondDerivative(const float x) const
Definition: curve.h:401
QuadraticCurve ScaleInX(const float x_scale) const
Definition: curve.h:277
float Epsilon() const
Definition: curve.h:423
void RootsWithoutNormalizing(RootsArray *roots) const
Definition: curve.h:233
float CriticalPoint() const
Return the x at which the derivative is zero.
Definition: curve.h:216
Represent a quadratic polynomial in the form c_[2] * x^2 + c_[1] * x + c_[0].
Definition: curve.h:90
float ReliableDiscriminant(const float epsilon) const
int NumCoeff() const
Returns the number of coefficients in this curve.
Definition: curve.h:273
Represent a cubic polynomial of the form, c_[3] * x^3 + c_[2] * x^2 + c_[1] * x + c_[0]...
Definition: curve.h:355
Initialization parameters to create a quaternion with values and derivatives at x=0.
Definition: curve.h:59
QuadraticCurve ScaleInXByReciprocal(const float x_scale_reciprocal) const
Definition: curve.h:284
float Evaluate(const float x) const
Definition: curve.h:150
void ShiftLeft(const float x_shift)
int NumCoeff() const
Returns the number of coefficients in this curve.
Definition: curve.h:438
void ScaleUp(float y_scale)
Scale the curve along the y-axis by a factor of y_scale.
Definition: curve.h:380
QuadraticCurve AbsCoeff() const
Definition: curve.h:296
QuadraticCurve & operator-=(const QuadraticCurve &rhs)
Subtract the coefficients of another quadratic curve from this one.
Definition: curve.h:124
void RootsInRange(const Range &x_limits, RootsArray *roots) const
Definition: curve.h:240
float ThirdDerivative(const float x) const
Definition: curve.h:409
float Coeff(int i) const
Returns the coefficient for x-to-the-ith -power.
Definition: curve.h:270
Initialization parameters to create a quaternion with values and derivatives at a specified x...
Definition: curve.h:72
void ShiftUp(const float y_offset)
Shift the curve along the y-axis by y_offset: y_offset up the y-axis.
Definition: curve.h:139
void XsForValue(float value, RootsArray *roots) const
Calculate the x-coordinates at the value.
Definition: curve.h:245
float SecondDerivative(const float) const
Definition: curve.h:165
void SetCoeff(int i, float coeff)
Overrides the coefficent for x to the ith power.
Definition: curve.h:435
void RangesBelowZero(const Range &x_limits, RangeArray *matching) const
Return the ranges on which the quadratic is below zero.
Definition: curve.h:265
QuadraticCurve & operator+=(const QuadraticCurve &rhs)
Add the coefficients of another quadratic curve to this one.
Definition: curve.h:116
float Evaluate(const float x) const
Definition: curve.h:388
bool UniformCurvature(const Range &x_limits) const
float Discriminant() const
Definition: curve.h:208
float MaxCoeff() const
Definition: curve.h:200
float SecondDerivative() const
Definition: curve.h:160
void ShiftUp(float y_offset)
Shift the curve along the y-axis by y_offset: y_offset up the y-axis.
Definition: curve.h:377
void RangesMatchingSign(const Range &x_limits, const float sign, RangeArray *matching) const
Definition: curve.h:254
float EpsilonInRange(const float max_x) const
Definition: curve.h:180
void ShiftLeft(const float x_shift)
void RangesAboveZero(const Range &x_limits, RangeArray *matching) const
Return the ranges on which the quadratic is above zero.
Definition: curve.h:260
bool operator==(const QuadraticCurve &rhs) const
Equality. Checks for exact match. Useful for testing.
float Epsilon(const float x) const
Definition: curve.h:192
void ShiftRight(const float x_shift)
Shift the curve along the x-axis: x_shift to the right.
Definition: curve.h:374
std::string Text() const
A string with the equation for this quadratic. Useful for debugging.
void ShiftRight(const float x_shift)
Shift the curve along the x-axis: x_shift to the right.
Definition: curve.h:136
float EpsilonOfCoefficients() const
Definition: curve.h:188
Represent an interval on a number line.
Definition: range.h:37