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_AttributeInteger.h>
10 #include <ModelAPI_AttributeRefAttr.h>
11 #include <ModelAPI_AttributeRefList.h>
12 #include <ModelAPI_ResultConstruction.h>
13 #include <ModelAPI_Data.h>
15 #include <GeomAPI_Dir2d.h>
16 #include <GeomAPI_XY.h>
21 void SketchSolver_ConstraintMultiTranslation::getAttributes(
22 Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
23 std::vector<std::vector<Slvs_hEntity> >& thePoints,
24 std::vector<std::vector<Slvs_hEntity> >& theCircular)
26 DataPtr aData = myBaseConstraint->data();
27 AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
28 AttributePtr aEndPointAttr = aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID());
29 if (!aStartPointAttr || !aStartPointAttr->isInitialized() ||
30 !aEndPointAttr || !aEndPointAttr->isInitialized()) {
31 myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
35 int aType = SLVS_E_UNKNOWN; // type of created entity
36 Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
37 if (anEntityID == SLVS_E_UNKNOWN)
38 anEntityID = changeEntity(aStartPointAttr, aType);
39 theStartPoint = anEntityID;
40 anEntityID = myGroup->getAttributeId(aEndPointAttr);
41 if (anEntityID == SLVS_E_UNKNOWN)
42 anEntityID = changeEntity(aEndPointAttr, aType);
43 theEndPoint = anEntityID;
45 // Lists of objects and number of copies
46 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
47 aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
48 myNumberOfObjects = anInitialRefList->size();
49 myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID())->value();
50 AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
51 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
53 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
57 // Obtain all points of initial features and store them into separate lists
58 // containing their translated copies.
59 // Also all circles and arc collected too, because they will be constrained by equal radii.
61 ResultConstructionPtr aRC;
62 std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
63 std::vector<Slvs_hEntity> aCircs; // list of circular objects
64 std::list<ObjectPtr> anObjectList = aRefList->list();
65 std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
66 while (anObjectIter != anObjectList.end()) {
71 for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
72 aFeature = ModelAPI_Feature::feature(*anObjectIter);
75 anEntityID = changeEntity(aFeature, aType);
76 Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
78 case SLVS_E_POINT_IN_2D:
79 case SLVS_E_POINT_IN_3D:
80 aPoints[0].push_back(anEntityID);
82 case SLVS_E_LINE_SEGMENT:
83 aPoints[0].push_back(anEntity.point[0]); // start point of line
84 aPoints[1].push_back(anEntity.point[1]); // end point of line
87 aPoints[0].push_back(anEntity.point[0]); // center of circle
88 aCircs.push_back(anEntityID);
90 case SLVS_E_ARC_OF_CIRCLE:
91 aPoints[0].push_back(anEntity.point[1]); // start point of arc
92 aPoints[1].push_back(anEntity.point[2]); // end point of arc
93 aCircs.push_back(anEntityID);
96 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
101 if (!aPoints[0].empty())
102 thePoints.push_back(aPoints[0]);
103 if (!aPoints[1].empty())
104 thePoints.push_back(aPoints[1]);
106 theCircular.push_back(aCircs);
110 void SketchSolver_ConstraintMultiTranslation::process()
113 if (!myBaseConstraint || !myStorage || myGroup == 0) {
114 /// TODO: Put error message here
117 if (!mySlvsConstraints.empty()) // some data is changed, update constraint
118 update(myBaseConstraint);
120 Slvs_hEntity aStartPoint, aEndPoint;
121 std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
122 std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
123 getAttributes(aStartPoint, aEndPoint, aPointsAndCopies, aCircsAndCopies);
124 if (!myErrorMsg.empty())
127 // Create lines between neighbor translated points and make them parallel to the translation line.
128 // Also these lines should have equal lengths.
129 Slvs_Constraint aConstraint;
130 Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
131 myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
132 aTranslationLine.h = myStorage->addEntity(aTranslationLine);
133 myTranslationLine = aTranslationLine.h;
134 std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
135 for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
136 size_t aSize = aCopyIter->size();
137 for (size_t i = 0; i < aSize - 1; i++) {
138 Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
139 myGroup->getWorkplaneId(), (*aCopyIter)[i], (*aCopyIter)[i+1]);
140 aLine.h = myStorage->addEntity(aLine);
141 // Equal length constraint
142 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
143 SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
144 SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aTranslationLine.h, aLine.h);
145 aConstraint.h = myStorage->addConstraint(aConstraint);
146 mySlvsConstraints.push_back(aConstraint.h);
147 // Parallel constraint
148 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
149 SLVS_C_PARALLEL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
150 aTranslationLine.h, aLine.h);
151 aConstraint.h = myStorage->addConstraint(aConstraint);
152 mySlvsConstraints.push_back(aConstraint.h);
155 // Equal radii constraints
156 for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
157 size_t aSize = aCopyIter->size();
158 for (size_t i = 0; i < aSize - 1; i++) {
159 aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
160 SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
161 (*aCopyIter)[i], (*aCopyIter)[i+1]);
162 aConstraint.h = myStorage->addConstraint(aConstraint);
163 mySlvsConstraints.push_back(aConstraint.h);
167 // Set the translation line unchanged during constraint recalculation
168 for (int i = 0; i < 2; i++) {
169 if (myStorage->isPointFixed(aTranslationLine.point[i], aConstraint.h, true))
171 aConstraint = Slvs_MakeConstraint(
172 SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
173 aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
174 aConstraint.h = myStorage->addConstraint(aConstraint);
175 mySlvsConstraints.push_back(aConstraint.h);
181 void SketchSolver_ConstraintMultiTranslation::update(ConstraintPtr theConstraint)
184 if (!theConstraint || theConstraint == myBaseConstraint) {
185 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
186 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
187 AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID());
188 if (anInitialRefList->size() != myNumberOfObjects ||
189 (size_t)aNbCopies->value() != myNumberOfCopies) {
190 remove(myBaseConstraint);
195 SketchSolver_Constraint::update();
198 bool SketchSolver_ConstraintMultiTranslation::remove(ConstraintPtr theConstraint)
201 if (theConstraint && theConstraint != myBaseConstraint)
203 bool isFullyRemoved = true;
204 std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
205 for (; aCIter != mySlvsConstraints.end(); aCIter++)
206 isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
207 mySlvsConstraints.clear();
209 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
210 for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
211 myStorage->removeEntity(aFeatIt->second);
213 if (isFullyRemoved) {
214 myFeatureMap.clear();
215 myAttributeMap.clear();
218 cleanRemovedEntities();
222 void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
224 Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
225 // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
227 for (int i = 0; i < 2; i++) {
228 Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
229 aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
230 aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
232 double aDelta[2] = {aXY[2] - aXY[0], aXY[3] - aXY[1]};
233 if (fabs(aDelta[0]) + fabs(aDelta[1]) < tolerance) {
234 myStorage->setNeedToResolve(false);
238 // Update positions of all points to satisfy distances
239 std::list<Slvs_Constraint> aParallel = myStorage->getConstraintsByType(SLVS_C_PARALLEL);
240 std::list<Slvs_Constraint>::iterator aParIt = aParallel.begin();
241 std::vector<Slvs_hConstraint>::iterator aCIt;
242 Slvs_hConstraint aFixed; // temporary variable
243 for (; aParIt != aParallel.end(); aParIt++) {
244 for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
245 if (aParIt->h == *aCIt)
247 if (aCIt == mySlvsConstraints.end())
249 Slvs_Entity aLine = myStorage->getEntity(aParIt->entityB);
250 if (myStorage->isPointFixed(aLine.point[1], aFixed))
252 Slvs_Entity aStart = myStorage->getEntity(aLine.point[0]);
253 Slvs_Entity aEnd = myStorage->getEntity(aLine.point[1]);
254 for (int i = 0; i < 2; i++) {
255 Slvs_Param aFrom = myStorage->getParameter(aStart.param[i]);
256 Slvs_Param aTo = myStorage->getParameter(aEnd.param[i]);
257 aTo.val = aFrom.val + aDelta[i];
258 myStorage->updateParameter(aTo);
262 // update positions of centers of arcs for correct radius calculation
263 std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
264 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
265 for (aParIt = aRadii.begin(); aParIt != aRadii.end(); aParIt++) {
266 int aNbFound = 0; // number of arcs used in translation
267 for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
268 if (aFeatIt->second == aParIt->entityA || aFeatIt->second == aParIt->entityB) {
269 if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
276 // two arcs were found, update their centers
277 Slvs_Entity anArcA = myStorage->getEntity(aParIt->entityA);
278 Slvs_Entity anArcB = myStorage->getEntity(aParIt->entityB);
279 if (myStorage->isPointFixed(anArcB.point[0], aFixed))
281 Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
282 Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
283 for (int i = 0; i < 2; i++) {
284 Slvs_Param aFrom = myStorage->getParameter(aCenterA.param[i]);
285 Slvs_Param aTo = myStorage->getParameter(aCenterB.param[i]);
286 aTo.val = aFrom.val + aDelta[i];
287 myStorage->updateParameter(aTo);