86 qreal dx = (
p1.x() -
p2.x());
87 qreal dy = (
p1.y() -
p2.y());
88 return sqrt(dx*dx + dy*dy);
94 FitVector tHat1(points.at(end + 1), points.at(end));
103 FitVector tHat1(points.at(end - 1), points.at(end));
120 u =
new qreal[(last-first+1)];
123 for (i = first + 1; i <= last; ++i) {
124 u[i-first] =
u[i-first-1] +
125 distance(points.at(i), points.at(i - 1));
128 qreal denominator =
u[last-first];
133 for (i = first + 1; i <= last; ++i) {
134 u[i-first] =
u[i-first] / denominator;
149 result.
m_X =
v.m_X * s; result.
m_Y =
v.m_Y * s;
164 FitVector cpointb(points.at(center - 1));
166 FitVector cpointa(points.at(center + 1));
170 tHatCenter.
m_X = ((V1.
m_X + V2.
m_X) / 2.0);
171 tHatCenter.
m_Y = ((V1.
m_Y + V2.
m_Y) / 2.0);
196 return (3 *
u *
u *
tmp);
223 curve =
new QPointF[4];
224 nPts = last - first + 1;
231 for (i = 0; i < nPts; ++i) {
249 for (i = 0; i < nPts; ++i) {
250 C[0][0] += (
A[i][0]).dot(
A[i][0]);
251 C[0][1] +=
A[i][0].dot(
A[i][1]);
254 C[1][1] +=
A[i][1].dot(
A[i][1]);
256 FitVector vfirstp1(points.at(first + i));
270 X[0] +=
A[i][0].dot(
tmp);
271 X[1] +=
A[i][1].dot(
tmp);
275 det_C0_C1 =
C[0][0] *
C[1][1] -
C[1][0] *
C[0][1];
276 det_C0_X =
C[0][0] * X[1] -
C[0][1] * X[0];
277 det_X_C1 = X[0] *
C[1][1] - X[1] *
C[0][1];
281 det_C0_C1 = (
C[0][0] *
C[1][1]) * 10e-12;
286 alpha_l = det_X_C1 / det_C0_C1;
287 alpha_r = det_C0_X / det_C0_C1;
293 if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
294 qreal dist =
distance(points.at(last), points.at(first)) / 3.0;
296 curve[0] = points.at(first);
297 curve[3] = points.at(last);
302 curve[1] = tHat1 + curve[0];
303 curve[2] = tHat2 + curve[3];
311 curve[0] = points.at(first);
312 curve[3] = points.at(last);
314 tHat1.
scale(alpha_l);
315 tHat2.
scale(alpha_r);
317 curve[1] = tHat1 + curve[0];
318 curve[2] = tHat2 + curve[3];
328static QPointF
BezierII(
int degree, QPointF *V, qreal t)
334 Vtemp =
new QPointF[degree+1];
336 for (i = 0; i <= degree; ++i) {
341 for (i = 1; i <= degree; ++i) {
342 for (j = 0; j <= degree - i; ++j) {
343 Vtemp[j].setX((1.0 - t) * Vtemp[j].x() + t * Vtemp[j+1].x());
344 Vtemp[j].setY((1.0 - t) * Vtemp[j].y() + t * Vtemp[j+1].y());
366 *splitPoint = (last - first + 1) / 2;
368 for (i = first + 1; i < last; ++i) {
372 if (dist >= maxDist) {
387 qreal numerator, denominator;
388 QPointF Q1[3], Q2[2];
389 QPointF Q_u, Q1_u, Q2_u;
397 for (i = 0; i <= 2; ++i) {
398 Q1[i].setX((
Q[i+1].x() -
Q[i].x()) * 3.0);
399 Q1[i].setY((
Q[i+1].y() -
Q[i].y()) * 3.0);
403 for (i = 0; i <= 1; ++i) {
404 Q2[i].setX((Q1[i+1].x() - Q1[i].x()) * 2.0);
405 Q2[i].setY((Q1[i+1].y() - Q1[i].y()) * 2.0);
413 numerator = (Q_u.x() -
P.x()) * (Q1_u.x()) + (Q_u.y() -
P.y()) * (Q1_u.y());
414 denominator = (Q1_u.x()) * (Q1_u.x()) + (Q1_u.y()) * (Q1_u.y()) +
415 (Q_u.x() -
P.x()) * (Q2_u.x()) + (Q_u.y() -
P.y()) * (Q2_u.y());
422 uPrime =
u - (numerator / denominator);
434 int nPts = last - first + 1;
438 uPrime =
new qreal[nPts];
439 for (i = first; i <= last; ++i) {
452 qreal iterationError;
453 int maxIterations = 4;
461 iterationError = error * error;
462 nPts = last - first + 1;
465 qreal dist =
distance(points.at(last), points.at(first)) / 3.0;
467 curve =
new QPointF[4];
469 curve[0] = points.at(first);
470 curve[3] = points.at(last);
475 curve[1] = tHat1 + curve[0];
476 curve[2] = tHat2 + curve[3];
489 if (maxError < error) {
498 if (maxError < iterationError) {
499 for (i = 0; i < maxIterations; ++i) {
502 curve =
GenerateBezier(points, first, last, uPrime, tHat1, tHat2);
504 curve, uPrime, &splitPoint);
505 if (maxError < error) {
522 QPointF *cu1 = 0, *cu2 = 0;
523 cu1 =
FitCubic(points, first, splitPoint, tHat1, tHatCenter, error, w1);
526 cu2 =
FitCubic(points, splitPoint, last, tHatCenter, tHat2, error, w2);
528 QPointF *newcurve =
new QPointF[w1+w2];
529 for (
int i = 0; i < w1; ++i) {
530 newcurve[i] = cu1[i];
532 for (
int i = 0; i < w2; ++i) {
533 newcurve[i+w1] = cu2[i];
552 curve =
FitCubic(points, 0, points.count() - 1, tHat1, tHat2, error, width);
557 path->moveTo(curve[0]);
558 path->curveTo(curve[1], curve[2], curve[3]);
559 for (
int i = 4; i < width; i += 4) {
560 path->curveTo(curve[i+1], curve[i+2], curve[i+3]);
Eigen::Matrix< double, 4, 2 > Q
KoPathShape * bezierFit(const QList< QPointF > &points, float error)
FitVector ComputeLeftTangent(const QList< QPointF > &points, int end)
static FitVector VectorSub(FitVector a, FitVector b)
static FitVector VectorScale(FitVector v, qreal s)
static qreal * Reparameterize(const QList< QPointF > &points, int first, int last, qreal *u, QPointF *curve)
QPointF * GenerateBezier(const QList< QPointF > &points, int first, int last, qreal *uPrime, FitVector tHat1, FitVector tHat2)
FitVector ComputeRightTangent(const QList< QPointF > &points, int end)
const qreal Zero
our equivalent to zero
static FitVector ComputeCenterTangent(const QList< QPointF > &points, int center)
static QPointF BezierII(int degree, QPointF *V, qreal t)
static qreal ComputeMaxError(const QList< QPointF > &points, int first, int last, QPointF *curve, qreal *u, int *splitPoint)
QPointF * FitCubic(const QList< QPointF > &points, int first, int last, FitVector tHat1, FitVector tHat2, float error, int &width)
static qreal * ChordLengthParameterize(const QList< QPointF > &points, int first, int last)
qreal distance(const QPointF &p1, const QPointF &p2)
static FitVector VectorAdd(FitVector a, FitVector b)
static qreal NewtonRaphsonRootFind(QPointF *Q, QPointF P, qreal u)
FitVector(const QPointF &a, const QPointF &b)
FitVector(const QPointF &p)
QPointF operator+(const QPointF &p)
qreal dot(const FitVector &v) const
The position of a path point within a path shape.
static bool qFuzzyCompare(half p1, half p2)