FreeCAD

Форк
0
/
ViewProviderInspection.cpp 
803 строки · 28.7 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net>     *
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 <QApplication>
27
#include <QMenu>
28
#include <QMessageBox>
29

30
#include <Inventor/SoPickedPoint.h>
31
#include <Inventor/actions/SoRayPickAction.h>
32
#include <Inventor/actions/SoSearchAction.h>
33
#include <Inventor/details/SoFaceDetail.h>
34
#include <Inventor/errors/SoDebugError.h>
35
#include <Inventor/events/SoButtonEvent.h>
36
#include <Inventor/events/SoKeyboardEvent.h>
37
#include <Inventor/events/SoMouseButtonEvent.h>
38
#include <Inventor/nodes/SoCoordinate3.h>
39
#include <Inventor/nodes/SoDrawStyle.h>
40
#include <Inventor/nodes/SoIndexedFaceSet.h>
41
#include <Inventor/nodes/SoIndexedLineSet.h>
42
#include <Inventor/nodes/SoMaterial.h>
43
#include <Inventor/nodes/SoMaterialBinding.h>
44
#include <Inventor/nodes/SoNormal.h>
45
#include <Inventor/nodes/SoPointSet.h>
46
#include <Inventor/nodes/SoShapeHints.h>
47
#endif
48

49
#include <App/GeoFeature.h>
50
#include <Gui/Application.h>
51
#include <Gui/Document.h>
52
#include <Gui/Flag.h>
53
#include <Gui/MainWindow.h>
54
#include <Gui/SoFCColorBar.h>
55
#include <Gui/View3DInventorViewer.h>
56
#include <Gui/Widgets.h>
57
#include <Mod/Inspection/App/InspectionFeature.h>
58
#include <Mod/Points/App/Properties.h>
59

60
#include "ViewProviderInspection.h"
61

62

63
using namespace InspectionGui;
64

65

66
bool ViewProviderInspection::addflag = false;
67
App::PropertyFloatConstraint::Constraints ViewProviderInspection::floatRange = {1.0, 64.0, 1.0};
68

69
PROPERTY_SOURCE(InspectionGui::ViewProviderInspection, Gui::ViewProviderDocumentObject)
70

71
ViewProviderInspection::ViewProviderInspection()
72
{
73
    ADD_PROPERTY_TYPE(OutsideGrayed,
74
                      (false),
75
                      "",
76
                      (App::PropertyType)(App::Prop_Output | App::Prop_Hidden),
77
                      "");
78
    ADD_PROPERTY_TYPE(PointSize,
79
                      (1.0),
80
                      "Display",
81
                      (App::PropertyType)(App::Prop_None /*App::Prop_Hidden*/),
82
                      "");
83
    PointSize.setConstraints(&floatRange);
84

85
    pcColorRoot = new SoSeparator();
86
    pcColorRoot->ref();
87
    pcMatBinding = new SoMaterialBinding;
88
    pcMatBinding->ref();
89
    pcColorMat = new SoMaterial;
90
    pcColorMat->ref();
91
    pcColorStyle = new SoDrawStyle();
92
    pcColorRoot->addChild(pcColorStyle);
93
    pcCoords = new SoCoordinate3;
94
    pcCoords->ref();
95
    // simple color bar
96
    pcColorBar = new Gui::SoFCColorBar;
97
    pcColorBar->Attach(this);
98
    pcColorBar->ref();
99
    pcColorBar->setRange(-0.1f, 0.1f, 3);
100
    pcLinkRoot = new SoGroup;
101
    pcLinkRoot->ref();
102

103
    pcPointStyle = new SoDrawStyle();
104
    pcPointStyle->ref();
105
    pcPointStyle->style = SoDrawStyle::POINTS;
106
    pcPointStyle->pointSize = PointSize.getValue();
107
    SelectionStyle.setValue(1);  // BBOX
108
}
109

