1
/***************************************************************************
2
* Copyright (c) 2011 Juergen Riegel <juergen.riegel@web.de> *
4
* This file is part of the FreeCAD CAx development system. *
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. *
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. *
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 *
21
***************************************************************************/
23
#include "PreCompiled.h"
26
# include <Bnd_Box.hxx>
27
# include <BRep_Tool.hxx>
28
# include <BRepBndLib.hxx>
29
# include <BRepBuilderAPI_MakeVertex.hxx>
30
# include <BRepExtrema_DistShapeShape.hxx>
31
# include <BRepMesh_IncrementalMesh.hxx>
32
# include <gp_Trsf.hxx>
33
# include <Precision.hxx>
34
# include <Poly_Array1OfTriangle.hxx>
35
# include <Poly_Polygon3D.hxx>
36
# include <Poly_PolygonOnTriangulation.hxx>
37
# include <Poly_Triangulation.hxx>
38
# include <Standard_Version.hxx>
39
# include <TColgp_Array1OfDir.hxx>
40
# include <TColgp_Array1OfPnt.hxx>
41
# include <TColStd_Array1OfInteger.hxx>
43
# include <TopExp_Explorer.hxx>
45
# include <TopoDS_Edge.hxx>
46
# include <TopoDS_Face.hxx>
47
# include <TopoDS_Shape.hxx>
48
# include <TopoDS_Vertex.hxx>
49
# include <TopTools_IndexedMapOfShape.hxx>
55
# include <Inventor/SoPickedPoint.h>
56
# include <Inventor/details/SoFaceDetail.h>
57
# include <Inventor/details/SoLineDetail.h>
58
# include <Inventor/details/SoPointDetail.h>
59
# include <Inventor/errors/SoDebugError.h>
60
# include <Inventor/nodes/SoCoordinate3.h>
61
# include <Inventor/nodes/SoDrawStyle.h>
62
# include <Inventor/nodes/SoMaterial.h>
63
# include <Inventor/nodes/SoMaterialBinding.h>
64
# include <Inventor/nodes/SoNormal.h>
65
# include <Inventor/nodes/SoNormalBinding.h>
66
# include <Inventor/nodes/SoPolygonOffset.h>
67
# include <Inventor/nodes/SoSeparator.h>
68
# include <Inventor/nodes/SoShapeHints.h>
70
# include <boost/algorithm/string/predicate.hpp>
73
#include <App/Application.h>
74
#include <App/Document.h>
75
#include <Base/Console.h>
76
#include <Base/Parameter.h>
77
#include <Base/TimeInfo.h>
78
#include <Base/Tools.h>
80
#include <Gui/BitmapFactory.h>
81
#include <Gui/Control.h>
82
#include <Gui/SoFCSelectionAction.h>
83
#include <Gui/SoFCUnifiedSelection.h>
84
#include <Gui/ViewParams.h>
85
#include <Mod/Part/App/ShapeMapHasher.h>
86
#include <Mod/Part/App/Tools.h>
88
#include "ViewProviderExt.h"
89
#include "ViewProviderPartExtPy.h"
90
#include "SoBrepEdgeSet.h"
91
#include "SoBrepFaceSet.h"
92
#include "SoBrepPointSet.h"
93
#include "TaskFaceAppearances.h"
96
FC_LOG_LEVEL_INIT("Part", true, true)
98
using namespace PartGui;
100
// Helper functions to consistently convert between float and long
102
float fromPercent(long value)
104
return std::roundf(value) / 100.0F;
107
long toPercent(float value)
109
return std::lround(100.0 * value);
113
PROPERTY_SOURCE(PartGui::ViewProviderPartExt, Gui::ViewProviderGeometryObject)
116
//**************************************************************************
117
// Construction/Destruction
119
App::PropertyFloatConstraint::Constraints ViewProviderPartExt::sizeRange = {1.0,64.0,1.0};
120
App::PropertyFloatConstraint::Constraints ViewProviderPartExt::tessRange = {0.01,100.0,0.01};
121
App::PropertyQuantityConstraint::Constraints ViewProviderPartExt::angDeflectionRange = {1.0,180.0,0.05};
122
const char* ViewProviderPartExt::LightingEnums[]= {"One side","Two side",nullptr};
123
const char* ViewProviderPartExt::DrawStyleEnums[]= {"Solid","Dashed","Dotted","Dashdot",nullptr};
125
ViewProviderPartExt::ViewProviderPartExt()
127
texture.initExtension(this);
129
VisualTouched = true;
130
forceUpdateCount = 0;
131
NormalsFromUV = true;
133
// get default line color
134
unsigned long lcol = Gui::ViewParams::instance()->getDefaultShapeLineColor(); // dark grey (25,25,25)
136
lr = ((lcol >> 24) & 0xff) / 255.0; lg = ((lcol >> 16) & 0xff) / 255.0; lb = ((lcol >> 8) & 0xff) / 255.0;
137
// get default vertex color
138
unsigned long vcol = Gui::ViewParams::instance()->getDefaultShapeVertexColor();
140
vr = ((vcol >> 24) & 0xff) / 255.0; vg = ((vcol >> 16) & 0xff) / 255.0; vb = ((vcol >> 8) & 0xff) / 255.0;
141
int lwidth = Gui::ViewParams::instance()->getDefaultShapeLineWidth();
142
int psize = Gui::ViewParams::instance()->getDefaultShapePointSize();
146
ParameterGrp::handle hPart = App::GetApplication().GetParameterGroupByPath
147
("User parameter:BaseApp/Preferences/Mod/Part");
148
NormalsFromUV = hPart->GetBool("NormalsFromUVNodes", NormalsFromUV);
150
long twoside = hPart->GetBool("TwoSideRendering", true) ? 1 : 0;
152
// Let the user define a custom lower limit but a value less than
153
// OCCT's epsilon is not allowed
154
double lowerLimit = hPart->GetFloat("MinimumDeviation", tessRange.LowerBound);
155
lowerLimit = std::max(lowerLimit, Precision::Confusion());
156
tessRange.LowerBound = lowerLimit;
158
static const char *osgroup = "Object Style";
161
lmat.ambientColor.set(0.2f,0.2f,0.2f);
162
lmat.diffuseColor.set(lr,lg,lb);
163
lmat.specularColor.set(0.0f,0.0f,0.0f);
164
lmat.emissiveColor.set(0.0f,0.0f,0.0f);
165
lmat.shininess = 1.0f;
166
lmat.transparency = 0.0f;
169
vmat.ambientColor.set(0.2f,0.2f,0.2f);
170
vmat.diffuseColor.set(vr,vg,vb);
171
vmat.specularColor.set(0.0f,0.0f,0.0f);
172
vmat.emissiveColor.set(0.0f,0.0f,0.0f);
173
vmat.shininess = 1.0f;
174
vmat.transparency = 0.0f;
176
ADD_PROPERTY_TYPE(LineMaterial,(lmat), osgroup, App::Prop_None, "Object line material.");
177
ADD_PROPERTY_TYPE(PointMaterial,(vmat), osgroup, App::Prop_None, "Object point material.");
178
ADD_PROPERTY_TYPE(LineColor, (lmat.diffuseColor), osgroup, App::Prop_None, "Set object line color.");
179
ADD_PROPERTY_TYPE(PointColor, (vmat.diffuseColor), osgroup, App::Prop_None, "Set object point color");
180
ADD_PROPERTY_TYPE(PointColorArray, (PointColor.getValue()), osgroup, App::Prop_None, "Object point color array.");
181
ADD_PROPERTY_TYPE(LineColorArray,(LineColor.getValue()), osgroup, App::Prop_None, "Object line color array.");
182
ADD_PROPERTY_TYPE(LineWidth,(lwidth), osgroup, App::Prop_None, "Set object line width.");
183
LineWidth.setConstraints(&sizeRange);
184
PointSize.setConstraints(&sizeRange);
185
ADD_PROPERTY_TYPE(PointSize,(psize), osgroup, App::Prop_None, "Set object point size.");
186
ADD_PROPERTY_TYPE(Deviation,(0.5f), osgroup, App::Prop_None,
187
"Sets the accuracy of the polygonal representation of the model\n"
188
"in the 3D view (tessellation). Lower values indicate better quality.\n"
189
"The value is in percent of object's size.");
190
Deviation.setConstraints(&tessRange);
191
ADD_PROPERTY_TYPE(AngularDeflection,(28.5), osgroup, App::Prop_None,
192
"Specify how finely to generate the mesh for rendering on screen or when exporting.\n"
193
"The default value is 28.5 degrees, or 0.5 radians. The smaller the value\n"
194
"the smoother the appearance in the 3D view, and the finer the mesh that will be exported.");
195
AngularDeflection.setConstraints(&angDeflectionRange);
196
ADD_PROPERTY_TYPE(Lighting,(twoside), osgroup, App::Prop_None, "Set object lighting.");
197
Lighting.setEnums(LightingEnums);
198
ADD_PROPERTY_TYPE(DrawStyle,((long int)0), osgroup, App::Prop_None, "Defines the style of the edges in the 3D view.");
199
DrawStyle.setEnums(DrawStyleEnums);
201
coords = new SoCoordinate3();
203
faceset = new SoBrepFaceSet();
207
normb = new SoNormalBinding;
208
normb->value = SoNormalBinding::PER_VERTEX_INDEXED;
210
lineset = new SoBrepEdgeSet();
212
nodeset = new SoBrepPointSet();
215
pcFaceBind = new SoMaterialBinding();
218
pcLineBind = new SoMaterialBinding();
220
pcLineMaterial = new SoMaterial;
221
pcLineMaterial->ref();
222
LineMaterial.touch();
224
pcPointBind = new SoMaterialBinding();
226
pcPointMaterial = new SoMaterial;
227
pcPointMaterial->ref();
228
PointMaterial.touch();
230
pcLineStyle = new SoDrawStyle();
232
pcLineStyle->style = SoDrawStyle::LINES;
233
pcLineStyle->lineWidth = LineWidth.getValue();
235
pcPointStyle = new SoDrawStyle();
237
pcPointStyle->style = SoDrawStyle::POINTS;
238
pcPointStyle->pointSize = PointSize.getValue();
240
pShapeHints = new SoShapeHints;
241
pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
246
sPixmap = "Part_3D_object";
250
ViewProviderPartExt::~ViewProviderPartExt()
254
pcPointBind->unref();
255
pcLineMaterial->unref();
256
pcPointMaterial->unref();
257
pcLineStyle->unref();
258
pcPointStyle->unref();
259
pShapeHints->unref();
268
PyObject* ViewProviderPartExt::getPyObject()
271
pyViewObject = new ViewProviderPartExtPy(this);
273
pyViewObject->IncRef();
277
void ViewProviderPartExt::onChanged(const App::Property* prop)
279
// The lower limit of the deviation has been increased to avoid
281
// https://forum.freecad.org/viewtopic.php?f=3&t=24912&p=195613
282
if (prop == &Deviation) {
283
if(isUpdateForced()||Visibility.getValue())
286
VisualTouched = true;
288
if (prop == &AngularDeflection) {
289
if(isUpdateForced()||Visibility.getValue())
292
VisualTouched = true;
294
if (prop == &LineWidth) {
295
pcLineStyle->lineWidth = LineWidth.getValue();
297
else if (prop == &PointSize) {
298
pcPointStyle->pointSize = PointSize.getValue();
300
else if (prop == &LineColor) {
301
const App::Color& c = LineColor.getValue();
302
pcLineMaterial->diffuseColor.setValue(c.r,c.g,c.b);
303
if (c != LineMaterial.getValue().diffuseColor)
304
LineMaterial.setDiffuseColor(c);
305
LineColorArray.setValue(LineColor.getValue());
307
else if (prop == &PointColor) {
308
const App::Color& c = PointColor.getValue();
309
pcPointMaterial->diffuseColor.setValue(c.r,c.g,c.b);
310
if (c != PointMaterial.getValue().diffuseColor)
311
PointMaterial.setDiffuseColor(c);
312
PointColorArray.setValue(PointColor.getValue());
314
else if (prop == &LineMaterial) {
315
const App::Material& Mat = LineMaterial.getValue();
316
if (LineColor.getValue() != Mat.diffuseColor)
317
LineColor.setValue(Mat.diffuseColor);
318
pcLineMaterial->ambientColor.setValue(Mat.ambientColor.r,Mat.ambientColor.g,Mat.ambientColor.b);
319
pcLineMaterial->diffuseColor.setValue(Mat.diffuseColor.r,Mat.diffuseColor.g,Mat.diffuseColor.b);
320
pcLineMaterial->specularColor.setValue(Mat.specularColor.r,Mat.specularColor.g,Mat.specularColor.b);
321
pcLineMaterial->emissiveColor.setValue(Mat.emissiveColor.r,Mat.emissiveColor.g,Mat.emissiveColor.b);
322
pcLineMaterial->shininess.setValue(Mat.shininess);
323
pcLineMaterial->transparency.setValue(Mat.transparency);
325
else if (prop == &PointMaterial) {
326
const App::Material& Mat = PointMaterial.getValue();
327
if (PointColor.getValue() != Mat.diffuseColor)
328
PointColor.setValue(Mat.diffuseColor);
329
pcPointMaterial->ambientColor.setValue(Mat.ambientColor.r,Mat.ambientColor.g,Mat.ambientColor.b);
330
pcPointMaterial->diffuseColor.setValue(Mat.diffuseColor.r,Mat.diffuseColor.g,Mat.diffuseColor.b);
331
pcPointMaterial->specularColor.setValue(Mat.specularColor.r,Mat.specularColor.g,Mat.specularColor.b);
332
pcPointMaterial->emissiveColor.setValue(Mat.emissiveColor.r,Mat.emissiveColor.g,Mat.emissiveColor.b);
333
pcPointMaterial->shininess.setValue(Mat.shininess);
334
pcPointMaterial->transparency.setValue(Mat.transparency);
336
else if (prop == &PointColorArray) {
337
setHighlightedPoints(PointColorArray.getValues());
339
else if (prop == &LineColorArray) {
340
setHighlightedEdges(LineColorArray.getValues());
342
else if (prop == &_diffuseColor) {
343
// Used to load the old DiffuseColor values asynchronously
344
ShapeAppearance.setDiffuseColors(_diffuseColor.getValues());
345
ShapeAppearance.setTransparency(Transparency.getValue() / 100.0F);
347
else if (prop == &ShapeAppearance) {
348
setHighlightedFaces(ShapeAppearance);
349
ViewProviderGeometryObject::onChanged(prop);
351
else if (prop == &Transparency) {
352
const App::Material& Mat = ShapeAppearance[0];
353
long value = toPercent(Mat.transparency);
354
if (value != Transparency.getValue()) {
355
float trans = fromPercent(Transparency.getValue());
356
ShapeAppearance.setTransparency(trans);
359
else if (prop == &Lighting) {
360
if (Lighting.getValue() == 0)
361
pShapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
363
pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
365
else if (prop == &DrawStyle) {
366
if (DrawStyle.getValue() == 0)
367
pcLineStyle->linePattern = 0xffff;
368
else if (DrawStyle.getValue() == 1)
369
pcLineStyle->linePattern = 0xf00f;
370
else if (DrawStyle.getValue() == 2)
371
pcLineStyle->linePattern = 0x0f0f;
373
pcLineStyle->linePattern = 0xff88;
376
// if the object was invisible and has been changed, recreate the visual
377
if (prop == &Visibility && (isUpdateForced() || Visibility.getValue()) && VisualTouched) {
379
// updateVisual() may not be triggered by any change (e.g.
380
// triggered by an external object through forceUpdate()). And
381
// since ShapeAppearance is not changed here either, do not falsely set
382
// the document modified status
383
Base::ObjectStatusLocker<App::Property::Status,App::Property> guard(
384
App::Property::NoModify, &ShapeAppearance);
385
// The material has to be checked again (#0001736)
386
onChanged(&ShapeAppearance);
390
ViewProviderGeometryObject::onChanged(prop);
393
bool ViewProviderPartExt::allowOverride(const App::DocumentObject &) const {
394
// Many derived view providers still uses static_cast to get object
395
// pointer, so check for exact type here.
396
return is<ViewProviderPartExt>();
399
void ViewProviderPartExt::attach(App::DocumentObject *pcFeat)
401
// call parent attach method
402
ViewProviderGeometryObject::attach(pcFeat);
404
// Workaround for #0000433, i.e. use SoSeparator instead of SoGroup
405
auto* pcNormalRoot = new SoSeparator();
406
auto* pcFlatRoot = new SoSeparator();
407
auto* pcWireframeRoot = new SoSeparator();
408
auto* pcPointsRoot = new SoSeparator();
409
auto* wireframe = new SoSeparator();
411
// Must turn off all intermediate render caching, and let pcRoot to handle
412
// cache without interference.
413
pcNormalRoot->renderCaching =
414
pcFlatRoot->renderCaching =
415
pcWireframeRoot->renderCaching =
416
pcPointsRoot->renderCaching =
417
wireframe->renderCaching = SoSeparator::OFF;
419
pcNormalRoot->boundingBoxCaching =
420
pcFlatRoot->boundingBoxCaching =
421
pcWireframeRoot->boundingBoxCaching =
422
pcPointsRoot->boundingBoxCaching =
423
wireframe->boundingBoxCaching = SoSeparator::OFF;
425
// Avoid any Z-buffer artifacts, so that the lines always appear on top of the faces
426
// The correct order is Edges, Polygon offset, Faces.
427
SoPolygonOffset* offset = new SoPolygonOffset();
430
wireframe->setName("Edge");
431
wireframe->addChild(pcLineBind);
432
wireframe->addChild(pcLineMaterial);
433
wireframe->addChild(pcLineStyle);
434
wireframe->addChild(lineset);
436
// normal viewing with edges and points
437
pcNormalRoot->addChild(pcPointsRoot);
438
pcNormalRoot->addChild(wireframe);
439
pcNormalRoot->addChild(offset);
440
pcNormalRoot->addChild(pcFlatRoot);
442
// just faces with no edges or points
443
pcFlatRoot->addChild(pShapeHints);
444
pcFlatRoot->addChild(pcFaceBind);
445
pcFlatRoot->addChild(texture.getAppearance());
446
texture.setup(pcShapeMaterial);
447
SoDrawStyle* pcFaceStyle = new SoDrawStyle();
448
pcFaceStyle->style = SoDrawStyle::FILLED;
449
pcFlatRoot->addChild(pcFaceStyle);
450
pcFlatRoot->addChild(norm);
451
pcFlatRoot->addChild(normb);
452
pcFlatRoot->addChild(faceset);
455
pcWireframeRoot->addChild(wireframe);
456
pcWireframeRoot->addChild(pcPointsRoot);
458
// normal viewing with edges and points
459
pcPointsRoot->addChild(pcPointBind);
460
pcPointsRoot->addChild(pcPointMaterial);
461
pcPointsRoot->addChild(pcPointStyle);
462
pcPointsRoot->addChild(nodeset);
464
// Move 'coords' before the switch
465
pcRoot->insertChild(coords,pcRoot->findChild(pcModeSwitch));
467
// putting all together with the switch
468
addDisplayMaskMode(pcNormalRoot, "Flat Lines");
469
addDisplayMaskMode(pcFlatRoot, "Shaded");
470
addDisplayMaskMode(pcWireframeRoot, "Wireframe");
471
addDisplayMaskMode(pcPointsRoot, "Point");
474
void ViewProviderPartExt::setDisplayMode(const char* ModeName)
476
if ( strcmp("Flat Lines",ModeName)==0 )
477
setDisplayMaskMode("Flat Lines");
478
else if ( strcmp("Shaded",ModeName)==0 )
479
setDisplayMaskMode("Shaded");
480
else if ( strcmp("Wireframe",ModeName)==0 )
481
setDisplayMaskMode("Wireframe");
482
else if ( strcmp("Points",ModeName)==0 )
483
setDisplayMaskMode("Point");
485
ViewProviderGeometryObject::setDisplayMode( ModeName );
488
std::vector<std::string> ViewProviderPartExt::getDisplayModes() const
490
// get the modes of the father
491
std::vector<std::string> StrList = ViewProviderGeometryObject::getDisplayModes();
493
// add your own modes
494
StrList.emplace_back("Flat Lines");
495
StrList.emplace_back("Shaded");
496
StrList.emplace_back("Wireframe");
497
StrList.emplace_back("Points");
502
std::string ViewProviderPartExt::getElement(const SoDetail* detail) const
504
std::stringstream str;
506
if (detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
507
const SoFaceDetail* face_detail = static_cast<const SoFaceDetail*>(detail);
508
int face = face_detail->getPartIndex() + 1;
509
str << "Face" << face;
511
else if (detail->getTypeId() == SoLineDetail::getClassTypeId()) {
512
const SoLineDetail* line_detail = static_cast<const SoLineDetail*>(detail);
513
int edge = line_detail->getLineIndex() + 1;
514
str << "Edge" << edge;
516
else if (detail->getTypeId() == SoPointDetail::getClassTypeId()) {
517
const SoPointDetail* point_detail = static_cast<const SoPointDetail*>(detail);
518
int vertex = point_detail->getCoordinateIndex() - nodeset->startIndex.getValue() + 1;
519
str << "Vertex" << vertex;
526
SoDetail* ViewProviderPartExt::getDetail(const char* subelement) const
528
auto type = Part::TopoShape::getElementTypeAndIndex(subelement);
529
std::string element = type.first;
530
int index = type.second;
532
if (element == "Face") {
533
SoFaceDetail* detail = new SoFaceDetail();
534
detail->setPartIndex(index - 1);
537
else if (element == "Edge") {
538
SoLineDetail* detail = new SoLineDetail();
539
detail->setLineIndex(index - 1);
542
else if (element == "Vertex") {
543
SoPointDetail* detail = new SoPointDetail();
544
static_cast<SoPointDetail*>(detail)->setCoordinateIndex(index + nodeset->startIndex.getValue() - 1);
551
std::vector<Base::Vector3d> ViewProviderPartExt::getModelPoints(const SoPickedPoint* pp) const
554
std::vector<Base::Vector3d> pts;
555
std::string element = this->getElement(pp->getDetail());
556
const auto &shape = Part::Feature::getTopoShape(getObject());
558
TopoDS_Shape subShape = shape.getSubShape(element.c_str());
560
// get the point of the vertex directly
561
if (subShape.ShapeType() == TopAbs_VERTEX) {
562
const TopoDS_Vertex& v = TopoDS::Vertex(subShape);
563
gp_Pnt p = BRep_Tool::Pnt(v);
564
pts.emplace_back(p.X(),p.Y(),p.Z());
566
// get the nearest point on the edge
567
else if (subShape.ShapeType() == TopAbs_EDGE) {
568
const SbVec3f& vec = pp->getPoint();
569
BRepBuilderAPI_MakeVertex mkVert(gp_Pnt(vec[0],vec[1],vec[2]));
570
BRepExtrema_DistShapeShape distSS(subShape, mkVert.Vertex(), 0.1);
571
if (distSS.NbSolution() > 0) {
572
gp_Pnt p = distSS.PointOnShape1(1);
573
pts.emplace_back(p.X(),p.Y(),p.Z());
576
// get the nearest point on the face
577
else if (subShape.ShapeType() == TopAbs_FACE) {
578
const SbVec3f& vec = pp->getPoint();
579
BRepBuilderAPI_MakeVertex mkVert(gp_Pnt(vec[0],vec[1],vec[2]));
580
BRepExtrema_DistShapeShape distSS(subShape, mkVert.Vertex(), 0.1);
581
if (distSS.NbSolution() > 0) {
582
gp_Pnt p = distSS.PointOnShape1(1);
583
pts.emplace_back(p.X(),p.Y(),p.Z());
592
// if something went wrong returns an empty array
596
std::vector<Base::Vector3d> ViewProviderPartExt::getSelectionShape(const char* /*Element*/) const
601
void ViewProviderPartExt::setHighlightedFaces(const std::vector<App::Material>& materials)
603
if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange))
604
getObject()->touch(true);
606
Gui::SoUpdateVBOAction action;
607
action.apply(this->faceset);
609
int size = static_cast<int>(materials.size());
610
if (size > 1 && size == this->faceset->partIndex.getNum()) {
611
pcFaceBind->value = SoMaterialBinding::PER_PART;
612
texture.activateMaterial();
614
pcShapeMaterial->diffuseColor.setNum(size);
615
pcShapeMaterial->ambientColor.setNum(size);
616
pcShapeMaterial->specularColor.setNum(size);
617
pcShapeMaterial->emissiveColor.setNum(size);
618
pcShapeMaterial->shininess.setNum(size);
619
pcShapeMaterial->transparency.setNum(size);
621
SbColor* dc = pcShapeMaterial->diffuseColor.startEditing();
622
SbColor* ac = pcShapeMaterial->ambientColor.startEditing();
623
SbColor* sc = pcShapeMaterial->specularColor.startEditing();
624
SbColor* ec = pcShapeMaterial->emissiveColor.startEditing();
625
float* sh = pcShapeMaterial->shininess.startEditing();
626
float* tr = pcShapeMaterial->transparency.startEditing();
628
for (int i = 0; i < size; i++) {
629
dc[i].setValue(materials[i].diffuseColor.r, materials[i].diffuseColor.g, materials[i].diffuseColor.b);
630
ac[i].setValue(materials[i].ambientColor.r, materials[i].ambientColor.g, materials[i].ambientColor.b);
631
sc[i].setValue(materials[i].specularColor.r, materials[i].specularColor.g, materials[i].specularColor.b);
632
ec[i].setValue(materials[i].emissiveColor.r, materials[i].emissiveColor.g, materials[i].emissiveColor.b);
633
sh[i] = materials[i].shininess;
634
tr[i] = materials[i].transparency;
637
pcShapeMaterial->diffuseColor.finishEditing();
638
pcShapeMaterial->ambientColor.finishEditing();
639
pcShapeMaterial->specularColor.finishEditing();
640
pcShapeMaterial->emissiveColor.finishEditing();
641
pcShapeMaterial->shininess.finishEditing();
642
pcShapeMaterial->transparency.finishEditing();
644
else if (size == 1) {
645
pcFaceBind->value = SoMaterialBinding::OVERALL;
646
setCoinAppearance(materials[0]);
650
void ViewProviderPartExt::setHighlightedFaces(const App::PropertyMaterialList& appearance)
652
setHighlightedFaces(appearance.getValues());
655
std::map<std::string,App::Color> ViewProviderPartExt::getElementColors(const char *element) const {
656
std::map<std::string,App::Color> ret;
658
if(!element || !element[0]) {
659
auto color = ShapeAppearance.getDiffuseColor();
660
color.a = Transparency.getValue()/100.0f;
662
ret["Edge"] = LineColor.getValue();
663
ret["Vertex"] = PointColor.getValue();
667
if(boost::starts_with(element,"Face")) {
668
auto size = ShapeAppearance.getSize();
669
if(element[4]=='*') {
670
auto color = ShapeAppearance.getDiffuseColor();
671
color.a = Transparency.getValue()/100.0f;
672
bool singleColor = true;
673
for(int i=0;i<size;++i) {
674
if (ShapeAppearance.getDiffuseColor(i) != color) {
675
ret[std::string(element, 4) + std::to_string(i + 1)] =
676
ShapeAppearance.getDiffuseColor(i);
678
singleColor = singleColor
679
&& ShapeAppearance.getDiffuseColor(0) == ShapeAppearance.getDiffuseColor(i);
681
if(size && singleColor) {
682
color = ShapeAppearance.getDiffuseColor(0);
683
color.a = Transparency.getValue()/100.0f;
688
int idx = atoi(element+4);
689
if(idx>0 && idx<=size)
690
ret[element] = ShapeAppearance.getDiffuseColor(idx - 1);
692
ret[element] = ShapeAppearance.getDiffuseColor();
694
ret[element].a = Transparency.getValue()/100.0f;
696
} else if (boost::starts_with(element,"Edge")) {
697
auto size = LineColorArray.getSize();
698
if(element[4]=='*') {
699
auto color = LineColor.getValue();
700
bool singleColor = true;
701
for(int i=0;i<size;++i) {
702
if(LineColorArray[i]!=color)
703
ret[std::string(element,4)+std::to_string(i+1)] = LineColorArray[i];
704
singleColor = singleColor && LineColorArray[0]==LineColorArray[i];
706
if(singleColor && size) {
707
color = LineColorArray[0];
712
int idx = atoi(element+4);
713
if(idx>0 && idx<=size)
714
ret[element] = LineColorArray[idx-1];
716
ret[element] = LineColor.getValue();
718
} else if (boost::starts_with(element,"Vertex")) {
719
auto size = PointColorArray.getSize();
720
if(element[5]=='*') {
721
auto color = PointColor.getValue();
722
bool singleColor = true;
723
for(int i=0;i<size;++i) {
724
if(PointColorArray[i]!=color)
725
ret[std::string(element,5)+std::to_string(i+1)] = PointColorArray[i];
726
singleColor = singleColor && PointColorArray[0]==PointColorArray[i];
728
if(singleColor && size) {
729
color = PointColorArray[0];
732
ret["Vertex"] = color;
734
int idx = atoi(element+5);
735
if(idx>0 && idx<=size)
736
ret[element] = PointColorArray[idx-1];
738
ret[element] = PointColor.getValue();
744
void ViewProviderPartExt::unsetHighlightedFaces()
746
ShapeAppearance.touch();
747
Transparency.touch();
750
void ViewProviderPartExt::setHighlightedEdges(const std::vector<App::Color>& colors)
752
if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange))
753
getObject()->touch(true);
754
int size = static_cast<int>(colors.size());
756
// Although indexed lineset is used the material binding must be PER_FACE!
757
pcLineBind->value = SoMaterialBinding::PER_FACE;
758
const int32_t* cindices = this->lineset->coordIndex.getValues(0);
759
int numindices = this->lineset->coordIndex.getNum();
760
pcLineMaterial->diffuseColor.setNum(size);
761
SbColor* ca = pcLineMaterial->diffuseColor.startEditing();
764
for (int i = 0; i < numindices; ++i) {
765
if (cindices[i] < 0) {
766
ca[linecount].setValue(colors[linecount].r, colors[linecount].g, colors[linecount].b);
768
if (linecount >= size)
773
pcLineMaterial->diffuseColor.finishEditing();
775
else if (size == 1) {
776
pcLineBind->value = SoMaterialBinding::OVERALL;
777
pcLineMaterial->diffuseColor.setValue(colors[0].r, colors[0].g, colors[0].b);
781
void ViewProviderPartExt::unsetHighlightedEdges()
783
pcLineBind->value = SoMaterialBinding::OVERALL;
784
LineMaterial.touch();
787
void ViewProviderPartExt::setHighlightedPoints(const std::vector<App::Color>& colors)
789
if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange))
790
getObject()->touch(true);
791
int size = static_cast<int>(colors.size());
793
pcPointBind->value = SoMaterialBinding::PER_VERTEX;
794
pcPointMaterial->diffuseColor.setNum(size);
795
SbColor* ca = pcPointMaterial->diffuseColor.startEditing();
796
for (int i = 0; i < size; ++i)
797
ca[i].setValue(colors[i].r, colors[i].g, colors[i].b);
798
pcPointMaterial->diffuseColor.finishEditing();
800
else if (size == 1) {
801
pcPointBind->value = SoMaterialBinding::OVERALL;
802
pcPointMaterial->diffuseColor.setValue(colors[0].r, colors[0].g, colors[0].b);
806
void ViewProviderPartExt::unsetHighlightedPoints()
808
PointColorArray.touch();
811
bool ViewProviderPartExt::loadParameter()
813
bool changed = false;
814
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath
815
("User parameter:BaseApp/Preferences/Mod/Part");
816
float deviation = hGrp->GetFloat("MeshDeviation",0.2);
817
float angularDeflection = hGrp->GetFloat("MeshAngularDeflection",28.65);
818
NormalsFromUV = hGrp->GetBool("NormalsFromUVNodes", NormalsFromUV);
820
if (Deviation.getValue() != deviation) {
821
Deviation.setValue(deviation);
824
if (AngularDeflection.getValue() != angularDeflection ) {
825
AngularDeflection.setValue(angularDeflection);
831
void ViewProviderPartExt::reload()
837
void ViewProviderPartExt::updateData(const App::Property* prop)
839
const char *propName = prop->getName();
840
if (propName && (strcmp(propName, "Shape") == 0 || strstr(propName, "Touched"))) {
841
// calculate the visual only if visible
842
if (isUpdateForced() || Visibility.getValue())
845
VisualTouched = true;
847
if (!VisualTouched) {
848
if (this->faceset->partIndex.getNum() >
849
this->pcShapeMaterial->diffuseColor.getNum()) {
850
this->pcFaceBind->value = SoMaterialBinding::OVERALL;
854
Gui::ViewProviderGeometryObject::updateData(prop);
857
void ViewProviderPartExt::startRestoring()
859
Gui::ViewProviderGeometryObject::startRestoring();
862
void ViewProviderPartExt::finishRestoring()
864
// The ShapeAppearance property is restored after DiffuseColor
865
// and currently sets a single color.
866
// In case DiffuseColor has defined multiple colors they will
867
// be passed to the scene graph now.
868
if (_diffuseColor.getSize() > 1) {
869
onChanged(&_diffuseColor);
871
Gui::ViewProviderGeometryObject::finishRestoring();
874
void ViewProviderPartExt::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
876
QIcon iconObject = mergeGreyableOverlayIcons(Gui::BitmapFactory().pixmap("Part_ColorFace.svg"));
877
Gui::ViewProviderGeometryObject::setupContextMenu(menu, receiver, member);
878
QAction* act = menu->addAction(iconObject, QObject::tr("Set appearance per face..."), receiver, member);
879
act->setData(QVariant((int)ViewProvider::Color));
882
bool ViewProviderPartExt::changeFaceAppearances()
884
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
886
Gui::Control().showDialog(dlg);
890
Gui::Selection().clearSelection();
891
Gui::Control().showDialog(new TaskFaceAppearances(this));
895
bool ViewProviderPartExt::setEdit(int ModNum)
897
if (ModNum == ViewProvider::Color) {
898
// When double-clicking on the item for this pad the
899
// object unsets and sets its edit mode without closing
901
return changeFaceAppearances();
904
return Gui::ViewProviderGeometryObject::setEdit(ModNum);
908
void ViewProviderPartExt::unsetEdit(int ModNum)
910
if (ModNum == ViewProvider::Color) {
914
Gui::ViewProviderGeometryObject::unsetEdit(ModNum);
918
void ViewProviderPartExt::updateVisual()
920
Gui::SoUpdateVBOAction action;
921
action.apply(this->faceset);
924
Gui::SoSelectionElementAction saction(Gui::SoSelectionElementAction::None);
925
saction.apply(this->faceset);
926
saction.apply(this->lineset);
927
saction.apply(this->nodeset);
929
// Clear highlighting
930
Gui::SoHighlightElementAction haction;
931
haction.apply(this->faceset);
932
haction.apply(this->lineset);
933
haction.apply(this->nodeset);
935
TopoDS_Shape cShape = Part::Feature::getShape(getObject());
936
if (cShape.IsNull()) {
937
coords ->point .setNum(0);
938
norm ->vector .setNum(0);
939
faceset ->coordIndex .setNum(0);
940
faceset ->partIndex .setNum(0);
941
lineset ->coordIndex .setNum(0);
942
nodeset ->startIndex .setValue(0);
943
VisualTouched = false;
947
// time measurement and book keeping
948
Base::TimeElapsed start_time;
949
int numTriangles=0,numNodes=0,numNorms=0,numFaces=0,numEdges=0,numLines=0;
950
std::set<int> faceEdges;
953
// calculating the deflection value
955
BRepBndLib::Add(cShape, bounds);
957
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
958
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
959
Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue();
961
// Since OCCT 7.6 a value of equal 0 is not allowed any more, this can happen if a single vertex
962
// should be displayed.
963
if (deflection < gp::Resolution()) {
964
deflection = Precision::Confusion();
967
// For very big objects the computed deflection can become very high and thus leads to a useless
968
// tessellation. To avoid this the upper limit is set to 20.0
969
// See also forum: https://forum.freecad.org/viewtopic.php?t=77521
970
deflection = std::min(deflection, 20.0);
972
// create or use the mesh on the data structure
973
Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI;
975
#if OCC_VERSION_HEX >= 0x070500
976
IMeshTools_Parameters meshParams;
977
meshParams.Deflection = deflection;
978
meshParams.Relative = Standard_False;
979
meshParams.Angle = AngDeflectionRads;
980
meshParams.InParallel = Standard_True;
981
meshParams.AllowQualityDecrease = Standard_True;
983
BRepMesh_IncrementalMesh(cShape, meshParams);
985
BRepMesh_IncrementalMesh(cShape, deflection, Standard_False, AngDeflectionRads, Standard_True);
988
// We must reset the location here because the transformation data
989
// are set in the placement property
990
TopLoc_Location aLoc;
991
cShape.Location(aLoc);
993
// count triangles and nodes in the mesh
994
TopTools_IndexedMapOfShape faceMap;
995
TopExp::MapShapes(cShape, TopAbs_FACE, faceMap);
996
for (int i=1; i <= faceMap.Extent(); i++) {
997
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(faceMap(i)), aLoc);
999
mesh = Part::Tools::triangulationOfFace(TopoDS::Face(faceMap(i)));
1001
// Note: we must also count empty faces
1002
if (!mesh.IsNull()) {
1003
numTriangles += mesh->NbTriangles();
1004
numNodes += mesh->NbNodes();
1005
numNorms += mesh->NbNodes();
1009
for (xp.Init(faceMap(i),TopAbs_EDGE);xp.More();xp.Next()) {
1010
faceEdges.insert(Part::ShapeMapHasher{}(xp.Current()));
1015
// get an indexed map of edges
1016
TopTools_IndexedMapOfShape edgeMap;
1017
TopExp::MapShapes(cShape, TopAbs_EDGE, edgeMap);
1019
// key is the edge number, value the coord indexes. This is needed to keep the same order as the edges.
1020
std::map<int, std::vector<int32_t> > lineSetMap;
1021
std::set<int> edgeIdxSet;
1022
std::vector<int32_t> edgeVector;
1024
// count and index the edges
1025
for (int i=1; i <= edgeMap.Extent(); i++) {
1026
edgeIdxSet.insert(i);
1029
const TopoDS_Edge& aEdge = TopoDS::Edge(edgeMap(i));
1030
TopLoc_Location aLoc;
1032
// handling of the free edge that are not associated to a face
1033
// Note: The assumption that if for an edge BRep_Tool::Polygon3D
1034
// returns a valid object is wrong. This e.g. happens for ruled
1035
// surfaces which gets created by two edges or wires.
1036
// So, we have to store the hashes of the edges associated to a face.
1037
// If the hash of a given edge is not in this list we know it's really
1039
int hash = Part::ShapeMapHasher{}(aEdge);
1040
if (faceEdges.find(hash) == faceEdges.end()) {
1041
Handle(Poly_Polygon3D) aPoly = Part::Tools::polygonOfEdge(aEdge, aLoc);
1042
if (!aPoly.IsNull()) {
1043
int nbNodesInEdge = aPoly->NbNodes();
1044
numNodes += nbNodesInEdge;
1049
// handling of the vertices
1050
TopTools_IndexedMapOfShape vertexMap;
1051
TopExp::MapShapes(cShape, TopAbs_VERTEX, vertexMap);
1052
numNodes += vertexMap.Extent();
1054
// create memory for the nodes and indexes
1055
coords ->point .setNum(numNodes);
1056
norm ->vector .setNum(numNorms);
1057
faceset ->coordIndex .setNum(numTriangles*4);
1058
faceset ->partIndex .setNum(numFaces);
1059
// get the raw memory for fast fill up
1060
SbVec3f* verts = coords ->point .startEditing();
1061
SbVec3f* norms = norm ->vector .startEditing();
1062
int32_t* index = faceset ->coordIndex .startEditing();
1063
int32_t* parts = faceset ->partIndex .startEditing();
1065
// preset the normal vector with null vector
1066
for (int i=0;i < numNorms;i++)
1067
norms[i]= SbVec3f(0.0,0.0,0.0);
1069
int ii = 0,faceNodeOffset=0,faceTriaOffset=0;
1070
for (int i=1; i <= faceMap.Extent(); i++, ii++) {
1071
TopLoc_Location aLoc;
1072
const TopoDS_Face &actFace = TopoDS::Face(faceMap(i));
1073
// get the mesh of the shape
1074
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc);
1075
if (mesh.IsNull()) {
1076
mesh = Part::Tools::triangulationOfFace(actFace);
1078
if (mesh.IsNull()) {
1083
// getting the transformation of the shape/face
1085
Standard_Boolean identity = true;
1086
if (!aLoc.IsIdentity()) {
1088
myTransf = aLoc.Transformation();
1091
// getting size of node and triangle array of this face
1092
int nbNodesInFace = mesh->NbNodes();
1093
int nbTriInFace = mesh->NbTriangles();
1094
// check orientation
1095
TopAbs_Orientation orient = actFace.Orientation();
1098
// cycling through the poly mesh
1099
#if OCC_VERSION_HEX < 0x070600
1100
const Poly_Array1OfTriangle& Triangles = mesh->Triangles();
1101
const TColgp_Array1OfPnt& Nodes = mesh->Nodes();
1102
TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper());
1104
int numNodes = mesh->NbNodes();
1105
TColgp_Array1OfDir Normals (1, numNodes);
1108
Part::Tools::getPointNormals(actFace, mesh, Normals);
1110
for (int g=1;g<=nbTriInFace;g++) {
1112
Standard_Integer N1,N2,N3;
1113
#if OCC_VERSION_HEX < 0x070600
1114
Triangles(g).Get(N1,N2,N3);
1116
mesh->Triangle(g).Get(N1,N2,N3);
1119
// change orientation of the triangle if the face is reversed
1120
if ( orient != TopAbs_FORWARD ) {
1121
Standard_Integer tmp = N1;
1126
// get the 3 points of this triangle
1127
#if OCC_VERSION_HEX < 0x070600
1128
gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3));
1130
gp_Pnt V1(mesh->Node(N1)), V2(mesh->Node(N2)), V3(mesh->Node(N3));
1133
// get the 3 normals of this triangle
1134
gp_Vec NV1, NV2, NV3;
1135
if (NormalsFromUV) {
1136
NV1.SetXYZ(Normals(N1).XYZ());
1137
NV2.SetXYZ(Normals(N2).XYZ());
1138
NV3.SetXYZ(Normals(N3).XYZ());
1141
gp_Vec v1(V1.X(),V1.Y(),V1.Z()),
1142
v2(V2.X(),V2.Y(),V2.Z()),
1143
v3(V3.X(),V3.Y(),V3.Z());
1144
gp_Vec normal = (v2-v1)^(v3-v1);
1150
// transform the vertices and normals to the place of the face
1152
V1.Transform(myTransf);
1153
V2.Transform(myTransf);
1154
V3.Transform(myTransf);
1155
if (NormalsFromUV) {
1156
NV1.Transform(myTransf);
1157
NV2.Transform(myTransf);
1158
NV3.Transform(myTransf);
1162
// add the normals for all points of this triangle
1163
norms[faceNodeOffset+N1-1] += SbVec3f(NV1.X(),NV1.Y(),NV1.Z());
1164
norms[faceNodeOffset+N2-1] += SbVec3f(NV2.X(),NV2.Y(),NV2.Z());
1165
norms[faceNodeOffset+N3-1] += SbVec3f(NV3.X(),NV3.Y(),NV3.Z());
1168
verts[faceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
1169
verts[faceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
1170
verts[faceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));
1172
// set the index vector with the 3 point indexes and the end delimiter
1173
index[faceTriaOffset*4+4*(g-1)] = faceNodeOffset+N1-1;
1174
index[faceTriaOffset*4+4*(g-1)+1] = faceNodeOffset+N2-1;
1175
index[faceTriaOffset*4+4*(g-1)+2] = faceNodeOffset+N3-1;
1176
index[faceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX;
1179
parts[ii] = nbTriInFace; // new part
1181
// handling the edges lying on this face
1182
TopExp_Explorer Exp;
1183
for(Exp.Init(actFace,TopAbs_EDGE);Exp.More();Exp.Next()) {
1184
const TopoDS_Edge &curEdge = TopoDS::Edge(Exp.Current());
1185
// get the overall index of this edge
1186
int edgeIndex = edgeMap.FindIndex(curEdge);
1187
edgeVector.push_back((int32_t)edgeIndex-1);
1188
// already processed this index ?
1189
if (edgeIdxSet.find(edgeIndex)!=edgeIdxSet.end()) {
1191
// this holds the indices of the edge's triangulation to the current polygon
1192
Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(curEdge, mesh, aLoc);
1194
continue; // polygon does not exist
1196
// getting the indexes of the edge polygon
1197
const TColStd_Array1OfInteger& indices = aPoly->Nodes();
1198
for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) {
1199
int nodeIndex = indices(i);
1200
int index = faceNodeOffset+nodeIndex-1;
1201
lineSetMap[edgeIndex].push_back(index);
1203
// usually the coordinates for this edge are already set by the
1204
// triangles of the face this edge belongs to. However, there are
1205
// rare cases where some points are only referenced by the polygon
1206
// but not by any triangle. Thus, we must apply the coordinates to
1207
// make sure that everything is properly set.
1208
#if OCC_VERSION_HEX < 0x070600
1209
gp_Pnt p(Nodes(nodeIndex));
1211
gp_Pnt p(mesh->Node(nodeIndex));
1214
p.Transform(myTransf);
1215
verts[index].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z()));
1218
// remove the handled edge index from the set
1219
edgeIdxSet.erase(edgeIndex);
1223
edgeVector.push_back(-1);
1225
// counting up the per Face offsets
1226
faceNodeOffset += nbNodesInFace;
1227
faceTriaOffset += nbTriInFace;
1230
// handling of the free edges
1231
for (int i=1; i <= edgeMap.Extent(); i++) {
1232
const TopoDS_Edge& aEdge = TopoDS::Edge(edgeMap(i));
1233
Standard_Boolean identity = true;
1235
TopLoc_Location aLoc;
1237
// handling of the free edge that are not associated to a face
1238
int hash = Part::ShapeMapHasher{}(aEdge);
1239
if (faceEdges.find(hash) == faceEdges.end()) {
1240
Handle(Poly_Polygon3D) aPoly = Part::Tools::polygonOfEdge(aEdge, aLoc);
1241
if (!aPoly.IsNull()) {
1242
if (!aLoc.IsIdentity()) {
1244
myTransf = aLoc.Transformation();
1247
const TColgp_Array1OfPnt& aNodes = aPoly->Nodes();
1248
int nbNodesInEdge = aPoly->NbNodes();
1251
for (Standard_Integer j=1;j <= nbNodesInEdge;j++) {
1254
pnt.Transform(myTransf);
1255
int index = faceNodeOffset+j-1;
1256
verts[index].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z()));
1257
lineSetMap[i].push_back(index);
1260
faceNodeOffset += nbNodesInEdge;
1265
nodeset->startIndex.setValue(faceNodeOffset);
1266
for (int i=0; i<vertexMap.Extent(); i++) {
1267
const TopoDS_Vertex& aVertex = TopoDS::Vertex(vertexMap(i+1));
1268
gp_Pnt pnt = BRep_Tool::Pnt(aVertex);
1269
verts[faceNodeOffset+i].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z()));
1272
// normalize all normals
1273
for (int i = 0; i< numNorms ;i++)
1274
norms[i].normalize();
1276
std::vector<int32_t> lineSetCoords;
1277
for (const auto & it : lineSetMap) {
1278
lineSetCoords.insert(lineSetCoords.end(), it.second.begin(), it.second.end());
1279
lineSetCoords.push_back(-1);
1282
// preset the index vector size
1283
numLines = lineSetCoords.size();
1284
lineset ->coordIndex .setNum(numLines);
1285
int32_t* lines = lineset ->coordIndex .startEditing();
1288
for (std::vector<int32_t>::const_iterator it=lineSetCoords.begin();it!=lineSetCoords.end();++it,l++)
1291
// end the editing of the nodes
1292
coords ->point .finishEditing();
1293
norm ->vector .finishEditing();
1294
faceset ->coordIndex .finishEditing();
1295
faceset ->partIndex .finishEditing();
1296
lineset ->coordIndex .finishEditing();
1298
catch (const Standard_Failure& e) {
1299
FC_ERR("Cannot compute Inventor representation for the shape of "
1300
<< pcObject->getFullName() << ": " << e.GetMessageString());
1303
FC_ERR("Cannot compute Inventor representation for the shape of " << pcObject->getFullName());
1307
// printing some information
1308
Base::Console().Log("ViewProvider update time: %f s\n",Base::TimeElapsed::diffTimeF(start_time,Base::TimeElapsed()));
1309
Base::Console().Log("Shape tria info: Faces:%d Edges:%d Nodes:%d Triangles:%d IdxVec:%d\n",numFaces,numEdges,numNodes,numTriangles,numLines);
1313
VisualTouched = false;
1315
// The material has to be checked again
1316
setHighlightedFaces(ShapeAppearance.getValues());
1317
setHighlightedEdges(LineColorArray.getValues());
1318
setHighlightedPoints(PointColorArray.getValue());
1321
void ViewProviderPartExt::forceUpdate(bool enable) {
1323
if(++forceUpdateCount == 1) {
1324
if(!isShow() && VisualTouched)
1327
}else if(forceUpdateCount)
1332
void ViewProviderPartExt::handleChangedPropertyName(Base::XMLReader& reader,
1333
const char* TypeName,
1334
const char* PropName)
1336
if (strcmp(PropName, "DiffuseColor") == 0
1337
&& strcmp(TypeName, App::PropertyColorList::getClassTypeId().getName()) == 0) {
1339
// PropertyColorLists are loaded asynchronously as they're stored in separate files
1340
_diffuseColor.Restore(reader);
1343
Gui::ViewProviderGeometryObject::handleChangedPropertyName(reader, TypeName, PropName);