Qt 4.8
Classes | Public Functions | Private Functions | Properties | Friends | List of all members
QTriangulator< T >::ComplexToSimple Class Reference

Classes

class  CompareEdges
 
struct  Edge
 
struct  Event
 
struct  Intersection
 
struct  Split
 

Public Functions

 ComplexToSimple (QTriangulator< T > *parent)
 
void decompose ()
 

Private Functions

QPair< QRBTree< int >::Node *, QRBTree< int >::Node * > bounds (const QPodPoint &point) const
 
bool calculateIntersection (int left, int right)
 
void calculateIntersections ()
 
bool edgeIsLeftOfEdge (int leftEdgeIndex, int rightEdgeIndex) const
 
void fillPriorityQueue ()
 
void initEdges ()
 
void insertEdgeIntoVectorIfWanted (ShortArray &orderedEdges, int i)
 
QPair< QRBTree< int >::Node *, QRBTree< int >::Node * > outerBounds (const QPodPoint &point) const
 
void removeUnusedPoints ()
 
void removeUnwantedEdgesAndConnect ()
 
void reorderEdgeListRange (QRBTree< int >::Node *leftmost, QRBTree< int >::Node *rightmost)
 
QRBTree< int >::NodesearchEdgeLeftOf (int edgeIndex) const
 
QRBTree< int >::NodesearchEdgeLeftOf (int edgeIndex, QRBTree< int >::Node *after) const
 
void sortEdgeList (const QPodPoint eventPoint)
 
int splitEdge (int splitIndex)
 
void splitEdgeListRange (QRBTree< int >::Node *leftmost, QRBTree< int >::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint)
 
bool splitEdgesAtIntersections ()
 

Properties

QRBTree< int > m_edgeList
 
QDataBuffer< Edgem_edges
 
QDataBuffer< Eventm_events
 
int m_initialPointCount
 
QTriangulatorm_parent
 
QInt64Set m_processedEdgePairs
 
QDataBuffer< Splitm_splits
 
QMaxHeap< Intersectionm_topIntersection
 

Friends

class CompareEdges
 

Detailed Description

template<typename T>
class QTriangulator< T >::ComplexToSimple

Definition at line 1325 of file qtriangulator.cpp.

Constructors and Destructors

◆ ComplexToSimple()

template<typename T>
QTriangulator< T >::ComplexToSimple::ComplexToSimple ( QTriangulator< T > *  parent)
inline

Definition at line 1328 of file qtriangulator.cpp.

1328  : m_parent(parent),
1329  m_edges(0), m_events(0), m_splits(0) { }

Functions

◆ bounds()

template<typename T >
QPair< QRBTree< int >::Node *, QRBTree< int >::Node * > QTriangulator< T >::ComplexToSimple::bounds ( const QPodPoint point) const
private

Definition at line 1813 of file qtriangulator.cpp.

1814 {
1815  QRBTree<int>::Node *current = m_edgeList.root;
1816  QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> result(0, 0);
1817  while (current) {
1818  const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1819  const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1821  if (d == 0) {
1822  result.first = result.second = current;
1823  break;
1824  }
1825  current = (d < 0 ? current->left : current->right);
1826  }
1827  if (current == 0)
1828  return result;
1829 
1830  current = result.first->left;
1831  while (current) {
1832  const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1833  const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1835  Q_ASSERT(d >= 0);
1836  if (d == 0) {
1837  result.first = current;
1838  current = current->left;
1839  } else {
1840  current = current->right;
1841  }
1842  }
1843 
1844  current = result.second->right;
1845  while (current) {
1846  const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1847  const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1849  Q_ASSERT(d <= 0);
1850  if (d == 0) {
1851  result.second = current;
1852  current = current->right;
1853  } else {
1854  current = current->left;
1855  }
1856  }
1857 
1858  return result;
1859 }
double d
Definition: qnumeric_p.h:62
Node * root
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
Type & at(int i)
Definition: qdatabuffer_p.h:86
__int64 qint64
Definition: qglobal.h:942
QDataBuffer< QPodPoint > m_vertices

◆ calculateIntersection()

template<typename T >
bool QTriangulator< T >::ComplexToSimple::calculateIntersection ( int  left,
int  right 
)
private

Definition at line 1727 of file qtriangulator.cpp.