110
ViewProviderInspection::~ViewProviderInspection()
111
{
112
    pcColorRoot->unref();
113
    pcCoords->unref();
114
    pcMatBinding->unref();
115
    pcColorMat->unref();
116
    pcColorBar->Detach(this);
117
    pcColorBar->unref();
118
    pcLinkRoot->unref();
119
    pcPointStyle->unref();
120
}
121

122
void ViewProviderInspection::onChanged(const App::Property* prop)
123
{
124
    if (prop == &OutsideGrayed) {
125
        if (pcColorBar) {
126
            pcColorBar->setOutsideGrayed(OutsideGrayed.getValue());
127
            pcColorBar->Notify(0);
128
        }
129
    }
130
    else if (prop == &PointSize) {
131
        pcPointStyle->pointSize = PointSize.getValue();
132
    }
133
    else {
134
        inherited::onChanged(prop);
135
    }
136
}
137

138
void ViewProviderInspection::hide()
139
{
140
    inherited::hide();
141
    pcColorStyle->style = SoDrawStyle::INVISIBLE;
142
}
143

144
void ViewProviderInspection::show()
145
{
146
    inherited::show();
147
    pcColorStyle->style = SoDrawStyle::FILLED;
148
}
149

150
void ViewProviderInspection::attach(App::DocumentObject* pcFeat)
151
{
152
    // creates the standard viewing modes
153
    inherited::attach(pcFeat);
154

155
    SoShapeHints* flathints = new SoShapeHints;
156
    flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
157
    flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
158

159
    SoGroup* pcColorShadedRoot = new SoGroup();
160
    pcColorShadedRoot->addChild(flathints);
161

162
    // color shaded  ------------------------------------------
163
    SoDrawStyle* pcFlatStyle = new SoDrawStyle();
164
    pcFlatStyle->style = SoDrawStyle::FILLED;
165
    pcColorShadedRoot->addChild(pcFlatStyle);
166

167
    pcColorShadedRoot->addChild(pcColorMat);
168
    pcColorShadedRoot->addChild(pcMatBinding);
169
    pcColorShadedRoot->addChild(pcLinkRoot);
170

171
    addDisplayMaskMode(pcColorShadedRoot, "ColorShaded");
172

173
    // Check for an already existing color bar
174
    Gui::SoFCColorBar* pcBar =
175
        ((Gui::SoFCColorBar*)findFrontRootOfType(Gui::SoFCColorBar::getClassTypeId()));
176
    if (pcBar) {
177
        float fMin = pcColorBar->getMinValue();
178
        float fMax = pcColorBar->getMaxValue();
179

180
        // Attach to the foreign color bar and delete our own bar
181
        pcBar->Attach(this);
182
        pcBar->ref();
183
        pcBar->setRange(fMin, fMax, 3);
184
        pcBar->Notify(0);
185
        pcColorBar->Detach(this);
186
        pcColorBar->unref();
187
        pcColorBar = pcBar;
188
    }
189

190
    pcColorRoot->addChild(pcColorBar);
191
}
192

193
bool ViewProviderInspection::setupFaces(const Data::ComplexGeoData* data)
194
{
195
    std::vector<Base::Vector3d> points;
196
    std::vector<Data::ComplexGeoData::Facet> faces;
197

198
    // set the Distance property to the correct size to sync size of material node with number
199
    // of vertices/points of the referenced geometry
200
    double accuracy = data->getAccuracy();
201
    data->getFaces(points, faces, accuracy);
202
    if (faces.empty()) {
203
        return false;
204
    }
205

206
    setupCoords(points);
207
    setupFaceIndexes(faces);
208
    return true;
209
}
210

211
bool ViewProviderInspection::setupLines(const Data::ComplexGeoData* data)
212
{
213
    std::vector<Base::Vector3d> points;
214
    std::vector<Data::ComplexGeoData::Line> lines;
215

216
    double accuracy = data->getAccuracy();
217
    data->getLines(points, lines, accuracy);
218
    if (lines.empty()) {
219
        return false;
220
    }
221

222
    setupCoords(points);
223
    setupLineIndexes(lines);
224
    return true;
225
}
226

