return;
Slvs_Constraint aConstraint;
- Slvs_hConstraint aConstrID = myStorage->isPointFixed(thePointID);
- bool isForceUpdate = (aConstrID != SLVS_E_UNKNOWN && !myBaseConstraint &&
+ Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
+ bool isFixed = myStorage->isPointFixed(thePointID, aConstrID, true);
+ bool isForceUpdate = (isFixed && !myBaseConstraint &&
myStorage->isTemporary(aConstrID));
if (!isForceUpdate) { // create new constraint
- if (aConstrID != SLVS_E_UNKNOWN)
- return; // the coincident point is already fixed
+ if (isFixed) return;
aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
0.0, thePointID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
aConstraint.h = myStorage->addConstraint(aConstraint);
if (!myBaseConstraint)
myStorage->addConstraintWhereDragged(aConstraint.h);
} else { // update already existent constraint
- if (aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
+ if (!isFixed || aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
return;
aConstraint = myStorage->getConstraint(aConstrID);
aConstraint.ptA = thePointID;
if (isUsedInEqual(theLine, anEqual)) {
// Check another entity of Equal is already fixed
Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
- Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
- if (isFixed(anOtherEntity)) {
+ if (myStorage->isEntityFixed(anOtherEntID, true)) {
// Fix start point of the line (if end point is not fixed yet) ...
- Slvs_hConstraint anEndFixedID = myStorage->isPointFixed(theLine.point[1]);
- if (anEndFixedID == SLVS_E_UNKNOWN)
+ Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
+ bool isFixed = myStorage->isPointFixed(theLine.point[1], anEndFixedID, true);
+ if (isFixed == SLVS_E_UNKNOWN)
fixPoint(theLine.point[0]);
// ... and create fixed point lying on this line
Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
std::list<Slvs_Constraint>::const_iterator aPLIter = aPonLineList.begin();
for (; aPLIter != aPonLineList.end() && !isPonLineFixed; aPLIter++)
if (aPLIter->entityA == theLine.h) {
- isPonLineFixed = (myStorage->isPointFixed(aPLIter->ptA) != SLVS_E_UNKNOWN);
+ isPonLineFixed = myStorage->isPointFixed(aPLIter->ptA, anEndFixedID);
aFixedPoint = aPLIter->ptA;
}
if (isUsedInEqual(theCircle, anEqual)) {
// Check another entity of Equal is already fixed
Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
- Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
- if (isFixed(anOtherEntity))
+ if (myStorage->isEntityFixed(anOtherEntID, true))
isFixRadius = false;
}
if (isUsedInEqual(theArc, anEqual)) {
// Check another entity of Equal is already fixed
Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
- Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
- if (isFixed(anOtherEntity)) {
+ if (myStorage->isEntityFixed(anOtherEntID, true)) {
isFixRadius = false;
+ Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
aPointsToFix.pop_back();
aPointsToFix.push_back(theArc.point[0]);
}
}
- Slvs_hConstraint aConstrID = myStorage->isPointFixed(theArc.point[0]);
+ Slvs_hConstraint aConstrID;
int aNbPointsToFix = 2; // number of fixed points for the arc
- if (aConstrID != SLVS_E_UNKNOWN)
+ if (myStorage->isPointFixed(theArc.point[0], aConstrID, true))
aNbPointsToFix--;
// Radius of the arc
return false;
}
-bool SketchSolver_ConstraintRigid::isFixed(const Slvs_Entity& theEntity) const
-{
- if (theEntity.type == SLVS_E_POINT_IN_2D)
- return myStorage->isPointFixed(theEntity.h) != SLVS_E_UNKNOWN;
-
- // Check all the points of entity are fixed
- int aNbFixed = 0;
- for (int i = 0; i < 4; i++) {
- if (theEntity.point[i] != SLVS_E_UNKNOWN &&
- myStorage->isPointFixed(theEntity.point[i]) != SLVS_E_UNKNOWN)
- aNbFixed++;
- }
-
- switch (theEntity.type) {
- case SLVS_E_LINE_SEGMENT:
- case SLVS_E_ARC_OF_CIRCLE:
- if (aNbFixed == 2) return true;
- case SLVS_E_CIRCLE:
- if (aNbFixed == 1) return true;
- }
- return false;
-}
-
/// \return \c true, if the Equal constrait is found
bool isUsedInEqual(const Slvs_Entity& theEntity, Slvs_Constraint& theEqual) const;
- /// \brief Verifies the entity is already fixed
- bool isFixed(const Slvs_Entity& theEntity) const;
-
protected:
FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
};
#include <ModelAPI_ResultConstruction.h>
#include <SketchPlugin_Constraint.h>
+#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintFillet.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintCoincidence.h>
{
std::list<ObjectPtr> aList = theList->list();
std::list<ObjectPtr>::iterator anIt = aList.begin();
+ std::list<FeaturePtr> aFeatures;
+ // Sort features, at begining there are features used by Equal constraint
for (; anIt != aList.end(); anIt++) {
if (!(*anIt))
continue;
FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+ std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(aFeature);
+ std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+ for (; aCIter != aConstraints.end(); aCIter++)
+ if ((*aCIter)->getKind() == SketchPlugin_ConstraintEqual::ID())
+ break;
+ if (aCIter != aConstraints.end())
+ aFeatures.push_front(aFeature);
+ else
+ aFeatures.push_back(aFeature);
+ }
+
+ std::list<FeaturePtr>::iterator aFeatIter = aFeatures.begin();
+ for (; aFeatIter != aFeatures.end(); aFeatIter++) {
SolverConstraintPtr aConstraint =
- SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+ SketchSolver_Builder::getInstance()->createRigidConstraint(*aFeatIter);
if (!aConstraint)
continue;
aConstraint->setGroup(this);
}
-Slvs_hConstraint SketchSolver_Storage::isPointFixed(const Slvs_hEntity& thePointID) const
+bool SketchSolver_Storage::isPointFixed(
+ const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate) const
{
// Search the set of coincident points
+ std::set<Slvs_hEntity> aCoincident;
+ aCoincident.insert(thePointID);
std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
- if (aCPIter->find(thePointID) != aCPIter->end())
+ if (aCPIter->find(thePointID) != aCPIter->end()) {
+ aCoincident = *aCPIter;
break;
- if (aCPIter == myCoincidentPoints.end()) {
- std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
- for (; aConstrIter != myConstraints.end(); aConstrIter++)
- if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
- aConstrIter->ptA == thePointID)
- return aConstrIter->h;
- return SLVS_E_UNKNOWN;
- }
+ }
// Search the Rigid constraint
std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
for (; aConstrIter != myConstraints.end(); aConstrIter++)
if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
- aCPIter->find(aConstrIter->ptA) != aCPIter->end())
- return aConstrIter->h;
+ aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
+ theFixed = aConstrIter->h;
+ return true;
+ }
+
+ if (theAccurate) {
+ // Try to find the fixed entity which uses such point or its coincidence
+ std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
+ for (; anEntIter != myEntities.end(); anEntIter++) {
+ for (int i = 0; i < 4; i++) {
+ Slvs_hEntity aPt = anEntIter->point[i];
+ if (aPt != SLVS_E_UNKNOWN &&
+ (aPt == thePointID || aCoincident.find(aPt) != aCoincident.end())) {
+ if (isEntityFixed(anEntIter->h, true))
+ return true;
+ }
+ }
+ }
+ }
return SLVS_E_UNKNOWN;
}
+bool SketchSolver_Storage::isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate) const
+{
+ int aPos = Search(theEntityID, myEntities);
+ if (aPos < 0 || aPos >= (int)myEntities.size())
+ return false;
+
+ // Firstly, find how many points are under Rigid constraint
+ int aNbFixed = 0;
+ for (int i = 0; i < 4; i++) {
+ Slvs_hEntity aPoint = myEntities[aPos].point[i];
+ if (aPoint == SLVS_E_UNKNOWN)
+ continue;
+
+ std::set<Slvs_hEntity> aCoincident;
+ aCoincident.insert(aPoint);
+ std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
+ for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
+ if (aCPIter->find(aPoint) != aCPIter->end()) {
+ aCoincident = *aCPIter;
+ break;
+ }
+
+ // Search the Rigid constraint
+ std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
+ aCoincident.find(aConstrIter->ptA) != aCoincident.end())
+ aNbFixed++;
+ }
+
+ std::list<Slvs_Constraint> aList;
+ std::list<Slvs_Constraint>::iterator anIt;
+ Slvs_hConstraint aTempID; // used in isPointFixed() method
+
+ if (myEntities[aPos].type == SLVS_E_LINE_SEGMENT) {
+ if (aNbFixed == 2)
+ return true;
+ else if (aNbFixed == 0 || !theAccurate)
+ return false;
+ // Additional check (the line may be fixed if it is used by different constraints):
+ // 1. The line is used in Equal constraint, another entity is fixed and there is a fixed point on line
+ aList = getConstraintsByType(SLVS_C_PT_ON_LINE);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID && isPointFixed(anIt->ptA, aTempID))
+ break;
+ if (anIt != aList.end()) {
+ aList = getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES);
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ return true;
+ }
+ }
+ // 2. The line is used in Parallel/Perpendicular and Length constraints
+ aList = getConstraintsByType(SLVS_C_PARALLEL);
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ break;
+ }
+ if (anIt != aList.end()) {
+ aList = getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if ((anIt->ptA == myEntities[aPos].point[0] && anIt->ptB == myEntities[aPos].point[1]) ||
+ (anIt->ptA == myEntities[aPos].point[1] && anIt->ptB == myEntities[aPos].point[0]))
+ return true;
+ }
+ // 3. Another verifiers ...
+ } else if (myEntities[aPos].type == SLVS_E_CIRCLE) {
+ if (aNbFixed == 0)
+ return false;
+ // Search for Diameter constraint
+ aList = getConstraintsByType(SLVS_C_DIAMETER);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID)
+ return true;
+ if (!theAccurate)
+ return false;
+ // Additional check (the circle may be fixed if it is used by different constraints):
+ // 1. The circle is used in Equal constraint and another entity is fixed
+ aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ return true;
+ }
+ // 2. Another verifiers ...
+ } else if (myEntities[aPos].type == SLVS_E_ARC_OF_CIRCLE) {
+ if (aNbFixed > 2)
+ return true;
+ else if (aNbFixed <= 1)
+ return false;
+ // Search for Diameter constraint
+ aList = getConstraintsByType(SLVS_C_DIAMETER);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID)
+ return true;
+ if (!theAccurate)
+ return false;
+ // Additional check (the arc may be fixed if it is used by different constraints):
+ // 1. The arc is used in Equal constraint and another entity is fixed
+ aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ return true;
+ }
+ // 2. Another verifiers ...
+ }
+ return false;
+}
+
Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
{
void copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo);
/// \brief Verifies the current point or another coincident one is fixed
- /// \return the ID of the Fixed constraint or SLVS_E_UNKNOWN
- Slvs_hConstraint isPointFixed(const Slvs_hEntity& thePointID) const;
+ /// \param[in] thePointID entity to be checked fixed
+ /// \param[out] theFixed ID of constraint
+ /// \param[in] theAccurate if \c true, the calculation will be made for all type of constraints,
+ /// if \c false, only the point is verified
+ /// \return \c true if the point is fixed
+ bool isPointFixed(const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate = false) const;
+ /// \brief Verifies the current entity is fully fixed (may not be changed by constraints)
+ /// \param[in] theEntityID entity to be checked fixed
+ /// \param[in] theAccurate if \c true, the calculation will be made for all type of constraints,
+ /// if \c false, only points are verified
+ /// \return \c true if the entity is fixed
+ bool isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate = false) const;
/** \brief Add new constraint to the current group
* \param[in] theConstraint SolveSpace's constraint