FreeCAD

Форк
0
/
CompassDialWidget.cpp 
260 строк · 9.4 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2022 WandererFan <wandererfan@gmail.com>                *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
//largely based on a python widget from:
24
//https://github.com/tcalmant/demo-ipopo-qt/blob/master/pc/details/compass.py
25

26
#include "PreCompiled.h"
27
#ifndef _PreComp_
28
#include <QtGui>
29
#endif
30

31
#include <Mod/TechDraw/TechDrawGlobal.h>
32

33
#include <Base/Console.h>
34
#include <Base/Tools.h>
35

36
#include "CompassDialWidget.h"
37

38
using namespace TechDrawGui;
39
using CardinalMap = std::map<int, std::string>;
40

41
CompassDialWidget::CompassDialWidget(QWidget* parent) : QWidget(parent),
42
    m_markInterval(15),
43
    m_defaultSize(75),
44
    m_defaultMargin(10),
45
    m_designRadius(64)
46
{
47
    setObjectName(QString::fromUtf8("Compass"));
48
    m_rect = QRect(0, 0, m_defaultSize, m_defaultSize);
49
    m_angle = 0.0;
50
    m_margin = m_defaultMargin;
51
    m_designDiameter = 2 * m_designRadius;
52

53
    QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
54
    sizePolicy.setHorizontalStretch(1);
55
    sizePolicy.setVerticalStretch(1);
56
    setSizePolicy(sizePolicy);
57

58
    repaint();
59
}
60

61
QSize CompassDialWidget::sizeHint() const
62
{
63
    return m_rect.size();
64
}
65

66
QSize CompassDialWidget::minimumSizeHint() const
67
{
68
    return QRect(0, 0, m_defaultSize, m_defaultSize).size();
69
}
70

71
void CompassDialWidget::paintEvent(QPaintEvent* event)
72
{
73
    Q_UNUSED(event);
74
    QPainter painter(this);
75
    drawWidget(painter);
76
    QWidget::paintEvent(event);
77
}
78

79
void CompassDialWidget::drawWidget(QPainter& painter)
80
{
81
    painter.setRenderHint(QPainter::Antialiasing, true);
82

83
    // Draw the background
84
    drawBackground(painter);
85

86
    //Draw the cardinal points
87
    drawMarkings(painter);
88

89
    //Draw the needle
90
    drawNeedle(painter);
91
}
92

93
void CompassDialWidget::drawBackground(QPainter& painter)
94
{
95
    painter.save();
96

97
    //Move to the center of the compass
98
    painter.translate(width() / 2, height() / 2);
99
    double scale = std::min((float) width() / (float) (m_designDiameter + 2.0 * m_margin),
100
                            (float) height() / (float) (m_designDiameter + 2.0 * m_margin));
101
    painter.scale(scale, scale);
102

103
    painter.setPen(QPen(Qt::NoPen));
104
    // Clear the background
105
    int circleWidth = 2.0 * (m_designRadius + m_margin);
106
    int circleHeight = 2.0 * (m_designRadius + m_margin);
107
    QRect circleRect(-circleWidth / 2, -circleHeight / 2, circleWidth, circleHeight);
108
    painter.drawEllipse(circleRect);
109
//    QRect backRect(-m_rect.width() / 2, -m_rect.height() / 2, m_rect.width(), m_rect.height());
110
    QPainterPath backPath;
111
    backPath.addEllipse(circleRect);
112
    painter.fillPath(backPath, palette().brush((QPalette::Window)));
113
//    painter.fillRect(backRect, palette().brush((QPalette::Window)));
114
    painter.restore();
115
}
116

117
//Draws the cardinal points on painter. This widget was designed such that
118
//the dial gradations extend to 50 units from center and the compass point text
119
//begins at 52 units from the center.  With the font size set to 12 pixels, this
120
//gives a design area of a circle with a radius of approximately 64 units.  All of
121
//the constants reflect this design size.
122
void CompassDialWidget::drawMarkings(QPainter& painter)
123
{
124
    CardinalMap CompassPointText( { {0, "Y"}, {45, "XY"}, {90, "X"}, {135, "X-Y"}, {180, "-Y"},
125
                                    {225, "-X-Y"}, {270, "-X"}, {315, "-XY"} } );
126
    painter.save();
127
    int markInterval(15);
128

129
    //Move to the center of the compass
130
    painter.translate(width() / 2, height() / 2);
131
    double scale = std::min((float) width() / (float) (m_designDiameter + 2.0 * m_margin),
132
                            (float) height() / (float) (m_designDiameter + 2.0 * m_margin));
133
    painter.scale(scale, scale);
134

135
    // Setup the fonts and the painter
136
    QFont widgetFont = font();
137
    widgetFont.setPixelSize(12);
138
    QFontMetrics metrics(widgetFont);
139

140
    //outer circle
141
    int circleWidth = 2.0 * (m_designRadius + m_margin);
142
    int circleHeight = 2.0 * (m_designRadius + m_margin);
143
    QRect circleRect(-circleWidth / 2, -circleHeight / 2, circleWidth, circleHeight);
144
    painter.drawEllipse(circleRect);
145

146
    painter.setFont(widgetFont);
147
    painter.setPen(QPen(palette().color(QPalette::WindowText)));
148

149
    int iDegree = 0;
150
    while ( iDegree < 360 ) {
151
        if (iDegree % 45 == 0) {
152
            //Named direction (every 45°)
153
            painter.drawLine(0, -40, 0, -50);    //this has to depend on m_rect or size?
154
            QString qPointText = Base::Tools::fromStdString(CompassPointText.at(iDegree));
155
            painter.drawText(-metrics.boundingRect(qPointText).width() / 2.0, -52, qPointText);
156
            // what is -52? line end point y = -50 + 2 for margin?
157
        } else {
158
            //Small line
159
            painter.drawLine(0, -45, 0, -50);
160
        }
161

162
        //Next line (+15°)
163
        painter.rotate(markInterval);
164
        iDegree += markInterval;
165
    }
166

167
    painter.restore();
168
}
169

