FreeCAD

Форк
0
/
ViewProvider.cpp 
764 строки · 27.0 Кб
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 <boost/math/special_functions/fpclassify.hpp>
26
#include <limits>
27

28
#include <Inventor/errors/SoDebugError.h>
29
#include <Inventor/events/SoMouseButtonEvent.h>
30
#include <Inventor/nodes/SoCamera.h>
31
#include <Inventor/nodes/SoCoordinate3.h>
32
#include <Inventor/nodes/SoDrawStyle.h>
33
#include <Inventor/nodes/SoIndexedPointSet.h>
34
#include <Inventor/nodes/SoMaterial.h>
35
#include <Inventor/nodes/SoMaterialBinding.h>
36
#include <Inventor/nodes/SoNormal.h>
37
#include <Inventor/nodes/SoPointSet.h>
38
#endif
39

40
#include <App/Document.h>
41
#include <Base/Vector3D.h>
42
#include <Gui/Application.h>
43
#include <Gui/Document.h>
44
#include <Gui/SoFCSelection.h>
45
#include <Gui/View3DInventorViewer.h>
46
#include <Mod/Points/App/PointsFeature.h>
47
#include <Mod/Points/App/Properties.h>
48

49
#include "ViewProvider.h"
50

51

52
using namespace PointsGui;
53
using namespace Points;
54

55

56
PROPERTY_SOURCE_ABSTRACT(PointsGui::ViewProviderPoints, Gui::ViewProviderGeometryObject)
57

58

59
App::PropertyFloatConstraint::Constraints ViewProviderPoints::floatRange = {1.0, 64.0, 1.0};
60

61
ViewProviderPoints::ViewProviderPoints()
62
{
63
    static const char* osgroup = "Object Style";
64

65
    ADD_PROPERTY_TYPE(PointSize, (2.0F), osgroup, App::Prop_None, "Set point size");
66
    PointSize.setConstraints(&floatRange);
67

68
    // Create the selection node
69
    pcHighlight = Gui::ViewProviderBuilder::createSelection();
70
    pcHighlight->ref();
71
    if (pcHighlight->selectionMode.getValue() == Gui::SoFCSelection::SEL_OFF) {
72
        Selectable.setValue(false);
73
    }
74

75
    // BBOX
76
    SelectionStyle.setValue(1);
77

78
    pcPointsCoord = new SoCoordinate3();
79
    pcPointsCoord->ref();
80
    pcPointsNormal = new SoNormal();
81
    pcPointsNormal->ref();
82
    pcColorMat = new SoMaterial;
83
    pcColorMat->ref();
84

85
    pcPointStyle = new SoDrawStyle();
86
    pcPointStyle->ref();
87
    pcPointStyle->style = SoDrawStyle::POINTS;
88
    pcPointStyle->pointSize = PointSize.getValue();
89
}
90

91
ViewProviderPoints::~ViewProviderPoints()
92
{
93
    pcHighlight->unref();
94
    pcPointsCoord->unref();
95
    pcPointsNormal->unref();
96
    pcColorMat->unref();
97
    pcPointStyle->unref();
98
}
99

100
void ViewProviderPoints::onChanged(const App::Property* prop)
101
{
102
    if (prop == &PointSize) {
103
        pcPointStyle->pointSize = PointSize.getValue();
104
    }
105
    else if (prop == &SelectionStyle) {
106
        pcHighlight->style =
107
            SelectionStyle.getValue() ? Gui::SoFCSelection::BOX : Gui::SoFCSelection::EMISSIVE;
108
    }
109
    else {
110
        ViewProviderGeometryObject::onChanged(prop);
111
    }
112
}
113

114
void ViewProviderPoints::setVertexColorMode(App::PropertyColorList* pcProperty)
115
{
116
    const std::vector<App::Color>& val = pcProperty->getValues();
117

118
    pcColorMat->diffuseColor.setNum(val.size());
119
    SbColor* col = pcColorMat->diffuseColor.startEditing();
120

121
    std::size_t i = 0;
122
    for (const auto& it : val) {
123
        col[i++].setValue(it.r, it.g, it.b);
124
    }
125

126
    pcColorMat->diffuseColor.finishEditing();
127
}
128