1728 {
1729  const Edge &e1 = m_edges.at(left);
1730  const Edge &e2 = m_edges.at(right);
1731 
1732  const QPodPoint &u1 = m_parent->m_vertices.at((qint32)e1.from);
1733  const QPodPoint &u2 = m_parent->m_vertices.at((qint32)e1.to);
1734  const QPodPoint &v1 = m_parent->m_vertices.at((qint32)e2.from);
1735  const QPodPoint &v2 = m_parent->m_vertices.at((qint32)e2.to);
1736  if (qMax(u1.x, u2.x) <= qMin(v1.x, v2.x))
1737  return false;
1738 
1739  quint64 key = (left > right ? (quint64(right) << 32) | quint64(left) : (quint64(left) << 32) | quint64(right));
1740  if (m_processedEdgePairs.contains(key))
1741  return false;
1743 
1744  Intersection intersection;
1745  intersection.leftEdge = left;
1746  intersection.rightEdge = right;
1747  intersection.intersectionPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(u1, u2, v1, v2);
1748 
1749  if (!intersection.intersectionPoint.isValid())
1750  return false;
1751 
1752  Q_ASSERT(intersection.intersectionPoint.isOnLine(u1, u2));
1753  Q_ASSERT(intersection.intersectionPoint.isOnLine(v1, v2));
1754 
1755  intersection.vertex = m_parent->m_vertices.size();
1756  m_topIntersection.push(intersection);
1757  m_parent->m_vertices.add(intersection.intersectionPoint.round());
1758  return true;
1759 }
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
int qint32
Definition: qglobal.h:937
bool contains(quint64 key) const
void insert(quint64 key)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
static QIntersectionPoint qIntersectionPoint(const QPodPoint &point)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
unsigned __int64 quint64
Definition: qglobal.h:943
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
Type & at(int i)
Definition: qdatabuffer_p.h:86
void add(const Type &t)
Definition: qdatabuffer_p.h:93
int key
QMaxHeap< Intersection > m_topIntersection
QDataBuffer< QPodPoint > m_vertices
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
int size() const
Definition: qdatabuffer_p.h:83

◆ calculateIntersections()

template<typename T >
void QTriangulator< T >::ComplexToSimple::calculateIntersections ( )
private

Definition at line 2046 of file qtriangulator.cpp.

2047 {
2049 
2050  Q_ASSERT(m_topIntersection.empty());
2051  Q_ASSERT(m_edgeList.root == 0);
2052 
2053  // Find all intersection points.
2054  while (!m_events.isEmpty()) {
2055  Event event = m_events.last();
2056  sortEdgeList(event.point);
2057 
2058  // Find all edges in the edge list that contain the current vertex and mark them to be split later.
2060  QRBTree<int>::Node *leftNode = range.first ? m_edgeList.previous(range.first) : 0;
2061  int vertex = (event.type == Event::Upper ? m_edges.at(event.edge).upper() : m_edges.at(event.edge).lower());
2062  QIntersectionPoint eventPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point);
2063 
2064  if (range.first != 0) {
2065  splitEdgeListRange(range.first, range.second, vertex, eventPoint);
2066  reorderEdgeListRange(range.first, range.second);
2067  }
2068 
2069  // Handle the edges with start or end point in the current vertex.
2070  while (!m_events.isEmpty() && m_events.last().point == event.point) {
2071  event = m_events.last();
2072  m_events.pop_back();
2073  int i = event.edge;
2074 
2075  if (m_edges.at(i).node) {
2076  // Remove edge from edge list.
2077  Q_ASSERT(event.type == Event::Lower);
2080  m_edgeList.deleteNode(m_edges.at(i).node);
2081  if (!left || !right)
2082  continue;
2083  calculateIntersection(left->data, right->data);
2084  } else {
2085  // Insert edge into edge list.
2086  Q_ASSERT(event.type == Event::Upper);
2087  QRBTree<int>::Node *left = searchEdgeLeftOf(i, leftNode);
2088  m_edgeList.attachAfter(left, m_edges.at(i).node = m_edgeList.newNode());
2089  m_edges.at(i).node->data = i;
2090  QRBTree<int>::Node *right = m_edgeList.next(m_edges.at(i).node);
2091  if (left)
2092  calculateIntersection(left->data, i);
2093  if (right)
2094  calculateIntersection(i, right->data);
2095  }
2096  }
2097  while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= eventPoint)
2098  m_topIntersection.pop();
2099 #ifdef Q_TRIANGULATOR_DEBUG
2100  DebugDialog dialog(this, vertex);
2101  dialog.exec();
2102 #endif
2103  }
2105 }
EventRef event
Node * previous(Node *node) const
Node * newNode()
QRBTree< int >::Node * searchEdgeLeftOf(int edgeIndex) const
Node * next(Node *node) const
T1 first
Definition: qpair.h:65
T2 second
Definition: qpair.h:66
Node * root
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
void splitEdgeListRange(QRBTree< int >::Node *leftmost, QRBTree< int >::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint)
QPair< QRBTree< int >::Node *, QRBTree< int >::Node * > bounds(const QPodPoint &point) const
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
static QIntersectionPoint qIntersectionPoint(const QPodPoint &point)
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
void reorderEdgeListRange(QRBTree< int >::Node *leftmost, QRBTree< int >::Node *rightmost)
void attachAfter(Node *parent, Node *child)
void sortEdgeList(const QPodPoint eventPoint)
void deleteNode(Node *&node)
bool calculateIntersection(int left, int right)
QMaxHeap< Intersection > m_topIntersection
Q_CORE_EXPORT QTextStream & left(QTextStream &s)

