PageRenderTime 27ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/GUISupport/Qt/Chart/vtkQtChartQuad.cxx

https://github.com/naucoin/VTKSlicerWidgets
C++ | 267 lines | 192 code | 35 blank | 40 comment | 51 complexity | 87803b9d4d4f7ad0a0f1d5c2cfc107d4 MD5 | raw file
  1. /*=========================================================================
  2. Program: Visualization Toolkit
  3. Module: vtkQtChartQuad.cxx
  4. Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  5. All rights reserved.
  6. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  7. This software is distributed WITHOUT ANY WARRANTY; without even
  8. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  9. PURPOSE. See the above copyright notice for more information.
  10. =========================================================================*/
  11. /*-------------------------------------------------------------------------
  12. Copyright 2008 Sandia Corporation.
  13. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  14. the U.S. Government retains certain rights in this software.
  15. -------------------------------------------------------------------------*/
  16. /// \file vtkQtChartQuad.cxx
  17. /// \date November 13, 2008
  18. #ifdef _MSC_VER
  19. // Disable warnings that Qt headers give.
  20. #pragma warning(disable:4127)
  21. #endif
  22. #include "vtkQtChartQuad.h"
  23. #include <QPolygonF>
  24. vtkQtChartQuad::vtkQtChartQuad()
  25. : vtkQtChartShape()
  26. {
  27. this->Points = new QPolygonF(4);
  28. }
  29. vtkQtChartQuad::vtkQtChartQuad(int series, int index)
  30. : vtkQtChartShape(series, index)
  31. {
  32. this->Points = new QPolygonF(4);
  33. }
  34. vtkQtChartQuad::vtkQtChartQuad(const vtkQtChartQuad &other)
  35. : vtkQtChartShape(other)
  36. {
  37. this->Points = new QPolygonF(*other.Points);
  38. }
  39. vtkQtChartQuad::~vtkQtChartQuad()
  40. {
  41. delete this->Points;
  42. }
  43. vtkQtChartQuad &vtkQtChartQuad::operator=(const vtkQtChartQuad &other)
  44. {
  45. vtkQtChartShape::operator=(other);
  46. *this->Points = *other.Points;
  47. return *this;
  48. }
  49. void vtkQtChartQuad::getBounds(QRectF &bounds) const
  50. {
  51. bounds = this->Points->boundingRect();
  52. }
  53. bool vtkQtChartQuad::contains(const QPointF &point) const
  54. {
  55. // Use the line segments to form a convex loop. Use the loop to
  56. // determine if the point is inside the quad.
  57. for(int i = 0; i < 4; i++)
  58. {
  59. // If the following expression is less than zero, the point is
  60. // outside the loop:
  61. // (y - y0)*(x1 - x0) - (x - x0)*(y1 - y0)
  62. int j = i == 3 ? 0 : i + 1;
  63. float xDiff = (*this->Points)[j].x() - (*this->Points)[i].x();
  64. float yDiff = (*this->Points)[j].y() - (*this->Points)[i].y();
  65. if(((point.y() - (*this->Points)[i].y()) * xDiff) -
  66. ((point.x() - (*this->Points)[i].x()) * yDiff) < 0.0)
  67. {
  68. return false;
  69. }
  70. }
  71. return true;
  72. }
  73. bool vtkQtChartQuad::intersects(const QRectF &area) const
  74. {
  75. // Get the bounding box code for each of the quad points. If any of
  76. // the quad points are in the area, return true.
  77. int i = 0;
  78. int code[4] = {0, 0, 0, 0};
  79. for( ; i < 4; i++)
  80. {
  81. code[i] = vtkQtChartShape::getBoundingBoxCode((*this->Points)[i], area);
  82. if(code[i] == 0)
  83. {
  84. return true;
  85. }
  86. }
  87. // See if all the points are to one side of the area.
  88. if((code[0] & code[1] & code[2] & code[3]) != 0)
  89. {
  90. return false;
  91. }
  92. // Check for 4-corner case.
  93. int corner[4] =
  94. {
  95. vtkQtChartShape::Top | vtkQtChartShape::Left,
  96. vtkQtChartShape::Top | vtkQtChartShape::Right,
  97. vtkQtChartShape::Bottom | vtkQtChartShape::Right,
  98. vtkQtChartShape::Bottom | vtkQtChartShape::Left
  99. };
  100. for(i = 0; i < 4; i++)
  101. {
  102. if(code[i] == corner[0])
  103. {
  104. i++;
  105. bool found = true;
  106. for(int j = 1; found && j < 4; j++, i++)
  107. {
  108. found = code[i % 4] == corner[j];
  109. }
  110. if(found)
  111. {
  112. return true;
  113. }
  114. }
  115. }
  116. // See if the diagonals guarantee an intersection.
  117. int leftRight = vtkQtChartShape::Left | vtkQtChartShape::Right;
  118. int topBottom = vtkQtChartShape::Top | vtkQtChartShape::Bottom;
  119. int combined = code[0] | code[2];
  120. if(combined == leftRight || combined == topBottom)
  121. {
  122. return true;
  123. }
  124. combined = code[1] | code[3];
  125. if(combined == leftRight || combined == topBottom)
  126. {
  127. return true;
  128. }
  129. // See if any of the line segments cross the area.
  130. for(i = 0; i < 4; i++)
  131. {
  132. int j = i == 3 ? 0 : i + 1;
  133. if((code[i] & code[j]) != 0)
  134. {
  135. // Line segment is completely on one side of the area.
  136. continue;
  137. }
  138. // See if the combined code guarantees an intersection.
  139. combined = code[i] | code[j];
  140. if(combined == leftRight || combined == topBottom)
  141. {
  142. return true;
  143. }
  144. // Calculate if the line intersects the area. First, clip the x
  145. // coordinates.
  146. float x1 = (*this->Points)[i].x();
  147. float y1 = (*this->Points)[i].y();
  148. float x2 = (*this->Points)[j].x();
  149. float y2 = (*this->Points)[j].y();
  150. float dx = x2 - x1;
  151. float dy = y2 - y1;
  152. if(x1 < area.left())
  153. {
  154. y1 += (dy * (area.left() - x1)) / dx;
  155. x1 = area.left();
  156. }
  157. else if(x1 > area.right())
  158. {
  159. y1 -= (dy * (x1 - area.right())) / dx;
  160. x1 = area.right();
  161. }
  162. if(x2 < area.left())
  163. {
  164. y2 += (dy * (area.left() - x2)) / dx;
  165. x2 = area.left();
  166. }
  167. else if(x2 > area.right())
  168. {
  169. y2 -= (dy * (x2 - area.right())) / dx;
  170. x2 = area.right();
  171. }
  172. // Check the new y codes.
  173. int code1 = vtkQtChartShape::getYBoundingBoxCode(y1, area);
  174. int code2 = vtkQtChartShape::getYBoundingBoxCode(y2, area);
  175. if((code1 & code2) != 0)
  176. {
  177. continue;
  178. }
  179. // Next, clip the y coordinates.
  180. if(y1 < area.top())
  181. {
  182. x1 += (dx * (area.top() - y1)) / dy;
  183. y1 = area.top();
  184. }
  185. else if(y1 < area.bottom())
  186. {
  187. x1 -= (dx * (y1 - area.bottom())) / dy;
  188. y1 = area.bottom();
  189. }
  190. if(y2 < area.top())
  191. {
  192. x2 += (dx * (area.top() - y2)) / dy;
  193. y2 = area.top();
  194. }
  195. else if(y2 < area.bottom())
  196. {
  197. x2 -= (dx * (y2 - area.bottom())) / dy;
  198. y2 = area.bottom();
  199. }
  200. // Check the new x codes.
  201. code1 = vtkQtChartShape::getXBoundingBoxCode(x1, area);
  202. code2 = vtkQtChartShape::getXBoundingBoxCode(x2, area);
  203. if((code1 & code2) != 0)
  204. {
  205. continue;
  206. }
  207. return true;
  208. }
  209. return false;
  210. }
  211. const QPolygonF &vtkQtChartQuad::getPoints() const
  212. {
  213. return *this->Points;
  214. }
  215. void vtkQtChartQuad::setPoints(const QPolygonF &points)
  216. {
  217. if(points.size() == 4)
  218. {
  219. *this->Points = points;
  220. }
  221. }
  222. void vtkQtChartQuad::setPoint(int index, const QPointF &point)
  223. {
  224. if(index >= 0 && index < 4)
  225. {
  226. (*this->Points)[index] = point;
  227. }
  228. }