129
void ViewProviderPoints::setVertexGreyvalueMode(Points::PropertyGreyValueList* pcProperty)
130
{
131
    const std::vector<float>& val = pcProperty->getValues();
132

133
    pcColorMat->diffuseColor.setNum(val.size());
134
    SbColor* col = pcColorMat->diffuseColor.startEditing();
135

136
    std::size_t i = 0;
137
    for (float it : val) {
138
        col[i++].setValue(it, it, it);
139
    }
140

141
    pcColorMat->diffuseColor.finishEditing();
142
}
143

144
void ViewProviderPoints::setVertexNormalMode(Points::PropertyNormalList* pcProperty)
145
{
146
    const std::vector<Base::Vector3f>& val = pcProperty->getValues();
147

148
    pcPointsNormal->vector.setNum(val.size());
149
    SbVec3f* norm = pcPointsNormal->vector.startEditing();
150

151
    std::size_t i = 0;
152
    for (const auto& it : val) {
153
        norm[i++].setValue(it.x, it.y, it.z);
154
    }
155

156
    pcPointsNormal->vector.finishEditing();
157
}
158

159
void ViewProviderPoints::setDisplayMode(const char* ModeName)
160
{
161
    int numPoints = pcPointsCoord->point.getNum();
162

163
    if (strcmp("Color", ModeName) == 0) {
164
        std::map<std::string, App::Property*> Map;
165
        pcObject->getPropertyMap(Map);
166
        for (auto& it : Map) {
167
            Base::Type type = it.second->getTypeId();
168
            if (type == App::PropertyColorList::getClassTypeId()) {
169
                App::PropertyColorList* colors = static_cast<App::PropertyColorList*>(it.second);
170
                if (numPoints != colors->getSize()) {
171
#ifdef FC_DEBUG
172
                    SoDebugError::postWarning(
173
                        "ViewProviderPoints::setDisplayMode",
174
                        "The number of points (%d) doesn't match with the number of colors (%d).",
175
                        numPoints,
176
                        colors->getSize());
177
#endif
178
                    // fallback
179
                    setDisplayMaskMode("Point");
180
                }
181
                else {
182
                    setVertexColorMode(colors);
183
                    setDisplayMaskMode("Color");
184
                }
185
                break;
186
            }
187
        }
188
    }
189
    else if (strcmp("Intensity", ModeName) == 0) {
190
        std::map<std::string, App::Property*> Map;
191
        pcObject->getPropertyMap(Map);
192
        for (const auto& it : Map) {
193
            Base::Type type = it.second->getTypeId();
194
            if (type == Points::PropertyGreyValueList::getClassTypeId()) {
195
                Points::PropertyGreyValueList* greyValues =
196
                    static_cast<Points::PropertyGreyValueList*>(it.second);
197
                if (numPoints != greyValues->getSize()) {
198
#ifdef FC_DEBUG
199
                    SoDebugError::postWarning("ViewProviderPoints::setDisplayMode",
200
                                              "The number of points (%d) doesn't match with the "
201
                                              "number of grey values (%d).",
202
                                              numPoints,
203
                                              greyValues->getSize());
204
#endif
205
                    // Intensity mode is not possible then set the default () mode instead.
206
                    setDisplayMaskMode("Point");
207
                }
208
                else {
209
                    setVertexGreyvalueMode((Points::PropertyGreyValueList*)it.second);
210
                    setDisplayMaskMode("Color");
211
                }
212
                break;
213
            }
214
        }
215
    }
216
    else if (strcmp("Shaded", ModeName) == 0) {
217
        std::map<std::string, App::Property*> Map;
218
        pcObject->getPropertyMap(Map);
219
        for (const auto& it : Map) {
220
            Base::Type type = it.second->getTypeId();
221
            if (type == Points::PropertyNormalList::getClassTypeId()) {
222
                Points::PropertyNormalList* normals =
223
                    static_cast<Points::PropertyNormalList*>(it.second);
224
                if (numPoints != normals->getSize()) {
225
#ifdef FC_DEBUG
226
                    SoDebugError::postWarning(
227
                        "ViewProviderPoints::setDisplayMode",
228
                        "The number of points (%d) doesn't match with the number of normals (%d).",
229
                        numPoints,
230
                        normals->getSize());
231
#endif
232
                    // fallback
233
                    setDisplayMaskMode("Point");
234
                }
235
                else {
236
                    setVertexNormalMode(normals);
237
                    setDisplayMaskMode("Shaded");
238
                }
239
                break;
240
            }
241
        }
242
    }
243
    else if (strcmp("Points", ModeName) == 0) {
244
        setDisplayMaskMode("Point");
245
    }
246

247
    ViewProviderGeometryObject::setDisplayMode(ModeName);
248
}
249

