FreeCAD

Форк
0
/
ViewProviderCurvature.cpp 
669 строк · 24.8 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2004 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
#ifndef _PreComp_
25
#include <algorithm>
26
#include <iomanip>
27
#include <ios>
28
#include <sstream>
29
#include <QCursor>
30
#include <QMenu>
31

32
#include <Inventor/SoPickedPoint.h>
33
#include <Inventor/details/SoFaceDetail.h>
34
#include <Inventor/actions/SoSearchAction.h>
35
#include <Inventor/events/SoLocation2Event.h>
36
#include <Inventor/events/SoMouseButtonEvent.h>
37
#include <Inventor/nodes/SoDrawStyle.h>
38
#include <Inventor/nodes/SoIndexedFaceSet.h>
39
#include <Inventor/nodes/SoMaterial.h>
40
#include <Inventor/nodes/SoShapeHints.h>
41
#include <Inventor/sensors/SoIdleSensor.h>
42
#endif
43

44
#include <boost/range/adaptors.hpp>
45

46
#include <App/Annotation.h>
47
#include <App/Document.h>
48
#include <App/DocumentObjectGroup.h>
49
#include <Base/Console.h>
50
#include <Gui/Application.h>
51
#include <Gui/BitmapFactory.h>
52
#include <Gui/Document.h>
53
#include <Gui/MainWindow.h>
54
#include <Gui/Selection.h>
55
#include <Gui/SoFCColorBar.h>
56
#include <Gui/SoFCSelection.h>
57
#include <Gui/View3DInventorViewer.h>
58
#include <Gui/Widgets.h>
59

60
#include <Mod/Mesh/App/FeatureMeshCurvature.h>
61
#include <Mod/Mesh/App/MeshFeature.h>
62

63
#include "ViewProviderCurvature.h"
64

65

66
using namespace Mesh;
67
using namespace MeshGui;
68
using namespace std;
69

70
bool ViewProviderMeshCurvature::addflag = false;
71

72
PROPERTY_SOURCE(MeshGui::ViewProviderMeshCurvature, Gui::ViewProviderDocumentObject)
73

74
ViewProviderMeshCurvature::ViewProviderMeshCurvature()
75
{
76
    // NOLINTBEGIN
77
    pcColorRoot = new SoSeparator();
78
    pcColorRoot->ref();
79
    pcColorMat = new SoMaterial;
80
    pcColorMat->ref();
81
    pcColorStyle = new SoDrawStyle();
82
    pcColorRoot->addChild(pcColorStyle);
83
    // simple color bar
84
    pcColorBar = new Gui::SoFCColorBar;
85
    pcColorBar->Attach(this);
86
    pcColorBar->ref();
87
    pcColorBar->setRange(-0.5f, 0.5f, 3);
88
    pcLinkRoot = new SoGroup;
89
    pcLinkRoot->ref();
90
    // NOLINTEND
91

92
    App::Material mat;
93
    const SbColor* cols {};
94
    if (pcColorMat->ambientColor.getNum() == 1) {
95
        cols = pcColorMat->ambientColor.getValues(0);
96
        mat.ambientColor.setPackedValue(cols[0].getPackedValue());
97
    }
98
    if (pcColorMat->diffuseColor.getNum() == 1) {
99
        cols = pcColorMat->diffuseColor.getValues(0);
100
        mat.diffuseColor.setPackedValue(cols[0].getPackedValue());
101
    }
102
    if (pcColorMat->emissiveColor.getNum() == 1) {
103
        cols = pcColorMat->emissiveColor.getValues(0);
104
        mat.emissiveColor.setPackedValue(cols[0].getPackedValue());
105
    }
106
    if (pcColorMat->specularColor.getNum() == 1) {
107
        cols = pcColorMat->specularColor.getValues(0);
108
        mat.specularColor.setPackedValue(cols[0].getPackedValue());
109
    }
110
    if (pcColorMat->shininess.getNum() == 1) {
111
        const float* shiny = pcColorMat->shininess.getValues(0);
112
        mat.shininess = shiny[0];
113
    }
114
    if (pcColorMat->transparency.getNum() == 1) {
115
        const float* trans = pcColorMat->transparency.getValues(0);
116
        mat.transparency = trans[0];
117
    }
118

119
    ADD_PROPERTY(TextureMaterial, (mat));
120
    SelectionStyle.setValue(1);  // BBOX
121
}
122

