X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintRigid.cpp;h=ed8ae371271336fa7c9ef9724b6c92a0a5c0c46c;hb=868158fe6d39b25e60ac528295b1c908821e4af5;hp=a1deb96ccd44516b25004ebf166363b615ae6554;hpb=33b3a43ad2266cb044e4232c902344842adbba7c;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp index a1deb96cc..ed8ae3712 100644 --- a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp @@ -5,12 +5,16 @@ #include #include #include +#include +#include #include #include #include #include +#include + SketchSolver_ConstraintRigid::SketchSolver_ConstraintRigid(FeaturePtr theFeature) : SketchSolver_Constraint(), myBaseFeature(theFeature) @@ -31,65 +35,76 @@ void SketchSolver_ConstraintRigid::process() double aValue; std::vector anEntities; getAttributes(aValue, anEntities); - if (!myErrorMsg.empty()) + if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty())) return; + fixFeature(); +} - Slvs_Constraint aConstraint; - std::vector::iterator aConstrIter = mySlvsConstraints.begin(); - bool isEmpty = aConstrIter == mySlvsConstraints.end(); - - // Check the fixed entity is an arc - if (isEmpty) { - if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Arc::ID()) { - Slvs_Entity anArc = myStorage->getEntity(myFeatureMap.begin()->second); - fixArc(anArc); - return; - } +void SketchSolver_ConstraintRigid::update(ConstraintPtr theConstraint) +{ + cleanErrorMsg(); + if (theConstraint && theConstraint == myBaseConstraint && + theConstraint->getKind() == myBaseConstraint->getKind() && + checkAttributesChanged(theConstraint)) { + // remove previous constraint and set the given one + remove(myBaseConstraint); + myBaseConstraint = theConstraint; + process(); } +} - std::vector::const_iterator anEntIter = anEntities.begin(); - for (; anEntIter != anEntities.end(); anEntIter++) { - if (*anEntIter == SLVS_E_UNKNOWN) - continue; - Slvs_hConstraint aConstrID = myStorage->isPointFixed(*anEntIter); - bool isForceUpdate = (aConstrID != SLVS_E_UNKNOWN && !myBaseConstraint); - if (isEmpty && !isForceUpdate) { // create new constraint - if (aConstrID != SLVS_E_UNKNOWN) - continue; // the coincident point is already fixed - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), - aValue, *anEntIter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - if (!myBaseConstraint) - myStorage->addTemporaryConstraint(aConstraint.h); - } else { // update already existent constraint - if (aConstrID == SLVS_E_UNKNOWN || myBaseConstraint) - aConstrID = *aConstrIter; - aConstraint = myStorage->getConstraint(aConstrID); - aConstraint.ptA = *anEntIter; - myStorage->addConstraint(aConstraint); - if (!myBaseConstraint) - myStorage->addTemporaryConstraint(aConstraint.h); - if (!isEmpty) { - aConstrIter++; - isEmpty = aConstrIter == mySlvsConstraints.end(); - } +static void fixEntity(StoragePtr theStorage, const Slvs_hEntity& theEntID) +{ + Slvs_Entity anEntity = theStorage->getEntity(theEntID); + anEntity.group = SLVS_G_OUTOFGROUP; + theStorage->updateEntity(anEntity); + // move out of group all sub-entities + for (int i = 0; i < 4; ++i) + if (anEntity.point[i] != SLVS_E_UNKNOWN) + fixEntity(theStorage, anEntity.point[i]); + // move out of group the radius of circle + if (anEntity.distance != SLVS_E_UNKNOWN) + fixEntity(theStorage, anEntity.distance); + // move out of group parameters + for (int i = 0; i < 4; ++i) + if (anEntity.param[i] != SLVS_E_UNKNOWN) { + Slvs_Param aParam = theStorage->getParameter(anEntity.param[i]); + aParam.group = SLVS_G_OUTOFGROUP; + theStorage->updateParameter(aParam); } - } +} - if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Circle::ID()) { - // Fix radius of a circle - AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast( - myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID())); - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(), - aRadiusAttr->value() * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - if (!myBaseConstraint) - myStorage->addTemporaryConstraint(aConstraint.h); - } +void SketchSolver_ConstraintRigid::fixFeature() +{ + Slvs_hEntity anEntID = fixedEntity(); + if (anEntID != SLVS_E_UNKNOWN) + fixEntity(myStorage, anEntID); } +Slvs_hEntity SketchSolver_ConstraintRigid::fixedEntity() const +{ + Slvs_hEntity anEntID = SLVS_E_UNKNOWN; + if (myBaseConstraint) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + if (aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + std::map::const_iterator aFound = myFeatureMap.find(aFeature); + if (aFound != myFeatureMap.end()) + anEntID = aFound->second; + } else { + std::map::const_iterator aFound = myAttributeMap.find(aRefAttr->attr()); + if (aFound != myAttributeMap.end()) + anEntID = aFound->second; + } + } + else if (myBaseFeature) { + std::map::const_iterator aFound = myFeatureMap.find(myBaseFeature); + if (aFound != myFeatureMap.end()) + anEntID = aFound->second; + } + return anEntID; +} void SketchSolver_ConstraintRigid::getAttributes( double& theValue, @@ -117,6 +132,11 @@ void SketchSolver_ConstraintRigid::getAttributes( myFeatureMap[myBaseFeature] = anEntityID; } + if (anEntityID == SLVS_E_UNKNOWN) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + // Check the entity is complex Slvs_Entity anEntity = myStorage->getEntity(anEntityID); if (anEntity.point[0] != SLVS_E_UNKNOWN) { @@ -126,38 +146,6 @@ void SketchSolver_ConstraintRigid::getAttributes( theAttributes.push_back(anEntityID); } -void SketchSolver_ConstraintRigid::adjustConstraint() -{ - if (myFeatureMap.empty() || ( - myFeatureMap.begin()->first->getKind() != SketchPlugin_Arc::ID() && - myFeatureMap.begin()->first->getKind() != SketchPlugin_Circle::ID())) - return; - FeaturePtr aFeature = myFeatureMap.begin()->first; - - // Search radius constraints and update them - Slvs_Constraint aConstraint; - std::vector::iterator aCIter = mySlvsConstraints.begin(); - for (; aCIter != mySlvsConstraints.end(); aCIter++) { - aConstraint = myStorage->getConstraint(*aCIter); - if (aConstraint.type != SLVS_C_DIAMETER) - continue; - double aRadius = 0.0; - if (aFeature->getKind() == SketchPlugin_Arc::ID()) { - std::shared_ptr aCenter = std::dynamic_pointer_cast( - aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt(); - std::shared_ptr aStart = std::dynamic_pointer_cast( - aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt(); - aRadius = aCenter->distance(aStart); - } else { - aRadius = std::dynamic_pointer_cast( - aFeature->attribute(SketchPlugin_Circle::RADIUS_ID()))->value(); - } - - aConstraint.valA = aRadius * 2.0; - *aCIter = myStorage->updateConstraint(aConstraint); - } -} - bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint) { @@ -165,27 +153,195 @@ bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint) if (theConstraint && theConstraint != myBaseConstraint) return false; bool isFullyRemoved = true; + std::vector::iterator aCIter = mySlvsConstraints.begin(); - for (; aCIter != mySlvsConstraints.end(); aCIter++) + for (; aCIter != mySlvsConstraints.end(); ++aCIter) isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; + std::map::iterator aFIter = myFeatureMap.begin(); + for (; aFIter != myFeatureMap.end(); ++aFIter) + isFullyRemoved = myStorage->removeEntity(aFIter->second) && isFullyRemoved; + + std::map::iterator anAtIter = myAttributeMap.begin(); + for (; anAtIter != myAttributeMap.end(); ++anAtIter) + isFullyRemoved = myStorage->removeEntity(anAtIter->second) && isFullyRemoved; + if (isFullyRemoved) { myFeatureMap.clear(); myAttributeMap.clear(); myValueMap.clear(); + mySlvsConstraints.clear(); } else cleanRemovedEntities(); return true; } +Slvs_hConstraint SketchSolver_ConstraintRigid::fixPoint(const Slvs_hEntity& thePointID) +{ + if (thePointID == SLVS_E_UNKNOWN) + return SLVS_C_UNKNOWN; + + Slvs_Constraint aConstraint; + 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 (isFixed) return aConstrID; + aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), + 0.0, thePointID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + if (!myBaseConstraint) + myStorage->addConstraintWhereDragged(aConstraint.h); + } else { // update already existent constraint + if (!isFixed || aConstrID == SLVS_C_UNKNOWN || myBaseConstraint) + return SLVS_C_UNKNOWN; + aConstraint = myStorage->getConstraint(aConstrID); + aConstraint.ptA = thePointID; + myStorage->addConstraint(aConstraint); + if (!myBaseConstraint) + myStorage->addConstraintWhereDragged(aConstraint.h); + } + return aConstraint.h; +} + +void SketchSolver_ConstraintRigid::fixLine(const Slvs_Entity& theLine) +{ + Slvs_Constraint anEqual; + if (myStorage->isAxisParallel(theLine.h)) { + // Fix one point and a line length + Slvs_hConstraint aFixed; + if (!myStorage->isPointFixed(theLine.point[0], aFixed, true) && + !myStorage->isPointFixed(theLine.point[1], aFixed, true)) + fixPoint(theLine.point[0]); + if (!myStorage->isUsedInEqual(theLine.h, anEqual)) { + // Check the distance is not set yet + std::list aDistConstr = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE); + std::list::const_iterator aDIt = aDistConstr.begin(); + for (; aDIt != aDistConstr.end(); aDIt++) + if ((aDIt->ptA == theLine.point[0] && aDIt->ptB == theLine.point[1]) || + (aDIt->ptA == theLine.point[1] && aDIt->ptB == theLine.point[0])) + return; + // Calculate distance between points on the line + double aCoords[4]; + for (int i = 0; i < 2; i++) { + Slvs_Entity aPnt = myStorage->getEntity(theLine.point[i]); + for (int j = 0; j < 2; j++) { + Slvs_Param aParam = myStorage->getParameter(aPnt.param[j]); + aCoords[2*i+j] = aParam.val; + } + } + double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) + + (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1])); + // fix line length + Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), + SLVS_C_PT_PT_DISTANCE, myGroup->getWorkplaneId(), aLength, + theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + aDistance.h = myStorage->addConstraint(aDistance); + mySlvsConstraints.push_back(aDistance.h); + } + return; + } + else if (myStorage->isUsedInEqual(theLine.h, anEqual)) { + // Check another entity of Equal is already fixed + Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA; + if (myStorage->isEntityFixed(anOtherEntID, true)) { + // Fix start point of the line (if end point is not fixed yet) ... + 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]; + // Firstly, search already fixed point on line + bool isPonLineFixed = false; + Slvs_hEntity aFixedPoint; + std::list aPonLineList = myStorage->getConstraintsByType(SLVS_C_PT_ON_LINE); + std::list::const_iterator aPLIter = aPonLineList.begin(); + for (; aPLIter != aPonLineList.end() && !isPonLineFixed; aPLIter++) + if (aPLIter->entityA == theLine.h) { + isPonLineFixed = myStorage->isPointFixed(aPLIter->ptA, anEndFixedID); + aFixedPoint = aPLIter->ptA; + } + + if (isPonLineFixed) { // update existent constraint + myStorage->copyEntity(aPointToCopy, aFixedPoint); + } else { // create new constraint + Slvs_hEntity aCopied = myStorage->copyEntity(aPointToCopy); + Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE, + myGroup->getWorkplaneId(), 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN); + aPonLine.h = myStorage->addConstraint(aPonLine); + mySlvsConstraints.push_back(aPonLine.h); + fixPoint(aCopied); + } + return; + } + } + + for (int i = 0; i < 2; i++) + fixPoint(theLine.point[i]); +} + +void SketchSolver_ConstraintRigid::fixCircle(const Slvs_Entity& theCircle) +{ + bool isFixRadius = true; + // Verify the arc is under Equal constraint + Slvs_Constraint anEqual; + if (myStorage->isUsedInEqual(theCircle.h, anEqual)) { + // Check another entity of Equal is already fixed + Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA; + if (myStorage->isEntityFixed(anOtherEntID, true)) + isFixRadius = false; + } + + fixPoint(theCircle.point[0]); + + if (isFixRadius) { + // Search the radius is already fixed + std::list aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER); + std::list::const_iterator aDiamIter = aDiamConstr.begin(); + for (; aDiamIter != aDiamConstr.end(); aDiamIter++) + if (aDiamIter->entityA == theCircle.h) + return; + + // Fix radius of a circle + AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast( + myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID())); + Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, + myGroup->getWorkplaneId(), aRadiusAttr->value() * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, + myFeatureMap.begin()->second, SLVS_E_UNKNOWN); + aFixedR.h = myStorage->addConstraint(aFixedR); + mySlvsConstraints.push_back(aFixedR.h); + } +} void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc) { - Slvs_Constraint aConstraint; - Slvs_hConstraint aConstrID = myStorage->isPointFixed(theArc.point[0]); - int aPointsToFix = 2; // number of fixed points for the arc - if (aConstrID != SLVS_E_UNKNOWN) - aPointsToFix--; + bool isFixRadius = true; + std::list aPointsToFix; + aPointsToFix.push_back(theArc.point[1]); + aPointsToFix.push_back(theArc.point[2]); + + // Verify the arc is under Equal constraint + Slvs_Constraint anEqual; + if (myStorage->isUsedInEqual(theArc.h, anEqual)) { + // Check another entity of Equal is already fixed + Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA; + 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; + int aNbPointsToFix = 2; // number of fixed points for the arc + if (myStorage->isPointFixed(theArc.point[0], aConstrID, true)) + aNbPointsToFix--; // Radius of the arc FeaturePtr aFeature = myFeatureMap.begin()->first; @@ -212,32 +368,26 @@ void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc) myStorage->updateParameter(aParam); } - for (int i = 1; aPointsToFix > 0; i++, aPointsToFix--) { - aConstrID = myStorage->isPointFixed(theArc.point[i]); - if (aConstrID != SLVS_E_UNKNOWN) - continue; // the coincident point is already fixed - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), - 0.0, theArc.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - if (!myBaseConstraint) - myStorage->addTemporaryConstraint(aConstraint.h); - } + std::list::iterator aPtIt = aPointsToFix.begin(); + for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--) + fixPoint(*aPtIt); - // Fix radius of the arc - bool isExists = false; - std::list aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER); - std::list::iterator anIt = aDiamConstraints.begin(); - for (; anIt != aDiamConstraints.end() && !isExists; anIt) - if (anIt->entityA == myFeatureMap.begin()->second) - isExists = true; - if (!isExists) { - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(), - aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - if (!myBaseConstraint) - myStorage->addTemporaryConstraint(aConstraint.h); + if (isFixRadius) { + // Fix radius of the arc + bool isExists = false; + std::list aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER); + std::list::iterator anIt = aDiamConstraints.begin(); + for (; anIt != aDiamConstraints.end() && !isExists; anIt++) + if (anIt->entityA == theArc.h) + isExists = true; + if (!isExists) { + Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, + myGroup->getWorkplaneId(), aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, + myFeatureMap.begin()->second, SLVS_E_UNKNOWN); + aFixedR.h = myStorage->addConstraint(aFixedR); + mySlvsConstraints.push_back(aFixedR.h); + if (!myBaseConstraint) + myStorage->addConstraintWhereDragged(aFixedR.h); + } } } -