227
bool ViewProviderInspection::setupPoints(const Data::ComplexGeoData* data,
228
                                         App::PropertyContainer* container)
229
{
230
    std::vector<Base::Vector3d> points;
231
    std::vector<Base::Vector3f> normals;
232
    std::vector<Base::Vector3d> normals_d;
233
    double accuracy = data->getAccuracy();
234
    data->getPoints(points, normals_d, accuracy);
235
    if (points.empty()) {
236
        return false;
237
    }
238

239
    normals.reserve(normals_d.size());
240
    std::transform(normals_d.cbegin(),
241
                   normals_d.cend(),
242
                   std::back_inserter(normals),
243
                   [](const Base::Vector3d& p) {
244
                       return Base::toVector<float>(p);
245
                   });
246

247
    // If getPoints() doesn't deliver normals check a second property
248
    if (normals.empty() && container) {
249
        App::Property* propN = container->getPropertyByName("Normal");
250
        if (propN && propN->isDerivedFrom<Points::PropertyNormalList>()) {
251
            normals = static_cast<Points::PropertyNormalList*>(propN)->getValues();
252
        }
253
    }
254

255
    setupCoords(points);
256
    if (!normals.empty() && normals.size() == points.size()) {
257
        setupNormals(normals);
258
    }
259

260
    this->pcLinkRoot->addChild(this->pcPointStyle);
261
    this->pcLinkRoot->addChild(new SoPointSet());
262

263
    return true;
264
}
265

266
void ViewProviderInspection::setupCoords(const std::vector<Base::Vector3d>& points)
267
{
268
    this->pcLinkRoot->addChild(this->pcCoords);
269
    this->pcCoords->point.setNum(points.size());
270
    SbVec3f* pts = this->pcCoords->point.startEditing();
271
    for (size_t i = 0; i < points.size(); i++) {
272
        const Base::Vector3d& p = points[i];
273
        pts[i].setValue((float)p.x, (float)p.y, (float)p.z);
274
    }
275
    this->pcCoords->point.finishEditing();
276
}
277

278
void ViewProviderInspection::setupNormals(const std::vector<Base::Vector3f>& normals)
279
{
280
    SoNormal* normalNode = new SoNormal();
281
    normalNode->vector.setNum(normals.size());
282
    SbVec3f* norm = normalNode->vector.startEditing();
283

284
    std::size_t i = 0;
285
    for (const auto& it : normals) {
286
        norm[i++].setValue(it.x, it.y, it.z);
287
    }
288

289
    normalNode->vector.finishEditing();
290
    this->pcLinkRoot->addChild(normalNode);
291
}
292

293
void ViewProviderInspection::setupLineIndexes(const std::vector<Data::ComplexGeoData::Line>& lines)
294
{
295
    SoIndexedLineSet* line = new SoIndexedLineSet();
296
    this->pcLinkRoot->addChild(line);
297
    line->coordIndex.setNum(3 * lines.size());
298
    int32_t* indices = line->coordIndex.startEditing();
299
    unsigned long j = 0;
300
    for (const auto& it : lines) {
301
        indices[3 * j + 0] = it.I1;
302
        indices[3 * j + 1] = it.I2;
303
        indices[3 * j + 2] = SO_END_LINE_INDEX;
304
        j++;
305
    }
306
    line->coordIndex.finishEditing();
307
}
308

309
void ViewProviderInspection::setupFaceIndexes(const std::vector<Data::ComplexGeoData::Facet>& faces)
310
{
311
    SoIndexedFaceSet* face = new SoIndexedFaceSet();
312
    this->pcLinkRoot->addChild(face);
313
    face->coordIndex.setNum(4 * faces.size());
314
    int32_t* indices = face->coordIndex.startEditing();
315
    unsigned long j = 0;
316
    for (const auto& it : faces) {
317
        indices[4 * j + 0] = it.I1;
318
        indices[4 * j + 1] = it.I2;
319
        indices[4 * j + 2] = it.I3;
320
        indices[4 * j + 3] = SO_END_FACE_INDEX;
321
        j++;
322
    }
323
    face->coordIndex.finishEditing();
324
}
325

