+ fixes #0001060: Editing sketch crashes FreeCAD
This commit is contained in:
parent
16a8965038
commit
6a211b9dbe
|
@ -2160,6 +2160,110 @@ void SketchObject::appendRedundantMsg(const std::vector<int> &redundant, std::st
|
||||||
msg = ss.str();
|
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)
|
PyObject *SketchObject::getPyObject(void)
|
||||||
{
|
{
|
||||||
if (PythonObject.is(Py::_None())) {
|
if (PythonObject.is(Py::_None())) {
|
||||||
|
|
|
@ -164,6 +164,10 @@ public:
|
||||||
virtual Base::Axis getAxis(int axId) const;
|
virtual Base::Axis getAxis(int axId) const;
|
||||||
/// verify and accept the assigned geometry
|
/// verify and accept the assigned geometry
|
||||||
virtual void acceptGeometry();
|
virtual void acceptGeometry();
|
||||||
|
/// Check for constraints with invalid indexes
|
||||||
|
bool evaluateConstraints() const;
|
||||||
|
/// Remove constraints with invalid indexes
|
||||||
|
void validateConstraints();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// get called by the container when a property has changed
|
/// get called by the container when a property has changed
|
||||||
|
|
|
@ -61,6 +61,7 @@ SketcherValidation::SketcherValidation(Sketcher::SketchObject* Obj, QWidget* par
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->fixButton->setEnabled(false);
|
ui->fixButton->setEnabled(false);
|
||||||
|
ui->fixConstraint->setEnabled(false);
|
||||||
double tolerances[8] = {
|
double tolerances[8] = {
|
||||||
Precision::Confusion() / 100,
|
Precision::Confusion() / 100,
|
||||||
Precision::Confusion() / 10,
|
Precision::Confusion() / 10,
|
||||||
|
@ -316,6 +317,26 @@ void SketcherValidation::on_fixButton_clicked()
|
||||||
doc->recompute();
|
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)
|
void SketcherValidation::showPoints(const std::vector<Base::Vector3d>& pts)
|
||||||
{
|
{
|
||||||
SoCoordinate3 * coords = new SoCoordinate3();
|
SoCoordinate3 * coords = new SoCoordinate3();
|
||||||
|
|
|
@ -49,6 +49,8 @@ protected:
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void on_findButton_clicked();
|
void on_findButton_clicked();
|
||||||
void on_fixButton_clicked();
|
void on_fixButton_clicked();
|
||||||
|
void on_findConstraint_clicked();
|
||||||
|
void on_fixConstraint_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void showPoints(const std::vector<Base::Vector3d>&);
|
void showPoints(const std::vector<Base::Vector3d>&);
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>242</width>
|
<width>242</width>
|
||||||
<height>137</height>
|
<height>192</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Sketcher validation</string>
|
<string>Sketcher validation</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -47,6 +47,29 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|
|
@ -3967,6 +3967,13 @@ bool ViewProviderSketch::setEdit(int ModNum)
|
||||||
return false;
|
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)
|
// clear the selection (convenience)
|
||||||
Gui::Selection().clearSelection();
|
Gui::Selection().clearSelection();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user