123
ViewProviderMeshCurvature::~ViewProviderMeshCurvature()
124
{
125
    pcColorRoot->unref();
126
    pcColorMat->unref();
127
    pcColorBar->Detach(this);
128
    pcColorBar->unref();
129
    pcLinkRoot->unref();
130
}
131

132
void ViewProviderMeshCurvature::onChanged(const App::Property* prop)
133
{
134
    if (prop == &TextureMaterial) {
135
        const App::Material& Mat = TextureMaterial.getValue();
136
        pcColorMat->ambientColor.setValue(Mat.ambientColor.r,
137
                                          Mat.ambientColor.g,
138
                                          Mat.ambientColor.b);
139
        pcColorMat->specularColor.setValue(Mat.specularColor.r,
140
                                           Mat.specularColor.g,
141
                                           Mat.specularColor.b);
142
        pcColorMat->emissiveColor.setValue(Mat.emissiveColor.r,
143
                                           Mat.emissiveColor.g,
144
                                           Mat.emissiveColor.b);
145
        pcColorMat->shininess.setValue(Mat.shininess);
146
        pcColorMat->transparency.setValue(Mat.transparency);
147
    }
148

149
    ViewProviderDocumentObject::onChanged(prop);
150
}
151

152
void ViewProviderMeshCurvature::hide()
153
{
154
    inherited::hide();
155
    pcColorStyle->style = SoDrawStyle::INVISIBLE;
156
}
157

158
void ViewProviderMeshCurvature::show()
159
{
160
    inherited::show();
161
    pcColorStyle->style = SoDrawStyle::FILLED;
162
}
163

164
void ViewProviderMeshCurvature::init(const Mesh::PropertyCurvatureList* pCurvInfo)
165
{
166
    std::vector<float> aMinValues, aMaxValues;
167
    const std::vector<Mesh::CurvatureInfo>& fCurvInfo = pCurvInfo->getValues();
168
    aMinValues.reserve(fCurvInfo.size());
169
    aMaxValues.reserve(fCurvInfo.size());
170

171
    for (const auto& jt : fCurvInfo) {
172
        aMinValues.push_back(jt.fMinCurvature);
173
        aMaxValues.push_back(jt.fMaxCurvature);
174
    }
175

176
    if (aMinValues.empty() || aMaxValues.empty()) {
177
        return;  // no values inside
178
    }
179

180
    float fMin = *std::min_element(aMinValues.begin(), aMinValues.end());
181
    float fMax = *std::max_element(aMinValues.begin(), aMinValues.end());
182

183
    // histogram over all values
184
    std::map<int, int> aHistogram;
185
    for (float aMinValue : aMinValues) {
186
        int grp = (int)(10.0F * (aMinValue - fMin) / (fMax - fMin));
187
        aHistogram[grp]++;
188
    }
189

190
    float fRMin = -1.0F;
191
    for (const auto& mIt : aHistogram) {
192
        if ((float)mIt.second / (float)aMinValues.size() > 0.15F) {
193
            fRMin = mIt.first * (fMax - fMin) / 10.0F + fMin;
194
            break;
195
        }
196
    }
197

198
    fMin = *std::min_element(aMaxValues.begin(), aMaxValues.end());
199
    fMax = *std::max_element(aMaxValues.begin(), aMaxValues.end());
200

201
    // histogram over all values
202
    aHistogram.clear();
203
    for (float aMaxValue : aMaxValues) {
204
        int grp = (int)(10.0F * (aMaxValue - fMin) / (fMax - fMin));
205
        aHistogram[grp]++;
206
    }
207

208
    float fRMax = 1.0F;
209
    for (std::map<int, int>::reverse_iterator rIt2 = aHistogram.rbegin(); rIt2 != aHistogram.rend();
210
         ++rIt2) {
211
        if ((float)rIt2->second / (float)aMaxValues.size() > 0.15F) {
212
            fRMax = rIt2->first * (fMax - fMin) / 10.0F + fMin;
213
            break;
214
        }
215
    }
216

217
    float fAbs = std::max<float>(fabs(fRMin), fabs(fRMax));
218
    fRMin = -fAbs;
219
    fRMax = fAbs;
220
    fMin = fRMin;
221
    fMax = fRMax;
222
    pcColorBar->setRange(fMin, fMax, 3);
223
}
224