◆ decompose()

template<typename T >
void QTriangulator< T >::ComplexToSimple::decompose ( )

Definition at line 1669 of file qtriangulator.cpp.

Referenced by QTriangulator< T >::triangulate().

1670 {
1672  initEdges();
1673  do {
1675  } while (splitEdgesAtIntersections());
1676 
1679 
1680  m_parent->m_indices.clear();
1681  QBitArray processed(m_edges.size(), false);
1682  for (int first = 0; first < m_edges.size(); ++first) {
1683  // If already processed, or if unused path, skip.
1684  if (processed.at(first) || m_edges.at(first).next == -1)
1685  continue;
1686 
1687  int i = first;
1688  do {
1689  Q_ASSERT(!processed.at(i));
1690  Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
1691  m_parent->m_indices.push_back(m_edges.at(i).from);
1692  processed.setBit(i);
1693  i = m_edges.at(i).next; // CCW order
1694  } while (i != first);
1695  m_parent->m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON
1696  }
1697 }
QVector< T > m_indices
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QBitArray class provides an array of bits.
Definition: qbitarray.h:54
QDataBuffer< QPodPoint > m_vertices
int size() const
Definition: qdatabuffer_p.h:83

◆ edgeIsLeftOfEdge()

template<typename T >
bool QTriangulator< T >::ComplexToSimple::edgeIsLeftOfEdge ( int  leftEdgeIndex,
int  rightEdgeIndex 
) const
private

Definition at line 1762 of file qtriangulator.cpp.

1763 {
1764  const Edge &leftEdge = m_edges.at(leftEdgeIndex);
1765  const Edge &rightEdge = m_edges.at(rightEdgeIndex);
1766  const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
1767  const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
1768  const QPodPoint &upper = m_parent->m_vertices.at(leftEdge.upper());
1769  if (upper.x < qMin(l.x, u.x))
1770  return true;
1771  if (upper.x > qMax(l.x, u.x))
1772  return false;
1774  // d < 0: left, d > 0: right, d == 0: on top
1775  if (d == 0)
1776  d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
1777  return d < 0;
1778 }
double d
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
quint16 u
static qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
Type & at(int i)
Definition: qdatabuffer_p.h:86
__int64 qint64
Definition: qglobal.h:942
QFactoryLoader * l
QDataBuffer< QPodPoint > m_vertices

◆ fillPriorityQueue()

template<typename T >
void QTriangulator< T >::ComplexToSimple::fillPriorityQueue ( )
private

Definition at line 2022 of file qtriangulator.cpp.

2023 {
2024  m_events.reset();
2025  m_events.reserve(m_edges.size() * 2);
2026  for (int i = 0; i < m_edges.size(); ++i) {
2027  Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
2028  Q_ASSERT(m_edges.at(i).node == 0);
2029  Q_ASSERT(m_edges.at(i).pointingUp == m_edges.at(i).originallyPointingUp);
2030  Q_ASSERT(m_edges.at(i).pointingUp == (m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from)));
2031  // Ignore zero-length edges.
2032  if (m_parent->m_vertices.at(m_edges.at(i).to) != m_parent->m_vertices.at(m_edges.at(i).from)) {
2033  QPodPoint upper = m_parent->m_vertices.at(m_edges.at(i).upper());
2034  QPodPoint lower = m_parent->m_vertices.at(m_edges.at(i).lower());
2035  Event upperEvent = {{upper.x, upper.y}, Event::Upper, i};
2036  Event lowerEvent = {{lower.x, lower.y}, Event::Lower, i};
2037  m_events.add(upperEvent);
2038  m_events.add(lowerEvent);
2039  }
2040  }
2041  //qSort(m_events.data(), m_events.data() + m_events.size());
2042  sort(m_events.data(), m_events.size());
2043 }
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static void sort(T *array, int count, LessThan lessThan)
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPodPoint > m_vertices

◆ initEdges()

template<typename T >
void QTriangulator< T >::ComplexToSimple::initEdges ( )
private

Definition at line 1700 of file qtriangulator.cpp.

1701 {
1702  // Initialize edge structure.
1703  // 'next' and 'previous' are not being initialized at this point.
1704  int first = 0;
1705  for (int i = 0; i < m_parent->m_indices.size(); ++i) {
1706  if (m_parent->m_indices.at(i) == T(-1)) { // Q_TRIANGULATE_END_OF_POLYGON
1707  if (m_edges.size() != first)
1708  m_edges.last().to = m_edges.at(first).from;
1709  first = m_edges.size();
1710  } else {
1711  Q_ASSERT(i + 1 < m_parent->m_indices.size());
1712  // {node, from, to, next, previous, winding, mayIntersect, pointingUp, originallyPointingUp}
1713  Edge edge = {0, int(m_parent->m_indices.at(i)), int(m_parent->m_indices.at(i + 1)), -1, -1, 0, true, false, false};
1714  m_edges.add(edge);
1715  }
1716  }
1717  if (first != m_edges.size())
1718  m_edges.last().to = m_edges.at(first).from;
1719  for (int i = 0; i < m_edges.size(); ++i) {
1720  m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
1721  m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
1722  }
1723 }
QVector< T > m_indices
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPodPoint > m_vertices

