Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom into Dev_1.1.0
[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   if (!aMirrorObjectRefs->isInitialized())
47     return;
48
49   std::shared_ptr<ModelAPI_Data> aData = data();
50   AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
51       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
52   AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
53       aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
54   std::list<ObjectPtr> anInitialList =  aRefListOfShapes->list();
55   std::list<ObjectPtr> aMirroredList =  aRefListOfMirrored->list();
56   std::vector<bool> isUsed(anInitialList.size(), false);
57   // add new items to the list
58   for(int anInd = 0; anInd < aMirrorObjectRefs->size(); anInd++) {
59     std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aMirrorObjectRefs->value(anInd);
60     std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
61     std::vector<bool>::iterator aUsedIt = isUsed.begin();
62     for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
63       if (*anIt == aSelect->context()) {
64         *aUsedIt = true;
65         break;
66       }
67     if (anIt == anInitialList.end())
68       aRefListOfShapes->append(aSelect->context());
69   }
70   // remove unused items
71   std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
72   std::list<ObjectPtr>::iterator aMirrorIter = aMirroredList.begin();
73   std::vector<bool>::iterator aUsedIter = isUsed.begin();
74   for (; aUsedIter != isUsed.end(); aUsedIter++) {
75     if (!(*aUsedIter)) {
76       aRefListOfShapes->remove(*anInitIter);
77       if (aMirrorIter != aMirroredList.end()) {
78         aRefListOfMirrored->remove(*aMirrorIter);
79         // remove the corresponding feature from the sketch
80         ResultConstructionPtr aRC =
81             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirrorIter);
82         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
83         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
84         if (aFeature)
85           aDoc->removeFeature(aFeature);
86       }
87     }
88     if (anInitIter != anInitialList.end())
89       anInitIter++;
90     if (aMirrorIter != aMirroredList.end())
91       aMirrorIter++;
92   }
93
94   static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
95
96   // Check consistency of initial list and mirrored list
97   anInitialList =  aRefListOfShapes->list();
98   anInitIter = anInitialList.begin();
99   aMirrorIter = aMirroredList.begin();
100   int indFirstWrong = 0; // index of element starts difference in the lists
101   std::set<int> anInvalidInd; // list of indices of removed features
102   std::shared_ptr<SketchPlugin_Feature> aFeatureIn, aFeatureOut;
103   for ( ; anInitIter != anInitialList.end(); anInitIter++, indFirstWrong++) {
104     // Add features and store indices of objects to remove
105     aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
106     ResultConstructionPtr aRCIn;
107     if (!aFeatureIn) {
108       aRCIn = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
109       if (aRCIn)
110         aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(
111             aRCIn->document()->feature(aRCIn));
112     }
113     if (aMirrorIter == aMirroredList.end())
114       aFeatureOut = std::shared_ptr<SketchPlugin_Feature>();
115     else {
116       aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirrorIter);
117       if (!aFeatureOut) {
118         ResultConstructionPtr aRC =
119             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
120         if (aRC)
121           aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(
122               aRC->document()->feature(aRC));
123       }
124     }
125     if (!aFeatureIn) {
126       if (aFeatureOut)
127         break; // the lists are inconsistent
128       continue;
129     }
130     if (!aFeatureOut) {
131       if (aMirrorIter != aMirroredList.end())
132         break; // the lists are inconsistent
133       // There is no mirrored object yet, create it
134       FeaturePtr aNewFeature = sketch()->addFeature(aFeatureIn->getKind());
135       aFeatureIn->data()->copyTo(aNewFeature->data());
136       aNewFeature->execute();
137       ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
138
139       std::shared_ptr<GeomAPI_Shape> aShapeIn = aRCIn->shape();
140       const std::list<ResultPtr>& aResults = aNewFeature->results();
141       std::list<ResultPtr>::const_iterator anIt = aResults.begin();
142       for (; anIt != aResults.end(); anIt++) {
143         ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
144         if (!aRC) continue;
145         std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
146         if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
147             (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
148             (aShapeIn->isFace() && aShapeOut->isFace()))
149           aRefListOfMirrored->append(aRC);
150       }
151       continue;
152     }
153     if (aFeatureIn->getKind() != aFeatureOut->getKind())
154       break; // the lists are inconsistent
155     if (!aFeatureIn->data()->isValid()) {
156       // initial feature was removed, delete it from lists
157       anInvalidInd.insert(indFirstWrong);
158     }
159     aMirrorIter++;
160   }
161   // Remove from the list objects already deleted before
162   std::set<int>::reverse_iterator anIt = anInvalidInd.rbegin();
163   for ( ; anIt != anInvalidInd.rend(); anIt++) {
164     if (*anIt < indFirstWrong) indFirstWrong--;
165     aRefListOfShapes->remove(aRefListOfShapes->object(*anIt));
166     aRefListOfMirrored->remove(aRefListOfMirrored->object(*anIt));
167   }
168   // If the lists inconsistent, remove all objects from mirrored list starting from indFirstWrong
169   if (anInitIter != anInitialList.end()) {
170     while (aRefListOfMirrored->size() > indFirstWrong)
171       aRefListOfMirrored->remove(aRefListOfMirrored->object(indFirstWrong));
172     // Create mirrored features instead of removed
173     anInitialList =  aRefListOfShapes->list();
174     anInitIter = anInitialList.begin();
175     for (int i = 0; i < indFirstWrong; i++) anInitIter++;
176     for ( ; anInitIter != anInitialList.end(); anInitIter++) {
177       aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
178       FeaturePtr aNewFeature = aFeatureIn->document()->addFeature(aFeatureIn->getKind());
179       aRefListOfMirrored->append(aNewFeature);
180     }
181   }
182 }
183
184 AISObjectPtr SketchPlugin_ConstraintMirror::getAISObject(AISObjectPtr thePrevious)
185 {
186   if (!sketch())
187     return thePrevious;
188
189   AISObjectPtr anAIS = thePrevious;
190   if (!anAIS) {
191     anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane());
192   }
193   return anAIS;
194 }
195
196