FreeCAD

Форк
0
/
ViewProviderInspection.cpp 
810 строк · 28.9 Кб
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/SoFCColorBarNotifier.h>
56
#include <Gui/View3DInventorViewer.h>
57
#include <Gui/Widgets.h>
58
#include <Mod/Inspection/App/InspectionFeature.h>
59
#include <Mod/Points/App/Properties.h>
60

61
#include "ViewProviderInspection.h"
62

63

64
using namespace InspectionGui;
65

66

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

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

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

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

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

112
ViewProviderInspection::~ViewProviderInspection()
113
{
114
    pcColorRoot->unref();
115
    pcCoords->unref();
116
    pcMatBinding->unref();
117
    pcColorMat->unref();
118
    deleteColorBar();
119
    pcLinkRoot->unref();
120
    pcPointStyle->unref();
121
}
122

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

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

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

151
void ViewProviderInspection::deleteColorBar()
152
{
153
    Gui::SoFCColorBarNotifier::instance().detach(pcColorBar);
154
    pcColorBar->Detach(this);
155
    pcColorBar->unref();
156
}
157

158
void ViewProviderInspection::attach(App::DocumentObject* pcFeat)
159
{
160
    // creates the standard viewing modes
161
    inherited::attach(pcFeat);
162

163
    SoShapeHints* flathints = new SoShapeHints;
164
    flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
165
    flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
166

167
    SoGroup* pcColorShadedRoot = new SoGroup();
168
    pcColorShadedRoot->addChild(flathints);
169

170
    // color shaded  ------------------------------------------
171
    SoDrawStyle* pcFlatStyle = new SoDrawStyle();
172
    pcFlatStyle->style = SoDrawStyle::FILLED;
173
    pcColorShadedRoot->addChild(pcFlatStyle);
174

175
    pcColorShadedRoot->addChild(pcColorMat);
176
    pcColorShadedRoot->addChild(pcMatBinding);
177
    pcColorShadedRoot->addChild(pcLinkRoot);
178

179
    addDisplayMaskMode(pcColorShadedRoot, "ColorShaded");
180

181
    // Check for an already existing color bar
182
    Gui::SoFCColorBar* pcBar =
183
        ((Gui::SoFCColorBar*)findFrontRootOfType(Gui::SoFCColorBar::getClassTypeId()));
184
    if (pcBar) {
185
        float fMin = pcColorBar->getMinValue();
186
        float fMax = pcColorBar->getMaxValue();
187

188
        // Attach to the foreign color bar and delete our own bar
189
        pcBar->Attach(this);
190
        pcBar->ref();
191
        pcBar->setRange(fMin, fMax, 3);
192
        pcBar->Notify(0);
193
        deleteColorBar();
194
        pcColorBar = pcBar;
195
    }
196

197
    pcColorRoot->addChild(pcColorBar);
198
}
199

200
bool ViewProviderInspection::setupFaces(const Data::ComplexGeoData* data)
201
{
202
    std::vector<Base::Vector3d> points;
203
    std::vector<Data::ComplexGeoData::Facet> faces;
204

205
    // set the Distance property to the correct size to sync size of material node with number
206
    // of vertices/points of the referenced geometry
207
    double accuracy = data->getAccuracy();
208
    data->getFaces(points, faces, accuracy);
209
    if (faces.empty()) {
210
        return false;
211
    }
212

213
    setupCoords(points);
214
    setupFaceIndexes(faces);
215
    return true;
216
}
217

218
bool ViewProviderInspection::setupLines(const Data::ComplexGeoData* data)
219
{
220
    std::vector<Base::Vector3d> points;
221
    std::vector<Data::ComplexGeoData::Line> lines;
222

223
    double accuracy = data->getAccuracy();
224
    data->getLines(points, lines, accuracy);
225
    if (lines.empty()) {
226
        return false;
227
    }
228

229
    setupCoords(points);
230
    setupLineIndexes(lines);
231
    return true;
232
}
233

234
bool ViewProviderInspection::setupPoints(const Data::ComplexGeoData* data,
235
                                         App::PropertyContainer* container)