250
std::vector<std::string> ViewProviderPoints::getDisplayModes() const
251
{
252
    std::vector<std::string> StrList;
253
    StrList.emplace_back("Points");
254

255
    // FIXME: This way all display modes are added even if the points feature
256
    // doesn't support it.
257
    // For the future a more flexible way is needed to add new display modes
258
    // at a later time
259
#if 1
260
    StrList.emplace_back("Color");
261
    StrList.emplace_back("Shaded");
262
    StrList.emplace_back("Intensity");
263

264
#else
265
    if (pcObject) {
266
        std::map<std::string, App::Property*> Map;
267
        pcObject->getPropertyMap(Map);
268

269
        for (std::map<std::string, App::Property*>::iterator it = Map.begin(); it != Map.end();
270
             ++it) {
271
            Base::Type type = it->second->getTypeId();
272
            if (type == Points::PropertyNormalList::getClassTypeId()) {
273
                StrList.push_back("Shaded");
274
            }
275
            else if (type == Points::PropertyGreyValueList::getClassTypeId()) {
276
                StrList.push_back("Intensity");
277
            }
278
            else if (type == App::PropertyColorList::getClassTypeId()) {
279
                StrList.push_back("Color");
280
            }
281
        }
282
    }
283
#endif
284

285
    return StrList;
286
}
287

288
QIcon ViewProviderPoints::getIcon() const
289
{
290
    // clang-format off
291
    static const char * const Points_Feature_xpm[] = {
292
        "16 16 4 1",
293
        ".	c none",
294
        "s	c #000000",
295
        "b	c #FFFF00",
296
        "r	c #FF0000",
297
        "ss.....ss.....bb",
298
        "ss..ss.ss.....bb",
299
        "....ss..........",
300
        "...........bb...",
301
        ".ss..ss....bb...",
302
        ".ss..ss.........",
303
        "........bb....bb",
304
        "ss......bb....bb",
305
        "ss..rr......bb..",
306
        "....rr......bb..",
307
        "........bb......",
308
        "..rr....bb..bb..",
309
        "..rr........bb..",
310
        ".....rr.........",
311
        "rr...rr..rr..rr.",
312
        "rr.......rr..rr."};
313
    QPixmap px(Points_Feature_xpm);
314
    return px;
315
    // clang-format on
316
}
317

318
bool ViewProviderPoints::setEdit(int ModNum)
319
{
320
    if (ModNum == ViewProvider::Transform) {
321
        return ViewProviderGeometryObject::setEdit(ModNum);
322
    }
323
    else if (ModNum == ViewProvider::Cutting) {
324
        return true;
325
    }
326
    return false;
327
}
328

329
void ViewProviderPoints::unsetEdit(int ModNum)
330
{
331
    if (ModNum == ViewProvider::Transform) {
332
        ViewProviderGeometryObject::unsetEdit(ModNum);
333
    }
334
}
335

336
void ViewProviderPoints::clipPointsCallback(void*, SoEventCallback* n)
337
{
338
    // When this callback function is invoked we must in either case leave the edit mode
339
    Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
340
    view->setEditing(false);
341
    view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), clipPointsCallback);
342
    n->setHandled();
343

344
    std::vector<SbVec2f> clPoly = view->getGLPolygon();
345
    if (clPoly.size() < 3) {
346
        return;
347
    }
348
    if (clPoly.front() != clPoly.back()) {
349
        clPoly.push_back(clPoly.front());
350
    }
351

352
    std::vector<Gui::ViewProvider*> views =
353
        view->getViewProvidersOfType(ViewProviderPoints::getClassTypeId());
354
    for (auto it : views) {
355
        ViewProviderPoints* that = static_cast<ViewProviderPoints*>(it);
356
        if (that->getEditingMode() > -1) {
357
            that->finishEditing();
358
            that->cut(clPoly, *view);
359
        }
360
    }
