From af2bbf674ee936c7b3a15819eeaac35ca973478b Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 21 Apr 2024 10:41:47 +0200 Subject: [PATCH 1/3] Sketch: expose several methods to Python * expose detectDegeneratedGeometries to Python * expose removeDegeneratedGeometries to Python * expose delConstraintsToExternal to Python * expose evaluateConstraints to Python * expose validateConstraints to Python --- src/Mod/Sketcher/App/SketchObjectPy.xml | 51 ++++++++++++++++++++++ src/Mod/Sketcher/App/SketchObjectPyImp.cpp | 43 ++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml index 52df924057..1f601064f8 100644 --- a/src/Mod/Sketcher/App/SketchObjectPy.xml +++ b/src/Mod/Sketcher/App/SketchObjectPy.xml @@ -94,6 +94,38 @@ deleteAllGeometry() + + + +Detect degenerated geometries. A curve geometry is considered degenerated +if the parameter range is less than the tolerance. + +detectDegeneratedGeometries(tolerance:float) + + Args: + tolerance: The tolerance to check the parameter range of a curve. + + Returns: + The number of degenerated geometries. + + + + + + +Remove degenerated geometries. A curve geometry is considered degenerated +if the parameter range is less than the tolerance. + +removeDegeneratedGeometries(tolerance:float) + + Args: + tolerance: The tolerance to check the parameter range of a curve. + + Returns: + The number of degenerated geometries. + + + @@ -263,6 +295,11 @@ delConstraintOnPoint(geoId:int, pointPos:int) + + + Deletes all constraints referencing an external geometry. + + @@ -720,6 +757,20 @@ setLabelDistance(constraintIndex:int, value:float) + + + + Check for constraints with invalid indexes. Returns True if invalid constraints are found, False otherwise. + + + + + + + Removes constraints with invalid indexes. + + + diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index 54d2eac944..56e6af78da 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -46,6 +46,7 @@ // other python types #include "ConstraintPy.h" #include "GeometryFacadePy.h" +#include "SketchAnalysis.h" using namespace Sketcher; @@ -260,6 +261,30 @@ PyObject* SketchObjectPy::deleteAllGeometry(PyObject* args) Py_Return; } +PyObject* SketchObjectPy::detectDegeneratedGeometries(PyObject* args) +{ + double tolerance {}; + if (!PyArg_ParseTuple(args, "d", &tolerance)) { + return nullptr; + } + + SketchAnalysis analyse(this->getSketchObjectPtr()); + int count = analyse.detectDegeneratedGeometries(tolerance); + return Py::new_reference_to(Py::Long(count)); +} + +PyObject* SketchObjectPy::removeDegeneratedGeometries(PyObject* args) +{ + double tolerance {}; + if (!PyArg_ParseTuple(args, "d", &tolerance)) { + return nullptr; + } + + SketchAnalysis analyse(this->getSketchObjectPtr()); + int count = analyse.removeDegeneratedGeometries(tolerance); + return Py::new_reference_to(Py::Long(count)); +} + PyObject* SketchObjectPy::deleteAllConstraints(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { @@ -617,6 +642,12 @@ PyObject* SketchObjectPy::delConstraintOnPoint(PyObject* args) Py_Return; } +PyObject* SketchObjectPy::delConstraintsToExternal() +{ + this->getSketchObjectPtr()->delConstraintsToExternal(); + Py_Return; +} + PyObject* SketchObjectPy::setDatum(PyObject* args) { double Datum; @@ -1941,6 +1972,18 @@ PyObject* SketchObjectPy::makeMissingEquality(PyObject* args) Py_Return; } +PyObject* SketchObjectPy::evaluateConstraints() +{ + bool ok = this->getSketchObjectPtr()->evaluateConstraints(); + return Py::new_reference_to(Py::Boolean(ok)); +} + +PyObject* SketchObjectPy::validateConstraints() +{ + this->getSketchObjectPtr()->validateConstraints(); + Py_Return; +} + PyObject* SketchObjectPy::autoRemoveRedundants(PyObject* args) { PyObject* updategeo = Py_True; From 5ca56616a7e4aedd029a419c2e564844ac7c4936 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 21 Apr 2024 11:16:17 +0200 Subject: [PATCH 2/3] Sketch: Fix linter warnings --- .../Sketcher/Gui/TaskSketcherValidation.cpp | 150 ++++++++---------- 1 file changed, 68 insertions(+), 82 deletions(-) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp index 4718f260af..236837545e 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -68,22 +69,29 @@ SketcherValidation::SketcherValidation(Sketcher::SketchObject* Obj, QWidget* par ui->fixDegenerated->setEnabled(false); ui->swapReversed->setEnabled(false); ui->checkBoxIgnoreConstruction->setEnabled(true); - double tolerances[8] = {Precision::Confusion() / 100, - Precision::Confusion() / 10, - Precision::Confusion(), - Precision::Confusion() * 10, - Precision::Confusion() * 100, - Precision::Confusion() * 1000, - Precision::Confusion() * 10000, - Precision::Confusion() * 100000}; + std::array tolerances = { + // NOLINTBEGIN + Precision::Confusion() / 100.0, + Precision::Confusion() / 10.0, + Precision::Confusion(), + Precision::Confusion() * 10.0, + Precision::Confusion() * 100.0, + Precision::Confusion() * 1000.0, + Precision::Confusion() * 10000.0, + Precision::Confusion() * 100000.0 + // NOLINTEND + }; QLocale loc; - for (int i = 0; i < 8; i++) { - ui->comboBoxTolerance->addItem(loc.toString(tolerances[i]), QVariant(tolerances[i])); + for (double it : tolerances) { + ui->comboBoxTolerance->addItem(loc.toString(it), QVariant(it)); } ui->comboBoxTolerance->setCurrentIndex(5); ui->comboBoxTolerance->setEditable(true); - ui->comboBoxTolerance->setValidator(new QDoubleValidator(0, 10, 10, this)); + const double bottom = 0.0; + const double top = 10.0; + const int decimals = 10; + ui->comboBoxTolerance->setValidator(new QDoubleValidator(bottom, top, decimals, this)); } SketcherValidation::~SketcherValidation() @@ -93,48 +101,32 @@ SketcherValidation::~SketcherValidation() void SketcherValidation::setupConnections() { - connect(ui->findButton, &QPushButton::clicked, this, &SketcherValidation::onFindButtonClicked); - connect(ui->fixButton, &QPushButton::clicked, this, &SketcherValidation::onFixButtonClicked); - connect(ui->highlightButton, - &QPushButton::clicked, - this, - &SketcherValidation::onHighlightButtonClicked); - connect(ui->findConstraint, - &QPushButton::clicked, - this, - &SketcherValidation::onFindConstraintClicked); - connect(ui->fixConstraint, - &QPushButton::clicked, - this, - &SketcherValidation::onFixConstraintClicked); - connect(ui->findReversed, - &QPushButton::clicked, - this, - &SketcherValidation::onFindReversedClicked); - connect(ui->swapReversed, - &QPushButton::clicked, - this, - &SketcherValidation::onSwapReversedClicked); - connect(ui->orientLockEnable, - &QPushButton::clicked, - this, - &SketcherValidation::onOrientLockEnableClicked); - connect(ui->orientLockDisable, - &QPushButton::clicked, - this, - &SketcherValidation::onOrientLockDisableClicked); - connect(ui->delConstrExtr, - &QPushButton::clicked, - this, - &SketcherValidation::onDelConstrExtrClicked); - connect(ui->findDegenerated, - &QPushButton::clicked, - this, - &SketcherValidation::onFindDegeneratedClicked); - connect(ui->fixDegenerated, - &QPushButton::clicked, - this, - &SketcherValidation::onFixDegeneratedClicked); + // clang-format off + connect(ui->findButton, &QPushButton::clicked, + this, &SketcherValidation::onFindButtonClicked); + connect(ui->fixButton, &QPushButton::clicked, + this, &SketcherValidation::onFixButtonClicked); + connect(ui->highlightButton, &QPushButton::clicked, + this, &SketcherValidation::onHighlightButtonClicked); + connect(ui->findConstraint, &QPushButton::clicked, + this, &SketcherValidation::onFindConstraintClicked); + connect(ui->fixConstraint, &QPushButton::clicked, + this, &SketcherValidation::onFixConstraintClicked); + connect(ui->findReversed, &QPushButton::clicked, + this, &SketcherValidation::onFindReversedClicked); + connect(ui->swapReversed, &QPushButton::clicked, + this, &SketcherValidation::onSwapReversedClicked); + connect(ui->orientLockEnable, &QPushButton::clicked, + this, &SketcherValidation::onOrientLockEnableClicked); + connect(ui->orientLockDisable, &QPushButton::clicked, + this, &SketcherValidation::onOrientLockDisableClicked); + connect(ui->delConstrExtr, &QPushButton::clicked, + this, &SketcherValidation::onDelConstrExtrClicked); + connect(ui->findDegenerated, &QPushButton::clicked, + this, &SketcherValidation::onFindDegeneratedClicked); + connect(ui->fixDegenerated, &QPushButton::clicked, + this, &SketcherValidation::onFixDegeneratedClicked); + // clang-format on } void SketcherValidation::changeEvent(QEvent* e) @@ -152,8 +144,8 @@ void SketcherValidation::onFindButtonClicked() } double prec = Precision::Confusion(); - bool ok; - double conv; + bool ok {}; + double conv {}; conv = QLocale::system().toDouble(ui->comboBoxTolerance->currentText(), &ok); @@ -208,7 +200,7 @@ void SketcherValidation::onFixButtonClicked() // undo command open App::Document* doc = sketch->getDocument(); - doc->openTransaction("add coincident constraint"); + doc->openTransaction("Add coincident constraint"); sketchAnalyser.makeMissingPointOnPointCoincident(); @@ -277,15 +269,13 @@ void SketcherValidation::onFindReversedClicked() std::vector points; const std::vector& geom = sketch->getExternalGeometry(); - for (std::size_t i = 0; i < geom.size(); i++) { - Part::Geometry* g = geom[i]; + for (const auto geo : geom) { // only arcs of circles need to be repaired. Arcs of ellipse were so broken there should be // nothing to repair from. - if (g->is()) { - const Part::GeomArcOfCircle* segm = static_cast(g); + if (const auto segm = dynamic_cast(geo)) { if (segm->isReversed()) { - points.push_back(segm->getStartPoint(/*emulateCCW=*/true)); - points.push_back(segm->getEndPoint(/*emulateCCW=*/true)); + points.push_back(segm->getStartPoint(/*emulateCCWXY=*/true)); + points.push_back(segm->getEndPoint(/*emulateCCWXY=*/true)); } } } @@ -397,8 +387,7 @@ void SketcherValidation::onDelConstrExtrClicked() return; } - int reply; - reply = QMessageBox::question( + int reply = QMessageBox::question( this, tr("Delete constraints to external geom."), tr("You are about to delete ALL constraints that deal with external geometry. This is " @@ -425,31 +414,30 @@ void SketcherValidation::onDelConstrExtrClicked() void SketcherValidation::showPoints(const std::vector& pts) { - SoCoordinate3* coords = new SoCoordinate3(); - SoDrawStyle* drawStyle = new SoDrawStyle(); + auto coords = new SoCoordinate3(); + auto drawStyle = new SoDrawStyle(); drawStyle->pointSize = 6; - SoPointSet* pcPoints = new SoPointSet(); + auto pcPoints = new SoPointSet(); coincidenceRoot = new SoGroup(); coincidenceRoot->addChild(drawStyle); - SoSeparator* pointsep = new SoSeparator(); - SoBaseColor* basecol = new SoBaseColor(); - basecol->rgb.setValue(1.0f, 0.5f, 0.0f); + auto pointsep = new SoSeparator(); + auto basecol = new SoBaseColor(); + basecol->rgb.setValue(1.0F, 0.5F, 0.0F); pointsep->addChild(basecol); pointsep->addChild(coords); pointsep->addChild(pcPoints); coincidenceRoot->addChild(pointsep); // Draw markers - SoBaseColor* markcol = new SoBaseColor(); - markcol->rgb.setValue(1.0f, 1.0f, 0.0f); - SoMarkerSet* marker = new SoMarkerSet(); - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 9)); + auto markcol = new SoBaseColor(); + markcol->rgb.setValue(1.0F, 1.0F, 0.0F); + auto marker = new SoMarkerSet(); + long markerSize = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") + ->GetInt("MarkerSize", 9); + marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex("PLUS", int(markerSize)); pointsep->addChild(markcol); pointsep->addChild(marker); @@ -531,13 +519,11 @@ void SketcherValidation::onFixDegeneratedClicked() TaskSketcherValidation::TaskSketcherValidation(Sketcher::SketchObject* Obj) { QWidget* widget = new SketcherValidation(Obj); - Gui::TaskView::TaskBox* taskbox = - new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(), true, nullptr); + auto taskbox = new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } -TaskSketcherValidation::~TaskSketcherValidation() -{} +TaskSketcherValidation::~TaskSketcherValidation() = default; #include "moc_TaskSketcherValidation.cpp" From 5c610c3a0516d14b2101a1e078fd5e29c0ec287b Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 21 Apr 2024 11:56:02 +0200 Subject: [PATCH 3/3] Sketcher: Fixes #13518: ValidateSketch cannot be scripted --- src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp index 236837545e..f98f04176d 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -202,7 +203,7 @@ void SketcherValidation::onFixButtonClicked() App::Document* doc = sketch->getDocument(); doc->openTransaction("Add coincident constraint"); - sketchAnalyser.makeMissingPointOnPointCoincident(); + Gui::cmdAppObjectArgs(sketch.get(), "makeMissingPointOnPointCoincident()"); ui->fixButton->setEnabled(false); hidePoints(); @@ -257,7 +258,7 @@ void SketcherValidation::onFixConstraintClicked() return; } - sketch->validateConstraints(); + Gui::cmdAppObjectArgs(sketch.get(), "validateConstraints()"); ui->fixConstraint->setEnabled(false); } @@ -402,7 +403,7 @@ void SketcherValidation::onDelConstrExtrClicked() App::Document* doc = sketch->getDocument(); doc->openTransaction("Delete constraints"); - sketch->delConstraintsToExternal(); + Gui::cmdAppObjectArgs(sketch.get(), "delConstraintsToExternal()"); doc->commitTransaction(); @@ -503,7 +504,7 @@ void SketcherValidation::onFixDegeneratedClicked() doc->openTransaction("Remove degenerated geometry"); double prec = Precision::Confusion(); - sketchAnalyser.removeDegeneratedGeometries(prec); + Gui::cmdAppObjectArgs(sketch.get(), "removeDegeneratedGeometries(%.12f)", prec); ui->fixButton->setEnabled(false); hidePoints();