Sketch: Fix crash when moving sketch with hidden constraints

Clicking the eye icon on the constraints panel hides all constraints. This calls SketchObject::setVirtualSpace where the existing Constraint
objects will be replaced. However, the Constraint objects are also stored inside the member 'solvedSketch' but won't be replaced so that the
pointers there will become dangling.

If the user starts to drag the sketch the pointers are still dangling and cause a crash when calling 'solvedSketch.moveGeometries'.

The crash can be reproduced with:
1. Create a sketch
2. Add a single line
3. Set a length constraint
4. Make it a non-driving constraint
5. Hide it with the eye icon or by unticking the check box
6. Move the line

The same crash also occurs when calling the methods setLabelDistance() or setLabelPosition() from Python and then trying to move the sketch.

Solution:

To fix the problem add the lightweight method 'Sketch::updateConstraints' and call it inside SketchObject::setVirtualSpace to quickly update
the pointers after invalidating them.

This fixes issue 19566
This commit is contained in:
wmayer
2026-03-12 16:17:08 -04:00
committed by pjcreath
parent 8ce3c4a1cc
commit 51b37da53e
3 changed files with 33 additions and 0 deletions
+24
View File
@@ -2581,6 +2581,30 @@ int Sketch::addConstraints(
return rtn;
}
bool Sketch::updateConstraints(const std::vector<int>& constrIds,
const std::vector<Constraint*>& ConstraintList)
{
if (Constrs.size() != ConstraintList.size()) {
return false;
}
int size = static_cast<int>(ConstraintList.size());
auto it = std::find_if(constrIds.begin(), constrIds.end(), [size](int id) {
return id < 0 || id >= size;
});
if (it != constrIds.end()) {
return false;
}
for (int id : constrIds) {
Constraint* constr = ConstraintList[id];
Constrs[id].constr = constr;
Constrs[id].driving = constr->isDriving;
}
return true;
}
void Sketch::getBlockedGeometry(
std::vector<bool>& blockedGeometry,
std::vector<bool>& unenforceableConstraints,
+4
View File
@@ -250,6 +250,10 @@ public:
/// add one constraint to the sketch
int addConstraint(const Constraint* constraint);
/// Updates the internal constraints of the given indexes
bool updateConstraints(const std::vector<int>& constrIds,
const std::vector<Constraint*>& ConstraintList);
/**
* add a fixed X coordinate constraint to a point
*
+5
View File
@@ -1180,6 +1180,7 @@ int SketchObject::setLabelPosition(int ConstrId, float value)
constNew->LabelPosition = value;
newVals[ConstrId] = constNew;
this->Constraints.setValues(std::move(newVals));
solvedSketch.updateConstraints({ConstrId}, this->Constraints.getValues());
return 0;
}
@@ -1214,6 +1215,7 @@ int SketchObject::setLabelDistance(int ConstrId, float value)
constNew->LabelDistance = value;
newVals[ConstrId] = constNew;
this->Constraints.setValues(std::move(newVals));
solvedSketch.updateConstraints({ConstrId}, this->Constraints.getValues());
return 0;
}
@@ -1405,6 +1407,7 @@ int SketchObject::setVirtualSpace(int ConstrId, bool isinvirtualspace)
newVals[ConstrId] = constNew;
this->Constraints.setValues(std::move(newVals));
solvedSketch.updateConstraints({ConstrId}, this->Constraints.getValues());
// Solver didn't actually update, but we need this to inform view provider
// to redraw
@@ -1440,6 +1443,7 @@ int SketchObject::setVirtualSpace(std::vector<int> constrIds, bool isinvirtualsp
}
this->Constraints.setValues(std::move(newVals));
solvedSketch.updateConstraints(constrIds, this->Constraints.getValues());
// Solver didn't actually update, but we need this to inform view provider
// to redraw
@@ -1479,6 +1483,7 @@ int SketchObject::toggleVirtualSpace(int ConstrId)
newVals[ConstrId] = constNew;
this->Constraints.setValues(std::move(newVals));
solvedSketch.updateConstraints({ConstrId}, this->Constraints.getValues());
// Solver didn't actually update, but we need this to inform view provider
// to redraw