diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 527cf6eb4c..0e78b50940 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -128,10 +128,11 @@ int Sketch::setUpSketch(const std::vector &GeoList, for (int i=int(GeoList.size())-extGeoCount; i < int(GeoList.size()); i++) extGeoList.push_back(GeoList[i]); - std::vector blockedGeometry(intGeoList.size(),false); + std::vector blockedGeometry(intGeoList.size(),false); // these geometries are blocked, frozen and sent as fixed parameters to the solver + std::vector 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 &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 &ConstraintList) int rtn = -1; for (std::vector::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it) - rtn = addConstraint (*it); + rtn = addConstraint (*it); return rtn; } -void Sketch::getBlockedGeometry(std::vector & blockedGeometry, const std::vector &ConstraintList) +int Sketch::addConstraints(const std::vector &ConstraintList, std::vector &unenforceableConstraints) { + int rtn = -1; - for (std::vector::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it) { - if((*it)->Type == Blocked) { - int geoid = (*it)->First; + int cid = 0; + for (std::vector::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, std::vector & unenforceableConstraints, const std::vector &ConstraintList) +{ + std::vector internalAlignmentConstraintIndex; + std::vector internalAlignmentgeo; + + std::vector geo2blockingconstraintindex(blockedGeometry.size(),-1); + + // Detect Blocked and internal constraints + int i = 0; + for (std::vector::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it,++i) { + switch((*it)->Type) { + case Blocked: + { + int geoid = (*it)->First; + + if(geoid>=0 && geoid::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::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::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) diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index 80a82055f0..41dd67fbca 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -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 &geo, std::vector &blockedGeometry); /// get boolean list indicating whether the geometry is to be blocked or not - void getBlockedGeometry(std::vector & blockedGeometry, const std::vector &ConstraintList); + void getBlockedGeometry(std::vector & blockedGeometry, std::vector & unenforceableConstraints, const std::vector &ConstraintList); /// returns the actual geometry std::vector extractGeometry(bool withConstructionElements=true, bool withExternalElements=false) const; @@ -149,6 +149,8 @@ public: //@{ /// add all constraints in the list int addConstraints(const std::vector &ConstraintList); + /// add all constraints in the list, provided that are enforceable + int addConstraints(const std::vector &ConstraintList, std::vector & unenforceableConstraints); /// add one constraint to the sketch int addConstraint(const Constraint *constraint);