Sketcher: Retrieve 1-based list of malformed constraints from solver

This commit is contained in:
Abdullah Tahiri
2021-01-04 08:59:18 +01:00
committed by abdullahtahiriyo
parent c2dd10b41a
commit 64df620407
4 changed files with 86 additions and 50 deletions

View File

@@ -76,7 +76,6 @@ Sketch::Sketch()
, RecalculateInitialSolutionWhileMovingPoint(false)
, GCSsys(), ConstraintsCounter(0)
, isInitMove(false), isFine(true), moveStep(0)
, malformedConstraints(false)
, defaultSolver(GCS::DogLeg)
, defaultSolverRedundant(GCS::DogLeg)
, debugMode(GCS::Minimal)
@@ -127,7 +126,8 @@ void Sketch::clear(void)
isInitMove = false;
ConstraintsCounter = 0;
Conflicting.clear();
malformedConstraints = false;
Redundant.clear();
MalformedConstraints.clear();
}
bool Sketch::analyseBlockedGeometry( const std::vector<Part::Geometry *> &internalGeoList,
@@ -1913,8 +1913,9 @@ int Sketch::addConstraints(const std::vector<Constraint *> &ConstraintList)
rtn = addConstraint (*it);
if(rtn == -1) {
Base::Console().Error("Sketcher constraint number %d is malformed!\n",cid);
malformedConstraints = true;
int humanconstraintid = cid + 1;
Base::Console().Error("Sketcher constraint number %d is malformed!\n",humanconstraintid);
MalformedConstraints.push_back(humanconstraintid);
}
}
@@ -1932,8 +1933,9 @@ int Sketch::addConstraints(const std::vector<Constraint *> &ConstraintList,
rtn = addConstraint (*it);
if(rtn == -1) {
Base::Console().Error("Sketcher constraint number %d is malformed!\n",cid);
malformedConstraints = true;
int humanconstraintid = cid + 1;
Base::Console().Error("Sketcher constraint number %d is malformed!\n",humanconstraintid);
MalformedConstraints.push_back(humanconstraintid);
}
}
else {

View File

@@ -106,7 +106,8 @@ public:
inline float getSolveTime() const { return SolveTime; }
inline bool hasMalformedConstraints(void) const { return malformedConstraints; }
inline bool hasMalformedConstraints(void) const { return !MalformedConstraints.empty(); }
inline const std::vector<int> &getMalformedConstraints(void) const { return MalformedConstraints; }
public:
std::set < std::pair< int, Sketcher::PointPos>> getDependencyGroup(int geoId, PointPos pos) const;
@@ -425,6 +426,7 @@ protected:
int ConstraintsCounter;
std::vector<int> Conflicting;
std::vector<int> Redundant;
std::vector<int> MalformedConstraints;
std::vector<double *> pDependentParametersList;
@@ -453,8 +455,6 @@ protected:
Base::Vector3d initToPoint;
double moveStep;
bool malformedConstraints;
public:
GCS::Algorithm defaultSolver;
GCS::Algorithm defaultSolverRedundant;

View File

@@ -133,6 +133,7 @@ SketchObject::SketchObject()
lastDoF=0;
lastHasConflict=false;
lastHasRedundancies=false;
lastHasMalformedConstraints=false;
lastSolverStatus=0;
lastSolveTime=0;
@@ -213,12 +214,14 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
appendRedundantMsg(lastRedundant, msg);
return new App::DocumentObjectExecReturn(msg.c_str(),this);
}
else if (err == -5) {
std::string msg="Sketch with malformed constraints\n";
appendMalformedConstraintsMsg(lastMalformedConstraints, msg);
return new App::DocumentObjectExecReturn(msg.c_str(),this);
}
else if (err == -1) { // Solver failed
return new App::DocumentObjectExecReturn("Solving the sketch failed",this);
}
else if (solvedSketch.hasMalformedConstraints()) {
return new App::DocumentObjectExecReturn("Sketch has malformed constraints");
}
// this is not necessary for sketch representation in edit mode, unless we want to trigger an update of
// the objects that depend on this sketch (like pads)
@@ -237,6 +240,16 @@ int SketchObject::hasConflicts(void) const
return 0;
}
void SketchObject::retrieveSolverDiagnostics()
{
lastHasConflict = solvedSketch.hasConflicts();
lastHasRedundancies = solvedSketch.hasRedundancies();
lastHasMalformedConstraints = solvedSketch.hasMalformedConstraints();
lastConflicting=solvedSketch.getConflicting();
lastRedundant=solvedSketch.getRedundant();
lastMalformedConstraints=solvedSketch.getMalformedConstraints();
}
int SketchObject::solve(bool updateGeoAfterSolving/*=true*/)
{
Base::StateLocker lock(managedoperation, true); // no need to check input data validity as this is an sketchobject managed operation.
@@ -264,10 +277,8 @@ int SketchObject::solve(bool updateGeoAfterSolving/*=true*/)
solverNeedsUpdate=false;
lastHasConflict = solvedSketch.hasConflicts();
lastHasRedundancies = solvedSketch.hasRedundancies();
lastConflicting=solvedSketch.getConflicting();
lastRedundant=solvedSketch.getRedundant();
retrieveSolverDiagnostics();
lastSolveTime=0.0;
lastSolverStatus=GCS::Failed; // Failure is default for notifying the user unless otherwise proven
@@ -288,6 +299,9 @@ int SketchObject::solve(bool updateGeoAfterSolving/*=true*/)
// The situation is exactly the same as in the over-constrained situation.
err = -3;
}
else if (lastHasMalformedConstraints) {
err = -5;
}
else {
lastSolverStatus=solvedSketch.solve();
if (lastSolverStatus != 0){ // solving
@@ -295,7 +309,7 @@ int SketchObject::solve(bool updateGeoAfterSolving/*=true*/)
}
}
if(solvedSketch.hasMalformedConstraints()) {
if(lastHasMalformedConstraints) {
Base::Console().Error("Sketch %s has malformed constraints!\n",this->getNameInDocument());
}
@@ -680,12 +694,9 @@ int SketchObject::setUpSketch()
lastDoF = solvedSketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
getExternalGeometryCount());
lastHasConflict = solvedSketch.hasConflicts();
lastHasRedundancies = solvedSketch.hasRedundancies();
lastConflicting=solvedSketch.getConflicting();
lastRedundant=solvedSketch.getRedundant();
retrieveSolverDiagnostics();
if(lastHasRedundancies || lastDoF < 0 || lastHasConflict)
if(lastHasRedundancies || lastDoF < 0 || lastHasConflict || lastHasMalformedConstraints)
Constraints.touch();
return lastDoF;
@@ -708,10 +719,7 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP
lastDoF = solvedSketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
getExternalGeometryCount());
lastHasConflict = solvedSketch.hasConflicts();
lastHasRedundancies = solvedSketch.hasRedundancies();
lastConflicting=solvedSketch.getConflicting();
lastRedundant=solvedSketch.getRedundant();
retrieveSolverDiagnostics();
solverNeedsUpdate=false;
}
@@ -7097,40 +7105,50 @@ bool SketchObject::arePointsCoincident(int GeoId1, PointPos PosId1,
}
void SketchObject::appendConflictMsg(const std::vector<int> &conflicting, std::string &msg)
{
appendConstraintsMsg(conflicting,
"Please remove the following conflicting constraint:\n",
"Please remove at least one of the following conflicting constraints:\n",
msg);
}
void SketchObject::appendRedundantMsg(const std::vector<int> &redundant, std::string &msg)
{
appendConstraintsMsg(redundant,
"Please remove the following redundant constraint:",
"Please remove the following redundant constraints:",
msg);
}
void SketchObject::appendMalformedConstraintsMsg(const std::vector<int> &malformed, std::string &msg)
{
appendConstraintsMsg(malformed,
"Please remove the following malformed constraint:",
"Please remove the following malformed constraints:",
msg);
}
void SketchObject::appendConstraintsMsg(const std::vector<int> &vector,
const std::string &singularmsg,
const std::string &pluralmsg,
std::string &msg)
{
std::stringstream ss;
if (msg.length() > 0)
ss << msg;
if (conflicting.size() > 0) {
if (conflicting.size() == 1)
ss << "Please remove the following constraint:\n";
if (vector.size() > 0) {
if (vector.size() == 1)
ss << singularmsg << std::endl;
else
ss << "Please remove at least one of the following constraints:\n";
ss << conflicting[0];
for (unsigned int i=1; i < conflicting.size(); i++)
ss << ", " << conflicting[i];
ss << pluralmsg;
ss << vector[0] << std::endl;
for (unsigned int i=1; i < vector.size(); i++)
ss << ", " << vector[i];
ss << "\n";
}
msg = ss.str();
}
void SketchObject::appendRedundantMsg(const std::vector<int> &redundant, std::string &msg)
{
std::stringstream ss;
if (msg.length() > 0)
ss << msg;
if (redundant.size() > 0) {
if (redundant.size() == 1)
ss << "Please remove the following redundant constraint:\n";
else
ss << "Please remove the following redundant constraints:\n";
ss << redundant[0];
for (unsigned int i=1; i < redundant.size(); i++)
ss << ", " << redundant[i];
ss << "\n";
}
msg = ss.str();
}
void SketchObject::getGeometryWithDependentParameters(std::vector<std::pair<int,PointPos>>& geometrymap)
{

View File

@@ -306,6 +306,8 @@ public:
static void appendConflictMsg(const std::vector<int> &conflicting, std::string &msg);
/// generates a warning message about redundant constraints and appends it to the given message
static void appendRedundantMsg(const std::vector<int> &redundant, std::string &msg);
/// generates a warning message about malformed constraints and appends it to the given message
static void appendMalformedConstraintsMsg(const std::vector<int> &malformed, std::string &msg);
double calculateAngleViaPoint(int geoId1, int geoId2, double px, double py);
bool isPointOnCurve(int geoIdCurve, double px, double py);
@@ -346,6 +348,8 @@ public:
inline bool getLastHasConflicts() const {return lastHasConflict;}
/// gets HasRedundancies status of last solver execution
inline bool getLastHasRedundancies() const {return lastHasRedundancies;}
/// gets HasMalformedConstraints status of last solver execution
inline bool getLastHasMalformedConstraints() const {return lastHasMalformedConstraints;}
/// gets solver status of last solver execution
inline int getLastSolverStatus() const {return lastSolverStatus;}
/// gets solver SolveTime of last solver execution
@@ -354,6 +358,8 @@ public:
inline const std::vector<int> &getLastConflicting(void) const { return lastConflicting; }
/// gets the redundant constraints of last solver execution
inline const std::vector<int> &getLastRedundant(void) const { return lastRedundant; }
/// gets the redundant constraints of last solver execution
inline const std::vector<int> &getLastMalformedConstraints(void) const { return lastMalformedConstraints; }
public: /* Solver exposed interface */
/// gets the solved sketch as a reference
@@ -476,6 +482,14 @@ protected:
// migration functions
void migrateSketch(void);
static void appendConstraintsMsg(const std::vector<int> &vector,
const std::string & singularmsg,
const std::string & pluralmsg,
std::string &msg);
// retrieves redundant, conflicting and malformed constraint information from the solver
void retrieveSolverDiagnostics();
private:
/// Flag to allow external geometry from other bodies than the one this sketch belongs to
bool allowOtherBody;
@@ -498,11 +512,13 @@ private:
int lastDoF;
bool lastHasConflict;
bool lastHasRedundancies;
bool lastHasMalformedConstraints;
int lastSolverStatus;
float lastSolveTime;
std::vector<int> lastConflicting;
std::vector<int> lastRedundant;
std::vector<int> lastMalformedConstraints;
boost::signals2::scoped_connection constraintsRenamedConn;
boost::signals2::scoped_connection constraintsRemovedConn;