FreeCAD

Форк
0
/
QuickMeasure.cpp 
223 строки · 8.2 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2023 Pierre-Louis Boyer <development@Ondsel.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
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
#include <cmath>
27
#include <vector>
28
#include <QTimer>
29
#endif
30

31
#include <App/Document.h>
32
#include <App/DocumentObject.h>
33
#include <App/Link.h>
34
#include <App/Part.h>
35
#include <Base/UnitsApi.h>
36
#include <Gui/Application.h>
37
#include <Gui/MainWindow.h>
38
#include <Gui/Selection.h>
39
#include <Gui/ViewProvider.h>
40

41
#include <Mod/Part/App/PartFeature.h>
42
#include <Mod/Part/App/TopoShape.h>
43

44
#include <Mod/Measure/App/Measurement.h>
45

46
#include "QuickMeasure.h"
47

48
using namespace Measure;
49
using namespace MeasureGui;
50

51
QuickMeasure::QuickMeasure(QObject* parent)
52
    : QObject(parent)
53
    , measurement {new Measure::Measurement()}
54
{
55
    selectionTimer = new QTimer(this);
56
    pendingProcessing = false;
57
    connect(selectionTimer, &QTimer::timeout, this, &QuickMeasure::processSelection);
58
}
59

60
QuickMeasure::~QuickMeasure()
61
{
62
    delete selectionTimer;
63
    delete measurement;
64
}
65

66
void QuickMeasure::onSelectionChanged(const Gui::SelectionChanges& msg)
67
{
68
    if (canMeasureSelection(msg)) {
69
        if (!pendingProcessing) {
70
            selectionTimer->start(100);
71
        }
72
        pendingProcessing = true;
73
    }
74
}
75

76
void QuickMeasure::processSelection()
77
{
78
    if (pendingProcessing) {
79
        pendingProcessing = false;
80
        try {
81
            tryMeasureSelection();
82
        }
83
        catch (const Base::IndexError&) {
84
            // ignore this exception because it can be caused by trying to access a non-existing
85
            // sub-element e.g. when selecting a construction geometry in sketcher
86
        }
87
        catch (const Base::ValueError&) {
88
            // ignore this exception because it can be caused by trying to access a non-existing
89
            // sub-element e.g. when selecting a constraint in sketcher
90
        }
91
        catch (const Base::Exception& e) {
92
            e.ReportException();
93
        }
94
    }
95
}
96

97
void QuickMeasure::tryMeasureSelection()
98
{
99
    measurement->clear();
100
    addSelectionToMeasurement();
101
    printResult();
102
}
103

104
bool QuickMeasure::canMeasureSelection(const Gui::SelectionChanges& msg) const
105
{
106
    if (msg.Type == Gui::SelectionChanges::SetPreselect
107
        || msg.Type == Gui::SelectionChanges::RmvPreselect) {
108
        return false;
109
    }
110

111
    Gui::Document* doc = Gui::Application::Instance->activeDocument();
112
    return doc != nullptr;
113
}
114

115
void QuickMeasure::addSelectionToMeasurement()
116
{
117
    int count = 0;
118
    int limit = 100;
119

120
    for (auto& selObj : Gui::Selection().getSelectionEx()) {
121
        App::DocumentObject* obj = selObj.getObject();
122

123
        std::string vpType = obj->getViewProviderName();
124
        auto* vp = Gui::Application::Instance->getViewProvider(obj);
125
        if ((vpType == "SketcherGui::ViewProviderSketch" && vp->isEditing())
126
            || vpType.find("Gui::ViewProviderOrigin") != std::string::npos
127
            || vpType.find("Gui::ViewProviderPart") != std::string::npos
128
            || vpType.find("SpreadsheetGui") != std::string::npos
129
            || vpType.find("TechDrawGui") != std::string::npos) {
130
            continue;
131
        }
132

133
        const std::vector<std::string> subNames = selObj.getSubNames();
134

135
        // Check that there's not too many selection
136
        count += subNames.empty() ? 1 : subNames.size();
137
        if (count > limit) {
138
            measurement->clear();
139
            return;
140
        }
141

142
        if (subNames.empty()) {
143
            measurement->addReference3D(obj, "");
144
        }
145
        else {
146
            for (auto& subName : subNames) {
147
                measurement->addReference3D(obj, subName);
148
            }
149
        }
150
    }
151
}
152

