Salome HOME
Simplification and refactoring of unit tests for SketchPlugin
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_MultiTranslation.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:    SketchPlugin_MultiTranslation.cpp
4 // Created: 21 Apr 2015
5 // Author:  Artem ZHIDKOV
6
7 #include "SketchPlugin_MultiTranslation.h"
8 #include "SketchPlugin_Tools.h"
9
10 #include <GeomAPI_XY.h>
11 #include <GeomDataAPI_Point2D.h>
12 #include <ModelAPI_AttributeDouble.h>
13 #include <ModelAPI_AttributeInteger.h>
14 #include <ModelAPI_Data.h>
15 #include <ModelAPI_ResultConstruction.h>
16 #include <ModelAPI_AttributeRefList.h>
17 #include <ModelAPI_AttributeRefAttr.h>
18 #include <ModelAPI_AttributeString.h>
19 #include <ModelAPI_Events.h>
20 #include <ModelAPI_Session.h>
21 #include <ModelAPI_Validator.h>
22 #include <ModelAPI_Tools.h>
23
24 #include <SketchPlugin_SketchEntity.h>
25 #include <SketcherPrs_Factory.h>
26
27 SketchPlugin_MultiTranslation::SketchPlugin_MultiTranslation()
28 {
29 }
30
31 void SketchPlugin_MultiTranslation::initAttributes()
32 {
33   data()->addAttribute(VALUE_TYPE(),   ModelAPI_AttributeString::typeId());
34
35   data()->addAttribute(START_POINT_ID(), ModelAPI_AttributeRefAttr::typeId());
36   data()->addAttribute(END_POINT_ID(), ModelAPI_AttributeRefAttr::typeId());
37
38   data()->addAttribute(NUMBER_OF_OBJECTS_ID(), ModelAPI_AttributeInteger::typeId());
39   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId());
40   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
41   data()->addAttribute(TRANSLATION_LIST_ID(), ModelAPI_AttributeRefList::typeId());
42   ModelAPI_Session::get()->validators()->
43     registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A());
44   ModelAPI_Session::get()->validators()->
45     registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
46 }
47
48 void SketchPlugin_MultiTranslation::execute()
49 {
50   if (!sketch()) {
51     // it is possible, that this method is called before this feature has back reference to sketch
52     // in this case, the execute is performed after this is done
53     return;
54   }
55
56   AttributeRefListPtr aTranslationObjectRefs = reflist(TRANSLATION_LIST_ID());
57   int aNbCopies = integer(NUMBER_OF_OBJECTS_ID())->value()-1;
58   if (aNbCopies <= 0)
59     return;
60
61   // Calculate shift vector
62   AttributeRefAttrPtr aStartAttr = data()->refattr(START_POINT_ID());
63   AttributeRefAttrPtr anEndAttr = data()->refattr(END_POINT_ID());
64
65   if (!aStartAttr || !anEndAttr || !aStartAttr->isInitialized() || !anEndAttr->isInitialized())
66     return;
67
68   DataPtr aData = data();
69   AttributePoint2DPtr aStart = GeomDataAPI_Point2D::getPoint2D(aData, START_POINT_ID());
70   AttributePoint2DPtr aEnd = GeomDataAPI_Point2D::getPoint2D(aData, END_POINT_ID());
71   if (!aStart || !aEnd)
72     return;
73
74   std::shared_ptr<GeomAPI_XY>
75     aShiftVec(new GeomAPI_XY(aEnd->x() - aStart->x(), aEnd->y() - aStart->y()));
76
77   // Wait all objects being created, then send update events
78   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
79   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
80   if (isUpdateFlushed)
81     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
82
83   AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
84       aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
85   AttributeRefListPtr aRefListOfTranslated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
86       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
87   int aCurrentNbCopies = aRefListOfShapes->size() ?
88       aRefListOfTranslated->size() / aRefListOfShapes->size() - 1 : 0;
89   std::list<ObjectPtr> anInitialList = aRefListOfShapes->list();
90   std::list<ObjectPtr> aTargetList = aRefListOfTranslated->list();
91   std::list<ObjectPtr> anAddition;
92   std::vector<bool> isUsed(anInitialList.size(), false);
93   // collect new items and check the items to remove
94   for(int anInd = 0; anInd < aTranslationObjectRefs->size(); anInd++) {
95     //std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aTranslationObjectRefs->value(anInd);
96     ObjectPtr anObject = aTranslationObjectRefs->object(anInd);
97     std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
98     std::vector<bool>::iterator aUsedIt = isUsed.begin();
99     for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
100       if (*anIt == anObject) {
101         *aUsedIt = true;
102         break;
103       }
104     if (anIt == anInitialList.end())
105       anAddition.push_back(anObject);
106   }
107   // remove unused items
108   std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
109   std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
110   std::vector<bool>::iterator aUsedIter = isUsed.begin();
111   std::set<FeaturePtr> aFeaturesToBeRemoved;
112   for (; aUsedIter != isUsed.end(); aUsedIter++) {
113     if (!(*aUsedIter)) {
114       aRefListOfShapes->remove(*anInitIter);
115       aRefListOfTranslated->remove(*aTargetIter++);
116       for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end();
117            i++, aTargetIter++) {
118         aRefListOfTranslated->remove(*aTargetIter);
119         // remove the corresponding feature from the sketch
120         ResultConstructionPtr aRC =
121             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
122         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
123         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
124         if (aFeature)
125           aFeaturesToBeRemoved.insert(aFeature);
126       }
127     } else {
128       for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++)
129         aTargetIter++;
130     }
131     if (anInitIter != anInitialList.end())
132       anInitIter++;
133   }
134   ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
135   // change number of copies
136   if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) {
137     bool isAdd = aNbCopies > aCurrentNbCopies;
138     int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies;
139     int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies;
140     int ind = 0;
141
142     aTargetList = aRefListOfTranslated->list();
143     aTargetIter = aTargetList.begin();
144     ObjectPtr anObjToCopy = *aTargetIter;
145     while (aTargetIter != aTargetList.end()) {
146       aRefListOfTranslated->remove(*aTargetIter);
147       aTargetIter++;
148       ind++;
149       if (ind > aMinCopies && ind <=aMaxCopies) {
150         while (ind <= aMaxCopies) {
151           if (isAdd) {
152             // Add new shifted item
153             ObjectPtr anObject = copyFeature(anObjToCopy);
154             aTargetList.insert(aTargetIter, anObject);
155           } else {
156             // remove object
157             std::list<ObjectPtr>::iterator aRemoveIt = aTargetIter++;
158             ObjectPtr anObject = *aRemoveIt;
159             aTargetList.erase(aRemoveIt);
160             aRefListOfTranslated->remove(anObject);
161             // remove the corresponding feature from the sketch
162             ResultConstructionPtr aRC =
163                 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anObject);
164             DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
165             FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
166             if (aFeature)
167               aDoc->removeFeature(aFeature);
168           }
169           ind++;
170         }
171         ind = 0;
172         if (aTargetIter != aTargetList.end())
173           anObjToCopy = *aTargetIter;
174       }
175     }
176
177     for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++)
178       aRefListOfTranslated->append(*aTargetIter);
179   }
180   // add new items
181   std::list<ObjectPtr>::iterator anAddIter = anAddition.begin();
182   for (; anAddIter != anAddition.end(); anAddIter++) {
183     aRefListOfShapes->append(*anAddIter);
184     aRefListOfTranslated->append(*anAddIter);
185     for (int i = 0; i < aNbCopies; i++) {
186       ObjectPtr anObject = copyFeature(*anAddIter);
187       aRefListOfTranslated->append(anObject);
188     }
189   }
190
191   // send events to update the sub-features by the solver
192   if (isUpdateFlushed)
193     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
194 }
195
196 AISObjectPtr SketchPlugin_MultiTranslation::getAISObject(AISObjectPtr thePrevious)
197 {
198   if (!sketch())
199     return thePrevious;
200
201   AISObjectPtr anAIS = SketcherPrs_Factory::translateConstraint(this, sketch()->coordinatePlane(),
202                                                                 thePrevious);
203   return anAIS;
204 }
205
206 void SketchPlugin_MultiTranslation::erase()
207 {
208   static Events_Loop* aLoop = Events_Loop::loop();
209   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
210
211   // Set copy attribute to false on all copied features.
212   AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
213       data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
214   AttributeRefListPtr aRefListOfTranslated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
215       data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
216
217   if(aRefListOfShapes.get() && aRefListOfTranslated.get()) {
218     for(int anIndex = 0; anIndex < aRefListOfTranslated->size(); anIndex++) {
219       ObjectPtr anObject = aRefListOfTranslated->object(anIndex);
220       if(aRefListOfShapes->isInList(anObject)) {
221         // Don't modify attribute of original features, just skip.
222         continue;
223       }
224       if(anObject.get()) {
225         ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
226         if(aRes.get()) {
227           FeaturePtr aFeature = aRes->document()->feature(aRes);
228           if(aFeature.get()) {
229             AttributeBooleanPtr aBooleanAttr =
230               aFeature->boolean(SketchPlugin_SketchEntity::COPY_ID());
231             if(aBooleanAttr.get()) {
232               if (ModelAPI_Session::get()->isOperation()) // if this is not undo or redo
233                 aBooleanAttr->setValue(false);
234               // Redisplay object as it is not copy anymore.
235               ModelAPI_EventCreator::get()->sendUpdated(aRes, aRedispEvent);
236             }
237           }
238         }
239       }
240     }
241   }
242
243   SketchPlugin_ConstraintBase::erase();
244 }
245
246 ObjectPtr SketchPlugin_MultiTranslation::copyFeature(ObjectPtr theObject)
247 {
248   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
249   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
250   if (!aFeature || !aResult)
251     return ObjectPtr();
252
253   FeaturePtr aNewFeature =
254     SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aFeature, sketch(), true);
255
256   aNewFeature->execute();
257   static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
258   ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
259
260   std::shared_ptr<GeomAPI_Shape> aShapeIn = aResult->shape();
261   const std::list<ResultPtr>& aResults = aNewFeature->results();
262   std::list<ResultPtr>::const_iterator anIt = aResults.begin();
263   for (; anIt != aResults.end(); anIt++) {
264     ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
265     if (!aRC) continue;
266     std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
267     if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
268         (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
269         (aShapeIn->isFace() && aShapeOut->isFace()))
270       return aRC;
271   }
272   return ObjectPtr();
273 }
274
275 void SketchPlugin_MultiTranslation::attributeChanged(const std::string& theID)
276 {
277   if (theID == TRANSLATION_LIST_ID()) {
278     AttributeRefListPtr aTranslationObjectRefs = reflist(TRANSLATION_LIST_ID());
279     if (aTranslationObjectRefs->size() == 0) {
280       int aNbCopies = integer(NUMBER_OF_OBJECTS_ID())->value()-1;
281       if (aNbCopies <= 0)
282         return;
283
284       DocumentPtr aDoc = document();
285       // Clear list of objects
286       AttributeRefListPtr aRefListOfTranslated = reflist(SketchPlugin_Constraint::ENTITY_B());
287       std::list<ObjectPtr> aTargetList = aRefListOfTranslated->list();
288       std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
289       while (aTargetIter != aTargetList.end()) {
290         aTargetIter++;
291         for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
292           aRefListOfTranslated->remove(*aTargetIter);
293           FeaturePtr aFeature = ModelAPI_Feature::feature(*aTargetIter);
294           if (aFeature)
295             aDoc->removeFeature(aFeature);
296         }
297       }
298       aRefListOfTranslated->clear();
299       reflist(SketchPlugin_Constraint::ENTITY_A())->clear();
300     }
301   }
302 }