361

362
    view->redraw();
363
}
364

365
// -------------------------------------------------
366

367
PROPERTY_SOURCE(PointsGui::ViewProviderScattered, PointsGui::ViewProviderPoints)
368

369
ViewProviderScattered::ViewProviderScattered()
370
{
371
    pcPoints = new SoPointSet();
372
    pcPoints->ref();
373
}
374

375
ViewProviderScattered::~ViewProviderScattered()
376
{
377
    pcPoints->unref();
378
}
379

380
void ViewProviderScattered::attach(App::DocumentObject* pcObj)
381
{
382
    // call parent's attach to define display modes
383
    ViewProviderGeometryObject::attach(pcObj);
384

385
    pcHighlight->objectName = pcObj->getNameInDocument();
386
    pcHighlight->documentName = pcObj->getDocument()->getName();
387
    pcHighlight->subElementName = "Main";
388

389
    // Highlight for selection
390
    pcHighlight->addChild(pcPointsCoord);
391
    pcHighlight->addChild(pcPoints);
392

393
    std::vector<std::string> modes = getDisplayModes();
394

395
    // points part ---------------------------------------------
396
    SoGroup* pcPointRoot = new SoGroup();
397
    pcPointRoot->addChild(pcPointStyle);
398
    pcPointRoot->addChild(pcShapeMaterial);
399
    pcPointRoot->addChild(pcHighlight);
400
    addDisplayMaskMode(pcPointRoot, "Point");
401

402
    // points shaded ---------------------------------------------
403
    if (std::find(modes.begin(), modes.end(), std::string("Shaded")) != modes.end()) {
404
        SoGroup* pcPointShadedRoot = new SoGroup();
405
        pcPointShadedRoot->addChild(pcPointStyle);
406
        pcPointShadedRoot->addChild(pcShapeMaterial);
407
        pcPointShadedRoot->addChild(pcPointsNormal);
408
        pcPointShadedRoot->addChild(pcHighlight);
409
        addDisplayMaskMode(pcPointShadedRoot, "Shaded");
410
    }
411

412
    // color shaded  ------------------------------------------
413
    if (std::find(modes.begin(), modes.end(), std::string("Color")) != modes.end()
414
        || std::find(modes.begin(), modes.end(), std::string("Intensity")) != modes.end()) {
415
        SoGroup* pcColorShadedRoot = new SoGroup();
416
        pcColorShadedRoot->addChild(pcPointStyle);
417
        SoMaterialBinding* pcMatBinding = new SoMaterialBinding;
418
        pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
419
        pcColorShadedRoot->addChild(pcColorMat);
420
        pcColorShadedRoot->addChild(pcMatBinding);
421
        pcColorShadedRoot->addChild(pcHighlight);
422
        addDisplayMaskMode(pcColorShadedRoot, "Color");
423
    }
424
}
425

426
void ViewProviderScattered::updateData(const App::Property* prop)
427
{
428
    ViewProviderPoints::updateData(prop);
429
    if (prop->is<Points::PropertyPointKernel>()) {
430
        ViewProviderPointsBuilder builder;
431
        builder.createPoints(prop, pcPointsCoord, pcPoints);
432

433
        // The number of points might have changed, so force also a resize of the Inventor internals
434
        setActiveMode();
435
    }
436
    else if (prop->is<Points::PropertyNormalList>()) {
437
        setActiveMode();
438
    }
439
    else if (prop->is<Points::PropertyGreyValueList>()) {
440
        setActiveMode();
441
    }
442
    else if (prop->is<App::PropertyColorList>()) {
443
        setActiveMode();
444
    }
445
}
446

447
void ViewProviderScattered::cut(const std::vector<SbVec2f>& picked,
448
                                Gui::View3DInventorViewer& Viewer)
