Salome HOME
SketchSolver Refactoring: Eliminate SolveSpace as a sketch solver.
[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
104 void SketchSolver_ConstraintMulti::adjustConstraint()
105 {
106   AttributeRefListPtr aRefList =
107       myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
108   if (!aRefList || aRefList->size() == 0) {
109     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
110     return;
111   }
112
113   FeaturePtr anOriginal, aFeature;
114   std::list<double>::iterator aXIt, aYIt;
115
116   std::list<ObjectPtr> anObjectList = aRefList->list();
117   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
118   while (anObjIt != anObjectList.end()) {
119     anOriginal = ModelAPI_Feature::feature(*anObjIt++);
120     if (!anOriginal)
121       continue;
122
123     // Fill lists of coordinates of points composing a feature
124     std::list<double> aX, aY;
125     double aXCoord, aYCoord;
126     std::list<AttributePtr> aPoints =
127         anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
128     std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
129     for (; aPtIt != aPoints.end(); ++aPtIt) {
130       AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
131       if (aPoint2D->isInitialized()) {
132         aXCoord = aPoint2D->x();
133         aYCoord = aPoint2D->y();
134         getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
135       } else
136         aXCoord = aYCoord = 0;
137
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
148       if (myIsEventsBlocked)
149         aFeature->data()->blockSendAttributeUpdated(true);
150
151       if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
152         aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
153             anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
154
155       aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
156       for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
157            aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
158         if (!(*aPtIt)->isInitialized())
159           continue;
160         transformRelative(*aXIt, *aYIt);
161         getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
162
163         AttributePoint2DPtr aPoint2D =
164             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
165         aPoint2D->setValue(aXCoord, aYCoord);
166       }
167     }
168   }
169
170   myAdjusted = true;
171 }
172
173 void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
174                                           PlaneGCSSolver_Update*)
175 {
176   if (myFeatures.find(theFeature) == myFeatures.end())
177     return; // the feature is not used by constraint => nothing to update
178
179   // update derivative object
180   updateLocal();
181   myAdjusted = false;
182   adjustConstraint();
183 }
184
185 void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
186 {
187   myIsEventsBlocked = isBlocked;
188
189   std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
190   for (; anIt != myFeatures.end(); ++anIt)
191     (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
192
193   SketchSolver_Constraint::blockEvents(isBlocked);
194 }