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