]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp
Salome HOME
4b3bbb997422f734031314f85a4ac833366c00c8
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintMirror.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:    SketchPlugin_ConstraintMirror.cpp
4 // Created: 17 Mar 2015
5 // Author:  Artem ZHIDKOV
6
7 #include "SketchPlugin_ConstraintMirror.h"
8
9 #include <ModelAPI_AttributeDouble.h>
10 #include <ModelAPI_Data.h>
11 #include <ModelAPI_ResultConstruction.h>
12 #include <ModelAPI_AttributeRefList.h>
13 #include <ModelAPI_Events.h>
14 #include <ModelAPI_Session.h>
15 #include <ModelAPI_Validator.h>
16
17 #include <SketchPlugin_Line.h>
18 #include <SketchPlugin_Sketch.h>
19
20 #include <SketcherPrs_Factory.h>
21
22 #include <Config_PropManager.h>
23
24 SketchPlugin_ConstraintMirror::SketchPlugin_ConstraintMirror()
25 {
26 }
27
28 void SketchPlugin_ConstraintMirror::initAttributes()
29 {
30   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
31   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
32   data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::typeId());
33   data()->addAttribute(SketchPlugin_ConstraintMirror::MIRROR_LIST_ID(), ModelAPI_AttributeRefList::typeId());
34   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
35   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_C());
36 }
37
38 void SketchPlugin_ConstraintMirror::execute()
39 {
40   AttributeRefListPtr aMirrorObjectRefs = reflist(SketchPlugin_ConstraintMirror::MIRROR_LIST_ID());
41
42   // Wait all objects being created, then send update events
43   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
44   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
45   if (isUpdateFlushed)
46     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
47
48   std::shared_ptr<ModelAPI_Data> aData = data();
49   AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
50       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
51   AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
52       aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
53   std::list<ObjectPtr> anInitialList =  aRefListOfShapes->list();
54   std::list<ObjectPtr> aMirroredList =  aRefListOfMirrored->list();
55   std::vector<bool> isUsed(anInitialList.size(), false);
56   // add new items to the list
57   for(int anInd = 0; anInd < aMirrorObjectRefs->size(); anInd++) {
58     ObjectPtr anObject = aMirrorObjectRefs->object(anInd);
59     std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
60     std::vector<bool>::iterator aUsedIt = isUsed.begin();
61     for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
62       if (*anIt == anObject) {
63         *aUsedIt = true;
64         break;
65       }
66     if (anIt == anInitialList.end())
67       aRefListOfShapes->append(anObject);
68   }
69   // remove unused items
70   std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
71   std::list<ObjectPtr>::iterator aMirrorIter = aMirroredList.begin();
72   std::vector<bool>::iterator aUsedIter = isUsed.begin();
73   for (; aUsedIter != isUsed.end(); aUsedIter++) {
74     if (!(*aUsedIter)) {
75       aRefListOfShapes->remove(*anInitIter);
76       if (aMirrorIter != aMirroredList.end()) {
77         aRefListOfMirrored->remove(*aMirrorIter);
78         // remove the corresponding feature from the sketch
79         ResultConstructionPtr aRC =
80             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirrorIter);
81         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
82         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
83         if (aFeature)
84           aDoc->removeFeature(aFeature);
85       }
86     }
87     if (anInitIter != anInitialList.end())
88       anInitIter++;
89     if (aMirrorIter != aMirroredList.end())
90       aMirrorIter++;
91   }
92
93   static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
94
95   // Check consistency of initial list and mirrored list
96   anInitialList =  aRefListOfShapes->list();
97   anInitIter = anInitialList.begin();
98   aMirrorIter = aMirroredList.begin();
99   int indFirstWrong = 0; // index of element starts difference in the lists
100   std::set<int> anInvalidInd; // list of indices of removed features
101   std::shared_ptr<SketchPlugin_Feature> aFeatureIn, aFeatureOut;
102   for ( ; anInitIter != anInitialList.end(); anInitIter++, indFirstWrong++) {
103     // Add features and store indices of objects to remove
104     aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
105     ResultConstructionPtr aRCIn;
106     if (!aFeatureIn) {
107       aRCIn = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
108       if (aRCIn)
109         aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(
110             aRCIn->document()->feature(aRCIn));
111     }
112     if (aMirrorIter == aMirroredList.end())
113       aFeatureOut = std::shared_ptr<SketchPlugin_Feature>();
114     else {
115       aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirrorIter);
116       if (!aFeatureOut) {
117         ResultConstructionPtr aRC =
118             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
119         if (aRC)
120           aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(
121               aRC->document()->feature(aRC));
122       }
123     }
124     if (!aFeatureIn) {
125       if (aFeatureOut)
126         break; // the lists are inconsistent
127       continue;
128     }
129     if (!aFeatureOut) {
130       if (aMirrorIter != aMirroredList.end())
131         break; // the lists are inconsistent
132       // There is no mirrored object yet, create it
133       FeaturePtr aNewFeature = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aFeatureIn, sketch(), true);
134       aNewFeature->execute();
135       ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
136
137       std::shared_ptr<GeomAPI_Shape> aShapeIn = aRCIn->shape();
138       const std::list<ResultPtr>& aResults = aNewFeature->results();
139       std::list<ResultPtr>::const_iterator anIt = aResults.begin();
140       for (; anIt != aResults.end(); anIt++) {
141         ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
142         if (!aRC) continue;
143         std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
144         if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
145             (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
146             (aShapeIn->isFace() && aShapeOut->isFace()))
147           aRefListOfMirrored->append(aRC);
148       }
149       continue;
150     }
151     if (aFeatureIn->getKind() != aFeatureOut->getKind())
152       break; // the lists are inconsistent
153     if (!aFeatureIn->data()->isValid()) {
154       // initial feature was removed, delete it from lists
155       anInvalidInd.insert(indFirstWrong);
156     }
157     aMirrorIter++;
158   }
159   // Remove from the list objects already deleted before
160   std::set<int>::reverse_iterator anIt = anInvalidInd.rbegin();
161   for ( ; anIt != anInvalidInd.rend(); anIt++) {
162     if (*anIt < indFirstWrong) indFirstWrong--;
163     aRefListOfShapes->remove(aRefListOfShapes->object(*anIt));
164     aRefListOfMirrored->remove(aRefListOfMirrored->object(*anIt));
165   }
166   // If the lists inconsistent, remove all objects from mirrored list starting from indFirstWrong
167   if (anInitIter != anInitialList.end()) {
168     while (aRefListOfMirrored->size() > indFirstWrong)
169       aRefListOfMirrored->remove(aRefListOfMirrored->object(indFirstWrong));
170     // Create mirrored features instead of removed
171     anInitialList =  aRefListOfShapes->list();
172     anInitIter = anInitialList.begin();
173     for (int i = 0; i < indFirstWrong; i++) anInitIter++;
174     for ( ; anInitIter != anInitialList.end(); anInitIter++) {
175       aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
176       FeaturePtr aNewFeature = aFeatureIn->document()->addFeature(aFeatureIn->getKind());
177       aRefListOfMirrored->append(aNewFeature);
178     }
179   }
180
181   // send events to update the sub-features by the solver
182   if (isUpdateFlushed)
183     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
184 }
185
186 AISObjectPtr SketchPlugin_ConstraintMirror::getAISObject(AISObjectPtr thePrevious)
187 {
188   if (!sketch())
189     return thePrevious;
190
191   AISObjectPtr anAIS = thePrevious;
192   if (!anAIS) {
193     anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane());
194   }
195   return anAIS;
196 }
197
198 void SketchPlugin_ConstraintMirror::erase()
199 {
200   // Set copy attribute to false on all copied features.
201   AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
202       data()->attribute(SketchPlugin_Constraint::ENTITY_C()));
203
204   if(aRefListOfMirrored.get()) {
205     static Events_Loop* aLoop = Events_Loop::loop();
206     static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
207
208     std::list<ObjectPtr> aTargetList = aRefListOfMirrored->list();
209     for(std::list<ObjectPtr>::const_iterator aTargetIt = aTargetList.cbegin(); aTargetIt != aTargetList.cend(); aTargetIt++) {
210       if((*aTargetIt).get()) {
211         ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(*aTargetIt);
212         if(aRes.get()) {
213           FeaturePtr aFeature = aRes->document()->feature(aRes);
214           if(aFeature.get()) {
215             AttributeBooleanPtr aBooleanAttr = aFeature->boolean(SketchPlugin_SketchEntity::COPY_ID());
216             if(aBooleanAttr.get()) {
217               if (ModelAPI_Session::get()->isOperation()) // if this is not undo or redo
218                 aBooleanAttr->setValue(false);
219               // Redisplay object as it is not copy anymore.
220               ModelAPI_EventCreator::get()->sendUpdated(aRes, aRedispEvent);
221             }
222           }
223         }
224       }
225     }
226   }
227
228   SketchPlugin_ConstraintBase::erase();
229 }
230
231 void SketchPlugin_ConstraintMirror::attributeChanged(const std::string& theID)
232 {
233   if (theID == MIRROR_LIST_ID()) {
234     AttributeRefListPtr aMirrorObjectRefs = reflist(MIRROR_LIST_ID());
235     if (aMirrorObjectRefs->size() == 0) {
236       // Clear list of objects
237       AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
238           data()->attribute(SketchPlugin_Constraint::ENTITY_C()));
239       std::list<ObjectPtr> aTargetList = aRefListOfMirrored->list();
240       std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
241       for (; aTargetIter != aTargetList.end(); aTargetIter++) {
242         aRefListOfMirrored->remove(*aTargetIter);
243         // remove the corresponding feature from the sketch
244         ResultConstructionPtr aRC =
245             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
246         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
247         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
248         if (aFeature)
249           aDoc->removeFeature(aFeature);
250       }
251       aRefListOfMirrored->clear();
252       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
253         data()->attribute(SketchPlugin_Constraint::ENTITY_B()))->clear();
254     }
255   }
256 }
257