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_AttributeRefAttr.h>
10 #include <ModelAPI_AttributeRefList.h>
11 #include <ModelAPI_ResultConstruction.h>
13 #include <GeomAPI_Dir2d.h>
14 #include <GeomAPI_XY.h>
18 #define PI 3.1415926535897932
20 void SketchSolver_ConstraintMultiRotation::getAttributes(
21 Slvs_hEntity& theCenter, double& theAngle,
22 std::vector<std::vector<Slvs_hEntity> >& thePoints,
23 std::vector<std::vector<Slvs_hEntity> >& theCircular)
25 DataPtr aData = myBaseConstraint->data();
26 theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
27 aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
29 AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
30 if (!aCenterAttr || !aCenterAttr->isInitialized()) {
31 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
34 int aType = SLVS_E_UNKNOWN; // type of created entity
35 Slvs_hEntity anEntityID = myGroup->getAttributeId(aCenterAttr);
36 if (anEntityID == SLVS_E_UNKNOWN)
37 anEntityID = changeEntity(aCenterAttr, aType);
38 theCenter = anEntityID;
40 // Lists of objects and number of copies
41 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
42 aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
43 myNumberOfObjects = anInitialRefList->size();
44 myNumberOfCopies = (size_t)std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
45 aData->attribute(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID()))->value();
46 AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
47 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
49 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
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.
57 ResultConstructionPtr aRC;
58 std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
59 std::vector<Slvs_hEntity> aCircs; // list of circular objects
60 std::list<ObjectPtr> anObjectList = aRefList->list();
61 std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
62 while (anObjectIter != anObjectList.end()) {
67 for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
68 aFeature = ModelAPI_Feature::feature(*anObjectIter);
71 anEntityID = changeEntity(aFeature, aType);
72 Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
74 case SLVS_E_POINT_IN_2D:
75 case SLVS_E_POINT_IN_3D:
76 aPoints[0].push_back(anEntityID);
78 case SLVS_E_LINE_SEGMENT:
79 aPoints[0].push_back(anEntity.point[0]); // start point of line
80 aPoints[1].push_back(anEntity.point[1]); // end point of line
83 aPoints[0].push_back(anEntity.point[0]); // center of circle
84 aCircs.push_back(anEntityID);
86 case SLVS_E_ARC_OF_CIRCLE:
87 aPoints[0].push_back(anEntity.point[1]); // start point of arc
88 aPoints[1].push_back(anEntity.point[2]); // end point of arc
89 aCircs.push_back(anEntityID);
92 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
97 if (!aPoints[0].empty())
98 thePoints.push_back(aPoints[0]);
99 if (!aPoints[1].empty())
100 thePoints.push_back(aPoints[1]);
102 theCircular.push_back(aCircs);
106 void SketchSolver_ConstraintMultiRotation::process()
109 if (!myBaseConstraint || !myStorage || myGroup == 0) {
110 /// TODO: Put error message here
113 if (!mySlvsConstraints.empty()) // some data is changed, update constraint
114 update(myBaseConstraint);
116 Slvs_hEntity aCenter;
117 std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
118 std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
119 getAttributes(aCenter, myAngle, aPointsAndCopies, aCircsAndCopies);
120 if (!myErrorMsg.empty())
123 // Create lines between neighbor rotated points and make angle between them equal to anAngle.
124 // Also these lines should have equal lengths.
125 Slvs_Constraint aConstraint;
126 myRotationCenter = aCenter;
127 Slvs_Entity aPrevLine;
128 std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
129 for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
130 size_t aSize = aCopyIter->size();
131 if (aSize <= 1) continue;
133 aPrevLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
134 myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[0]);
135 aPrevLine.h = myStorage->addEntity(aPrevLine);
136 for (size_t i = 1; i < aSize; i++) {
137 Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
138 myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[i]);
139 aLine.h = myStorage->addEntity(aLine);
140 // Equal length constraint
141 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
142 SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
143 SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aPrevLine.h, aLine.h);
144 aConstraint.h = myStorage->addConstraint(aConstraint);
145 mySlvsConstraints.push_back(aConstraint.h);
147 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
148 SLVS_C_ANGLE, myGroup->getWorkplaneId(), fabs(myAngle), SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
149 aPrevLine.h, aLine.h);
150 if (myAngle < 0.0) // clockwise rotation
151 aConstraint.other = true;
152 aConstraint.h = myStorage->addConstraint(aConstraint);
153 mySlvsConstraints.push_back(aConstraint.h);
158 // Equal radii constraints
159 for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
160 size_t aSize = aCopyIter->size();
161 for (size_t i = 0; i < aSize - 1; i++) {
162 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
163 SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
164 (*aCopyIter)[i], (*aCopyIter)[i+1]);
165 aConstraint.h = myStorage->addConstraint(aConstraint);
166 mySlvsConstraints.push_back(aConstraint.h);
170 // Set the rotation center unchanged during constraint recalculation
171 if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
172 aConstraint = Slvs_MakeConstraint(
173 SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
174 myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
175 aConstraint.h = myStorage->addConstraint(aConstraint);
176 mySlvsConstraints.push_back(aConstraint.h);
182 void SketchSolver_ConstraintMultiRotation::update(ConstraintPtr theConstraint)
185 if (!theConstraint || theConstraint == myBaseConstraint) {
186 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
187 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
188 if (anInitialRefList->size() != myNumberOfObjects) {
189 remove(myBaseConstraint);
195 // update angle value
196 myAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
197 myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
199 SketchSolver_Constraint::update();
202 bool SketchSolver_ConstraintMultiRotation::remove(ConstraintPtr theConstraint)
205 if (theConstraint && theConstraint != myBaseConstraint)
207 bool isFullyRemoved = true;
208 std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
209 for (; aCIter != mySlvsConstraints.end(); aCIter++)
210 isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
211 mySlvsConstraints.clear();
213 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
214 for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
215 myStorage->removeEntity(aFeatIt->second);
217 if (isFullyRemoved) {
218 myFeatureMap.clear();
219 myAttributeMap.clear();
222 cleanRemovedEntities();
226 void SketchSolver_ConstraintMultiRotation::adjustConstraint()
228 if (abs(myAngle) < tolerance) {
229 myStorage->setNeedToResolve(false);
233 // Obtain coordinates of rotation center
234 Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
236 for (int i = 0; i < 2; i++)
237 aCenterXY[i] = myStorage->getParameter(aRotCenter.param[i]).val;
239 double cosA = cos(myAngle * PI / 180.0);
240 double sinA = sin(myAngle * PI / 180.0);
242 // Update positions of all points to satisfy angles
243 std::list<Slvs_Constraint> aConstrAngle = myStorage->getConstraintsByType(SLVS_C_ANGLE);
244 std::list<Slvs_Constraint>::iterator anAngIt = aConstrAngle.begin();
245 std::vector<Slvs_hConstraint>::iterator aCIt;
246 Slvs_hConstraint aFixed; // temporary variable
247 double aVec[2]; // coordinates of vector defining a line
248 Slvs_Param aTarget[2]; // parameter to be changed
249 for (; anAngIt != aConstrAngle.end(); anAngIt++) {
250 for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
251 if (anAngIt->h == *aCIt)
253 if (aCIt == mySlvsConstraints.end())
255 Slvs_Entity aLineA = myStorage->getEntity(anAngIt->entityA);
256 Slvs_Entity aLineB = myStorage->getEntity(anAngIt->entityB);
257 if (myStorage->isPointFixed(aLineB.point[1], aFixed))
259 Slvs_Entity aPointA = myStorage->getEntity(aLineA.point[1]);
260 Slvs_Entity aPointB = myStorage->getEntity(aLineB.point[1]);
261 for (int i = 0; i < 2; i++) {
262 aVec[i] = myStorage->getParameter(aPointA.param[i]).val - aCenterXY[i];
263 aTarget[i] = myStorage->getParameter(aPointB.param[i]);
265 aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
266 aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
267 myStorage->updateParameter(aTarget[0]);
268 myStorage->updateParameter(aTarget[1]);
270 anAngIt->valA = myAngle;
271 myStorage->updateConstraint(*anAngIt);
274 // update positions of centers of arcs for correct radius calculation
275 std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
276 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
277 for (anAngIt = aRadii.begin(); anAngIt != aRadii.end(); anAngIt++) {
278 int aNbFound = 0; // number of arcs used in translation
279 for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
280 if (aFeatIt->second == anAngIt->entityA || aFeatIt->second == anAngIt->entityB) {
281 if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
288 // two arcs were found, update their centers
289 Slvs_Entity anArcA = myStorage->getEntity(anAngIt->entityA);
290 Slvs_Entity anArcB = myStorage->getEntity(anAngIt->entityB);
291 if (myStorage->isPointFixed(anArcB.point[0], aFixed))
293 Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
294 Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
295 for (int i = 0; i < 2; i++) {
296 aVec[i] = myStorage->getParameter(aCenterA.param[i]).val - aCenterXY[i];
297 aTarget[i] = myStorage->getParameter(aCenterB.param[i]);
299 aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
300 aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
301 myStorage->updateParameter(aTarget[0]);
302 myStorage->updateParameter(aTarget[1]);