326
void ViewProviderInspection::updateData(const App::Property* prop)
327
{
328
    // set to the expected size
329
    if (prop->isDerivedFrom<App::PropertyLink>()) {
330
        App::GeoFeature* object =
331
            static_cast<const App::PropertyLink*>(prop)->getValue<App::GeoFeature*>();
332
        const App::PropertyComplexGeoData* propData =
333
            object ? object->getPropertyOfGeometry() : nullptr;
334
        if (propData) {
335
            Gui::coinRemoveAllChildren(this->pcLinkRoot);
336

337
            const Data::ComplexGeoData* data = propData->getComplexData();
338
            if (!setupFaces(data)) {
339
                if (!setupLines(data)) {
340
                    setupPoints(data, object);
341
                }
342
            }
343
        }
344
    }
345
    else if (prop->is<Inspection::PropertyDistanceList>()) {
346
        // force an update of the Inventor data nodes
347
        if (this->pcObject) {
348
            App::Property* link = this->pcObject->getPropertyByName("Actual");
349
            if (link) {
350
                updateData(link);
351
            }
352
            setDistances();
353
        }
354
    }
355
    else if (prop->is<App::PropertyFloat>()) {
356
        if (strcmp(prop->getName(), "SearchRadius") == 0) {
357
            float fSearchRadius = ((App::PropertyFloat*)prop)->getValue();
358
            this->search_radius = fSearchRadius;
359
            pcColorBar->setRange(-fSearchRadius, fSearchRadius, 4);
360
            pcColorBar->Notify(0);
361
        }
362
    }
363
}
364

365
SoSeparator* ViewProviderInspection::getFrontRoot() const
366
{
367
    return pcColorRoot;
368
}
369

370
void ViewProviderInspection::setDistances()
371
{
372
    if (!pcObject) {
373
        return;
374
    }
375

376
    App::Property* pDistances = pcObject->getPropertyByName("Distances");
377
    if (!pDistances) {
378
        SoDebugError::post("ViewProviderInspection::setDistances", "Unknown property 'Distances'");
379
        return;
380
    }
381
    if (pDistances->getTypeId() != Inspection::PropertyDistanceList::getClassTypeId()) {
382
        SoDebugError::post(
383
            "ViewProviderInspection::setDistances",
384
            "Property 'Distances' has type %s (Inspection::PropertyDistanceList was expected)",
385
            pDistances->getTypeId().getName());
386
        return;
387
    }
388

389
    // distance values
390
    const std::vector<float>& fValues =
391
        static_cast<Inspection::PropertyDistanceList*>(pDistances)->getValues();
392
    if ((int)fValues.size() != this->pcCoords->point.getNum()) {
393
        pcMatBinding->value = SoMaterialBinding::OVERALL;
394
        return;
395
    }
396

397
    if (pcColorMat->diffuseColor.getNum() != static_cast<int>(fValues.size())) {
398
        pcColorMat->diffuseColor.setNum(static_cast<int>(fValues.size()));
399
    }
400
    if (pcColorMat->transparency.getNum() != static_cast<int>(fValues.size())) {
401
        pcColorMat->transparency.setNum(static_cast<int>(fValues.size()));
402
    }
403

404
    SbColor* cols = pcColorMat->diffuseColor.startEditing();
405
    float* tran = pcColorMat->transparency.startEditing();
406

407
    unsigned long j = 0;
408
    for (std::vector<float>::const_iterator jt = fValues.begin(); jt != fValues.end(); ++jt, j++) {
409
        App::Color col = pcColorBar->getColor(*jt);
410
        cols[j] = SbColor(col.r, col.g, col.b);
411
        if (pcColorBar->isVisible(*jt)) {
412
            tran[j] = 0.0f;
413
        }
414
        else {
415
            tran[j] = 0.8f;
416
        }
417
    }
418

419
    pcColorMat->diffuseColor.finishEditing();
420
    pcColorMat->transparency.finishEditing();
421
    pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
422
}
423