449
{
450
    // create the polygon from the picked points
451
    Base::Polygon2d cPoly;
452
    for (const auto& it : picked) {
453
        cPoly.Add(Base::Vector2d(it[0], it[1]));
454
    }
455

456
    // get a reference to the point feature
457
    Points::Feature* fea = static_cast<Points::Feature*>(pcObject);
458
    const Points::PointKernel& points = fea->Points.getValue();
459

460
    SoCamera* pCam = Viewer.getSoRenderManager()->getCamera();
461
    SbViewVolume vol = pCam->getViewVolume();
462

463
    // search for all points inside/outside the polygon
464
    std::vector<unsigned long> removeIndices;
465
    removeIndices.reserve(points.size());
466

467
    unsigned long index = 0;
468
    for (Points::PointKernel::const_iterator jt = points.begin(); jt != points.end();
469
         ++jt, ++index) {
470
        SbVec3f pt(jt->x, jt->y, jt->z);
471

472
        // project from 3d to 2d
473
        vol.projectToScreen(pt, pt);
474
        if (cPoly.Contains(Base::Vector2d(pt[0], pt[1]))) {
475
            removeIndices.push_back(index);
476
        }
477
    }
478

479
    if (removeIndices.empty()) {
480
        return;  // nothing needs to be done
481
    }
482

483
    // Remove the points from the cloud and open a transaction object for the undo/redo stuff
484
    Gui::Application::Instance->activeDocument()->openCommand(
485
        QT_TRANSLATE_NOOP("Command", "Cut points"));
486

487
    // sets the points outside the polygon to update the Inventor node
488
    fea->Points.removeIndices(removeIndices);
489

490
    std::map<std::string, App::Property*> Map;
491
    pcObject->getPropertyMap(Map);
492

493
    for (const auto& it : Map) {
494
        Base::Type type = it.second->getTypeId();
495
        if (type == Points::PropertyNormalList::getClassTypeId()) {
496
            static_cast<Points::PropertyNormalList*>(it.second)->removeIndices(removeIndices);
497
        }
498
        else if (type == Points::PropertyGreyValueList::getClassTypeId()) {
499
            static_cast<Points::PropertyGreyValueList*>(it.second)->removeIndices(removeIndices);
500
        }
501
        else if (type == App::PropertyColorList::getClassTypeId()) {
502
            // static_cast<App::PropertyColorList*>(it->second)->removeIndices(removeIndices);
503
            const std::vector<App::Color>& colors =
504
                static_cast<App::PropertyColorList*>(it.second)->getValues();
505

506
            if (removeIndices.size() > colors.size()) {
507
                break;
508
            }
509

510
            std::vector<App::Color> remainValue;
511
            remainValue.reserve(colors.size() - removeIndices.size());
512

513
            std::vector<unsigned long>::iterator pos = removeIndices.begin();
514
            for (std::vector<App::Color>::const_iterator jt = colors.begin(); jt != colors.end();
515
                 ++jt) {
516
                unsigned long index = jt - colors.begin();
517
                if (pos == removeIndices.end()) {
518
                    remainValue.push_back(*jt);
519
                }
520
                else if (index != *pos) {
521
                    remainValue.push_back(*jt);
522
                }
523
                else {
524
                    ++pos;
525
                }
526
            }
527

528
            static_cast<App::PropertyColorList*>(it.second)->setValues(remainValue);
529
        }
530
    }
531

532
    // unset the modified flag because we don't need the features' execute() to be called
533
    Gui::Application::Instance->activeDocument()->commitCommand();
534
    fea->purgeTouched();
535
}
536

537
// -------------------------------------------------
538

539
PROPERTY_SOURCE(PointsGui::ViewProviderStructured, PointsGui::ViewProviderPoints)
540

541
ViewProviderStructured::ViewProviderStructured()
542
{
543
    pcPoints = new SoIndexedPointSet();
544
    pcPoints->ref();
545
}
546

547
ViewProviderStructured::~ViewProviderStructured()
548
{
549
    pcPoints->unref();
550
}
551