◆ insertEdgeIntoVectorIfWanted()

template<typename T >
void QTriangulator< T >::ComplexToSimple::insertEdgeIntoVectorIfWanted ( ShortArray orderedEdges,
int  i 
)
private

Definition at line 2161 of file qtriangulator.cpp.

2162 {
2163  // Edges with zero length should not reach this part.
2164  Q_ASSERT(m_parent->m_vertices.at(m_edges.at(i).from) != m_parent->m_vertices.at(m_edges.at(i).to));
2165 
2166  // Skip edges with unwanted winding number.
2167  int windingNumber = m_edges.at(i).winding;
2168  if (m_edges.at(i).originallyPointingUp)
2169  ++windingNumber;
2170 
2171  // Make sure exactly one fill rule is specified.
2173 
2174  if ((m_parent->m_hint & QVectorPath::WindingFill) && windingNumber != 0 && windingNumber != 1)
2175  return;
2176 
2177  // Skip cancelling edges.
2178  if (!orderedEdges.isEmpty()) {
2179  int j = orderedEdges[orderedEdges.size() - 1];
2180  // If the last edge is already connected in one end, it should not be cancelled.
2181  if (m_edges.at(j).next == -1 && m_edges.at(j).previous == -1
2182  && (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(j).to))
2183  && (m_parent->m_vertices.at(m_edges.at(i).to) == m_parent->m_vertices.at(m_edges.at(j).from))) {
2184  orderedEdges.removeLast();
2185  return;
2186  }
2187  }
2188  orderedEdges.append(i);
2189 }
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPodPoint > m_vertices

◆ outerBounds()

template<typename T >
QPair< QRBTree< int >::Node *, QRBTree< int >::Node * > QTriangulator< T >::ComplexToSimple::outerBounds ( const QPodPoint point) const
private

Definition at line 1862 of file qtriangulator.cpp.

1863 {
1864  QRBTree<int>::Node *current = m_edgeList.root;
1865  QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> result(0, 0);
1866 
1867  while (current) {
1868  const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1869  const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1871  if (d == 0)
1872  break;
1873  if (d < 0) {
1874  result.second = current;
1875  current = current->left;
1876  } else {
1877  result.first = current;
1878  current = current->right;
1879  }
1880  }
1881 
1882  if (!current)
1883  return result;
1884 
1885  QRBTree<int>::Node *mid = current;
1886 
1887  current = mid->left;
1888  while (current) {
1889  const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1890  const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1892  Q_ASSERT(d >= 0);
1893  if (d == 0) {
1894  current = current->left;
1895  } else {
1896  result.first = current;
1897  current = current->right;
1898  }
1899  }
1900 
1901  current = mid->right;
1902  while (current) {
1903  const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1904  const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1906  Q_ASSERT(d <= 0);
1907  if (d == 0) {
1908  current = current->right;
1909  } else {
1910  result.second = current;
1911  current = current->left;
1912  }
1913  }
1914 
1915  return result;
1916 }
double d
Definition: qnumeric_p.h:62
Node * root
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
Type & at(int i)
Definition: qdatabuffer_p.h:86
__int64 qint64
Definition: qglobal.h:942
QDataBuffer< QPodPoint > m_vertices

◆ removeUnusedPoints()

template<typename T >
void QTriangulator< T >::ComplexToSimple::removeUnusedPoints ( )
private

Definition at line 2331 of file qtriangulator.cpp.

2331  {
2332  QBitArray used(m_parent->m_vertices.size(), false);
2333  for (int i = 0; i < m_edges.size(); ++i) {
2334  Q_ASSERT((m_edges.at(i).previous == -1) == (m_edges.at(i).next == -1));
2335  if (m_edges.at(i).next != -1)
2336  used.setBit(m_edges.at(i).from);
2337  }
2339  newMapping.resize(m_parent->m_vertices.size());
2340  int count = 0;
2341  for (int i = 0; i < m_parent->m_vertices.size(); ++i) {
2342  if (used.at(i)) {
2343  m_parent->m_vertices.at(count) = m_parent->m_vertices.at(i);
2344  newMapping.at(i) = count;
2345  ++count;
2346  }
2347  }
2348  m_parent->m_vertices.resize(count);
2349  for (int i = 0; i < m_edges.size(); ++i) {
2350  m_edges.at(i).from = newMapping.at(m_edges.at(i).from);
2351  m_edges.at(i).to = newMapping.at(m_edges.at(i).to);
2352  }
2353 }
void resize(int size)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Type & at(int i)
Definition: qdatabuffer_p.h:86
The QBitArray class provides an array of bits.
Definition: qbitarray.h:54
QDataBuffer< QPodPoint > m_vertices
int size() const
Definition: qdatabuffer_p.h:83

