1 #include <SketchSolver_ConstraintMultiRotation.h>
2 #include <SketchSolver_Group.h>
3 #include <SketchSolver_Error.h>
5 #include <SketchPlugin_Arc.h>
6 #include <SketchPlugin_MultiRotation.h>
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>
14 #include <GeomAPI_Dir2d.h>
15 #include <GeomAPI_XY.h>
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> >& theCircular)
24 DataPtr aData = myBaseConstraint->data();
25 theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
26 aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
28 AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
29 if (!aCenterAttr || !aCenterAttr->isInitialized()) {
30 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
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;
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_COPIES_ID())->value();
44 AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
45 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
47 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
51 // Obtain all points of initial features and store them into separate lists
52 // containing their translated copies.
53 // Also all circles and arc collected too, because they will be constrained by equal radii.
55 ResultConstructionPtr aRC;
56 std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
57 std::vector<Slvs_hEntity> aCircs; // list of circular objects
58 std::list<ObjectPtr> anObjectList = aRefList->list();
59 std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
60 while (anObjectIter != anObjectList.end()) {
65 for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
66 aFeature = ModelAPI_Feature::feature(*anObjectIter);
69 anEntityID = changeEntity(aFeature, aType);
70 Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
72 case SLVS_E_POINT_IN_2D:
73 case SLVS_E_POINT_IN_3D:
74 aPoints[0].push_back(anEntityID);
76 case SLVS_E_LINE_SEGMENT:
77 aPoints[0].push_back(anEntity.point[0]); // start point of line
78 aPoints[1].push_back(anEntity.point[1]); // end point of line
81 aPoints[0].push_back(anEntity.point[0]); // center of circle
82 aCircs.push_back(anEntityID);
84 case SLVS_E_ARC_OF_CIRCLE:
85 aPoints[0].push_back(anEntity.point[1]); // start point of arc
86 aPoints[1].push_back(anEntity.point[2]); // end point of arc
87 aCircs.push_back(anEntityID);
90 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
95 if (!aPoints[0].empty())
96 thePoints.push_back(aPoints[0]);
97 if (!aPoints[1].empty())
98 thePoints.push_back(aPoints[1]);
100 theCircular.push_back(aCircs);
104 void SketchSolver_ConstraintMultiRotation::process()
107 if (!myBaseConstraint || !myStorage || myGroup == 0) {
108 /// TODO: Put error message here
111 if (!mySlvsConstraints.empty()) // some data is changed, update constraint
112 update(myBaseConstraint);
114 Slvs_hEntity aCenter;
115 std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
116 std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
117 getAttributes(aCenter, myAngle, aPointsAndCopies, aCircsAndCopies);
118 if (!myErrorMsg.empty())
121 // Create lines between neighbor rotated points and make angle between them equal to anAngle.
122 // Also these lines should have equal lengths.
123 Slvs_Constraint aConstraint;
124 myRotationCenter = aCenter;
125 Slvs_Entity aPrevLine;
126 std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
127 for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
128 size_t aSize = aCopyIter->size();
129 if (aSize <= 1) continue;
131 aPrevLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
132 myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[0]);
133 aPrevLine.h = myStorage->addEntity(aPrevLine);
134 for (size_t i = 1; i < aSize; i++) {
135 Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
136 myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[i]);
137 aLine.h = myStorage->addEntity(aLine);
138 // Equal length constraint
139 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
140 SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
141 SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aPrevLine.h, aLine.h);
142 aConstraint.h = myStorage->addConstraint(aConstraint);
143 mySlvsConstraints.push_back(aConstraint.h);
145 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
146 SLVS_C_ANGLE, myGroup->getWorkplaneId(), fabs(myAngle), SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
147 aPrevLine.h, aLine.h);
148 if (myAngle < 0.0) // clockwise rotation
149 aConstraint.other = true;
150 aConstraint.h = myStorage->addConstraint(aConstraint);
151 mySlvsConstraints.push_back(aConstraint.h);
156 // Equal radii constraints
157 for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
158 size_t aSize = aCopyIter->size();
159 for (size_t i = 0; i < aSize - 1; i++) {
160 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
161 SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
162 (*aCopyIter)[i], (*aCopyIter)[i+1]);
163 aConstraint.h = myStorage->addConstraint(aConstraint);
164 mySlvsConstraints.push_back(aConstraint.h);
168 // Set the rotation center unchanged during constraint recalculation
169 if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
170 aConstraint = Slvs_MakeConstraint(
171 SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
172 myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
173 aConstraint.h = myStorage->addConstraint(aConstraint);
174 mySlvsConstraints.push_back(aConstraint.h);
180 void SketchSolver_ConstraintMultiRotation::update(ConstraintPtr theConstraint)
183 if (!theConstraint || theConstraint == myBaseConstraint) {
184 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
185 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
186 AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID());
187 if (anInitialRefList->size() != myNumberOfObjects || aNbCopies->value() != myNumberOfCopies) {
188 remove(myBaseConstraint);
194 // update angle value
195 myAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
196 myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
198 SketchSolver_Constraint::update();
201 bool SketchSolver_ConstraintMultiRotation::remove(ConstraintPtr theConstraint)
204 if (theConstraint && theConstraint != myBaseConstraint)
206 bool isFullyRemoved = true;
207 std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
208 for (; aCIter != mySlvsConstraints.end(); aCIter++)
209 isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
210 mySlvsConstraints.clear();
212 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
213 for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
214 myStorage->removeEntity(aFeatIt->second);
216 if (isFullyRemoved) {
217 myFeatureMap.clear();
218 myAttributeMap.clear();
221 cleanRemovedEntities();
225 void SketchSolver_ConstraintMultiRotation::adjustConstraint()
227 if (abs(myAngle) < tolerance) {
228 myStorage->setNeedToResolve(false);
232 // Obtain coordinates of rotation center
233 Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
235 for (int i = 0; i < 2; i++)
236 aCenterXY[i] = myStorage->getParameter(aRotCenter.param[i]).val;
238 double cosA = cos(myAngle * PI / 180.0);
239 double sinA = sin(myAngle * PI / 180.0);
241 // Update positions of all points to satisfy angles
242 std::list<Slvs_Constraint> aConstrAngle = myStorage->getConstraintsByType(SLVS_C_ANGLE);
243 std::list<Slvs_Constraint>::iterator anAngIt = aConstrAngle.begin();
244 std::vector<Slvs_hConstraint>::iterator aCIt;
245 Slvs_hConstraint aFixed; // temporary variable
246 double aVec[2]; // coordinates of vector defining a line
247 Slvs_Param aTarget[2]; // parameter to be changed
248 for (; anAngIt != aConstrAngle.end(); anAngIt++) {
249 for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
250 if (anAngIt->h == *aCIt)
252 if (aCIt == mySlvsConstraints.end())
254 Slvs_Entity aLineA = myStorage->getEntity(anAngIt->entityA);
255 Slvs_Entity aLineB = myStorage->getEntity(anAngIt->entityB);
256 if (myStorage->isPointFixed(aLineB.point[1], aFixed))
258 Slvs_Entity aPointA = myStorage->getEntity(aLineA.point[1]);
259 Slvs_Entity aPointB = myStorage->getEntity(aLineB.point[1]);
260 for (int i = 0; i < 2; i++) {
261 aVec[i] = myStorage->getParameter(aPointA.param[i]).val - aCenterXY[i];
262 aTarget[i] = myStorage->getParameter(aPointB.param[i]);
264 aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
265 aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
266 myStorage->updateParameter(aTarget[0]);
267 myStorage->updateParameter(aTarget[1]);
269 anAngIt->valA = myAngle;
270 myStorage->updateConstraint(*anAngIt);
273 // update positions of centers of arcs for correct radius calculation
274 std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
275 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
276 for (anAngIt = aRadii.begin(); anAngIt != aRadii.end(); anAngIt++) {
277 int aNbFound = 0; // number of arcs used in translation
278 for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
279 if (aFeatIt->second == anAngIt->entityA || aFeatIt->second == anAngIt->entityB) {
280 if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
287 // two arcs were found, update their centers
288 Slvs_Entity anArcA = myStorage->getEntity(anAngIt->entityA);
289 Slvs_Entity anArcB = myStorage->getEntity(anAngIt->entityB);
290 if (myStorage->isPointFixed(anArcB.point[0], aFixed))
292 Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
293 Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
294 for (int i = 0; i < 2; i++) {
295 aVec[i] = myStorage->getParameter(aCenterA.param[i]).val - aCenterXY[i];
296 aTarget[i] = myStorage->getParameter(aCenterB.param[i]);
298 aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
299 aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
300 myStorage->updateParameter(aTarget[0]);
301 myStorage->updateParameter(aTarget[1]);