Qt 4.8
Classes | Public Functions | Static Public Functions | Private Functions | Properties | List of all members
QWingedEdge Class Reference

#include <qpathclipper_p.h>

Classes

struct  TraversalStatus
 

Public Functions

int addEdge (const QPointF &a, const QPointF &b)
 
int addEdge (int vertexA, int vertexB)
 
int addVertex (const QPointF &p)
 
QPathEdgeedge (int edge)
 
const QPathEdgeedge (int edge) const
 
int edgeCount () const
 
bool isInside (qreal x, qreal y) const
 
TraversalStatus next (const TraversalStatus &status) const
 
 QWingedEdge ()
 
 QWingedEdge (const QPainterPath &subject, const QPainterPath &clip)
 
void simplify ()
 
QPainterPath toPath () const
 
QPathVertexvertex (int vertex)
 
const QPathVertexvertex (int vertex) const
 
int vertexCount () const
 

Static Public Functions

static QPathEdge::Traversal flip (QPathEdge::Traversal traversal)
 
static QPathEdge::Direction flip (QPathEdge::Direction direction)
 

Private Functions

qreal delta (int vertex, int a, int b) const
 
TraversalStatus findInsertStatus (int vertex, int edge) const
 
int insert (const QPathVertex &vertex)
 
void intersectAndAdd ()
 
void printNode (int i, FILE *handle)
 
void removeEdge (int ei)
 

Properties

QDataBuffer< QPathEdgem_edges
 
QPathSegments m_segments
 
QVector< qrealm_splitPoints
 
QDataBuffer< QPathVertexm_vertices
 

Detailed Description

Definition at line 232 of file qpathclipper_p.h.

Constructors and Destructors

◆ QWingedEdge() [1/2]

QWingedEdge::QWingedEdge ( )

Definition at line 863 of file qpathclipper.cpp.

863  :
864  m_edges(0),
865  m_vertices(0),
866  m_segments(0)
867 {
868 }
QDataBuffer< QPathEdge > m_edges
QPathSegments m_segments
QDataBuffer< QPathVertex > m_vertices

◆ QWingedEdge() [2/2]

QWingedEdge::QWingedEdge ( const QPainterPath subject,
const QPainterPath clip 
)

Definition at line 870 of file qpathclipper.cpp.

870  :
871  m_edges(subject.elementCount()),
872  m_vertices(subject.elementCount()),
873  m_segments(subject.elementCount())
874 {
875  m_segments.setPath(subject);
876  m_segments.addPath(clip);
877 
878  intersectAndAdd();
879 }
void intersectAndAdd()
void setPath(const QPainterPath &path)
QDataBuffer< QPathEdge > m_edges
QPathSegments m_segments
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
QDataBuffer< QPathVertex > m_vertices
void addPath(const QPainterPath &path)

Functions

◆ addEdge() [1/2]

int QWingedEdge::addEdge ( const QPointF a,
const QPointF b 
)

Definition at line 1203 of file qpathclipper.cpp.

1204 {
1205  int fi = insert(a);
1206  int si = insert(b);
1207 
1208  return addEdge(fi, si);
1209 }
int insert(const QPathVertex &vertex)
int addEdge(const QPointF &a, const QPointF &b)

◆ addEdge() [2/2]

int QWingedEdge::addEdge ( int  vertexA,
int  vertexB 
)

Definition at line 1211 of file qpathclipper.cpp.