236
{
237
    std::vector<Base::Vector3d> points;
238
    std::vector<Base::Vector3f> normals;
239
    std::vector<Base::Vector3d> normals_d;
240
    double accuracy = data->getAccuracy();
241
    data->getPoints(points, normals_d, accuracy);
242
    if (points.empty()) {
243
        return false;
244
    }
245

246
    normals.reserve(normals_d.size());
247
    std::transform(normals_d.cbegin(),
248
                   normals_d.cend(),
249
                   std::back_inserter(normals),
250
                   [](const Base::Vector3d& p) {
251
                       return Base::toVector<float>(p);
252
                   });
253

254
    // If getPoints() doesn't deliver normals check a second property
255
    if (normals.empty() && container) {
256
        App::Property* propN = container->getPropertyByName("Normal");
257
        if (propN && propN->isDerivedFrom<Points::PropertyNormalList>()) {
258
            normals = static_cast<Points::PropertyNormalList*>(propN)->getValues();
259
        }
260
    }
261

262
    setupCoords(points);
263
    if (!normals.empty() && normals.size() == points.size()) {
264
        setupNormals(normals);
265
    }
266

267
    this->pcLinkRoot->addChild(this->pcPointStyle);
268
    this->pcLinkRoot->addChild(new SoPointSet());
269

270
    return true;
271
}
272

273
void ViewProviderInspection::setupCoords(const std::vector<Base::Vector3d>& points)
274
{
275
    this->pcLinkRoot->addChild(this->pcCoords);
276
    this->pcCoords->point.setNum(points.size());
277
    SbVec3f* pts = this->pcCoords->point.startEditing();
278
    for (size_t i = 0; i < points.size(); i++) {
279
        const Base::Vector3d& p = points[i];
280
        pts[i].setValue((float)p.x, (float)p.y, (float)p.z);
281
    }
282
    this->pcCoords->point.finishEditing();
283
}
284

285
void ViewProviderInspection::setupNormals(const std::vector<Base::Vector3f>& normals)
286
{
287
    SoNormal* normalNode = new SoNormal();
288
    normalNode->vector.setNum(normals.size());
289
    SbVec3f* norm = normalNode->vector.startEditing();
290

291
    std::size_t i = 0;
292
    for (const auto& it : normals) {
293
        norm[i++].setValue(it.x, it.y, it.z);
294
    }
295

296
    normalNode->vector.finishEditing();
297
    this->pcLinkRoot->addChild(normalNode);
298
}
299

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

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

333
void ViewProviderInspection::updateData(const App::Property* prop)
334
{
335
    // set to the expected size
336
    if (prop->isDerivedFrom<App::PropertyLink>()) {
337
        App::GeoFeature* object =
338
            static_cast<const App::PropertyLink*>(prop)->getValue<App::GeoFeature*>();
339
        const App::PropertyComplexGeoData* propData =
340
            object ? object->getPropertyOfGeometry() : nullptr;
341
        if (propData) {
342
            Gui::coinRemoveAllChildren(this->pcLinkRoot);
343

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

372
SoSeparator* ViewProviderInspection::getFrontRoot() const
373
{
374
    return pcColorRoot;
375
}
376

377
void ViewProviderInspection::setDistances()
378
{
379
    if (!pcObject) {
380
        return;
381
    }
382

383
    App::Property* pDistances = pcObject->getPropertyByName("Distances");
384
    if (!pDistances) {
385
        SoDebugError::post("ViewProviderInspection::setDistances", "Unknown property 'Distances'");
386
        return;
387
    }
388
    if (pDistances->getTypeId() != Inspection::PropertyDistanceList::getClassTypeId()) {
389
        SoDebugError::post(
390
            "ViewProviderInspection::setDistances",
391
            "Property 'Distances' has type %s (Inspection::PropertyDistanceList was expected)",
392
            pDistances->getTypeId().getName());
393
        return;
394
    }
395

396
    // distance values
397
    const std::vector<float>& fValues =
398
        static_cast<Inspection::PropertyDistanceList*>(pDistances)->getValues();
399
    if ((int)fValues.size() != this->pcCoords->point.getNum()) {
400
        pcMatBinding->value = SoMaterialBinding::OVERALL;
401
        return;
402
    }
403

404
    if (pcColorMat->diffuseColor.getNum() != static_cast<int>(fValues.size())) {
405
        pcColorMat->diffuseColor.setNum(static_cast<int>(fValues.size()));
406
    }
407
    if (pcColorMat->transparency.getNum() != static_cast<int>(fValues.size())) {
408
        pcColorMat->transparency.setNum(static_cast<int>(fValues.size()));
409
    }
410

411
    SbColor* cols = pcColorMat->diffuseColor.startEditing();
412
    float* tran = pcColorMat->transparency.startEditing();
413

414
    unsigned long j = 0;
415
    for (std::vector<float>::const_iterator jt = fValues.begin(); jt != fValues.end(); ++jt, j++) {
416
        App::Color col = pcColorBar->getColor(*jt);
417
        cols[j] = SbColor(col.r, col.g, col.b);
418
        if (pcColorBar->isVisible(*jt)) {
419
            tran[j] = 0.0f;
420
        }
421
        else {
422
            tran[j] = 0.8f;
423
        }
424
    }
425

426
    pcColorMat->diffuseColor.finishEditing();
427
    pcColorMat->transparency.finishEditing();
428
    pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
429
}
430

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

445
    return px;
446
}
447

448
void ViewProviderInspection::setDisplayMode(const char* ModeName)
449
{
450
    if (strcmp("Visual Inspection", ModeName) == 0) {
451
        setDistances();
452
        setDisplayMaskMode("ColorShaded");
453
    }
454

455
    inherited::setDisplayMode(ModeName);
456
}
457

458
std::vector<std::string> ViewProviderInspection::getDisplayModes() const
459
{
460
    // add modes
461
    std::vector<std::string> StrList;
462
    StrList.emplace_back("Visual Inspection");
463
    return StrList;
464
}
465

466
void ViewProviderInspection::OnChange(Base::Subject<int>& /*rCaller*/, int /*rcReason*/)
467
{
468
    setActiveMode();
469
}
470

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

501
        this->deleteLater();
502
    }
503

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

527
private:
528
    QPointer<QWidget> widget;
529
};
530
}  // namespace InspectionGui
531

