Salome HOME
Merge branch 'master' into cgt/devCEA
[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
21   // Lists of objects and number of copies
22   AttributeRefListPtr anInitialRefList =
23       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
24   myNumberOfObjects = anInitialRefList->size();
25   myNumberOfCopies = myBaseConstraint->integer(nameNbObjects())->value() - 1;
26   if (myNumberOfCopies <= 0)
27     return;
28
29   AttributeRefListPtr aRefList =
30       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
31   if (!aRefList || aRefList->size() == 0) {
32     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
33     return;
34   }
35
36   FeaturePtr aFeature;
37   std::list<ObjectPtr> anObjectList = aRefList->list();
38   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
39   // execute for the feature is not called yet
40   if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size())
41     myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
42
43   while (anObjIt != anObjectList.end()) {
44     aFeature = ModelAPI_Feature::feature(*anObjIt++);
45     if (!aFeature)
46       continue;
47
48     // the entity is not created, so it is a copy in "multi" constraint, force its creation
49     if (!myStorage->update(aFeature))
50       myStorage->update(aFeature, true);
51     theEntities.push_back(myStorage->entity(aFeature));
52     myFeatures.insert(aFeature);
53     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
54       // just add copied features into the list of objects
55       aFeature = ModelAPI_Feature::feature(*anObjIt);
56       if (aFeature)
57         myFeatures.insert(aFeature);
58     }
59   }
60 }
61
62 bool SketchSolver_ConstraintMulti::remove()
63 {
64   myStorage->unsubscribeUpdates(this);
65
66   myFeatures.clear();
67   return SketchSolver_Constraint::remove();
68 }
69
70 void SketchSolver_ConstraintMulti::update()
71 {
72   cleanErrorMsg();
73   AttributeRefListPtr anInitialRefList =
74       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
75   AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
76   if (!anInitialRefList || !aNbObjects)
77     return; // the "Multi" constraint is in queue to remove
78   bool isUpdated =
79     anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
80   if (!isUpdated) {
81     // additional check that the features and their copies are changed
82     AttributeRefListPtr aRefList =
83         myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
84     if (aRefList && aRefList->size() != 0) {
85       FeaturePtr aFeature;
86       std::list<ObjectPtr> anObjectList = aRefList->list();
87       std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
88       for (; anObjIt != anObjectList.end(); ++anObjIt) {
89         aFeature = ModelAPI_Feature::feature(*anObjIt);
90         if (aFeature && myFeatures.find(aFeature) == myFeatures.end()) {
91           isUpdated = true;
92           break;
93         }
94       }
95     } else
96       isUpdated = true;
97   }
98   if (isUpdated) {
99     remove();
100     process();
101   }
102
103   // update derived object
104   updateLocal();
105   adjustConstraint();
106 }
107
108 void SketchSolver_ConstraintMulti::adjustConstraint()
109 {
110   AttributeRefListPtr aRefList =
111       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
112   if (!aRefList || aRefList->size() == 0) {
113     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
114     return;
115   }
116
117   FeaturePtr anOriginal, aFeature;
118   std::list<double>::iterator aXIt, aYIt;
119
120   std::list<ObjectPtr> anObjectList = aRefList->list();
121   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
122   while (anObjIt != anObjectList.end()) {
123     anOriginal = ModelAPI_Feature::feature(*anObjIt++);
124     if (!anOriginal)
125       continue;
126
127     // Fill lists of coordinates of points composing a feature
128     std::list<double> aX, aY;
129     double aXCoord, aYCoord;
130     std::list<AttributePtr> aPoints =
131         anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
132     std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
133     for (; aPtIt != aPoints.end(); ++aPtIt) {
134       AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
135       if (aPoint2D->isInitialized()) {
136         aXCoord = aPoint2D->x();
137         aYCoord = aPoint2D->y();
138         getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
139       } else
140         aXCoord = aYCoord = 0;
141
142       aX.push_back(aXCoord);
143       aY.push_back(aYCoord);
144     }
145
146     // Calculate positions of copied features
147     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
148       aFeature = ModelAPI_Feature::feature(*anObjIt);
149       if (!aFeature)
150         continue;
151
152       if (myIsEventsBlocked)
153         aFeature->data()->blockSendAttributeUpdated(true);
154
155       if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
156         aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
157             anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
158
159       aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
160       for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
161            aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
162         if (!(*aPtIt)->isInitialized())
163           continue;
164         transformRelative(*aXIt, *aYIt);
165         getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
166
167         AttributePoint2DPtr aPoint2D =
168             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
169         aPoint2D->setValue(aXCoord, aYCoord);
170       }
171     }
172   }
173
174   myAdjusted = true;
175 }
176
177 void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
178                                           PlaneGCSSolver_Update*)
179 {
180   if (myFeatures.find(theFeature) == myFeatures.end())
181     return; // the feature is not used by constraint => nothing to update
182
183   // update derivative object
184   updateLocal();
185   myAdjusted = false;
186   adjustConstraint();
187 }
188
189 void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
190 {
191   myIsEventsBlocked = isBlocked;
192
193   std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
194   for (; anIt != myFeatures.end(); ++anIt)
195     (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
196
197   SketchSolver_Constraint::blockEvents(isBlocked);
198 }