Sketcher: Block Constraint - Advanced redundant/conflict redundant handling
=========================================================================== Block constraint is naturally redundant/conflicting with almost any other constraint applied to an edge (certainly with constraints operating only on that element). As such, a block constraint will have very little applicability in absence of a way to handle this redundancy/conflicting. For example, in the case of a BSpline all its internal geometry (construction circles on poles and its constraints) would have to be removed before locking. This would mean that it is not possible to define the BSpline shape and then block it, as when removing the internal geometry the shape would be lost. In other cases, like temporally blocking to avoid that a part of the sketch moves while performing some operation with the idea of afterwards unblocking it, it would mean removing all constraints, to add the block constraint, then perform the action, then remove the block constraint and manually constraint it again. Handling this situation in a user expected way means ignoring certain constraints (those causing the redundancy/conflicting), so that the solver is not aware of them and does not complain. However, generally ignoring those constraints has a negative effect, in that constraints applied by the user on already blocked geometry, or constraints that otherwise lead to a conflicting or redundant situation as a consequence of actions (further constraining) after the Block constrain is applied are ignored, thereby not properly informing the user of this situation, which is undesirable. This new mechanism takes account on the position of the constraints relative to the involved blocked constraint(s). As such, redundant/conflicting constraints that were added before the Block constraint are ignored, whereas those constraints that lead to a redundant/conflicting situation and added AFTER the block constraint was already in place, those are not ignored and are reported accordingly.
This commit is contained in:
@@ -128,10 +128,11 @@ int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList,
|
||||
for (int i=int(GeoList.size())-extGeoCount; i < int(GeoList.size()); i++)
|
||||
extGeoList.push_back(GeoList[i]);
|
||||
|
||||
std::vector<bool> blockedGeometry(intGeoList.size(),false);
|
||||
std::vector<bool> blockedGeometry(intGeoList.size(),false); // these geometries are blocked, frozen and sent as fixed parameters to the solver
|
||||
std::vector<bool> unenforceableConstraints(ConstraintList.size(),false); // these constraints are unenforceable due to a Blocked constraint
|
||||
|
||||
if(!intGeoList.empty())
|
||||
getBlockedGeometry(blockedGeometry,ConstraintList);
|
||||
getBlockedGeometry(blockedGeometry, unenforceableConstraints, ConstraintList);
|
||||
|
||||
addGeometry(intGeoList,blockedGeometry);
|
||||
int extStart=Geoms.size();
|
||||
@@ -142,7 +143,7 @@ int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList,
|
||||
|
||||
// The Geoms list might be empty after an undo/redo
|
||||
if (!Geoms.empty()) {
|
||||
addConstraints(ConstraintList);
|
||||
addConstraints(ConstraintList,unenforceableConstraints);
|
||||
}
|
||||
GCSsys.clearByTag(-1);
|
||||
GCSsys.declareUnknowns(Parameters);
|
||||
@@ -1322,22 +1323,121 @@ int Sketch::addConstraints(const std::vector<Constraint *> &ConstraintList)
|
||||
int rtn = -1;
|
||||
|
||||
for (std::vector<Constraint *>::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it)
|
||||
rtn = addConstraint (*it);
|
||||
rtn = addConstraint (*it);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
void Sketch::getBlockedGeometry(std::vector<bool> & blockedGeometry, const std::vector<Constraint *> &ConstraintList)
|
||||
int Sketch::addConstraints(const std::vector<Constraint *> &ConstraintList, std::vector<bool> &unenforceableConstraints)
|
||||
{
|
||||
int rtn = -1;
|
||||
|
||||
for (std::vector<Constraint *>::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it) {
|
||||
if((*it)->Type == Blocked) {
|
||||
int geoid = (*it)->First;
|
||||
int cid = 0;
|
||||
for (std::vector<Constraint *>::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it,++cid) {
|
||||
if (!unenforceableConstraints[cid] && (*it)->Type != Blocked) {
|
||||
rtn = addConstraint (*it);
|
||||
}
|
||||
else {
|
||||
++ConstraintsCounter; // For correct solver redundant reporting
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(geoid>=0 && geoid<blockedGeometry.size())
|
||||
blockedGeometry[geoid]=true;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
void Sketch::getBlockedGeometry(std::vector<bool> & blockedGeometry, std::vector<bool> & unenforceableConstraints, const std::vector<Constraint *> &ConstraintList)
|
||||
{
|
||||
std::vector<int> internalAlignmentConstraintIndex;
|
||||
std::vector<int> internalAlignmentgeo;
|
||||
|
||||
std::vector<int> geo2blockingconstraintindex(blockedGeometry.size(),-1);
|
||||
|
||||
// Detect Blocked and internal constraints
|
||||
int i = 0;
|
||||
for (std::vector<Constraint *>::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it,++i) {
|
||||
switch((*it)->Type) {
|
||||
case Blocked:
|
||||
{
|
||||
int geoid = (*it)->First;
|
||||
|
||||
if(geoid>=0 && geoid<int(blockedGeometry.size())) {
|
||||
blockedGeometry[geoid]=true;
|
||||
geo2blockingconstraintindex[geoid]=i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InternalAlignment:
|
||||
internalAlignmentConstraintIndex.push_back(i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if a GeoId is blocked and it is linked to Internal Alignment, then GeoIds linked via Internal Alignment are also to be blocked
|
||||
for(std::vector<int>::iterator it = internalAlignmentConstraintIndex.begin(); it != internalAlignmentConstraintIndex.end() ; it++) {
|
||||
if ( blockedGeometry[ConstraintList[(*it)]->Second] ) {
|
||||
blockedGeometry[ConstraintList[(*it)]->First] = true;
|
||||
// asociated geometry gets the same blocking constraint index as the blocked element
|
||||
geo2blockingconstraintindex[ConstraintList[(*it)]->First]= geo2blockingconstraintindex[ConstraintList[(*it)]->Second];
|
||||
internalAlignmentgeo.push_back(ConstraintList[(*it)]->First);
|
||||
unenforceableConstraints[(*it)]= true;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (std::vector<Constraint *>::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it,++i) {
|
||||
if((*it)->isDriving) {
|
||||
// additionally any further constraint on auxiliary elements linked via Internal Alignment are also uneforceable.
|
||||
for(std::vector<int>::iterator itg = internalAlignmentgeo.begin(); itg != internalAlignmentgeo.end() ; itg++) {
|
||||
if( (*it)->First==*itg || (*it)->Second==*itg || (*it)->Third==*itg ) {
|
||||
unenforceableConstraints[i]= true;
|
||||
}
|
||||
}
|
||||
// IMPORTANT NOTE:
|
||||
// The rest of the ignoring of redundant/conflicting applies to constraints introduced before the blocking constraint only
|
||||
// Constraints introduced after the block will not be ignored and will lead to redundancy/conflicting status as per normal
|
||||
// solver behaviour
|
||||
|
||||
// further, any constraint taking only one element, which is blocked is also unenforceable
|
||||
if((*it)->Second==Constraint::GeoUndef && (*it)->Third==Constraint::GeoUndef) {
|
||||
if (blockedGeometry[(*it)->First] && i < geo2blockingconstraintindex[(*it)->First]) {
|
||||
unenforceableConstraints[i]= true;
|
||||
}
|
||||
}
|
||||
// further any constraint on only two elements where both elements are blocked or one is blocked and the other is an axis or external
|
||||
// provided that the constraints precede the last block constraint.
|
||||
else if((*it)->Third==Constraint::GeoUndef) {
|
||||
if ( ((*it)->First>=0 && (*it)->Second>=0 && blockedGeometry[(*it)->First] && blockedGeometry[(*it)->Second] &&
|
||||
(i < geo2blockingconstraintindex[(*it)->First] || i < geo2blockingconstraintindex[(*it)->Second])) ||
|
||||
((*it)->First<0 && (*it)->Second>=0 && blockedGeometry[(*it)->Second] && i < geo2blockingconstraintindex[(*it)->Second]) ||
|
||||
((*it)->First>=0 && (*it)->Second<0 && blockedGeometry[(*it)->First] && i < geo2blockingconstraintindex[(*it)->First]) ){
|
||||
unenforceableConstraints[i]= true;
|
||||
}
|
||||
}
|
||||
// further any constraint on three elements where the three of them are blocked, or two are blocked and the other is an axis or external geo
|
||||
// or any constraint on three elements where one is blocked and the other two are axis or external geo, provided that the constraints precede
|
||||
// the last block constraint.
|
||||
else {
|
||||
if( ((*it)->First>=0 && (*it)->Second>=0 && (*it)->Third>=0 &&
|
||||
blockedGeometry[(*it)->First] && blockedGeometry[(*it)->Second] && blockedGeometry[(*it)->Third] &&
|
||||
(i < geo2blockingconstraintindex[(*it)->First] || i < geo2blockingconstraintindex[(*it)->Second] || i < geo2blockingconstraintindex[(*it)->Third])) ||
|
||||
((*it)->First<0 && (*it)->Second>=0 && (*it)->Third>=0 && blockedGeometry[(*it)->Second] && blockedGeometry[(*it)->Third] &&
|
||||
(i < geo2blockingconstraintindex[(*it)->Second] || i < geo2blockingconstraintindex[(*it)->Third])) ||
|
||||
((*it)->First>=0 && (*it)->Second<0 && (*it)->Third>=0 && blockedGeometry[(*it)->First] && blockedGeometry[(*it)->Third] &&
|
||||
(i < geo2blockingconstraintindex[(*it)->First] || i < geo2blockingconstraintindex[(*it)->Third])) ||
|
||||
((*it)->First>=0 && (*it)->Second>=0 && (*it)->Third<0 && blockedGeometry[(*it)->First] && blockedGeometry[(*it)->Second] &&
|
||||
(i < geo2blockingconstraintindex[(*it)->First] || i < geo2blockingconstraintindex[(*it)->Second])) ||
|
||||
((*it)->First>=0 && (*it)->Second<0 && (*it)->Third<0 && blockedGeometry[(*it)->First] && i < geo2blockingconstraintindex[(*it)->First]) ||
|
||||
((*it)->First<0 && (*it)->Second>=0 && (*it)->Third<0 && blockedGeometry[(*it)->Second] && i < geo2blockingconstraintindex[(*it)->Second]) ||
|
||||
((*it)->First<0 && (*it)->Second<0 && (*it)->Third>=0 && blockedGeometry[(*it)->Third] && i < geo2blockingconstraintindex[(*it)->Third]) ) {
|
||||
|
||||
unenforceableConstraints[i]= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Sketch::addCoordinateXConstraint(int geoId, PointPos pos, double * value)
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
/// add unspecified geometry, where each element's "fixed" status is given by the blockedGeometry array
|
||||
int addGeometry(const std::vector<Part::Geometry *> &geo, std::vector<bool> &blockedGeometry);
|
||||
/// get boolean list indicating whether the geometry is to be blocked or not
|
||||
void getBlockedGeometry(std::vector<bool> & blockedGeometry, const std::vector<Constraint *> &ConstraintList);
|
||||
void getBlockedGeometry(std::vector<bool> & blockedGeometry, std::vector<bool> & unenforceableConstraints, const std::vector<Constraint *> &ConstraintList);
|
||||
/// returns the actual geometry
|
||||
std::vector<Part::Geometry *> extractGeometry(bool withConstructionElements=true,
|
||||
bool withExternalElements=false) const;
|
||||
@@ -149,6 +149,8 @@ public:
|
||||
//@{
|
||||
/// add all constraints in the list
|
||||
int addConstraints(const std::vector<Constraint *> &ConstraintList);
|
||||
/// add all constraints in the list, provided that are enforceable
|
||||
int addConstraints(const std::vector<Constraint *> &ConstraintList, std::vector<bool> & unenforceableConstraints);
|
||||
/// add one constraint to the sketch
|
||||
int addConstraint(const Constraint *constraint);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user