225
void ViewProviderMeshCurvature::slotChangedObject(const App::DocumentObject& Obj,
226
                                                  const App::Property& Prop)
227
{
228
    // we get this for any object for that a property has changed. Thus, we must regard that object
229
    // which is linked by our link property
230
    App::DocumentObject* object = static_cast<Mesh::Curvature*>(pcObject)->Source.getValue();
231
    if (object == &Obj) {
232
        const Mesh::PropertyMeshKernel& mesh = static_cast<Mesh::Feature*>(object)->Mesh;
233
        if ((&mesh) == (&Prop)) {
234
            const Mesh::MeshObject& kernel = mesh.getValue();
235
            pcColorMat->diffuseColor.setNum((int)kernel.countPoints());
236
            pcColorMat->transparency.setNum((int)kernel.countPoints());
237
            static_cast<Mesh::Curvature*>(pcObject)
238
                ->Source.touch();  // make sure to recompute the feature
239
        }
240
    }
241
}
242

243
void ViewProviderMeshCurvature::attach(App::DocumentObject* pcFeat)
244
{
245
    // creates the standard viewing modes
246
    inherited::attach(pcFeat);
247
    attachDocument(pcFeat->getDocument());
248

249
    SoShapeHints* flathints = new SoShapeHints;
250
    flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
251
    flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
252

253
    SoGroup* pcColorShadedRoot = new SoGroup();
254
    pcColorShadedRoot->addChild(flathints);
255

256
    // color shaded
257
    SoDrawStyle* pcFlatStyle = new SoDrawStyle();
258
    pcFlatStyle->style = SoDrawStyle::FILLED;
259
    pcColorShadedRoot->addChild(pcFlatStyle);
260

261
    SoMaterialBinding* pcMatBinding = new SoMaterialBinding;
262
    pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
263
    pcColorShadedRoot->addChild(pcColorMat);
264
    pcColorShadedRoot->addChild(pcMatBinding);
265
    pcColorShadedRoot->addChild(pcLinkRoot);
266

267
    addDisplayMaskMode(pcColorShadedRoot, "ColorShaded");
268

269
    // Check for an already existing color bar
270
    Gui::SoFCColorBar* pcBar =
271
        ((Gui::SoFCColorBar*)findFrontRootOfType(Gui::SoFCColorBar::getClassTypeId()));
272
    if (pcBar) {
273
        float fMin = pcColorBar->getMinValue();
274
        float fMax = pcColorBar->getMaxValue();
275

276
        // Attach to the foreign color bar and delete our own bar
277
        pcBar->Attach(this);
278
        pcBar->ref();
279
        pcBar->setRange(fMin, fMax, 3);
280
        pcBar->Notify(0);
281
        pcColorBar->Detach(this);
282
        pcColorBar->unref();
283
        pcColorBar = pcBar;
284
    }
285

286
    pcColorRoot->addChild(pcColorBar);
287
}
288

