Salome HOME
bd0a82ad3206962483ae6a6bffa4b5d5fe5b5fa8
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMulti.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 #include <SketchSolver_ConstraintMulti.h>
4 #include <SketchSolver_Error.h>
5 #include <SketchSolver_Manager.h>
6
7 #include <GeomDataAPI_Point2D.h>
8 #include <ModelAPI_AttributeInteger.h>
9 #include <ModelAPI_AttributeRefAttr.h>
10 #include <ModelAPI_AttributeRefList.h>
11 #include <SketchPlugin_Arc.h>
12 #include <SketchPlugin_Circle.h>
13 #include <SketchPlugin_Line.h>
14 #include <SketchPlugin_Point.h>
15 #include <SketchPlugin_IntersectionPoint.h>
16
17 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
18 {
19   myAdjusted = false;
20   DataPtr aData = myBaseConstraint->data();
21
22   // Lists of objects and number of copies
23   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
24       aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
25   myNumberOfObjects = anInitialRefList->size();
26   myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
27   if (myNumberOfCopies <= 0)
28     return;
29
30   AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
31       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
32   if (!aRefList || aRefList->size() == 0) {
33     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
34     return;
35   }
36
37   FeaturePtr aFeature;
38   std::list<ObjectPtr> anObjectList = aRefList->list();
39   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
40   // execute for the feature is not called yet
41   if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size()) 
42     myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
43
44   while (anObjIt != anObjectList.end()) {
45     aFeature = ModelAPI_Feature::feature(*anObjIt++);
46     if (!aFeature)
47       continue;
48
49     // the entity is not created, so it is a copy in "multi" constraint, force its creation
50     if (!myStorage->update(aFeature)) 
51       myStorage->update(aFeature, myGroupID, true);
52     theEntities.push_back(myStorage->entity(aFeature));
53     myFeatures.insert(aFeature);
54     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
55       // just add copied features into the list of objects
56       aFeature = ModelAPI_Feature::feature(*anObjIt);
57       if (aFeature)
58         myFeatures.insert(aFeature);
59     }
60   }
61 }
62
63 bool SketchSolver_ConstraintMulti::remove()
64 {
65   myFeatures.clear();
66   return SketchSolver_Constraint::remove();
67 }
68
69 void SketchSolver_ConstraintMulti::update()
70 {
71   update(false);
72 }
73
74 void SketchSolver_ConstraintMulti::update(bool isForce)
75 {
76   cleanErrorMsg();
77   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
78       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
79   AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
80   if (!anInitialRefList || !aNbObjects)
81     return; // the "Multi" constraint is in queue to remove
82   bool isUpdated = 
83     anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
84   if (!isUpdated) {
85     // additional check that the features and their copies are changed
86     AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
87         myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
88     if (aRefList && aRefList->size() != 0) {
89       FeaturePtr aFeature;
90       std::list<ObjectPtr> anObjectList = aRefList->list();
91       std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
92       for (; anObjIt != anObjectList.end(); ++anObjIt) {
93         aFeature = ModelAPI_Feature::feature(*anObjIt);
94         if (aFeature && myFeatures.find(aFeature) == myFeatures.end()) {
95           isUpdated = true;
96           break;
97         }
98       }
99     } else
100       isUpdated = true;
101   }
102   if (isUpdated) {
103     remove();
104     process();
105     return;
106   }
107
108   // update derivative object
109   updateLocal();
110   if (isForce)
111     myAdjusted = false;
112   adjustConstraint();
113 }
114
115 void SketchSolver_ConstraintMulti::adjustConstraint()
116 {
117   AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
118       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
119   if (!aRefList || aRefList->size() == 0) {
120     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
121     return;
122   }
123
124   FeaturePtr anOriginal, aFeature;
125   std::list<ObjectPtr> anObjectList = aRefList->list();
126   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
127   while (anObjIt != anObjectList.end()) {
128     anOriginal = ModelAPI_Feature::feature(*anObjIt++);
129     if (!anOriginal)
130       continue;
131
132     // Fill lists of coordinates of points composing a feature
133     std::list<double> aX, aY;
134     std::list<double>::iterator aXIt, aYIt;
135     double aXCoord, aYCoord;
136     EntityWrapperPtr anEntity = myStorage->entity(anOriginal);
137     std::list<EntityWrapperPtr> aSubs = anEntity->subEntities();
138     std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
139     for (; aSIt != aSubs.end(); ++aSIt) {
140       if ((*aSIt)->type() != ENTITY_POINT)
141         continue;
142       AttributePoint2DPtr aPoint =
143           std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSIt)->baseAttribute());
144       if (aPoint) {
145         aXCoord = aPoint->x();
146         aYCoord = aPoint->y();
147       } else {
148         std::list<ParameterWrapperPtr> aParameters = (*aSIt)->parameters();
149         aXCoord = aParameters.front()->value();
150         aYCoord = aParameters.back()->value();
151       }
152       getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
153       aX.push_back(aXCoord);
154       aY.push_back(aYCoord);
155     }
156
157     // Calculate positions of copied features
158     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
159       aFeature = ModelAPI_Feature::feature(*anObjIt);
160       if (!aFeature)
161         continue;
162       anEntity = myStorage->entity(aFeature);
163
164       if (!anEntity || !myStorage->isEventsBlocked())
165         aFeature->data()->blockSendAttributeUpdated(true);
166
167       std::list<AttributePtr> aPoints;
168       if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
169         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
170         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::START_ID()));
171         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::END_ID()));
172       } else if (aFeature->getKind() == SketchPlugin_Line::ID()) {
173         aPoints.push_back(aFeature->attribute(SketchPlugin_Line::START_ID()));
174         aPoints.push_back(aFeature->attribute(SketchPlugin_Line::END_ID()));
175       } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
176         aPoints.push_back(aFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
177         // update circle's radius
178         aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
179             anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
180       } else if (aFeature->getKind() == SketchPlugin_Point::ID() ||
181                aFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
182         aPoints.push_back(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
183
184       std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
185       for (aXIt = aX.begin(), aYIt = aY.begin(); aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
186         transformRelative(*aXIt, *aYIt);
187         getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
188
189         std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
190             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
191         aPoint2D->setValue(aXCoord, aYCoord);
192       }
193
194       // update feature in the storage if it is used by another constraints
195       if (anEntity)
196         myStorage->update(aFeature);
197       else { // update attributes, if they exist in the storage
198         for (aPtIt = aPoints.begin(); aPtIt != aPoints.end(); ++aPtIt) {
199           EntityWrapperPtr aPntEnt = myStorage->entity(*aPtIt);
200           if (aPntEnt)
201             myStorage->update(*aPtIt);
202         }
203       }
204
205       if (!anEntity || !myStorage->isEventsBlocked())
206         aFeature->data()->blockSendAttributeUpdated(false);
207     }
208   }
209
210   myAdjusted = true;
211 }
212
213 bool SketchSolver_ConstraintMulti::isUsed(FeaturePtr theFeature) const
214 {
215   return theFeature && (myFeatures.find(theFeature) != myFeatures.end() ||
216          SketchSolver_Constraint::isUsed(theFeature));
217 }
218
219 bool SketchSolver_ConstraintMulti::isUsed(AttributePtr theAttribute) const
220 {
221   AttributePtr anAttribute = theAttribute;
222   AttributeRefAttrPtr aRefAttr =
223       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
224   if (aRefAttr) {
225     if (aRefAttr->isObject())
226       return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
227     else
228       anAttribute = aRefAttr->attr();
229   }
230   if (!anAttribute)
231     return false;
232
233   FeaturePtr anOwner = ModelAPI_Feature::feature(anAttribute->owner());
234   return myFeatures.find(anOwner) != myFeatures.end();
235 }