Salome HOME
Merge Dev_2.1.0 with PythonAPI branch
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMultiRotation.cpp
1 #include <SketchSolver_ConstraintMultiRotation.h>
2 #include <SketchSolver_Group.h>
3 #include <SketchSolver_Error.h>
4
5 #include <SketchPlugin_Arc.h>
6 #include <SketchPlugin_MultiRotation.h>
7
8 #include <ModelAPI_AttributeDouble.h>
9 #include <ModelAPI_AttributeInteger.h>
10 #include <ModelAPI_AttributeRefAttr.h>
11 #include <ModelAPI_AttributeRefList.h>
12 #include <ModelAPI_ResultConstruction.h>
13
14 #include <GeomAPI_Dir2d.h>
15 #include <GeomAPI_XY.h>
16
17 #include <math.h>
18
19 void SketchSolver_ConstraintMultiRotation::getAttributes(
20     Slvs_hEntity& theCenter, double& theAngle,
21     std::vector< std::vector<Slvs_hEntity> >& thePoints,
22     std::vector< std::vector<Slvs_hEntity> >& theEntities)
23 {
24   DataPtr aData = myBaseConstraint->data();
25   theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
26       aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
27
28   AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
29   if (!aCenterAttr || !aCenterAttr->isInitialized()) {
30     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
31     return;
32   }
33   int aType = SLVS_E_UNKNOWN; // type of created entity
34   Slvs_hEntity anEntityID = myGroup->getAttributeId(aCenterAttr);
35   if (anEntityID == SLVS_E_UNKNOWN)
36     anEntityID = changeEntity(aCenterAttr, aType);
37   theCenter = anEntityID;
38
39   // Lists of objects and number of copies
40   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
41       aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
42   myNumberOfObjects = anInitialRefList->size();
43   myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1;
44   if (myNumberOfCopies <= 0)
45     return;
46   AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
47       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
48   if (!aRefList) {
49     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
50     return;
51   }
52
53   // Obtain all points of initial features and store them into separate lists
54   // containing their translated copies.
55   // Also all circles and arc collected too, because they will be constrained by equal radii.
56   FeaturePtr aFeature;
57   ResultConstructionPtr aRC;
58   static const size_t MAX_POINTS = 3;
59   std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
60   std::vector<Slvs_hEntity> anEntities;
61   std::list<ObjectPtr> anObjectList = aRefList->list();
62   std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
63   while (anObjectIter != anObjectList.end()) {
64     for (size_t i = 0; i < MAX_POINTS; ++i)
65       aPoints[i].clear();
66     anEntities.clear();
67
68     for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
69       aFeature = ModelAPI_Feature::feature(*anObjectIter);
70       if (!aFeature)
71         continue;
72       anEntityID = changeEntity(aFeature, aType);
73       anEntities.push_back(anEntityID);
74       Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
75       switch (aType) {
76       case SLVS_E_POINT_IN_2D:
77       case SLVS_E_POINT_IN_3D:
78         aPoints[0].push_back(anEntityID);
79         break;
80       case SLVS_E_LINE_SEGMENT:
81         aPoints[0].push_back(anEntity.point[0]); // start point of line
82         aPoints[1].push_back(anEntity.point[1]); // end point of line
83         break;
84       case SLVS_E_CIRCLE:
85         aPoints[0].push_back(anEntity.point[0]); // center of circle
86         break;
87       case SLVS_E_ARC_OF_CIRCLE:
88         aPoints[0].push_back(anEntity.point[0]); // center of arc
89         aPoints[1].push_back(anEntity.point[1]); // start point of arc
90         aPoints[2].push_back(anEntity.point[2]); // end point of arc
91         break;
92       default:
93         myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
94         return;
95       }
96     }
97
98     for (size_t i = 0; i < MAX_POINTS; ++i)
99       if (!aPoints[i].empty())
100         thePoints.push_back(aPoints[i]);
101     if (!anEntities.empty())
102       theEntities.push_back(anEntities);
103   }
104 }
105
106 void SketchSolver_ConstraintMultiRotation::process()
107 {
108   cleanErrorMsg();
109   if (!myBaseConstraint || !myStorage || myGroup == 0) {
110     /// TODO: Put error message here
111     return;
112   }
113   if (!mySlvsConstraints.empty()) // some data is changed, update constraint
114     update(myBaseConstraint);
115
116   std::vector<std::vector<Slvs_hEntity> > anEntitiesAndCopies;
117   getAttributes(myRotationCenter, myAngle, myPointsAndCopies, anEntitiesAndCopies);
118   if (!myErrorMsg.empty())
119     return;
120
121   // Set the rotation center unchanged during constraint recalculation
122   Slvs_Constraint aConstraint;
123   if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
124     aConstraint = Slvs_MakeConstraint(
125         SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
126         myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
127     aConstraint.h = myStorage->addConstraint(aConstraint);
128     mySlvsConstraints.push_back(aConstraint.h);
129   }
130
131   myAdjusted = false;
132   processEntities(anEntitiesAndCopies);
133   adjustConstraint();
134 }
135
136 void SketchSolver_ConstraintMultiRotation::updateLocal()
137 {
138   double aValue = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
139       myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
140   if (fabs(myAngle - aValue) > tolerance)
141     myAdjusted = false;
142   // update angle value
143   myAngle = aValue;
144 }
145
146 void SketchSolver_ConstraintMultiRotation::adjustConstraint()
147 {
148   if (fabs(myAngle) < tolerance) {
149     myStorage->setNeedToResolve(false);
150     return;
151   }
152   if (myAdjusted)
153     return;
154
155   std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
156   std::list<Slvs_Constraint>::const_iterator aCoIt;
157
158   // Check overconstrained on rotation center (if it is coincident with other fixed point)
159   Slvs_hConstraint aFixedCenter;
160   if (myStorage->isPointFixed(myRotationCenter, aFixedCenter, false)) {
161     Slvs_hConstraint aFixed;
162     for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt)
163       if ((aCoIt->ptA == myRotationCenter && myStorage->isPointFixed(aCoIt->ptB, aFixed, true)) ||
164           (aCoIt->ptB == myRotationCenter && myStorage->isPointFixed(aCoIt->ptA, aFixed, true))) {
165         // Un-fix the center
166         myStorage->removeConstraint(aFixedCenter);
167         std::vector<Slvs_hConstraint>::iterator aSCIt = mySlvsConstraints.begin();
168         for (; aSCIt != mySlvsConstraints.end(); ++aSCIt)
169           if (*aSCIt == aFixedCenter) {
170             mySlvsConstraints.erase(aSCIt);
171             break;
172           }
173       }
174   }
175
176   // Obtain coordinates of rotation center
177   Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
178   myCenterCoord[0] = myStorage->getParameter(aRotCenter.param[0]).val;
179   myCenterCoord[1] = myStorage->getParameter(aRotCenter.param[1]).val;
180
181   myRotationVal[0] = sin(myAngle * PI / 180.0);
182   myRotationVal[1] = cos(myAngle * PI / 180.0);
183
184   SketchSolver_ConstraintMulti::adjustConstraint();
185 }
186
187 void SketchSolver_ConstraintMultiRotation::getRelative(
188     double theAbsX, double theAbsY, double& theRelX, double& theRelY)
189 {
190   theRelX = theAbsX - myCenterCoord[0];
191   theRelY = theAbsY - myCenterCoord[1];
192 }
193
194 void SketchSolver_ConstraintMultiRotation::getAbsolute(
195     double theRelX, double theRelY, double& theAbsX, double& theAbsY)
196 {
197   theAbsX = theRelX + myCenterCoord[0];
198   theAbsY = theRelY + myCenterCoord[1];
199 }
200
201 void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY)
202 {
203   // rotate direction
204   // myRotationVal[0] = sinA, myRotationVal[1] = cosA
205   double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0];
206   theY = theX * myRotationVal[0] + theY * myRotationVal[1];
207   theX = aTemp;
208 }
209
210 const std::string& SketchSolver_ConstraintMultiRotation::nameNbObjects()
211 {
212   return SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID();
213 }