Qt 4.8
Macros | Enumerations | Functions
qbezier.cpp File Reference
#include "qbezier_p.h"
#include <qdebug.h>
#include <qline.h>
#include <qpolygon.h>
#include <qvector.h>
#include <qlist.h>
#include <qmath.h>
#include <private/qnumeric_p.h>
#include <private/qmath_p.h>

Go to the source code of this file.

Macros

#define INV_EPS   (1L<<14)
 
#define KAPPA   qreal(0.5522847498)
 
#define M_SQRT2   1.41421356237309504880
 

Enumerations

enum  ShiftResult { Ok, Discard, Split, Circle }
 

Functions

static bool addCircle (const QBezier *b, qreal offset, QBezier *o)
 
static bool findInflections (qreal a, qreal b, qreal c, qreal *t1, qreal *t2, qreal *tCups)
 
static ShiftResult good_offset (const QBezier *b1, const QBezier *b2, qreal offset, qreal threshold)
 
static int quadraticRoots (qreal a, qreal b, qreal c, qreal *x1, qreal *x2)
 
static ShiftResult shift (const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
 
static void splitBezierAt (const QBezier &bez, qreal t, QBezier *left, QBezier *right)
 

Macro Definition Documentation

◆ INV_EPS

#define INV_EPS   (1L<<14)

Definition at line 61 of file qbezier.cpp.

◆ KAPPA

#define KAPPA   qreal(0.5522847498)

◆ M_SQRT2

#define M_SQRT2   1.41421356237309504880

Definition at line 65 of file qbezier.cpp.

Enumeration Type Documentation

◆ ShiftResult

Enumerator
Ok 
Discard 
Split 
Circle 

Definition at line 258 of file qbezier.cpp.

258  {
259  Ok,
260  Discard,
261  Split,
262  Circle
263 };
Definition: qbezier.cpp:259

Function Documentation

◆ addCircle()

static bool addCircle ( const QBezier b,
qreal  offset,
QBezier o 
)
static

Definition at line 373 of file qbezier.cpp.

Referenced by QBezier::shifted().

374 {
375  QPointF normals[3];
376 
377  normals[0] = QPointF(b->y2 - b->y1, b->x1 - b->x2);
378  qreal dist = qSqrt(normals[0].x()*normals[0].x() + normals[0].y()*normals[0].y());
379  if (qFuzzyIsNull(dist))
380  return false;
381  normals[0] /= dist;
382  normals[2] = QPointF(b->y4 - b->y3, b->x3 - b->x4);
383  dist = qSqrt(normals[2].x()*normals[2].x() + normals[2].y()*normals[2].y());
384  if (qFuzzyIsNull(dist))
385  return false;
386  normals[2] /= dist;
387 
388  normals[1] = QPointF(b->x1 - b->x2 - b->x3 + b->x4, b->y1 - b->y2 - b->y3 + b->y4);
389  normals[1] /= -1*qSqrt(normals[1].x()*normals[1].x() + normals[1].y()*normals[1].y());
390 
391  qreal angles[2];
392  qreal sign = 1.;
393  for (int i = 0; i < 2; ++i) {
394  qreal cos_a = normals[i].x()*normals[i+1].x() + normals[i].y()*normals[i+1].y();
395  if (cos_a > 1.)
396  cos_a = 1.;
397  if (cos_a < -1.)
398  cos_a = -1;
399  angles[i] = qAcos(cos_a)/Q_PI;
400  }
401 
402  if (angles[0] + angles[1] > 1.) {
403  // more than 180 degrees
404  normals[1] = -normals[1];
405  angles[0] = 1. - angles[0];
406  angles[1] = 1. - angles[1];
407  sign = -1.;
408 
409  }
410 
411  QPointF circle[3];
412  circle[0] = QPointF(b->x1, b->y1) + normals[0]*offset;
413  circle[1] = QPointF(qreal(0.5)*(b->x1 + b->x4), qreal(0.5)*(b->y1 + b->y4)) + normals[1]*offset;
414  circle[2] = QPointF(b->x4, b->y4) + normals[2]*offset;
415 
416  for (int i = 0; i < 2; ++i) {
417  qreal kappa = qreal(2.0) * KAPPA * sign * offset * angles[i];
418 
419  o->x1 = circle[i].x();
420  o->y1 = circle[i].y();
421  o->x2 = circle[i].x() - normals[i].y()*kappa;
422  o->y2 = circle[i].y() + normals[i].x()*kappa;
423  o->x3 = circle[i+1].x() + normals[i+1].y()*kappa;
424  o->y3 = circle[i+1].y() - normals[i+1].x()*kappa;
425  o->x4 = circle[i+1].x();
426  o->y4 = circle[i+1].y();
427 
428  ++o;
429  }
430  return true;
431 }
double qreal
Definition: qglobal.h:1193
qreal x2
Definition: qbezier_p.h:116
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
qreal y2
Definition: qbezier_p.h:116
qreal x4
Definition: qbezier_p.h:116
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
static int sign(int x)
#define KAPPA
Definition: qbezier.cpp:370
qreal y4
Definition: qbezier_p.h:116
qreal qAcos(qreal v)
Definition: qmath.h:141
qreal x3
Definition: qbezier_p.h:116
qreal x1
Definition: qbezier_p.h:116
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
qreal y1
Definition: qbezier_p.h:116
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
qreal y3
Definition: qbezier_p.h:116
qreal qSqrt(qreal v)
Definition: qmath.h:205
static const qreal Q_PI
Definition: qmath_p.h:61

◆ findInflections()

static bool findInflections ( qreal  a,
qreal  b,
qreal  c,
qreal t1,
qreal t2,
qreal tCups 
)
inlinestatic

Definition at line 164 of file qbezier.cpp.

166 {
167  qreal r1 = 0, r2 = 0;
168 
169  short rootsCount = quadraticRoots(a, b, c, &r1, &r2);
170 
171  if (rootsCount >= 1) {
172  if (r1 < r2) {
173  *t1 = r1;
174  *t2 = r2;
175  } else {
176  *t1 = r2;
177  *t2 = r1;
178  }
179  if (!qFuzzyIsNull(a))
180  *tCups = qreal(0.5) * (-b / a);
181  else
182  *tCups = 2;
183 
184  return true;
185  }
186 
187  return false;
188 }
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
long ASN1_INTEGER_get ASN1_INTEGER * a
static int quadraticRoots(qreal a, qreal b, qreal c, qreal *x1, qreal *x2)
Definition: qbezier.cpp:133
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043

◆ good_offset()

static ShiftResult good_offset ( const QBezier b1,
const QBezier b2,
qreal  offset,
qreal  threshold 
)
static

Definition at line 265 of file qbezier.cpp.

Referenced by shift().

266 {
267  const qreal o2 = offset*offset;
268  const qreal max_dist_line = threshold*offset*offset;
269  const qreal max_dist_normal = threshold*offset;
270  const qreal spacing = qreal(0.25);
271  for (qreal i = spacing; i < qreal(0.99); i += spacing) {
272  QPointF p1 = b1->pointAt(i);
273  QPointF p2 = b2->pointAt(i);
274  qreal d = (p1.x() - p2.x())*(p1.x() - p2.x()) + (p1.y() - p2.y())*(p1.y() - p2.y());
275  if (qAbs(d - o2) > max_dist_line)
276  return Split;
277 
278  QPointF normalPoint = b1->normalVector(i);
279  qreal l = qAbs(normalPoint.x()) + qAbs(normalPoint.y());
280  if (l != qreal(0.0)) {
281  d = qAbs( normalPoint.x()*(p1.y() - p2.y()) - normalPoint.y()*(p1.x() - p2.x()) ) / l;
282  if (d > max_dist_normal)
283  return Split;
284  }
285  }
286  return Ok;
287 }
double d
Definition: qnumeric_p.h:62
double qreal
Definition: qglobal.h:1193
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
QPointF pointAt(qreal t) const
Definition: qbezier_p.h:163
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
QPointF normalVector(qreal t) const
Definition: qbezier_p.h:188
Definition: qbezier.cpp:259
QFactoryLoader * l
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287

◆ quadraticRoots()

static int quadraticRoots ( qreal  a,
qreal  b,
qreal  c,
qreal x1,
qreal x2 
)
inlinestatic

Definition at line 133 of file qbezier.cpp.

Referenced by findInflections().

135 {
136  if (qFuzzyIsNull(a)) {
137  if (qFuzzyIsNull(b))
138  return 0;
139  *x1 = *x2 = (-c / b);
140  return 1;
141  } else {
142  const qreal det = b * b - 4 * a * c;
143  if (qFuzzyIsNull(det)) {
144  *x1 = *x2 = -b / (2 * a);
145  return 1;
146  }
147  if (det > 0) {
148  if (qFuzzyIsNull(b)) {
149  *x2 = qSqrt(-c / a);
150  *x1 = -(*x2);
151  return 2;
152  }
153  const qreal stableA = b / (2 * a);
154  const qreal stableB = c / (a * stableA * stableA);
155  const qreal stableC = -1 - qSqrt(1 - stableB);
156  *x2 = stableA * stableC;
157  *x1 = (stableA * stableB) / stableC;
158  return 2;
159  } else
160  return 0;
161  }
162 }
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
long ASN1_INTEGER_get ASN1_INTEGER * a
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
qreal qSqrt(qreal v)
Definition: qmath.h:205

◆ shift()

static ShiftResult shift ( const QBezier orig,
QBezier shifted,
qreal  offset,
qreal  threshold 
)
static

Definition at line 289 of file qbezier.cpp.

Referenced by qrgb444::byte_mul(), QWSCalibratedMouseHandler::calibrate(), checksum(), QImage::mirrored(), qt_memrotate270_tiled(), qt_memrotate90_tiled(), qt_static_shift(), QBezier::shifted(), and QAxServerBase::TranslateAcceleratorW().

290 {
291  int map[4];
292  bool p1_p2_equal = (orig->x1 == orig->x2 && orig->y1 == orig->y2);
293  bool p2_p3_equal = (orig->x2 == orig->x3 && orig->y2 == orig->y3);
294  bool p3_p4_equal = (orig->x3 == orig->x4 && orig->y3 == orig->y4);
295 
296  QPointF points[4];
297  int np = 0;
298  points[np] = QPointF(orig->x1, orig->y1);
299  map[0] = 0;
300  ++np;
301  if (!p1_p2_equal) {
302  points[np] = QPointF(orig->x2, orig->y2);
303  ++np;
304  }
305  map[1] = np - 1;
306  if (!p2_p3_equal) {
307  points[np] = QPointF(orig->x3, orig->y3);
308  ++np;
309  }
310  map[2] = np - 1;
311  if (!p3_p4_equal) {
312  points[np] = QPointF(orig->x4, orig->y4);
313  ++np;
314  }
315  map[3] = np - 1;
316  if (np == 1)
317  return Discard;
318 
319  QRectF b = orig->bounds();
320  if (np == 4 && b.width() < .1*offset && b.height() < .1*offset) {
321  qreal l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) +
322  (orig->y1 - orig->y2)*(orig->y1 - orig->y1) *
323  (orig->x3 - orig->x4)*(orig->x3 - orig->x4) +
324  (orig->y3 - orig->y4)*(orig->y3 - orig->y4);
325  qreal dot = (orig->x1 - orig->x2)*(orig->x3 - orig->x4) +
326  (orig->y1 - orig->y2)*(orig->y3 - orig->y4);
327  if (dot < 0 && dot*dot < 0.8*l)
328  // the points are close and reverse dirction. Approximate the whole
329  // thing by a semi circle
330  return Circle;
331  }
332 
333  QPointF points_shifted[4];
334 
335  QLineF prev = QLineF(QPointF(), points[1] - points[0]);
336  QPointF prev_normal = prev.normalVector().unitVector().p2();
337 
338  points_shifted[0] = points[0] + offset * prev_normal;
339 
340  for (int i = 1; i < np - 1; ++i) {
341  QLineF next = QLineF(QPointF(), points[i + 1] - points[i]);
342  QPointF next_normal = next.normalVector().unitVector().p2();
343 
344  QPointF normal_sum = prev_normal + next_normal;
345 
346  qreal r = qreal(1.0) + prev_normal.x() * next_normal.x()
347  + prev_normal.y() * next_normal.y();
348 
349  if (qFuzzyIsNull(r)) {
350  points_shifted[i] = points[i] + offset * prev_normal;
351  } else {
352  qreal k = offset / r;
353  points_shifted[i] = points[i] + k * normal_sum;
354  }
355 
356  prev_normal = next_normal;
357  }
358 
359  points_shifted[np - 1] = points[np - 1] + offset * prev_normal;
360 
361  *shifted = QBezier::fromPoints(points_shifted[map[0]], points_shifted[map[1]],
362  points_shifted[map[2]], points_shifted[map[3]]);
363 
364  return good_offset(orig, shifted, offset, threshold);
365 }
double qreal
Definition: qglobal.h:1193
qreal x2
Definition: qbezier_p.h:116
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
QLineF unitVector() const
Returns the unit vector for this line, i.e a line starting at the same point as this line with a leng...
Definition: qline.cpp:786
qreal y2
Definition: qbezier_p.h:116
qreal x4
Definition: qbezier_p.h:116
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
static QBezier fromPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
Definition: qbezier.cpp:71
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
qreal y4
Definition: qbezier_p.h:116
QRectF bounds() const
Definition: qbezier.cpp:223
qreal x3
Definition: qbezier_p.h:116
QPointF p2() const
Returns the line&#39;s end point.
Definition: qline.h:319
QFactoryLoader * l
qreal x1
Definition: qbezier_p.h:116
qreal y1
Definition: qbezier_p.h:116
static ShiftResult good_offset(const QBezier *b1, const QBezier *b2, qreal offset, qreal threshold)
Definition: qbezier.cpp:265
QLineF normalVector() const
Returns a line that is perpendicular to this line with the same starting point and length...
Definition: qline.h:334
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
static qreal dot(const QPointF &a, const QPointF &b)
qreal y3
Definition: qbezier_p.h:116

