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