Salome HOME
Creating an arc by 3 points and a tangent arc
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMulti.cpp
1 #include <SketchSolver_ConstraintMulti.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Manager.h>
4
5 #include <GeomDataAPI_Point2D.h>
6 #include <ModelAPI_AttributeInteger.h>
7 #include <ModelAPI_AttributeRefAttr.h>
8 #include <ModelAPI_AttributeRefList.h>
9 #include <SketchPlugin_Arc.h>
10 #include <SketchPlugin_Circle.h>
11 #include <SketchPlugin_Line.h>
12 #include <SketchPlugin_Point.h>
13
14 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
15 {
16   myAdjusted = false;
17   DataPtr aData = myBaseConstraint->data();
18
19   // Lists of objects and number of copies
20   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
21       aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
22   myNumberOfObjects = anInitialRefList->size();
23   myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
24   if (myNumberOfCopies <= 0)
25     return;
26
27   AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
28       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
29   if (!aRefList || aRefList->size() == 0) {
30     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
31     return;
32   }
33
34   FeaturePtr aFeature;
35   std::list<ObjectPtr> anObjectList = aRefList->list();
36   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
37   if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size()) // execute for the feature is not called yet
38     myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
39
40   while (anObjIt != anObjectList.end()) {
41     aFeature = ModelAPI_Feature::feature(*anObjIt++);
42     if (!aFeature)
43       continue;
44
45     myStorage->update(aFeature);
46     theEntities.push_back(myStorage->entity(aFeature));
47     myFeatures.insert(aFeature);
48     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
49       // just add copied features into the list of objects
50       aFeature = ModelAPI_Feature::feature(*anObjIt);
51       if (aFeature)
52         myFeatures.insert(aFeature);
53     }
54   }
55 }
56
57 bool SketchSolver_ConstraintMulti::remove()
58 {
59   myFeatures.clear();
60   return SketchSolver_Constraint::remove();
61 }
62
63 void SketchSolver_ConstraintMulti::update()
64 {
65   update(false);
66 }
67
68 void SketchSolver_ConstraintMulti::update(bool isForce)
69 {
70   cleanErrorMsg();
71   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
72       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
73   AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
74   bool isUpdated= anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
75   if (!isUpdated) {
76     // additional check that the features and their copies are changed
77     AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
78         myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
79     if (aRefList && aRefList->size() != 0) {
80       FeaturePtr aFeature;
81       std::list<ObjectPtr> anObjectList = aRefList->list();
82       std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
83       for (; anObjIt != anObjectList.end(); ++anObjIt) {
84         aFeature = ModelAPI_Feature::feature(*anObjIt);
85         if (aFeature && myFeatures.find(aFeature) == myFeatures.end()) {
86           isUpdated = true;
87           break;
88         }
89       }
90     } else
91       isUpdated = true;
92   }
93   if (isUpdated) {
94     remove();
95     process();
96     return;
97   }
98
99   // update derivative object
100   updateLocal();
101   if (isForce)
102     myAdjusted = false;
103   // update parent object
104   SketchSolver_Constraint::update();
105 }
106
107 void SketchSolver_ConstraintMulti::adjustConstraint()
108 {
109   AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
110       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
111   if (!aRefList || aRefList->size() == 0) {
112     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
113     return;
114   }
115
116   FeaturePtr aFeature;
117   std::list<ObjectPtr> anObjectList = aRefList->list();
118   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
119   while (anObjIt != anObjectList.end()) {
120     aFeature = ModelAPI_Feature::feature(*anObjIt++);
121     if (!aFeature)
122       continue;
123
124     // Fill lists of coordinates of points composing a feature
125     std::list<double> aX, aY;
126     std::list<double>::iterator aXIt, aYIt;
127     double aXCoord, aYCoord;
128     EntityWrapperPtr anEntity = myStorage->entity(aFeature);
129     std::list<EntityWrapperPtr> aSubs = anEntity->subEntities();
130     std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
131     for (; aSIt != aSubs.end(); ++aSIt) {
132       if ((*aSIt)->type() != ENTITY_POINT)
133         continue;
134       std::list<ParameterWrapperPtr> aParameters = (*aSIt)->parameters();
135       aXCoord = aParameters.front()->value();
136       aYCoord = aParameters.back()->value();
137       getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
138       aX.push_back(aXCoord);
139       aY.push_back(aYCoord);
140     }
141
142     // Calculate positions of copied features
143     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
144       aFeature = ModelAPI_Feature::feature(*anObjIt);
145       if (!aFeature)
146         continue;
147       anEntity = myStorage->entity(aFeature);
148
149       if (!anEntity || !myStorage->isEventsBlocked())
150         aFeature->data()->blockSendAttributeUpdated(true);
151
152       std::list<AttributePtr> aPoints;
153       if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
154         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
155         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::START_ID()));
156         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::END_ID()));
157       } else if (aFeature->getKind() == SketchPlugin_Line::ID()) {
158         aPoints.push_back(aFeature->attribute(SketchPlugin_Line::START_ID()));
159         aPoints.push_back(aFeature->attribute(SketchPlugin_Line::END_ID()));
160       } else if (aFeature->getKind() == SketchPlugin_Circle::ID())
161         aPoints.push_back(aFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
162       else if (aFeature->getKind() == SketchPlugin_Point::ID())
163         aPoints.push_back(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
164
165       std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
166       for (aXIt = aX.begin(), aYIt = aY.begin(); aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
167         transformRelative(*aXIt, *aYIt);
168         getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
169
170         std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
171             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
172         aPoint2D->setValue(aXCoord, aYCoord);
173       }
174
175       // update feature in the storage if it is used by another constraints
176       if (anEntity)
177         myStorage->update(aFeature);
178
179       if (!anEntity || !myStorage->isEventsBlocked())
180         aFeature->data()->blockSendAttributeUpdated(false);
181     }
182   }
183
184   myAdjusted = true;
185 }