Salome HOME
Make concealment of results working on compsolids: if at least one sub-body is concea...
[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_AttributeSelectionList.h>
14 #include <ModelAPI_Events.h>
15 #include <ModelAPI_Session.h>
16 #include <ModelAPI_Validator.h>
17
18 #include <SketchPlugin_Line.h>
19 #include <SketchPlugin_Sketch.h>
20
21 #include <SketcherPrs_Factory.h>
22
23 #include <Config_PropManager.h>
24
25 SketchPlugin_ConstraintMirror::SketchPlugin_ConstraintMirror()
26 {
27 }
28
29 void SketchPlugin_ConstraintMirror::initAttributes()
30 {
31   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
32   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
33   data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::typeId());
34   AttributeSelectionListPtr aSelection = 
35     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
36     SketchPlugin_ConstraintMirror::MIRROR_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
37   aSelection->setSelectionType("EDGE");
38   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
39   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_C());
40 }
41
42 void SketchPlugin_ConstraintMirror::execute()
43 {
44   AttributeSelectionListPtr aMirrorObjectRefs =
45       selectionList(SketchPlugin_ConstraintMirror::MIRROR_LIST_ID());
46
47   // Wait all objects being created, then send update events
48   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
49   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
50   if (isUpdateFlushed)
51     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
52
53   std::shared_ptr<ModelAPI_Data> aData = data();
54   AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
55       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
56   AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
57       aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
58   std::list<ObjectPtr> anInitialList =  aRefListOfShapes->list();
59   std::list<ObjectPtr> aMirroredList =  aRefListOfMirrored->list();
60   std::vector<bool> isUsed(anInitialList.size(), false);
61   // add new items to the list
62   for(int anInd = 0; anInd < aMirrorObjectRefs->size(); anInd++) {
63     std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aMirrorObjectRefs->value(anInd);
64     std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
65     std::vector<bool>::iterator aUsedIt = isUsed.begin();
66     for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
67       if (*anIt == aSelect->context()) {
68         *aUsedIt = true;
69         break;
70       }
71     if (anIt == anInitialList.end())
72       aRefListOfShapes->append(aSelect->context());
73   }
74   // remove unused items
75   std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
76   std::list<ObjectPtr>::iterator aMirrorIter = aMirroredList.begin();
77   std::vector<bool>::iterator aUsedIter = isUsed.begin();
78   for (; aUsedIter != isUsed.end(); aUsedIter++) {
79     if (!(*aUsedIter)) {
80       aRefListOfShapes->remove(*anInitIter);
81       if (aMirrorIter != aMirroredList.end()) {
82         aRefListOfMirrored->remove(*aMirrorIter);
83         // remove the corresponding feature from the sketch
84         ResultConstructionPtr aRC =
85             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirrorIter);
86         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
87         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
88         if (aFeature)
89           aDoc->removeFeature(aFeature);
90       }
91     }
92     if (anInitIter != anInitialList.end())
93       anInitIter++;
94     if (aMirrorIter != aMirroredList.end())
95       aMirrorIter++;
96   }
97
98   static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
99
100   // Check consistency of initial list and mirrored list
101   anInitialList =  aRefListOfShapes->list();
102   anInitIter = anInitialList.begin();
103   aMirrorIter = aMirroredList.begin();
104   int indFirstWrong = 0; // index of element starts difference in the lists
105   std::set<int> anInvalidInd; // list of indices of removed features
106   std::shared_ptr<SketchPlugin_Feature> aFeatureIn, aFeatureOut;
107   for ( ; anInitIter != anInitialList.end(); anInitIter++, indFirstWrong++) {
108     // Add features and store indices of objects to remove
109     aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
110     ResultConstructionPtr aRCIn;
111     if (!aFeatureIn) {
112       aRCIn = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
113       if (aRCIn)
114         aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(
115             aRCIn->document()->feature(aRCIn));
116     }
117     if (aMirrorIter == aMirroredList.end())
118       aFeatureOut = std::shared_ptr<SketchPlugin_Feature>();
119     else {
120       aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirrorIter);
121       if (!aFeatureOut) {
122         ResultConstructionPtr aRC =
123             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
124         if (aRC)
125           aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(
126               aRC->document()->feature(aRC));
127       }
128     }
129     if (!aFeatureIn) {
130       if (aFeatureOut)
131         break; // the lists are inconsistent
132       continue;
133     }
134     if (!aFeatureOut) {
135       if (aMirrorIter != aMirroredList.end())
136         break; // the lists are inconsistent
137       // There is no mirrored object yet, create it
138       FeaturePtr aNewFeature = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aFeatureIn, sketch());
139       aNewFeature->execute();
140       ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
141
142       std::shared_ptr<GeomAPI_Shape> aShapeIn = aRCIn->shape();
143       const std::list<ResultPtr>& aResults = aNewFeature->results();
144       std::list<ResultPtr>::const_iterator anIt = aResults.begin();
145       for (; anIt != aResults.end(); anIt++) {
146         ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
147         if (!aRC) continue;
148         std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
149         if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
150             (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
151             (aShapeIn->isFace() && aShapeOut->isFace()))
152           aRefListOfMirrored->append(aRC);
153       }
154       continue;
155     }
156     if (aFeatureIn->getKind() != aFeatureOut->getKind())
157       break; // the lists are inconsistent
158     if (!aFeatureIn->data()->isValid()) {
159       // initial feature was removed, delete it from lists
160       anInvalidInd.insert(indFirstWrong);
161     }
162     aMirrorIter++;
163   }
164   // Remove from the list objects already deleted before
165   std::set<int>::reverse_iterator anIt = anInvalidInd.rbegin();
166   for ( ; anIt != anInvalidInd.rend(); anIt++) {
167     if (*anIt < indFirstWrong) indFirstWrong--;
168     aRefListOfShapes->remove(aRefListOfShapes->object(*anIt));
169     aRefListOfMirrored->remove(aRefListOfMirrored->object(*anIt));
170   }
171   // If the lists inconsistent, remove all objects from mirrored list starting from indFirstWrong
172   if (anInitIter != anInitialList.end()) {
173     while (aRefListOfMirrored->size() > indFirstWrong)
174       aRefListOfMirrored->remove(aRefListOfMirrored->object(indFirstWrong));
175     // Create mirrored features instead of removed
176     anInitialList =  aRefListOfShapes->list();
177     anInitIter = anInitialList.begin();
178     for (int i = 0; i < indFirstWrong; i++) anInitIter++;
179     for ( ; anInitIter != anInitialList.end(); anInitIter++) {
180       aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
181       FeaturePtr aNewFeature = aFeatureIn->document()->addFeature(aFeatureIn->getKind());
182       aRefListOfMirrored->append(aNewFeature);
183     }
184   }
185
186   // send events to update the sub-features by the solver
187   if (isUpdateFlushed)
188     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
189 }
190
191 AISObjectPtr SketchPlugin_ConstraintMirror::getAISObject(AISObjectPtr thePrevious)
192 {
193   if (!sketch())
194     return thePrevious;
195
196   AISObjectPtr anAIS = thePrevious;
197   if (!anAIS) {
198     anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane());
199   }
200   return anAIS;
201 }
202
203
204 void SketchPlugin_ConstraintMirror::attributeChanged(const std::string& theID)
205 {
206   if (theID == MIRROR_LIST_ID()) {
207     AttributeSelectionListPtr aMirrorObjectRefs = selectionList(MIRROR_LIST_ID());
208     if (aMirrorObjectRefs->size() == 0) {
209       // Clear list of objects
210       AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
211           data()->attribute(SketchPlugin_Constraint::ENTITY_C()));
212       std::list<ObjectPtr> aTargetList = aRefListOfMirrored->list();
213       std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
214       for (; aTargetIter != aTargetList.end(); aTargetIter++) {
215         aRefListOfMirrored->remove(*aTargetIter);
216         // remove the corresponding feature from the sketch
217         ResultConstructionPtr aRC =
218             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
219         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
220         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
221         if (aFeature)
222           aDoc->removeFeature(aFeature);
223       }
224     }
225   }
226 }
227