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:
Abdullah Tahiri
2017-12-21 10:11:26 +01:00
committed by wmayer
parent 9b7d1d6042
commit 34f533b0e1
2 changed files with 113 additions and 11 deletions

View File

@@ -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)

View File

@@ -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);