1
/***************************************************************************
2
* Copyright (c) 2012 Thomas Anderson <blobfish[at]gmx.com> *
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 <QCoreApplication>
27
# include <QHeaderView>
28
# include <QPushButton>
31
# include <QTextStream>
34
# include <Standard_Version.hxx>
35
# include <Bnd_Box.hxx>
36
# include <BOPAlgo_ArgumentAnalyzer.hxx>
37
# include <BOPAlgo_ListOfCheckResult.hxx>
38
# include <BRepBndLib.hxx>
39
# include <BRepBuilderAPI_Copy.hxx>
40
# include <BRepCheck_Analyzer.hxx>
41
# include <BRepCheck_ListIteratorOfListOfStatus.hxx>
42
# include <BRepCheck_Result.hxx>
43
# include <BRepTools_ShapeSet.hxx>
44
# include <ShapeAnalysis_FreeBounds.hxx>
46
# include <TopoDS_Compound.hxx>
47
# include <TopTools_IndexedMapOfShape.hxx>
49
# include <TopExp_Explorer.hxx>
50
# include <Inventor/nodes/SoCube.h>
51
# include <Inventor/nodes/SoDrawStyle.h>
52
# include <Inventor/nodes/SoMaterial.h>
53
# include <Inventor/nodes/SoResetTransform.h>
54
# include <Inventor/nodes/SoSeparator.h>
55
# include <Inventor/nodes/SoSwitch.h>
56
# include <Inventor/nodes/SoTransform.h>
59
#include <Base/Interpreter.h>
60
#include <Gui/Application.h>
61
#include <Gui/BitmapFactory.h>
62
#include <Gui/Document.h>
63
#include <Gui/MainWindow.h>
64
#include <Gui/Selection.h>
65
#include <Gui/ViewProvider.h>
66
#include <Gui/WaitCursor.h>
67
#include <Mod/Part/App/PartFeature.h>
69
#include "TaskCheckGeometry.h"
72
using namespace PartGui;
74
QVector<QString> buildShapeEnumVector()
76
QVector<QString>names;
77
names.push_back(QObject::tr("Compound")); //TopAbs_COMPOUND
78
names.push_back(QObject::tr("Compound Solid")); //TopAbs_COMPSOLID
79
names.push_back(QObject::tr("Solid")); //TopAbs_SOLID
80
names.push_back(QObject::tr("Shell")); //TopAbs_SHELL
81
names.push_back(QObject::tr("Face")); //TopAbs_FACE
82
names.push_back(QObject::tr("Wire")); //TopAbs_WIRE
83
names.push_back(QObject::tr("Edge")); //TopAbs_EDGE
84
names.push_back(QObject::tr("Vertex")); //TopAbs_VERTEX
85
names.push_back(QObject::tr("Shape")); //TopAbs_SHAPE
89
QString shapeEnumToString(const int &index)
91
static QVector<QString> names = buildShapeEnumVector();
92
if (index < 0 || index > TopAbs_SHAPE)
94
return names.at(index);
97
QVector<QString> buildCheckStatusStringVector()
99
QVector<QString>names;
100
names.push_back(QObject::tr("No Error")); // BRepCheck_NoError
101
names.push_back(QObject::tr("Invalid Point On Curve")); // BRepCheck_InvalidPointOnCurve
102
names.push_back(QObject::tr("Invalid Point On Curve On Surface")); // BRepCheck_InvalidPointOnCurveOnSurface
103
names.push_back(QObject::tr("Invalid Point On Surface")); // BRepCheck_InvalidPointOnSurface
104
names.push_back(QObject::tr("No 3D Curve")); // BRepCheck_No3DCurve
105
names.push_back(QObject::tr("Multiple 3D Curve")); // BRepCheck_Multiple3DCurve
106
names.push_back(QObject::tr("Invalid 3D Curve")); // BRepCheck_Invalid3DCurve
107
names.push_back(QObject::tr("No Curve On Surface")); // BRepCheck_NoCurveOnSurface
108
names.push_back(QObject::tr("Invalid Curve On Surface")); // BRepCheck_InvalidCurveOnSurface
109
names.push_back(QObject::tr("Invalid Curve On Closed Surface")); // BRepCheck_InvalidCurveOnClosedSurface
110
names.push_back(QObject::tr("Invalid Same Range Flag")); // BRepCheck_InvalidSameRangeFlag
111
names.push_back(QObject::tr("Invalid Same Parameter Flag")); // BRepCheck_InvalidSameParameterFlag
112
names.push_back(QObject::tr("Invalid Degenerated Flag")); // BRepCheck_InvalidDegeneratedFlag
113
names.push_back(QObject::tr("Free Edge")); // BRepCheck_FreeEdge
114
names.push_back(QObject::tr("Invalid MultiConnexity")); // BRepCheck_InvalidMultiConnexity
115
names.push_back(QObject::tr("Invalid Range")); // BRepCheck_InvalidRange
116
names.push_back(QObject::tr("Empty Wire")); // BRepCheck_EmptyWire
117
names.push_back(QObject::tr("Redundant Edge")); // BRepCheck_RedundantEdge
118
names.push_back(QObject::tr("Self Intersecting Wire")); // BRepCheck_SelfIntersectingWire
119
names.push_back(QObject::tr("No Surface")); // BRepCheck_NoSurface
120
names.push_back(QObject::tr("Invalid Wire")); // BRepCheck_InvalidWire
121
names.push_back(QObject::tr("Redundant Wire")); // BRepCheck_RedundantWire
122
names.push_back(QObject::tr("Intersecting Wires")); // BRepCheck_IntersectingWires
123
names.push_back(QObject::tr("Invalid Imbrication Of Wires")); // BRepCheck_InvalidImbricationOfWires
124
names.push_back(QObject::tr("Empty Shell")); // BRepCheck_EmptyShell
125
names.push_back(QObject::tr("Redundant Face")); // BRepCheck_RedundantFace
126
names.push_back(QObject::tr("Unorientable Shape")); // BRepCheck_UnorientableShape
127
names.push_back(QObject::tr("Not Closed")); // BRepCheck_NotClosed
128
names.push_back(QObject::tr("Not Connected")); // BRepCheck_NotConnected
129
names.push_back(QObject::tr("Sub Shape Not In Shape")); // BRepCheck_SubshapeNotInShape
130
names.push_back(QObject::tr("Bad Orientation")); // BRepCheck_BadOrientation
131
names.push_back(QObject::tr("Bad Orientation Of Sub Shape")); // BRepCheck_BadOrientationOfSubshape
132
names.push_back(QObject::tr("Invalid Tolerance Value")); // BRepCheck_InvalidToleranceValue
133
names.push_back(QObject::tr("Check Failed")); // BRepCheck_CheckFail
138
QString checkStatusToString(const int &index)
140
static QVector<QString> names = buildCheckStatusStringVector();
143
return QString(QObject::tr("No Result"));
145
if (index > 33 || index < 0)
147
QString message(QObject::tr("Out Of Enum Range:") + QStringLiteral(" "));
149
number.setNum(index);
153
return names.at(index);
156
QVector<QString> buildBOPCheckResultVector()
158
QVector<QString> results;
159
results.push_back(QObject::tr("Boolean operation: Unknown check")); //BOPAlgo_CheckUnknown
160
results.push_back(QObject::tr("Boolean operation: Bad type")); //BOPAlgo_BadType
161
results.push_back(QObject::tr("Boolean operation: Self-intersection found")); //BOPAlgo_SelfIntersect
162
results.push_back(QObject::tr("Boolean operation: Edge too small")); //BOPAlgo_TooSmallEdge
163
results.push_back(QObject::tr("Boolean operation: Non-recoverable face")); //BOPAlgo_NonRecoverableFace
164
results.push_back(QObject::tr("Boolean operation: Incompatibility of vertex")); //BOPAlgo_IncompatibilityOfVertex
165
results.push_back(QObject::tr("Boolean operation: Incompatibility of edge")); //BOPAlgo_IncompatibilityOfEdge
166
results.push_back(QObject::tr("Boolean operation: Incompatibility of face")); //BOPAlgo_IncompatibilityOfFace
167
results.push_back(QObject::tr("Boolean operation: Aborted")); //BOPAlgo_OperationAborted
168
results.push_back(QObject::tr("Boolean operation: GeomAbs_C0")); //BOPAlgo_GeomAbs_C0
169
results.push_back(QObject::tr("Boolean operation: Invalid curve on surface")); //BOPAlgo_InvalidCurveOnSurface
170
results.push_back(QObject::tr("Boolean operation: Not valid")); //BOPAlgo_NotValid
175
QString getBOPCheckString(const BOPAlgo_CheckStatus &status)
177
static QVector<QString> strings = buildBOPCheckResultVector();
178
int index = static_cast<int>(status);
179
if (index < 0 || index > strings.size())
181
return strings.at(index);
184
ResultEntry::ResultEntry()
186
viewProviderRoot = nullptr;
191
selectionStrings.clear();
194
ResultEntry::~ResultEntry()
196
if (boxSep && viewProviderRoot)
197
viewProviderRoot->removeChild(boxSep);
198
if (viewProviderRoot)
199
viewProviderRoot->unref();
200
qDeleteAll(children);
203
void ResultEntry::buildEntryName()
205
ResultEntry* parentEntry = this;
206
while (parentEntry->parent) {
207
ResultEntry* temp = parentEntry->parent;
210
parentEntry = parentEntry->parent;
214
QTextStream stream(&stringOut);
215
TopTools_IndexedMapOfShape shapeMap;
218
switch (this->shape.ShapeType())
220
case TopAbs_COMPOUND:
221
TopExp::MapShapes(parentEntry->shape, TopAbs_COMPOUND, shapeMap);
222
stream << "Compound";
224
case TopAbs_COMPSOLID:
225
TopExp::MapShapes(parentEntry->shape, TopAbs_COMPSOLID, shapeMap);
226
stream << "CompSolid";
229
TopExp::MapShapes(parentEntry->shape, TopAbs_SOLID, shapeMap);
233
TopExp::MapShapes(parentEntry->shape, TopAbs_SHELL, shapeMap);
237
TopExp::MapShapes(parentEntry->shape, TopAbs_WIRE, shapeMap);
241
TopExp::MapShapes(parentEntry->shape, TopAbs_FACE, shapeMap);
245
TopExp::MapShapes(parentEntry->shape, TopAbs_EDGE, shapeMap);
249
TopExp::MapShapes(parentEntry->shape, TopAbs_VERTEX, shapeMap);
253
stream << "Unexpected shape type";
257
index = shapeMap.FindIndex(this->shape);
259
this->name = stringOut;
262
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
264
ResultModel::ResultModel(QObject *parent) : QAbstractItemModel(parent)
269
ResultModel::~ResultModel()
275
QModelIndex ResultModel::index(int row, int column, const QModelIndex &parent) const
279
ResultEntry *parentNode = nodeFromIndex(parent);
282
return createIndex(row, column, parentNode->children.at(row));
285
QModelIndex ResultModel::parent(const QModelIndex &child) const
287
ResultEntry *childNode = nodeFromIndex(child);
290
ResultEntry *parentNode = childNode->parent;
293
ResultEntry *grandParentNode = parentNode->parent;
294
if (!grandParentNode)
296
int row = grandParentNode->children.indexOf(parentNode);
297
return createIndex(row, 0, parentNode);
300
int ResultModel::rowCount(const QModelIndex &parent) const
302
ResultEntry *parentNode = nodeFromIndex(parent);
305
return parentNode->children.size();
308
int ResultModel::columnCount(const QModelIndex &parent) const
314
QVariant ResultModel::data(const QModelIndex &index, int role) const
316
if (role != Qt::DisplayRole)
318
ResultEntry *node = nodeFromIndex(index);
321
switch (index.column())
324
return QVariant(node->name);
326
return QVariant(node->type);
328
return QVariant(node->error);
333
QVariant ResultModel::headerData(int section, Qt::Orientation orientation, int role) const
335
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
340
return QVariant(QString(tr("Name")));
342
return QVariant(QString(tr("Type")));
344
return QVariant(QString(tr("Error")));
349
void ResultModel::setResults(ResultEntry *resultsIn)
351
this->beginResetModel();
355
this->endResetModel();
358
ResultEntry* ResultModel::getEntry(const QModelIndex &index)
360
return nodeFromIndex(index);
363
ResultEntry* ResultModel::nodeFromIndex(const QModelIndex &index) const
366
return static_cast<ResultEntry *>(index.internalPointer());
371
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
373
TaskCheckGeometryResults::TaskCheckGeometryResults(QWidget *parent) : QWidget(parent)
375
this->setWindowTitle(tr("Check Geometry Results"));
380
TaskCheckGeometryResults::~TaskCheckGeometryResults()
383
Gui::Selection().clearSelection();
385
catch (const Py::Exception&) {
386
Base::PyException e; // extract the Python error text
391
void TaskCheckGeometryResults::setupInterface()
393
message = new QLabel(this);
394
message->setText(tr("Check is running..."));
395
model = new ResultModel(this);
396
treeView = new QTreeView(this);
397
treeView->setModel(model);
398
treeView->setSelectionMode(QAbstractItemView::SingleSelection);
399
treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
400
connect(treeView->selectionModel(), &QItemSelectionModel::currentRowChanged,
401
this, &TaskCheckGeometryResults::currentRowChanged);
403
QVBoxLayout *layout = new QVBoxLayout();
404
layout->addWidget(message);
405
layout->addWidget(treeView);
406
this->setLayout(layout);
409
void TaskCheckGeometryResults::goCheck()
412
auto selection = Gui::Selection().getSelection();
414
int selectedCount(0), checkedCount(0), invalidShapes(0);
415
ResultEntry *theRoot = new ResultEntry();
417
std::string scopeName {tr("Boolean operation check...").toStdString()};
418
#if OCC_VERSION_HEX < 0x070500
419
Handle(Message_ProgressIndicator) theProgress = new BOPProgressIndicator(tr("Check geometry"),
420
Gui::getMainWindow());
421
theProgress->NewScope(scopeName.c_str());
424
Handle(Message_ProgressIndicator) theProgress = new BOPProgressIndicator(tr("Check geometry"),
425
Gui::getMainWindow());
426
Message_ProgressRange theRange(theProgress->Start());
427
Message_ProgressScope theScope(theRange,
428
TCollection_AsciiString(scopeName.c_str()),
433
for(const auto &sel : selection) {
435
TopoDS_Shape shape = Part::Feature::getShape(sel.pObject,sel.SubName,true);
438
currentSeparator = Gui::Application::Instance->getViewProvider(sel.pObject)->getRoot();
439
if (!currentSeparator)
442
QTextStream baseStream(&baseName);
443
baseStream << sel.DocName;
444
baseStream << "." << sel.FeatName;
448
buildShapeContent(sel.pObject, baseName, shape);
450
BRepCheck_Analyzer shapeCheck(shape);
451
if (!shapeCheck.IsValid())
454
ResultEntry *entry = new ResultEntry();
455
entry->parent = theRoot;
456
entry->shape = shape;
457
entry->name = baseName;
458
entry->type = shapeEnumToString(shape.ShapeType());
459
entry->error = tr("Invalid");
460
entry->viewProviderRoot = currentSeparator;
461
entry->viewProviderRoot->ref();
462
goSetupResultBoundingBox(entry);
463
theRoot->children.push_back(entry);
464
recursiveCheck(shapeCheck, shape, entry);
465
continue; //don't run BOPAlgo_ArgumentAnalyzer if BRepCheck_Analyzer finds something.
469
//BOPAlgo_ArgumentAnalyzer can be really slow!
470
//so only run it when the shape seems valid to BRepCheck_Analyzer And
471
//when the option is set.
473
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
474
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
475
bool runSignal = group->GetBool("RunBOPCheck", false);
476
group->SetBool("RunBOPCheck", runSignal);
478
std::string label = tr("Checking").toStdString() + " ";
479
label += sel.pObject->Label.getStrValue();
481
#if OCC_VERSION_HEX < 0x070500
482
theProgress->NewScope(label.c_str());
483
invalidShapes += goBOPSingleCheck(shape, theRoot, baseName, theProgress);
484
theProgress->EndScope();
485
if (theProgress->UserBreak())
488
Message_ProgressScope theInnerScope(theScope.Next(), TCollection_AsciiString(label.c_str()), 1);
489
theInnerScope.Show();
490
invalidShapes += goBOPSingleCheck(shape, theRoot, baseName, theInnerScope);
491
theInnerScope.Close();
492
if (theScope.UserBreak())
498
model->setResults(theRoot);
499
treeView->expandAll();
500
treeView->header()->resizeSections(QHeaderView::ResizeToContents);
501
QString aMessage {tr("%1 processed out of %2 selected").arg(checkedCount).arg(selectedCount)};
502
aMessage += QLatin1String("\n ") + tr("%n invalid shapes.", "", invalidShapes);
503
message->setText(aMessage);
506
void TaskCheckGeometryResults::recursiveCheck(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape,
509
ResultEntry *branchNode = parent;
510
BRepCheck_ListIteratorOfListOfStatus listIt;
511
if (!shapeCheck.Result(shape).IsNull() && !checkedMap.Contains(shape))
513
listIt.Initialize(shapeCheck.Result(shape)->Status());
514
if (listIt.Value() != BRepCheck_NoError)
516
ResultEntry *entry = new ResultEntry();
517
entry->parent = parent;
518
entry->shape = shape;
519
entry->buildEntryName();
520
entry->type = shapeEnumToString(shape.ShapeType());
521
entry->error = checkStatusToString(listIt.Value());
522
entry->viewProviderRoot = currentSeparator;
523
entry->viewProviderRoot->ref();
524
dispatchError(entry, listIt.Value());
525
parent->children.push_back(entry);
529
checkedMap.Add(shape);
531
if (shape.ShapeType() == TopAbs_SOLID)
532
checkSub(shapeCheck, shape, TopAbs_SHELL, branchNode);
533
if (shape.ShapeType() == TopAbs_EDGE)
534
checkSub(shapeCheck, shape, TopAbs_VERTEX, branchNode);
535
if (shape.ShapeType() == TopAbs_FACE)
537
checkSub(shapeCheck, shape, TopAbs_WIRE, branchNode);
538
checkSub(shapeCheck, shape, TopAbs_EDGE, branchNode);
539
checkSub(shapeCheck, shape, TopAbs_VERTEX, branchNode);
542
for (TopoDS_Iterator it(shape); it.More(); it.Next())
543
recursiveCheck(shapeCheck, it.Value(), branchNode);
546
void TaskCheckGeometryResults::checkSub(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape,
547
const TopAbs_ShapeEnum subType, ResultEntry *parent)
549
BRepCheck_ListIteratorOfListOfStatus itl;
551
for (exp.Init(shape,subType); exp.More(); exp.Next())
553
const Handle(BRepCheck_Result)& res = shapeCheck.Result(exp.Current());
554
const TopoDS_Shape& sub = exp.Current();
555
for (res->InitContextIterator(); res->MoreShapeInContext(); res->NextShapeInContext())
557
if (res->ContextualShape().IsSame(shape))
559
for (itl.Initialize(res->StatusOnShape()); itl.More(); itl.Next())
561
if (itl.Value() == BRepCheck_NoError)
564
ResultEntry *entry = new ResultEntry();
565
entry->parent = parent;
567
entry->buildEntryName();
568
entry->type = shapeEnumToString(sub.ShapeType());
569
entry->error = checkStatusToString(itl.Value());
570
entry->viewProviderRoot = currentSeparator;
571
entry->viewProviderRoot->ref();
572
dispatchError(entry, itl.Value());
573
parent->children.push_back(entry);
580
void TaskCheckGeometryResults::buildShapeContent(App::DocumentObject *pObject, const QString &baseName, const TopoDS_Shape &shape)
583
bool advancedShapeContent = App::GetApplication().GetUserParameter().GetGroup("BaseApp")->GetGroup("Preferences")->
584
GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry")->GetBool("AdvancedShapeContent", true);
585
int decimals = App::GetApplication().GetUserParameter().
586
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Units")->GetInt("Decimals", 2);
587
std::ostringstream stream;
588
if (!shapeContentString.empty())
589
stream << std::endl << std::endl;
590
stream << tr("Checked object").toStdString() << ": ";
591
Base::PyGILStateLocker lock;
593
PyObject* module = PyImport_ImportModule("BasicShapes.ShapeContent");
595
throw Py::Exception();
598
args.setItem(0, Py::asObject(pObject->getPyObject()));
599
args.setItem(1, Py::Long(decimals));
600
args.setItem(2, Py::Boolean(advancedShapeContent));
601
Py::Module shapecontent(module, true);
602
Py::String result(shapecontent.callMemberFunction("buildShapeContent", args));
603
stream << result.as_std_string("utf-8");
605
catch (Py::Exception&) {
608
stream << baseName.toLatin1().data() << std::endl;
609
BRepTools_ShapeSet set;
611
set.DumpExtent(stream);
613
shapeContentString += stream.str();
616
QString TaskCheckGeometryResults::getShapeContentString()
618
return QString::fromStdString(shapeContentString);
621
#if OCC_VERSION_HEX < 0x070500
622
int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, ResultEntry *theRoot, const QString &baseName,
623
const Handle(Message_ProgressIndicator)& theProgress)
625
int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, ResultEntry *theRoot, const QString &baseName,
626
const Message_ProgressScope& theScope)
629
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
630
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
631
bool runSingleThreaded = group->GetBool("RunBOPCheckSingleThreaded", false);
632
bool logErrors = group->GetBool("LogErrors", true);
633
bool argumentTypeMode = group->GetBool("ArgumentTypeMode", true);
634
bool selfInterMode = group->GetBool("SelfInterMode", true);
635
bool smallEdgeMode = group->GetBool("SmallEdgeMode", true);
636
bool rebuildFaceMode = group->GetBool("RebuildFaceMode", true);
637
bool continuityMode = group->GetBool("ContinuityMode", true);
638
bool tangentMode = group->GetBool("TangentMode", true);
639
bool mergeVertexMode = group->GetBool("MergeVertexMode", true);
640
bool mergeEdgeMode = group->GetBool("MergeEdgeMode", true);
641
bool curveOnSurfaceMode = group->GetBool("CurveOnSurfaceMode", true);
643
//Reference use: src/BOPTest/BOPTest_CheckCommands.cxx
645
//I don't why we need to make a copy, but it doesn't work without it.
646
//BRepAlgoAPI_Check also makes a copy of the shape.
648
//didn't use BRepAlgoAPI_Check because it calls BRepCheck_Analyzer itself and
649
//doesn't give us access to it. so I didn't want to run BRepCheck_Analyzer twice to get invalid results.
651
//BOPAlgo_ArgumentAnalyzer can check 2 objects with respect to a boolean op.
652
//this is left for another time.
653
TopoDS_Shape BOPCopy = BRepBuilderAPI_Copy(shapeIn).Shape();
654
BOPAlgo_ArgumentAnalyzer BOPCheck;
656
#if OCC_VERSION_HEX < 0x070500
657
BOPCheck.SetProgressIndicator(theProgress);
658
#elif OCC_VERSION_HEX < 0x070600
659
BOPCheck.SetProgressIndicator(theScope);
665
BOPCheck.SetShape1(BOPCopy);
666
//all settings are false by default. so only turn on what we want.
667
BOPCheck.ArgumentTypeMode() = argumentTypeMode;
668
BOPCheck.SelfInterMode() = selfInterMode;
669
BOPCheck.SmallEdgeMode() = smallEdgeMode;
670
BOPCheck.RebuildFaceMode() = rebuildFaceMode;
671
BOPCheck.ContinuityMode() = continuityMode;
673
BOPCheck.SetParallelMode(!runSingleThreaded); //this doesn't help for speed right now(occt 6.9.1).
674
BOPCheck.SetRunParallel(!runSingleThreaded); //performance boost, use all available cores
675
BOPCheck.TangentMode() = tangentMode; //these 4 new tests add about 5% processing time.
676
BOPCheck.MergeVertexMode() = mergeVertexMode;
677
BOPCheck.MergeEdgeMode() = mergeEdgeMode;
678
BOPCheck.CurveOnSurfaceMode() = curveOnSurfaceMode;
681
Base::TimeElapsed start_time;
687
float bopAlgoTime = Base::TimeElapsed::diffTimeF(start_time, Base::TimeElapsed());
688
std::cout << std::endl << "BopAlgo check time is: " << bopAlgoTime << std::endl << std::endl;
691
if (!BOPCheck.HasFaulty())
694
ResultEntry *entry = new ResultEntry();
695
entry->parent = theRoot;
696
entry->shape = BOPCopy; //this will cause a problem, with existing entry. i.e. entry is true.
697
entry->name = baseName;
698
entry->type = shapeEnumToString(shapeIn.ShapeType());
699
entry->error = QObject::tr("Invalid");
700
entry->viewProviderRoot = currentSeparator;
701
entry->viewProviderRoot->ref();
702
goSetupResultBoundingBox(entry);
703
theRoot->children.push_back(entry);
705
const BOPAlgo_ListOfCheckResult &BOPResults = BOPCheck.GetCheckResult();
706
BOPAlgo_ListIteratorOfListOfCheckResult BOPResultsIt(BOPResults);
707
for (; BOPResultsIt.More(); BOPResultsIt.Next())
709
const BOPAlgo_CheckResult ¤t = BOPResultsIt.Value();
710
const TopTools_ListOfShape &faultyShapes1 = current.GetFaultyShapes1();
711
TopTools_ListIteratorOfListOfShape faultyShapes1It(faultyShapes1);
713
for (;faultyShapes1It.More(); faultyShapes1It.Next())
715
const TopoDS_Shape &faultyShape = faultyShapes1It.Value();
716
ResultEntry *faultyEntry = new ResultEntry();
717
faultyEntry->parent = entry;
718
faultyEntry->shape = faultyShape;
719
faultyEntry->buildEntryName();
720
faultyEntry->type = shapeEnumToString(faultyShape.ShapeType());
721
faultyEntry->error = getBOPCheckString(current.GetCheckStatus());
722
faultyEntry->viewProviderRoot = currentSeparator;
723
entry->viewProviderRoot->ref();
724
goSetupResultBoundingBox(faultyEntry);
726
if (faultyShape.ShapeType() == TopAbs_FACE)
728
goSetupResultTypedSelection(faultyEntry, faultyShape, TopAbs_FACE);
730
else if (faultyShape.ShapeType() == TopAbs_EDGE)
732
goSetupResultTypedSelection(faultyEntry, faultyShape, TopAbs_EDGE);
734
else if (faultyShape.ShapeType() == TopAbs_VERTEX)
736
goSetupResultTypedSelection(faultyEntry, faultyShape, TopAbs_VERTEX);
738
entry->children.push_back(faultyEntry);
740
/*log BOPCheck errors to report view*/
742
std::clog << faultyEntry->parent->name.toStdString().c_str() << " : "
743
<< faultyEntry->name.toStdString().c_str() << " : "
744
<< faultyEntry->type.toStdString().c_str() << " : "
745
<< faultyEntry->error.toStdString().c_str()
754
void TaskCheckGeometryResults::dispatchError(ResultEntry *entry, const BRepCheck_Status &stat)
756
std::vector<FunctionMapType>::iterator mapIt;
757
for (mapIt = functionMap.begin(); mapIt != functionMap.end(); ++mapIt)
759
if (std::get<0>(*mapIt) == entry->shape.ShapeType() && std::get<1>(*mapIt) == stat)
761
(std::get<2>(*mapIt))(entry);
765
goSetupResultBoundingBox(entry);
766
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
767
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
768
bool logErrors = group->GetBool("LogErrors", true); //log errors to report view
770
/*log BRepCheck errors to report view*/
772
std::clog << entry->parent->name.toStdString().c_str() << " : "
773
<< entry->name.toStdString().c_str() << " : "
774
<< entry->type.toStdString().c_str() << " : "
775
<< entry->error.toStdString().c_str() << " (BRepCheck)"
780
void TaskCheckGeometryResults::setupFunctionMap()
782
functionMap.emplace_back(TopAbs_SHELL, BRepCheck_NotClosed, goSetupResultShellNotClosed);
783
functionMap.emplace_back(TopAbs_WIRE, BRepCheck_NotClosed, goSetupResultWireNotClosed);
784
functionMap.emplace_back(TopAbs_VERTEX, BRepCheck_InvalidPointOnCurve, goSetupResultInvalidPointCurve);
785
functionMap.emplace_back(TopAbs_FACE, BRepCheck_IntersectingWires, goSetupResultIntersectingWires);
786
functionMap.emplace_back(TopAbs_EDGE, BRepCheck_InvalidCurveOnSurface, goSetupResultInvalidCurveSurface);
787
functionMap.emplace_back(TopAbs_EDGE, BRepCheck_InvalidSameParameterFlag, goSetupResultInvalidSameParameterFlag);
788
functionMap.emplace_back(TopAbs_FACE, BRepCheck_UnorientableShape, goSetupResultUnorientableShapeFace);
791
void TaskCheckGeometryResults::currentRowChanged (const QModelIndex ¤t, const QModelIndex &previous)
793
Gui::Selection().clearSelection();
794
if (previous.isValid())
796
ResultEntry *entry = model->getEntry(previous);
799
if (entry->boxSwitch)
800
entry->boxSwitch->whichChild.setValue(SO_SWITCH_NONE);
803
if (current.isValid())
805
ResultEntry *entry = model->getEntry(current);
808
if (entry->boxSwitch)
809
entry->boxSwitch->whichChild.setValue(0);
810
QStringList::Iterator stringIt;
811
for (stringIt = entry->selectionStrings.begin(); stringIt != entry->selectionStrings.end(); ++stringIt)
813
//need unique delimiter.
814
QString doc, object, sub;
815
if (!this->split((*stringIt), doc, object, sub))
817
Gui::Selection().addSelection(doc.toLatin1(), object.toLatin1(), sub.toLatin1());
823
bool TaskCheckGeometryResults::split(QString &input, QString &doc, QString &object, QString &sub)
825
QStringList strings = input.split(QString::fromLatin1("."));
826
if (strings.size() != 3)
829
object = strings.at(1);
834
////////////////////////////////////////////////////////////////////////////////////////////////
836
QString PartGui::buildSelectionName(const ResultEntry *entry, const TopoDS_Shape &shape)
838
const ResultEntry *parentEntry = entry;
839
while(parentEntry->parent)
841
ResultEntry *temp = parentEntry->parent;
844
parentEntry = parentEntry->parent;
848
QTextStream stream(&stringOut);
849
stream << parentEntry->name;
851
TopTools_IndexedMapOfShape shapeMap;
854
switch (shape.ShapeType())
857
TopExp::MapShapes(parentEntry->shape, TopAbs_FACE, shapeMap);
861
TopExp::MapShapes(parentEntry->shape, TopAbs_EDGE, shapeMap);
865
TopExp::MapShapes(parentEntry->shape, TopAbs_VERTEX, shapeMap);
869
stream << "Unexpected shape type";
873
index = shapeMap.FindIndex(shape);
878
void PartGui::goSetupResultTypedSelection(ResultEntry* entry, const TopoDS_Shape& shape, TopAbs_ShapeEnum type)
881
for (it.Init(shape, type); it.More(); it.Next())
883
QString name = buildSelectionName(entry, (it.Current()));
885
entry->selectionStrings.append(name);
889
void PartGui::goSetupResultBoundingBox(ResultEntry *entry)
891
//empty compound throws bounding box error. Mantis #0001426
895
BRepBndLib::Add(entry->shape, boundingBox);
896
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
897
boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
898
SbVec3f boundCenter((xmax - xmin)/2 + xmin, (ymax - ymin)/2 + ymin, (zmax - zmin)/2 + zmin);
900
entry->boxSep = new SoSeparator();
901
entry->viewProviderRoot->addChild(entry->boxSep);
902
entry->boxSwitch = new SoSwitch();
903
entry->boxSep->addChild(entry->boxSwitch);
904
SoGroup *group = new SoGroup();
905
entry->boxSwitch->addChild(group);
906
entry->boxSwitch->whichChild.setValue(SO_SWITCH_NONE);
907
SoDrawStyle *dStyle = new SoDrawStyle();
908
dStyle->style.setValue(SoDrawStyle::LINES);
909
dStyle->linePattern.setValue(0xc0c0);
910
group->addChild(dStyle);
911
SoMaterial *material = new SoMaterial();
912
material->diffuseColor.setValue(255.0, 255.0, 255.0);
913
material->ambientColor.setValue(255.0, 255.0, 255.0);
914
group->addChild(material);
916
SoResetTransform *reset = new SoResetTransform();
917
group->addChild(reset);
919
SoTransform *position = new SoTransform();
920
position->translation.setValue(boundCenter);
921
group->addChild(position);
923
SoCube *cube = new SoCube();
924
cube->width.setValue(xmax - xmin);
925
cube->height.setValue(ymax - ymin);
926
cube->depth.setValue(zmax - zmin);
927
group->addChild(cube);
929
catch (const Standard_Failure &){}
932
void PartGui::goSetupResultShellNotClosed(ResultEntry *entry)
934
ShapeAnalysis_FreeBounds shellCheck(entry->shape);
935
TopoDS_Compound closedWires = shellCheck.GetClosedWires();
936
TopoDS_Compound openWires = shellCheck.GetOpenWires();
938
goSetupResultTypedSelection(entry, closedWires, TopAbs_EDGE);
939
goSetupResultTypedSelection(entry, openWires, TopAbs_EDGE);
941
goSetupResultBoundingBox(entry);
944
void PartGui::goSetupResultWireNotClosed(ResultEntry *entry)
946
goSetupResultTypedSelection(entry, entry->shape, TopAbs_EDGE);
947
goSetupResultBoundingBox(entry);
950
void PartGui::goSetupResultInvalidPointCurve(ResultEntry *entry)
952
goSetupResultTypedSelection(entry, entry->shape, TopAbs_VERTEX);
953
goSetupResultBoundingBox(entry);
956
void PartGui::goSetupResultIntersectingWires(ResultEntry *entry)
958
goSetupResultTypedSelection(entry, entry->shape, TopAbs_FACE);
959
goSetupResultBoundingBox(entry);
962
void PartGui::goSetupResultInvalidCurveSurface(ResultEntry *entry)
964
goSetupResultTypedSelection(entry, entry->shape, TopAbs_EDGE);
965
goSetupResultBoundingBox(entry);
968
void PartGui::goSetupResultInvalidSameParameterFlag(ResultEntry *entry)
970
goSetupResultTypedSelection(entry, entry->shape, TopAbs_EDGE);
971
goSetupResultBoundingBox(entry);
974
void PartGui::goSetupResultUnorientableShapeFace(ResultEntry *entry)
976
goSetupResultTypedSelection(entry, entry->shape, TopAbs_FACE);
977
goSetupResultBoundingBox(entry);
980
////////////////////////////////////////////////////////////////////////////////////////////////
982
TaskCheckGeometryDialog::TaskCheckGeometryDialog()
983
: widget(nullptr), contentLabel(nullptr), okBtn(nullptr), settingsBtn(nullptr), resultsBtn(nullptr)
985
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
986
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
987
bool expandShapeContent = group->GetBool("ExpandShapeContent", false);
989
this->setButtonPosition(TaskDialog::South);
990
widget = new TaskCheckGeometryResults();
992
taskbox = new Gui::TaskView::TaskBox(
993
Gui::BitmapFactory().pixmap("Part_CheckGeometry"),
994
widget->windowTitle(), true, nullptr);
995
taskbox->groupLayout()->addWidget(widget);
996
Content.push_back(taskbox);
998
contentLabel = new QTextEdit();
999
contentLabel->setText(widget->getShapeContentString());
1000
shapeContentBox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("Part_CheckGeometry"),
1001
tr("Shape Content"), true, nullptr);
1002
shapeContentBox->groupLayout()->addWidget(contentLabel);
1003
if (!expandShapeContent){
1004
shapeContentBox->hideGroupBox();
1006
Content.push_back(shapeContentBox);
1008
settingsBox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("Part_CheckGeometry"),
1009
tr("Settings"), true, nullptr);
1010
Content.push_back(settingsBox);
1012
autoRunCheckBox = new QCheckBox();
1013
autoRunCheckBox->setText(tr("Skip this settings page"));
1014
autoRunCheckBox->setToolTip(
1015
tr("Skip this settings page and run the geometry check automatically.")
1016
+ QStringLiteral("\n")
1017
+ tr("Default: false"));
1018
autoRunCheckBox->setChecked(group->GetBool("AutoRun", false));
1019
connect(autoRunCheckBox, &QCheckBox::toggled,
1020
this, &TaskCheckGeometryDialog::onAutoRunCheckBoxToggled);
1021
settingsBox->groupLayout()->addWidget(autoRunCheckBox);
1023
runBOPCheckBox = new QCheckBox();
1024
runBOPCheckBox->setText(tr("Run boolean operation check"));
1025
runBOPCheckBox->setToolTip(tr(
1026
"Extra boolean operations check that can sometimes find errors that\n"
1027
"the standard BRep geometry check misses. These errors do not always\n"
1028
"mean the checked object is unusable. Default: false"));
1029
runBOPCheckBox->setChecked(group->GetBool("RunBOPCheck", false));
1030
connect(runBOPCheckBox, &QCheckBox::toggled,
1031
this, &TaskCheckGeometryDialog::onRunBOPCheckBoxToggled);
1032
settingsBox->groupLayout()->addWidget(runBOPCheckBox);
1034
runSingleThreadedCheckBox = new QCheckBox();
1035
runSingleThreadedCheckBox->setText(tr("Single-threaded"));
1036
runSingleThreadedCheckBox->setToolTip(tr(
1037
"Run the geometry check in a single thread. This is slower,\n"
1038
"but more stable. Default: false"));
1039
runSingleThreadedCheckBox->setChecked(group->GetBool("RunSingleThreaded", false));
1040
connect(runSingleThreadedCheckBox, &QCheckBox::toggled,
1041
this, &TaskCheckGeometryDialog::onRunSingleThreadedCheckBoxToggled);
1042
settingsBox->groupLayout()->addWidget(runSingleThreadedCheckBox);
1044
logErrorsCheckBox = new QCheckBox();
1045
logErrorsCheckBox->setText(tr("Log errors"));
1046
logErrorsCheckBox->setToolTip(tr("Log errors to report view. Default: true"));
1047
logErrorsCheckBox->setChecked(group->GetBool("LogErrors", true));
1048
connect(logErrorsCheckBox, &QCheckBox::toggled,
1049
this, &TaskCheckGeometryDialog::onLogErrorsCheckBoxToggled);
1050
settingsBox->groupLayout()->addWidget(logErrorsCheckBox);
1052
expandShapeContentCheckBox = new QCheckBox();
1053
expandShapeContentCheckBox->setText(tr("Expand shape content"));
1054
expandShapeContentCheckBox->setToolTip(tr(
1055
"Expand shape content. Changes will take effect next time you use \n"
1056
"the check geometry tool. Default: false"));
1057
expandShapeContentCheckBox->setChecked(group->GetBool("ExpandShapeContent", false));
1058
connect(expandShapeContentCheckBox, &QCheckBox::toggled,
1059
this, &TaskCheckGeometryDialog::onExpandShapeContentCheckBoxToggled);
1060
settingsBox->groupLayout()->addWidget(expandShapeContentCheckBox);
1062
advancedShapeContentCheckBox = new QCheckBox();
1063
advancedShapeContentCheckBox->setText(tr("Advanced shape content"));
1064
advancedShapeContentCheckBox->setToolTip(tr(
1065
"Show advanced shape content. Changes will take effect next time you use \n"
1066
"the check geometry tool. Default: false"));
1067
advancedShapeContentCheckBox->setChecked(group->GetBool("AdvancedShapeContent", true));
1068
connect(advancedShapeContentCheckBox, &QCheckBox::toggled,
1069
this, &TaskCheckGeometryDialog::onAdvancedShapeContentCheckBoxToggled);
1070
settingsBox->groupLayout()->addWidget(advancedShapeContentCheckBox);
1072
settingsBox->groupLayout()->addWidget(new QLabel(tr("\nIndividual boolean operation checks:")));
1074
argumentTypeModeCheckBox = new QCheckBox();
1075
argumentTypeModeCheckBox->setText(QStringLiteral(" ") + tr("Bad type"));
1076
argumentTypeModeCheckBox->setToolTip(tr("Check for bad argument types. Default: true"));
1077
argumentTypeModeCheckBox->setChecked(group->GetBool("ArgumentTypeMode", true));
1078
connect(argumentTypeModeCheckBox, &QCheckBox::toggled,
1079
this, &TaskCheckGeometryDialog::onArgumentTypeModeCheckBoxToggled);
1080
settingsBox->groupLayout()->addWidget(argumentTypeModeCheckBox);
1082
selfInterModeCheckBox = new QCheckBox();
1083
selfInterModeCheckBox->setText(QStringLiteral(" ") + tr("Self-intersect"));
1084
selfInterModeCheckBox->setToolTip(tr("Check for self-intersections. Default: true"));
1085
selfInterModeCheckBox->setChecked(group->GetBool("SelfInterMode", true));
1086
connect(selfInterModeCheckBox, &QCheckBox::toggled,
1087
this, &TaskCheckGeometryDialog::onSelfInterModeCheckBoxToggled);
1088
settingsBox->groupLayout()->addWidget(selfInterModeCheckBox);
1090
smallEdgeModeCheckBox = new QCheckBox();
1091
smallEdgeModeCheckBox->setText(QStringLiteral(" ") + tr("Too small edge"));
1092
smallEdgeModeCheckBox->setToolTip(tr("Check for edges that are too small. Default: true"));
1093
smallEdgeModeCheckBox->setChecked(group->GetBool("SmallEdgeMode", true));
1094
connect(smallEdgeModeCheckBox, &QCheckBox::toggled,
1095
this, &TaskCheckGeometryDialog::onSmallEdgeModeCheckBoxToggled);
1096
settingsBox->groupLayout()->addWidget(smallEdgeModeCheckBox);
1098
rebuildFaceModeCheckBox = new QCheckBox();
1099
rebuildFaceModeCheckBox->setText(QStringLiteral(" ") + tr("Nonrecoverable face"));
1100
rebuildFaceModeCheckBox->setToolTip(tr("Check for nonrecoverable faces. Default: true"));
1101
rebuildFaceModeCheckBox->setChecked(group->GetBool("RebuildFaceMode", true));
1102
connect(rebuildFaceModeCheckBox, &QCheckBox::toggled,
1103
this, &TaskCheckGeometryDialog::onRebuildFaceModeCheckBoxToggled);
1104
settingsBox->groupLayout()->addWidget(rebuildFaceModeCheckBox);
1106
continuityModeCheckBox = new QCheckBox();
1107
continuityModeCheckBox->setText(QStringLiteral(" ") + tr("Continuity"));
1108
continuityModeCheckBox->setToolTip(tr("Check for continuity. Default: true"));
1109
continuityModeCheckBox->setChecked(group->GetBool("ContinuityMode", true));
1110
connect(continuityModeCheckBox, &QCheckBox::toggled,
1111
this, &TaskCheckGeometryDialog::onContinuityModeCheckBoxToggled);
1112
settingsBox->groupLayout()->addWidget(continuityModeCheckBox);
1114
tangentModeCheckBox = new QCheckBox();
1115
tangentModeCheckBox->setText(QStringLiteral(" ") + tr("Incompatibility of face"));
1116
tangentModeCheckBox->setToolTip(tr("Check for incompatible faces. Default: true"));
1117
tangentModeCheckBox->setChecked(group->GetBool("TangentMode", true));
1118
connect(tangentModeCheckBox, &QCheckBox::toggled,
1119
this, &TaskCheckGeometryDialog::onTangentModeCheckBoxToggled);
1120
settingsBox->groupLayout()->addWidget(tangentModeCheckBox);
1122
mergeVertexModeCheckBox = new QCheckBox();
1123
mergeVertexModeCheckBox->setText(QStringLiteral(" ") + tr("Incompatibility of vertex"));
1124
mergeVertexModeCheckBox->setToolTip(tr("Check for incompatible vertices. Default: true"));
1125
mergeVertexModeCheckBox->setChecked(group->GetBool("MergeVertexMode", true));
1126
connect(mergeVertexModeCheckBox, &QCheckBox::toggled,
1127
this, &TaskCheckGeometryDialog::onMergeVertexModeCheckBoxToggled);
1128
settingsBox->groupLayout()->addWidget(mergeVertexModeCheckBox);
1130
mergeEdgeModeCheckBox = new QCheckBox();
1131
mergeEdgeModeCheckBox->setText(QStringLiteral(" ") + tr("Incompatibility of edge"));
1132
mergeEdgeModeCheckBox->setToolTip(tr("Check for incompatible edges. Default: true"));
1133
mergeEdgeModeCheckBox->setChecked(group->GetBool("MergeEdgeMode", true));
1134
connect(mergeEdgeModeCheckBox, &QCheckBox::toggled,
1135
this, &TaskCheckGeometryDialog::onMergeEdgeModeCheckBoxToggled);
1136
settingsBox->groupLayout()->addWidget(mergeEdgeModeCheckBox);
1138
curveOnSurfaceModeCheckBox = new QCheckBox();
1139
curveOnSurfaceModeCheckBox->setText(QStringLiteral(" ") + tr("Invalid curve on surface"));
1140
curveOnSurfaceModeCheckBox->setToolTip(tr("Check for invalid curves on surfaces. Default: true"));
1141
curveOnSurfaceModeCheckBox->setChecked(group->GetBool("CurveOnSurfaceMode", true));
1142
connect(curveOnSurfaceModeCheckBox, &QCheckBox::toggled,
1143
this, &TaskCheckGeometryDialog::onCurveOnSurfaceModeCheckBoxToggled);
1144
settingsBox->groupLayout()->addWidget(curveOnSurfaceModeCheckBox);
1145
if (group->GetBool("AutoRun",false)){
1146
settingsBox->hide();
1148
contentLabel->setText(widget->getShapeContentString());
1151
shapeContentBox->hide();
1155
bool TaskCheckGeometryDialog::accept()
1157
settingsBtn->setEnabled(true);
1158
settingsBox->hide();
1159
shapeContentBox->show();
1162
QScrollBar *v = contentLabel->verticalScrollBar();
1163
v->setValue(v->maximum()); //scroll to bottom
1164
int curval = v->value(); //save position
1165
contentLabel->setText(widget->getShapeContentString());
1166
v->setValue(curval+(v->maximum()-curval)/5);
1170
bool TaskCheckGeometryDialog::reject()
1175
void TaskCheckGeometryDialog::onClicked(QAbstractButton *btn)
1177
/** when ok (run check) is clicked or when close is clicked
1178
* the appropriate accept() or reject() is called already
1179
* all we need to do here is enable / disable / show / hide
1184
settingsBtn->setEnabled(true);
1185
} else if (btn == settingsBtn){
1186
settingsBtn->setEnabled(false);
1188
shapeContentBox->hide();
1189
settingsBox->show();
1190
resultsBtn->setEnabled(true);
1191
} else if (btn == resultsBtn){
1192
settingsBtn->setEnabled(true);
1194
shapeContentBox->show();
1195
settingsBox->hide();
1196
resultsBtn->setEnabled(false);
1200
void TaskCheckGeometryDialog::modifyStandardButtons(QDialogButtonBox* box)
1202
okBtn = box->button(QDialogButtonBox::Ok);
1203
okBtn->setText(tr("Run check"));
1204
settingsBtn = box->addButton(tr("Settings"),QDialogButtonBox::ActionRole);
1205
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1206
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1207
if(!group->GetBool("AutoRun",false))
1208
settingsBtn->setEnabled(false);
1209
resultsBtn = box->addButton(tr("Results"),QDialogButtonBox::ActionRole);
1210
resultsBtn->setEnabled(false);
1211
connect(box, &QDialogButtonBox::clicked, this, &TaskCheckGeometryDialog::onClicked);
1214
void TaskCheckGeometryDialog::onAutoRunCheckBoxToggled(bool isOn)
1216
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1217
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1218
group->SetBool("AutoRun", isOn);
1221
void TaskCheckGeometryDialog::onRunBOPCheckBoxToggled(bool isOn)
1223
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1224
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1225
group->SetBool("RunBOPCheck", isOn);
1228
void TaskCheckGeometryDialog::onRunSingleThreadedCheckBoxToggled(bool isOn)
1230
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1231
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1232
group->SetBool("RunSingleThreaded", isOn);
1235
void TaskCheckGeometryDialog::onLogErrorsCheckBoxToggled(bool isOn)
1237
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1238
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1239
group->SetBool("LogErrors", isOn);
1242
void TaskCheckGeometryDialog::onArgumentTypeModeCheckBoxToggled(bool isOn)
1244
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1245
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1246
group->SetBool("ArgumentTypeMode", isOn);
1249
void TaskCheckGeometryDialog::onExpandShapeContentCheckBoxToggled(bool isOn)
1251
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1252
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1253
group->SetBool("ExpandShapeContent", isOn);
1256
void TaskCheckGeometryDialog::onAdvancedShapeContentCheckBoxToggled(bool isOn)
1258
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1259
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1260
group->SetBool("AdvancedShapeContent", isOn);
1263
void TaskCheckGeometryDialog::onSelfInterModeCheckBoxToggled(bool isOn)
1265
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1266
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1267
group->SetBool("SelfInterMode", isOn);
1270
void TaskCheckGeometryDialog::onSmallEdgeModeCheckBoxToggled(bool isOn)
1272
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1273
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1274
group->SetBool("SmallEdgeMode", isOn);
1277
void TaskCheckGeometryDialog::onRebuildFaceModeCheckBoxToggled(bool isOn)
1279
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1280
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1281
group->SetBool("RebuildFaceMode", isOn);
1284
void TaskCheckGeometryDialog::onContinuityModeCheckBoxToggled(bool isOn)
1286
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1287
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1288
group->SetBool("ContinuityMode", isOn);
1291
void TaskCheckGeometryDialog::onTangentModeCheckBoxToggled(bool isOn)
1293
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1294
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1295
group->SetBool("TangentMode", isOn);
1298
void TaskCheckGeometryDialog::onMergeVertexModeCheckBoxToggled(bool isOn)
1300
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1301
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1302
group->SetBool("MergeVertexMode", isOn);
1305
void TaskCheckGeometryDialog::onMergeEdgeModeCheckBoxToggled(bool isOn)
1307
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1308
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1309
group->SetBool("MergeEdgeMode", isOn);
1312
void TaskCheckGeometryDialog::onCurveOnSurfaceModeCheckBoxToggled(bool isOn)
1314
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
1315
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod")->GetGroup("Part")->GetGroup("CheckGeometry");
1316
group->SetBool("CurveOnSurfaceMode", isOn);
1319
TaskCheckGeometryDialog::~TaskCheckGeometryDialog()
1328
delete contentLabel;
1329
contentLabel = nullptr;
1333
////////////////////////////////////////////////////////////////////////////////////////////////
1335
BOPProgressIndicator::BOPProgressIndicator (const QString& title, QWidget* parent)
1340
myProgress = new QProgressDialog(parent);
1341
myProgress->setWindowTitle(title);
1342
myProgress->setAttribute(Qt::WA_DeleteOnClose);
1345
BOPProgressIndicator::~BOPProgressIndicator ()
1347
myProgress->close();
1350
#if OCC_VERSION_HEX < 0x070500
1351
Standard_Boolean BOPProgressIndicator::Show (const Standard_Boolean theForce)
1360
myProgress->setRange(0, 0);
1361
myProgress->setValue(0);
1364
Handle(TCollection_HAsciiString) aName = GetScope(1).GetName(); //current step
1365
if (!aName.IsNull())
1366
myProgress->setLabelText (QString::fromUtf8(aName->ToCString()));
1369
return Standard_True;
1372
void BOPProgressIndicator::Show (const Message_ProgressScope& theScope,
1373
const Standard_Boolean isForce)
1375
Standard_CString aName = theScope.Name(); //current step
1376
myProgress->setLabelText (QString::fromUtf8(aName));
1382
QCoreApplication::processEvents();
1385
void BOPProgressIndicator::Reset()
1392
myProgress->setRange(0, 0);
1393
myProgress->setValue(0);
1397
Standard_Boolean BOPProgressIndicator::UserBreak()
1399
QThread *currentThread = QThread::currentThread();
1400
if (currentThread == myProgress->thread()) {
1401
// this is needed to check the status outside BOPAlgo_ArgumentAnalyzer
1403
// Hint: We must make sure to do this only when calling from the GUI
1404
// thread because when calling it from a worker thread the thrown
1405
// exception isn't handled anywhere and thus std::terminate is called
1407
return Standard_True;
1409
// it suffices to update only every second
1410
// to avoid to unnecessarily process events
1412
myProgress->setValue(steps);
1413
if (time.elapsed() > 1000) {
1415
QCoreApplication::processEvents();
1417
canceled = myProgress->wasCanceled();
1422
return Standard_False;
1425
#include "moc_TaskCheckGeometry.cpp"