424
QIcon ViewProviderInspection::getIcon() const
425
{
426
    // Get the icon of the view provider to the associated feature
427
    QIcon px = inherited::getIcon();
428
    App::Property* pActual = pcObject->getPropertyByName("Actual");
429
    if (pActual && pActual->isDerivedFrom<App::PropertyLink>()) {
430
        App::DocumentObject* docobj = ((App::PropertyLink*)pActual)->getValue();
431
        if (docobj) {
432
            Gui::Document* doc = Gui::Application::Instance->getDocument(docobj->getDocument());
433
            Gui::ViewProvider* view = doc->getViewProvider(docobj);
434
            px = view->getIcon();
435
        }
436
    }
437

438
    return px;
439
}
440

441
void ViewProviderInspection::setDisplayMode(const char* ModeName)
442
{
443
    if (strcmp("Visual Inspection", ModeName) == 0) {
444
        setDistances();
445
        setDisplayMaskMode("ColorShaded");
446
    }
447

448
    inherited::setDisplayMode(ModeName);
449
}
450

451
std::vector<std::string> ViewProviderInspection::getDisplayModes() const
452
{
453
    // add modes
454
    std::vector<std::string> StrList;
455
    StrList.emplace_back("Visual Inspection");
456
    return StrList;
457
}
458

459
void ViewProviderInspection::OnChange(Base::Subject<int>& /*rCaller*/, int /*rcReason*/)
460
{
461
    setActiveMode();
462
}
463

464
namespace InspectionGui
465
{
466
// Proxy class that receives an asynchronous custom event
467
class ViewProviderProxyObject: public QObject
468
{
469
public:
470
    explicit ViewProviderProxyObject(QWidget* w)
471
        : QObject(nullptr)
472
        , widget(w)
473
    {}
474
    ~ViewProviderProxyObject() override = default;
475
    void customEvent(QEvent*) override
476
    {
477
        if (!widget.isNull()) {
478
            QList<Gui::Flag*> flags = widget->findChildren<Gui::Flag*>();
479
            if (!flags.isEmpty()) {
480
                int ret =
481
                    QMessageBox::question(Gui::getMainWindow(),
482
                                          QObject::tr("Remove annotations"),
483
                                          QObject::tr("Do you want to remove all annotations?"),
484
                                          QMessageBox::Yes,
485
                                          QMessageBox::No);
486
                if (ret == QMessageBox::Yes) {
487
                    for (auto it : flags) {
488
                        it->deleteLater();
489
                    }
490
                }
491
            }
492
        }
493

494
        this->deleteLater();
495
    }
496

497
    static void
498
    addFlag(Gui::View3DInventorViewer* view, const QString& text, const SoPickedPoint* point)
499
    {
500
        Gui::Flag* flag = new Gui::Flag;
501
        QPalette p;
502
        p.setColor(QPalette::Window, QColor(85, 0, 127));
503
        p.setColor(QPalette::Text, QColor(220, 220, 220));
504
        flag->setPalette(p);
505
        flag->setText(text);
506
        flag->setOrigin(point->getPoint());
507
        Gui::GLFlagWindow* flags = nullptr;
508
        std::list<Gui::GLGraphicsItem*> glItems =
509
            view->getGraphicsItemsOfType(Gui::GLFlagWindow::getClassTypeId());
510
        if (glItems.empty()) {
511
            flags = new Gui::GLFlagWindow(view);
512
            view->addGraphicsItem(flags);
513
        }
514
        else {
515
            flags = static_cast<Gui::GLFlagWindow*>(glItems.front());
516
        }
517
        flags->addFlag(flag, Gui::FlagLayout::BottomLeft);
518
    }
519

520
private:
521
    QPointer<QWidget> widget;
522
};
523
}  // namespace InspectionGui
524

