Skip to content

Commit

Permalink
+ fixes #1060: Editing sketch crashes FreeCAD
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Dec 27, 2014
1 parent 16a8965 commit 6a211b9
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 2 deletions.
104 changes: 104 additions & 0 deletions src/Mod/Sketcher/App/SketchObject.cpp
Expand Up @@ -2160,6 +2160,110 @@ void SketchObject::appendRedundantMsg(const std::vector<int> &redundant, std::st
msg = ss.str();
}

bool SketchObject::evaluateConstraints() const
{
int intGeoCount = getHighestCurveIndex() + 1;
int extGeoCount = getExternalGeometryCount();

std::vector<Part::Geometry *> geometry = getCompleteGeometry();
const std::vector<Sketcher::Constraint *>& constraints = Constraints.getValues();
if (static_cast<int>(geometry.size()) != extGeoCount + intGeoCount)
return false;
if (geometry.size() < 2)
return false;

std::vector<Sketcher::Constraint *>::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<Part::Geometry *> geometry = getCompleteGeometry();
const std::vector<Sketcher::Constraint *>& constraints = Constraints.getValues();

std::vector<Sketcher::Constraint *> newConstraints;
std::vector<Sketcher::Constraint *>::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())) {
Expand Down
4 changes: 4 additions & 0 deletions src/Mod/Sketcher/App/SketchObject.h
Expand Up @@ -164,6 +164,10 @@ class SketcherExport SketchObject : public Part::Part2DObject
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
Expand Down
21 changes: 21 additions & 0 deletions src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp
Expand Up @@ -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,
Expand Down Expand Up @@ -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<Base::Vector3d>& pts)
{
SoCoordinate3 * coords = new SoCoordinate3();
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Sketcher/Gui/TaskSketcherValidation.h
Expand Up @@ -49,6 +49,8 @@ class SketcherValidation : public QWidget
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<Base::Vector3d>&);
Expand Down
27 changes: 25 additions & 2 deletions src/Mod/Sketcher/Gui/TaskSketcherValidation.ui
Expand Up @@ -7,13 +7,13 @@
<x>0</x>
<y>0</y>
<width>242</width>
<height>137</height>
<height>192</height>
</rect>
</property>
<property name="windowTitle">
<string>Sketcher validation</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
Expand Down Expand Up @@ -47,6 +47,29 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Invalid constraints</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QPushButton" name="findConstraint">
<property name="text">
<string>Find</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="fixConstraint">
<property name="text">
<string>Fix</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
Expand Down
7 changes: 7 additions & 0 deletions src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
Expand Up @@ -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();

Expand Down

0 comments on commit 6a211b9

Please sign in to comment.