◆ splitBezierAt()

static void splitBezierAt ( const QBezier bez,
qreal  t,
QBezier left,
QBezier right 
)
inlinestatic

Definition at line 501 of file qbezier.cpp.

503 {
504  left->x1 = bez.x1;
505  left->y1 = bez.y1;
506 
507  left->x2 = bez.x1 + t * ( bez.x2 - bez.x1 );
508  left->y2 = bez.y1 + t * ( bez.y2 - bez.y1 );
509 
510  left->x3 = bez.x2 + t * ( bez.x3 - bez.x2 ); // temporary holding spot
511  left->y3 = bez.y2 + t * ( bez.y3 - bez.y2 ); // temporary holding spot
512 
513  right->x3 = bez.x3 + t * ( bez.x4 - bez.x3 );
514  right->y3 = bez.y3 + t * ( bez.y4 - bez.y3 );
515 
516  right->x2 = left->x3 + t * ( right->x3 - left->x3);
517  right->y2 = left->y3 + t * ( right->y3 - left->y3);
518 
519  left->x3 = left->x2 + t * ( left->x3 - left->x2 );
520  left->y3 = left->y2 + t * ( left->y3 - left->y2 );
521 
522  left->x4 = right->x1 = left->x3 + t * (right->x2 - left->x3);
523  left->y4 = right->y1 = left->y3 + t * (right->y2 - left->y3);
524 
525  right->x4 = bez.x4;
526  right->y4 = bez.y4;
527 }
qreal x2
Definition: qbezier_p.h:116
qreal y2
Definition: qbezier_p.h:116
qreal x4
Definition: qbezier_p.h:116
qreal y4
Definition: qbezier_p.h:116
qreal x3
Definition: qbezier_p.h:116
qreal x1
Definition: qbezier_p.h:116
qreal y1
Definition: qbezier_p.h:116
qreal y3
Definition: qbezier_p.h:116