X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintMultiRotation.cpp;h=bd53679d9ae635b2882bc62374c5703e5b936a76;hb=383021cb51c4720904096ca851db5ee79255b402;hp=0e8ec23d6584d6c5efd5bbabdda41437362466c4;hpb=0a90e07193a237900913ac3eb11cde08526a8964;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp index 0e8ec23d6..bd53679d9 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp @@ -1,37 +1,16 @@ #include -#include #include +#include -#include #include -#include -#include -#include -#include -#include - -#include -#include +#include #include -static double squareDistance( - StoragePtr theStorage, const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) -{ - Slvs_Entity aPoint1 = theStorage->getEntity(thePoint1); - Slvs_Entity aPoint2 = theStorage->getEntity(thePoint2); - double x1 = theStorage->getParameter(aPoint1.param[0]).val; - double y1 = theStorage->getParameter(aPoint1.param[1]).val; - double x2 = theStorage->getParameter(aPoint2.param[0]).val; - double y2 = theStorage->getParameter(aPoint2.param[1]).val; - return (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2); -} - void SketchSolver_ConstraintMultiRotation::getAttributes( - Slvs_hEntity& theCenter, double& theAngle, - std::vector >& thePoints, - std::vector >& theCircular) + EntityWrapperPtr& theCenter, double& theAngle, + bool& theFullValue, std::list& theEntities) { DataPtr aData = myBaseConstraint->data(); theAngle = std::dynamic_pointer_cast( @@ -42,337 +21,162 @@ void SketchSolver_ConstraintMultiRotation::getAttributes( myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); return; } - int aType = SLVS_E_UNKNOWN; // type of created entity - Slvs_hEntity anEntityID = myGroup->getAttributeId(aCenterAttr); - if (anEntityID == SLVS_E_UNKNOWN) - anEntityID = changeEntity(aCenterAttr, aType); - theCenter = anEntityID; - - // Lists of objects and number of copies - AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Constraint::ENTITY_A())); - myNumberOfObjects = anInitialRefList->size(); - myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID())->value(); - AttributeRefListPtr aRefList = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); - if (!aRefList) { - myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); - return; - } - // Obtain all points of initial features and store them into separate lists - // containing their translated copies. - // Also all circles and arc collected too, because they will be constrained by equal radii. - FeaturePtr aFeature; - ResultConstructionPtr aRC; - std::vector aPoints[2]; // lists of points of features - std::vector aCircs; // list of circular objects - std::list anObjectList = aRefList->list(); - std::list::iterator anObjectIter = anObjectList.begin(); - while (anObjectIter != anObjectList.end()) { - aPoints[0].clear(); - aPoints[1].clear(); - aCircs.clear(); - - for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) { - aFeature = ModelAPI_Feature::feature(*anObjectIter); - if (!aFeature) - continue; - anEntityID = changeEntity(aFeature, aType); - Slvs_Entity anEntity = myStorage->getEntity(anEntityID); - switch (aType) { - case SLVS_E_POINT_IN_2D: - case SLVS_E_POINT_IN_3D: - aPoints[0].push_back(anEntityID); - break; - case SLVS_E_LINE_SEGMENT: - aPoints[0].push_back(anEntity.point[0]); // start point of line - aPoints[1].push_back(anEntity.point[1]); // end point of line - break; - case SLVS_E_CIRCLE: - aPoints[0].push_back(anEntity.point[0]); // center of circle - aCircs.push_back(anEntityID); - break; - case SLVS_E_ARC_OF_CIRCLE: - aPoints[0].push_back(anEntity.point[1]); // start point of arc - aPoints[1].push_back(anEntity.point[2]); // end point of arc - aCircs.push_back(anEntityID); - break; - default: - myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); - return; - } - } + myType = CONSTRAINT_MULTI_ROTATION; - if (!aPoints[0].empty()) - thePoints.push_back(aPoints[0]); - if (!aPoints[1].empty()) - thePoints.push_back(aPoints[1]); - if (!aCircs.empty()) - theCircular.push_back(aCircs); - } + myStorage->update(aCenterAttr); + theCenter = myStorage->entity(aCenterAttr); + + AttributeStringPtr aMethodTypeAttr = aData->string(SketchPlugin_MultiRotation::ANGLE_TYPE()); + theFullValue = aMethodTypeAttr->value() != "SingleAngle"; + + getEntities(theEntities); } void SketchSolver_ConstraintMultiRotation::process() { cleanErrorMsg(); - if (!myBaseConstraint || !myStorage || myGroup == 0) { + if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) { /// TODO: Put error message here return; } - if (!mySlvsConstraints.empty()) // some data is changed, update constraint - update(myBaseConstraint); - Slvs_hEntity aCenter; - std::vector > aPointsAndCopies; - std::vector > aCircsAndCopies; - getAttributes(aCenter, myAngle, aPointsAndCopies, aCircsAndCopies); + EntityWrapperPtr aRotationCenter; + bool isFullValue; + std::list aBaseEntities; + getAttributes(aRotationCenter, myAngle, isFullValue, aBaseEntities); if (!myErrorMsg.empty()) return; - myAuxLines.clear(); - - // Create lines between neighbor rotated points and make angle between them equal to anAngle. - // Also these lines should have equal lengths. - Slvs_Constraint aConstraint; - myRotationCenter = aCenter; - Slvs_Entity aPrevLine; - std::vector >::iterator aCopyIter = aPointsAndCopies.begin(); - for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) { - size_t aSize = aCopyIter->size(); - if (aSize <= 1) continue; - - aPrevLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(), - myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[0]); - aPrevLine.h = myStorage->addEntity(aPrevLine); - std::vector anEqualLines(1, aPrevLine.h); - for (size_t i = 1; i < aSize; i++) { - Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(), - myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[i]); - aLine.h = myStorage->addEntity(aLine); - // Equal length constraint - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0, - SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aPrevLine.h, aLine.h); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - // Angle constraint - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_ANGLE, myGroup->getWorkplaneId(), fabs(myAngle), SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, - aPrevLine.h, aLine.h); - if (myAngle < 0.0) // clockwise rotation - aConstraint.other = true; - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - - aPrevLine = aLine; - anEqualLines.push_back(aPrevLine.h); - } + BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + std::list aRotConstraints; - myAuxLines.push_back(anEqualLines); - } - // Equal radii constraints - for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) { - size_t aSize = aCopyIter->size(); - for (size_t i = 0; i < aSize - 1; i++) { - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, - (*aCopyIter)[i], (*aCopyIter)[i+1]); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - } - } - - // Set the rotation center unchanged during constraint recalculation - if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) { - aConstraint = Slvs_MakeConstraint( - SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0, - myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); + std::list::iterator anEntIt = aBaseEntities.begin(); + for (; anEntIt != aBaseEntities.end(); ++anEntIt) { + std::list aNewConstraints = + aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType, + myAngle, isFullValue, aRotationCenter, EntityWrapperPtr(), std::list(1, *anEntIt)); + aRotConstraints.insert(aRotConstraints.end(), aNewConstraints.begin(), aNewConstraints.end()); } + myStorage->addConstraint(myBaseConstraint, aRotConstraints); + myAdjusted = false; adjustConstraint(); } -void SketchSolver_ConstraintMultiRotation::update(ConstraintPtr theConstraint) +void SketchSolver_ConstraintMultiRotation::updateLocal() { - cleanErrorMsg(); - if (!theConstraint || theConstraint == myBaseConstraint) { - AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID()); - if (anInitialRefList->size() != myNumberOfObjects || aNbCopies->value() != myNumberOfCopies) { - remove(myBaseConstraint); - process(); - return; - } - } - - // update angle value - myAngle = std::dynamic_pointer_cast( + double aValue = std::dynamic_pointer_cast( myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value(); + if (fabs(myAngle - aValue) > tolerance) + myAdjusted = false; + // update angle value + myAngle = aValue; - SketchSolver_Constraint::update(); -} + // update center + DataPtr aData = myBaseConstraint->data(); + AttributePoint2DPtr aCenterPointAttribute = GeomDataAPI_Point2D::getPoint2D(aData, + SketchPlugin_MultiRotation::CENTER_ID()); + bool aCenterPointChanged = aCenterPointAttribute != myCenterPointAttribute; + if (aCenterPointChanged) + myCenterPointAttribute = aCenterPointAttribute; + + AttributeStringPtr aMethodTypeAttr = aData->string(SketchPlugin_MultiRotation::ANGLE_TYPE()); + bool aFullValue = aMethodTypeAttr->value() != "SingleAngle"; + bool isMethodChanged = aFullValue != myIsFullValue; + if (isMethodChanged) + myIsFullValue = aFullValue; + + if (aCenterPointChanged || isMethodChanged) { + DataPtr aData = myBaseConstraint->data(); + std::list aConstraints = myStorage->constraint(myBaseConstraint); + std::list::const_iterator anIt = aConstraints.begin(), + aLast = aConstraints.end(); + std::list anEntities; + for (; anIt != aLast; anIt++) { + ConstraintWrapperPtr aConstraint = *anIt; + aConstraint->setIsFullValue(myIsFullValue); + if (aCenterPointChanged) { + anEntities.clear(); + const std::list& aConstraintEntities = aConstraint->entities(); + std::list::const_iterator aSIt = aConstraintEntities.begin(), + aSLast = aConstraintEntities.end(); + EntityWrapperPtr aCenterPointEntity = *aSIt++; + if (aCenterPointChanged) { + AttributePtr aCenterPointAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID()); + myStorage->update(aCenterPointAttr); + aCenterPointEntity = myStorage->entity(aCenterPointAttr); + } + anEntities.push_back(aCenterPointEntity); + + for (; aSIt != aSLast; ++aSIt) + anEntities.push_back(*aSIt); + + aConstraint->setEntities(anEntities); + } + } + myStorage->addConstraint(myBaseConstraint, aConstraints); -bool SketchSolver_ConstraintMultiRotation::remove(ConstraintPtr theConstraint) -{ - cleanErrorMsg(); - if (theConstraint && theConstraint != myBaseConstraint) - return false; - bool isFullyRemoved = true; - std::vector::iterator aCIter = mySlvsConstraints.begin(); - for (; aCIter != mySlvsConstraints.end(); aCIter++) - isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; - mySlvsConstraints.clear(); - - std::map::iterator aFeatIt = myFeatureMap.begin(); - for (; aFeatIt != myFeatureMap.end(); aFeatIt++) - myStorage->removeEntity(aFeatIt->second); - - if (isFullyRemoved) { - myFeatureMap.clear(); - myAttributeMap.clear(); - myValueMap.clear(); - } else - cleanRemovedEntities(); - return true; + myAdjusted = false; + } } void SketchSolver_ConstraintMultiRotation::adjustConstraint() { - if (abs(myAngle) < tolerance) { + if (myAdjusted) + return; + + if (fabs(myAngle) < tolerance) { myStorage->setNeedToResolve(false); return; } - // Check the lengths of auxiliary lines are zero. - // If they become zero, remove corresponding Angle constraints. - // It they become non-zero (but were zero recently), add Angle constraint. - std::vector::iterator aConstr = mySlvsConstraints.begin(); - std::map anEqualLines; - bool isFirstRemoved = false; - for (; aConstr != mySlvsConstraints.end(); - isFirstRemoved ? aConstr = mySlvsConstraints.begin() : ++aConstr) { - isFirstRemoved = false; - Slvs_Constraint aConstraint = myStorage->getConstraint(*aConstr); - if (aConstraint.type == SLVS_C_ANGLE || aConstraint.type == SLVS_C_EQUAL_LENGTH_LINES) { - Slvs_Entity aLine = myStorage->getEntity(aConstraint.entityA); - // Line length became zero => remove constraint - if (squareDistance(myStorage, aLine.point[0], aLine.point[1]) < tolerance * tolerance) { - myStorage->removeConstraint(aConstraint.h); - isFirstRemoved = aConstr == mySlvsConstraints.begin(); - std::vector::iterator aTmpIter = aConstr--; - mySlvsConstraints.erase(aTmpIter); - } - // Store the lines into the map - anEqualLines[aConstraint.entityB] = aConstraint.entityA; - } - } - // Create Angle and Equal constraints for non-degenerated lines - AuxLinesList::iterator anIt = myAuxLines.begin(); - for (; anIt != myAuxLines.end(); ++anIt) { - if (anEqualLines.find(anIt->back()) != anEqualLines.end()) - continue; - - std::vector::iterator anEqLinesIt = anIt->begin(); - Slvs_hEntity aPrevLine = (*anEqLinesIt); - // Check the length of the line - Slvs_Entity aLine = myStorage->getEntity(aPrevLine); - if (squareDistance(myStorage, aLine.point[0], aLine.point[1]) < tolerance * tolerance) - continue; - - for (++anEqLinesIt; anEqLinesIt != anIt->end(); ++anEqLinesIt) { - Slvs_hEntity aLine = (*anEqLinesIt); - // Equal length constraint - Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0, - SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aPrevLine, aLine); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - // Angle constraint - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_ANGLE, myGroup->getWorkplaneId(), fabs(myAngle), SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, - aPrevLine, aLine); - if (myAngle < 0.0) // clockwise rotation - aConstraint.other = true; - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - - aPrevLine = aLine; - } - } + const std::list& aConstraints = myStorage->constraint(myBaseConstraint); + std::list::const_iterator aCIt = aConstraints.begin(); + for (; aCIt != aConstraints.end(); ++aCIt) + (*aCIt)->setValue(myAngle); // Obtain coordinates of rotation center - Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter); - double aCenterXY[2]; - for (int i = 0; i < 2; i++) - aCenterXY[i] = myStorage->getParameter(aRotCenter.param[i]).val; - - double cosA = cos(myAngle * PI / 180.0); - double sinA = sin(myAngle * PI / 180.0); - - // Update positions of all points to satisfy angles - std::list aConstrAngle = myStorage->getConstraintsByType(SLVS_C_ANGLE); - std::list::iterator anAngIt = aConstrAngle.begin(); - std::vector::iterator aCIt; - Slvs_hConstraint aFixed; // temporary variable - double aVec[2]; // coordinates of vector defining a line - Slvs_Param aTarget[2]; // parameter to be changed - for (; anAngIt != aConstrAngle.end(); anAngIt++) { - for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++) - if (anAngIt->h == *aCIt) - break; - if (aCIt == mySlvsConstraints.end()) - continue; - Slvs_Entity aLineA = myStorage->getEntity(anAngIt->entityA); - Slvs_Entity aLineB = myStorage->getEntity(anAngIt->entityB); - if (myStorage->isPointFixed(aLineB.point[1], aFixed)) - continue; - Slvs_Entity aPointA = myStorage->getEntity(aLineA.point[1]); - Slvs_Entity aPointB = myStorage->getEntity(aLineB.point[1]); - for (int i = 0; i < 2; i++) { - aVec[i] = myStorage->getParameter(aPointA.param[i]).val - aCenterXY[i]; - aTarget[i] = myStorage->getParameter(aPointB.param[i]); - } - aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA; - aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA; - myStorage->updateParameter(aTarget[0]); - myStorage->updateParameter(aTarget[1]); + EntityWrapperPtr aRotCenter = myStorage->entity( + myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID())); + std::list aParams = aRotCenter->parameters(); + myCenterCoord[0] = aParams.front()->value(); + myCenterCoord[1] = aParams.back()->value(); - anAngIt->valA = myAngle; - myStorage->updateConstraint(*anAngIt); - } + double anAngleValue = myAngle; + if (myIsFullValue && myNumberOfCopies > 0) + anAngleValue /= myNumberOfCopies; - // update positions of centers of arcs for correct radius calculation - std::list aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS); - std::map::iterator aFeatIt; - for (anAngIt = aRadii.begin(); anAngIt != aRadii.end(); anAngIt++) { - int aNbFound = 0; // number of arcs used in translation - for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++) - if (aFeatIt->second == anAngIt->entityA || aFeatIt->second == anAngIt->entityB) { - if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID()) - aNbFound++; - else - break; - } - if (aNbFound != 2) - continue; - // two arcs were found, update their centers - Slvs_Entity anArcA = myStorage->getEntity(anAngIt->entityA); - Slvs_Entity anArcB = myStorage->getEntity(anAngIt->entityB); - if (myStorage->isPointFixed(anArcB.point[0], aFixed)) - continue; - Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]); - Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]); - for (int i = 0; i < 2; i++) { - aVec[i] = myStorage->getParameter(aCenterA.param[i]).val - aCenterXY[i]; - aTarget[i] = myStorage->getParameter(aCenterB.param[i]); - } - aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA; - aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA; - myStorage->updateParameter(aTarget[0]); - myStorage->updateParameter(aTarget[1]); - } + myRotationVal[0] = sin(anAngleValue * PI / 180.0); + myRotationVal[1] = cos(anAngleValue * PI / 180.0); + + SketchSolver_ConstraintMulti::adjustConstraint(); +} + +void SketchSolver_ConstraintMultiRotation::getRelative( + double theAbsX, double theAbsY, double& theRelX, double& theRelY) +{ + theRelX = theAbsX - myCenterCoord[0]; + theRelY = theAbsY - myCenterCoord[1]; +} + +void SketchSolver_ConstraintMultiRotation::getAbsolute( + double theRelX, double theRelY, double& theAbsX, double& theAbsY) +{ + theAbsX = theRelX + myCenterCoord[0]; + theAbsY = theRelY + myCenterCoord[1]; +} + +void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY) +{ + // rotate direction + // myRotationVal[0] = sinA, myRotationVal[1] = cosA + double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0]; + theY = theX * myRotationVal[0] + theY * myRotationVal[1]; + theX = aTemp; +} + +const std::string& SketchSolver_ConstraintMultiRotation::nameNbObjects() +{ + return SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID(); }