552
void ViewProviderStructured::attach(App::DocumentObject* pcObj)
553
{
554
    // call parent's attach to define display modes
555
    ViewProviderGeometryObject::attach(pcObj);
556

557
    pcHighlight->objectName = pcObj->getNameInDocument();
558
    pcHighlight->documentName = pcObj->getDocument()->getName();
559
    pcHighlight->subElementName = "Main";
560

561
    // Highlight for selection
562
    pcHighlight->addChild(pcPointsCoord);
563
    pcHighlight->addChild(pcPoints);
564

565
    std::vector<std::string> modes = getDisplayModes();
566

567
    // points part ---------------------------------------------
568
    SoGroup* pcPointRoot = new SoGroup();
569
    pcPointRoot->addChild(pcPointStyle);
570
    pcPointRoot->addChild(pcShapeMaterial);
571
    pcPointRoot->addChild(pcHighlight);
572
    addDisplayMaskMode(pcPointRoot, "Point");
573

574
    // points shaded ---------------------------------------------
575
    if (std::find(modes.begin(), modes.end(), std::string("Shaded")) != modes.end()) {
576
        SoGroup* pcPointShadedRoot = new SoGroup();
577
        pcPointShadedRoot->addChild(pcPointStyle);
578
        pcPointShadedRoot->addChild(pcShapeMaterial);
579
        pcPointShadedRoot->addChild(pcPointsNormal);
580
        pcPointShadedRoot->addChild(pcHighlight);
581
        addDisplayMaskMode(pcPointShadedRoot, "Shaded");
582
    }
583

584
    // color shaded  ------------------------------------------
585
    if (std::find(modes.begin(), modes.end(), std::string("Color")) != modes.end()
586
        || std::find(modes.begin(), modes.end(), std::string("Intensity")) != modes.end()) {
587
        SoGroup* pcColorShadedRoot = new SoGroup();
588
        pcColorShadedRoot->addChild(pcPointStyle);
589
        SoMaterialBinding* pcMatBinding = new SoMaterialBinding;
590
        pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
591
        pcColorShadedRoot->addChild(pcColorMat);
592
        pcColorShadedRoot->addChild(pcMatBinding);
593
        pcColorShadedRoot->addChild(pcHighlight);
594
        addDisplayMaskMode(pcColorShadedRoot, "Color");
595
    }
596
}
597

598
void ViewProviderStructured::updateData(const App::Property* prop)
599
{
600
    ViewProviderPoints::updateData(prop);
601
    if (prop->is<Points::PropertyPointKernel>()) {
602
        ViewProviderPointsBuilder builder;
603
        builder.createPoints(prop, pcPointsCoord, pcPoints);
604

605
        // The number of points might have changed, so force also a resize of the Inventor internals
606
        setActiveMode();
607
    }
608
}
609

610
void ViewProviderStructured::cut(const std::vector<SbVec2f>& picked,
611
                                 Gui::View3DInventorViewer& Viewer)
612
{
613
    // create the polygon from the picked points
614
    Base::Polygon2d cPoly;
615
    for (const auto& it : picked) {
616
        cPoly.Add(Base::Vector2d(it[0], it[1]));
617
    }
618

619
    // get a reference to the point feature
620
    Points::Feature* fea = static_cast<Points::Feature*>(pcObject);
621
    const Points::PointKernel& points = fea->Points.getValue();
622

623
    SoCamera* pCam = Viewer.getSoRenderManager()->getCamera();
624
    SbViewVolume vol = pCam->getViewVolume();
625

626
    // search for all points inside/outside the polygon
627
    Points::PointKernel newKernel;
628
    newKernel.reserve(points.size());
629

630
    bool invalidatePoints = false;
631
    double nan = std::numeric_limits<double>::quiet_NaN();
632
    for (const auto& point : points) {
633
        // valid point?
634
        Base::Vector3d vec(point);
635
        if (!(boost::math::isnan(point.x) || boost::math::isnan(point.y)
636
              || boost::math::isnan(point.z))) {
637
            SbVec3f pt(point.x, point.y, point.z);
638

639
            // project from 3d to 2d
640
            vol.projectToScreen(pt, pt);
641
            if (cPoly.Contains(Base::Vector2d(pt[0], pt[1]))) {
642
                invalidatePoints = true;
643
                vec.Set(nan, nan, nan);
644
            }
645
        }
646

647
        newKernel.push_back(vec);
648
    }
649

650
    if (invalidatePoints) {
651
        // Remove the points from the cloud and open a transaction object for the undo/redo stuff
652
        Gui::Application::Instance->activeDocument()->openCommand(
653
            QT_TRANSLATE_NOOP("Command", "Cut points"));
654

655
        // sets the points outside the polygon to update the Inventor node
656
        fea->Points.setValue(newKernel);
657

658
        // unset the modified flag because we don't need the features' execute() to be called
659
        Gui::Application::Instance->activeDocument()->commitCommand();
660
        fea->purgeTouched();
661
    }
662
}
663