170
//Draws a needle on painter
171
void CompassDialWidget::drawNeedle(QPainter& painter)
172
{
173
    painter.save();
174

175
    //Move to the center of the compass
176
    painter.translate(width() / 2, height() / 2);
177

178
    //Rotate to the correct angle
179
    painter.rotate(m_angle);
180
    double scale = std::min((float) width() / (float) (m_designDiameter + 2.0 * m_margin),
181
                            (float) height() / (float) (m_designDiameter + 2.0 * m_margin));
182
    painter.scale(scale, scale);
183

184
    //Setup the painter
185
    QPen needlePen(palette().color(QPalette::WindowText));
186
    needlePen.setWidth(2);
187
    needlePen.setStyle(Qt::DashDotLine);
188
    painter.setPen(needlePen);
189
    painter.setBrush(palette().color(QPalette::WindowText));
190

191
    //Draw the section line
192
    int sectionLineExtent(25);
193
    painter.drawLine(0, sectionLineExtent, 0, -sectionLineExtent);
194
    needlePen.setStyle(Qt::SolidLine);
195
    painter.setPen(needlePen);
196
    int viewDirectionExtent(15);
197
    painter.drawLine(-viewDirectionExtent, sectionLineExtent, 0, sectionLineExtent);
198
    painter.drawLine(-viewDirectionExtent, -sectionLineExtent, 0, -sectionLineExtent);
199

200
    //Draw the arrowheads of the needle section line
201
    needlePen.setWidth(1);
202
    needlePen.setStyle(Qt::SolidLine);
203
    painter.setPen(needlePen);
204
    int arrowLength(5);
205
    int arrowWidth(3);  //actual 1/2 width
206
    painter.drawPolygon(
207
        QPolygon( { QPoint(0, sectionLineExtent),
208
                    QPoint(-arrowLength, sectionLineExtent + arrowWidth),
209
                    QPoint(-arrowLength, sectionLineExtent - arrowWidth),
210
                    QPoint(0, sectionLineExtent) } ) );
211
    painter.drawPolygon(
212
        QPolygon( { QPoint(0, -sectionLineExtent),
213
                    QPoint(-arrowLength, -(sectionLineExtent + arrowWidth)),
214
                    QPoint(-arrowLength, -(sectionLineExtent - arrowWidth)),
215
                    QPoint(0, -sectionLineExtent) } ) );
216

217
    //draw the actual needle
218
    needlePen.setStyle(Qt::SolidLine);
219
    painter.setPen(needlePen);
220
    painter.setBrush(palette().color(QPalette::BrightText));
221
    int needleExtent(40);
222
    painter.drawPolygon(
223
        QPolygon( { QPoint(needleExtent, 0),
224
                    QPoint(0, 5),
225
                    QPoint(-15, 2),
226
                    QPoint(-15, -2),
227
                    QPoint(0, -5),
228
                    QPoint(needleExtent, 0) } ) );
229

230
    //draw needle pivot
231
    painter.setBrush(palette().color(QPalette::WindowText));
232
    int pivotSize(4);
233
    QRect pivotRect(-pivotSize / 2, -pivotSize / 2, pivotSize, pivotSize);
234
    painter.drawEllipse(pivotRect);
235

236
    //draw needle point
237
    painter.setBrush(QBrush(Qt::red));
238
    int pointLength(5);
239
    int pointWidth(3);
240
    painter.drawPolygon(
241
        QPolygon( { QPoint(needleExtent, 0),
242
                    QPoint(needleExtent - pointLength, pointWidth),
243
                    QPoint(needleExtent - pointLength, -pointWidth),
244
                    QPoint(needleExtent, 0) } ) );
245

246
    painter.restore();
247
}
248

249
//convert a conventional angle to a Qt angle and set the dial accordingly
250
void CompassDialWidget::setAngle(double newAngle)
251
{
252
    m_angle = fmod(360.0 - newAngle, 360.0);
253
    repaint();
254
}
255

256
void CompassDialWidget::setSize(int newSize)
257
{
258
    m_rect = QRect(0, 0, newSize, newSize);
259
    repaint();
260
}
261

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.