525
void ViewProviderInspection::inspectCallback(void* ud, SoEventCallback* n)
526
{
527
    Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
528
    const SoEvent* ev = n->getEvent();
529
    if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
530
        const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(ev);
531

532
        // Mark all incoming mouse button events as handled, especially, to deactivate the selection
533
        // node
534
        n->getAction()->setHandled();
535
        n->setHandled();
536
        if (mbe->getButton() == SoMouseButtonEvent::BUTTON2
537
            && mbe->getState() == SoButtonEvent::UP) {
538
            n->setHandled();
539
            // context-menu
540
            QMenu menu;
541
            QAction* fl = menu.addAction(QObject::tr("Annotation"));
542
            fl->setCheckable(true);
543
            fl->setChecked(addflag);
544
            QAction* cl = menu.addAction(QObject::tr("Leave info mode"));
545
            QAction* id = menu.exec(QCursor::pos());
546
            if (fl == id) {
547
                addflag = fl->isChecked();
548
            }
549
            else if (cl == id) {
550
                // post an event to a proxy object to make sure to avoid problems
551
                // when opening a modal dialog
552
                QApplication::postEvent(new ViewProviderProxyObject(view->getGLWidget()),
553
                                        new QEvent(QEvent::User));
554
                view->setEditing(false);
555
                view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
556
                view->setRedirectToSceneGraph(false);
557
                view->setRedirectToSceneGraphEnabled(false);
558
                view->setSelectionEnabled(true);
559
                view->removeEventCallback(SoButtonEvent::getClassTypeId(), inspectCallback, ud);
560
            }
561
        }
562
        else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1
563
                 && mbe->getState() == SoButtonEvent::UP) {
564
            const SoPickedPoint* point = n->getPickedPoint();
565
            if (!point) {
566
                Base::Console().Message("No point picked.\n");
567
                return;
568
            }
569

570
            n->setHandled();
571

572
            // check if we have picked one a node of the view provider we are insterested in
573
            Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());
574
            if (vp && vp->isDerivedFrom<ViewProviderInspection>()) {
575
                ViewProviderInspection* that = static_cast<ViewProviderInspection*>(vp);
576
                QString info = that->inspectDistance(point);
577
                Gui::getMainWindow()->setPaneText(1, info);
578
                if (addflag) {
579
                    ViewProviderProxyObject::addFlag(view, info, point);
580
                }
581
                else {
582
                    Gui::ToolTip::showText(QCursor::pos(), info);
583
                }
584
            }
585
            else {
586
                // the nearest picked point was not part of the view provider
587
                SoRayPickAction action(view->getSoRenderManager()->getViewportRegion());
588
                action.setPickAll(true);
589
                action.setPoint(mbe->getPosition());
590
                action.apply(view->getSoRenderManager()->getSceneGraph());
591

592
                const SoPickedPointList& pps = action.getPickedPointList();
593
                for (int i = 0; i < pps.getLength(); ++i) {
594
                    const SoPickedPoint* point = pps[i];
595
                    vp = view->getViewProviderByPathFromTail(point->getPath());
596
                    if (vp && vp->isDerivedFrom<ViewProviderInspection>()) {
597
                        ViewProviderInspection* self = static_cast<ViewProviderInspection*>(vp);
598
                        QString info = self->inspectDistance(point);
599
                        Gui::getMainWindow()->setPaneText(1, info);
600
                        if (addflag) {
601
                            ViewProviderProxyObject::addFlag(view, info, point);
602
                        }
603
                        else {
604
                            Gui::ToolTip::showText(QCursor::pos(), info);
605
                        }
606
                        break;
607
                    }
608
                }
609
            }
610
        }
611
    }
612
    // toggle between inspection and navigation mode
613
    else if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
614
        const SoKeyboardEvent* const ke = static_cast<const SoKeyboardEvent*>(ev);
615
        if (ke->getState() == SoButtonEvent::DOWN && ke->getKey() == SoKeyboardEvent::ESCAPE) {
616
            SbBool toggle = view->isRedirectedToSceneGraph();
617
            view->setRedirectToSceneGraph(!toggle);
618
            n->setHandled();
619
        }