◆ removeUnwantedEdgesAndConnect()

template<typename T >
void QTriangulator< T >::ComplexToSimple::removeUnwantedEdgesAndConnect ( )
private

Definition at line 2192 of file qtriangulator.cpp.

2193 {
2194  Q_ASSERT(m_edgeList.root == 0);
2195  // Initialize priority queue.
2197 
2198  ShortArray orderedEdges;
2199 
2200  while (!m_events.isEmpty()) {
2201  Event event = m_events.last();
2202  int edgeIndex = event.edge;
2203 
2204  // Check that all the edges in the list crosses the current scanline
2205  //if (m_edgeList.root) {
2206  // for (QRBTree<int>::Node *node = m_edgeList.front(m_edgeList.root); node; node = m_edgeList.next(node)) {
2207  // Q_ASSERT(event.point <= m_points.at(m_edges.at(node->data).lower()));
2208  // }
2209  //}
2210 
2211  orderedEdges.clear();
2213  if (m_edgeList.root) {
2215  // Process edges that are going to be removed from the edge list at the current event point.
2216  while (current != b.second) {
2217  Q_ASSERT(current);
2218  Q_ASSERT(m_edges.at(current->data).node == current);
2219  Q_ASSERT(QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point).isOnLine(m_parent->m_vertices.at(m_edges.at(current->data).from), m_parent->m_vertices.at(m_edges.at(current->data).to)));
2220  Q_ASSERT(m_parent->m_vertices.at(m_edges.at(current->data).from) == event.point || m_parent->m_vertices.at(m_edges.at(current->data).to) == event.point);
2221  insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
2222  current = m_edgeList.next(current);
2223  }
2224  }
2225 
2226  // Remove edges above the event point, insert edges below the event point.
2227  do {
2228  event = m_events.last();
2229  m_events.pop_back();
2230  edgeIndex = event.edge;
2231 
2232  // Edges with zero length should not reach this part.
2233  Q_ASSERT(m_parent->m_vertices.at(m_edges.at(edgeIndex).from) != m_parent->m_vertices.at(m_edges.at(edgeIndex).to));
2234 
2235  if (m_edges.at(edgeIndex).node) {
2236  Q_ASSERT(event.type == Event::Lower);
2237  Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).lower()));
2238  m_edgeList.deleteNode(m_edges.at(edgeIndex).node);
2239  } else {
2240  Q_ASSERT(event.type == Event::Upper);
2241  Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).upper()));
2242  QRBTree<int>::Node *left = searchEdgeLeftOf(edgeIndex, b.first);
2243  m_edgeList.attachAfter(left, m_edges.at(edgeIndex).node = m_edgeList.newNode());
2244  m_edges.at(edgeIndex).node->data = edgeIndex;
2245  }
2246  } while (!m_events.isEmpty() && m_events.last().point == event.point);
2247 
2248  if (m_edgeList.root) {
2250 
2251  // Calculate winding number and turn counter-clockwise.
2252  int currentWindingNumber = (b.first ? m_edges.at(b.first->data).winding : 0);
2253  while (current != b.second) {
2254  Q_ASSERT(current);
2255  //Q_ASSERT(b.second == 0 || m_edgeList.order(current, b.second) < 0);
2256  int i = current->data;
2257  Q_ASSERT(m_edges.at(i).node == current);
2258 
2259  // Winding number.
2260  int ccwWindingNumber = m_edges.at(i).winding = currentWindingNumber;
2261  if (m_edges.at(i).originallyPointingUp) {
2262  --m_edges.at(i).winding;
2263  } else {
2264  ++m_edges.at(i).winding;
2265  ++ccwWindingNumber;
2266  }
2267  currentWindingNumber = m_edges.at(i).winding;
2268 
2269  // Turn counter-clockwise.
2270  if ((ccwWindingNumber & 1) == 0) {
2271  Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
2272  qSwap(m_edges.at(i).from, m_edges.at(i).to);
2273  m_edges.at(i).pointingUp = !m_edges.at(i).pointingUp;
2274  }
2275 
2276  current = m_edgeList.next(current);
2277  }
2278 
2279  // Process edges that were inserted into the edge list at the current event point.
2281  while (current != b.first) {
2282  Q_ASSERT(current);
2283  Q_ASSERT(m_edges.at(current->data).node == current);
2284  insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
2285  current = m_edgeList.previous(current);
2286  }
2287  }
2288  if (orderedEdges.isEmpty())
2289  continue;
2290 
2291  Q_ASSERT((orderedEdges.size() & 1) == 0);
2292 
2293  // Connect edges.
2294  // First make sure the first edge point towards the current point.
2295  int i;
2296  if (m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).from) == event.point) {
2297  i = 1;
2298  int copy = orderedEdges[0]; // Make copy in case the append() will cause a reallocation.
2299  orderedEdges.append(copy);
2300  } else {
2301  Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).to) == event.point);
2302  i = 0;
2303  }
2304 
2305  // Remove references to duplicate points. First find the point with lowest index.
2306  int pointIndex = INT_MAX;
2307  for (int j = i; j < orderedEdges.size(); j += 2) {
2308  Q_ASSERT(j + 1 < orderedEdges.size());
2309  Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j]).to) == event.point);
2310  Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j + 1]).from) == event.point);
2311  if (m_edges.at(orderedEdges[j]).to < pointIndex)
2312  pointIndex = m_edges.at(orderedEdges[j]).to;
2313  if (m_edges.at(orderedEdges[j + 1]).from < pointIndex)
2314  pointIndex = m_edges.at(orderedEdges[j + 1]).from;
2315  }
2316 
2317  for (; i < orderedEdges.size(); i += 2) {
2318  // Remove references to duplicate points by making all edges reference one common point.
2319  m_edges.at(orderedEdges[i]).to = m_edges.at(orderedEdges[i + 1]).from = pointIndex;
2320 
2321  Q_ASSERT(m_edges.at(orderedEdges[i]).pointingUp || m_edges.at(orderedEdges[i]).previous != -1);
2322  Q_ASSERT(!m_edges.at(orderedEdges[i + 1]).pointingUp || m_edges.at(orderedEdges[i + 1]).next != -1);
2323 
2324  m_edges.at(orderedEdges[i]).next = orderedEdges[i + 1];
2325  m_edges.at(orderedEdges[i + 1]).previous = orderedEdges[i];
2326  }
2327  } // end while
2328 }
EventRef event
Node * previous(Node *node) const
Node * newNode()
QRBTree< int >::Node * searchEdgeLeftOf(int edgeIndex) const
Node * next(Node *node) const
T1 first
Definition: qpair.h:65
T2 second
Definition: qpair.h:66
Node * root
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static QIntersectionPoint qIntersectionPoint(const QPodPoint &point)
QVarLengthArray< int, 6 > ShortArray
void insertEdgeIntoVectorIfWanted(ShortArray &orderedEdges, int i)
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
Type & at(int i)
Definition: qdatabuffer_p.h:86
void attachAfter(Node *parent, Node *child)
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
void deleteNode(Node *&node)
QDataBuffer< QPodPoint > m_vertices
QPair< QRBTree< int >::Node *, QRBTree< int >::Node * > outerBounds(const QPodPoint &point) const
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
Node * front(Node *node) const
#define INT_MAX
Node * back(Node *node) const

