X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintMultiRotation.cpp;h=cf2cac48aab28cee9cf02c1e0e9a49e9574ff8d0;hb=97c06c5cd9fc736f9b5a1dacde369a9d7b5be703;hp=d93983f721985c2cb98e7f9d57a0bedb1d8f1f4a;hpb=58c49c9bea03fb99e7d94fdbe2f95516b76e593a;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp index d93983f72..cf2cac48a 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp @@ -1,356 +1,194 @@ +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + #include -#include #include +#include -#include -#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); -} +#include void SketchSolver_ConstraintMultiRotation::getAttributes( - Slvs_hEntity& theCenter, double& theAngle, - std::vector< std::vector >& thePoints, - std::vector< std::vector >& theEntities) + EntityWrapperPtr& theCenter, ScalarWrapperPtr& theAngle, + bool& theFullValue, bool& theReversed, std::list& theEntities) { - DataPtr aData = myBaseConstraint->data(); - theAngle = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value(); - - AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID()); + AttributePtr anAngleAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()); + PlaneGCSSolver_AttributeBuilder aValueBuilder; + theAngle = std::dynamic_pointer_cast( + aValueBuilder.createAttribute(anAngleAttr)); + myStorage->addEntity(anAngleAttr, theAngle); + + AttributeRefAttrPtr aCenterAttr = + myBaseConstraint->refattr(SketchPlugin_MultiRotation::CENTER_ID()); if (!aCenterAttr || !aCenterAttr->isInitialized()) { 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; - } + myType = CONSTRAINT_MULTI_ROTATION; - // 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; - static const size_t MAX_POINTS = 3; - std::vector aPoints[MAX_POINTS]; // lists of points of features - std::vector anEntities; - std::list anObjectList = aRefList->list(); - std::list::iterator anObjectIter = anObjectList.begin(); - while (anObjectIter != anObjectList.end()) { - for (size_t i = 0; i < MAX_POINTS; ++i) - aPoints[i].clear(); - anEntities.clear(); + myStorage->update(AttributePtr(aCenterAttr)); + theCenter = myStorage->entity(AttributePtr(aCenterAttr)); - for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) { - aFeature = ModelAPI_Feature::feature(*anObjectIter); - if (!aFeature) - continue; - anEntityID = changeEntity(aFeature, aType); - anEntities.push_back(anEntityID); - 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 - break; - case SLVS_E_ARC_OF_CIRCLE: - aPoints[0].push_back(anEntity.point[0]); // center of arc - aPoints[1].push_back(anEntity.point[1]); // start point of arc - aPoints[2].push_back(anEntity.point[2]); // end point of arc - break; - default: - myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); - return; - } - } + AttributeStringPtr aMethodTypeAttr = + myBaseConstraint->string(SketchPlugin_MultiRotation::ANGLE_TYPE()); + theFullValue = aMethodTypeAttr->value() != "SingleAngle"; - for (size_t i = 0; i < MAX_POINTS; ++i) - if (!aPoints[i].empty()) - thePoints.push_back(aPoints[i]); - if (!anEntities.empty()) - theEntities.push_back(anEntities); - } + theReversed = myBaseConstraint->boolean(SketchPlugin_MultiRotation::REVERSED_ID())->value(); + + getEntities(theEntities); + + // add owner of central point of Multi-Rotation to the list of monitored features + FeaturePtr anOwner = ModelAPI_Feature::feature(aCenterAttr->attr()->owner()); + if (anOwner) + myOriginalFeatures.insert(anOwner); } void SketchSolver_ConstraintMultiRotation::process() { cleanErrorMsg(); - if (!myBaseConstraint || !myStorage || myGroup == 0) { - /// TODO: Put error message here + if (!myBaseConstraint || !myStorage) { + // Not enough parameters are assigned return; } - if (!mySlvsConstraints.empty()) // some data is changed, update constraint - update(myBaseConstraint); - std::vector > anEntitiesAndCopies; - getAttributes(myRotationCenter, myAngle, myPointsAndCopies, anEntitiesAndCopies); + EntityWrapperPtr aRotationCenter; + std::list aBaseEntities; + getAttributes(aRotationCenter, myAngle, myIsFullValue, myIsRevered, aBaseEntities); if (!myErrorMsg.empty()) return; - // Set the rotation center unchanged during constraint recalculation - Slvs_Constraint aConstraint; - 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); - } - - // Keep all objects unchanged (only initial object may be changed by user) - myCircsAndCopies.clear(); - std::vector >::const_iterator anEntIt = anEntitiesAndCopies.begin(); - std::vector::const_iterator aCpIt; - for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) { - std::vector aCircs; - aCpIt = anEntIt->begin(); - // Obtain initial points - Slvs_Entity anInitial = myStorage->getEntity(*aCpIt); - if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D) - myInitialPoints.insert(anInitial.h); - else { - for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++) - myInitialPoints.insert(anInitial.point[i]); - } - - // Fix the copies - for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) { - const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt); - std::vector aNewConstr; - if (anEntity.type == SLVS_E_CIRCLE) { - aCircs.push_back(anEntity.distance); - // for circles we fix only center - aNewConstr = myStorage->fixEntity(anEntity.point[0]); - } else - aNewConstr = myStorage->fixEntity(*aCpIt); - mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end()); - } - - if (!aCircs.empty()) - myCircsAndCopies.push_back(aCircs); - } - + myAdjusted = false; adjustConstraint(); + + myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP()); } -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; - } - } - + double aValue = myBaseConstraint->real(SketchPlugin_MultiRotation::ANGLE_ID())->value(); + bool isReversed = myBaseConstraint->boolean(SketchPlugin_MultiRotation::REVERSED_ID())->value(); + if (fabs(myAngle->value() - aValue) > tolerance || isReversed != myIsRevered) + myAdjusted = false; // update angle value - myAngle = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value(); + myAngle->setValue(aValue); + myIsRevered = isReversed; - 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) + myAdjusted = false; } -bool SketchSolver_ConstraintMultiRotation::remove(ConstraintPtr theConstraint) +void SketchSolver_ConstraintMultiRotation::adjustConstraint() { - 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); - myStorage->removeUnusedEntities(); + if (myAdjusted) + return; - std::map aFeatureMapCopy = myFeatureMap; + double anAngleValue = myAngle->value(); + if (fabs(anAngleValue) < tolerance) { + myStorage->setNeedToResolve(false); + return; + } + if (myIsRevered) + anAngleValue *= -1.0; - if (isFullyRemoved) { - myFeatureMap.clear(); - myAttributeMap.clear(); - myValueMap.clear(); - } else - cleanRemovedEntities(); + // Obtain coordinates of rotation center + AttributeRefAttrPtr aCenterAttr = + myBaseConstraint->refattr(SketchPlugin_MultiRotation::CENTER_ID()); + std::shared_ptr aRotCenter = + std::dynamic_pointer_cast( + myStorage->entity(AttributePtr(aCenterAttr))); + if (aRotCenter) + { + GCSPointPtr aCenterPoint = aRotCenter->point(); + myCenterCoord[0] = *(aCenterPoint->x); + myCenterCoord[1] = *(aCenterPoint->y); + } + else + { + AttributePoint2DPtr aCenterPnt = + std::dynamic_pointer_cast(aCenterAttr->attr()); + myCenterCoord[0] = aCenterPnt->x(); + myCenterCoord[1] = aCenterPnt->y(); + } - // Restore initial features - std::map::iterator aFIter = aFeatureMapCopy.begin(); - for (; aFIter != aFeatureMapCopy.end(); ++aFIter) + if (myIsFullValue && myNumberOfCopies > 0) { - if (myFeatureMap.find(aFIter->first) != myFeatureMap.end()) - continue; // the feature was not removed - Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first); - if (anEntity != SLVS_E_UNKNOWN) - myFeatureMap[aFIter->first] = anEntity; + // if the full angle value is equal to 360, then distribute rotated items + // to avoid superposition of original feature and last copy + if (fabs(anAngleValue - 360.0) < 1.e-7) + anAngleValue /= (myNumberOfCopies + 1); + else + anAngleValue /= myNumberOfCopies; } - // Clear list of rotated points - myPointsAndCopies.clear(); - myInitialPoints.clear(); + myRotationVal[0] = sin(anAngleValue * PI / 180.0); + myRotationVal[1] = cos(anAngleValue * PI / 180.0); - return true; + SketchSolver_ConstraintMulti::adjustConstraint(); } -void SketchSolver_ConstraintMultiRotation::addFeature(FeaturePtr theFeature) +void SketchSolver_ConstraintMultiRotation::getRelative( + double theAbsX, double theAbsY, double& theRelX, double& theRelY) { - SketchSolver_Constraint::addFeature(theFeature); - - std::map::iterator aFeatIt = myFeatureMap.find(theFeature); - if (aFeatIt == myFeatureMap.end()) - return; - - // store list of points of the feature - const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second); - for (int i = 0; i < 4; i++) - if (theEntity.point[i] != SLVS_E_UNKNOWN) - myPointsJustUpdated.insert(theEntity.point[i]); + theRelX = theAbsX - myCenterCoord[0]; + theRelY = theAbsY - myCenterCoord[1]; } -void SketchSolver_ConstraintMultiRotation::adjustConstraint() +void SketchSolver_ConstraintMultiRotation::getAbsolute( + double theRelX, double theRelY, double& theAbsX, double& theAbsY) { - if (abs(myAngle) < tolerance) { - myStorage->setNeedToResolve(false); - return; - } - - std::list aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT); - std::list::const_iterator aCoIt; - - // Check overconstrained on rotation center (if it is coincident with other fixed point) - Slvs_hConstraint aFixedCenter; - if (myStorage->isPointFixed(myRotationCenter, aFixedCenter, false)) { - Slvs_hConstraint aFixed; - for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) - if ((aCoIt->ptA == myRotationCenter && myStorage->isPointFixed(aCoIt->ptB, aFixed, true)) || - (aCoIt->ptB == myRotationCenter && myStorage->isPointFixed(aCoIt->ptA, aFixed, true))) { - // Un-fix the center - myStorage->removeConstraint(aFixedCenter); - std::vector::iterator aSCIt = mySlvsConstraints.begin(); - for (; aSCIt != mySlvsConstraints.end(); ++aSCIt) - if (*aSCIt == aFixedCenter) { - mySlvsConstraints.erase(aSCIt); - break; - } - } - } - - // 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); - - double aVec[2]; // coordinates of vector defining a direction from rotation center to a point - - // Update positions of all points to satisfy angles - std::vector< std::vector >::const_iterator aPointsIter = myPointsAndCopies.begin(); - std::vector::const_iterator aCopyIter; - for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) { - aCopyIter = aPointsIter->begin(); - const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); - for (int i = 0; i < 2; i++) - aVec[i] = myStorage->getParameter(anInitial.param[i]).val - aCenterXY[i]; - - // if the point is coincident with another one which is temporary fixed (moved by user), - // we will update its position correspondingly - Slvs_hConstraint aFixed; - for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) { - if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) || - (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) { - Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA; - if (!myStorage->isTemporary(aFixed) && - myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end()) - continue; // nothing to change - - const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId); - for (int i = 0; i < 2; i++) { - Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]); - const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]); - anInitParam.val = anOtherParam.val; - myStorage->updateParameter(anInitParam); - aVec[i] = anOtherParam.val - aCenterXY[i]; - } - } - } - - // update copied points - aCopyIter = aPointsIter->begin(); - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - // rotate direction - double aTemp = aVec[0] * cosA - aVec[1] * sinA; - aVec[1] = aVec[0] * sinA + aVec[1] * cosA; - aVec[0] = aTemp; - - const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter); - for (int i = 0; i < 2; i++) { - Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]); - aParam.val = aCenterXY[i] + aVec[i]; - myStorage->updateParameter(aParam); - } - } - } + theAbsX = theRelX + myCenterCoord[0]; + theAbsY = theRelY + myCenterCoord[1]; +} - for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) { - aCopyIter = aPointsIter->begin(); - const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); - const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]); - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter); - Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]); - aCopyRad.val = anInitRad.val; - myStorage->updateParameter(aCopyRad); - } - } +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; +} - myPointsJustUpdated.clear(); +const std::string& SketchSolver_ConstraintMultiRotation::nameNbObjects() +{ + return SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID(); }