Salome HOME
Fix the problem of the updating of "multi" constraints
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMultiRotation.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 #include <SketchSolver_ConstraintMultiRotation.h>
4 #include <SketchSolver_Error.h>
5 #include <SketchSolver_Manager.h>
6
7 #include <PlaneGCSSolver_AttributeBuilder.h>
8 #include <PlaneGCSSolver_PointWrapper.h>
9 #include <PlaneGCSSolver_ScalarWrapper.h>
10 #include <PlaneGCSSolver_UpdateFeature.h>
11
12 #include <SketchPlugin_MultiRotation.h>
13
14 #include <ModelAPI_AttributeString.h>
15
16 #include <cmath>
17
18 void SketchSolver_ConstraintMultiRotation::getAttributes(
19     EntityWrapperPtr& theCenter, ScalarWrapperPtr& theAngle,
20     bool& theFullValue, std::list<EntityWrapperPtr>& theEntities)
21 {
22   AttributePtr anAngleAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID());
23   PlaneGCSSolver_AttributeBuilder aValueBuilder;
24   theAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(
25       aValueBuilder.createAttribute(anAngleAttr));
26   myStorage->addEntity(anAngleAttr, theAngle);
27
28   AttributeRefAttrPtr aCenterAttr =
29       myBaseConstraint->refattr(SketchPlugin_MultiRotation::CENTER_ID());
30   if (!aCenterAttr || !aCenterAttr->isInitialized()) {
31     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
32     return;
33   }
34
35   myType = CONSTRAINT_MULTI_ROTATION;
36
37   myStorage->update(AttributePtr(aCenterAttr));
38   theCenter = myStorage->entity(AttributePtr(aCenterAttr));
39
40   AttributeStringPtr aMethodTypeAttr =
41       myBaseConstraint->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
42   theFullValue = aMethodTypeAttr->value() != "SingleAngle";
43
44   getEntities(theEntities);
45
46   // add owner of central point of Multi-Rotation to the list of monitored features
47   FeaturePtr anOwner = ModelAPI_Feature::feature(aCenterAttr->attr()->owner());
48   if (anOwner)
49     myOriginalFeatures.insert(anOwner);
50 }
51
52 void SketchSolver_ConstraintMultiRotation::process()
53 {
54   cleanErrorMsg();
55   if (!myBaseConstraint || !myStorage) {
56     // Not enough parameters are assigned
57     return;
58   }
59
60   EntityWrapperPtr aRotationCenter;
61   std::list<EntityWrapperPtr> aBaseEntities;
62   getAttributes(aRotationCenter, myAngle, myIsFullValue, aBaseEntities);
63   if (!myErrorMsg.empty())
64     return;
65
66   myAdjusted = false;
67   adjustConstraint();
68
69   myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
70 }
71
72 void SketchSolver_ConstraintMultiRotation::updateLocal()
73 {
74   double aValue = myBaseConstraint->real(SketchPlugin_MultiRotation::ANGLE_ID())->value();
75   if (fabs(myAngle->value() - aValue) > tolerance)
76     myAdjusted = false;
77   // update angle value
78   myAngle->setValue(aValue);
79
80   // update center
81   DataPtr aData = myBaseConstraint->data();
82   AttributePoint2DPtr aCenterPointAttribute = GeomDataAPI_Point2D::getPoint2D(aData,
83                                            SketchPlugin_MultiRotation::CENTER_ID());
84   bool aCenterPointChanged = aCenterPointAttribute != myCenterPointAttribute;
85   if (aCenterPointChanged)
86     myCenterPointAttribute = aCenterPointAttribute;
87
88   AttributeStringPtr aMethodTypeAttr = aData->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
89   bool aFullValue = aMethodTypeAttr->value() != "SingleAngle";
90   bool isMethodChanged = aFullValue != myIsFullValue;
91   if (isMethodChanged)
92     myIsFullValue = aFullValue;
93
94   if (aCenterPointChanged || isMethodChanged)
95     myAdjusted = false;
96 }
97
98 void SketchSolver_ConstraintMultiRotation::adjustConstraint()
99 {
100   if (myAdjusted)
101     return;
102
103   double anAngleValue = myAngle->value();
104   if (fabs(anAngleValue) < tolerance) {
105     myStorage->setNeedToResolve(false);
106     return;
107   }
108
109   // Obtain coordinates of rotation center
110   std::shared_ptr<PlaneGCSSolver_PointWrapper> aRotCenter =
111       std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myStorage->entity(
112       myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID())));
113   GCSPointPtr aCenterPoint = aRotCenter->point();
114   myCenterCoord[0] = *(aCenterPoint->x);
115   myCenterCoord[1] = *(aCenterPoint->y);
116
117   if (myIsFullValue && myNumberOfCopies > 0)
118     anAngleValue /= myNumberOfCopies;
119
120   myRotationVal[0] = sin(anAngleValue * PI / 180.0);
121   myRotationVal[1] = cos(anAngleValue * PI / 180.0);
122
123   SketchSolver_ConstraintMulti::adjustConstraint();
124 }
125
126 void SketchSolver_ConstraintMultiRotation::getRelative(
127     double theAbsX, double theAbsY, double& theRelX, double& theRelY)
128 {
129   theRelX = theAbsX - myCenterCoord[0];
130   theRelY = theAbsY - myCenterCoord[1];
131 }
132
133 void SketchSolver_ConstraintMultiRotation::getAbsolute(
134     double theRelX, double theRelY, double& theAbsX, double& theAbsY)
135 {
136   theAbsX = theRelX + myCenterCoord[0];
137   theAbsY = theRelY + myCenterCoord[1];
138 }
139
140 void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY)
141 {
142   // rotate direction
143   // myRotationVal[0] = sinA, myRotationVal[1] = cosA
144   double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0];
145   theY = theX * myRotationVal[0] + theY * myRotationVal[1];
146   theX = aTemp;
147 }
148
149 const std::string& SketchSolver_ConstraintMultiRotation::nameNbObjects()
150 {
151   return SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID();
152 }