◆ reorderEdgeListRange()

template<typename T >
void QTriangulator< T >::ComplexToSimple::reorderEdgeListRange ( QRBTree< int >::Node leftmost,
QRBTree< int >::Node rightmost 
)
private

Definition at line 1938 of file qtriangulator.cpp.

1939 {
1940  Q_ASSERT(leftmost && rightmost);
1941 
1942  QRBTree<int>::Node *storeLeftmost = leftmost;
1943  QRBTree<int>::Node *storeRightmost = rightmost;
1944 
1945  // Reorder.
1946  while (leftmost != rightmost) {
1947  Edge &left = m_edges.at(leftmost->data);
1948  Edge &right = m_edges.at(rightmost->data);
1949  qSwap(left.node, right.node);
1950  qSwap(leftmost->data, rightmost->data);
1951  leftmost = m_edgeList.next(leftmost);
1952  if (leftmost == rightmost)
1953  break;
1954  rightmost = m_edgeList.previous(rightmost);
1955  }
1956 
1957  rightmost = m_edgeList.next(storeRightmost);
1958  leftmost = m_edgeList.previous(storeLeftmost);
1959  if (leftmost)
1960  calculateIntersection(leftmost->data, storeLeftmost->data);
1961  if (rightmost)
1962  calculateIntersection(storeRightmost->data, rightmost->data);
1963 }
Node * previous(Node *node) const
Node * next(Node *node) const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
bool calculateIntersection(int left, int right)
Q_CORE_EXPORT QTextStream & left(QTextStream &s)

◆ searchEdgeLeftOf() [1/2]

template<typename T >
QRBTreeIntNodePointer QTriangulator< T >::ComplexToSimple::searchEdgeLeftOf ( int  edgeIndex) const
private

Definition at line 1781 of file qtriangulator.cpp.

1782 {
1783  QRBTree<int>::Node *current = m_edgeList.root;
1784  QRBTree<int>::Node *result = 0;
1785  while (current) {
1786  if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
1787  current = current->left;
1788  } else {
1789  result = current;
1790  current = current->right;
1791  }
1792  }
1793  return result;
1794 }
bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const
Node * root