1212 {
1213  if (fi == si)
1214  return -1;
1215 
1216  int common = commonEdge(*this, fi, si);
1217  if (common >= 0)
1218  return common;
1219 
1220  m_edges << QPathEdge(fi, si);
1221 
1222  int ei = m_edges.size() - 1;
1223 
1224  QPathVertex *fp = vertex(fi);
1225  QPathVertex *sp = vertex(si);
1226 
1227  QPathEdge *ep = edge(ei);
1228 
1229  const QPointF tangent = QPointF(*sp) - QPointF(*fp);
1230  ep->angle = computeAngle(tangent);
1231  ep->invAngle = ep->angle + 64;
1232  if (ep->invAngle >= 128)
1233  ep->invAngle -= 128;
1234 
1235  QPathVertex *vertices[2] = { fp, sp };
1237 
1238 #ifdef QDEBUG_CLIPPER
1239  printf("** Adding edge %d / vertices: %.07f %.07f, %.07f %.07f\n", ei, fp->x, fp->y, sp->x, sp->y);
1240 #endif
1241 
1242  for (int i = 0; i < 2; ++i) {
1243  QPathVertex *vp = vertices[i];
1244  if (vp->edge < 0) {
1245  vp->edge = ei;
1246  ep->setNext(dirs[i], ei);
1247  } else {
1248  int vi = ep->vertex(dirs[i]);
1249  Q_ASSERT(vertex(vi) == vertices[i]);
1250 
1251  TraversalStatus os = findInsertStatus(vi, ei);
1252  QPathEdge *op = edge(os.edge);
1253 
1254  Q_ASSERT(vertex(op->vertex(os.direction)) == vertices[i]);
1255 
1256  TraversalStatus ns = next(os);
1257  ns.flipDirection();
1258  QPathEdge *np = edge(ns.edge);
1259 
1260  op->setNext(os.traversal, os.direction, ei);
1261  np->setNext(ns.traversal, ns.direction, ei);
1262 
1263  int oe = os.edge;
1264  int ne = ns.edge;
1265 
1266  os = next(os);
1267  ns = next(ns);
1268 
1269  os.flipDirection();
1270  ns.flipDirection();
1271 
1272  Q_ASSERT(os.edge == ei);
1273  Q_ASSERT(ns.edge == ei);
1274 
1275  ep->setNext(os.traversal, os.direction, oe);
1276  ep->setNext(ns.traversal, ns.direction, ne);
1277  }
1278  }
1279 
1280  Q_ASSERT(ep->next(QPathEdge::RightTraversal, QPathEdge::Forward) >= 0);
1282  Q_ASSERT(ep->next(QPathEdge::LeftTraversal, QPathEdge::Forward) >= 0);
1284 
1285  return ei;
1286 }
TraversalStatus findInsertStatus(int vertex, int edge) const
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
QPathVertex * vertex(int vertex)
int vertex(Direction direction) const
TraversalStatus next(const TraversalStatus &status) const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static double computeAngle(const QPointF &v)
QDataBuffer< QPathEdge > m_edges
int next(Traversal traversal, Direction direction) const
double invAngle
QPathEdge * edge(int edge)
void setNext(Traversal traversal, Direction direction, int next)
double angle
static int commonEdge(const QWingedEdge &list, int a, int b)
int size() const
Definition: qdatabuffer_p.h:83

◆ addVertex()

int QWingedEdge::addVertex ( const QPointF p)
inline

Definition at line 464 of file qpathclipper_p.h.

465 {
466  m_vertices << p;
467  return m_vertices.size() - 1;
468 }
QDataBuffer< QPathVertex > m_vertices
int size() const
Definition: qdatabuffer_p.h:83

◆ delta()

qreal QWingedEdge::delta ( int  vertex,
int  a,
int  b 
) const
private

Definition at line 1017 of file qpathclipper.cpp.

Referenced by findInsertStatus().

1018 {
1019  const QPathEdge *ap = edge(a);
1020  const QPathEdge *bp = edge(b);
1021 
1022  double a_angle = ap->angle;
1023  double b_angle = bp->angle;
1024 
1025  if (vertex == ap->second)
1026  a_angle = ap->invAngle;
1027 
1028  if (vertex == bp->second)
1029  b_angle = bp->invAngle;
1030 
1031  double result = b_angle - a_angle;
1032 
1033  if (result >= 128.)
1034  return result - 128.;
1035  else if (result < 0)
1036  return result + 128.;
1037  else
1038  return result;
1039 }
QPathVertex * vertex(int vertex)
long ASN1_INTEGER_get ASN1_INTEGER * a
double invAngle
QPathEdge * edge(int edge)
double angle

