Qt 4.8
Classes | Functions
qstroker.cpp File Reference
#include "private/qstroker_p.h"
#include "private/qbezier_p.h"
#include "private/qmath_p.h"
#include "qline.h"
#include "qtransform.h"
#include <qmath.h>

Go to the source code of this file.

Classes

class  QSubpathBackwardIterator
 
class  QSubpathFlatIterator
 
class  QSubpathForwardIterator
 

Functions

static qreal adapted_angle_on_x (const QLineF &line)
 
static bool lineIntersectsRect (qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
 
static bool lineRectIntersectsRect (qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
 
static void qdashstroker_cubicTo (qfixed, qfixed, qfixed, qfixed, qfixed, qfixed, void *)
 
static void qdashstroker_lineTo (qfixed x, qfixed y, void *data)
 
static void qdashstroker_moveTo (qfixed x, qfixed y, void *data)
 
QPointF qt_curves_for_arc (const QRectF &rect, qreal startAngle, qreal sweepLength, QPointF *curves, int *point_count)
 Creates a number of curves for a given arc definition. More...
 
Q_GUI_EXPORT void qt_find_ellipse_coords (const QRectF &r, qreal angle, qreal length, QPointF *startPoint, QPointF *endPoint)
 
template<class Iterator >
bool qt_stroke_side (Iterator *it, QStroker *stroker, bool capFirst, QLineF *startTangent)
 
qreal qt_t_for_arc_angle (qreal angle)
 

Function Documentation

◆ adapted_angle_on_x()

static qreal adapted_angle_on_x ( const QLineF line)
inlinestatic

Definition at line 182 of file qstroker.cpp.

Referenced by QStroker::joinPoints().

183 {
184  qreal angle = line.angle(QLineF(0, 0, 1, 0));
185  if (line.dy() > 0)
186  angle = 360 - angle;
187  return angle;
188 }
double qreal
Definition: qglobal.h:1193
qreal dy() const
Returns the vertical component of the line&#39;s vector.
Definition: qline.h:329
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
qreal angle() const
Returns the angle of the line in degrees.
Definition: qline.cpp:719
qreal angle(const QPointF &p1, const QPointF &p2)

◆ lineIntersectsRect()

static bool lineIntersectsRect ( qfixed2d  p1,
qfixed2d  p2,
const qfixed2d tl,
const qfixed2d br 
)
static

Definition at line 1069 of file qstroker.cpp.

Referenced by QDashStroker::processCurrentSubpath().

1070 {
1071  if (!lineRectIntersectsRect(p1, p2, tl, br))
1072  return false;
1073  if (p1.x == p2.x || p1.y == p2.y)
1074  return true;
1075 
1076  if (p1.y > p2.y)
1077  qSwap(p1, p2); // make p1 above p2
1078  qfixed2d u;
1079  qfixed2d v;
1080  qfixed2d w = {p2.x - p1.x, p2.y - p1.y};
1081  if (p1.x < p2.x) {
1082  // backslash
1083  u.x = tl.x - p1.x; u.y = br.y - p1.y;
1084  v.x = br.x - p1.x; v.y = tl.y - p1.y;
1085  } else {
1086  // slash
1087  u.x = tl.x - p1.x; u.y = tl.y - p1.y;
1088  v.x = br.x - p1.x; v.y = br.y - p1.y;
1089  }
1090 #if defined(QFIXED_IS_26_6) || defined(QFIXED_IS_16_16)
1091  qint64 val1 = qint64(u.x) * qint64(w.y) - qint64(u.y) * qint64(w.x);
1092  qint64 val2 = qint64(v.x) * qint64(w.y) - qint64(v.y) * qint64(w.x);
1093  return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
1094 #elif defined(QFIXED_IS_32_32)
1095  // Cannot do proper test because it may overflow.
1096  return true;
1097 #else
1098  qreal val1 = u.x * w.y - u.y * w.x;
1099  qreal val2 = v.x * w.y - v.y * w.x;
1100  return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
1101 #endif
1102 }
double qreal
Definition: qglobal.h:1193
quint16 u
qfixed x
Definition: qstroker_p.h:105
qfixed y
Definition: qstroker_p.h:106
__int64 qint64
Definition: qglobal.h:942
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
static bool lineRectIntersectsRect(qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
Definition: qstroker.cpp:1062

◆ lineRectIntersectsRect()

static bool lineRectIntersectsRect ( qfixed2d  p1,
qfixed2d  p2,
const qfixed2d tl,
const qfixed2d br 
)
inlinestatic

Definition at line 1062 of file qstroker.cpp.

Referenced by lineIntersectsRect(), and QDashStroker::processCurrentSubpath().

1063 {
1064  return ((p1.x > tl.x || p2.x > tl.x) && (p1.x < br.x || p2.x < br.x)
1065  && (p1.y > tl.y || p2.y > tl.y) && (p1.y < br.y || p2.y < br.y));
1066 }
qfixed x
Definition: qstroker_p.h:105
qfixed y
Definition: qstroker_p.h:106

◆ qdashstroker_cubicTo()

static void qdashstroker_cubicTo ( qfixed  ,
qfixed  ,
qfixed  ,
qfixed  ,
qfixed  ,
qfixed  ,
void *   
)
inlinestatic

Definition at line 1015 of file qstroker.cpp.

Referenced by QDashStroker::QDashStroker().

1015  {
1016  Q_ASSERT(0);
1017 // ((QStroker *) data)->cubicTo(c1x, c1y, c2x, c2y, ex, ey);
1018 }
#define Q_ASSERT(cond)
Definition: qglobal.h:1823

◆ qdashstroker_lineTo()

static void qdashstroker_lineTo ( qfixed  x,
qfixed  y,
void *  data 
)
inlinestatic

Definition at line 1011 of file qstroker.cpp.

Referenced by QDashStroker::QDashStroker().

1011  {
1012  ((QStroker *) data)->lineTo(x, y);
1013 }
static const char * data(const QByteArray &arr)

◆ qdashstroker_moveTo()

static void qdashstroker_moveTo ( qfixed  x,
qfixed  y,
void *  data 
)
inlinestatic

Definition at line 1007 of file qstroker.cpp.

Referenced by QDashStroker::QDashStroker().

1007  {
1008  ((QStroker *) data)->moveTo(x, y);
1009 }
static const char * data(const QByteArray &arr)

◆ qt_curves_for_arc()

QPointF qt_curves_for_arc ( const QRectF rect,
qreal  startAngle,
qreal  sweepLength,
QPointF curves,
int *  point_count 
)

Creates a number of curves for a given arc definition.

Warning
This function is not part of the public interface.

The arc is defined an arc along the ellipses that fits into rect starting at startAngle and an arc length of sweepLength.

The function has three out parameters. The return value is the starting point of the arc. The curves array represents the list of cubicTo elements up to a maximum of point_count. There are of course 3 points pr curve.

Definition at line 859 of file qstroker.cpp.

Referenced by QPainterPath::addEllipse(), QPainterPath::arcTo(), QPaintEngineEx::drawEllipse(), QStroker::joinPoints(), and QStrokerOps::strokeEllipse().

861 {
862  Q_ASSERT(point_count);
863  Q_ASSERT(curves);
864 
865  *point_count = 0;
866  if (qt_is_nan(rect.x()) || qt_is_nan(rect.y()) || qt_is_nan(rect.width()) || qt_is_nan(rect.height())
867  || qt_is_nan(startAngle) || qt_is_nan(sweepLength)) {
868  qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN, results are undefined");
869  return QPointF();
870  }
871 
872  if (rect.isNull()) {
873  return QPointF();
874  }
875 
876  qreal x = rect.x();
877  qreal y = rect.y();
878 
879  qreal w = rect.width();
880  qreal w2 = rect.width() / 2;
881  qreal w2k = w2 * QT_PATH_KAPPA;
882 
883  qreal h = rect.height();
884  qreal h2 = rect.height() / 2;
885  qreal h2k = h2 * QT_PATH_KAPPA;
886 
887  QPointF points[16] =
888  {
889  // start point
890  QPointF(x + w, y + h2),
891 
892  // 0 -> 270 degrees
893  QPointF(x + w, y + h2 + h2k),
894  QPointF(x + w2 + w2k, y + h),
895  QPointF(x + w2, y + h),
896 
897  // 270 -> 180 degrees
898  QPointF(x + w2 - w2k, y + h),
899  QPointF(x, y + h2 + h2k),
900  QPointF(x, y + h2),
901 
902  // 180 -> 90 degrees
903  QPointF(x, y + h2 - h2k),
904  QPointF(x + w2 - w2k, y),
905  QPointF(x + w2, y),
906 
907  // 90 -> 0 degrees
908  QPointF(x + w2 + w2k, y),
909  QPointF(x + w, y + h2 - h2k),
910  QPointF(x + w, y + h2)
911  };
912 
913  if (sweepLength > 360) sweepLength = 360;
914  else if (sweepLength < -360) sweepLength = -360;
915 
916  // Special case fast paths
917  if (startAngle == 0.0) {
918  if (sweepLength == 360.0) {
919  for (int i = 11; i >= 0; --i)
920  curves[(*point_count)++] = points[i];
921  return points[12];
922  } else if (sweepLength == -360.0) {
923  for (int i = 1; i <= 12; ++i)
924  curves[(*point_count)++] = points[i];
925  return points[0];
926  }
927  }
928 
929  int startSegment = int(qFloor(startAngle / 90));
930  int endSegment = int(qFloor((startAngle + sweepLength) / 90));
931 
932  qreal startT = (startAngle - startSegment * 90) / 90;
933  qreal endT = (startAngle + sweepLength - endSegment * 90) / 90;
934 
935  int delta = sweepLength > 0 ? 1 : -1;
936  if (delta < 0) {
937  startT = 1 - startT;
938  endT = 1 - endT;
939  }
940 
941  // avoid empty start segment
942  if (qFuzzyIsNull(startT - qreal(1))) {
943  startT = 0;
944  startSegment += delta;
945  }
946 
947  // avoid empty end segment
948  if (qFuzzyIsNull(endT)) {
949  endT = 1;
950  endSegment -= delta;
951  }
952 
953  startT = qt_t_for_arc_angle(startT * 90);
954  endT = qt_t_for_arc_angle(endT * 90);
955 
956  const bool splitAtStart = !qFuzzyIsNull(startT);
957  const bool splitAtEnd = !qFuzzyIsNull(endT - qreal(1));
958 
959  const int end = endSegment + delta;
960 
961  // empty arc?
962  if (startSegment == end) {
963  const int quadrant = 3 - ((startSegment % 4) + 4) % 4;
964  const int j = 3 * quadrant;
965  return delta > 0 ? points[j + 3] : points[j];
966  }
967 
968  QPointF startPoint, endPoint;
969  qt_find_ellipse_coords(rect, startAngle, sweepLength, &startPoint, &endPoint);
970 
971  for (int i = startSegment; i != end; i += delta) {
972  const int quadrant = 3 - ((i % 4) + 4) % 4;
973  const int j = 3 * quadrant;
974 
975  QBezier b;
976  if (delta > 0)
977  b = QBezier::fromPoints(points[j + 3], points[j + 2], points[j + 1], points[j]);
978  else
979  b = QBezier::fromPoints(points[j], points[j + 1], points[j + 2], points[j + 3]);
980 
981  // empty arc?
982  if (startSegment == endSegment && qFuzzyCompare(startT, endT))
983  return startPoint;
984 
985  if (i == startSegment) {
986  if (i == endSegment && splitAtEnd)
987  b = b.bezierOnInterval(startT, endT);
988  else if (splitAtStart)
989  b = b.bezierOnInterval(startT, 1);
990  } else if (i == endSegment && splitAtEnd) {
991  b = b.bezierOnInterval(0, endT);
992  }
993 
994  // push control points
995  curves[(*point_count)++] = b.pt2();
996  curves[(*point_count)++] = b.pt3();
997  curves[(*point_count)++] = b.pt4();
998  }
999 
1000  Q_ASSERT(*point_count > 0);
1001  curves[*(point_count)-1] = endPoint;
1002 
1003  return startPoint;
1004 }
QPointF pt4() const
Definition: qbezier_p.h:97
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
double qreal
Definition: qglobal.h:1193
int qFloor(qreal v)
Definition: qmath.h:73
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
static bool qt_is_nan(double d)
Definition: qnumeric_p.h:183
#define QT_PATH_KAPPA
Definition: qstroker_p.h:113
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static QBezier fromPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
Definition: qbezier.cpp:71
qreal qt_t_for_arc_angle(qreal angle)
Definition: qstroker.cpp:796
QBezier bezierOnInterval(qreal t0, qreal t1) const
Definition: qbezier.cpp:687
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
Q_CORE_EXPORT void qWarning(const char *,...)
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
Q_GUI_EXPORT void qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length, QPointF *startPoint, QPointF *endPoint)
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
QPointF pt2() const
Definition: qbezier_p.h:95
QPointF pt3() const
Definition: qbezier_p.h:96
bool qFuzzyCompare(const QMatrix &m1, const QMatrix &m2)
The qFuzzyCompare function is for comparing two matrices using a fuzziness factor.
Definition: qmatrix.h:172
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
static const KeyPair *const end
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:655

◆ qt_find_ellipse_coords()

Q_GUI_EXPORT void qt_find_ellipse_coords ( const QRectF r,
qreal  angle,
qreal  length,
QPointF startPoint,
QPointF endPoint 
)

Definition at line 97 of file qpainterpath.cpp.

Referenced by QPainterPath::arcMoveTo(), qt_curves_for_arc(), and qt_t_for_arc_angle().

99 {
100  if (r.isNull()) {
101  if (startPoint)
102  *startPoint = QPointF();
103  if (endPoint)
104  *endPoint = QPointF();
105  return;
106  }
107 
108  qreal w2 = r.width() / 2;
109  qreal h2 = r.height() / 2;
110 
111  qreal angles[2] = { angle, angle + length };
112  QPointF *points[2] = { startPoint, endPoint };
113 
114  for (int i = 0; i < 2; ++i) {
115  if (!points[i])
116  continue;
117 
118  qreal theta = angles[i] - 360 * qFloor(angles[i] / 360);
119  qreal t = theta / 90;
120  // truncate
121  int quadrant = int(t);
122  t -= quadrant;
123 
124  t = qt_t_for_arc_angle(90 * t);
125 
126  // swap x and y?
127  if (quadrant & 1)
128  t = 1 - t;
129 
130  qreal a, b, c, d;
131  QBezier::coefficients(t, a, b, c, d);
132  QPointF p(a + b + c*QT_PATH_KAPPA, d + c + b*QT_PATH_KAPPA);
133 
134  // left quadrants
135  if (quadrant == 1 || quadrant == 2)
136  p.rx() = -p.x();
137 
138  // top quadrants
139  if (quadrant == 0 || quadrant == 1)
140  p.ry() = -p.y();
141 
142  *points[i] = r.center() + QPointF(w2 * p.x(), h2 * p.y());
143  }
144 }
double d
Definition: qnumeric_p.h:62
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
int qFloor(qreal v)
Definition: qmath.h:73
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
static void coefficients(qreal t, qreal &a, qreal &b, qreal &c, qreal &d)
Definition: qbezier_p.h:152
#define QT_PATH_KAPPA
Definition: qstroker_p.h:113
long ASN1_INTEGER_get ASN1_INTEGER * a
qreal qt_t_for_arc_angle(qreal angle)
Definition: qstroker.cpp:796
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 angle(const QPointF &p1, const QPointF &p2)
QPointF center() const
Returns the center point of the rectangle.
Definition: qrect.h:686
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:655

◆ qt_stroke_side()

template<class Iterator >
bool qt_stroke_side ( Iterator it,
QStroker stroker,
bool  capFirst,
QLineF startTangent 
)

Definition at line 635 of file qstroker.cpp.

Referenced by QStroker::processCurrentSubpath().

639 {
640  // Used in CurveToElement section below.
641  const int MAX_OFFSET = 16;
642  QBezier offsetCurves[MAX_OFFSET];
643 
644  Q_ASSERT(it->hasNext()); // The initaial move to
645  QStrokerOps::Element first_element = it->next();
646  Q_ASSERT(first_element.isMoveTo());
647 
648  qfixed2d start = first_element;
649 
650 #ifdef QPP_STROKE_DEBUG
651  qDebug(" -> (side) [%.2f, %.2f], startPos=%d",
652  qt_fixed_to_real(start.x),
653  qt_fixed_to_real(start.y));
654 #endif
655 
656  qfixed2d prev = start;
657 
658  bool first = true;
659 
660  qfixed offset = stroker->strokeWidth() / 2;
661 
662  while (it->hasNext()) {
663  QStrokerOps::Element e = it->next();
664 
665  // LineToElement
666  if (e.isLineTo()) {
667 #ifdef QPP_STROKE_DEBUG
668  qDebug("\n ---> (side) lineto [%.2f, %.2f]", e.x, e.y);
669 #endif
670  QLineF line(qt_fixed_to_real(prev.x), qt_fixed_to_real(prev.y),
672  if (line.p1() != line.p2()) {
673  QLineF normal = line.normalVector();
674  normal.setLength(offset);
675  line.translate(normal.dx(), normal.dy());
676 
677  // If we are starting a new subpath, move to correct starting point.
678  if (first) {
679  if (capFirst)
680  stroker->joinPoints(prev.x, prev.y, line, stroker->capStyleMode());
681  else
682  stroker->emitMoveTo(qt_real_to_fixed(line.x1()), qt_real_to_fixed(line.y1()));
683  *startTangent = line;
684  first = false;
685  } else {
686  stroker->joinPoints(prev.x, prev.y, line, stroker->joinStyleMode());
687  }
688 
689  // Add the stroke for this line.
690  stroker->emitLineTo(qt_real_to_fixed(line.x2()),
691  qt_real_to_fixed(line.y2()));
692  prev = e;
693  }
694 
695  // CurveToElement
696  } else if (e.isCurveTo()) {
697  QStrokerOps::Element cp2 = it->next(); // control point 2
698  QStrokerOps::Element ep = it->next(); // end point
699 
700 #ifdef QPP_STROKE_DEBUG
701  qDebug("\n ---> (side) cubicTo [%.2f, %.2f]",
702  qt_fixed_to_real(ep.x),
703  qt_fixed_to_real(ep.y));
704 #endif
705 
706  QBezier bezier =
711 
712  int count = bezier.shifted(offsetCurves,
713  MAX_OFFSET,
714  offset,
715  stroker->curveThreshold());
716 
717  if (count) {
718  // If we are starting a new subpath, move to correct starting point
719  QLineF tangent = bezier.startTangent();
720  tangent.translate(offsetCurves[0].pt1() - bezier.pt1());
721  if (first) {
722  QPointF pt = offsetCurves[0].pt1();
723  if (capFirst) {
724  stroker->joinPoints(prev.x, prev.y,
725  tangent,
726  stroker->capStyleMode());
727  } else {
728  stroker->emitMoveTo(qt_real_to_fixed(pt.x()),
729  qt_real_to_fixed(pt.y()));
730  }
731  *startTangent = tangent;
732  first = false;
733  } else {
734  stroker->joinPoints(prev.x, prev.y,
735  tangent,
736  stroker->joinStyleMode());
737  }
738 
739  // Add these beziers
740  for (int i=0; i<count; ++i) {
741  QPointF cp1 = offsetCurves[i].pt2();
742  QPointF cp2 = offsetCurves[i].pt3();
743  QPointF ep = offsetCurves[i].pt4();
744  stroker->emitCubicTo(qt_real_to_fixed(cp1.x()), qt_real_to_fixed(cp1.y()),
745  qt_real_to_fixed(cp2.x()), qt_real_to_fixed(cp2.y()),
746  qt_real_to_fixed(ep.x()), qt_real_to_fixed(ep.y()));
747  }
748  }
749 
750  prev = ep;
751  }
752  }
753 
754  if (start == prev) {
755  // closed subpath, join first and last point
756 #ifdef QPP_STROKE_DEBUG
757  qDebug("\n ---> (side) closed subpath");
758 #endif
759  // don't join empty subpaths
760  if (!first)
761  stroker->joinPoints(prev.x, prev.y, *startTangent, stroker->joinStyleMode());
762  return true;
763  } else {
764 #ifdef QPP_STROKE_DEBUG
765  qDebug("\n ---> (side) open subpath");
766 #endif
767  return false;
768  }
769 }
QPointF pt4() const
Definition: qbezier_p.h:97
qfixed strokeWidth() const
Definition: qstroker_p.h:213
#define qt_real_to_fixed(real)
Definition: qstroker_p.h:101
QLineF startTangent() const
Definition: qbezier_p.h:132
#define it(className, varName)
void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey)
Definition: qstroker_p.h:354
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
LineJoinMode capStyleMode() const
Definition: qstroker_p.h:217
qreal dy() const
Returns the vertical component of the line&#39;s vector.
Definition: qline.h:329
QPointF pt1() const
Definition: qbezier_p.h:94
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
void emitMoveTo(qfixed x, qfixed y)
Definition: qstroker_p.h:336
int shifted(QBezier *curveSegments, int maxSegmets, qreal offset, float threshold) const
Definition: qbezier.cpp:433
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
bool isLineTo() const
Definition: qstroker_p.h:139
Q_CORE_EXPORT void qDebug(const char *,...)
static QBezier fromPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
Definition: qbezier.cpp:71
void translate(const QPointF &p)
Translates this line by the given offset.
Definition: qline.h:339
qfixed x
Definition: qstroker_p.h:105
LineJoinMode joinStyleMode() const
Definition: qstroker_p.h:221
void setLength(qreal len)
Sets the length of the line to the given length.
Definition: qline.h:360
qfixed y
Definition: qstroker_p.h:106
qreal dx() const
Returns the horizontal component of the line&#39;s vector.
Definition: qline.h:324
qfixed curveThreshold() const
Definition: qstroker_p.h:175
void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join)
Definition: qstroker.cpp:442
#define qt_fixed_to_real(fixed)
Definition: qstroker_p.h:102
QPointF pt2() const
Definition: qbezier_p.h:95
QPointF pt3() const
Definition: qbezier_p.h:96
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
bool isCurveTo() const
Definition: qstroker_p.h:140
QLineF normalVector() const
Returns a line that is perpendicular to this line with the same starting point and length...
Definition: qline.h:334
void emitLineTo(qfixed x, qfixed y)
Definition: qstroker_p.h:345
qreal qfixed
Definition: qstroker_p.h:100

◆ qt_t_for_arc_angle()

qreal qt_t_for_arc_angle ( qreal  angle)
Warning
This function is not part of the public interface.

For a given angle in the range [0 .. 90], finds the corresponding parameter t of the prototype cubic bezier arc segment b = fromPoints(QPointF(1, 0), QPointF(1, KAPPA), QPointF(KAPPA, 1), QPointF(0, 1));

From the bezier equation: b.pointAt(t).x() = (1-t)^3 + t*(1-t)^2 + t^2*(1-t)*KAPPA b.pointAt(t).y() = t*(1-t)^2 * KAPPA + t^2*(1-t) + t^3

Third degree coefficients: b.pointAt(t).x() = at^3 + bt^2 + ct + d where a = 2-3*KAPPA, b = 3*(KAPPA-1), c = 0, d = 1

b.pointAt(t).y() = at^3 + bt^2 + ct + d where a = 3*KAPPA-2, b = 6*KAPPA+3, c = 3*KAPPA, d = 0

Newton's method to find the zero of a function: given a function f(x) and initial guess x_0 x_1 = f(x_0) / f'(x_0) x_2 = f(x_1) / f'(x_1) etc...

Definition at line 796 of file qstroker.cpp.

Referenced by qt_curves_for_arc(), and qt_find_ellipse_coords().

797 {
798  if (qFuzzyIsNull(angle))
799  return 0;
800 
801  if (qFuzzyCompare(angle, qreal(90)))
802  return 1;
803 
804  qreal radians = Q_PI * angle / 180;
805  qreal cosAngle = qCos(radians);
806  qreal sinAngle = qSin(radians);
807 
808  // initial guess
809  qreal tc = angle / 90;
810  // do some iterations of newton's method to approximate cosAngle
811  // finds the zero of the function b.pointAt(tc).x() - cosAngle
812  tc -= ((((2-3*QT_PATH_KAPPA) * tc + 3*(QT_PATH_KAPPA-1)) * tc) * tc + 1 - cosAngle) // value
813  / (((6-9*QT_PATH_KAPPA) * tc + 6*(QT_PATH_KAPPA-1)) * tc); // derivative
814  tc -= ((((2-3*QT_PATH_KAPPA) * tc + 3*(QT_PATH_KAPPA-1)) * tc) * tc + 1 - cosAngle) // value
815  / (((6-9*QT_PATH_KAPPA) * tc + 6*(QT_PATH_KAPPA-1)) * tc); // derivative
816 
817  // initial guess
818  qreal ts = tc;
819  // do some iterations of newton's method to approximate sinAngle
820  // finds the zero of the function b.pointAt(tc).y() - sinAngle
821  ts -= ((((3*QT_PATH_KAPPA-2) * ts - 6*QT_PATH_KAPPA + 3) * ts + 3*QT_PATH_KAPPA) * ts - sinAngle)
822  / (((9*QT_PATH_KAPPA-6) * ts + 12*QT_PATH_KAPPA - 6) * ts + 3*QT_PATH_KAPPA);
823  ts -= ((((3*QT_PATH_KAPPA-2) * ts - 6*QT_PATH_KAPPA + 3) * ts + 3*QT_PATH_KAPPA) * ts - sinAngle)
824  / (((9*QT_PATH_KAPPA-6) * ts + 12*QT_PATH_KAPPA - 6) * ts + 3*QT_PATH_KAPPA);
825 
826  // use the average of the t that best approximates cosAngle
827  // and the t that best approximates sinAngle
828  qreal t = 0.5 * (tc + ts);
829 
830 #if 0
831  printf("angle: %f, t: %f\n", angle, t);
832  qreal a, b, c, d;
833  bezierCoefficients(t, a, b, c, d);
834  printf("cosAngle: %.10f, value: %.10f\n", cosAngle, a + b + c * QT_PATH_KAPPA);
835  printf("sinAngle: %.10f, value: %.10f\n", sinAngle, b * QT_PATH_KAPPA + c + d);
836 #endif
837 
838  return t;
839 }
double d
Definition: qnumeric_p.h:62
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_PATH_KAPPA
Definition: qstroker_p.h:113
long ASN1_INTEGER_get ASN1_INTEGER * a
qreal qSin(qreal v)
Definition: qmath.h:93
qreal angle(const QPointF &p1, const QPointF &p2)
bool qFuzzyCompare(const QMatrix &m1, const QMatrix &m2)
The qFuzzyCompare function is for comparing two matrices using a fuzziness factor.
Definition: qmatrix.h:172
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
qreal qCos(qreal v)
Definition: qmath.h:109
static const qreal Q_PI
Definition: qmath_p.h:61