Merge branch 'logari81/sketch-diagnostics'
This commit is contained in:
commit
dbce31d44f
|
@ -96,8 +96,9 @@ void Sketch::clear(void)
|
||||||
Conflicting.clear();
|
Conflicting.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Constraint *> &ConstraintList,
|
int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList,
|
||||||
bool withDiagnose, int extGeoCount)
|
const std::vector<Constraint *> &ConstraintList,
|
||||||
|
int extGeoCount)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
@ -119,13 +120,11 @@ int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std:
|
||||||
addConstraints(ConstraintList);
|
addConstraints(ConstraintList);
|
||||||
|
|
||||||
GCSsys.clearByTag(-1);
|
GCSsys.clearByTag(-1);
|
||||||
GCSsys.clearByTag(-2);
|
GCSsys.declareUnknowns(Parameters);
|
||||||
GCSsys.initSolution(Parameters);
|
GCSsys.initSolution();
|
||||||
|
GCSsys.getConflicting(Conflicting);
|
||||||
if (withDiagnose)
|
GCSsys.getRedundant(Redundant);
|
||||||
return diagnose();
|
return GCSsys.dofsNumber();
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* nameByType(Sketch::GeoType type)
|
const char* nameByType(Sketch::GeoType type)
|
||||||
|
@ -744,10 +743,7 @@ int Sketch::addPointCoincidentConstraint(int geoId1, PointPos pos1, int geoId2,
|
||||||
GCS::Point &p1 = Points[pointId1];
|
GCS::Point &p1 = Points[pointId1];
|
||||||
GCS::Point &p2 = Points[pointId2];
|
GCS::Point &p2 = Points[pointId2];
|
||||||
int tag = ++ConstraintsCounter;
|
int tag = ++ConstraintsCounter;
|
||||||
// trick: we do not tag coincidence constraints in order to exclude
|
GCSsys.addConstraintP2PCoincident(p1, p2, tag);
|
||||||
// them from the diagnosing of conflicts
|
|
||||||
//GCSsys.addConstraintP2PCoincident(p1, p2, tag);
|
|
||||||
GCSsys.addConstraintP2PCoincident(p1, p2);
|
|
||||||
return ConstraintsCounter;
|
return ConstraintsCounter;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1569,7 +1565,6 @@ int Sketch::solve(void)
|
||||||
Base::TimeInfo start_time;
|
Base::TimeInfo start_time;
|
||||||
if (!isInitMove) { // make sure we are in single subsystem mode
|
if (!isInitMove) { // make sure we are in single subsystem mode
|
||||||
GCSsys.clearByTag(-1);
|
GCSsys.clearByTag(-1);
|
||||||
GCSsys.clearByTag(-2);
|
|
||||||
isFine = true;
|
isFine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1593,32 +1588,33 @@ int Sketch::solve(void)
|
||||||
break;
|
break;
|
||||||
case 3: // last resort: augment the system with a second subsystem and use the SQP solver
|
case 3: // last resort: augment the system with a second subsystem and use the SQP solver
|
||||||
solvername = "SQP(augmented system)";
|
solvername = "SQP(augmented system)";
|
||||||
GCSsys.clearByTag(-1);
|
|
||||||
GCSsys.clearByTag(-2);
|
|
||||||
InitParameters.resize(Parameters.size());
|
InitParameters.resize(Parameters.size());
|
||||||
int i=0;
|
int i=0;
|
||||||
for (std::vector<double*>::iterator it = Parameters.begin(); it != Parameters.end(); ++it, i++) {
|
for (std::vector<double*>::iterator it = Parameters.begin(); it != Parameters.end(); ++it, i++) {
|
||||||
InitParameters[i] = **it;
|
InitParameters[i] = **it;
|
||||||
GCSsys.addConstraintEqual(*it, &InitParameters[i], -2);
|
GCSsys.addConstraintEqual(*it, &InitParameters[i], -1);
|
||||||
}
|
}
|
||||||
GCSsys.initSolution(Parameters);
|
GCSsys.initSolution();
|
||||||
ret = GCSsys.solve(isFine);
|
ret = GCSsys.solve(isFine);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if successfully solved try write the parameters back
|
// if successfully solved try to write the parameters back
|
||||||
if (ret == GCS::Success) {
|
if (ret == GCS::Success) {
|
||||||
GCSsys.applySolution();
|
GCSsys.applySolution();
|
||||||
valid_solution = updateGeometry();
|
valid_solution = updateGeometry();
|
||||||
if (!valid_solution)
|
if (!valid_solution) {
|
||||||
|
GCSsys.undoSolution();
|
||||||
|
updateGeometry();
|
||||||
Base::Console().Warning("Invalid solution from %s solver.\n", solvername.c_str());
|
Base::Console().Warning("Invalid solution from %s solver.\n", solvername.c_str());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
valid_solution = false;
|
valid_solution = false;
|
||||||
//Base::Console().Log("NotSolved ");
|
//Base::Console().Log("NotSolved ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soltype == 3) // cleanup temporary constraints of the augmented system
|
if (soltype == 3) // cleanup temporary constraints of the augmented system
|
||||||
GCSsys.clearByTag(-2);
|
GCSsys.clearByTag(-1);
|
||||||
|
|
||||||
if (valid_solution) {
|
if (valid_solution) {
|
||||||
if (soltype == 1)
|
if (soltype == 1)
|
||||||
|
@ -1637,11 +1633,6 @@ int Sketch::solve(void)
|
||||||
}
|
}
|
||||||
} // soltype
|
} // soltype
|
||||||
|
|
||||||
if (!valid_solution) { // undo any changes
|
|
||||||
GCSsys.undoSolution();
|
|
||||||
updateGeometry();
|
|
||||||
}
|
|
||||||
|
|
||||||
Base::TimeInfo end_time;
|
Base::TimeInfo end_time;
|
||||||
//Base::Console().Log("T:%s\n",Base::TimeInfo::diffTime(start_time,end_time).c_str());
|
//Base::Console().Log("T:%s\n",Base::TimeInfo::diffTime(start_time,end_time).c_str());
|
||||||
SolveTime = Base::TimeInfo::diffTimeF(start_time,end_time);
|
SolveTime = Base::TimeInfo::diffTimeF(start_time,end_time);
|
||||||
|
@ -1655,7 +1646,6 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
||||||
geoId = checkGeoId(geoId);
|
geoId = checkGeoId(geoId);
|
||||||
|
|
||||||
GCSsys.clearByTag(-1);
|
GCSsys.clearByTag(-1);
|
||||||
GCSsys.clearByTag(-2);
|
|
||||||
|
|
||||||
// don't try to move sketches that contain conflicting constraints
|
// don't try to move sketches that contain conflicting constraints
|
||||||
if (hasConflicts()) {
|
if (hasConflicts()) {
|
||||||
|
@ -1760,7 +1750,7 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
||||||
}
|
}
|
||||||
InitParameters = MoveParameters;
|
InitParameters = MoveParameters;
|
||||||
|
|
||||||
GCSsys.initSolution(Parameters);
|
GCSsys.initSolution();
|
||||||
isInitMove = true;
|
isInitMove = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1838,18 +1828,6 @@ Base::Vector3d Sketch::getPoint(int geoId, PointPos pos)
|
||||||
return Base::Vector3d();
|
return Base::Vector3d();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sketch::diagnose(void)
|
|
||||||
{
|
|
||||||
Conflicting.clear();
|
|
||||||
if (GCSsys.isInit()) {
|
|
||||||
int dofs = GCSsys.diagnose(Parameters, Conflicting);
|
|
||||||
return dofs;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TopoShape Sketch::toShape(void) const
|
TopoShape Sketch::toShape(void) const
|
||||||
|
|
|
@ -53,9 +53,21 @@ public:
|
||||||
int solve(void);
|
int solve(void);
|
||||||
/// delete all geometry and constraints, leave an empty sketch
|
/// delete all geometry and constraints, leave an empty sketch
|
||||||
void clear(void);
|
void clear(void);
|
||||||
/// set the sketch up with geoms and constraints
|
/** set the sketch up with geoms and constraints
|
||||||
|
*
|
||||||
|
* returns the degree of freedom of a sketch and calculates a list of
|
||||||
|
* conflicting constraints
|
||||||
|
*
|
||||||
|
* 0 degrees of freedom correspond to a fully constrained sketch
|
||||||
|
* -1 degrees of freedom correspond to an over-constrained sketch
|
||||||
|
* positive degrees of freedom correspond to an under-constrained sketch
|
||||||
|
*
|
||||||
|
* an over-constrained sketch will always contain conflicting constraints
|
||||||
|
* a fully constrained or under-constrained sketch may contain conflicting
|
||||||
|
* constraints or may not
|
||||||
|
*/
|
||||||
int setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Constraint *> &ConstraintList,
|
int setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Constraint *> &ConstraintList,
|
||||||
bool withDiagnose=true, int extGeoCount=0);
|
int extGeoCount=0);
|
||||||
/// return the actual geometry of the sketch a TopoShape
|
/// return the actual geometry of the sketch a TopoShape
|
||||||
Part::TopoShape toShape(void) const;
|
Part::TopoShape toShape(void) const;
|
||||||
/// add unspecified geometry
|
/// add unspecified geometry
|
||||||
|
@ -71,20 +83,10 @@ public:
|
||||||
/// retrieves a point
|
/// retrieves a point
|
||||||
Base::Vector3d getPoint(int geoId, PointPos pos);
|
Base::Vector3d getPoint(int geoId, PointPos pos);
|
||||||
|
|
||||||
/** returns the degree of freedom of a sketch and calculates a list of
|
bool hasConflicts(void) const { return (Conflicting.size() > 0); }
|
||||||
* conflicting constraints
|
const std::vector<int> &getConflicting(void) const { return Conflicting; }
|
||||||
*
|
bool hasRedundancies(void) const { return (Redundant.size() > 0); }
|
||||||
* 0 degrees of freedom correspond to a fully constrained sketch
|
const std::vector<int> &getRedundant(void) const { return Redundant; }
|
||||||
* -1 degrees of freedom correspond to an over-constrained sketch
|
|
||||||
* positive degrees of freedom correspond to an under-constrained sketch
|
|
||||||
*
|
|
||||||
* an over-constrained sketch will always contain conflicting constraints
|
|
||||||
* a fully constrained or under-constrained sketch may contain conflicting
|
|
||||||
* constraints or may not
|
|
||||||
*/
|
|
||||||
int diagnose(void);
|
|
||||||
bool hasConflicts(void) const { return (Conflicting.size() > 0); };
|
|
||||||
const std::vector<int> &getConflicting(void) const { return Conflicting; };
|
|
||||||
|
|
||||||
/** set the datum of a distance or angle constraint to a certain value and solve
|
/** set the datum of a distance or angle constraint to a certain value and solve
|
||||||
* This can cause the solving to fail!
|
* This can cause the solving to fail!
|
||||||
|
@ -201,6 +203,7 @@ protected:
|
||||||
GCS::System GCSsys;
|
GCS::System GCSsys;
|
||||||
int ConstraintsCounter;
|
int ConstraintsCounter;
|
||||||
std::vector<int> Conflicting;
|
std::vector<int> Conflicting;
|
||||||
|
std::vector<int> Redundant;
|
||||||
|
|
||||||
// solving parameters
|
// solving parameters
|
||||||
std::vector<double*> Parameters; // with memory allocation
|
std::vector<double*> Parameters; // with memory allocation
|
||||||
|
|
|
@ -97,7 +97,7 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
|
||||||
rebuildExternalGeometry();
|
rebuildExternalGeometry();
|
||||||
Sketch sketch;
|
Sketch sketch;
|
||||||
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
||||||
true, getExternalGeometryCount());
|
getExternalGeometryCount());
|
||||||
if (dofs < 0) { // over-constrained sketch
|
if (dofs < 0) { // over-constrained sketch
|
||||||
std::string msg="Over-constrained sketch\n";
|
std::string msg="Over-constrained sketch\n";
|
||||||
appendConflictMsg(sketch.getConflicting(), msg);
|
appendConflictMsg(sketch.getConflicting(), msg);
|
||||||
|
@ -108,6 +108,11 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
|
||||||
appendConflictMsg(sketch.getConflicting(), msg);
|
appendConflictMsg(sketch.getConflicting(), msg);
|
||||||
return new App::DocumentObjectExecReturn(msg.c_str(),this);
|
return new App::DocumentObjectExecReturn(msg.c_str(),this);
|
||||||
}
|
}
|
||||||
|
if (sketch.hasRedundancies()) { // redundant constraints
|
||||||
|
std::string msg="Sketch with redundant constraints\n";
|
||||||
|
appendRedundantMsg(sketch.getRedundant(), msg);
|
||||||
|
return new App::DocumentObjectExecReturn(msg.c_str(),this);
|
||||||
|
}
|
||||||
|
|
||||||
// solve the sketch
|
// solve the sketch
|
||||||
if (sketch.solve() != 0)
|
if (sketch.solve() != 0)
|
||||||
|
@ -128,7 +133,7 @@ int SketchObject::hasConflicts(void) const
|
||||||
// set up a sketch (including dofs counting and diagnosing of conflicts)
|
// set up a sketch (including dofs counting and diagnosing of conflicts)
|
||||||
Sketch sketch;
|
Sketch sketch;
|
||||||
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
||||||
true, getExternalGeometryCount());
|
getExternalGeometryCount());
|
||||||
if (dofs < 0) // over-constrained sketch
|
if (dofs < 0) // over-constrained sketch
|
||||||
return -2;
|
return -2;
|
||||||
if (sketch.hasConflicts()) // conflicting constraints
|
if (sketch.hasConflicts()) // conflicting constraints
|
||||||
|
@ -166,7 +171,7 @@ int SketchObject::setDatum(int ConstrId, double Datum)
|
||||||
// set up a sketch (including dofs counting and diagnosing of conflicts)
|
// set up a sketch (including dofs counting and diagnosing of conflicts)
|
||||||
Sketch sketch;
|
Sketch sketch;
|
||||||
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
||||||
true, getExternalGeometryCount());
|
getExternalGeometryCount());
|
||||||
int err=0;
|
int err=0;
|
||||||
if (dofs < 0) // over-constrained sketch
|
if (dofs < 0) // over-constrained sketch
|
||||||
err = -3;
|
err = -3;
|
||||||
|
@ -192,7 +197,7 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP
|
||||||
{
|
{
|
||||||
Sketch sketch;
|
Sketch sketch;
|
||||||
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
||||||
true, getExternalGeometryCount());
|
getExternalGeometryCount());
|
||||||
if (dofs < 0) // over-constrained sketch
|
if (dofs < 0) // over-constrained sketch
|
||||||
return -1;
|
return -1;
|
||||||
if (sketch.hasConflicts()) // conflicting constraints
|
if (sketch.hasConflicts()) // conflicting constraints
|
||||||
|
@ -1388,10 +1393,32 @@ void SketchObject::appendConflictMsg(const std::vector<int> &conflicting, std::s
|
||||||
if (msg.length() > 0)
|
if (msg.length() > 0)
|
||||||
ss << msg;
|
ss << msg;
|
||||||
if (conflicting.size() > 0) {
|
if (conflicting.size() > 0) {
|
||||||
ss << "Please remove at least one of the constraints (" << conflicting[0];
|
if (conflicting.size() == 1)
|
||||||
|
ss << "Please remove the following constraint:\n";
|
||||||
|
else
|
||||||
|
ss << "Please remove at least one of the following constraints:\n";
|
||||||
|
ss << conflicting[0];
|
||||||
for (unsigned int i=1; i < conflicting.size(); i++)
|
for (unsigned int i=1; i < conflicting.size(); i++)
|
||||||
ss << ", " << conflicting[i];
|
ss << ", " << conflicting[i];
|
||||||
ss << ")\n";
|
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();
|
msg = ss.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,8 @@ public:
|
||||||
|
|
||||||
/// generates a warning message about constraint conflicts and appends it to the given message
|
/// generates a warning message about constraint conflicts and appends it to the given message
|
||||||
static void appendConflictMsg(const std::vector<int> &conflicting, std::string &msg);
|
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);
|
||||||
|
|
||||||
// from base class
|
// from base class
|
||||||
virtual PyObject *getPyObject(void);
|
virtual PyObject *getPyObject(void);
|
||||||
|
|
|
@ -41,19 +41,20 @@ typedef boost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> Gra
|
||||||
|
|
||||||
// System
|
// System
|
||||||
System::System()
|
System::System()
|
||||||
: clist(0),
|
: plist(0), clist(0),
|
||||||
c2p(), p2c(),
|
c2p(), p2c(),
|
||||||
subsyslist(0),
|
subSystems(0), subSystemsAux(0),
|
||||||
reference(),
|
reference(0),
|
||||||
init(false)
|
hasUnknowns(false), hasDiagnosis(false), isInit(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
System::System(std::vector<Constraint *> clist_)
|
System::System(std::vector<Constraint *> clist_)
|
||||||
: c2p(), p2c(),
|
: plist(0),
|
||||||
subsyslist(0),
|
c2p(), p2c(),
|
||||||
reference(),
|
subSystems(0), subSystemsAux(0),
|
||||||
init(false)
|
reference(0),
|
||||||
|
hasUnknowns(false), hasDiagnosis(false), isInit(false)
|
||||||
{
|
{
|
||||||
// create own (shallow) copy of constraints
|
// create own (shallow) copy of constraints
|
||||||
for (std::vector<Constraint *>::iterator constr=clist_.begin();
|
for (std::vector<Constraint *>::iterator constr=clist_.begin();
|
||||||
|
@ -125,7 +126,16 @@ System::~System()
|
||||||
|
|
||||||
void System::clear()
|
void System::clear()
|
||||||
{
|
{
|
||||||
clearReference();
|
plist.clear();
|
||||||
|
pIndex.clear();
|
||||||
|
hasUnknowns = false;
|
||||||
|
hasDiagnosis = false;
|
||||||
|
|
||||||
|
redundant.clear();
|
||||||
|
conflictingTags.clear();
|
||||||
|
redundantTags.clear();
|
||||||
|
|
||||||
|
reference.clear();
|
||||||
clearSubSystems();
|
clearSubSystems();
|
||||||
free(clist);
|
free(clist);
|
||||||
c2p.clear();
|
c2p.clear();
|
||||||
|
@ -148,7 +158,9 @@ void System::clearByTag(int tagId)
|
||||||
|
|
||||||
int System::addConstraint(Constraint *constr)
|
int System::addConstraint(Constraint *constr)
|
||||||
{
|
{
|
||||||
clearReference();
|
isInit = false;
|
||||||
|
if (constr->getTag() >= 0) // negatively tagged constraints have no impact
|
||||||
|
hasDiagnosis = false; // on the diagnosis
|
||||||
|
|
||||||
clist.push_back(constr);
|
clist.push_back(constr);
|
||||||
VEC_pD constr_params = constr->params();
|
VEC_pD constr_params = constr->params();
|
||||||
|
@ -163,12 +175,15 @@ int System::addConstraint(Constraint *constr)
|
||||||
|
|
||||||
void System::removeConstraint(Constraint *constr)
|
void System::removeConstraint(Constraint *constr)
|
||||||
{
|
{
|
||||||
clearReference();
|
|
||||||
clearSubSystems();
|
|
||||||
|
|
||||||
std::vector<Constraint *>::iterator it;
|
std::vector<Constraint *>::iterator it;
|
||||||
it = std::find(clist.begin(), clist.end(), constr);
|
it = std::find(clist.begin(), clist.end(), constr);
|
||||||
|
if (it == clist.end())
|
||||||
|
return;
|
||||||
|
|
||||||
clist.erase(it);
|
clist.erase(it);
|
||||||
|
if (constr->getTag() >= 0)
|
||||||
|
hasDiagnosis = false;
|
||||||
|
clearSubSystems();
|
||||||
|
|
||||||
VEC_pD constr_params = c2p[constr];
|
VEC_pD constr_params = c2p[constr];
|
||||||
for (VEC_pD::const_iterator param=constr_params.begin();
|
for (VEC_pD::const_iterator param=constr_params.begin();
|
||||||
|
@ -545,9 +560,18 @@ void System::rescaleConstraint(int id, double coeff)
|
||||||
clist[id]->rescale(coeff);
|
clist[id]->rescale(coeff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void System::declareUnknowns(VEC_pD ¶ms)
|
||||||
void System::initSolution(VEC_pD ¶ms)
|
|
||||||
{
|
{
|
||||||
|
plist = params;
|
||||||
|
pIndex.clear();
|
||||||
|
for (int i=0; i < int(plist.size()); ++i)
|
||||||
|
pIndex[plist[i]] = i;
|
||||||
|
hasUnknowns = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::initSolution()
|
||||||
|
{
|
||||||
|
// - Stores the current parameters values in the vector "reference"
|
||||||
// - identifies any decoupled subsystems and partitions the original
|
// - identifies any decoupled subsystems and partitions the original
|
||||||
// system into corresponding components
|
// system into corresponding components
|
||||||
// - Stores the current parameters in the vector "reference"
|
// - Stores the current parameters in the vector "reference"
|
||||||
|
@ -556,18 +580,38 @@ void System::initSolution(VEC_pD ¶ms)
|
||||||
// - Organizes the rest of constraints into two subsystems for
|
// - Organizes the rest of constraints into two subsystems for
|
||||||
// tag ids >=0 and < 0 respectively and applies the
|
// tag ids >=0 and < 0 respectively and applies the
|
||||||
// system reduction specified in the previous step
|
// system reduction specified in the previous step
|
||||||
MAP_pD_I pIndex;
|
|
||||||
for (int i=0; i < int(params.size()); ++i)
|
isInit = false;
|
||||||
pIndex[params[i]] = i;
|
if (!hasUnknowns)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// storing reference configuration
|
||||||
|
setReference();
|
||||||
|
|
||||||
|
// diagnose conflicting or redundant constraints
|
||||||
|
if (!hasDiagnosis) {
|
||||||
|
diagnose();
|
||||||
|
if (!hasDiagnosis)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::vector<Constraint *> clistR;
|
||||||
|
if (redundant.size()) {
|
||||||
|
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
|
||||||
|
constr != clist.end(); ++constr)
|
||||||
|
if (redundant.count(*constr) == 0)
|
||||||
|
clistR.push_back(*constr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
clistR = clist;
|
||||||
|
|
||||||
// partitioning into decoupled components
|
// partitioning into decoupled components
|
||||||
Graph g;
|
Graph g;
|
||||||
for (int i=0; i < int(params.size() + clist.size()); i++)
|
for (int i=0; i < int(plist.size() + clistR.size()); i++)
|
||||||
boost::add_vertex(g);
|
boost::add_vertex(g);
|
||||||
|
|
||||||
int cvtid = int(params.size());
|
int cvtid = int(plist.size());
|
||||||
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
|
for (std::vector<Constraint *>::const_iterator constr=clistR.begin();
|
||||||
constr != clist.end(); ++constr, cvtid++) {
|
constr != clistR.end(); ++constr, cvtid++) {
|
||||||
VEC_pD &cparams = c2p[*constr];
|
VEC_pD &cparams = c2p[*constr];
|
||||||
for (VEC_pD::const_iterator param=cparams.begin();
|
for (VEC_pD::const_iterator param=cparams.begin();
|
||||||
param != cparams.end(); ++param) {
|
param != cparams.end(); ++param) {
|
||||||
|
@ -580,113 +624,131 @@ void System::initSolution(VEC_pD ¶ms)
|
||||||
VEC_I components(boost::num_vertices(g));
|
VEC_I components(boost::num_vertices(g));
|
||||||
int componentsSize = boost::connected_components(g, &components[0]);
|
int componentsSize = boost::connected_components(g, &components[0]);
|
||||||
|
|
||||||
clearReference();
|
|
||||||
for (VEC_pD::const_iterator param=params.begin();
|
|
||||||
param != params.end(); ++param)
|
|
||||||
reference[*param] = **param;
|
|
||||||
|
|
||||||
// identification of equality constraints and parameter reduction
|
// identification of equality constraints and parameter reduction
|
||||||
std::set<Constraint *> eliminated; // constraints that will be eliminated through reduction
|
std::set<Constraint *> reducedConstrs; // constraints that will be eliminated through reduction
|
||||||
reductionmap.clear();
|
reductionmaps.clear(); // destroy any maps
|
||||||
|
reductionmaps.resize(componentsSize); // create empty maps to be filled in
|
||||||
{
|
{
|
||||||
VEC_pD reduced_params=params;
|
VEC_pD reducedParams=plist;
|
||||||
|
|
||||||
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
|
for (std::vector<Constraint *>::const_iterator constr=clistR.begin();
|
||||||
constr != clist.end(); ++constr) {
|
constr != clistR.end(); ++constr) {
|
||||||
if ((*constr)->getTag() >= 0 && (*constr)->getTypeId() == Equal) {
|
if ((*constr)->getTag() >= 0 && (*constr)->getTypeId() == Equal) {
|
||||||
MAP_pD_I::const_iterator it1,it2;
|
MAP_pD_I::const_iterator it1,it2;
|
||||||
it1 = pIndex.find((*constr)->params()[0]);
|
it1 = pIndex.find((*constr)->params()[0]);
|
||||||
it2 = pIndex.find((*constr)->params()[1]);
|
it2 = pIndex.find((*constr)->params()[1]);
|
||||||
if (it1 != pIndex.end() && it2 != pIndex.end()) {
|
if (it1 != pIndex.end() && it2 != pIndex.end()) {
|
||||||
eliminated.insert(*constr);
|
reducedConstrs.insert(*constr);
|
||||||
double *p_kept = reduced_params[it1->second];
|
double *p_kept = reducedParams[it1->second];
|
||||||
double *p_replaced = reduced_params[it2->second];
|
double *p_replaced = reducedParams[it2->second];
|
||||||
for (int i=0; i < int(params.size()); ++i)
|
for (int i=0; i < int(plist.size()); ++i)
|
||||||
if (reduced_params[i] == p_replaced)
|
if (reducedParams[i] == p_replaced)
|
||||||
reduced_params[i] = p_kept;
|
reducedParams[i] = p_kept;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i < int(params.size()); ++i)
|
for (int i=0; i < int(plist.size()); ++i)
|
||||||
if (params[i] != reduced_params[i])
|
if (plist[i] != reducedParams[i]) {
|
||||||
reductionmap[params[i]] = reduced_params[i];
|
int cid = components[i];
|
||||||
|
reductionmaps[cid][plist[i]] = reducedParams[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< std::vector<Constraint *> > clists0(componentsSize),
|
clists.clear(); // destroy any lists
|
||||||
clists1(componentsSize),
|
clists.resize(componentsSize); // create empty lists to be filled in
|
||||||
clists2(componentsSize);
|
int i = int(plist.size());
|
||||||
int i = int(params.size());
|
for (std::vector<Constraint *>::const_iterator constr=clistR.begin();
|
||||||
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
|
constr != clistR.end(); ++constr, i++) {
|
||||||
constr != clist.end(); ++constr, i++) {
|
if (reducedConstrs.count(*constr) == 0) {
|
||||||
if (eliminated.count(*constr) == 0) {
|
int cid = components[i];
|
||||||
int id = components[i];
|
clists[cid].push_back(*constr);
|
||||||
if ((*constr)->getTag() >= 0)
|
|
||||||
clists0[id].push_back(*constr);
|
|
||||||
else if ((*constr)->getTag() == -1) // move constraints
|
|
||||||
clists1[id].push_back(*constr);
|
|
||||||
else // distance from reference constraints
|
|
||||||
clists2[id].push_back(*constr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< std::vector<double *> > plists(componentsSize);
|
plists.clear(); // destroy any lists
|
||||||
for (int i=0; i < int(params.size()); ++i) {
|
plists.resize(componentsSize); // create empty lists to be filled in
|
||||||
int id = components[i];
|
for (int i=0; i < int(plist.size()); ++i) {
|
||||||
plists[id].push_back(params[i]);
|
int cid = components[i];
|
||||||
|
plists[cid].push_back(plist[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculates subSystems and subSystemsAux from clists, plists and reductionmaps
|
||||||
clearSubSystems();
|
clearSubSystems();
|
||||||
for (int cid=0; cid < componentsSize; cid++) {
|
for (int cid=0; cid < clists.size(); cid++) {
|
||||||
subsyslist.push_back(std::vector<SubSystem *>(0));
|
std::vector<Constraint *> clist0, clist1;
|
||||||
if (clists0[cid].size() > 0)
|
for (std::vector<Constraint *>::const_iterator constr=clists[cid].begin();
|
||||||
subsyslist[cid].push_back(new SubSystem(clists0[cid], plists[cid], reductionmap));
|
constr != clists[cid].end(); ++constr) {
|
||||||
if (clists1[cid].size() > 0)
|
if ((*constr)->getTag() >= 0)
|
||||||
subsyslist[cid].push_back(new SubSystem(clists1[cid], plists[cid], reductionmap));
|
clist0.push_back(*constr);
|
||||||
if (clists2[cid].size() > 0)
|
else // move or distance from reference constraints
|
||||||
subsyslist[cid].push_back(new SubSystem(clists2[cid], plists[cid], reductionmap));
|
clist1.push_back(*constr);
|
||||||
|
}
|
||||||
|
|
||||||
|
subSystems.push_back(NULL);
|
||||||
|
subSystemsAux.push_back(NULL);
|
||||||
|
if (clist0.size() > 0)
|
||||||
|
subSystems[cid] = new SubSystem(clist0, plists[cid], reductionmaps[cid]);
|
||||||
|
if (clist1.size() > 0)
|
||||||
|
subSystemsAux[cid] = new SubSystem(clist1, plists[cid], reductionmaps[cid]);
|
||||||
}
|
}
|
||||||
init = true;
|
|
||||||
|
isInit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::clearReference()
|
void System::setReference()
|
||||||
{
|
{
|
||||||
init = false;
|
|
||||||
reference.clear();
|
reference.clear();
|
||||||
|
reference.reserve(plist.size());
|
||||||
|
for (VEC_pD::const_iterator param=plist.begin();
|
||||||
|
param != plist.end(); ++param)
|
||||||
|
reference.push_back(**param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::resetToReference()
|
void System::resetToReference()
|
||||||
{
|
{
|
||||||
for (MAP_pD_D::const_iterator it=reference.begin();
|
if (reference.size() == plist.size()) {
|
||||||
it != reference.end(); ++it)
|
VEC_D::const_iterator ref=reference.begin();
|
||||||
*(it->first) = it->second;
|
VEC_pD::iterator param=plist.begin();
|
||||||
|
for (; ref != reference.end(); ++ref, ++param)
|
||||||
|
**param = *ref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int System::solve(VEC_pD ¶ms, bool isFine, Algorithm alg)
|
int System::solve(VEC_pD ¶ms, bool isFine, Algorithm alg)
|
||||||
{
|
{
|
||||||
initSolution(params);
|
declareUnknowns(params);
|
||||||
|
initSolution();
|
||||||
return solve(isFine, alg);
|
return solve(isFine, alg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int System::solve(bool isFine, Algorithm alg)
|
int System::solve(bool isFine, Algorithm alg)
|
||||||
{
|
{
|
||||||
|
if (!isInit)
|
||||||
|
return Failed;
|
||||||
|
|
||||||
bool isReset = false;
|
bool isReset = false;
|
||||||
// return success by default in order to permit coincidence constraints to be applied
|
// return success by default in order to permit coincidence constraints to be applied
|
||||||
// even if no other system has to be solved
|
// even if no other system has to be solved
|
||||||
int res = Success;
|
int res = Success;
|
||||||
for (int cid=0; cid < int(subsyslist.size()); cid++) {
|
for (int cid=0; cid < int(subSystems.size()); cid++) {
|
||||||
if (subsyslist[cid].size() > 0 && !isReset) {
|
if ((subSystems[cid] || subSystemsAux[cid]) && !isReset) {
|
||||||
resetToReference();
|
resetToReference();
|
||||||
isReset = true;
|
isReset = true;
|
||||||
}
|
}
|
||||||
if (subsyslist[cid].size() == 1)
|
if (subSystems[cid] && subSystemsAux[cid])
|
||||||
res = std::max(res, solve(subsyslist[cid][0], isFine, alg));
|
res = std::max(res, solve(subSystems[cid], subSystemsAux[cid], isFine));
|
||||||
else if (subsyslist[cid].size() == 2)
|
else if (subSystems[cid])
|
||||||
res = std::max(res, solve(subsyslist[cid][0], subsyslist[cid][1], isFine));
|
res = std::max(res, solve(subSystems[cid], isFine, alg));
|
||||||
else if (subsyslist[cid].size() > 2)
|
else if (subSystemsAux[cid])
|
||||||
// subsystem 1 has higher priority than subsystems 2,3,...
|
res = std::max(res, solve(subSystemsAux[cid], isFine, alg));
|
||||||
// these subsystems act like a preconditioner
|
}
|
||||||
for (int i=subsyslist[cid].size()-1; i > 0; i--)
|
if (res == Success) {
|
||||||
res = std::max(res, solve(subsyslist[cid][0], subsyslist[cid][i], isFine));
|
for (std::set<Constraint *>::const_iterator constr=redundant.begin();
|
||||||
|
constr != redundant.end(); constr++)
|
||||||
|
if ((*constr)->error() > XconvergenceFine) {
|
||||||
|
res = Converged;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1068,7 +1130,7 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
int xsizeB = subsysB->pSize();
|
int xsizeB = subsysB->pSize();
|
||||||
int csizeA = subsysA->cSize();
|
int csizeA = subsysA->cSize();
|
||||||
|
|
||||||
VEC_pD plist(xsizeA+xsizeB);
|
VEC_pD plistAB(xsizeA+xsizeB);
|
||||||
{
|
{
|
||||||
VEC_pD plistA, plistB;
|
VEC_pD plistA, plistB;
|
||||||
subsysA->getParamList(plistA);
|
subsysA->getParamList(plistA);
|
||||||
|
@ -1079,10 +1141,10 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
|
|
||||||
VEC_pD::const_iterator it;
|
VEC_pD::const_iterator it;
|
||||||
it = std::set_union(plistA.begin(),plistA.end(),
|
it = std::set_union(plistA.begin(),plistA.end(),
|
||||||
plistB.begin(),plistB.end(),plist.begin());
|
plistB.begin(),plistB.end(),plistAB.begin());
|
||||||
plist.resize(it-plist.begin());
|
plistAB.resize(it-plistAB.begin());
|
||||||
}
|
}
|
||||||
int xsize = plist.size();
|
int xsize = plistAB.size();
|
||||||
|
|
||||||
Eigen::MatrixXd B = Eigen::MatrixXd::Identity(xsize, xsize);
|
Eigen::MatrixXd B = Eigen::MatrixXd::Identity(xsize, xsize);
|
||||||
Eigen::MatrixXd JA(csizeA, xsize);
|
Eigen::MatrixXd JA(csizeA, xsize);
|
||||||
|
@ -1100,12 +1162,12 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
subsysA->redirectParams();
|
subsysA->redirectParams();
|
||||||
subsysB->redirectParams();
|
subsysB->redirectParams();
|
||||||
|
|
||||||
subsysB->getParams(plist,x);
|
subsysB->getParams(plistAB,x);
|
||||||
subsysA->getParams(plist,x);
|
subsysA->getParams(plistAB,x);
|
||||||
subsysB->setParams(plist,x); // just to ensure that A and B are synchronized
|
subsysB->setParams(plistAB,x); // just to ensure that A and B are synchronized
|
||||||
|
|
||||||
subsysB->calcGrad(plist,grad);
|
subsysB->calcGrad(plistAB,grad);
|
||||||
subsysA->calcJacobi(plist,JA);
|
subsysA->calcJacobi(plistAB,JA);
|
||||||
subsysA->calcResidual(resA);
|
subsysA->calcResidual(resA);
|
||||||
|
|
||||||
double convergence = isFine ? XconvergenceFine : XconvergenceRough;
|
double convergence = isFine ? XconvergenceFine : XconvergenceRough;
|
||||||
|
@ -1130,7 +1192,7 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
double tau=0.5;
|
double tau=0.5;
|
||||||
double rho=0.5;
|
double rho=0.5;
|
||||||
double alpha=1;
|
double alpha=1;
|
||||||
alpha = std::min(alpha, subsysA->maxStep(plist,xdir));
|
alpha = std::min(alpha, subsysA->maxStep(plistAB,xdir));
|
||||||
|
|
||||||
// Eq. 18.32
|
// Eq. 18.32
|
||||||
// double mu = lambda.lpNorm<Eigen::Infinity>() + 0.01;
|
// double mu = lambda.lpNorm<Eigen::Infinity>() + 0.01;
|
||||||
|
@ -1148,8 +1210,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
double deriv = grad.dot(xdir) - mu * resA.lpNorm<1>();
|
double deriv = grad.dot(xdir) - mu * resA.lpNorm<1>();
|
||||||
|
|
||||||
x = x0 + alpha * xdir;
|
x = x0 + alpha * xdir;
|
||||||
subsysA->setParams(plist,x);
|
subsysA->setParams(plistAB,x);
|
||||||
subsysB->setParams(plist,x);
|
subsysB->setParams(plistAB,x);
|
||||||
subsysA->calcResidual(resA);
|
subsysA->calcResidual(resA);
|
||||||
double f = subsysB->error() + mu * resA.lpNorm<1>();
|
double f = subsysB->error() + mu * resA.lpNorm<1>();
|
||||||
|
|
||||||
|
@ -1161,8 +1223,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
// Eigen::ComputeThinV).solve(-resA);
|
// Eigen::ComputeThinV).solve(-resA);
|
||||||
xdir1 = -Y*resA;
|
xdir1 = -Y*resA;
|
||||||
x += xdir1; // = x0 + alpha * xdir + xdir1
|
x += xdir1; // = x0 + alpha * xdir + xdir1
|
||||||
subsysA->setParams(plist,x);
|
subsysA->setParams(plistAB,x);
|
||||||
subsysB->setParams(plist,x);
|
subsysB->setParams(plistAB,x);
|
||||||
subsysA->calcResidual(resA);
|
subsysA->calcResidual(resA);
|
||||||
f = subsysB->error() + mu * resA.lpNorm<1>();
|
f = subsysB->error() + mu * resA.lpNorm<1>();
|
||||||
if (f < f0 + eta * alpha * deriv)
|
if (f < f0 + eta * alpha * deriv)
|
||||||
|
@ -1172,8 +1234,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
if (alpha < 1e-8) // let the linesearch fail
|
if (alpha < 1e-8) // let the linesearch fail
|
||||||
alpha = 0.;
|
alpha = 0.;
|
||||||
x = x0 + alpha * xdir;
|
x = x0 + alpha * xdir;
|
||||||
subsysA->setParams(plist,x);
|
subsysA->setParams(plistAB,x);
|
||||||
subsysB->setParams(plist,x);
|
subsysB->setParams(plistAB,x);
|
||||||
subsysA->calcResidual(resA);
|
subsysA->calcResidual(resA);
|
||||||
f = subsysB->error() + mu * resA.lpNorm<1>();
|
f = subsysB->error() + mu * resA.lpNorm<1>();
|
||||||
if (alpha < 1e-8) // let the linesearch fail
|
if (alpha < 1e-8) // let the linesearch fail
|
||||||
|
@ -1186,8 +1248,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
|
|
||||||
y = grad - JA.transpose() * lambda;
|
y = grad - JA.transpose() * lambda;
|
||||||
{
|
{
|
||||||
subsysB->calcGrad(plist,grad);
|
subsysB->calcGrad(plistAB,grad);
|
||||||
subsysA->calcJacobi(plist,JA);
|
subsysA->calcJacobi(plistAB,JA);
|
||||||
subsysA->calcResidual(resA);
|
subsysA->calcResidual(resA);
|
||||||
}
|
}
|
||||||
y = grad - JA.transpose() * lambda - y; // Eq. 18.13
|
y = grad - JA.transpose() * lambda - y; // Eq. 18.13
|
||||||
|
@ -1225,13 +1287,15 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
|
||||||
|
|
||||||
void System::applySolution()
|
void System::applySolution()
|
||||||
{
|
{
|
||||||
for (int cid=0; cid < int(subsyslist.size()); cid++)
|
for (int cid=0; cid < int(subSystems.size()); cid++) {
|
||||||
for (int i=subsyslist[cid].size()-1; i >= 0; i--)
|
if (subSystemsAux[cid])
|
||||||
subsyslist[cid][i]->applySolution();
|
subSystemsAux[cid]->applySolution();
|
||||||
|
if (subSystems[cid])
|
||||||
for (MAP_pD_pD::const_iterator it=reductionmap.begin();
|
subSystems[cid]->applySolution();
|
||||||
it != reductionmap.end(); ++it)
|
for (MAP_pD_pD::const_iterator it=reductionmaps[cid].begin();
|
||||||
*(it->first) = *(it->second);
|
it != reductionmaps[cid].end(); ++it)
|
||||||
|
*(it->first) = *(it->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::undoSolution()
|
void System::undoSolution()
|
||||||
|
@ -1239,7 +1303,7 @@ void System::undoSolution()
|
||||||
resetToReference();
|
resetToReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags)
|
int System::diagnose()
|
||||||
{
|
{
|
||||||
// Analyses the constrainess grad of the system and provides feedback
|
// Analyses the constrainess grad of the system and provides feedback
|
||||||
// The vector "conflictingTags" will hold a group of conflicting constraints
|
// The vector "conflictingTags" will hold a group of conflicting constraints
|
||||||
|
@ -1251,22 +1315,24 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags)
|
||||||
// will provide no feedback about possible conflicts between
|
// will provide no feedback about possible conflicts between
|
||||||
// two high priority constraints. For this reason, tagging
|
// two high priority constraints. For this reason, tagging
|
||||||
// constraints with 0 should be used carefully.
|
// constraints with 0 should be used carefully.
|
||||||
if (!isInit())
|
hasDiagnosis = false;
|
||||||
return -1;
|
if (!hasUnknowns) {
|
||||||
|
dofs = -1;
|
||||||
|
return dofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
redundant.clear();
|
||||||
conflictingTags.clear();
|
conflictingTags.clear();
|
||||||
std::vector<VEC_I> conflictingIndex;
|
redundantTags.clear();
|
||||||
VEC_I tags;
|
Eigen::MatrixXd J(clist.size(), plist.size());
|
||||||
Eigen::MatrixXd J(clist.size(), params.size());
|
|
||||||
int count=0;
|
int count=0;
|
||||||
for (std::vector<Constraint *>::iterator constr=clist.begin();
|
for (std::vector<Constraint *>::iterator constr=clist.begin();
|
||||||
constr != clist.end(); ++constr) {
|
constr != clist.end(); ++constr) {
|
||||||
(*constr)->revertParams();
|
(*constr)->revertParams();
|
||||||
if ((*constr)->getTag() >= 0) {
|
if ((*constr)->getTag() >= 0) {
|
||||||
count++;
|
count++;
|
||||||
tags.push_back((*constr)->getTag());
|
for (int j=0; j < int(plist.size()); j++)
|
||||||
for (int j=0; j < int(params.size()); j++)
|
J(count-1,j) = (*constr)->grad(plist[j]);
|
||||||
J(count-1,j) = (*constr)->grad(params[j]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,7 +1350,7 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags)
|
||||||
R = qrJT.matrixQR().topRows(constrNum)
|
R = qrJT.matrixQR().topRows(constrNum)
|
||||||
.triangularView<Eigen::Upper>();
|
.triangularView<Eigen::Upper>();
|
||||||
|
|
||||||
if (constrNum > rank) { // conflicting constraints
|
if (constrNum > rank) { // conflicting or redundant constraints
|
||||||
for (int i=1; i < rank; i++) {
|
for (int i=1; i < rank; i++) {
|
||||||
// eliminate non zeros above pivot
|
// eliminate non zeros above pivot
|
||||||
assert(R(i,i) != 0);
|
assert(R(i,i) != 0);
|
||||||
|
@ -1296,43 +1362,142 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conflictingIndex.resize(constrNum-rank);
|
std::vector< std::vector<Constraint *> > conflictGroups(constrNum-rank);
|
||||||
for (int j=rank; j < constrNum; j++) {
|
for (int j=rank; j < constrNum; j++) {
|
||||||
for (int row=0; row < rank; row++) {
|
for (int row=0; row < rank; row++) {
|
||||||
if (fabs(R(row,j)) > 1e-10) {
|
if (fabs(R(row,j)) > 1e-10) {
|
||||||
int origCol = qrJT.colsPermutation().indices()[row];
|
int origCol = qrJT.colsPermutation().indices()[row];
|
||||||
conflictingIndex[j-rank].push_back(origCol);
|
conflictGroups[j-rank].push_back(clist[origCol]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int origCol = qrJT.colsPermutation().indices()[j];
|
int origCol = qrJT.colsPermutation().indices()[j];
|
||||||
conflictingIndex[j-rank].push_back(origCol);
|
conflictGroups[j-rank].push_back(clist[origCol]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_I tags_set;
|
// try to remove the conflicting constraints and solve the
|
||||||
for (int i=0; i < conflictingIndex.size(); i++) {
|
// system in order to check if the removed constraints were
|
||||||
for (int j=0; j < conflictingIndex[i].size(); j++) {
|
// just redundant but not really conflicting
|
||||||
tags_set.insert(tags[conflictingIndex[i][j]]);
|
std::set<Constraint *> skipped;
|
||||||
|
SET_I satisfiedGroups;
|
||||||
|
while (1) {
|
||||||
|
std::map< Constraint *, SET_I > conflictingMap;
|
||||||
|
for (int i=0; i < conflictGroups.size(); i++) {
|
||||||
|
if (satisfiedGroups.count(i) == 0) {
|
||||||
|
for (int j=0; j < conflictGroups[i].size(); j++) {
|
||||||
|
Constraint *constr = conflictGroups[i][j];
|
||||||
|
if (constr->getTag() != 0) // exclude constraints tagged with zero
|
||||||
|
conflictingMap[constr].insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (conflictingMap.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
int maxPopularity = 0;
|
||||||
|
Constraint *mostPopular = NULL;
|
||||||
|
for (std::map< Constraint *, SET_I >::const_iterator it=conflictingMap.begin();
|
||||||
|
it != conflictingMap.end(); it++) {
|
||||||
|
if (it->second.size() > maxPopularity ||
|
||||||
|
(it->second.size() == maxPopularity && mostPopular &&
|
||||||
|
it->first->getTag() > mostPopular->getTag())) {
|
||||||
|
mostPopular = it->first;
|
||||||
|
maxPopularity = it->second.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxPopularity > 0) {
|
||||||
|
skipped.insert(mostPopular);
|
||||||
|
for (SET_I::const_iterator it=conflictingMap[mostPopular].begin();
|
||||||
|
it != conflictingMap[mostPopular].end(); it++)
|
||||||
|
satisfiedGroups.insert(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tags_set.erase(0); // exclude constraints tagged with zero
|
|
||||||
conflictingTags.resize(tags_set.size());
|
|
||||||
std::copy(tags_set.begin(), tags_set.end(), conflictingTags.begin());
|
|
||||||
|
|
||||||
if (paramsNum == rank) // over-constrained
|
std::vector<Constraint *> clistTmp;
|
||||||
return paramsNum - constrNum;
|
clistTmp.reserve(clist.size());
|
||||||
|
for (std::vector<Constraint *>::iterator constr=clist.begin();
|
||||||
|
constr != clist.end(); ++constr)
|
||||||
|
if (skipped.count(*constr) == 0)
|
||||||
|
clistTmp.push_back(*constr);
|
||||||
|
|
||||||
|
SubSystem *subSysTmp = new SubSystem(clistTmp, plist);
|
||||||
|
int res = solve(subSysTmp);
|
||||||
|
if (res == Success) {
|
||||||
|
subSysTmp->applySolution();
|
||||||
|
for (std::set<Constraint *>::const_iterator constr=skipped.begin();
|
||||||
|
constr != skipped.end(); constr++) {
|
||||||
|
double err = (*constr)->error();
|
||||||
|
if (err * err < XconvergenceFine)
|
||||||
|
redundant.insert(*constr);
|
||||||
|
}
|
||||||
|
resetToReference();
|
||||||
|
|
||||||
|
std::vector< std::vector<Constraint *> > conflictGroupsOrig=conflictGroups;
|
||||||
|
conflictGroups.clear();
|
||||||
|
for (int i=conflictGroupsOrig.size()-1; i >= 0; i--) {
|
||||||
|
bool isRedundant = false;
|
||||||
|
for (int j=0; j < conflictGroupsOrig[i].size(); j++) {
|
||||||
|
if (redundant.count(conflictGroupsOrig[i][j]) > 0) {
|
||||||
|
isRedundant = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isRedundant)
|
||||||
|
conflictGroups.push_back(conflictGroupsOrig[i]);
|
||||||
|
else
|
||||||
|
constrNum--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete subSysTmp;
|
||||||
|
|
||||||
|
// simplified output of conflicting tags
|
||||||
|
SET_I conflictingTagsSet;
|
||||||
|
for (int i=0; i < conflictGroups.size(); i++) {
|
||||||
|
for (int j=0; j < conflictGroups[i].size(); j++) {
|
||||||
|
conflictingTagsSet.insert(conflictGroups[i][j]->getTag());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conflictingTagsSet.erase(0); // exclude constraints tagged with zero
|
||||||
|
conflictingTags.resize(conflictingTagsSet.size());
|
||||||
|
std::copy(conflictingTagsSet.begin(), conflictingTagsSet.end(),
|
||||||
|
conflictingTags.begin());
|
||||||
|
|
||||||
|
// output of redundant tags
|
||||||
|
SET_I redundantTagsSet;
|
||||||
|
for (std::set<Constraint *>::iterator constr=redundant.begin();
|
||||||
|
constr != redundant.end(); ++constr)
|
||||||
|
redundantTagsSet.insert((*constr)->getTag());
|
||||||
|
// remove tags represented at least in one non-redundant constraint
|
||||||
|
for (std::vector<Constraint *>::iterator constr=clist.begin();
|
||||||
|
constr != clist.end(); ++constr)
|
||||||
|
if (redundant.count(*constr) == 0)
|
||||||
|
redundantTagsSet.erase((*constr)->getTag());
|
||||||
|
redundantTags.resize(redundantTagsSet.size());
|
||||||
|
std::copy(redundantTagsSet.begin(), redundantTagsSet.end(),
|
||||||
|
redundantTags.begin());
|
||||||
|
|
||||||
|
if (paramsNum == rank && constrNum > rank) { // over-constrained
|
||||||
|
hasDiagnosis = true;
|
||||||
|
dofs = paramsNum - constrNum;
|
||||||
|
return dofs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return paramsNum - rank;
|
hasDiagnosis = true;
|
||||||
|
dofs = paramsNum - rank;
|
||||||
|
return dofs;
|
||||||
}
|
}
|
||||||
return params.size();
|
hasDiagnosis = true;
|
||||||
|
dofs = plist.size();
|
||||||
|
return dofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::clearSubSystems()
|
void System::clearSubSystems()
|
||||||
{
|
{
|
||||||
init = false;
|
isInit = false;
|
||||||
for (int i=0; i < int(subsyslist.size()); i++)
|
free(subSystems);
|
||||||
free(subsyslist[i]);
|
free(subSystemsAux);
|
||||||
subsyslist.clear();
|
subSystems.clear();
|
||||||
|
subSystemsAux.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir)
|
double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir)
|
||||||
|
|
|
@ -49,25 +49,31 @@ namespace GCS
|
||||||
// This is the main class. It holds all constraints and information
|
// This is the main class. It holds all constraints and information
|
||||||
// about partitioning into subsystems and solution strategies
|
// about partitioning into subsystems and solution strategies
|
||||||
private:
|
private:
|
||||||
std::vector<Constraint *> clist;
|
VEC_pD plist; // list of the unknown parameters
|
||||||
|
MAP_pD_I pIndex;
|
||||||
|
|
||||||
|
std::vector<Constraint *> clist;
|
||||||
std::map<Constraint *,VEC_pD > c2p; // constraint to parameter adjacency list
|
std::map<Constraint *,VEC_pD > c2p; // constraint to parameter adjacency list
|
||||||
std::map<double *,std::vector<Constraint *> > p2c; // parameter to constraint adjacency list
|
std::map<double *,std::vector<Constraint *> > p2c; // parameter to constraint adjacency list
|
||||||
|
|
||||||
// each row of subsyslist contains up to 3 subsystems.
|
std::vector<SubSystem *> subSystems, subSystemsAux;
|
||||||
// the first one has the highest priority, always used as the primary subsystem
|
|
||||||
// the second one is used as secondary subsystem
|
|
||||||
// the third one is used as secondary system and serves as a preconditioner
|
|
||||||
std::vector< std::vector<SubSystem *> > subsyslist;
|
|
||||||
void clearSubSystems();
|
void clearSubSystems();
|
||||||
|
|
||||||
MAP_pD_D reference;
|
VEC_D reference;
|
||||||
void clearReference();
|
void setReference(); // copies the current parameter values to reference
|
||||||
void resetToReference();
|
void resetToReference(); // reverts all parameter values to the stored reference
|
||||||
|
|
||||||
MAP_pD_pD reductionmap; // for simplification of equality constraints
|
std::vector< VEC_pD > plists; // partitioned plist except equality constraints
|
||||||
|
std::vector< std::vector<Constraint *> > clists; // partitioned clist except equality constraints
|
||||||
|
std::vector< MAP_pD_pD > reductionmaps; // for simplification of equality constraints
|
||||||
|
|
||||||
bool init;
|
int dofs;
|
||||||
|
std::set<Constraint *> redundant;
|
||||||
|
VEC_I conflictingTags, redundantTags;
|
||||||
|
|
||||||
|
bool hasUnknowns; // if plist is filled with the unknown parameters
|
||||||
|
bool hasDiagnosis; // if dofs, conflictingTags, redundantTags are up to date
|
||||||
|
bool isInit; // if plists, clists, reductionmaps are up to date
|
||||||
|
|
||||||
int solve_BFGS(SubSystem *subsys, bool isFine);
|
int solve_BFGS(SubSystem *subsys, bool isFine);
|
||||||
int solve_LM(SubSystem *subsys);
|
int solve_LM(SubSystem *subsys);
|
||||||
|
@ -147,7 +153,8 @@ namespace GCS
|
||||||
int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0);
|
int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0);
|
||||||
void rescaleConstraint(int id, double coeff);
|
void rescaleConstraint(int id, double coeff);
|
||||||
|
|
||||||
void initSolution(VEC_pD ¶ms);
|
void declareUnknowns(VEC_pD ¶ms);
|
||||||
|
void initSolution();
|
||||||
|
|
||||||
int solve(bool isFine=true, Algorithm alg=DogLeg);
|
int solve(bool isFine=true, Algorithm alg=DogLeg);
|
||||||
int solve(VEC_pD ¶ms, bool isFine=true, Algorithm alg=DogLeg);
|
int solve(VEC_pD ¶ms, bool isFine=true, Algorithm alg=DogLeg);
|
||||||
|
@ -157,9 +164,12 @@ namespace GCS
|
||||||
void applySolution();
|
void applySolution();
|
||||||
void undoSolution();
|
void undoSolution();
|
||||||
|
|
||||||
bool isInit() const { return init; }
|
int diagnose();
|
||||||
|
int dofsNumber() { return hasDiagnosis ? dofs : -1; }
|
||||||
int diagnose(VEC_pD ¶ms, VEC_I &conflictingTags);
|
void getConflicting(VEC_I &conflictingOut) const
|
||||||
|
{ conflictingOut = hasDiagnosis ? conflictingTags : VEC_I(0); }
|
||||||
|
void getRedundant(VEC_I &redundantOut) const
|
||||||
|
{ redundantOut = hasDiagnosis ? redundantTags : VEC_I(0); }
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
|
@ -54,8 +54,8 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch *sketchView)
|
||||||
|
|
||||||
this->groupLayout()->addWidget(proxy);
|
this->groupLayout()->addWidget(proxy);
|
||||||
|
|
||||||
connectionSetUp = sketchView->signalSetUp.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSetUp, this,_1,_2,_3));
|
connectionSetUp = sketchView->signalSetUp.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSetUp, this,_1));
|
||||||
connectionSolved = sketchView->signalSolved.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSolved, this,_1,_2));
|
connectionSolved = sketchView->signalSolved.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSolved, this,_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskSketcherMessages::~TaskSketcherMessages()
|
TaskSketcherMessages::~TaskSketcherMessages()
|
||||||
|
@ -65,43 +65,14 @@ TaskSketcherMessages::~TaskSketcherMessages()
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskSketcherMessages::slotSetUp(int type, int dofs, const std::string &msg)
|
void TaskSketcherMessages::slotSetUp(QString msg)
|
||||||
{
|
{
|
||||||
switch(type){
|
ui->labelConstrainStatus->setText(msg);
|
||||||
case -1:
|
|
||||||
ui->labelConstrainStatus->setText(QString::fromLatin1("Empty sketch"));
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
ui->labelConstrainStatus->setText(QString::fromLatin1("<font color='green'>Fully constrained sketch </font>"));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (dofs==1)
|
|
||||||
ui->labelConstrainStatus->setText(QString::fromLatin1("Under-constrained sketch with 1 degree of freedom"));
|
|
||||||
else
|
|
||||||
ui->labelConstrainStatus->setText(QString::fromLatin1("Under-constrained sketch with %1 degrees of freedom").arg(dofs));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ui->labelConstrainStatus->setText(QString::fromLatin1("<font color='red'>Sketch contains conflicting constraints<br/>%1</font>").arg(QString::fromStdString(msg)));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ui->labelConstrainStatus->setText(QString::fromLatin1("<font color='red'>Over-constrained sketch<br/>%1</font>").arg(QString::fromStdString(msg)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskSketcherMessages::slotSolved(int type, float time)
|
void TaskSketcherMessages::slotSolved(QString msg)
|
||||||
{
|
{
|
||||||
switch(type){
|
ui->labelSolverStatus->setText(msg);
|
||||||
case -1:
|
|
||||||
ui->labelSolverStatus->setText(QString());
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
ui->labelSolverStatus->setText(QString::fromLatin1("Solved in %1 sec").arg(time));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ui->labelSolverStatus->setText(QString::fromLatin1("Unsolved (%1)").arg(time));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_TaskSketcherMessages.cpp"
|
#include "moc_TaskSketcherMessages.cpp"
|
||||||
|
|
|
@ -47,8 +47,8 @@ public:
|
||||||
TaskSketcherMessages(ViewProviderSketch *sketchView);
|
TaskSketcherMessages(ViewProviderSketch *sketchView);
|
||||||
~TaskSketcherMessages();
|
~TaskSketcherMessages();
|
||||||
|
|
||||||
void slotSetUp(int type, int dofs, const std::string &msg);
|
void slotSetUp(QString msg);
|
||||||
void slotSolved(int type, float time);
|
void slotSolved(QString msg);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
|
||||||
|
|
|
@ -768,7 +768,7 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal,
|
||||||
int GeoId;
|
int GeoId;
|
||||||
Sketcher::PointPos PosId;
|
Sketcher::PointPos PosId;
|
||||||
getSketchObject()->getGeoVertexIndex(edit->DragPoint, GeoId, PosId);
|
getSketchObject()->getGeoVertexIndex(edit->DragPoint, GeoId, PosId);
|
||||||
edit->ActSketch.initMove(GeoId, PosId);
|
edit->ActSketch.initMove(GeoId, PosId, false);
|
||||||
relative = false;
|
relative = false;
|
||||||
xInit = 0;
|
xInit = 0;
|
||||||
yInit = 0;
|
yInit = 0;
|
||||||
|
@ -785,7 +785,7 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal,
|
||||||
edit->PreselectCurve != -1 && edit->DragCurve != edit->PreselectCurve) {
|
edit->PreselectCurve != -1 && edit->DragCurve != edit->PreselectCurve) {
|
||||||
Mode = STATUS_SKETCH_DragCurve;
|
Mode = STATUS_SKETCH_DragCurve;
|
||||||
edit->DragCurve = edit->PreselectCurve;
|
edit->DragCurve = edit->PreselectCurve;
|
||||||
edit->ActSketch.initMove(edit->DragCurve, Sketcher::none);
|
edit->ActSketch.initMove(edit->DragCurve, Sketcher::none, false);
|
||||||
const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve);
|
const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve);
|
||||||
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||||
relative = true;
|
relative = true;
|
||||||
|
@ -822,9 +822,9 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal,
|
||||||
if (edit->ActSketch.movePoint(GeoId, PosId, vec, relative) == 0) {
|
if (edit->ActSketch.movePoint(GeoId, PosId, vec, relative) == 0) {
|
||||||
setPositionText(Base::Vector2D(x,y));
|
setPositionText(Base::Vector2D(x,y));
|
||||||
draw(true);
|
draw(true);
|
||||||
signalSolved(0, edit->ActSketch.SolveTime);
|
signalSolved(QString::fromLatin1("Solved in %1 sec").arg(edit->ActSketch.SolveTime));
|
||||||
} else {
|
} else {
|
||||||
signalSolved(1, edit->ActSketch.SolveTime);
|
signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(edit->ActSketch.SolveTime));
|
||||||
//Base::Console().Log("Error solving:%d\n",ret);
|
//Base::Console().Log("Error solving:%d\n",ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -835,9 +835,9 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal,
|
||||||
if (edit->ActSketch.movePoint(edit->DragCurve, Sketcher::none, vec, relative) == 0) {
|
if (edit->ActSketch.movePoint(edit->DragCurve, Sketcher::none, vec, relative) == 0) {
|
||||||
setPositionText(Base::Vector2D(x,y));
|
setPositionText(Base::Vector2D(x,y));
|
||||||
draw(true);
|
draw(true);
|
||||||
signalSolved(0, edit->ActSketch.SolveTime);
|
signalSolved(QString::fromLatin1("Solved in %1 sec").arg(edit->ActSketch.SolveTime));
|
||||||
} else {
|
} else {
|
||||||
signalSolved(1, edit->ActSketch.SolveTime);
|
signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(edit->ActSketch.SolveTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -2694,42 +2694,7 @@ void ViewProviderSketch::updateData(const App::Property *prop)
|
||||||
|
|
||||||
if (edit && (prop == &(getSketchObject()->Geometry) || &(getSketchObject()->Constraints))) {
|
if (edit && (prop == &(getSketchObject()->Geometry) || &(getSketchObject()->Constraints))) {
|
||||||
edit->FullyConstrained = false;
|
edit->FullyConstrained = false;
|
||||||
int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(),
|
solveSketch();
|
||||||
getSketchObject()->Constraints.getValues(),
|
|
||||||
true, getSketchObject()->getExternalGeometryCount());
|
|
||||||
std::string msg;
|
|
||||||
if (getSketchObject()->Geometry.getSize() == 0) {
|
|
||||||
signalSetUp(-1, 0, msg);
|
|
||||||
signalSolved(-1, 0);
|
|
||||||
}
|
|
||||||
else if (dofs < 0) { // over-constrained sketch
|
|
||||||
SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg);
|
|
||||||
//Base::Console().Warning("Over-constrained sketch\n%s",msg.c_str());
|
|
||||||
signalSetUp(3, 0, msg);
|
|
||||||
signalSolved(-1,0);
|
|
||||||
}
|
|
||||||
else if (edit->ActSketch.hasConflicts()) { // conflicting constraints
|
|
||||||
SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg);
|
|
||||||
//Base::Console().Warning("Sketch with conflicting constraints\n%s",msg.c_str());
|
|
||||||
signalSetUp(2, dofs, msg);
|
|
||||||
signalSolved(-1,0);
|
|
||||||
}
|
|
||||||
else if (edit->ActSketch.solve() == 0) { // solving the sketch
|
|
||||||
if (dofs == 0) {
|
|
||||||
// color the sketch as fully constrained
|
|
||||||
edit->FullyConstrained = true;
|
|
||||||
//Base::Console().Message("Fully constrained sketch\n");
|
|
||||||
signalSetUp(0, 0, msg);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//Base::Console().Message("Under-constrained sketch with %d degrees of freedom\n", dofs);
|
|
||||||
signalSetUp(1, dofs, msg);
|
|
||||||
}
|
|
||||||
signalSolved(0,edit->ActSketch.SolveTime);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
signalSolved(1,edit->ActSketch.SolveTime);
|
|
||||||
}
|
|
||||||
draw(true);
|
draw(true);
|
||||||
}
|
}
|
||||||
if (edit && &(getSketchObject()->Constraints)) {
|
if (edit && &(getSketchObject()->Constraints)) {
|
||||||
|
@ -2831,49 +2796,64 @@ bool ViewProviderSketch::setEdit(int ModNum)
|
||||||
else
|
else
|
||||||
Gui::Control().showDialog(new TaskDlgEditSketch(this));
|
Gui::Control().showDialog(new TaskDlgEditSketch(this));
|
||||||
|
|
||||||
// set up the sketch and diagnose possible conflicts
|
solveSketch();
|
||||||
int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(),
|
|
||||||
getSketchObject()->Constraints.getValues(),
|
|
||||||
true, getSketchObject()->getExternalGeometryCount());
|
|
||||||
std::string msg;
|
|
||||||
if (getSketchObject()->Geometry.getSize() == 0) {
|
|
||||||
signalSetUp(-1, 0, msg);
|
|
||||||
signalSolved(-1, 0);
|
|
||||||
}
|
|
||||||
else if (dofs < 0) { // over-constrained sketch
|
|
||||||
SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg);
|
|
||||||
//Base::Console().Warning("Over-constrained sketch\n%s",msg.c_str());
|
|
||||||
signalSetUp(3, 0, msg);
|
|
||||||
signalSolved(-1, 0);
|
|
||||||
}
|
|
||||||
else if (edit->ActSketch.hasConflicts()) { // conflicting constraints
|
|
||||||
SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg);
|
|
||||||
//Base::Console().Warning("Sketch with conflicting constraints\n%s",msg.c_str());
|
|
||||||
signalSetUp(2, dofs, msg);
|
|
||||||
signalSolved(-1, 0);
|
|
||||||
}
|
|
||||||
else if (edit->ActSketch.solve() == 0) { // solving the sketch
|
|
||||||
if (dofs == 0) {
|
|
||||||
// color the sketch as fully constrained
|
|
||||||
edit->FullyConstrained = true;
|
|
||||||
//Base::Console().Message("Fully constrained sketch\n");
|
|
||||||
signalSetUp(0, 0, msg);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//Base::Console().Message("Under-constrained sketch with %d degrees of freedom\n", dofs);
|
|
||||||
signalSetUp(1, dofs, msg);
|
|
||||||
}
|
|
||||||
signalSolved(0, edit->ActSketch.SolveTime);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
signalSolved(1, edit->ActSketch.SolveTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw();
|
draw();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewProviderSketch::solveSketch(void)
|
||||||
|
{
|
||||||
|
// set up the sketch and diagnose possible conflicts
|
||||||
|
int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(),
|
||||||
|
getSketchObject()->Constraints.getValues(),
|
||||||
|
getSketchObject()->getExternalGeometryCount());
|
||||||
|
if (getSketchObject()->Geometry.getSize() == 0) {
|
||||||
|
signalSetUp(QString::fromLatin1("Empty sketch"));
|
||||||
|
signalSolved(QString());
|
||||||
|
}
|
||||||
|
else if (dofs < 0) { // over-constrained sketch
|
||||||
|
std::string msg;
|
||||||
|
SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg);
|
||||||
|
signalSetUp(QString::fromLatin1("<font color='red'>Over-constrained sketch<br/>%1</font>")
|
||||||
|
.arg(QString::fromStdString(msg)));
|
||||||
|
signalSolved(QString());
|
||||||
|
}
|
||||||
|
else if (edit->ActSketch.hasConflicts()) { // conflicting constraints
|
||||||
|
std::string msg;
|
||||||
|
SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg);
|
||||||
|
signalSetUp(QString::fromLatin1("<font color='red'>Sketch contains conflicting constraints<br/>%1</font>")
|
||||||
|
.arg(QString::fromStdString(msg)));
|
||||||
|
signalSolved(QString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (edit->ActSketch.hasRedundancies()) { // redundant constraints
|
||||||
|
std::string msg;
|
||||||
|
SketchObject::appendRedundantMsg(edit->ActSketch.getRedundant(), msg);
|
||||||
|
signalSetUp(QString::fromLatin1("<font color='orange'>Sketch contains redundant constraints<br/>%1</font>")
|
||||||
|
.arg(QString::fromStdString(msg)));
|
||||||
|
}
|
||||||
|
if (edit->ActSketch.solve() == 0) { // solving the sketch
|
||||||
|
if (dofs == 0) {
|
||||||
|
// color the sketch as fully constrained
|
||||||
|
edit->FullyConstrained = true;
|
||||||
|
if (!edit->ActSketch.hasRedundancies())
|
||||||
|
signalSetUp(QString::fromLatin1("<font color='green'>Fully constrained sketch </font>"));
|
||||||
|
}
|
||||||
|
else if (!edit->ActSketch.hasRedundancies()) {
|
||||||
|
if (dofs == 1)
|
||||||
|
signalSetUp(QString::fromLatin1("Under-constrained sketch with 1 degree of freedom"));
|
||||||
|
else
|
||||||
|
signalSetUp(QString::fromLatin1("Under-constrained sketch with %1 degrees of freedom").arg(dofs));
|
||||||
|
}
|
||||||
|
signalSolved(QString::fromLatin1("Solved in %1 sec").arg(edit->ActSketch.SolveTime));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(edit->ActSketch.SolveTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ViewProviderSketch::createEditInventorNodes(void)
|
void ViewProviderSketch::createEditInventorNodes(void)
|
||||||
{
|
{
|
||||||
assert(edit);
|
assert(edit);
|
||||||
|
|
|
@ -174,15 +174,17 @@ public:
|
||||||
/// signals if the constraints list has changed
|
/// signals if the constraints list has changed
|
||||||
boost::signal<void ()> signalConstraintsChanged;
|
boost::signal<void ()> signalConstraintsChanged;
|
||||||
/// signals if the sketch has been set up
|
/// signals if the sketch has been set up
|
||||||
boost::signal<void (int type, int dofs, std::string &msg)> signalSetUp;
|
boost::signal<void (QString msg)> signalSetUp;
|
||||||
/// signals if the sketch has been solved
|
/// signals if the sketch has been solved
|
||||||
boost::signal<void (int type, float time)> signalSolved;
|
boost::signal<void (QString msg)> signalSolved;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool setEdit(int ModNum);
|
virtual bool setEdit(int ModNum);
|
||||||
virtual void unsetEdit(int ModNum);
|
virtual void unsetEdit(int ModNum);
|
||||||
virtual void setEditViewer(Gui::View3DInventorViewer*, int ModNum);
|
virtual void setEditViewer(Gui::View3DInventorViewer*, int ModNum);
|
||||||
virtual void unsetEditViewer(Gui::View3DInventorViewer*);
|
virtual void unsetEditViewer(Gui::View3DInventorViewer*);
|
||||||
|
/// set up and solve the sketch
|
||||||
|
void solveSketch(void);
|
||||||
/// helper to detect whether the picked point lies on the sketch
|
/// helper to detect whether the picked point lies on the sketch
|
||||||
bool isPointOnSketch(const SoPickedPoint *pp) const;
|
bool isPointOnSketch(const SoPickedPoint *pp) const;
|
||||||
/// get called by the container whenever a property has been changed
|
/// get called by the container whenever a property has been changed
|
||||||
|
|
Loading…
Reference in New Issue
Block a user