◆ edge() [1/2]

QPathEdge * QWingedEdge::edge ( int  edge)
inline

Definition at line 449 of file qpathclipper_p.h.

Referenced by add(), addEdge(), clear(), commonEdge(), delta(), QPathClipper::doClip(), findCrossings(), findInsertStatus(), QPathClipper::handleCrossingEdges(), midPoint(), next(), removeEdge(), simplify(), toPath(), and traverse().

450 {
451  return edge < 0 ? 0 : &m_edges.at(edge);
452 }
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPathEdge > m_edges
QPathEdge * edge(int edge)

◆ edge() [2/2]

const QPathEdge * QWingedEdge::edge ( int  edge) const
inline

Definition at line 454 of file qpathclipper_p.h.

455 {
456  return edge < 0 ? 0 : &m_edges.at(edge);
457 }
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPathEdge > m_edges
QPathEdge * edge(int edge)

◆ edgeCount()

int QWingedEdge::edgeCount ( ) const
inline

Definition at line 444 of file qpathclipper_p.h.

Referenced by QPathClipper::doClip(), findCrossings(), simplify(), and toPath().

445 {
446  return m_edges.size();
447 }
QDataBuffer< QPathEdge > m_edges
int size() const
Definition: qdatabuffer_p.h:83

◆ findInsertStatus()

QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus ( int  vertex,
int  edge 
) const
private

Definition at line 1051 of file qpathclipper.cpp.

Referenced by addEdge().

1052 {
1053  const QPathVertex *vp = vertex(vi);
1054 
1055  Q_ASSERT(vp);
1056  Q_ASSERT(ei >= 0);
1057  Q_ASSERT(vp->edge >= 0);
1058 
1059  int position = vp->edge;
1060  qreal d = 128.;
1061 
1062  TraversalStatus status;
1063  status.direction = edge(vp->edge)->directionTo(vi);
1064  status.traversal = QPathEdge::RightTraversal;
1065  status.edge = vp->edge;
1066 
1067 #ifdef QDEBUG_CLIPPER
1068  const QPathEdge *ep = edge(ei);
1069  qDebug() << "Finding insert status for edge" << ei << "at vertex" << QPointF(*vp) << ", angles: " << ep->angle << ep->invAngle;
1070 #endif
1071 
1072  do {
1073  status = next(status);
1074  status.flip();
1075 
1076  Q_ASSERT(edge(status.edge)->vertex(status.direction) == vi);
1077  qreal d2 = delta(vi, ei, status.edge);
1078 
1079 #ifdef QDEBUG_CLIPPER
1080  const QPathEdge *op = edge(status.edge);
1081  qDebug() << "Delta to edge" << status.edge << d2 << ", angles: " << op->angle << op->invAngle;
1082 #endif
1083 
1084  if (d2 < d) {
1085  position = status.edge;
1086  d = d2;
1087  }
1088  } while (status.edge != vp->edge);
1089 
1090  status.traversal = QPathEdge::LeftTraversal;
1091  status.direction = QPathEdge::Forward;
1092  status.edge = position;
1093 
1094  if (edge(status.edge)->vertex(status.direction) != vi)
1095  status.flip();
1096 
1097 #ifdef QDEBUG_CLIPPER
1098  qDebug() << "Inserting edge" << ei << "to" << (status.traversal == QPathEdge::LeftTraversal ? "left" : "right") << "of edge" << status.edge;
1099 #endif
1100 
1101  Q_ASSERT(edge(status.edge)->vertex(status.direction) == vi);
1102 
1103  return status;
1104 }
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
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
QPathVertex * vertex(int vertex)
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
int vertex(Direction direction) const
TraversalStatus next(const TraversalStatus &status) const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Q_CORE_EXPORT void qDebug(const char *,...)
Direction directionTo(int vertex) const
double invAngle
QPathEdge * edge(int edge)
double angle
qreal delta(int vertex, int a, int b) const

