|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tcubicbezier.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI double invCubicBezierX(double x,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &a,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &aSpeed,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &bSpeed,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double aSpeedX = aSpeed.x;
|
|
Toshihiro Shimizu |
890ddd |
double bSpeedX = bSpeed.x;
|
|
Toshihiro Shimizu |
890ddd |
if (aSpeedX == 0)
|
|
Toshihiro Shimizu |
890ddd |
aSpeedX = epsilon;
|
|
Toshihiro Shimizu |
890ddd |
if (bSpeedX == 0)
|
|
Toshihiro Shimizu |
890ddd |
bSpeedX = -epsilon;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// a*u^3+b*u^2+c*u+d
|
|
Toshihiro Shimizu |
890ddd |
double x0 = a.x;
|
|
Toshihiro Shimizu |
890ddd |
double x1 = x0 + aSpeedX;
|
|
Toshihiro Shimizu |
890ddd |
double x3 = b.x;
|
|
Toshihiro Shimizu |
890ddd |
double x2 = x3 + bSpeedX;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double aX = x3 + 3 * (x1 - x2) - x0;
|
|
Toshihiro Shimizu |
890ddd |
double bX = 3 * (x2 - 2 * x1 + x0);
|
|
Toshihiro Shimizu |
890ddd |
double cX = 3 * (x1 - x0);
|
|
Toshihiro Shimizu |
890ddd |
double dX = x0 - x;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return cubicRoot(aX, bX, cX, dX);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI double getCubicBezierY(double x,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &a,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &aSpeed,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &bSpeed,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double y0 = a.y;
|
|
Toshihiro Shimizu |
890ddd |
double y1 = y0 + aSpeed.y;
|
|
Toshihiro Shimizu |
890ddd |
double y3 = b.y;
|
|
Toshihiro Shimizu |
890ddd |
double y2 = y3 + bSpeed.y;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double aY = y3 + 3 * (y1 - y2) - y0;
|
|
Toshihiro Shimizu |
890ddd |
double bY = 3 * (y2 - 2 * y1 + y0);
|
|
Toshihiro Shimizu |
890ddd |
double cY = 3 * (y1 - y0);
|
|
Toshihiro Shimizu |
890ddd |
double dY = y0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double u = invCubicBezierX(x, a, aSpeed, bSpeed, b);
|
|
Toshihiro Shimizu |
890ddd |
u = tcrop(u, 0.0, 1.0);
|
|
Toshihiro Shimizu |
890ddd |
return aY * u * u * u + bY * u * u + cY * u + dY;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DVAPI std::pair<tpointd, tpointd=""> getMinMaxCubicBezierY(const TPointD &a,</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &aSpeed,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &bSpeed,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double y0 = a.y;
|
|
Toshihiro Shimizu |
890ddd |
double y1 = y0 + aSpeed.y;
|
|
Toshihiro Shimizu |
890ddd |
double y3 = b.y;
|
|
Toshihiro Shimizu |
890ddd |
double y2 = y3 + bSpeed.y;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double aY = y3 + 3 * (y1 - y2) - y0;
|
|
Toshihiro Shimizu |
890ddd |
double bY = 3 * (y2 - 2 * y1 + y0);
|
|
Toshihiro Shimizu |
890ddd |
double cY = 3 * (y1 - y0);
|
|
Toshihiro Shimizu |
890ddd |
double dY = y0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double x0 = a.x;
|
|
Toshihiro Shimizu |
890ddd |
double x1 = x0 + aSpeed.x;
|
|
Toshihiro Shimizu |
890ddd |
double x3 = b.x;
|
|
Toshihiro Shimizu |
890ddd |
double x2 = x3 + bSpeed.x;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double aX = x3 + 3 * (x1 - x2) - x0;
|
|
Toshihiro Shimizu |
890ddd |
double bX = 3 * (x2 - 2 * x1 + x0);
|
|
Toshihiro Shimizu |
890ddd |
double cX = 3 * (x1 - x0);
|
|
Toshihiro Shimizu |
890ddd |
double dX = x0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double aaY = 3 * (y1 - y2) - y0 + y3;
|
|
Toshihiro Shimizu |
890ddd |
double bbY = 2 * (y0 + y2 - 2 * y1);
|
|
Toshihiro Shimizu |
890ddd |
double ccY = y1 - y0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (aaY == 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (a.y < b.y)
|
|
Toshihiro Shimizu |
890ddd |
return std::pair<tpointd, tpointd="">(TPointD(a.x, a.y),</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
TPointD(b.x, b.y));
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
return pair<tpointd, tpointd="">(TPointD(b.x, b.y),</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
TPointD(a.x, a.y));
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
double discr = bbY * bbY - 4 * aaY * ccY;
|
|
Toshihiro Shimizu |
890ddd |
if (discr < 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (a.y < b.y)
|
|
Toshihiro Shimizu |
890ddd |
return std::pair<tpointd, tpointd="">(TPointD(a.x, a.y),</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
TPointD(b.x, b.y));
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
return pair<tpointd, tpointd="">(TPointD(b.x, b.y),</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
TPointD(a.x, a.y));
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
double sqrt_discr = sqrt(discr);
|
|
Toshihiro Shimizu |
890ddd |
double inv_2aY = 1.0 / (2.0 * aaY);
|
|
Toshihiro Shimizu |
890ddd |
double u0 = (-bbY + sqrt_discr) * inv_2aY;
|
|
Toshihiro Shimizu |
890ddd |
double u1 = (-bbY - sqrt_discr) * inv_2aY;
|
|
Toshihiro Shimizu |
890ddd |
if (u0 > 1.0)
|
|
Toshihiro Shimizu |
890ddd |
u0 = 1.0;
|
|
Toshihiro Shimizu |
890ddd |
if (u0 < 0.0)
|
|
Toshihiro Shimizu |
890ddd |
u0 = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
if (u1 > 1.0)
|
|
Toshihiro Shimizu |
890ddd |
u1 = 1.0;
|
|
Toshihiro Shimizu |
890ddd |
if (u1 < 0.0)
|
|
Toshihiro Shimizu |
890ddd |
u1 = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
double y_0 = aY * u0 * u0 * u0 + bY * u0 * u0 + cY * u0 + dY;
|
|
Toshihiro Shimizu |
890ddd |
double y_1 = aY * u1 * u1 * u1 + bY * u1 * u1 + cY * u1 + dY;
|
|
Toshihiro Shimizu |
890ddd |
double x_0 = aX * u0 * u0 * u0 + bX * u0 * u0 + cX * u0 + dX;
|
|
Toshihiro Shimizu |
890ddd |
double x_1 = aX * u1 * u1 * u1 + bX * u1 * u1 + cX * u1 + dX;
|
|
Toshihiro Shimizu |
890ddd |
if (y_0 < y_1)
|
|
Toshihiro Shimizu |
890ddd |
return pair<tpointd, tpointd="">(TPointD(x_0, y_0), TPointD(x_1, y_1));</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
return pair<tpointd, tpointd="">(TPointD(x_1, y_1), TPointD(x_0, y_0));</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|