◆ searchEdgeLeftOf() [2/2]

template<typename T >
QRBTreeIntNodePointer QTriangulator< T >::ComplexToSimple::searchEdgeLeftOf ( int  edgeIndex,
QRBTree< int >::Node after 
) const
private

Definition at line 1797 of file qtriangulator.cpp.

1798 {
1799  if (!m_edgeList.root)
1800  return after;
1801  QRBTree<int>::Node *result = after;
1802  QRBTree<int>::Node *current = (after ? m_edgeList.next(after) : m_edgeList.front(m_edgeList.root));
1803  while (current) {
1804  if (edgeIsLeftOfEdge(edgeIndex, current->data))
1805  return result;
1806  result = current;
1807  current = m_edgeList.next(current);
1808  }
1809  return result;
1810 }
bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const
Node * next(Node *node) const
Node * root
Node * front(Node *node) const

◆ sortEdgeList()

template<typename T >
void QTriangulator< T >::ComplexToSimple::sortEdgeList ( const QPodPoint  eventPoint)
private

Definition at line 1966 of file qtriangulator.cpp.

1967 {
1968  QIntersectionPoint eventPoint2 = QT_PREPEND_NAMESPACE(qIntersectionPoint)(eventPoint);
1969  while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint < eventPoint2) {
1970  Intersection intersection = m_topIntersection.pop();
1971 
1972  QIntersectionPoint currentIntersectionPoint = intersection.intersectionPoint;
1973  int currentVertex = intersection.vertex;
1974 
1975  QRBTree<int>::Node *leftmost = m_edges.at(intersection.leftEdge).node;
1976  QRBTree<int>::Node *rightmost = m_edges.at(intersection.rightEdge).node;
1977 
1978  for (;;) {
1979  QRBTree<int>::Node *previous = m_edgeList.previous(leftmost);
1980  if (!previous)
1981  break;
1982  const Edge &edge = m_edges.at(previous->data);
1983  const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1984  const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1985  if (!currentIntersectionPoint.isOnLine(u, v)) {
1986  Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
1987  break;
1988  }
1989  leftmost = previous;
1990  }
1991 
1992  for (;;) {
1993  QRBTree<int>::Node *next = m_edgeList.next(rightmost);
1994  if (!next)
1995  break;
1996  const Edge &edge = m_edges.at(next->data);
1997  const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1998  const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1999  if (!currentIntersectionPoint.isOnLine(u, v)) {
2000  Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
2001  break;
2002  }
2003  rightmost = next;
2004  }
2005 
2006  Q_ASSERT(leftmost && rightmost);
2007  splitEdgeListRange(leftmost, rightmost, currentVertex, currentIntersectionPoint);
2008  reorderEdgeListRange(leftmost, rightmost);
2009 
2010  while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= currentIntersectionPoint)
2011  m_topIntersection.pop();
2012 
2013 #ifdef Q_TRIANGULATOR_DEBUG
2014  DebugDialog dialog(this, intersection.vertex);
2015  dialog.exec();
2016 #endif
2017 
2018  }
2019 }
static qint64 qCross(const QPodPoint &u, const QPodPoint &v)
int qint32
Definition: qglobal.h:937
Node * previous(Node *node) const
Node * next(Node *node) const
quint16 u
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
void splitEdgeListRange(QRBTree< int >::Node *leftmost, QRBTree< int >::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint)
bool isOnLine(const QPodPoint &u, const QPodPoint &v) const
static QIntersectionPoint qIntersectionPoint(const QPodPoint &point)
bool isAccurate() const
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
void reorderEdgeListRange(QRBTree< int >::Node *leftmost, QRBTree< int >::Node *rightmost)
Type & at(int i)
Definition: qdatabuffer_p.h:86
QMaxHeap< Intersection > m_topIntersection
QDataBuffer< QPodPoint > m_vertices

◆ splitEdge()

template<typename T >
int QTriangulator< T >::ComplexToSimple::splitEdge ( int  splitIndex)
private

Definition at line 2112 of file qtriangulator.cpp.

2113 {
2114  const Split &split = m_splits.at(splitIndex);
2115  Edge &lowerEdge = m_edges.at(split.edge);
2116  Q_ASSERT(lowerEdge.node == 0);
2117  Q_ASSERT(lowerEdge.previous == -1 && lowerEdge.next == -1);
2118 
2119  if (lowerEdge.from == split.vertex)
2120  return split.edge;
2121  if (lowerEdge.to == split.vertex)
2122  return lowerEdge.next;
2123 
2124  // Check that angle >= 90 degrees.
2125  //Q_ASSERT(qDot(m_points.at(m_edges.at(edgeIndex).from) - m_points.at(pointIndex),
2126  // m_points.at(m_edges.at(edgeIndex).to) - m_points.at(pointIndex)) <= 0);
2127 
2128  Edge upperEdge = lowerEdge;
2129  upperEdge.mayIntersect |= !split.accurate; // The edge may have been split before at an inaccurate split point.
2130  lowerEdge.mayIntersect = !split.accurate;
2131  if (lowerEdge.pointingUp) {
2132  lowerEdge.to = upperEdge.from = split.vertex;
2133  m_edges.add(upperEdge);
2134  return m_edges.size() - 1;
2135  } else {
2136  lowerEdge.from = upperEdge.to = split.vertex;
2137  m_edges.add(upperEdge);
2138  return split.edge;
2139  }
2140 }
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static void split(QT_FT_Vector *b)