289
void ViewProviderMeshCurvature::updateData(const App::Property* prop)
290
{
291
    // set to the expected size
292
    if (prop->isDerivedFrom<App::PropertyLink>()) {
293
        Mesh::Feature* object =
294
            static_cast<const App::PropertyLink*>(prop)->getValue<Mesh::Feature*>();
295
        Gui::coinRemoveAllChildren(this->pcLinkRoot);
296
        if (object) {
297
            const Mesh::MeshObject& kernel = object->Mesh.getValue();
298
            pcColorMat->diffuseColor.setNum((int)kernel.countPoints());
299
            pcColorMat->transparency.setNum((int)kernel.countPoints());
300

301
            // get the view provider of the associated mesh feature
302
            App::Document* rDoc = pcObject->getDocument();
303
            Gui::Document* pDoc = Gui::Application::Instance->getDocument(rDoc);
304
            ViewProviderMesh* view = static_cast<ViewProviderMesh*>(pDoc->getViewProvider(object));
305
            this->pcLinkRoot->addChild(view->getHighlightNode());
306

307
            Base::Placement p =
308
                static_cast<Mesh::Feature*>(view->getObject())->Placement.getValue();
309
            ViewProviderMesh::updateTransform(p, pcTransform);
310
        }
311
    }
312
    else if (prop->is<Mesh::PropertyCurvatureList>()) {
313
        const Mesh::PropertyCurvatureList* curv =
314
            static_cast<const Mesh::PropertyCurvatureList*>(prop);
315
        if (curv->getSize() < 3) {  // invalid array
316
            return;
317
        }
318
#if 0  // FIXME: Do not always change the range
319
        init(curv); // init color bar
320
#endif
321
        setActiveMode();
322
    }
323
}
324

325
SoSeparator* ViewProviderMeshCurvature::getFrontRoot() const
326
{
327
    return pcColorRoot;
328
}
329

330
void ViewProviderMeshCurvature::setVertexCurvatureMode(int mode)
331
{
332
    using PropertyMap = std::map<std::string, App::Property*>;
333
    Mesh::PropertyCurvatureList* pCurvInfo = nullptr;
334
    PropertyMap Map;
335
    pcObject->getPropertyMap(Map);
336

337
    auto it = std::find_if(Map.begin(), Map.end(), [](const PropertyMap::value_type& v) {
338
        Base::Type type = v.second->getTypeId();
339
        return (type == Mesh::PropertyCurvatureList::getClassTypeId());
340
    });
341

342
    if (it == Map.end()) {
343
        return;  // cannot display this feature type due to missing curvature property
344
    }
345

346
    pCurvInfo = static_cast<Mesh::PropertyCurvatureList*>(it->second);
347

348
    // curvature values
349
    std::vector<float> fValues = pCurvInfo->getCurvature(mode);
350
    pcColorMat->diffuseColor.setNum(fValues.size());
351
    pcColorMat->transparency.setNum(fValues.size());
352

353
    SbColor* diffcol = pcColorMat->diffuseColor.startEditing();
354
    float* transp = pcColorMat->transparency.startEditing();
355

356
    for (auto const& value : fValues | boost::adaptors::indexed(0)) {
357
        App::Color c = pcColorBar->getColor(value.value());
358
        diffcol[value.index()].setValue(c.r, c.g, c.b);
359
        transp[value.index()] = c.a;
360
    }
361

362
    pcColorMat->diffuseColor.finishEditing();
363
    pcColorMat->transparency.finishEditing();
364

365
    // In order to apply the transparency changes the IndexFaceSet node must be touched
366
    touchShapeNode();
367
}
368

369
void ViewProviderMeshCurvature::touchShapeNode()
370
{
371
    SoSearchAction searchAction;
372
    searchAction.setType(SoIndexedFaceSet::getClassTypeId());
373
    searchAction.setInterest(SoSearchAction::FIRST);
374
    searchAction.apply(pcLinkRoot);
375
    SoPath* selectionPath = searchAction.getPath();
376
    if (selectionPath) {
377
        selectionPath->getTail()->touch();
378
    }
379
}
380

381
QIcon ViewProviderMeshCurvature::getIcon() const
382
{
383
    static QPixmap px = Gui::BitmapFactory().pixmap(":/icons/Mesh_Tree_Curvature_Plot.svg");
384
    return px;
385
}
386