◆ flip() [1/2]

QPathEdge::Traversal QWingedEdge::flip ( QPathEdge::Traversal  traversal)
inlinestatic

◆ flip() [2/2]

QPathEdge::Direction QWingedEdge::flip ( QPathEdge::Direction  direction)
inlinestatic

Definition at line 485 of file qpathclipper_p.h.

◆ insert()

int QWingedEdge::insert ( const QPathVertex vertex)
private

Definition at line 1288 of file qpathclipper.cpp.

Referenced by addEdge().

1289 {
1290  if (!m_vertices.isEmpty()) {
1291  const QPathVertex &last = m_vertices.last();
1292  if (vertex.x == last.x && vertex.y == last.y)
1293  return m_vertices.size() - 1;
1294 
1295  for (int i = 0; i < m_vertices.size(); ++i) {
1296  const QPathVertex &v = m_vertices.at(i);
1297  if (qFuzzyCompare(v.x, vertex.x) && qFuzzyCompare(v.y, vertex.y)) {
1298  return i;
1299  }
1300  }
1301  }
1302 
1303  m_vertices << vertex;
1304  return m_vertices.size() - 1;
1305 }
QPathVertex * vertex(int vertex)
bool isEmpty() const
Definition: qdatabuffer_p.h:81
static Q_DECL_CONSTEXPR bool qFuzzyCompare(double p1, double p2)
Definition: qglobal.h:2030
Type & at(int i)
Definition: qdatabuffer_p.h:86
Type & last()
Definition: qdatabuffer_p.h:88
QDataBuffer< QPathVertex > m_vertices
int size() const
Definition: qdatabuffer_p.h:83

◆ intersectAndAdd()

void QWingedEdge::intersectAndAdd ( )
private

Definition at line 802 of file qpathclipper.cpp.

Referenced by QWingedEdge().

803 {
804  QIntersectionFinder finder;
806 
808 
809  for (int i = 0; i < m_segments.points(); ++i)
811 
813  for (int i = 0; i < m_segments.segments(); ++i) {
814  intersections.reset();
815 
816  int pathId = m_segments.pathId(i);
817 
819  while (isect) {
820  intersections << *isect;
821 
822  if (isect->next) {
823  isect += isect->next;
824  } else {
825  isect = 0;
826  }
827  }
828 
829  qSort(intersections.data(), intersections.data() + intersections.size());
830 
831  int first = m_segments.segmentAt(i).va;
832  int second = m_segments.segmentAt(i).vb;
833 
834  int last = first;
835  for (int j = 0; j < intersections.size(); ++j) {
836  const QPathSegments::Intersection &isect = intersections.at(j);
837 
838  QPathEdge *ep = edge(addEdge(last, isect.vertex));
839 
840  if (ep) {
841  const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1;
842  if (pathId == 0)
843  ep->windingA += dir;
844  else
845  ep->windingB += dir;
846  }
847 
848  last = isect.vertex;
849  }
850 
851  QPathEdge *ep = edge(addEdge(last, second));
852 
853  if (ep) {
854  const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1;
855  if (pathId == 0)
856  ep->windingA += dir;
857  else
858  ep->windingB += dir;
859  }
860  }
861 }
void produceIntersections(QPathSegments &segments)
int segments() const
const Intersection * intersectionAt(int index) const
int pathId(int index) const
const Segment & segmentAt(int index) const
int addVertex(const QPointF &p)
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
QPathSegments m_segments
const QPointF & pointAt(int vertex) const
QPathEdge * edge(int edge)
int addEdge(const QPointF &a, const QPointF &b)
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
int points() const
void reset()
Definition: qdatabuffer_p.h:79

