GraphicsArrowItem.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "GraphicsArrowItem.h"
  2. GraphicsArrowItem::GraphicsArrowItem(const QPointF &start,
  3. const QPointF &end,
  4. QGraphicsItem *parent)
  5. : QGraphicsItem(parent)
  6. {
  7. len = 16;
  8. startPos = start;
  9. endPos = end;
  10. }
  11. QRectF GraphicsArrowItem::boundingRect() const
  12. {
  13. QPainterPath path = getArrowsPath(startPos, endPos, len);
  14. return path.controlPointRect();
  15. }
  16. void GraphicsArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *w)
  17. {
  18. QPen pen =painter->pen();
  19. pen.setWidth(4);
  20. pen.setColor(_mColor);
  21. painter->setPen(pen);
  22. if(startPos !=endPos)
  23. {
  24. QPainterPath path = getArrowsPath(startPos, endPos, len);
  25. painter->drawPath(path);
  26. }
  27. }
  28. QLineF getEllipseAndLineNodes(qreal k, qreal b, qreal c, qreal d, qreal r)
  29. {
  30. // 求圆和直线的交点坐标
  31. // y = kx +b
  32. // (x+c)^2 + (y+d)^2 = r^2
  33. qreal temp1 = sqrt((k*k+1)*r*r - c*c*k*k + (2*c*d + 2*b*c)*k - d*d -2*b*d -b*b);
  34. qreal temp2 = (d+b)*k+c;
  35. qreal temp3 = k*k + 1;
  36. qreal x1 = -(temp1 + temp2) / temp3;
  37. qreal x2 = (temp1 - temp2) / temp3;
  38. qreal temp4 = sqrt(k*k*r*r + r*r - c*c*k*k + 2*c*d*k + 2*b*c*k - d*d - 2*b*d - b*b);
  39. qreal y1 = -(k*(c+temp4) +d*k*k-b) / temp3;
  40. qreal y2 = -(k*(c-temp4) +d*k*k-b) / temp3;
  41. return QLineF(QPointF(x1, y1), QPointF(x2, y2));
  42. }
  43. QLineF getVerticalLine(const QPointF &start,
  44. const QPointF &end,
  45. qreal distance,
  46. qreal len)
  47. {
  48. // 直线方程: y = kx + b
  49. if (end.y() != start.y() && end.x() != start.x()) // 不垂直X轴
  50. {
  51. qreal k = (start.y() - end.y()) / (start.x() - end.x());
  52. qreal b = start.y() - k * start.x();
  53. qreal c = -start.x();
  54. qreal d = -start.y();
  55. qreal r = distance;
  56. // 求圆和直线的交点坐标
  57. QLineF nodes = getEllipseAndLineNodes(k, b, c, d, r);
  58. qreal x,y; //交点
  59. if (start.x() > end.x())
  60. {
  61. if (nodes.x1() < nodes.x2())
  62. {
  63. x = nodes.x1();
  64. y = nodes.y1();
  65. }
  66. else
  67. {
  68. x = nodes.x2();
  69. y = nodes.y2();
  70. }
  71. }
  72. else
  73. {
  74. if (nodes.x1() > nodes.x2())
  75. {
  76. x = nodes.x1();
  77. y = nodes.y1();
  78. }
  79. else
  80. {
  81. x = nodes.x2();
  82. y = nodes.y2();
  83. }
  84. }
  85. qreal k1 = -1/k;
  86. qreal b1 = y - k1 * x;
  87. qreal c1 = -x;
  88. qreal d1 = -y;
  89. qreal r1 = len / 2;
  90. return getEllipseAndLineNodes(k1, b1, c1, d1, r1);
  91. }
  92. else
  93. {
  94. QLineF line;
  95. int dire;
  96. if (end.x() == start.x())
  97. {
  98. dire = end.y() > start.y() ? 1:-1;
  99. line = QLineF(QPointF(start.x() - len / 2, start.y() + (distance * dire)),
  100. QPointF(start.x() + len / 2, start.y() + (distance * dire)));
  101. }
  102. else
  103. {
  104. dire = end.x() > start.x() ? 1:-1;
  105. line = QLineF(QPointF(start.x() + (distance * dire), start.y() - len / 2),
  106. QPointF(start.x() + (distance * dire), start.y() + len / 2));
  107. }
  108. return line;
  109. }
  110. }
  111. QPainterPath GraphicsArrowItem::getArrowsPath(const QPointF &start,
  112. const QPointF &end,
  113. qreal len) const
  114. {
  115. QPainterPath path;
  116. path.moveTo(startPos);
  117. QLineF line1 = getVerticalLine(endPos, startPos, len * sqrt(3) / 2, len / 2);
  118. QLineF line2 = getVerticalLine(endPos, startPos, len * sqrt(3) / 2, len);
  119. path.lineTo(line1.p1());
  120. path.lineTo(line2.p1());
  121. path.lineTo(endPos);
  122. path.lineTo(line2.p2());
  123. path.lineTo(line1.p2());
  124. path.lineTo(startPos);
  125. return path;
  126. }