387
void ViewProviderMeshCurvature::setDisplayMode(const char* ModeName)
388
{
389
    if (strcmp("Mean curvature", ModeName) == 0) {
390
        setVertexCurvatureMode(Mesh::PropertyCurvatureList::MeanCurvature);
391
        setDisplayMaskMode("ColorShaded");
392
    }
393
    else if (strcmp("Gaussian curvature", ModeName) == 0) {
394
        setVertexCurvatureMode(Mesh::PropertyCurvatureList::GaussCurvature);
395
        setDisplayMaskMode("ColorShaded");
396
    }
397
    else if (strcmp("Maximum curvature", ModeName) == 0) {
398
        setVertexCurvatureMode(Mesh::PropertyCurvatureList::MaxCurvature);
399
        setDisplayMaskMode("ColorShaded");
400
    }
401
    else if (strcmp("Minimum curvature", ModeName) == 0) {
402
        setVertexCurvatureMode(Mesh::PropertyCurvatureList::MinCurvature);
403
        setDisplayMaskMode("ColorShaded");
404
    }
405
    else if (strcmp("Absolute curvature", ModeName) == 0) {
406
        setVertexCurvatureMode(Mesh::PropertyCurvatureList::AbsCurvature);
407
        setDisplayMaskMode("ColorShaded");
408
    }
409

410
    inherited::setDisplayMode(ModeName);
411
}
412

413
const char* ViewProviderMeshCurvature::getDefaultDisplayMode() const
414
{
415
    return "Absolute curvature";
416
}
417

418
std::vector<std::string> ViewProviderMeshCurvature::getDisplayModes() const
419
{
420
    std::vector<std::string> StrList = inherited::getDisplayModes();
421

422
    // add modes
423
    StrList.emplace_back("Absolute curvature");
424
    StrList.emplace_back("Mean curvature");
425
    StrList.emplace_back("Gaussian curvature");
426
    StrList.emplace_back("Maximum curvature");
427
    StrList.emplace_back("Minimum curvature");
428

429
    return StrList;
430
}
431

432
void ViewProviderMeshCurvature::OnChange(Base::Subject<int>& /*rCaller*/, int /*rcReason*/)
433
{
434
    setActiveMode();
435
}
436

437
namespace MeshGui
438
{
439

440
class Annotation
441
{
442
public:
443
    Annotation(Gui::ViewProviderDocumentObject* vp,
444
               const QString& s,
445
               const SbVec3f& p,
446
               const SbVec3f& n)
447
        : vp(vp)
448
        , s(s)
449
        , p(p)
450
        , n(n)
451
    {}
452

453
    static void run(void* data, SoSensor* sensor)
454
    {
455
        Annotation* self = static_cast<Annotation*>(data);
456
        self->show();
457
        delete self;
458
        delete sensor;
459
    }
460

461
    void show()
462
    {
463
        App::Document* doc = vp->getObject()->getDocument();
464

465
        std::vector<App::DocumentObject*> groups =
466
            doc->getObjectsOfType(App::DocumentObjectGroup::getClassTypeId());
467
        App::DocumentObjectGroup* group = nullptr;
468
        std::string internalname = "CurvatureGroup";
469
        for (const auto& it : groups) {
470
            if (internalname == it->getNameInDocument()) {
471
                group = static_cast<App::DocumentObjectGroup*>(it);
472
                break;
473
            }
474
        }
475
        if (!group) {
476
            group = static_cast<App::DocumentObjectGroup*>(
477
                doc->addObject("App::DocumentObjectGroup", internalname.c_str()));
478
        }
479

480
        App::AnnotationLabel* anno = static_cast<App::AnnotationLabel*>(
481
            group->addObject("App::AnnotationLabel", internalname.c_str()));
482
        QStringList lines = s.split(QLatin1String("\n"));
483
        std::vector<std::string> text;
484
        for (const auto& line : lines) {
485
            text.emplace_back((const char*)line.toLatin1());
486
        }
487
        anno->LabelText.setValues(text);
488
        std::stringstream str;
489
        str << "Curvature info (" << group->Group.getSize() << ")";
490
        anno->Label.setValue(str.str());
491
        anno->BasePosition.setValue(p[0], p[1], p[2]);
492
        anno->TextPosition.setValue(n[0], n[1], n[2]);
493
    }
494

495
private:
496
    Gui::ViewProviderDocumentObject* vp;
497
    QString s;
498
    SbVec3f p;
499
    SbVec3f n;
500
};
501

502
}  // namespace MeshGui
503