◆ isInside()

bool QWingedEdge::isInside ( qreal  x,
qreal  y 
) const

Definition at line 1795 of file qpathclipper.cpp.

1796 {
1797  int winding = 0;
1798  for (int i = 0; i < edgeCount(); ++i) {
1799  const QPathEdge *ep = edge(i);
1800 
1801  // left xor right
1802  int w = ((ep->flag >> 4) ^ (ep->flag >> 5)) & 1;
1803 
1804  if (!w)
1805  continue;
1806 
1807  QPointF a = *vertex(ep->first);
1808  QPointF b = *vertex(ep->second);
1809 
1810  if ((a.y() < y && b.y() > y) || (a.y() > y && b.y() < y)) {
1811  qreal intersectionX = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
1812 
1813  if (intersectionX > x)
1814  winding += w;
1815  }
1816  }
1817 
1818  return winding & 1;
1819 }
double qreal
Definition: qglobal.h:1193
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
QPathVertex * vertex(int vertex)
long ASN1_INTEGER_get ASN1_INTEGER * a
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
QPathEdge * edge(int edge)
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
int edgeCount() const

◆ next()

QWingedEdge::TraversalStatus QWingedEdge::next ( const TraversalStatus status) const

Definition at line 881 of file qpathclipper.cpp.

Referenced by add(), addEdge(), clear(), commonEdge(), findInsertStatus(), removeEdge(), and traverse().

882 {
883  const QPathEdge *sp = edge(status.edge);
884  Q_ASSERT(sp);
885 
886  TraversalStatus result;
887  result.edge = sp->next(status.traversal, status.direction);
888  result.traversal = status.traversal;
889  result.direction = status.direction;
890 
891  const QPathEdge *rp = edge(result.edge);
892  Q_ASSERT(rp);
893 
894  if (sp->vertex(status.direction) == rp->vertex(status.direction))
895  result.flip();
896 
897  return result;
898 }
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
int vertex(Direction direction) const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
int next(Traversal traversal, Direction direction) const
QPathEdge * edge(int edge)

◆ printNode()

void QWingedEdge::printNode ( int  i,
FILE *  handle 
)
private

◆ removeEdge()

void QWingedEdge::removeEdge ( int  ei)
private

Definition at line 1106 of file qpathclipper.cpp.

Referenced by simplify().

1107 {
1108  QPathEdge *ep = edge(ei);
1109 
1110  TraversalStatus status;
1111  status.direction = QPathEdge::Forward;
1112  status.traversal = QPathEdge::RightTraversal;
1113  status.edge = ei;
1114 
1115  TraversalStatus forwardRight = next(status);
1116  forwardRight.flipDirection();
1117 
1118  status.traversal = QPathEdge::LeftTraversal;
1119  TraversalStatus forwardLeft = next(status);
1120  forwardLeft.flipDirection();
1121 
1122  status.direction = QPathEdge::Backward;
1123  TraversalStatus backwardLeft = next(status);
1124  backwardLeft.flipDirection();
1125 
1126  status.traversal = QPathEdge::RightTraversal;
1127  TraversalStatus backwardRight = next(status);
1128  backwardRight.flipDirection();
1129 
1130  edge(forwardRight.edge)->setNext(forwardRight.traversal, forwardRight.direction, forwardLeft.edge);
1131  edge(forwardLeft.edge)->setNext(forwardLeft.traversal, forwardLeft.direction, forwardRight.edge);
1132 
1133  edge(backwardRight.edge)->setNext(backwardRight.traversal, backwardRight.direction, backwardLeft.edge);
1134  edge(backwardLeft.edge)->setNext(backwardLeft.traversal, backwardLeft.direction, backwardRight.edge);
1135 
1136  ep->setNext(QPathEdge::Forward, ei);
1137  ep->setNext(QPathEdge::Backward, ei);
1138 
1139  QPathVertex *a = vertex(ep->first);
1140  QPathVertex *b = vertex(ep->second);
1141 
1142  a->edge = backwardRight.edge;
1143  b->edge = forwardRight.edge;
1144 }
QPathVertex * vertex(int vertex)
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
long ASN1_INTEGER_get ASN1_INTEGER * a
TraversalStatus next(const TraversalStatus &status) const
QPathEdge * edge(int edge)
void setNext(Traversal traversal, Direction direction, int next)