◆ splitEdgeListRange()

template<typename T >
void QTriangulator< T >::ComplexToSimple::splitEdgeListRange ( QRBTree< int >::Node leftmost,
QRBTree< int >::Node rightmost,
int  vertex,
const QIntersectionPoint intersectionPoint 
)
private

Definition at line 1919 of file qtriangulator.cpp.

1920 {
1921  Q_ASSERT(leftmost && rightmost);
1922 
1923  // Split.
1924  for (;;) {
1925  const QPodPoint &u = m_parent->m_vertices.at(m_edges.at(leftmost->data).from);
1926  const QPodPoint &v = m_parent->m_vertices.at(m_edges.at(leftmost->data).to);
1927  Q_ASSERT(intersectionPoint.isOnLine(u, v));
1928  const Split split = {vertex, leftmost->data, intersectionPoint.isAccurate()};
1929  if (intersectionPoint.xOffset.numerator != 0 || intersectionPoint.yOffset.numerator != 0 || (intersectionPoint.upperLeft != u && intersectionPoint.upperLeft != v))
1930  m_splits.add(split);
1931  if (leftmost == rightmost)
1932  break;
1933  leftmost = m_edgeList.next(leftmost);
1934  }
1935 }
Node * next(Node *node) const
quint16 u
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool isOnLine(const QPodPoint &u, const QPodPoint &v) const
bool isAccurate() const
Type & at(int i)
Definition: qdatabuffer_p.h:86
static void split(QT_FT_Vector *b)
quint64 numerator
QDataBuffer< QPodPoint > m_vertices

◆ splitEdgesAtIntersections()

template<typename T >
bool QTriangulator< T >::ComplexToSimple::splitEdgesAtIntersections ( )
private

Definition at line 2143 of file qtriangulator.cpp.

2144 {
2145  for (int i = 0; i < m_edges.size(); ++i)
2146  m_edges.at(i).mayIntersect = false;
2147  bool checkForNewIntersections = false;
2148  for (int i = 0; i < m_splits.size(); ++i) {
2149  splitEdge(i);
2150  checkForNewIntersections |= !m_splits.at(i).accurate;
2151  }
2152  for (int i = 0; i < m_edges.size(); ++i) {
2153  m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
2154  m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
2155  }
2156  m_splits.reset();
2157  return checkForNewIntersections;
2158 }
Type & at(int i)
Definition: qdatabuffer_p.h:86
QDataBuffer< QPodPoint > m_vertices

Friends and Related Functions

◆ CompareEdges

template<typename T>
friend class CompareEdges
friend

Definition at line 1347 of file qtriangulator.cpp.

Properties

◆ m_edgeList

template<typename T>
QRBTree<int> QTriangulator< T >::ComplexToSimple::m_edgeList
private

Definition at line 1424 of file qtriangulator.cpp.

◆ m_edges

template<typename T>
QDataBuffer<Edge> QTriangulator< T >::ComplexToSimple::m_edges
private

Definition at line 1423 of file qtriangulator.cpp.

◆ m_events

template<typename T>
QDataBuffer<Event> QTriangulator< T >::ComplexToSimple::m_events
private

Definition at line 1425 of file qtriangulator.cpp.

◆ m_initialPointCount

template<typename T>
int QTriangulator< T >::ComplexToSimple::m_initialPointCount
private

Definition at line 1429 of file qtriangulator.cpp.

◆ m_parent

template<typename T>
QTriangulator* QTriangulator< T >::ComplexToSimple::m_parent
private

Definition at line 1422 of file qtriangulator.cpp.

◆ m_processedEdgePairs

template<typename T>
QInt64Set QTriangulator< T >::ComplexToSimple::m_processedEdgePairs
private

Definition at line 1428 of file qtriangulator.cpp.

◆ m_splits

template<typename T>
QDataBuffer<Split> QTriangulator< T >::ComplexToSimple::m_splits
private

Definition at line 1426 of file qtriangulator.cpp.

◆ m_topIntersection

template<typename T>
QMaxHeap<Intersection> QTriangulator< T >::ComplexToSimple::m_topIntersection
private

Definition at line 1427 of file qtriangulator.cpp.


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