664
// -------------------------------------------------
665

666
namespace Gui
667
{
668
/// @cond DOXERR
669
PROPERTY_SOURCE_TEMPLATE(PointsGui::ViewProviderPython, PointsGui::ViewProviderScattered)
670
/// @endcond
671

672
// explicit template instantiation
673
template class PointsGuiExport ViewProviderFeaturePythonT<PointsGui::ViewProviderScattered>;
674
}  // namespace Gui
675

676
// -------------------------------------------------
677

678
void ViewProviderPointsBuilder::buildNodes(const App::Property* prop,
679
                                           std::vector<SoNode*>& nodes) const
680
{
681
    SoCoordinate3* pcPointsCoord = nullptr;
682
    SoPointSet* pcPoints = nullptr;
683

684
    if (nodes.empty()) {
685
        pcPointsCoord = new SoCoordinate3();
686
        nodes.push_back(pcPointsCoord);
687
        pcPoints = new SoPointSet();
688
        nodes.push_back(pcPoints);
689
    }
690
    else if (nodes.size() == 2) {
691
        if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId()) {
692
            pcPointsCoord = static_cast<SoCoordinate3*>(nodes[0]);
693
        }
694
        if (nodes[1]->getTypeId() == SoPointSet::getClassTypeId()) {
695
            pcPoints = static_cast<SoPointSet*>(nodes[1]);
696
        }
697
    }
698

699
    if (pcPointsCoord && pcPoints) {
700
        createPoints(prop, pcPointsCoord, pcPoints);
701
    }
702
}
703

704
void ViewProviderPointsBuilder::createPoints(const App::Property* prop,
705
                                             SoCoordinate3* coords,
706
                                             SoPointSet* points) const
707
{
708
    const Points::PropertyPointKernel* prop_points =
709
        static_cast<const Points::PropertyPointKernel*>(prop);
710
    const Points::PointKernel& cPts = prop_points->getValue();
711

712
    coords->point.setNum(cPts.size());
713
    SbVec3f* vec = coords->point.startEditing();
714

715
    // get all points
716
    std::size_t idx = 0;
717
    const std::vector<Points::PointKernel::value_type>& kernel = cPts.getBasicPoints();
718
    for (std::vector<Points::PointKernel::value_type>::const_iterator it = kernel.begin();
719
         it != kernel.end();
720
         ++it, idx++) {
721
        vec[idx].setValue(it->x, it->y, it->z);
722
    }
723

724
    points->numPoints = cPts.size();
725
    coords->point.finishEditing();
726
}
727

728
void ViewProviderPointsBuilder::createPoints(const App::Property* prop,
729
                                             SoCoordinate3* coords,
730
                                             SoIndexedPointSet* points) const
731
{
732
    const Points::PropertyPointKernel* prop_points =
733
        static_cast<const Points::PropertyPointKernel*>(prop);
734
    const Points::PointKernel& cPts = prop_points->getValue();
735

736
    coords->point.setNum(cPts.size());
737
    SbVec3f* vec = coords->point.startEditing();
738

739
    // get all points
740
    std::size_t idx = 0;
741
    std::vector<int32_t> indices;
742
    indices.reserve(cPts.size());
743
    const std::vector<Points::PointKernel::value_type>& kernel = cPts.getBasicPoints();
744
    for (std::vector<Points::PointKernel::value_type>::const_iterator it = kernel.begin();
745
         it != kernel.end();
746
         ++it, idx++) {
747
        vec[idx].setValue(it->x, it->y, it->z);
748
        // valid point?
749
        if (!(boost::math::isnan(it->x) || boost::math::isnan(it->y)
750
              || boost::math::isnan(it->z))) {
751
            indices.push_back(idx);
752
        }
753
    }
754
    coords->point.finishEditing();
755

756
    // get all point indices
757
    idx = 0;
758
    points->coordIndex.setNum(indices.size());
759
    int32_t* pos = points->coordIndex.startEditing();
760
    for (int32_t index : indices) {
761
        pos[idx++] = index;
762
    }
763
    points->coordIndex.finishEditing();
764
}
765

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

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

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

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