504
void ViewProviderMeshCurvature::curvatureInfoCallback(void* ud, SoEventCallback* n)
505
{
506
    Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
507
    const SoEvent* ev = n->getEvent();
508
    if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
509
        const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(ev);
510

511
        // Mark all incoming mouse button events as handled, especially, to deactivate the selection
512
        // node
513
        n->getAction()->setHandled();
514
        if (mbe->getButton() == SoMouseButtonEvent::BUTTON2
515
            && mbe->getState() == SoButtonEvent::UP) {
516
            n->setHandled();
517
            // context-menu
518
            QMenu menu;
519
            QAction* fl = menu.addAction(QObject::tr("Annotation"));
520
            fl->setCheckable(true);
521
            fl->setChecked(addflag);
522
            QAction* cl = menu.addAction(QObject::tr("Leave info mode"));
523
            QAction* id = menu.exec(QCursor::pos());
524
            if (fl == id) {
525
                addflag = fl->isChecked();
526
            }
527
            else if (cl == id) {
528
                view->setEditing(false);
529
                view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
530
                view->setRedirectToSceneGraph(false);
531
                view->setSelectionEnabled(true);
532
                view->removeEventCallback(SoEvent::getClassTypeId(), curvatureInfoCallback, ud);
533
            }
534
        }
535
        else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1
536
                 && mbe->getState() == SoButtonEvent::UP) {
537
            const SoPickedPoint* point = n->getPickedPoint();
538
            if (!point) {
539
                Base::Console().Message("No facet picked.\n");
540
                return;
541
            }
542

543
            n->setHandled();
544

545
            // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is
546
            // really from the mesh we render and not from any other geometry
547
            Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());
548
            if (!vp || !vp->isDerivedFrom<ViewProviderMeshCurvature>()) {
549
                return;
550
            }
551
            ViewProviderMeshCurvature* self = static_cast<ViewProviderMeshCurvature*>(vp);
552
            const SoDetail* detail = point->getDetail(point->getPath()->getTail());
553
            if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
554
                const SoFaceDetail* facedetail = static_cast<const SoFaceDetail*>(detail);
555
                // get the curvature info of the three points of the picked facet
556
                int index1 = facedetail->getPoint(0)->getCoordinateIndex();
557
                int index2 = facedetail->getPoint(1)->getCoordinateIndex();
558
                int index3 = facedetail->getPoint(2)->getCoordinateIndex();
559
                std::string info = self->curvatureInfo(true, index1, index2, index3);
560
                QString text = QString::fromLatin1(info.c_str());
561
                if (addflag) {
562
                    SbVec3f pt = point->getPoint();
563
                    SbVec3f nl = point->getNormal();
564
                    Annotation* anno = new Annotation(self, text, pt, nl);
565
                    SoIdleSensor* sensor = new SoIdleSensor(Annotation::run, anno);
566
                    sensor->schedule();
567
                }
568
                else {
569
                    Gui::ToolTip::showText(QCursor::pos(), text);
570
                }
571
            }
572
        }
573
    }
574
    else if (ev->getTypeId().isDerivedFrom(SoLocation2Event::getClassTypeId())) {
575
        const SoPickedPoint* point = n->getPickedPoint();
576
        if (!point) {
577
            return;
578
        }
579
        n->setHandled();
580

581
        // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is
582
        // really from the mesh we render and not from any other geometry
583
        Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());
584
        if (!vp || !vp->isDerivedFrom<ViewProviderMeshCurvature>()) {
585
            return;
586
        }
587
        ViewProviderMeshCurvature* that = static_cast<ViewProviderMeshCurvature*>(vp);
588
        const SoDetail* detail = point->getDetail(point->getPath()->getTail());
589
        if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
590
            const SoFaceDetail* facedetail = static_cast<const SoFaceDetail*>(detail);
591
            // get the curvature info of the three points of the picked facet