◆ simplify()

void QWingedEdge::simplify ( )

Definition at line 1352 of file qpathclipper.cpp.

Referenced by QPathClipper::doClip().

1353 {
1354  for (int i = 0; i < edgeCount(); ++i) {
1355  const QPathEdge *ep = edge(i);
1356 
1357  // if both sides are part of the inside then we can collapse the edge
1358  int flag = 0x3 << 4;
1359  if ((ep->flag & flag) == flag) {
1360  removeEdge(i);
1361 
1362  ep->flag &= ~flag;
1363  }
1364  }
1365 }
QPathEdge * edge(int edge)
void removeEdge(int ei)
int edgeCount() const

◆ toPath()

QPainterPath QWingedEdge::toPath ( ) const

Definition at line 1367 of file qpathclipper.cpp.

Referenced by QPathClipper::clip().

1368 {
1369  QPainterPath path;
1370 
1371  for (int i = 0; i < edgeCount(); ++i) {
1372  const QPathEdge *ep = edge(i);
1373 
1374  if (ep->flag & 16) {
1375  add(path, *this, i, QPathEdge::LeftTraversal);
1376  }
1377 
1378  if (ep->flag & 32)
1379  add(path, *this, i, QPathEdge::RightTraversal);
1380  }
1381 
1382  return path;
1383 }
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
QPathEdge * edge(int edge)
int edgeCount() const

◆ vertex() [1/2]

QPathVertex * QWingedEdge::vertex ( int  vertex)
inline

Definition at line 470 of file qpathclipper_p.h.

Referenced by add(), addEdge(), commonEdge(), QPathClipper::doClip(), findCrossings(), findInsertStatus(), QPathClipper::handleCrossingEdges(), insert(), midPoint(), and removeEdge().

471 {
472  return vertex < 0 ? 0 : &m_vertices.at(vertex);
473 }
QPathVertex * vertex(int vertex)
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPathVertex > m_vertices

◆ vertex() [2/2]

const QPathVertex * QWingedEdge::vertex ( int  vertex) const
inline

Definition at line 475 of file qpathclipper_p.h.

476 {
477  return vertex < 0 ? 0 : &m_vertices.at(vertex);
478 }
QPathVertex * vertex(int vertex)
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPathVertex > m_vertices

◆ vertexCount()

int QWingedEdge::vertexCount ( ) const
inline

Definition at line 459 of file qpathclipper_p.h.

Referenced by QPathClipper::doClip().

460 {
461  return m_vertices.size();
462 }
QDataBuffer< QPathVertex > m_vertices
int size() const
Definition: qdatabuffer_p.h:83

Properties

◆ m_edges

QDataBuffer<QPathEdge> QWingedEdge::m_edges
private

Definition at line 287 of file qpathclipper_p.h.

Referenced by addEdge().

◆ m_segments

QPathSegments QWingedEdge::m_segments
private

Definition at line 292 of file qpathclipper_p.h.

Referenced by QPathSegments::addPath(), QWingedEdge(), and QPathSegments::setPath().

◆ m_splitPoints

QVector<qreal> QWingedEdge::m_splitPoints
private

Definition at line 290 of file qpathclipper_p.h.

◆ m_vertices

QDataBuffer<QPathVertex> QWingedEdge::m_vertices
private

Definition at line 288 of file qpathclipper_p.h.

Referenced by insert().


The documentation for this class was generated from the following files: