23
#include "PreCompiled.h"
29
#include <Inventor/SbBox2s.h>
30
#include <Inventor/SbLine.h>
31
#include <Inventor/SbPlane.h>
32
#include <Inventor/SoPickedPoint.h>
33
#include <Inventor/actions/SoToVRML2Action.h>
34
#include <Inventor/details/SoFaceDetail.h>
35
#include <Inventor/events/SoMouseButtonEvent.h>
36
#include <Inventor/nodes/SoBaseColor.h>
37
#include <Inventor/nodes/SoCoordinate3.h>
38
#include <Inventor/nodes/SoDrawStyle.h>
39
#include <Inventor/nodes/SoLightModel.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/SoOrthographicCamera.h>
45
#include <Inventor/nodes/SoPerspectiveCamera.h>
46
#include <Inventor/nodes/SoPolygonOffset.h>
47
#include <Inventor/nodes/SoShapeHints.h>
48
#include <Inventor/nodes/SoSeparator.h>
49
#include <Inventor/nodes/SoTransform.h>
50
#include <Inventor/VRMLnodes/SoVRMLGroup.h>
54
#include <QFutureWatcher>
55
#include <QtConcurrentMap>
57
#include <App/Document.h>
58
#include <Base/Console.h>
59
#include <Base/Exception.h>
60
#include <Base/Sequencer.h>
61
#include <Base/Stream.h>
62
#include <Base/Tools.h>
63
#include <Base/ViewProj.h>
64
#include <Gui/ActionFunction.h>
65
#include <Gui/Application.h>
66
#include <Gui/BitmapFactory.h>
67
#include <Gui/Command.h>
68
#include <Gui/Document.h>
70
#include <Gui/Selection.h>
71
#include <Gui/SoFCDB.h>
72
#include <Gui/SoFCOffscreenRenderer.h>
73
#include <Gui/SoFCSelection.h>
74
#include <Gui/SoFCSelectionAction.h>
75
#include <Gui/Utilities.h>
76
#include <Gui/View3DInventorViewer.h>
77
#include <Gui/WaitCursor.h>
78
#include <Gui/Window.h>
79
#include <Mod/Mesh/App/Core/Algorithm.h>
80
#include <Mod/Mesh/App/Core/Grid.h>
81
#include <Mod/Mesh/App/Core/Iterator.h>
82
#include <Mod/Mesh/App/Core/MeshIO.h>
83
#include <Mod/Mesh/App/Core/Triangulation.h>
84
#include <Mod/Mesh/App/Core/Trim.h>
85
#include <Mod/Mesh/App/Core/Visitor.h>
86
#include <Mod/Mesh/App/MeshFeature.h>
87
#include <Mod/Mesh/Gui/ViewProviderMeshPy.h>
88
#include <zipios++/gzipoutputstream.h>
90
#include "SoFCIndexedFaceSet.h"
91
#include "SoFCMeshObject.h"
92
#include "ViewProvider.h"
95
using namespace MeshGui;
96
namespace sp = std::placeholders;
99
using MeshCore::MeshFacet;
100
using MeshCore::MeshFacetIterator;
101
using MeshCore::MeshGeomFacet;
102
using MeshCore::MeshKernel;
103
using MeshCore::MeshPointIterator;
105
void ViewProviderMeshBuilder::buildNodes(const App::Property* prop,
106
std::vector<SoNode*>& nodes) const
108
SoCoordinate3* pcPointsCoord = nullptr;
109
SoIndexedFaceSet* pcFaces = nullptr;
112
pcPointsCoord = new SoCoordinate3();
113
nodes.push_back(pcPointsCoord);
114
pcFaces = new SoIndexedFaceSet();
115
nodes.push_back(pcFaces);
117
else if (nodes.size() == 2) {
118
if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId()) {
119
pcPointsCoord = static_cast<SoCoordinate3*>(nodes[0]);
121
if (nodes[1]->getTypeId() == SoIndexedFaceSet::getClassTypeId()) {
122
pcFaces = static_cast<SoIndexedFaceSet*>(nodes[1]);
126
if (pcPointsCoord && pcFaces) {
127
createMesh(prop, pcPointsCoord, pcFaces);
131
void ViewProviderMeshBuilder::createMesh(const App::Property* prop,
132
SoCoordinate3* coords,
133
SoIndexedFaceSet* faces) const
135
const Mesh::PropertyMeshKernel* mesh = static_cast<const Mesh::PropertyMeshKernel*>(prop);
136
const MeshCore::MeshKernel& rcMesh = mesh->getValue().getKernel();
137
createMesh(rcMesh, coords, faces);
140
void ViewProviderMeshBuilder::createMesh(const MeshCore::MeshKernel& kernel,
141
SoCoordinate3* coords,
142
SoIndexedFaceSet* faces) const
146
const MeshCore::MeshPointArray& cP = kernel.GetPoints();
147
coords->point.setNum(kernel.CountPoints());
148
SbVec3f* verts = coords->point.startEditing();
150
for (MeshCore::MeshPointArray::_TConstIterator it = cP.begin(); it != cP.end(); ++it, i++) {
151
verts[i].setValue(it->x, it->y, it->z);
153
coords->point.finishEditing();
157
const MeshCore::MeshFacetArray& cF = kernel.GetFacets();
158
faces->coordIndex.setNum(4 * kernel.CountFacets());
159
int32_t* indices = faces->coordIndex.startEditing();
160
for (MeshCore::MeshFacetArray::_TConstIterator it = cF.begin(); it != cF.end(); ++it, j++) {
161
for (int i = 0; i < 3; i++) {
162
indices[4 * j + i] = it->_aulPoints[i];
164
indices[4 * j + 3] = SO_END_FACE_INDEX;
166
faces->coordIndex.finishEditing();
169
PROPERTY_SOURCE(MeshGui::ViewProviderExport, Gui::ViewProviderDocumentObject)
171
ViewProviderExport::ViewProviderExport() = default;
173
ViewProviderExport::~ViewProviderExport() = default;
175
std::vector<std::string> ViewProviderExport::getDisplayModes() const
177
std::vector<std::string> mode;
178
mode.emplace_back("");
182
const char* ViewProviderExport::getDefaultDisplayMode() const
187
QIcon ViewProviderExport::getIcon() const
190
const char * Mesh_Feature_xpm[] = {
198
".............##.......",
199
".............###......",
200
".............#f##.....",
201
".#....####...#ff##....",
202
".##.##....#..#fff##...",
203
".###.........#ffff##..",
204
".####........#fffff##.",
205
".#####.......#ffffff##",
206
".............#########",
207
".####.................",
208
"#abab##########.......",
209
"#babababababab#.......",
210
"#ababababababa#.......",
211
"#babab################",
212
"#abab##cccccccccccc##.",
213
"#bab##cccccccccccc##..",
214
"#ab##cccccccccccc##...",
215
"#b##cccccccccccc##....",
216
"###cccccccccccc##.....",
217
"##cccccccccccc##......",
218
"###############.......",
219
"......................"};
220
QPixmap px(Mesh_Feature_xpm);
227
App::PropertyFloatConstraint::Constraints ViewProviderMesh::floatRange = {1.0F, 64.0F, 1.0F};
228
App::PropertyFloatConstraint::Constraints ViewProviderMesh::angleRange = {0.0F, 180.0F, 1.0F};
229
App::PropertyIntegerConstraint::Constraints ViewProviderMesh::intPercent = {0, 100, 5};
230
const char* ViewProviderMesh::LightingEnums[] = {"One side", "Two side", nullptr};
232
PROPERTY_SOURCE(MeshGui::ViewProviderMesh, Gui::ViewProviderGeometryObject)
234
ViewProviderMesh::ViewProviderMesh()
235
: highlightMode {HighlighMode::None}
238
static const char* osgroup = "Object Style";
240
ADD_PROPERTY_TYPE(LineTransparency, (0), osgroup, App::Prop_None, "Set line transparency.");
241
LineTransparency.setConstraints(&intPercent);
242
ADD_PROPERTY_TYPE(LineWidth, (1.0f), osgroup, App::Prop_None, "Set line width.");
243
LineWidth.setConstraints(&floatRange);
244
ADD_PROPERTY_TYPE(PointSize, (2.0f), osgroup, App::Prop_None, "Set point size.");
245
PointSize.setConstraints(&floatRange);
246
ADD_PROPERTY_TYPE(CreaseAngle, (0.0f), osgroup, App::Prop_None, "Set crease angle.");
247
CreaseAngle.setConstraints(&angleRange);
248
ADD_PROPERTY_TYPE(OpenEdges, (false), osgroup, App::Prop_None, "Set open edges.");
249
ADD_PROPERTY_TYPE(Coloring, (false), osgroup, App::Prop_None, "Set coloring.");
250
ADD_PROPERTY_TYPE(Lighting,
254
"Set if the illumination comes from two sides\n or one side in the 3D view.");
255
Lighting.setEnums(LightingEnums);
256
ADD_PROPERTY_TYPE(LineColor, (0, 0, 0), osgroup, App::Prop_None, "Set line color.");
259
pcHighlight = Gui::ViewProviderBuilder::createSelection();
261
if (pcHighlight->selectionMode.getValue() == Gui::SoFCSelection::SEL_OFF) {
262
Selectable.setValue(false);
265
pcShapeGroup = new SoGroup();
267
pcHighlight->addChild(pcShapeGroup);
269
pOpenColor = new SoBaseColor();
270
setOpenEdgeColorFrom(ShapeColor.getValue());
273
pcLineStyle = new SoDrawStyle();
275
pcLineStyle->style = SoDrawStyle::LINES;
276
pcLineStyle->lineWidth = LineWidth.getValue();
278
pcPointStyle = new SoDrawStyle();
280
pcPointStyle->style = SoDrawStyle::POINTS;
281
pcPointStyle->pointSize = PointSize.getValue();
283
pShapeHints = new SoShapeHints;
284
pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
287
pcMatBinding = new SoMaterialBinding;
288
pcMatBinding->value = SoMaterialBinding::OVERALL;
291
pLineColor = new SoMaterial;
296
Base::Reference<ParameterGrp> hGrp =
297
Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
300
App::Color color = ShapeColor.getValue();
301
unsigned long current = color.getPackedValue();
302
unsigned long setting = hGrp->GetUnsigned("MeshColor", current);
303
if (current != setting) {
304
color.setPackedValue((uint32_t)setting);
305
ShapeColor.setValue(color);
307
Transparency.setValue(hGrp->GetInt("MeshTransparency", 0));
310
color = LineColor.getValue();
311
current = color.getPackedValue();
312
setting = hGrp->GetUnsigned("LineColor", current);
313
if (current != setting) {
314
color.setPackedValue((uint32_t)setting);
315
LineColor.setValue(color);
317
LineTransparency.setValue(hGrp->GetInt("LineTransparency", 0));
319
bool twoside = hGrp->GetBool("TwoSideRendering", false);
321
Lighting.setValue(1);
324
Lighting.setValue((long)0);
327
bool normal_per_vertex = hGrp->GetBool("VertexPerNormals", false);
328
if (normal_per_vertex) {
329
double angle = hGrp->GetFloat("CreaseAngle", 0.0);
330
CreaseAngle.setValue(angle);
333
if (hGrp->GetBool("ShowBoundingBox", false)) {
334
SelectionStyle.setValue(1);
337
Coloring.setStatus(App::Property::Hidden, true);
341
ViewProviderMesh::~ViewProviderMesh()
343
pcHighlight->unref();
344
pcShapeGroup->unref();
346
pcLineStyle->unref();
347
pcPointStyle->unref();
348
pShapeHints->unref();
349
pcMatBinding->unref();
353
void ViewProviderMesh::onChanged(const App::Property* prop)
356
if (prop == &ShapeColor || prop == &ShapeMaterial) {
357
pcMatBinding->value = SoMaterialBinding::OVERALL;
359
if (prop == &LineTransparency) {
360
float trans = LineTransparency.getValue() / 100.0F;
361
pLineColor->transparency = trans;
363
else if (prop == &LineWidth) {
364
pcLineStyle->lineWidth = LineWidth.getValue();
366
else if (prop == &PointSize) {
367
pcPointStyle->pointSize = PointSize.getValue();
369
else if (prop == &CreaseAngle) {
370
pShapeHints->creaseAngle = Base::toRadians<float>(CreaseAngle.getValue());
372
else if (prop == &OpenEdges) {
373
showOpenEdges(OpenEdges.getValue());
375
else if (prop == &Lighting) {
376
if (Lighting.getValue() == 0) {
377
pShapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
380
pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
383
else if (prop == &LineColor) {
384
const App::Color& c = LineColor.getValue();
385
pLineColor->diffuseColor.setValue(c.r, c.g, c.b);
387
else if (prop == &Coloring) {
388
tryColorPerVertexOrFace(Coloring.getValue());
390
else if (prop == &SelectionStyle) {
392
SelectionStyle.getValue() ? Gui::SoFCSelection::BOX : Gui::SoFCSelection::EMISSIVE;
396
if (prop == &ShapeColor) {
397
setOpenEdgeColorFrom(ShapeColor.getValue());
399
else if (prop == &ShapeMaterial) {
400
setOpenEdgeColorFrom(ShapeMaterial.getValue().diffuseColor);
404
ViewProviderGeometryObject::onChanged(prop);
407
void ViewProviderMesh::setOpenEdgeColorFrom(const App::Color& c)
409
float r = 1.0F - c.r;
410
r = r < 0.5F ? 0.0F : 1.0F;
411
float g = 1.0F - c.g;
412
g = g < 0.5F ? 0.0F : 1.0F;
413
float b = 1.0F - c.b;
414
b = b < 0.5F ? 0.0F : 1.0F;
415
pOpenColor->rgb.setValue(r, g, b);
418
SoShape* ViewProviderMesh::getShapeNode() const
423
SoNode* ViewProviderMesh::getCoordNode() const
432
void ViewProviderMesh::attach(App::DocumentObject* pcFeat)
434
ViewProviderGeometryObject::attach(pcFeat);
436
pcHighlight->objectName = pcFeat->getNameInDocument();
437
pcHighlight->documentName = pcFeat->getDocument()->getName();
438
pcHighlight->subElementName = "Main";
447
SoGroup* pcFlatRoot = new SoGroup();
448
pcFlatRoot->addChild(pShapeHints);
449
pcFlatRoot->addChild(pcShapeMaterial);
450
pcFlatRoot->addChild(pcMatBinding);
451
pcFlatRoot->addChild(pcHighlight);
452
addDisplayMaskMode(pcFlatRoot, "Shaded");
455
SoGroup* pcPointRoot = new SoGroup();
456
pcPointRoot->addChild(pcPointStyle);
457
pcPointRoot->addChild(pShapeHints);
458
pcPointRoot->addChild(pcShapeMaterial);
459
pcPointRoot->addChild(pcMatBinding);
460
pcPointRoot->addChild(pcHighlight);
461
addDisplayMaskMode(pcPointRoot, "Point");
464
SoLightModel* pcLightModel = new SoLightModel();
465
pcLightModel->model = SoLightModel::BASE_COLOR;
466
SoGroup* pcWireRoot = new SoGroup();
467
pcWireRoot->addChild(pcLineStyle);
468
pcWireRoot->addChild(pcLightModel);
469
SoMaterialBinding* binding = new SoMaterialBinding;
470
binding->value = SoMaterialBinding::OVERALL;
471
pcWireRoot->addChild(binding);
472
pcWireRoot->addChild(pLineColor);
473
pcWireRoot->addChild(pcHighlight);
474
addDisplayMaskMode(pcWireRoot, "Wireframe");
479
SoPolygonOffset* offset = new SoPolygonOffset();
480
offset->styles = SoPolygonOffset::FILLED;
481
offset->factor = 1.0F;
482
offset->units = 1.0F;
484
SoSeparator* pcWireSep = new SoSeparator();
485
pcWireSep->addChild(pcLineStyle);
486
pcWireSep->addChild(pcLightModel);
487
pcWireSep->addChild(binding);
488
pcWireSep->addChild(pLineColor);
489
pcWireSep->addChild(pcHighlight);
491
SoGroup* pcFlatWireRoot = new SoGroup();
492
pcFlatWireRoot->addChild(pcWireSep);
493
pcFlatWireRoot->addChild(offset);
494
pcFlatWireRoot->addChild(pShapeHints);
495
pcFlatWireRoot->addChild(pcShapeMaterial);
496
pcFlatWireRoot->addChild(pcMatBinding);
497
pcFlatWireRoot->addChild(pcShapeGroup);
498
addDisplayMaskMode(pcFlatWireRoot, "Flat Lines");
500
if (getColorProperty() || getMaterialProperty()) {
501
Coloring.setStatus(App::Property::Hidden, false);
505
void ViewProviderMesh::updateData(const App::Property* prop)
507
Gui::ViewProviderGeometryObject::updateData(prop);
509
if (prop->is<App::PropertyColorList>()) {
510
Coloring.setStatus(App::Property::Hidden, false);
512
else if (prop->is<Mesh::PropertyMaterial>()) {
513
Coloring.setStatus(App::Property::Hidden, false);
517
QIcon ViewProviderMesh::getIcon() const
519
static QIcon icon = Gui::BitmapFactory().pixmap("Mesh_Tree");
523
App::PropertyColorList* ViewProviderMesh::getColorProperty() const
526
std::map<std::string, App::Property*> Map;
527
pcObject->getPropertyMap(Map);
528
for (const auto& it : Map) {
529
Base::Type type = it.second->getTypeId();
530
if (type == App::PropertyColorList::getClassTypeId()) {
531
App::PropertyColorList* colors = static_cast<App::PropertyColorList*>(it.second);
539
void ViewProviderMesh::tryColorPerVertexOrFace(bool on)
542
const Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
543
const Mesh::MeshObject& mesh = meshProp.getValue();
544
int numPoints = static_cast<int>(mesh.countPoints());
545
int numFacets = static_cast<int>(mesh.countFacets());
547
if (App::PropertyColorList* colors = getColorProperty()) {
548
if (colors->getSize() == numPoints) {
549
setColorPerVertex(colors);
551
else if (colors->getSize() == numFacets) {
552
setColorPerFace(colors);
555
else if (Mesh::PropertyMaterial* material = getMaterialProperty()) {
556
auto bind = material->getBinding();
557
if (bind == MeshCore::MeshIO::Binding::OVERALL) {
558
pcMatBinding->value = SoMaterialBinding::OVERALL;
560
if (!material->getDiffuseColor().empty()) {
561
auto c = material->getDiffuseColor()[0];
562
pcShapeMaterial->diffuseColor.setValue(c.r, c.g, c.b);
564
if (!material->getTransparency().empty()) {
565
pcShapeMaterial->transparency.setValue(material->getTransparency()[0]);
568
else if (bind == MeshCore::MeshIO::Binding::PER_VERTEX) {
569
if (material->getDiffuseColor().size() == std::size_t(numPoints)) {
570
pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
571
setDiffuseColor(material->getDiffuseColor());
574
else if (bind == MeshCore::MeshIO::Binding::PER_FACE) {
575
if (material->getAmbientColor().size() == std::size_t(numFacets)) {
576
pcMatBinding->value = SoMaterialBinding::PER_FACE;
577
setAmbientColor(material->getAmbientColor());
579
if (material->getDiffuseColor().size() == std::size_t(numFacets)) {
580
pcMatBinding->value = SoMaterialBinding::PER_FACE;
581
setDiffuseColor(material->getDiffuseColor());
583
if (material->getEmissiveColor().size() == std::size_t(numFacets)) {
584
pcMatBinding->value = SoMaterialBinding::PER_FACE;
585
setEmissiveColor(material->getEmissiveColor());
587
if (material->getSpecularColor().size() == std::size_t(numFacets)) {
588
pcMatBinding->value = SoMaterialBinding::PER_FACE;
589
setSpecularColor(material->getSpecularColor());
591
if (material->getTransparency().size() == std::size_t(numFacets)) {
592
pcMatBinding->value = SoMaterialBinding::PER_FACE;
593
setFacetTransparency(material->getTransparency());
599
pcMatBinding->value = SoMaterialBinding::OVERALL;
600
const App::Color& c = ShapeColor.getValue();
601
pcShapeMaterial->diffuseColor.setValue(c.r, c.g, c.b);
602
pcShapeMaterial->transparency.setValue(Transparency.getValue() / 100.0f);
606
void ViewProviderMesh::setColorPerVertex(const App::PropertyColorList* prop)
608
pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
609
setDiffuseColor(prop->getValues());
612
void ViewProviderMesh::setColorPerFace(const App::PropertyColorList* prop)
614
pcMatBinding->value = SoMaterialBinding::PER_FACE;
615
setDiffuseColor(prop->getValues());
618
void ViewProviderMesh::setColorField(const std::vector<App::Color>& val, SoMFColor& field)
620
field.setNum(val.size());
621
SbColor* col = field.startEditing();
624
for (auto it : val) {
625
col[i++].setValue(it.r, it.g, it.b);
628
field.finishEditing();
631
void ViewProviderMesh::setAmbientColor(const std::vector<App::Color>& val)
633
setColorField(val, pcShapeMaterial->ambientColor);
636
void ViewProviderMesh::setDiffuseColor(const std::vector<App::Color>& val)
638
setColorField(val, pcShapeMaterial->diffuseColor);
641
void ViewProviderMesh::setSpecularColor(const std::vector<App::Color>& val)
643
setColorField(val, pcShapeMaterial->specularColor);
646
void ViewProviderMesh::setEmissiveColor(const std::vector<App::Color>& val)
648
setColorField(val, pcShapeMaterial->emissiveColor);
651
Mesh::PropertyMaterial* ViewProviderMesh::getMaterialProperty() const
654
std::map<std::string, App::Property*> Map;
655
pcObject->getPropertyMap(Map);
656
for (const auto& it : Map) {
657
Base::Type type = it.second->getTypeId();
658
if (type == Mesh::PropertyMaterial::getClassTypeId()) {
659
Mesh::PropertyMaterial* material = static_cast<Mesh::PropertyMaterial*>(it.second);
668
void ViewProviderMesh::setDisplayMode(const char* ModeName)
670
if (strcmp("Shaded", ModeName) == 0) {
671
setDisplayMaskMode("Shaded");
673
else if (strcmp("Points", ModeName) == 0) {
674
setDisplayMaskMode("Point");
676
else if (strcmp("Flat Lines", ModeName) == 0) {
677
setDisplayMaskMode("Flat Lines");
679
else if (strcmp("Wireframe", ModeName) == 0) {
680
setDisplayMaskMode("Wireframe");
683
ViewProviderGeometryObject::setDisplayMode(ModeName);
686
std::vector<std::string> ViewProviderMesh::getDisplayModes() const
688
std::vector<std::string> StrList;
691
StrList.emplace_back("Shaded");
692
StrList.emplace_back("Wireframe");
693
StrList.emplace_back("Flat Lines");
694
StrList.emplace_back("Points");
699
bool ViewProviderMesh::exportToVrml(const char* filename,
700
const MeshCore::Material& mat,
703
SoCoordinate3* coords = new SoCoordinate3();
704
SoIndexedFaceSet* faces = new SoIndexedFaceSet();
705
ViewProviderMeshBuilder builder;
706
builder.createMesh(&static_cast<Mesh::Feature*>(pcObject)->Mesh, coords, faces);
708
SoMaterialBinding* binding = new SoMaterialBinding;
709
SoMaterial* material = new SoMaterial;
711
if (static_cast<int>(mat.diffuseColor.size()) == coords->point.getNum()) {
712
binding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
714
else if (static_cast<int>(mat.diffuseColor.size()) == faces->coordIndex.getNum() / 4) {
715
binding->value = SoMaterialBinding::PER_FACE_INDEXED;
718
if (mat.diffuseColor.size() > 1) {
719
material->diffuseColor.setNum(mat.diffuseColor.size());
720
SbColor* colors = material->diffuseColor.startEditing();
721
for (unsigned int i = 0; i < mat.diffuseColor.size(); i++) {
722
colors[i].setValue(mat.diffuseColor[i].r, mat.diffuseColor[i].g, mat.diffuseColor[i].b);
724
material->diffuseColor.finishEditing();
727
SoGroup* group = new SoGroup();
728
group->addChild(material);
729
group->addChild(binding);
730
group->addChild(new SoTransform());
731
group->addChild(coords);
732
group->addChild(faces);
734
SoToVRML2Action tovrml2;
736
tovrml2.apply(group);
738
SoVRMLGroup* vrmlRoot = tovrml2.getVRML2SceneGraph();
740
std::string buffer = Gui::SoFCDB::writeNodesToString(vrmlRoot);
743
Base::FileInfo fi(filename);
745
Base::ofstream str(fi, std::ios::out | std::ios::binary);
746
zipios::GZIPOutputStream gzip(str);
754
Base::ofstream str(fi, std::ios::out);
765
void ViewProviderMesh::exportMesh(const char* filename, const char* fmt) const
767
MeshCore::MeshIO::Format format = MeshCore::MeshIO::Undefined;
769
std::string dummy = "meshfile.";
771
format = MeshCore::MeshOutput::GetFormat(dummy.c_str());
774
MeshCore::Material mat;
775
int numColors = pcShapeMaterial->diffuseColor.getNum();
776
const SbColor* colors = pcShapeMaterial->diffuseColor.getValues(0);
777
mat.diffuseColor.reserve(numColors);
778
for (int i = 0; i < numColors; i++) {
779
const SbColor& c = colors[i];
780
mat.diffuseColor.emplace_back(c[0], c[1], c[2]);
783
Mesh::MeshObject mesh = static_cast<Mesh::Feature*>(getObject())->Mesh.getValue();
784
mesh.setPlacement(static_cast<Mesh::Feature*>(getObject())->globalPlacement());
785
if (mat.diffuseColor.size() == mesh.countPoints()) {
786
mat.binding = MeshCore::MeshIO::PER_VERTEX;
788
else if (mat.diffuseColor.size() == mesh.countFacets()) {
789
mat.binding = MeshCore::MeshIO::PER_FACE;
792
mat.binding = MeshCore::MeshIO::OVERALL;
795
mesh.save(filename, format, &mat, getObject()->Label.getValue());
798
void ViewProviderMesh::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
800
ViewProviderGeometryObject::setupContextMenu(menu, receiver, member);
803
Gui::ActionFunction* func = new Gui::ActionFunction(menu);
804
QAction* act = menu->addAction(QObject::tr("Display components"));
805
act->setCheckable(true);
806
act->setChecked(pcMatBinding->value.getValue() == SoMaterialBinding::PER_FACE
807
&& highlightMode == HighlighMode::Component);
808
func->toggle(act, [this](bool on) {
809
this->setHighlightedComponents(on);
812
QAction* seg = menu->addAction(QObject::tr("Display segments"));
813
seg->setCheckable(true);
814
seg->setChecked(pcMatBinding->value.getValue() == SoMaterialBinding::PER_FACE
815
&& highlightMode == HighlighMode::Segment);
816
func->toggle(seg, [this](bool on) {
817
this->setHighlightedSegments(on);
820
QAction* col = menu->addAction(QObject::tr("Display colors"));
821
col->setVisible(canHighlightColors());
822
col->setCheckable(true);
823
col->setChecked(highlightMode == HighlighMode::Color);
824
func->toggle(col, [this](bool on) {
825
this->setHighlightedColors(on);
829
bool ViewProviderMesh::setEdit(int ModNum)
831
if (ModNum == ViewProvider::Transform) {
832
return ViewProviderGeometryObject::setEdit(ModNum);
834
else if (ModNum == ViewProvider::Color) {
835
highlightComponents();
840
void ViewProviderMesh::unsetEdit(int ModNum)
842
if (ModNum == ViewProvider::Transform) {
843
ViewProviderGeometryObject::unsetEdit(ModNum);
845
else if (ModNum == ViewProvider::Color) {
846
unhighlightSelection();
850
bool ViewProviderMesh::createToolMesh(const std::vector<SbVec2f>& rclPoly,
851
const SbViewVolume& vol,
852
const Base::Vector3f& rcNormal,
853
std::vector<MeshCore::MeshGeomFacet>& aFaces)
855
float fX {}, fY {}, fZ {};
856
SbVec3f pt1, pt2, pt3, pt4;
858
std::vector<Base::Vector3f> top, bottom, polygon;
860
for (std::vector<SbVec2f>::const_iterator it = rclPoly.begin(); it != rclPoly.end(); ++it) {
862
std::vector<SbVec2f>::const_iterator nt = it + 1;
863
if (nt == rclPoly.end()) {
864
nt = rclPoly.begin();
866
else if (*it == *nt) {
870
vol.projectPointToLine(*it, pt1, pt2);
871
vol.projectPointToLine(*nt, pt3, pt4);
874
pt1.getValue(fX, fY, fZ);
875
face._aclPoints[0].Set(fX, fY, fZ);
876
pt4.getValue(fX, fY, fZ);
877
face._aclPoints[1].Set(fX, fY, fZ);
878
pt3.getValue(fX, fY, fZ);
879
face._aclPoints[2].Set(fX, fY, fZ);
880
if (face.Area() > 0) {
881
aFaces.push_back(face);
885
pt1.getValue(fX, fY, fZ);
886
face._aclPoints[0].Set(fX, fY, fZ);
887
pt2.getValue(fX, fY, fZ);
888
face._aclPoints[1].Set(fX, fY, fZ);
889
pt4.getValue(fX, fY, fZ);
890
face._aclPoints[2].Set(fX, fY, fZ);
891
if (face.Area() > 0) {
892
aFaces.push_back(face);
895
if (it + 1 < rclPoly.end()) {
896
pt1.getValue(fX, fY, fZ);
897
top.emplace_back(fX, fY, fZ);
898
pt2.getValue(fX, fY, fZ);
899
bottom.emplace_back(fX, fY, fZ);
901
it->getValue(fX, fY);
902
polygon.emplace_back(fX, fY, 0.0f);
907
std::vector<MeshGeomFacet> aLid;
908
MeshCore::EarClippingTriangulator cTria;
909
cTria.SetPolygon(polygon);
910
bool ok = cTria.TriangulatePolygon();
912
std::vector<MeshFacet> faces = cTria.GetFacets();
913
for (const auto& face : faces) {
914
MeshGeomFacet topFacet;
915
topFacet._aclPoints[0] = top[face._aulPoints[0]];
916
topFacet._aclPoints[1] = top[face._aulPoints[1]];
917
topFacet._aclPoints[2] = top[face._aulPoints[2]];
918
if (topFacet.GetNormal() * rcNormal < 0) {
919
std::swap(topFacet._aclPoints[1], topFacet._aclPoints[2]);
920
topFacet.CalcNormal();
922
aFaces.push_back(topFacet);
924
MeshGeomFacet botFacet;
925
botFacet._aclPoints[0] = bottom[face._aulPoints[0]];
926
botFacet._aclPoints[1] = bottom[face._aulPoints[1]];
927
botFacet._aclPoints[2] = bottom[face._aulPoints[2]];
928
if (botFacet.GetNormal() * rcNormal > 0) {
929
std::swap(botFacet._aclPoints[1], botFacet._aclPoints[2]);
930
botFacet.CalcNormal();
932
aFaces.push_back(botFacet);
938
void ViewProviderMesh::showOpenEdges(bool show)
948
MeshSplit(ViewProviderMesh* mesh,
949
std::vector<SbVec2f> poly,
950
const Gui::ViewVolumeProjection& proj)
952
, poly(std::move(poly))
957
Gui::Document* gui = mesh->getDocument();
958
gui->openCommand(QT_TRANSLATE_NOOP("Command", "Cut"));
959
ViewProviderMesh* copy = makeCopy();
960
mesh->cutMesh(poly, proj, false);
961
copy->cutMesh(poly, proj, true);
962
gui->commitCommand();
967
Gui::Document* gui = mesh->getDocument();
968
gui->openCommand(QT_TRANSLATE_NOOP("Command", "Trim"));
969
ViewProviderMesh* copy = makeCopy();
970
mesh->trimMesh(poly, proj, false);
971
copy->trimMesh(poly, proj, true);
972
gui->commitCommand();
975
ViewProviderMesh* makeCopy() const
977
Gui::Document* gui = mesh->getDocument();
978
App::Document* doc = gui->getDocument();
980
Mesh::Feature* cpy = static_cast<Mesh::Feature*>(doc->addObject("Mesh::Feature"));
981
Mesh::Feature* org = static_cast<Mesh::Feature*>(mesh->getObject());
982
cpy->Label.setValue(org->Label.getValue());
983
cpy->Mesh.setValue(org->Mesh.getValue());
985
return static_cast<ViewProviderMesh*>(gui->getViewProvider(cpy));
989
ViewProviderMesh* mesh;
990
std::vector<SbVec2f> poly;
991
Gui::ViewVolumeProjection proj;
995
void ViewProviderMesh::clipMeshCallback(void* ud, SoEventCallback* n)
1001
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
1002
view->setEditing(false);
1003
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), clipMeshCallback, ud);
1006
Gui::SelectionRole role {};
1007
std::vector<SbVec2f> clPoly = view->getGLPolygon(&role);
1008
if (clPoly.size() < 3) {
1011
if (clPoly.front() != clPoly.back()) {
1012
clPoly.push_back(clPoly.front());
1015
std::vector<Gui::ViewProvider*> views =
1016
view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1017
if (!views.empty()) {
1018
Gui::Application::Instance->activeDocument()->openCommand(
1019
QT_TRANSLATE_NOOP("Command", "Cut"));
1020
bool commitCommand = false;
1021
for (auto it : views) {
1022
ViewProviderMesh* self = static_cast<ViewProviderMesh*>(it);
1023
if (self->getEditingMode() > -1) {
1024
self->finishEditing();
1025
SoCamera* cam = view->getSoRenderManager()->getCamera();
1026
SbViewVolume vv = cam->getViewVolume();
1027
Gui::ViewVolumeProjection proj(vv);
1028
proj.setTransform(static_cast<Mesh::Feature*>(self->getObject())
1029
->Placement.getValue()
1031
if (role == Gui::SelectionRole::Inner) {
1032
self->cutMesh(clPoly, proj, true);
1033
commitCommand = true;
1035
else if (role == Gui::SelectionRole::Outer) {
1036
self->cutMesh(clPoly, proj, false);
1037
commitCommand = true;
1039
else if (role == Gui::SelectionRole::Split) {
1043
Gui::TimerFunction* func = new Gui::TimerFunction();
1044
func->setAutoDelete(true);
1045
MeshSplit* split = new MeshSplit(self, clPoly, proj);
1046
func->setFunction([split]() {
1049
func->singleShot(0);
1054
if (commitCommand) {
1055
Gui::Application::Instance->activeDocument()->commitCommand();
1058
Gui::Application::Instance->activeDocument()->abortCommand();
1065
void ViewProviderMesh::trimMeshCallback(void* ud, SoEventCallback* n)
1071
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
1072
view->setEditing(false);
1073
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), trimMeshCallback, ud);
1076
Gui::SelectionRole role {};
1077
std::vector<SbVec2f> clPoly = view->getGLPolygon(&role);
1078
if (clPoly.size() < 3) {
1081
if (clPoly.front() != clPoly.back()) {
1082
clPoly.push_back(clPoly.front());
1085
std::vector<Gui::ViewProvider*> views =
1086
view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1087
if (!views.empty()) {
1088
Gui::Application::Instance->activeDocument()->openCommand(
1089
QT_TRANSLATE_NOOP("Command", "Trim"));
1090
bool commitCommand = false;
1091
for (auto it : views) {
1092
ViewProviderMesh* self = static_cast<ViewProviderMesh*>(it);
1093
if (self->getEditingMode() > -1) {
1094
self->finishEditing();
1095
SoCamera* cam = view->getSoRenderManager()->getCamera();
1096
SbViewVolume vv = cam->getViewVolume();
1097
Gui::ViewVolumeProjection proj(vv);
1098
proj.setTransform(static_cast<Mesh::Feature*>(self->getObject())
1099
->Placement.getValue()
1101
if (role == Gui::SelectionRole::Inner) {
1102
self->trimMesh(clPoly, proj, true);
1103
commitCommand = true;
1105
else if (role == Gui::SelectionRole::Outer) {
1106
self->trimMesh(clPoly, proj, false);
1107
commitCommand = true;
1109
else if (role == Gui::SelectionRole::Split) {
1113
Gui::TimerFunction* func = new Gui::TimerFunction();
1114
func->setAutoDelete(true);
1115
MeshSplit* split = new MeshSplit(self, clPoly, proj);
1116
func->setFunction([split]() {
1119
func->singleShot(0);
1124
if (commitCommand) {
1125
Gui::Application::Instance->activeDocument()->commitCommand();
1128
Gui::Application::Instance->activeDocument()->abortCommand();
1135
void ViewProviderMesh::partMeshCallback(void* ud, SoEventCallback* cb)
1141
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(cb->getUserData());
1142
view->setEditing(false);
1143
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), partMeshCallback, ud);
1146
Gui::SelectionRole role {};
1147
std::vector<SbVec2f> clPoly = view->getGLPolygon(&role);
1148
if (clPoly.size() < 3) {
1151
if (clPoly.front() != clPoly.back()) {
1152
clPoly.push_back(clPoly.front());
1157
view->getNearPlane(b, n);
1158
Base::Vector3f cNormal(n[0], n[1], n[2]);
1159
SoCamera* pCam = view->getSoRenderManager()->getCamera();
1160
SbViewVolume vol = pCam->getViewVolume();
1163
std::vector<MeshCore::MeshGeomFacet> aFaces;
1164
if (!ViewProviderMesh::createToolMesh(clPoly, vol, cNormal, aFaces)) {
1165
Base::Console().Message("The picked polygon seems to have self-overlappings. This could "
1166
"lead to strange results.");
1169
MeshCore::MeshKernel toolMesh;
1170
bool locked = Base::Sequencer().setLocked(true);
1172
Base::Sequencer().setLocked(locked);
1175
Gui::Application::Instance->activeDocument()->openCommand(
1176
QT_TRANSLATE_NOOP("Command", "Split"));
1179
std::vector<Gui::ViewProvider*> views =
1180
view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1181
for (auto view : views) {
1182
ViewProviderMesh* that = static_cast<ViewProviderMesh*>(view);
1183
if (that->getEditingMode() > -1) {
1184
that->finishEditing();
1185
Base::Placement plm =
1186
static_cast<Mesh::Feature*>(that->getObject())->Placement.getValue();
1188
MeshCore::MeshKernel copyToolMesh(toolMesh);
1189
copyToolMesh.Transform(plm.toMatrix());
1190
if (role == Gui::SelectionRole::Inner) {
1191
that->splitMesh(copyToolMesh, cNormal, true);
1194
that->splitMesh(copyToolMesh, cNormal, false);
1204
Gui::Application::Instance->activeDocument()->commitCommand();
1208
void ViewProviderMesh::segmMeshCallback(void* ud, SoEventCallback* cb)
1214
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(cb->getUserData());
1215
view->setEditing(false);
1216
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), segmMeshCallback, ud);
1219
Gui::SelectionRole role {};
1220
std::vector<SbVec2f> clPoly = view->getGLPolygon(&role);
1221
if (clPoly.size() < 3) {
1224
if (clPoly.front() != clPoly.back()) {
1225
clPoly.push_back(clPoly.front());
1230
view->getNearPlane(b, n);
1231
Base::Vector3f cNormal(n[0], n[1], n[2]);
1232
SoCamera* pCam = view->getSoRenderManager()->getCamera();
1233
SbViewVolume vol = pCam->getViewVolume();
1236
std::vector<MeshCore::MeshGeomFacet> aFaces;
1237
if (!ViewProviderMesh::createToolMesh(clPoly, vol, cNormal, aFaces)) {
1238
Base::Console().Message("The picked polygon seems to have self-overlappings. This could "
1239
"lead to strange results.");
1242
MeshCore::MeshKernel toolMesh;
1243
bool locked = Base::Sequencer().setLocked(true);
1245
Base::Sequencer().setLocked(locked);
1248
Gui::Application::Instance->activeDocument()->openCommand(
1249
QT_TRANSLATE_NOOP("Command", "Segment"));
1252
std::vector<Gui::ViewProvider*> views =
1253
view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1254
for (auto view : views) {
1255
ViewProviderMesh* that = static_cast<ViewProviderMesh*>(view);
1256
if (that->getEditingMode() > -1) {
1257
that->finishEditing();
1258
Base::Placement plm =
1259
static_cast<Mesh::Feature*>(that->getObject())->Placement.getValue();
1261
MeshCore::MeshKernel copyToolMesh(toolMesh);
1262
copyToolMesh.Transform(plm.toMatrix());
1263
if (role == Gui::SelectionRole::Inner) {
1264
that->segmentMesh(copyToolMesh, cNormal, true);
1267
that->segmentMesh(copyToolMesh, cNormal, false);
1277
Gui::Application::Instance->activeDocument()->commitCommand();
1281
void ViewProviderMesh::selectGLCallback(void* ud, SoEventCallback* n)
1284
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
1285
view->setEditing(false);
1286
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectGLCallback, ud);
1289
std::vector<SbVec2f> clPoly = view->getGLPolygon();
1290
if (clPoly.size() != 2) {
1293
const SoEvent* ev = n->getEvent();
1295
SbVec2f pos = clPoly[0];
1297
pos.getValue(pX, pY);
1298
const SbVec2s& sz = view->getSoRenderManager()->getViewportRegion().getViewportSizePixels();
1299
float fRatio = view->getSoRenderManager()->getViewportRegion().getViewportAspectRatio();
1300
if (fRatio > 1.0F) {
1301
pX = (pX - 0.5F) / fRatio + 0.5F;
1302
pos.setValue(pX, pY);
1304
else if (fRatio < 1.0F) {
1305
pY = (pY - 0.5F) * fRatio + 0.5F;
1306
pos.setValue(pX, pY);
1309
short x1 = (short)(pX * sz[0] + 0.5F);
1310
short y1 = (short)(pY * sz[1] + 0.5F);
1311
SbVec2s loc = ev->getPosition();
1315
short x = (x1 + x2) / 2;
1316
short y = (y1 + y2) / 2;
1317
short w = (x2 - x1);
1318
short h = (y2 - y1);
1326
std::vector<Gui::ViewProvider*> views;
1327
views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1328
for (auto it : views) {
1329
ViewProviderMesh* that = static_cast<ViewProviderMesh*>(it);
1330
if (that->getEditingMode() > -1) {
1331
that->finishEditing();
1336
view->getSoRenderManager()->getViewportRegion(),
1337
view->getSoRenderManager()->getCamera());
1344
void ViewProviderMesh::getFacetsFromPolygon(const std::vector<SbVec2f>& picked,
1345
const Base::ViewProjMethod& proj,
1347
std::vector<Mesh::FacetIndex>& indices) const
1349
const bool ok = true;
1350
Base::Polygon2d polygon;
1351
for (auto it : picked) {
1352
polygon.Add(Base::Vector2d(it[0], it[1]));
1356
Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
1357
MeshCore::MeshAlgorithm cAlg(meshProp.getValue().getKernel());
1358
cAlg.CheckFacets(&proj, polygon, true, indices);
1362
std::vector<Mesh::FacetIndex> complete(meshProp.getValue().countFacets());
1363
std::generate(complete.begin(), complete.end(), Base::iotaGen<Mesh::FacetIndex>(0));
1364
std::sort(indices.begin(), indices.end());
1365
std::vector<Mesh::FacetIndex> complementary;
1366
std::back_insert_iterator<std::vector<Mesh::FacetIndex>> biit(complementary);
1367
std::set_difference(complete.begin(), complete.end(), indices.begin(), indices.end(), biit);
1368
indices = complementary;
1372
Base::Console().Message("The picked polygon seems to have self-overlappings. This could "
1373
"lead to strange results.");
1377
std::vector<Mesh::FacetIndex> ViewProviderMesh::getFacetsOfRegion(const SbViewportRegion& select,
1378
const SbViewportRegion& region,
1379
SoCamera* camera) const
1381
SoSeparator* root = new SoSeparator();
1383
root->addChild(camera);
1384
root->addChild(this->getCoordNode());
1385
root->addChild(this->getShapeNode());
1386
Gui::SoGLSelectAction gl(region, select);
1390
std::vector<Mesh::FacetIndex> faces;
1391
faces.insert(faces.end(), gl.indices.begin(), gl.indices.end());
1395
void ViewProviderMesh::panCamera(SoCamera* cam,
1397
const SbPlane& panplane,
1398
const SbVec2f& currpos,
1399
const SbVec2f& prevpos)
1404
if (currpos == prevpos) {
1410
SbViewVolume vv = cam->getViewVolume(aspectratio);
1412
vv.projectPointToLine(currpos, line);
1413
SbVec3f current_planept;
1414
panplane.intersect(line, current_planept);
1415
vv.projectPointToLine(prevpos, line);
1416
SbVec3f old_planept;
1417
panplane.intersect(line, old_planept);
1421
cam->position = cam->position.getValue() - (current_planept - old_planept);
1424
void ViewProviderMesh::boxZoom(const SbBox2s& box, const SbViewportRegion& vp, SoCamera* cam)
1426
SbViewVolume vv = cam->getViewVolume(vp.getViewportAspectRatio());
1428
short sizeX {}, sizeY {};
1429
box.getSize(sizeX, sizeY);
1430
SbVec2s size = vp.getViewportSizePixels();
1434
if (sizeX == 0 && sizeY == 0) {
1443
box.getBounds(xmin, ymin, xmax, ymax);
1444
const SbVec2f center((float)((xmin + xmax) / 2) / (float)std::max((int)(size[0] - 1), 1),
1445
(float)(size[1] - (ymin + ymax) / 2)
1446
/ (float)std::max((int)(size[1] - 1), 1));
1448
SbPlane plane = vv.getPlane(cam->focalDistance.getValue());
1449
panCamera(cam, vp.getViewportAspectRatio(), plane, SbVec2f(0.5, 0.5), center);
1452
float scaleX = (float)sizeX / (float)size[0];
1453
float scaleY = (float)sizeY / (float)size[1];
1454
float scale = std::max<float>(scaleX, scaleY);
1455
if (cam->getTypeId() == SoOrthographicCamera::getClassTypeId()) {
1456
float height = static_cast<SoOrthographicCamera*>(cam)->height.getValue() * scale;
1457
static_cast<SoOrthographicCamera*>(cam)->height = height;
1459
else if (cam->getTypeId() == SoPerspectiveCamera::getClassTypeId()) {
1460
float height = static_cast<SoPerspectiveCamera*>(cam)->heightAngle.getValue() / 2.0F;
1461
height = 2.0F * atan(tan(height) * scale);
1462
static_cast<SoPerspectiveCamera*>(cam)->heightAngle = height;
1466
std::vector<Mesh::FacetIndex>
1467
ViewProviderMesh::getVisibleFacetsAfterZoom(const SbBox2s& rect,
1468
const SbViewportRegion& vp,
1469
SoCamera* camera) const
1473
camera = static_cast<SoCamera*>(camera->copy());
1474
boxZoom(rect, vp, camera);
1475
return getVisibleFacets(vp, camera);
1478
void ViewProviderMesh::renderGLCallback(void* ud, SoAction* action)
1480
if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
1481
ViewProviderMesh* mesh = static_cast<ViewProviderMesh*>(ud);
1482
Gui::SoVisibleFaceAction fa;
1483
fa.apply(mesh->getRoot());
1493
Vertex(const MeshCore::MeshKernel& kernel,
1494
const MeshCore::MeshFacetGrid& grid,
1495
const Base::Vector3f& pos)
1500
bool visible(const Base::Vector3f& base) const
1502
MeshCore::MeshAlgorithm meshAlg(kernel);
1503
bool ok = meshAlg.IsVertexVisible(base, pos, grid);
1508
const MeshCore::MeshKernel& kernel;
1509
const MeshCore::MeshFacetGrid& grid;
1515
std::vector<Mesh::FacetIndex> ViewProviderMesh::getVisibleFacets(const SbViewportRegion& vp,
1516
SoCamera* camera) const
1518
const Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
1519
const Mesh::MeshObject& mesh = meshProp.getValue();
1520
uint32_t count = (uint32_t)mesh.countFacets();
1522
SoSeparator* root = new SoSeparator;
1524
root->addChild(camera);
1526
SoLightModel* lm = new SoLightModel();
1527
lm->model = SoLightModel::BASE_COLOR;
1529
SoMaterial* mat = new SoMaterial();
1530
mat->diffuseColor.setNum(count);
1531
SbColor* diffcol = mat->diffuseColor.startEditing();
1532
for (uint32_t i = 0; i < count; i++) {
1534
diffcol[i].setPackedValue(i << 8, t);
1537
mat->diffuseColor.finishEditing();
1539
SoMaterialBinding* bind = new SoMaterialBinding();
1540
bind->value = SoMaterialBinding::PER_FACE;
1542
root->addChild(mat);
1543
root->addChild(bind);
1544
root->addChild(this->getCoordNode());
1545
root->addChild(this->getShapeNode());
1549
Gui::SoQtOffscreenRenderer renderer(vp);
1550
renderer.setBackgroundColor(SbColor4f(0.0F, 0.0F, 0.0F));
1553
renderer.render(root);
1554
renderer.writeToImage(img);
1557
int width = img.width();
1558
int height = img.height();
1560
std::vector<Mesh::FacetIndex> faces;
1561
for (int y = 0; y < height; y++) {
1562
for (int x = 0; x < width; x++) {
1563
QRgb rgb = img.pixel(x, y);
1564
rgb = rgb - (0xff << 24);
1565
if (rgb != 0 && rgb != color) {
1567
faces.push_back((Mesh::FacetIndex)rgb);
1572
std::sort(faces.begin(), faces.end());
1573
faces.erase(std::unique(faces.begin(), faces.end()), faces.end());
1578
void ViewProviderMesh::cutMesh(const std::vector<SbVec2f>& picked,
1579
const Base::ViewProjMethod& proj,
1583
std::vector<Mesh::FacetIndex> indices;
1584
getFacetsFromPolygon(picked, proj, inner, indices);
1585
removeFacets(indices);
1588
void ViewProviderMesh::trimMesh(const std::vector<SbVec2f>& polygon,
1589
const Base::ViewProjMethod& proj,
1592
Mesh::MeshObject* mesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.startEditing();
1594
Base::Polygon2d polygon2d;
1595
for (auto it : polygon) {
1596
polygon2d.Add(Base::Vector2d(it[0], it[1]));
1599
Mesh::MeshObject::CutType type = inner ? Mesh::MeshObject::INNER : Mesh::MeshObject::OUTER;
1600
mesh->trim(polygon2d, proj, type);
1601
static_cast<Mesh::Feature*>(pcObject)->Mesh.finishEditing();
1602
pcObject->purgeTouched();
1605
void ViewProviderMesh::splitMesh(const MeshCore::MeshKernel& toolMesh,
1606
const Base::Vector3f& normal,
1610
Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
1611
const MeshCore::MeshKernel& meshPropKernel = meshProp.getValue().getKernel();
1614
std::vector<Mesh::FacetIndex> indices;
1615
MeshCore::MeshFacetGrid cGrid(meshPropKernel);
1616
MeshCore::MeshAlgorithm cAlg(meshPropKernel);
1617
cAlg.GetFacetsFromToolMesh(toolMesh, normal, cGrid, indices);
1620
std::vector<Mesh::FacetIndex> complete(meshPropKernel.CountFacets());
1621
std::generate(complete.begin(), complete.end(), Base::iotaGen<Mesh::FacetIndex>(0));
1622
std::sort(indices.begin(), indices.end());
1623
std::vector<Mesh::FacetIndex> complementary;
1624
std::back_insert_iterator<std::vector<Mesh::FacetIndex>> biit(complementary);
1625
std::set_difference(complete.begin(), complete.end(), indices.begin(), indices.end(), biit);
1626
indices = complementary;
1630
Mesh::MeshObject* kernel = meshProp.getValue().meshFromSegment(indices);
1631
removeFacets(indices);
1632
Mesh::Feature* splitMesh = static_cast<Mesh::Feature*>(
1633
App::GetApplication().getActiveDocument()->addObject("Mesh::Feature",
1634
pcObject->getNameInDocument()));
1636
splitMesh->Mesh.setValuePtr(kernel);
1637
static_cast<Mesh::Feature*>(pcObject)->purgeTouched();
1640
void ViewProviderMesh::segmentMesh(const MeshCore::MeshKernel& toolMesh,
1641
const Base::Vector3f& normal,
1645
Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
1646
const MeshCore::MeshKernel& meshPropKernel = meshProp.getValue().getKernel();
1649
std::vector<Mesh::FacetIndex> indices;
1650
MeshCore::MeshFacetGrid cGrid(meshPropKernel);
1651
MeshCore::MeshAlgorithm cAlg(meshPropKernel);
1652
cAlg.GetFacetsFromToolMesh(toolMesh, normal, cGrid, indices);
1655
std::vector<Mesh::FacetIndex> complete(meshPropKernel.CountFacets());
1656
std::generate(complete.begin(), complete.end(), Base::iotaGen<Mesh::FacetIndex>(0));
1657
std::sort(indices.begin(), indices.end());
1658
std::vector<Mesh::FacetIndex> complementary;
1659
std::back_insert_iterator<std::vector<Mesh::FacetIndex>> biit(complementary);
1660
std::set_difference(complete.begin(), complete.end(), indices.begin(), indices.end(), biit);
1661
indices = complementary;
1664
Mesh::MeshObject* kernel = meshProp.startEditing();
1665
kernel->addSegment(indices);
1666
meshProp.finishEditing();
1667
static_cast<Mesh::Feature*>(pcObject)->purgeTouched();
1670
void ViewProviderMesh::faceInfoCallback(void* ud, SoEventCallback* n)
1672
const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(n->getEvent());
1673
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
1677
n->getAction()->setHandled();
1678
if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
1682
QAction* cl = menu.addAction(QObject::tr("Leave info mode"));
1683
QAction* id = menu.exec(QCursor::pos());
1685
view->setEditing(false);
1686
view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
1687
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), faceInfoCallback, ud);
1688
std::list<Gui::GLGraphicsItem*> glItems =
1689
view->getGraphicsItemsOfType(Gui::GLFlagWindow::getClassTypeId());
1690
for (auto glItem : glItems) {
1691
view->removeGraphicsItem(glItem);
1696
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
1697
"User parameter:BaseApp/Preferences/View");
1698
hGrp->SetBool("ShowNaviCube", hGrp->GetBool("ShowNaviCube", true));
1701
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1
1702
&& mbe->getState() == SoButtonEvent::DOWN) {
1703
const SoPickedPoint* point = n->getPickedPoint();
1705
Base::Console().Message("No facet picked.\n");
1713
Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());
1714
if (!vp || !vp->isDerivedFrom<ViewProviderMesh>()) {
1722
view->setEnabledNaviCube(false);
1724
ViewProviderMesh* that = static_cast<ViewProviderMesh*>(vp);
1725
const SoDetail* detail = point->getDetail(that->getShapeNode());
1726
if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
1728
const SoFaceDetail* faceDetail = static_cast<const SoFaceDetail*>(detail);
1729
Mesh::FacetIndex uFacet = faceDetail->getFaceIndex();
1730
that->faceInfo(uFacet);
1731
Gui::GLFlagWindow* flags = nullptr;
1732
std::list<Gui::GLGraphicsItem*> glItems =
1733
view->getGraphicsItemsOfType(Gui::GLFlagWindow::getClassTypeId());
1734
if (glItems.empty()) {
1735
flags = new Gui::GLFlagWindow(view);
1736
view->addGraphicsItem(flags);
1739
flags = static_cast<Gui::GLFlagWindow*>(glItems.front());
1743
static_cast<const SoPointDetail*>(faceDetail->getPoint(0))->getCoordinateIndex();
1745
static_cast<const SoPointDetail*>(faceDetail->getPoint(1))->getCoordinateIndex();
1747
static_cast<const SoPointDetail*>(faceDetail->getPoint(2))->getCoordinateIndex();
1748
Gui::Flag* flag = new Gui::Flag;
1749
flag->setText(QObject::tr("Index: %1").arg(uFacet));
1750
QString toolTip = QString::fromLatin1("Facet index: %1\n"
1751
"Points: <%2, %3, %4>")
1756
flag->setToolTip(toolTip);
1757
flag->setOrigin(point->getPoint());
1758
flags->addFlag(flag, Gui::FlagLayout::TopRight);
1763
void ViewProviderMesh::fillHoleCallback(void* ud, SoEventCallback* n)
1765
const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(n->getEvent());
1766
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
1770
n->getAction()->setHandled();
1771
if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
1775
QAction* cl = menu.addAction(QObject::tr("Leave hole-filling mode"));
1776
QAction* id = menu.exec(QCursor::pos());
1778
view->setEditing(false);
1779
view->setSelectionEnabled(true);
1780
view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
1781
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), fillHoleCallback, ud);
1784
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1
1785
&& mbe->getState() == SoButtonEvent::DOWN) {
1786
const SoPickedPoint* point = n->getPickedPoint();
1788
Base::Console().Message("No facet picked.\n");
1796
Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());
1797
if (!vp || !vp->isDerivedFrom<ViewProviderMesh>()) {
1800
ViewProviderMesh* that = static_cast<ViewProviderMesh*>(vp);
1801
const SoDetail* detail = point->getDetail(that->getShapeNode());
1802
if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
1804
Mesh::FacetIndex uFacet = ((SoFaceDetail*)detail)->getFaceIndex();
1805
that->fillHole(uFacet);
1810
void ViewProviderMesh::markPartCallback(void* ud, SoEventCallback* n)
1813
if (n->getEvent()->isOfType(SoMouseButtonEvent::getClassTypeId())) {
1814
const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(n->getEvent());
1815
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
1819
n->getAction()->setHandled();
1820
if (mbe->getButton() == SoMouseButtonEvent::BUTTON2
1821
&& mbe->getState() == SoButtonEvent::UP) {
1825
QAction* cl = menu.addAction(QObject::tr("Leave removal mode"));
1826
QAction* rm = menu.addAction(QObject::tr("Delete selected faces"));
1827
QAction* cf = menu.addAction(QObject::tr("Clear selected faces"));
1828
QAction* id = menu.exec(QCursor::pos());
1830
view->setEditing(false);
1831
view->setSelectionEnabled(true);
1832
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(),
1836
std::vector<ViewProvider*> views =
1837
view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1838
for (auto view : views) {
1839
static_cast<ViewProviderMesh*>(view)->clearSelection();
1842
else if (cf == id) {
1843
std::vector<ViewProvider*> views =
1844
view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1845
for (auto view : views) {
1846
static_cast<ViewProviderMesh*>(view)->clearSelection();
1849
else if (rm == id) {
1850
Gui::Application::Instance->activeDocument()->openCommand(
1851
QT_TRANSLATE_NOOP("Command", "Delete"));
1852
std::vector<ViewProvider*> views =
1853
view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
1854
for (auto view : views) {
1855
static_cast<ViewProviderMesh*>(view)->deleteSelection();
1858
Gui::Application::Instance->activeDocument()->commitCommand();
1861
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1
1862
&& mbe->getState() == SoButtonEvent::DOWN) {
1863
const SoPickedPoint* point = n->getPickedPoint();
1865
Base::Console().Message("No facet picked.\n");
1873
Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());
1874
if (!vp || !vp->isDerivedFrom<ViewProviderMesh>()) {
1877
ViewProviderMesh* that = static_cast<ViewProviderMesh*>(vp);
1878
const SoDetail* detail = point->getDetail(that->getShapeNode());
1879
if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
1881
Mesh::FacetIndex uFacet = static_cast<const SoFaceDetail*>(detail)->getFaceIndex();
1882
that->selectComponent(uFacet);
1888
void ViewProviderMesh::faceInfo(Mesh::FacetIndex uFacet)
1890
Mesh::Feature* fea = static_cast<Mesh::Feature*>(this->getObject());
1891
const MeshCore::MeshKernel& rKernel = fea->Mesh.getValue().getKernel();
1892
const MeshCore::MeshFacetArray& facets = rKernel.GetFacets();
1893
if (uFacet < facets.size()) {
1894
MeshCore::MeshFacet face = facets[uFacet];
1895
MeshCore::MeshGeomFacet tria = rKernel.GetFacet(face);
1896
Base::Console().Message(
1897
"Mesh: %s Facet %lu: Points: <%lu, %lu, %lu>, Neighbours: <%lu, %lu, %lu>\n"
1898
"Triangle: <[%.6f, %.6f, %.6f], [%.6f, %.6f, %.6f], [%.6f, %.6f, %.6f]>\n",
1899
fea->getNameInDocument(),
1904
face._aulNeighbours[0],
1905
face._aulNeighbours[1],
1906
face._aulNeighbours[2],
1907
tria._aclPoints[0].x,
1908
tria._aclPoints[0].y,
1909
tria._aclPoints[0].z,
1910
tria._aclPoints[1].x,
1911
tria._aclPoints[1].y,
1912
tria._aclPoints[1].z,
1913
tria._aclPoints[2].x,
1914
tria._aclPoints[2].y,
1915
tria._aclPoints[2].z);
1919
void ViewProviderMesh::fillHole(Mesh::FacetIndex uFacet)
1922
Base::Reference<ParameterGrp> hGrp =
1923
Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
1924
int level = (int)hGrp->GetInt("FillHoleLevel", 2);
1927
std::list<Mesh::PointIndex> aBorder;
1928
Mesh::Feature* fea = static_cast<Mesh::Feature*>(this->getObject());
1929
const MeshCore::MeshKernel& rKernel = fea->Mesh.getValue().getKernel();
1930
MeshCore::MeshRefPointToFacets cPt2Fac(rKernel);
1931
MeshCore::MeshAlgorithm meshAlg(rKernel);
1932
meshAlg.GetFacetBorder(uFacet, aBorder);
1933
std::vector<Mesh::PointIndex> boundary(aBorder.begin(), aBorder.end());
1934
std::list<std::vector<Mesh::PointIndex>> boundaries;
1935
boundaries.push_back(boundary);
1936
meshAlg.SplitBoundaryLoops(boundaries);
1938
std::vector<MeshCore::MeshFacet> newFacets;
1939
std::vector<Base::Vector3f> newPoints;
1940
unsigned long numberOfOldPoints = rKernel.CountPoints();
1941
for (const auto& it : boundaries) {
1942
if (it.size() < 3 ) {
1946
MeshCore::MeshFacetArray faces;
1947
MeshCore::MeshPointArray points;
1948
MeshCore::QuasiDelaunayTriangulator cTria ;
1949
cTria.SetVerifier(new MeshCore::TriangulationVerifierV2);
1950
if (meshAlg.FillupHole(boundary, cTria, faces, points, level, &cPt2Fac)) {
1951
if (boundary.front() == boundary.back()) {
1952
boundary.pop_back();
1956
unsigned long countBoundaryPoints = boundary.size();
1957
unsigned long countDifference = points.size() - countBoundaryPoints;
1958
if (countDifference > 0) {
1959
MeshCore::MeshPointArray::_TIterator pt = points.begin() + countBoundaryPoints;
1960
for (unsigned long i = 0; i < countDifference; i++, pt++) {
1961
boundary.push_back(numberOfOldPoints++);
1962
newPoints.push_back(*pt);
1965
for (auto& face : faces) {
1966
face._aulPoints[0] = boundary[face._aulPoints[0]];
1967
face._aulPoints[1] = boundary[face._aulPoints[1]];
1968
face._aulPoints[2] = boundary[face._aulPoints[2]];
1969
newFacets.push_back(face);
1974
if (newFacets.empty()) {
1979
Gui::Application::Instance->activeDocument()->openCommand(
1980
QT_TRANSLATE_NOOP("Command", "Fill hole"));
1981
Mesh::MeshObject* kernel = fea->Mesh.startEditing();
1982
kernel->addFacets(newFacets, newPoints, true);
1983
fea->Mesh.finishEditing();
1984
Gui::Application::Instance->activeDocument()->commitCommand();
1987
void ViewProviderMesh::setFacetTransparency(const std::vector<float>& facetTransparency)
1989
if (pcShapeMaterial->diffuseColor.getNum() != int(facetTransparency.size())) {
1990
App::Color c = ShapeColor.getValue();
1991
pcShapeMaterial->diffuseColor.setNum(facetTransparency.size());
1992
SbColor* cols = pcShapeMaterial->diffuseColor.startEditing();
1993
for (std::size_t index = 0; index < facetTransparency.size(); ++index) {
1994
cols[index].setValue(c.r, c.g, c.b);
1996
pcShapeMaterial->diffuseColor.finishEditing();
1999
pcShapeMaterial->transparency.setNum(facetTransparency.size());
2000
float* tran = pcShapeMaterial->transparency.startEditing();
2001
for (std::size_t index = 0; index < facetTransparency.size(); ++index) {
2002
tran[index] = facetTransparency[index];
2005
pcShapeMaterial->transparency.finishEditing();
2006
pcMatBinding->value = SoMaterialBinding::PER_FACE;
2009
void ViewProviderMesh::resetFacetTransparency()
2011
pcMatBinding->value = SoMaterialBinding::OVERALL;
2012
App::Color c = ShapeColor.getValue();
2013
pcShapeMaterial->diffuseColor.setValue(c.r, c.g, c.b);
2014
pcShapeMaterial->transparency.setValue(0);
2018
void ViewProviderMesh::appendFacets(const std::vector<Mesh::FacetIndex>&)
2021
void ViewProviderMesh::removeFacets(const std::vector<Mesh::FacetIndex>& facets)
2024
Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
2025
Mesh::MeshObject* kernel = meshProp.startEditing();
2028
App::PropertyColorList* prop = getColorProperty();
2029
bool ok = Coloring.getValue();
2031
if (prop && prop->getSize() == static_cast<int>(kernel->countPoints())) {
2032
std::vector<Mesh::PointIndex> pointDegree;
2033
unsigned long invalid = kernel->getPointDegree(facets, pointDegree);
2036
Coloring.setValue(false);
2038
const std::vector<App::Color>& colors = prop->getValues();
2039
std::vector<App::Color> valid_colors;
2040
valid_colors.reserve(kernel->countPoints() - invalid);
2041
std::size_t numPoints = pointDegree.size();
2042
for (std::size_t index = 0; index < numPoints; index++) {
2043
if (pointDegree[index] > 0) {
2044
valid_colors.push_back(colors[index]);
2048
prop->setValues(valid_colors);
2051
else if (prop && prop->getSize() == static_cast<int>(kernel->countFacets())) {
2053
Coloring.setValue(false);
2055
std::vector<bool> validFacets(kernel->countFacets(), true);
2056
for (auto it : facets) {
2057
validFacets[it] = false;
2060
const std::vector<App::Color>& colors = prop->getValues();
2061
std::vector<App::Color> valid_colors;
2062
valid_colors.reserve(colors.size());
2063
std::size_t numColors = colors.size();
2064
for (std::size_t index = 0; index < numColors; index++) {
2065
if (validFacets[index]) {
2066
valid_colors.push_back(colors[index]);
2070
prop->setValues(valid_colors);
2074
kernel->deleteFacets(facets);
2075
meshProp.finishEditing();
2076
pcObject->purgeTouched();
2078
Coloring.setValue(ok);
2081
void ViewProviderMesh::selectFacet(Mesh::FacetIndex facet)
2083
std::vector<Mesh::FacetIndex> selection;
2084
selection.push_back(facet);
2086
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2087
rMesh.addFacetsToSelection(selection);
2090
pcMatBinding->value = SoMaterialBinding::PER_FACE;
2091
int uCtFacets = (int)rMesh.countFacets();
2093
if (uCtFacets != pcShapeMaterial->diffuseColor.getNum()) {
2094
highlightSelection();
2097
pcShapeMaterial->diffuseColor.set1Value(facet, 1.0F, 0.0F, 0.0F);
2101
void ViewProviderMesh::deselectFacet(Mesh::FacetIndex facet)
2103
std::vector<Mesh::FacetIndex> selection;
2104
selection.push_back(facet);
2106
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2107
rMesh.removeFacetsFromSelection(selection);
2110
pcMatBinding->value = SoMaterialBinding::PER_FACE;
2111
int uCtFacets = (int)rMesh.countFacets();
2113
if (rMesh.hasSelectedFacets()) {
2114
if (uCtFacets != pcShapeMaterial->diffuseColor.getNum()) {
2115
highlightSelection();
2118
App::Color c = ShapeColor.getValue();
2119
pcShapeMaterial->diffuseColor.set1Value(facet, c.r, c.g, c.b);
2123
unhighlightSelection();
2127
bool ViewProviderMesh::isFacetSelected(Mesh::FacetIndex facet)
2129
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2130
const MeshCore::MeshFacetArray& faces = rMesh.getKernel().GetFacets();
2131
return faces[facet].IsFlag(MeshCore::MeshFacet::SELECTED);
2134
void ViewProviderMesh::selectComponent(Mesh::FacetIndex uFacet)
2136
std::vector<Mesh::FacetIndex> selection;
2137
selection.push_back(uFacet);
2139
MeshCore::MeshTopFacetVisitor clVisitor(selection);
2140
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2141
const MeshCore::MeshKernel& rKernel = rMesh.getKernel();
2142
MeshCore::MeshAlgorithm(rKernel).ResetFacetFlag(MeshCore::MeshFacet::VISIT);
2143
rKernel.VisitNeighbourFacets(clVisitor, uFacet);
2144
rMesh.addFacetsToSelection(selection);
2147
highlightSelection();
2150
void ViewProviderMesh::deselectComponent(Mesh::FacetIndex uFacet)
2152
std::vector<Mesh::FacetIndex> selection;
2153
selection.push_back(uFacet);
2155
MeshCore::MeshTopFacetVisitor clVisitor(selection);
2156
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2157
const MeshCore::MeshKernel& rKernel = rMesh.getKernel();
2158
MeshCore::MeshAlgorithm(rKernel).ResetFacetFlag(MeshCore::MeshFacet::VISIT);
2159
rKernel.VisitNeighbourFacets(clVisitor, uFacet);
2160
rMesh.removeFacetsFromSelection(selection);
2163
if (rMesh.hasSelectedFacets()) {
2164
highlightSelection();
2167
unhighlightSelection();
2171
void ViewProviderMesh::setSelection(const std::vector<Mesh::FacetIndex>& indices)
2173
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2174
rMesh.clearFacetSelection();
2175
rMesh.addFacetsToSelection(indices);
2178
if (indices.empty()) {
2179
unhighlightSelection();
2182
highlightSelection();
2186
void ViewProviderMesh::addSelection(const std::vector<Mesh::FacetIndex>& indices)
2188
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2189
rMesh.addFacetsToSelection(indices);
2192
highlightSelection();
2195
void ViewProviderMesh::removeSelection(const std::vector<Mesh::FacetIndex>& indices)
2197
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2198
rMesh.removeFacetsFromSelection(indices);
2201
if (rMesh.hasSelectedFacets()) {
2202
highlightSelection();
2205
unhighlightSelection();
2209
void ViewProviderMesh::invertSelection()
2211
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2212
const MeshCore::MeshFacetArray& faces = rMesh.getKernel().GetFacets();
2213
MeshCore::MeshIsNotFlag<MeshCore::MeshFacet> flag;
2214
unsigned long num_notsel =
2215
std::count_if(faces.begin(), faces.end(), [flag](const MeshCore::MeshFacet& f) {
2216
return flag(f, MeshCore::MeshFacet::SELECTED);
2218
std::vector<Mesh::FacetIndex> notselect;
2219
notselect.reserve(num_notsel);
2220
MeshCore::MeshFacetArray::_TConstIterator beg = faces.begin();
2221
MeshCore::MeshFacetArray::_TConstIterator end = faces.end();
2222
for (MeshCore::MeshFacetArray::_TConstIterator jt = beg; jt != end; ++jt) {
2223
if (!jt->IsFlag(MeshCore::MeshFacet::SELECTED)) {
2224
notselect.push_back(jt - beg);
2227
setSelection(notselect);
2230
void ViewProviderMesh::clearSelection()
2232
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2233
rMesh.clearFacetSelection();
2234
unhighlightSelection();
2237
void ViewProviderMesh::deleteSelection()
2239
std::vector<Mesh::FacetIndex> indices;
2240
Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
2241
const Mesh::MeshObject& rMesh = meshProp.getValue();
2242
rMesh.getFacetsFromSelection(indices);
2243
if (!indices.empty()) {
2244
rMesh.clearFacetSelection();
2245
unhighlightSelection();
2246
removeFacets(indices);
2250
bool ViewProviderMesh::hasSelection() const
2252
Mesh::PropertyMeshKernel& meshProp = static_cast<Mesh::Feature*>(pcObject)->Mesh;
2253
const Mesh::MeshObject& rMesh = meshProp.getValue();
2254
return rMesh.hasSelectedFacets();
2257
void ViewProviderMesh::selectArea(short x,
2261
const SbViewportRegion& region,
2264
SbViewportRegion vp;
2265
vp.setViewportPixels(x, y, w, h);
2266
std::vector<Mesh::FacetIndex> faces = getFacetsOfRegion(vp, region, camera);
2268
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2269
rMesh.addFacetsToSelection(faces);
2272
highlightSelection();
2275
void ViewProviderMesh::highlightSelection()
2277
std::vector<Mesh::FacetIndex> selection;
2278
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2279
rMesh.getFacetsFromSelection(selection);
2280
if (selection.empty()) {
2287
pcMatBinding->value = SoMaterialBinding::PER_FACE;
2288
App::Color c = ShapeColor.getValue();
2289
int uCtFacets = (int)rMesh.countFacets();
2290
pcShapeMaterial->diffuseColor.setNum(uCtFacets);
2292
SbColor* cols = pcShapeMaterial->diffuseColor.startEditing();
2293
for (int i = 0; i < uCtFacets; i++) {
2294
cols[i].setValue(c.r, c.g, c.b);
2296
for (Mesh::FacetIndex it : selection) {
2297
cols[it].setValue(1.0F, 0.0F, 0.0F);
2299
pcShapeMaterial->diffuseColor.finishEditing();
2302
void ViewProviderMesh::unhighlightSelection()
2304
App::Color c = ShapeColor.getValue();
2305
pcMatBinding->value = SoMaterialBinding::OVERALL;
2306
pcShapeMaterial->diffuseColor.setNum(1);
2307
pcShapeMaterial->diffuseColor.setValue(c.r, c.g, c.b);
2310
void ViewProviderMesh::setHighlightedComponents(bool on)
2313
highlightMode = HighlighMode::Component;
2314
highlightComponents();
2317
highlightMode = HighlighMode::None;
2318
unhighlightSelection();
2322
void ViewProviderMesh::highlightComponents()
2324
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2325
std::vector<std::vector<Mesh::FacetIndex>> comps = rMesh.getComponents();
2328
pcMatBinding->value = SoMaterialBinding::PER_FACE;
2329
int uCtFacets = (int)rMesh.countFacets();
2330
pcShapeMaterial->diffuseColor.setNum(uCtFacets);
2332
SbColor* cols = pcShapeMaterial->diffuseColor.startEditing();
2333
for (const auto& comp : comps) {
2334
float fMax = (float)RAND_MAX;
2335
float fRed = (float)rand() / fMax;
2336
float fGrn = (float)rand() / fMax;
2337
float fBlu = (float)rand() / fMax;
2338
for (Mesh::FacetIndex jt : comp) {
2339
cols[jt].setValue(fRed, fGrn, fBlu);
2342
pcShapeMaterial->diffuseColor.finishEditing();
2345
void ViewProviderMesh::setHighlightedSegments(bool on)
2348
highlightMode = HighlighMode::Segment;
2349
highlightSegments();
2352
highlightMode = HighlighMode::None;
2353
unhighlightSelection();
2357
void ViewProviderMesh::highlightSegments()
2359
std::vector<App::Color> colors;
2360
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2361
unsigned long numSegm = rMesh.countSegments();
2362
colors.resize(numSegm, this->ShapeColor.getValue());
2364
for (unsigned long i = 0; i < numSegm; i++) {
2366
if (col.fromHexString(rMesh.getSegment(i).getColor())) {
2371
highlightSegments(colors);
2374
void ViewProviderMesh::highlightSegments(const std::vector<App::Color>& colors)
2376
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2377
unsigned long numSegm = rMesh.countSegments();
2378
if (numSegm > 0 && numSegm == colors.size()) {
2380
pcMatBinding->value = SoMaterialBinding::PER_FACE;
2381
int uCtFacets = (int)rMesh.countFacets();
2383
pcShapeMaterial->diffuseColor.setNum(uCtFacets);
2384
SbColor* cols = pcShapeMaterial->diffuseColor.startEditing();
2385
for (unsigned long i = 0; i < numSegm; i++) {
2386
std::vector<Mesh::FacetIndex> segm = rMesh.getSegment(i).getIndices();
2387
float fRed = colors[i].r;
2388
float fGrn = colors[i].g;
2389
float fBlu = colors[i].b;
2390
for (Mesh::FacetIndex it : segm) {
2391
cols[it].setValue(fRed, fGrn, fBlu);
2394
pcShapeMaterial->diffuseColor.finishEditing();
2396
else if (colors.size() == 1) {
2397
pcMatBinding->value = SoMaterialBinding::OVERALL;
2398
float fRed = colors[0].r;
2399
float fGrn = colors[0].g;
2400
float fBlu = colors[0].b;
2401
pcShapeMaterial->diffuseColor.setValue(fRed, fGrn, fBlu);
2405
void ViewProviderMesh::setHighlightedColors(bool on)
2408
highlightMode = HighlighMode::Color;
2412
highlightMode = HighlighMode::None;
2413
unhighlightSelection();
2417
void ViewProviderMesh::highlightColors()
2419
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2421
App::PropertyColorList* prop = Base::freecad_dynamic_cast<App::PropertyColorList>(
2422
pcObject->getPropertyByName("FaceColors"));
2423
if (prop && prop->getSize() == int(rMesh.countFacets())) {
2424
setColorPerFace(prop);
2428
App::PropertyColorList* prop = Base::freecad_dynamic_cast<App::PropertyColorList>(
2429
pcObject->getPropertyByName("VertexColors"));
2430
if (prop && prop->getSize() == int(rMesh.countPoints())) {
2431
setColorPerVertex(prop);
2436
bool ViewProviderMesh::canHighlightColors() const
2438
const Mesh::MeshObject& rMesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue();
2440
App::PropertyColorList* prop = Base::freecad_dynamic_cast<App::PropertyColorList>(
2441
pcObject->getPropertyByName("FaceColors"));
2442
if (prop && prop->getSize() == int(rMesh.countFacets())) {
2447
App::PropertyColorList* prop = Base::freecad_dynamic_cast<App::PropertyColorList>(
2448
pcObject->getPropertyByName("VertexColors"));
2449
if (prop && prop->getSize() == int(rMesh.countPoints())) {
2457
PyObject* ViewProviderMesh::getPyObject()
2459
if (!pyViewObject) {
2460
pyViewObject = new ViewProviderMeshPy(this);
2462
pyViewObject->IncRef();
2463
return pyViewObject;
2468
PROPERTY_SOURCE(MeshGui::ViewProviderIndexedFaceSet, MeshGui::ViewProviderMesh)
2470
ViewProviderIndexedFaceSet::ViewProviderIndexedFaceSet()
2473
pcMeshCoord = nullptr;
2474
pcMeshFaces = nullptr;
2478
ViewProviderIndexedFaceSet::~ViewProviderIndexedFaceSet() = default;
2484
void ViewProviderIndexedFaceSet::attach(App::DocumentObject* pcFeat)
2486
ViewProviderMesh::attach(pcFeat);
2488
pcMeshCoord = new SoCoordinate3;
2489
pcHighlight->addChild(pcMeshCoord);
2491
pcMeshFaces = new SoFCIndexedFaceSet;
2492
pcHighlight->addChild(pcMeshFaces);
2495
Base::Reference<ParameterGrp> hGrp =
2496
Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
2497
int size = hGrp->GetInt("RenderTriangleLimit", -1);
2499
static_cast<SoFCIndexedFaceSet*>(pcMeshFaces)->renderTriangleLimit =
2500
(unsigned int)(pow(10.0F, size));
2504
void ViewProviderIndexedFaceSet::updateData(const App::Property* prop)
2506
ViewProviderMesh::updateData(prop);
2507
if (prop->is<Mesh::PropertyMeshKernel>()) {
2508
ViewProviderMeshBuilder builder;
2509
builder.createMesh(prop, pcMeshCoord, pcMeshFaces);
2510
showOpenEdges(OpenEdges.getValue());
2511
highlightSelection();
2515
void ViewProviderIndexedFaceSet::showOpenEdges(bool show)
2519
pcRoot->removeChild(pcOpenEdge);
2520
pcOpenEdge = nullptr;
2524
pcOpenEdge = new SoSeparator();
2525
pcOpenEdge->addChild(pcLineStyle);
2526
pcOpenEdge->addChild(pOpenColor);
2528
pcOpenEdge->addChild(pcMeshCoord);
2529
SoIndexedLineSet* lines = new SoIndexedLineSet;
2530
pcOpenEdge->addChild(lines);
2533
pcRoot->addChild(pcOpenEdge);
2537
const MeshCore::MeshKernel& rMesh =
2538
static_cast<Mesh::Feature*>(pcObject)->Mesh.getValue().getKernel();
2539
const MeshCore::MeshFacetArray& rFaces = rMesh.GetFacets();
2540
for (const auto& rFace : rFaces) {
2541
for (int i = 0; i < 3; i++) {
2542
if (rFace._aulNeighbours[i] == MeshCore::FACET_INDEX_MAX) {
2543
lines->coordIndex.set1Value(index++, rFace._aulPoints[i]);
2544
lines->coordIndex.set1Value(index++, rFace._aulPoints[(i + 1) % 3]);
2545
lines->coordIndex.set1Value(index++, SO_END_LINE_INDEX);
2552
SoShape* ViewProviderIndexedFaceSet::getShapeNode() const
2554
return this->pcMeshFaces;
2557
SoNode* ViewProviderIndexedFaceSet::getCoordNode() const
2559
return this->pcMeshCoord;
2564
PROPERTY_SOURCE(MeshGui::ViewProviderMeshObject, MeshGui::ViewProviderMesh)
2566
ViewProviderMeshObject::ViewProviderMeshObject()
2569
pcMeshNode = nullptr;
2570
pcMeshShape = nullptr;
2574
ViewProviderMeshObject::~ViewProviderMeshObject() = default;
2576
void ViewProviderMeshObject::attach(App::DocumentObject* pcFeat)
2578
ViewProviderMesh::attach(pcFeat);
2580
pcMeshNode = new SoFCMeshObjectNode;
2581
pcHighlight->addChild(pcMeshNode);
2583
pcMeshShape = new SoFCMeshObjectShape;
2584
pcHighlight->addChild(pcMeshShape);
2587
Base::Reference<ParameterGrp> hGrp =
2588
Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh");
2589
int size = hGrp->GetInt("RenderTriangleLimit", -1);
2591
pcMeshShape->renderTriangleLimit = (unsigned int)(pow(10.0F, size));
2595
void ViewProviderMeshObject::updateData(const App::Property* prop)
2597
ViewProviderMesh::updateData(prop);
2598
if (prop->is<Mesh::PropertyMeshKernel>()) {
2599
const Mesh::PropertyMeshKernel* mesh = static_cast<const Mesh::PropertyMeshKernel*>(prop);
2600
this->pcMeshNode->mesh.setValue(
2601
Base::Reference<const Mesh::MeshObject>(mesh->getValuePtr()));
2603
this->pcMeshShape->touch();
2607
void ViewProviderMeshObject::showOpenEdges(bool show)
2611
pcRoot->removeChild(pcOpenEdge);
2612
pcOpenEdge = nullptr;
2616
pcOpenEdge = new SoSeparator();
2617
pcOpenEdge->addChild(pcLineStyle);
2618
pcOpenEdge->addChild(pOpenColor);
2620
pcOpenEdge->addChild(pcMeshNode);
2621
pcOpenEdge->addChild(new SoFCMeshObjectBoundary);
2624
pcRoot->addChild(pcOpenEdge);
2628
SoShape* ViewProviderMeshObject::getShapeNode() const
2630
return this->pcMeshShape;
2633
SoNode* ViewProviderMeshObject::getCoordNode() const
2635
return this->pcMeshNode;