620
    }
621
}
622

623
namespace InspectionGui
624
{
625
float calcArea(const SbVec3f& v1, const SbVec3f& v2, const SbVec3f& v3)
626
{
627
    SbVec3f a = v2 - v1;
628
    SbVec3f b = v3 - v1;
629
    return a.cross(b).length() / 2.0f;
630
}
631

632
bool calcWeights(const SbVec3f& v1,
633
                 const SbVec3f& v2,
634
                 const SbVec3f& v3,
635
                 const SbVec3f& p,
636
                 float& w0,
637
                 float& w1,
638
                 float& w2)
639
{
640
    float fAreaABC = calcArea(v1, v2, v3);
641
    float fAreaPBC = calcArea(p, v2, v3);
642
    float fAreaPCA = calcArea(p, v3, v1);
643
    float fAreaPAB = calcArea(p, v1, v2);
644

645
    w0 = fAreaPBC / fAreaABC;
646
    w1 = fAreaPCA / fAreaABC;
647
    w2 = fAreaPAB / fAreaABC;
648

649
    return fabs(w0 + w1 + w2 - 1.0f) < 0.001f;
650
}
651
}  // namespace InspectionGui
652

653
QString ViewProviderInspection::inspectDistance(const SoPickedPoint* pp) const
654
{
655
    QString info;
656
    const SoDetail* detail = pp->getDetail(pp->getPath()->getTail());
657
    if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
658
        // get the distances of the three points of the picked facet
659
        const SoFaceDetail* facedetail = static_cast<const SoFaceDetail*>(detail);
660
        App::Property* pDistance = this->pcObject->getPropertyByName("Distances");
661
        if (pDistance && pDistance->is<Inspection::PropertyDistanceList>()) {
662
            Inspection::PropertyDistanceList* dist =
663
                static_cast<Inspection::PropertyDistanceList*>(pDistance);
664
            int index1 = facedetail->getPoint(0)->getCoordinateIndex();
665
            int index2 = facedetail->getPoint(1)->getCoordinateIndex();
666
            int index3 = facedetail->getPoint(2)->getCoordinateIndex();
667
            float fVal1 = (*dist)[index1];
668
            float fVal2 = (*dist)[index2];
669
            float fVal3 = (*dist)[index3];
670

671
            App::Property* pActual = this->pcObject->getPropertyByName("Actual");
672
            if (pActual && pActual->isDerivedFrom<App::PropertyLink>()) {
673
                float fSearchRadius = this->search_radius;
674
                if (fVal1 > fSearchRadius || fVal2 > fSearchRadius || fVal3 > fSearchRadius) {
675
                    info = QObject::tr("Distance: > %1").arg(fSearchRadius);
676
                }
677
                else if (fVal1 < -fSearchRadius || fVal2 < -fSearchRadius
678
                         || fVal3 < -fSearchRadius) {
679
                    info = QObject::tr("Distance: < %1").arg(-fSearchRadius);
680
                }
681
                else {
682
                    SoSearchAction searchAction;
683
                    searchAction.setType(SoCoordinate3::getClassTypeId());
684
                    searchAction.setInterest(SoSearchAction::FIRST);
685
                    searchAction.apply(pp->getPath()->getNodeFromTail(1));
686
                    SoPath* selectionPath = searchAction.getPath();
687

688
                    if (selectionPath) {
689
                        SoCoordinate3* coords =
690
                            static_cast<SoCoordinate3*>(selectionPath->getTail());
691
                        const SbVec3f& v1 = coords->point[index1];
692
                        const SbVec3f& v2 = coords->point[index2];
693
                        const SbVec3f& v3 = coords->point[index3];
694
                        const SbVec3f& p = pp->getObjectPoint();
695
                        // get the weights
696
                        float w1, w2, w3;
697
                        calcWeights(v1, v2, v3, p, w1, w2, w3);
698
                        float fVal = w1 * fVal1 + w2 * fVal2 + w3 * fVal3;
699
                        info = QObject::tr("Distance: %1").arg(fVal);
700
                    }
701
                }
702
            }
703
        }
704
    }