592
            int index1 = facedetail->getPoint(0)->getCoordinateIndex();
593
            int index2 = facedetail->getPoint(1)->getCoordinateIndex();
594
            int index3 = facedetail->getPoint(2)->getCoordinateIndex();
595
            std::string info = that->curvatureInfo(false, index1, index2, index3);
596
            Gui::getMainWindow()->setPaneText(1, QString::fromLatin1(info.c_str()));
597
        }
598
    }
599
}
600

601
std::string
602
ViewProviderMeshCurvature::curvatureInfo(bool detail, int index1, int index2, int index3) const
603
{
604
    // get the curvature info of the three points of the picked facet
605
    App::Property* prop = pcObject->getPropertyByName("CurvInfo");
606
    std::stringstream str;
607
    if (prop && prop->is<Mesh::PropertyCurvatureList>()) {
608
        Mesh::PropertyCurvatureList* curv = static_cast<Mesh::PropertyCurvatureList*>(prop);
609
        const Mesh::CurvatureInfo& cVal1 = (*curv)[index1];
610
        const Mesh::CurvatureInfo& cVal2 = (*curv)[index2];
611
        const Mesh::CurvatureInfo& cVal3 = (*curv)[index3];
612
        float fVal1 = 0.0F;
613
        float fVal2 = 0.0F;
614
        float fVal3 = 0.0F;
615

616
        bool print = true;
617
        std::string mode = getActiveDisplayMode();
618
        if (mode == "Minimum curvature") {
619
            fVal1 = cVal1.fMinCurvature;
620
            fVal2 = cVal2.fMinCurvature;
621
            fVal3 = cVal3.fMinCurvature;
622
        }
623
        else if (mode == "Maximum curvature") {
624
            fVal1 = cVal1.fMaxCurvature;
625
            fVal2 = cVal2.fMaxCurvature;
626
            fVal3 = cVal3.fMaxCurvature;
627
        }
628
        else if (mode == "Gaussian curvature") {
629
            fVal1 = cVal1.fMaxCurvature * cVal1.fMinCurvature;
630
            fVal2 = cVal2.fMaxCurvature * cVal2.fMinCurvature;
631
            fVal3 = cVal3.fMaxCurvature * cVal3.fMinCurvature;
632
        }
633
        else if (mode == "Mean curvature") {
634
            fVal1 = 0.5F * (cVal1.fMaxCurvature + cVal1.fMinCurvature);
635
            fVal2 = 0.5F * (cVal2.fMaxCurvature + cVal2.fMinCurvature);
636
            fVal3 = 0.5F * (cVal3.fMaxCurvature + cVal3.fMinCurvature);
637
        }
638
        else if (mode == "Absolute curvature") {
639
            fVal1 = fabs(cVal1.fMaxCurvature) > fabs(cVal1.fMinCurvature) ? cVal1.fMaxCurvature
640
                                                                          : cVal1.fMinCurvature;
641
            fVal2 = fabs(cVal2.fMaxCurvature) > fabs(cVal2.fMinCurvature) ? cVal2.fMaxCurvature
642
                                                                          : cVal2.fMinCurvature;
643
            fVal3 = fabs(cVal3.fMaxCurvature) > fabs(cVal3.fMinCurvature) ? cVal3.fMaxCurvature
644
                                                                          : cVal3.fMinCurvature;
645
        }
646
        else {
647
            print = false;
648
        }
649

650
        if (print) {
651
            if (!detail) {
652
                str << mode << ": <" << fVal1 << ", " << fVal2 << ", " << fVal3 << ">";
653
            }
654
            else {
655
                str.setf(std::ios::fixed | std::ios::showpoint);
656
                str.precision(5);
657
                str << mode << std::endl
658
                    << "v1: " << std::setw(5) << fVal1 << std::endl
659
                    << "v2: " << std::setw(5) << fVal2 << std::endl
660
                    << "v3: " << std::setw(5) << fVal3;
661
            }
662
        }
663
        else if (!detail) {
664
            str << "No curvature mode set";
665
        }
666
    }
667

668
    return str.str();
669
}
670

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

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

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

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