• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Vladimir Prus 2005.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt
4 // or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include "arrow.h"
7 
8 #include <QtGui/qapplication.h>
9 
10 #include <QtGui/qwidget.h>
11 #include <QtGui/qpainter.h>
12 #include <QtGui/qpainterpath.h>
13 
14 #include <stdlib.h>
15 #include <math.h>
16 
Arrow_widget(QWidget * parent)17 Arrow_widget::Arrow_widget(QWidget* parent) : QWidget(parent), color_(0)
18 {
19     QPalette pal = palette();
20     pal.setBrush(backgroundRole(), QBrush(Qt::white));
21     setPalette(pal);
22 }
23 
slotChangeColor()24 void Arrow_widget::slotChangeColor()
25 {
26     color_ = (color_ + 1) % 3;
27     update();
28 }
29 
30 void
draw_arrow(int x1,int y1,int x2,int y2,QPainter & painter)31 Arrow_widget::draw_arrow(int x1, int y1, int x2, int y2, QPainter& painter)
32 {
33     // The length of the from the tip of the arrow to the point
34     // where line starts.
35     const int arrowhead_length = 16;
36 
37     QPainterPath arrow;
38     arrow.moveTo(x1, y1);
39 
40     // Determine the angle of the straight line.
41     double a1 = (x2-x1);
42     double a2 = (y2-y1);
43     double b1 = 1;
44     double b2 = 0;
45 
46     double straight_length = sqrt(a1*a1 + a2*a2);
47 
48     double dot_product = a1*b1 + a2*b2;
49     double cosine = dot_product/
50         (sqrt(pow(a1, 2) + pow(a2, 2))*sqrt(b1 + b2));
51     double angle = acos(cosine);
52     if (y1 < y2)
53     {
54         angle = -angle;
55     }
56     double straight_angle = angle*180/M_PI;
57 
58     double limit = 10;
59 
60     double angle_to_vertical;
61     if (fabs(straight_angle) < 90)
62         angle_to_vertical = fabs(straight_angle);
63     else if (straight_angle > 0)
64         angle_to_vertical = 180-straight_angle;
65     else
66         angle_to_vertical = 180-(-straight_angle);
67 
68     double angle_delta = 0;
69     if (angle_to_vertical > limit)
70         angle_delta = 30 * (angle_to_vertical - limit)/90;
71     double start_angle = straight_angle > 0
72         ? straight_angle - angle_delta :
73         straight_angle + angle_delta;
74 
75 
76     QMatrix m1;
77     m1.translate(x1, y1);
78     m1.rotate(-start_angle);
79 
80     double end_angle = straight_angle > 0
81         ? (straight_angle + 180 + angle_delta) :
82         (straight_angle + 180 - angle_delta);
83 
84     QMatrix m2;
85     m2.reset();
86     m2.translate(x2, y2);
87     m2.rotate(-end_angle);
88 
89     arrow.cubicTo(m1.map(QPointF(straight_length/2, 0)),
90                   m2.map(QPointF(straight_length/2, 0)),
91                   m2.map(QPointF(arrowhead_length, 0)));
92 
93     painter.save();
94     painter.setBrush(Qt::NoBrush);
95     painter.drawPath(arrow);
96     painter.restore();
97 
98     painter.save();
99     painter.translate(x2, y2);
100 
101     painter.rotate(-90);
102     painter.rotate(-end_angle);
103     painter.rotate(180);
104 
105     QPolygon arrowhead(4);
106     arrowhead.setPoint(0, 0, 0);
107     arrowhead.setPoint(1, arrowhead_length/3, -arrowhead_length*5/4);
108     arrowhead.setPoint(2, 0, -arrowhead_length);
109     arrowhead.setPoint(3, -arrowhead_length/3, -arrowhead_length*5/4);
110 
111     painter.drawPolygon(arrowhead);
112 
113     painter.restore();
114 
115 }
116 
117 
paintEvent(QPaintEvent *)118 void Arrow_widget::paintEvent(QPaintEvent*)
119 {
120     QPainter p(this);
121 
122     p.setRenderHint(QPainter::Antialiasing);
123 
124     int base_x = 550;
125     int base_y = 200;
126 
127     if (color_ == 0)
128         p.setBrush(Qt::black);
129     else if (color_ == 1)
130         p.setBrush(Qt::green);
131     else if (color_ == 2)
132         p.setBrush(Qt::yellow);
133     else
134         p.setBrush(Qt::black);
135 
136     for (int x_step = 0; x_step < 6; ++x_step)
137     {
138         for (int y_step = 1; y_step <= 3; ++y_step)
139         {
140             draw_arrow(base_x, base_y, base_x+x_step*100,
141                        base_y - y_step*50, p);
142 
143             draw_arrow(base_x, base_y, base_x+x_step*100,
144                        base_y + y_step*50, p);
145 
146             draw_arrow(base_x, base_y, base_x-x_step*100,
147                        base_y + y_step*50, p);
148 
149             draw_arrow(base_x, base_y, base_x-x_step*100,
150                        base_y - y_step*50, p);
151         }
152     }
153 
154     draw_arrow(50, 400, 1000, 450, p);
155     draw_arrow(1000, 400, 50, 450, p);
156 
157 }
158 
159