1 #include <SketchSolver_ConstraintMultiTranslation.h>
2 #include <SketchSolver_Group.h>
3 #include <SketchSolver_Error.h>
5 #include <SketchPlugin_Arc.h>
6 #include <SketchPlugin_MultiTranslation.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>
19 void SketchSolver_ConstraintMultiTranslation::getAttributes(
20 Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
21 std::vector<std::vector<Slvs_hEntity> >& thePoints,
22 std::vector<std::vector<Slvs_hEntity> >& theCircular)
24 DataPtr aData = myBaseConstraint->data();
25 AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
26 AttributePtr aEndPointAttr = aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID());
27 if (!aStartPointAttr || !aStartPointAttr->isInitialized() ||
28 !aEndPointAttr || !aEndPointAttr->isInitialized()) {
29 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
33 int aType = SLVS_E_UNKNOWN; // type of created entity
34 Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
35 if (anEntityID == SLVS_E_UNKNOWN)
36 anEntityID = changeEntity(aStartPointAttr, aType);
37 theStartPoint = anEntityID;
38 anEntityID = myGroup->getAttributeId(aEndPointAttr);
39 if (anEntityID == SLVS_E_UNKNOWN)
40 anEntityID = changeEntity(aEndPointAttr, aType);
41 theEndPoint = anEntityID;
43 // Lists of objects and number of copies
44 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
45 aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
46 myNumberOfObjects = anInitialRefList->size();
47 myNumberOfCopies = (size_t)std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
48 aData->attribute(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID()))->value();
49 AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
50 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
52 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
56 // Obtain all points of initial features and store them into separate lists
57 // containing their translated copies.
58 // Also all circles and arc collected too, because they will be constrained by equal radii.
60 ResultConstructionPtr aRC;
61 std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
62 std::vector<Slvs_hEntity> aCircs; // list of circular objects
63 std::list<ObjectPtr> anObjectList = aRefList->list();
64 std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
65 while (anObjectIter != anObjectList.end()) {
70 for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
71 aFeature = ModelAPI_Feature::feature(*anObjectIter);
74 anEntityID = changeEntity(aFeature, aType);
75 Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
77 case SLVS_E_POINT_IN_2D:
78 case SLVS_E_POINT_IN_3D:
79 aPoints[0].push_back(anEntityID);
81 case SLVS_E_LINE_SEGMENT:
82 aPoints[0].push_back(anEntity.point[0]); // start point of line
83 aPoints[1].push_back(anEntity.point[1]); // end point of line
86 aPoints[0].push_back(anEntity.point[0]); // center of circle
87 aCircs.push_back(anEntityID);
89 case SLVS_E_ARC_OF_CIRCLE:
90 aPoints[0].push_back(anEntity.point[1]); // start point of arc
91 aPoints[1].push_back(anEntity.point[2]); // end point of arc
92 aCircs.push_back(anEntityID);
95 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
100 if (!aPoints[0].empty())
101 thePoints.push_back(aPoints[0]);
102 if (!aPoints[1].empty())
103 thePoints.push_back(aPoints[1]);
105 theCircular.push_back(aCircs);
109 void SketchSolver_ConstraintMultiTranslation::process()
112 if (!myBaseConstraint || !myStorage || myGroup == 0) {
113 /// TODO: Put error message here
116 if (!mySlvsConstraints.empty()) // some data is changed, update constraint
117 update(myBaseConstraint);
119 Slvs_hEntity aStartPoint, aEndPoint;
120 std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
121 std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
122 getAttributes(aStartPoint, aEndPoint, aPointsAndCopies, aCircsAndCopies);
123 if (!myErrorMsg.empty())
126 // Create lines between neighbor translated points and make them parallel to the translation line.
127 // Also these lines should have equal lengths.
128 Slvs_Constraint aConstraint;
129 Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
130 myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
131 aTranslationLine.h = myStorage->addEntity(aTranslationLine);
132 myTranslationLine = aTranslationLine.h;
133 std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
134 for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
135 size_t aSize = aCopyIter->size();
136 for (size_t i = 0; i < aSize - 1; i++) {
137 Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
138 myGroup->getWorkplaneId(), (*aCopyIter)[i], (*aCopyIter)[i+1]);
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, aTranslationLine.h, aLine.h);
144 aConstraint.h = myStorage->addConstraint(aConstraint);
145 mySlvsConstraints.push_back(aConstraint.h);
146 // Parallel constraint
147 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
148 SLVS_C_PARALLEL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
149 aTranslationLine.h, aLine.h);
150 aConstraint.h = myStorage->addConstraint(aConstraint);
151 mySlvsConstraints.push_back(aConstraint.h);
154 // Equal radii constraints
155 for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
156 size_t aSize = aCopyIter->size();
157 for (size_t i = 0; i < aSize - 1; i++) {
158 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
159 SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
160 (*aCopyIter)[i], (*aCopyIter)[i+1]);
161 aConstraint.h = myStorage->addConstraint(aConstraint);
162 mySlvsConstraints.push_back(aConstraint.h);
166 // Set the translation line unchanged during constraint recalculation
167 for (int i = 0; i < 2; i++) {
168 if (myStorage->isPointFixed(aTranslationLine.point[i], aConstraint.h, true))
170 aConstraint = Slvs_MakeConstraint(
171 SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
172 aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
173 aConstraint.h = myStorage->addConstraint(aConstraint);
174 mySlvsConstraints.push_back(aConstraint.h);
180 void SketchSolver_ConstraintMultiTranslation::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 if (anInitialRefList->size() != myNumberOfObjects) {
187 remove(myBaseConstraint);
192 SketchSolver_Constraint::update();
195 bool SketchSolver_ConstraintMultiTranslation::remove(ConstraintPtr theConstraint)
198 if (theConstraint && theConstraint != myBaseConstraint)
200 bool isFullyRemoved = true;
201 std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
202 for (; aCIter != mySlvsConstraints.end(); aCIter++)
203 isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
204 mySlvsConstraints.clear();
206 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
207 for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
208 myStorage->removeEntity(aFeatIt->second);
210 if (isFullyRemoved) {
211 myFeatureMap.clear();
212 myAttributeMap.clear();
215 cleanRemovedEntities();
219 void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
221 Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
222 // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
224 for (int i = 0; i < 2; i++) {
225 Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
226 aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
227 aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
229 double aDelta[2] = {aXY[2] - aXY[0], aXY[3] - aXY[1]};
230 if (fabs(aDelta[0]) + fabs(aDelta[1]) < tolerance) {
231 myStorage->setNeedToResolve(false);
235 // Update positions of all points to satisfy distances
236 std::list<Slvs_Constraint> aParallel = myStorage->getConstraintsByType(SLVS_C_PARALLEL);
237 std::list<Slvs_Constraint>::iterator aParIt = aParallel.begin();
238 std::vector<Slvs_hConstraint>::iterator aCIt;
239 Slvs_hConstraint aFixed; // temporary variable
240 for (; aParIt != aParallel.end(); aParIt++) {
241 for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
242 if (aParIt->h == *aCIt)
244 if (aCIt == mySlvsConstraints.end())
246 Slvs_Entity aLine = myStorage->getEntity(aParIt->entityB);
247 if (myStorage->isPointFixed(aLine.point[1], aFixed))
249 Slvs_Entity aStart = myStorage->getEntity(aLine.point[0]);
250 Slvs_Entity aEnd = myStorage->getEntity(aLine.point[1]);
251 for (int i = 0; i < 2; i++) {
252 Slvs_Param aFrom = myStorage->getParameter(aStart.param[i]);
253 Slvs_Param aTo = myStorage->getParameter(aEnd.param[i]);
254 aTo.val = aFrom.val + aDelta[i];
255 myStorage->updateParameter(aTo);
259 // update positions of centers of arcs for correct radius calculation
260 std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
261 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
262 for (aParIt = aRadii.begin(); aParIt != aRadii.end(); aParIt++) {
263 int aNbFound = 0; // number of arcs used in translation
264 for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
265 if (aFeatIt->second == aParIt->entityA || aFeatIt->second == aParIt->entityB) {
266 if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
273 // two arcs were found, update their centers
274 Slvs_Entity anArcA = myStorage->getEntity(aParIt->entityA);
275 Slvs_Entity anArcB = myStorage->getEntity(aParIt->entityB);
276 if (myStorage->isPointFixed(anArcB.point[0], aFixed))
278 Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
279 Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
280 for (int i = 0; i < 2; i++) {
281 Slvs_Param aFrom = myStorage->getParameter(aCenterA.param[i]);
282 Slvs_Param aTo = myStorage->getParameter(aCenterB.param[i]);
283 aTo.val = aFrom.val + aDelta[i];
284 myStorage->updateParameter(aTo);