+ fixes #0001060: Editing sketch crashes FreeCAD

This commit is contained in:
wmayer 2014-12-27 22:47:21 +01:00
parent 16a8965038
commit 6a211b9dbe
6 changed files with 163 additions and 2 deletions

View File

@ -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())) {

View File

@ -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

View File

@ -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<Base::Vector3d>& pts)
{
SoCoordinate3 * coords = new SoCoordinate3();

View File

@ -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<Base::Vector3d>&);

View File

@ -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">
@ -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/>

View File

@ -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();