532
void ViewProviderInspection::inspectCallback(void* ud, SoEventCallback* n)
533
{
534
    Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
535
    const SoEvent* ev = n->getEvent();
536
    if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
537
        const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(ev);
538

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

577
            n->setHandled();
578

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

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

630
namespace InspectionGui
631
{
632
float calcArea(const SbVec3f& v1, const SbVec3f& v2, const SbVec3f& v3)
633
{
634
    SbVec3f a = v2 - v1;
635
    SbVec3f b = v3 - v1;
636
    return a.cross(b).length() / 2.0f;
637
}
638

639
bool calcWeights(const SbVec3f& v1,
640
                 const SbVec3f& v2,
641
                 const SbVec3f& v3,
642
                 const SbVec3f& p,
643
                 float& w0,
644
                 float& w1,
645
                 float& w2)
646
{
647
    float fAreaABC = calcArea(v1, v2, v3);
648
    float fAreaPBC = calcArea(p, v2, v3);
649
    float fAreaPCA = calcArea(p, v3, v1);
650
    float fAreaPAB = calcArea(p, v1, v2);
651

652
    w0 = fAreaPBC / fAreaABC;
653
    w1 = fAreaPCA / fAreaABC;
654
    w2 = fAreaPAB / fAreaABC;
655

656
    return fabs(w0 + w1 + w2 - 1.0f) < 0.001f;
657
}
658
}  // namespace InspectionGui
659

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

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

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

716
        // get the distance of the picked point
717
        int index = pointdetail->getCoordinateIndex();
718
        App::Property* prop = this->pcObject->getPropertyByName("Distances");
719
        if (prop && prop->is<Inspection::PropertyDistanceList>()) {
720
            Inspection::PropertyDistanceList* dist =
721
                static_cast<Inspection::PropertyDistanceList*>(prop);
722
            float fVal = (*dist)[index];
723
            info = QObject::tr("Distance: %1").arg(fVal);
724
        }
725
    }
726

727
    return info;
728
}
729

730
// -----------------------------------------------
731

732
PROPERTY_SOURCE(InspectionGui::ViewProviderInspectionGroup, Gui::ViewProviderDocumentObjectGroup)
733

734

735
/**
736
 * Creates the view provider for an object group.
737
 */
738
ViewProviderInspectionGroup::ViewProviderInspectionGroup() = default;
739

740
ViewProviderInspectionGroup::~ViewProviderInspectionGroup() = default;
741

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

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

806
    QIcon groupIcon;
807
    groupIcon.addPixmap(QPixmap(ScanViewClosed), QIcon::Normal, QIcon::Off);
808
    groupIcon.addPixmap(QPixmap(ScanViewOpen), QIcon::Normal, QIcon::On);
809
    return groupIcon;
810
}
811

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

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

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

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