From 6a211b9dbe5e21f9765c4bd683dd9de9434d429e Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 27 Dec 2014 22:47:21 +0100 Subject: [PATCH] + fixes #0001060: Editing sketch crashes FreeCAD --- src/Mod/Sketcher/App/SketchObject.cpp | 104 ++++++++++++++++++ src/Mod/Sketcher/App/SketchObject.h | 4 + .../Sketcher/Gui/TaskSketcherValidation.cpp | 21 ++++ src/Mod/Sketcher/Gui/TaskSketcherValidation.h | 2 + .../Sketcher/Gui/TaskSketcherValidation.ui | 27 ++++- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 7 ++ 6 files changed, 163 insertions(+), 2 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 7173a5c04..9b9506650 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -2160,6 +2160,110 @@ void SketchObject::appendRedundantMsg(const std::vector &redundant, std::st msg = ss.str(); } +bool SketchObject::evaluateConstraints() const +{ + int intGeoCount = getHighestCurveIndex() + 1; + int extGeoCount = getExternalGeometryCount(); + + std::vector geometry = getCompleteGeometry(); + const std::vector& constraints = Constraints.getValues(); + if (static_cast(geometry.size()) != extGeoCount + intGeoCount) + return false; + if (geometry.size() < 2) + return false; + + std::vector::const_iterator it; + for (it = constraints.begin(); it != constraints.end(); ++it) { + switch ((*it)->Type) { + case Horizontal: + case Vertical: + case Radius: + case Distance: + case DistanceX: + case DistanceY: + if ((*it)->First < -extGeoCount || (*it)->First >= intGeoCount) + return false; + break; + case Perpendicular: + case Parallel: + case Equal: + case PointOnObject: + case Tangent: + case Symmetric: + if ((*it)->First < -extGeoCount || (*it)->First >= intGeoCount) + return false; + if ((*it)->Second < -extGeoCount || (*it)->Second >= intGeoCount) + return false; + break; + case Angle: + if ((*it)->First < -extGeoCount || (*it)->First >= intGeoCount) + return false; + if (((*it)->Second < -extGeoCount || (*it)->Second >= intGeoCount) && + (*it)->Second != Constraint::GeoUndef) + return false; + break; + default: + break; + } + } + + return true; +} + +void SketchObject::validateConstraints() +{ + int intGeoCount = getHighestCurveIndex() + 1; + int extGeoCount = getExternalGeometryCount(); + + std::vector geometry = getCompleteGeometry(); + const std::vector& constraints = Constraints.getValues(); + + std::vector newConstraints; + std::vector::const_iterator it; + for (it = constraints.begin(); it != constraints.end(); ++it) { + bool valid = true; + switch ((*it)->Type) { + case Horizontal: + case Vertical: + case Radius: + case Distance: + case DistanceX: + case DistanceY: + if ((*it)->First < -extGeoCount || (*it)->First >= intGeoCount) + valid = false; + break; + case Perpendicular: + case Parallel: + case Equal: + case PointOnObject: + case Tangent: + case Symmetric: + if ((*it)->First < -extGeoCount || (*it)->First >= intGeoCount) + valid = false; + if ((*it)->Second < -extGeoCount || (*it)->Second >= intGeoCount) + valid = false; + break; + case Angle: + if ((*it)->First < -extGeoCount || (*it)->First >= intGeoCount) + valid = false; + if (((*it)->Second < -extGeoCount || (*it)->Second >= intGeoCount) && + (*it)->Second != Constraint::GeoUndef) + valid = false; + break; + default: + break; + } + + if (valid) + newConstraints.push_back(*it); + } + + if (newConstraints.size() != constraints.size()) { + Constraints.setValues(newConstraints); + acceptGeometry(); + } +} + PyObject *SketchObject::getPyObject(void) { if (PythonObject.is(Py::_None())) { diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 37c6cc2ae..586e0d197 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -164,6 +164,10 @@ public: virtual Base::Axis getAxis(int axId) const; /// verify and accept the assigned geometry virtual void acceptGeometry(); + /// Check for constraints with invalid indexes + bool evaluateConstraints() const; + /// Remove constraints with invalid indexes + void validateConstraints(); protected: /// get called by the container when a property has changed diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp index 9a8032f5d..296c8b25a 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp @@ -61,6 +61,7 @@ SketcherValidation::SketcherValidation(Sketcher::SketchObject* Obj, QWidget* par { ui->setupUi(this); ui->fixButton->setEnabled(false); + ui->fixConstraint->setEnabled(false); double tolerances[8] = { Precision::Confusion() / 100, Precision::Confusion() / 10, @@ -316,6 +317,26 @@ void SketcherValidation::on_fixButton_clicked() doc->recompute(); } +void SketcherValidation::on_findConstraint_clicked() +{ + if (sketch->evaluateConstraints()) { + QMessageBox::information(this, tr("No invalid constraints"), + tr("No invalid constraints found")); + ui->fixConstraint->setEnabled(false); + } + else { + QMessageBox::warning(this, tr("Invalid constraints"), + tr("Invalid constraints found")); + ui->fixConstraint->setEnabled(true); + } +} + +void SketcherValidation::on_fixConstraint_clicked() +{ + sketch->validateConstraints(); + ui->fixConstraint->setEnabled(false); +} + void SketcherValidation::showPoints(const std::vector& pts) { SoCoordinate3 * coords = new SoCoordinate3(); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.h b/src/Mod/Sketcher/Gui/TaskSketcherValidation.h index 0311244b4..ec175f292 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.h @@ -49,6 +49,8 @@ protected: private Q_SLOTS: void on_findButton_clicked(); void on_fixButton_clicked(); + void on_findConstraint_clicked(); + void on_fixConstraint_clicked(); private: void showPoints(const std::vector&); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui index 4c408ddb0..366f01eb5 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui @@ -7,13 +7,13 @@ 0 0 242 - 137 + 192 Sketcher validation - + @@ -47,6 +47,29 @@ + + + + Invalid constraints + + + + + + Find + + + + + + + Fix + + + + + + diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index c1404acfa..5c3a853c3 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -3967,6 +3967,13 @@ bool ViewProviderSketch::setEdit(int ModNum) return false; } + Sketcher::SketchObject* sketch = getSketchObject(); + if (!sketch->evaluateConstraints()) { + QMessageBox::critical(Gui::getMainWindow(), tr("Invalid sketch"), + tr("The sketch is invalid and cannot be edited.\nUse the sketch validation tool.")); + return false; + } + // clear the selection (convenience) Gui::Selection().clearSelection();