153
void QuickMeasure::printResult()
154
{
155
    MeasureType mtype = measurement->getType();
156
    if (mtype == MeasureType::Surfaces) {
157
        Base::Quantity area(measurement->area(), Base::Unit::Area);
158
        print(tr("Total area: %1").arg(area.getUserString()));
159
    }
160
    /* deactivated because computing the volumes/area of solids makes a significant
161
    slow down in selection of complex solids.
162
    else if (mtype == MeasureType::Volumes) {
163
        Base::Quantity area(measurement->area(), Base::Unit::Area);
164
        Base::Quantity vol(measurement->volume(), Base::Unit::Volume);
165
        print(tr("Volume: %1, Area:
166
    %2").arg(vol.getSafeUserString()).arg(area.getSafeUserString()));
167
    }*/
168
    else if (mtype == MeasureType::TwoPlanes) {
169
        Base::Quantity dist(measurement->planePlaneDistance(), Base::Unit::Length);
170
        print(tr("Nominal distance: %1").arg(dist.getSafeUserString()));
171
    }
172
    else if (mtype == MeasureType::Cone || mtype == MeasureType::Plane) {
173
        Base::Quantity area(measurement->area(), Base::Unit::Area);
174
        print(tr("Area: %1").arg(area.getUserString()));
175
    }
176
    else if (mtype == MeasureType::Cylinder || mtype == MeasureType::Sphere
177
             || mtype == MeasureType::Torus) {
178
        Base::Quantity area(measurement->area(), Base::Unit::Area);
179
        Base::Quantity rad(measurement->radius(), Base::Unit::Length);
180
        print(tr("Area: %1, Radius: %2").arg(area.getSafeUserString(), rad.getSafeUserString()));
181
    }
182
    else if (mtype == MeasureType::Edges) {
183
        Base::Quantity dist(measurement->length(), Base::Unit::Length);
184
        print(tr("Total length: %1").arg(dist.getSafeUserString()));
185
    }
186
    else if (mtype == MeasureType::TwoParallelLines) {
187
        Base::Quantity dist(measurement->lineLineDistance(), Base::Unit::Length);
188
        print(tr("Nominal distance: %1").arg(dist.getSafeUserString()));
189
    }
190
    else if (mtype == MeasureType::TwoLines) {
191
        Base::Quantity angle(measurement->angle(), Base::Unit::Length);
192
        Base::Quantity dist(measurement->length(), Base::Unit::Length);
193
        print(tr("Angle: %1, Total length: %2")
194
                  .arg(angle.getSafeUserString(), dist.getSafeUserString()));
195
    }
196
    else if (mtype == MeasureType::Line) {
197
        Base::Quantity dist(measurement->length(), Base::Unit::Length);
198
        print(tr("Length: %1").arg(dist.getSafeUserString()));
199
    }
200
    else if (mtype == MeasureType::Circle) {
201
        Base::Quantity dist(measurement->radius(), Base::Unit::Length);
202
        print(tr("Radius: %1").arg(dist.getSafeUserString()));
203
    }
204
    else if (mtype == MeasureType::PointToPoint) {
205
        Base::Quantity dist(measurement->length(), Base::Unit::Length);
206
        print(tr("Distance: %1").arg(dist.getSafeUserString()));
207
    }
208
    else if (mtype == MeasureType::PointToEdge || mtype == MeasureType::PointToSurface) {
209
        Base::Quantity dist(measurement->length(), Base::Unit::Length);
210
        print(tr("Minimum distance: %1").arg(dist.getSafeUserString()));
211
    }
212
    else {
213
        print(QString::fromLatin1(""));
214
    }
215
}
216

217
void QuickMeasure::print(const QString& message)
218
{
219
    Gui::getMainWindow()->setRightSideMessage(message);
220
}
221

222

223
#include "moc_QuickMeasure.cpp"
224

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

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

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

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