Sketcher: restric ViewProviderSketch access to the solver

=========================================================

-> Split read and read/write operations

New interface to access the solver object (Sketch) of SketchObject is now read only (const):

const Sketcher::Sketch &getSolvedSketch(void) const;

-> Encapsulate solver r/w access in SketchObject

Rationale:

- r/w access (access to non-const functions of the solver) leads to unsynchronised solver status.

- Before this commit there was a non-enforceable shared responsibility between ViewProviderSketch
and SketchObject.

- This commit centralises r/w access in SketchObject and SketchObject takes responsibility for doing whatever
necessary so that the solver is synchronised as appropriate.

- For read-only access (const functions) it is possible to use at ViewProviderSketch getSolvedSketch() returning
a const reference to the solver object.

- As it regards the advanced solver configuration dialog, it has been modified to configure by const-casting that reference. This
is not optimal, but it is deemed acceptable, because it should be rewritten sooner or later to include only useful information
and the configuration probably centralised in an individual configuration object, possibly compatible with several solvers
(e.g. DeepSOIC's ConstraintSolver too).
This commit is contained in:
Abdullah Tahiri
2020-12-25 09:01:21 +01:00
committed by abdullahtahiriyo
parent 5c8e65728f
commit 04bbae80cf
4 changed files with 128 additions and 95 deletions

View File

@@ -189,7 +189,7 @@ struct EditData {
MarkerSize(7),
blockedPreselection(false),
FullyConstrained(false),
//ActSketch(0), // if you are wondering, it went to SketchObject, accessible via getSketchObject()->getSolvedSketch()
//ActSketch(0), // if you are wondering, it went to SketchObject, accessible via getSolvedSketch() and via SketchObject interface as appropriate
EditRoot(0),
PointsMaterials(0),
CurvesMaterials(0),
@@ -1139,7 +1139,7 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
}
return false;
case STATUS_SELECT_Point:
if (!getSketchObject()->getSolvedSketch().hasConflicts() &&
if (!getSolvedSketch().hasConflicts() &&
edit->PreselectPoint != -1 && edit->DragPoint != edit->PreselectPoint) {
Mode = STATUS_SKETCH_DragPoint;
edit->DragPoint = edit->PreselectPoint;
@@ -1147,7 +1147,7 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
Sketcher::PointPos PosId;
getSketchObject()->getGeoVertexIndex(edit->DragPoint, GeoId, PosId);
if (GeoId != Sketcher::Constraint::GeoUndef && PosId != Sketcher::none) {
getSketchObject()->getSolvedSketch().initMove(GeoId, PosId, false);
getSketchObject()->initTemporaryMove(GeoId, PosId, false);
relative = false;
xInit = 0;
yInit = 0;
@@ -1161,7 +1161,7 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
edit->PreselectConstraintSet.clear();
return true;
case STATUS_SELECT_Edge:
if (!getSketchObject()->getSolvedSketch().hasConflicts() &&
if (!getSolvedSketch().hasConflicts() &&
edit->PreselectCurve != -1 && edit->DragCurve != edit->PreselectCurve) {
Mode = STATUS_SKETCH_DragCurve;
edit->DragCurve = edit->PreselectCurve;
@@ -1183,7 +1183,7 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
// The B-Spline is constrained to be non-rational (equal weights), moving produces a bad effect
// because OCCT will normalize the values of the weights.
auto grp = getSketchObject()->getSolvedSketch().getDependencyGroup(edit->DragCurve, Sketcher::none);
auto grp = getSolvedSketch().getDependencyGroup(edit->DragCurve, Sketcher::none);
int bsplinegeoid = -1;
@@ -1231,7 +1231,7 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
}
getSketchObject()->getSolvedSketch().initMove(edit->DragCurve, Sketcher::none, false);
getSketchObject()->initTemporaryMove(edit->DragCurve, Sketcher::none, false);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) {
@@ -1273,12 +1273,12 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
getSketchObject()->getGeoVertexIndex(edit->DragPoint, GeoId, PosId);
Base::Vector3d vec(x,y,0);
if (GeoId != Sketcher::Constraint::GeoUndef && PosId != Sketcher::none) {
if (getSketchObject()->getSolvedSketch().movePoint(GeoId, PosId, vec, false) == 0) {
if (getSketchObject()->moveTemporaryPoint(GeoId, PosId, vec, false) == 0) {
setPositionText(Base::Vector2d(x,y));
draw(true,false);
signalSolved(QString::fromLatin1("Solved in %1 sec").arg(getSketchObject()->getSolvedSketch().getSolveTime()));
signalSolved(QString::fromLatin1("Solved in %1 sec").arg(getSolvedSketch().getSolveTime()));
} else {
signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(getSketchObject()->getSolvedSketch().getSolveTime()));
signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(getSolvedSketch().getSolveTime()));
//Base::Console().Log("Error solving:%d\n",ret);
}
}
@@ -1314,12 +1314,12 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
vec = center + dir / scalefactor;
}
if (getSketchObject()->getSolvedSketch().movePoint(edit->DragCurve, Sketcher::none, vec, relative) == 0) {
if (getSketchObject()->moveTemporaryPoint(edit->DragCurve, Sketcher::none, vec, relative) == 0) {
setPositionText(Base::Vector2d(x,y));
draw(true,false);
signalSolved(QString::fromLatin1("Solved in %1 sec").arg(getSketchObject()->getSolvedSketch().getSolveTime()));
signalSolved(QString::fromLatin1("Solved in %1 sec").arg(getSolvedSketch().getSolveTime()));
} else {
signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(getSketchObject()->getSolvedSketch().getSolveTime()));
signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(getSolvedSketch().getSolveTime()));
}
}
return true;
@@ -1380,7 +1380,7 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo
#endif
// with memory allocation
const std::vector<Part::Geometry *> geomlist = getSketchObject()->getSolvedSketch().extractGeometry(true, true);
const std::vector<Part::Geometry *> geomlist = getSolvedSketch().extractGeometry(true, true);
#ifdef _DEBUG
assert(int(geomlist.size()) == extGeoCount + intGeoCount);
@@ -1393,10 +1393,10 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo
Base::Vector3d p1(0.,0.,0.), p2(0.,0.,0.);
if (Constr->SecondPos != Sketcher::none) { // point to point distance
p1 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
p2 = getSketchObject()->getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
p2 = getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
} else if (Constr->Second != Constraint::GeoUndef) { // point to line distance
p1 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
const Part::Geometry *geo = GeoById(geomlist, Constr->Second);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = static_cast<const Part::GeomLineSegment *>(geo);
@@ -1408,7 +1408,7 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo
} else
return;
} else if (Constr->FirstPos != Sketcher::none) {
p2 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
p2 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
} else if (Constr->First != Constraint::GeoUndef) {
const Part::Geometry *geo = GeoById(geomlist, Constr->First);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
@@ -1534,11 +1534,11 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo
factor = factor * Base::sgn<double>((dir1+dir2) * vec);
}
} else {//angle-via-point
Base::Vector3d p = getSketchObject()->getSolvedSketch().getPoint(Constr->Third, Constr->ThirdPos);
Base::Vector3d p = getSolvedSketch().getPoint(Constr->Third, Constr->ThirdPos);
p0 = Base::Vector3d(p.x, p.y, 0);
dir1 = getSketchObject()->getSolvedSketch().calculateNormalAtPoint(Constr->First, p.x, p.y);
dir1 = getSolvedSketch().calculateNormalAtPoint(Constr->First, p.x, p.y);
dir1.RotateZ(-M_PI/2);//convert to vector of tangency by rotating
dir2 = getSketchObject()->getSolvedSketch().calculateNormalAtPoint(Constr->Second, p.x, p.y);
dir2 = getSolvedSketch().calculateNormalAtPoint(Constr->Second, p.x, p.y);
dir2.RotateZ(-M_PI/2);
Base::Vector3d vec = Base::Vector3d(toPos.x, toPos.y, 0) - p0;
@@ -3032,7 +3032,7 @@ void ViewProviderSketch::updateColor(void)
} else if (type == Sketcher::Coincident) {
auto selectpoint = [this, pcolor, PtNum](int geoid, Sketcher::PointPos pos){
if(geoid >= 0) {
int index = getSketchObject()->getSolvedSketch().getPointId(geoid, pos) + 1;
int index = getSolvedSketch().getPointId(geoid, pos) + 1;
if (index >= 0 && index < PtNum)
pcolor[index] = SelectColor;
}
@@ -3060,7 +3060,7 @@ void ViewProviderSketch::updateColor(void)
case EllipseFocus1:
case EllipseFocus2:
{
int index = getSketchObject()->getSolvedSketch().getPointId(constraint->First, constraint->FirstPos) + 1;
int index = getSolvedSketch().getPointId(constraint->First, constraint->FirstPos) + 1;
if (index >= 0 && index < PtNum) pcolor[index] = SelectColor;
}
break;
@@ -3760,7 +3760,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
const std::vector<Part::Geometry *> *geomlist;
std::vector<Part::Geometry *> tempGeo;
if (temp)
tempGeo = getSketchObject()->getSolvedSketch().extractGeometry(true, true); // with memory allocation
tempGeo = getSolvedSketch().extractGeometry(true, true); // with memory allocation
else
tempGeo = getSketchObject()->getCompleteGeometry(); // without memory allocation
geomlist = &tempGeo;
@@ -3880,7 +3880,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer
auto vpext = std::make_unique<SketcherGui::ViewProviderSketchGeometryExtension>();
vpext->setRepresentationFactor(scalefactor);
getSketchObject()->getSolvedSketch().updateExtension(GeoId, std::move(vpext));
getSketchObject()->updateSolverExtension(GeoId, std::move(vpext));
}
if(!circle->hasExtension(SketcherGui::ViewProviderSketchGeometryExtension::getClassTypeId()))
@@ -4881,12 +4881,12 @@ Restart:
Base::Vector3d midpos2, dir2, norm2;
if (temp)
midpos1 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
midpos1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
else
midpos1 = getSketchObject()->getPoint(Constr->First, Constr->FirstPos);
if (temp)
midpos2 = getSketchObject()->getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
midpos2 = getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
else
midpos2 = getSketchObject()->getPoint(Constr->Second, Constr->SecondPos);
@@ -4938,11 +4938,11 @@ Restart:
assert(0);//no point found!
} while (false);
if (temp)
midpos1 = getSketchObject()->getSolvedSketch().getPoint(ptGeoId, ptPosId);
midpos1 = getSolvedSketch().getPoint(ptGeoId, ptPosId);
else
midpos1 = getSketchObject()->getPoint(ptGeoId, ptPosId);
norm1 = getSketchObject()->getSolvedSketch().calculateNormalAtPoint(Constr->Second, midpos1.x, midpos1.y);
norm1 = getSolvedSketch().calculateNormalAtPoint(Constr->Second, midpos1.x, midpos1.y);
norm1.Normalize();
dir1 = norm1; dir1.RotateZ(-M_PI/2.0);
@@ -5206,15 +5206,15 @@ Restart:
Base::Vector3d pnt1(0.,0.,0.), pnt2(0.,0.,0.);
if (Constr->SecondPos != Sketcher::none) { // point to point distance
if (temp) {
pnt1 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
pnt2 = getSketchObject()->getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
pnt1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
pnt2 = getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
} else {
pnt1 = getSketchObject()->getPoint(Constr->First, Constr->FirstPos);
pnt2 = getSketchObject()->getPoint(Constr->Second, Constr->SecondPos);
}
} else if (Constr->Second != Constraint::GeoUndef) { // point to line distance
if (temp) {
pnt1 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
pnt1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
} else {
pnt1 = getSketchObject()->getPoint(Constr->First, Constr->FirstPos);
}
@@ -5230,7 +5230,7 @@ Restart:
break;
} else if (Constr->FirstPos != Sketcher::none) {
if (temp) {
pnt2 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
pnt2 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
} else {
pnt2 = getSketchObject()->getPoint(Constr->First, Constr->FirstPos);
}
@@ -5301,9 +5301,9 @@ Restart:
if (ptPosId != Sketcher::none) break;
assert(0);//no point found!
} while (false);
pos = getSketchObject()->getSolvedSketch().getPoint(ptGeoId, ptPosId);
pos = getSolvedSketch().getPoint(ptGeoId, ptPosId);
Base::Vector3d norm = getSketchObject()->getSolvedSketch().calculateNormalAtPoint(Constr->Second, pos.x, pos.y);
Base::Vector3d norm = getSolvedSketch().calculateNormalAtPoint(Constr->Second, pos.x, pos.y);
norm.Normalize();
Base::Vector3d dir = norm; dir.RotateZ(-M_PI/2.0);
@@ -5429,8 +5429,8 @@ Restart:
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
assert(Constr->Second >= -extGeoCount && Constr->Second < intGeoCount);
Base::Vector3d pnt1 = getSketchObject()->getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
Base::Vector3d pnt2 = getSketchObject()->getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
Base::Vector3d pnt1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
Base::Vector3d pnt2 = getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
SbVec3f p1(pnt1.x,pnt1.y,zConstr);
SbVec3f p2(pnt2.x,pnt2.y,zConstr);
@@ -5513,11 +5513,11 @@ Restart:
startangle = atan2(dir1.y,dir1.x);
}
else {//angle-via-point
Base::Vector3d p = getSketchObject()->getSolvedSketch().getPoint(Constr->Third, Constr->ThirdPos);
Base::Vector3d p = getSolvedSketch().getPoint(Constr->Third, Constr->ThirdPos);
p0 = SbVec3f(p.x, p.y, 0);
dir1 = getSketchObject()->getSolvedSketch().calculateNormalAtPoint(Constr->First, p.x, p.y);
dir1 = getSolvedSketch().calculateNormalAtPoint(Constr->First, p.x, p.y);
dir1.RotateZ(-M_PI/2);//convert to vector of tangency by rotating
dir2 = getSketchObject()->getSolvedSketch().calculateNormalAtPoint(Constr->Second, p.x, p.y);
dir2 = getSolvedSketch().calculateNormalAtPoint(Constr->Second, p.x, p.y);
dir2.RotateZ(-M_PI/2);
startangle = atan2(dir1.y,dir1.x);
@@ -6001,7 +6001,7 @@ void ViewProviderSketch::updateData(const App::Property *prop)
UpdateSolverInformation(); // just update the solver window with the last SketchObject solving information
if(getSketchObject()->getExternalGeometryCount()+getSketchObject()->getHighestCurveIndex() + 1 ==
getSketchObject()->getSolvedSketch().getGeometrySize()) {
getSolvedSketch().getGeometrySize()) {
Gui::MDIView *mdi = Gui::Application::Instance->editDocument()->getActiveView();
if (mdi->isDerivedFrom(Gui::View3DInventor::getClassTypeId()))
draw(false,true);
@@ -6255,8 +6255,7 @@ bool ViewProviderSketch::setEdit(int ModNum)
// Enable solver initial solution update while dragging.
ParameterGrp::handle hGrp2 = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher");
getSketchObject()->getSolvedSketch().setRecalculateInitialSolutionWhileMovingPoint(hGrp2->GetBool("RecalculateInitialSolutionWhileDragging",true));
getSketchObject()->setRecalculateInitialSolutionWhileMovingPoint(hGrp2->GetBool("RecalculateInitialSolutionWhileDragging",true));
// intercept del key press from main app
listener = new ShortcutListener(this);
@@ -6340,7 +6339,7 @@ void ViewProviderSketch::UpdateSolverInformation()
if (getSketchObject()->getLastSolverStatus() == 0) {
if (dofs == 0) {
// color the sketch as fully constrained if it has geometry (other than the axes)
if(getSketchObject()->getSolvedSketch().getGeometrySize()>2)
if(getSolvedSketch().getGeometrySize()>2)
edit->FullyConstrained = true;
if (!hasRedundancies) {
@@ -6826,6 +6825,11 @@ Sketcher::SketchObject *ViewProviderSketch::getSketchObject(void) const
return dynamic_cast<Sketcher::SketchObject *>(pcObject);
}
const Sketcher::Sketch &ViewProviderSketch::getSolvedSketch(void) const
{
return const_cast<const Sketcher::SketchObject *>(getSketchObject())->getSolvedSketch();
}
void ViewProviderSketch::deleteSelected()
{
std::vector<Gui::SelectionObject> selection;