summaryrefslogtreecommitdiff
path: root/tools/build/example/qt/qt4/hello/arrow.cpp
blob: e821b16909bbeb5c97f3ea9e059dd33a78062449 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright Vladimir Prus 2005.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)

#include "arrow.h"

#include <QtGui/qapplication.h>

#include <QtGui/qwidget.h>
#include <QtGui/qpainter.h>
#include <QtGui/qpainterpath.h>

#include <stdlib.h>
#include <math.h>

Arrow_widget::Arrow_widget(QWidget* parent) : QWidget(parent), color_(0)
{
    QPalette pal = palette();
    pal.setBrush(backgroundRole(), QBrush(Qt::white));
    setPalette(pal);
}

void Arrow_widget::slotChangeColor()
{
    color_ = (color_ + 1) % 3;
    update();
}

void 
Arrow_widget::draw_arrow(int x1, int y1, int x2, int y2, QPainter& painter)
{
    // The length of the from the tip of the arrow to the point
    // where line starts.
    const int arrowhead_length = 16;
    
    QPainterPath arrow;
    arrow.moveTo(x1, y1);
    
    // Determine the angle of the straight line.
    double a1 = (x2-x1);
    double a2 = (y2-y1);
    double b1 = 1;
    double b2 = 0;
    
    double straight_length = sqrt(a1*a1 + a2*a2);
    
    double dot_product = a1*b1 + a2*b2;
    double cosine = dot_product/
        (sqrt(pow(a1, 2) + pow(a2, 2))*sqrt(b1 + b2));
    double angle = acos(cosine);
    if (y1 < y2)
    {
        angle = -angle;
    }
    double straight_angle = angle*180/M_PI;
    
    double limit = 10;
    
    double angle_to_vertical;
    if (fabs(straight_angle) < 90)
        angle_to_vertical = fabs(straight_angle);
    else if (straight_angle > 0)
        angle_to_vertical = 180-straight_angle;
    else
        angle_to_vertical = 180-(-straight_angle);
    
    double angle_delta = 0;
    if (angle_to_vertical > limit)
        angle_delta = 30 * (angle_to_vertical - limit)/90;
    double start_angle = straight_angle > 0 
        ? straight_angle - angle_delta :
        straight_angle + angle_delta;
    
    
    QMatrix m1;
    m1.translate(x1, y1);
    m1.rotate(-start_angle);
    
    double end_angle = straight_angle > 0 
        ? (straight_angle + 180 + angle_delta) :
        (straight_angle + 180 - angle_delta);
    
    QMatrix m2;
    m2.reset();
    m2.translate(x2, y2);        
    m2.rotate(-end_angle);
    
    arrow.cubicTo(m1.map(QPointF(straight_length/2, 0)),              
                  m2.map(QPointF(straight_length/2, 0)),
                  m2.map(QPointF(arrowhead_length, 0)));
    
    painter.save();
    painter.setBrush(Qt::NoBrush);
    painter.drawPath(arrow);    
    painter.restore();
    
    painter.save();
    painter.translate(x2, y2);
    
    painter.rotate(-90);
    painter.rotate(-end_angle);
    painter.rotate(180);
    
    QPolygon arrowhead(4);
    arrowhead.setPoint(0, 0, 0);
    arrowhead.setPoint(1, arrowhead_length/3, -arrowhead_length*5/4);
    arrowhead.setPoint(2, 0, -arrowhead_length);
    arrowhead.setPoint(3, -arrowhead_length/3, -arrowhead_length*5/4);
    
    painter.drawPolygon(arrowhead);
    
    painter.restore();            
    
}


void Arrow_widget::paintEvent(QPaintEvent*)
{
    QPainter p(this);
    
    p.setRenderHint(QPainter::Antialiasing);
    
    int base_x = 550;
    int base_y = 200;

    if (color_ == 0)   
        p.setBrush(Qt::black);
    else if (color_ == 1)
        p.setBrush(Qt::green);
    else if (color_ == 2)
        p.setBrush(Qt::yellow);
    else
        p.setBrush(Qt::black);
    
    for (int x_step = 0; x_step < 6; ++x_step)
    {
        for (int y_step = 1; y_step <= 3; ++y_step)
        {
            draw_arrow(base_x, base_y, base_x+x_step*100, 
                       base_y - y_step*50, p);
            
            draw_arrow(base_x, base_y, base_x+x_step*100, 
                       base_y + y_step*50, p);
            
            draw_arrow(base_x, base_y, base_x-x_step*100, 
                       base_y + y_step*50, p);
            
            draw_arrow(base_x, base_y, base_x-x_step*100, 
                       base_y - y_step*50, p);
        }
    }

    draw_arrow(50, 400, 1000, 450, p);
    draw_arrow(1000, 400, 50, 450, p);
    
}