705
    else if (detail && detail->getTypeId() == SoPointDetail::getClassTypeId()) {
706
        // safe downward cast, know the type
707
        const SoPointDetail* pointdetail = static_cast<const SoPointDetail*>(detail);
708

709
        // get the distance of the picked point
710
        int index = pointdetail->getCoordinateIndex();
711
        App::Property* prop = this->pcObject->getPropertyByName("Distances");
712
        if (prop && prop->is<Inspection::PropertyDistanceList>()) {
713
            Inspection::PropertyDistanceList* dist =
714
                static_cast<Inspection::PropertyDistanceList*>(prop);
715
            float fVal = (*dist)[index];
716
            info = QObject::tr("Distance: %1").arg(fVal);
717
        }
718
    }
719

720
    return info;
721
}
722

723
// -----------------------------------------------
724

725
PROPERTY_SOURCE(InspectionGui::ViewProviderInspectionGroup, Gui::ViewProviderDocumentObjectGroup)
726

727

728
/**
729
 * Creates the view provider for an object group.
730
 */
731
ViewProviderInspectionGroup::ViewProviderInspectionGroup() = default;
732

733
ViewProviderInspectionGroup::~ViewProviderInspectionGroup() = default;
734

735
/**
736
 * Returns the pixmap for the opened list item.
737
 */
738
QIcon ViewProviderInspectionGroup::getIcon() const
739
{
740
    // clang-format off
741
    static const char * const ScanViewOpen[]={
742
        "16 16 10 1",
743
        "c c #000000",
744
        ". c None",
745
        "h c #808000",
746
        "# c #808080",
747
        "a c #ffff00",
748
        "r c #ff0000",
749
        "o c #ffff00",
750
        "g c #00ff00",
751
        "t c #00ffff",
752
        "b c #0000ff",
753
        "................",
754
        "...#####........",
755
        "..#hhhhh#.......",
756
        ".#hhhhhhh######.",
757
        ".#hhhhhhhhhhhh#c",
758
        ".#hhhhhhhhhhhh#c",
759
        ".#hhhhhhhhhhhh#c",
760
        "#############h#c",
761
        "#aaaaaaaaaa##h#c",
762
        "#aarroggtbbac##c",
763
        ".#arroggtbbaac#c",
764
        ".#aarroggtbbac#c",
765
        "..#aaaaaaaaaa#cc",
766
        "..#############c",
767
        "...ccccccccccccc",
768
        "................"};
769

770
    static const char * const ScanViewClosed[] = {
771
        "16 16 9 1",
772
        "c c #000000",
773
        ". c None",
774
        "# c #808080",
775
        "a c #ffff00",
776
        "r c #ff0000",
777
        "o c #ffff00",
778
        "g c #00ff00",
779
        "t c #00ffff",
780
        "b c #0000ff",
781
        "................",
782
        "...#####........",
783
        "..#aaaaa#.......",
784
        ".#aaaaaaa######.",
785
        ".#aaaaaaaaaaaa#c",
786
        ".#aarroggtbbaa#c",
787
        ".#aarroggtbbaa#c",
788
        ".#aarroggtbbaa#c",
789
        ".#aarroggtbbaa#c",
790
        ".#aarroggtbbaa#c",
791
        ".#aarroggtbbaa#c",
792
        ".#aarroggtbbaa#c",
793
        ".#aaaaaaaaaaaa#c",
794
        ".##############c",
795
        "..cccccccccccccc",
796
        "................"};
797
    // clang-format on
798

799
    QIcon groupIcon;
800
    groupIcon.addPixmap(QPixmap(ScanViewClosed), QIcon::Normal, QIcon::Off);
801
    groupIcon.addPixmap(QPixmap(ScanViewOpen), QIcon::Normal, QIcon::On);
802
    return groupIcon;
803
}
804

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

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

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

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