]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_MultiRotation.cpp
Salome HOME
COPY attribute in SketchEntity now persistent
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_MultiRotation.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:    SketchPlugin_MultiRotation.cpp
4 // Created: 21 Apr 2015
5 // Author:  Artem ZHIDKOV
6
7 #include "SketchPlugin_MultiRotation.h"
8 #include "SketchPlugin_Tools.h"
9
10 #include <GeomDataAPI_Point2D.h>
11 #include <ModelAPI_AttributeRefAttr.h>
12 #include <ModelAPI_AttributeDouble.h>
13 #include <ModelAPI_AttributeString.h>
14 #include <ModelAPI_AttributeInteger.h>
15 #include <ModelAPI_Data.h>
16 #include <ModelAPI_ResultConstruction.h>
17 #include <ModelAPI_AttributeRefList.h>
18 #include <ModelAPI_Events.h>
19 #include <ModelAPI_Session.h>
20 #include <ModelAPI_Validator.h>
21
22 #include <SketchPlugin_SketchEntity.h>
23
24 #include <GeomAPI_Pnt2d.h>
25 #include <GeomAPI_XY.h>
26
27 #include <SketcherPrs_Factory.h>
28
29 #include <cmath>
30
31 #define PI 3.1415926535897932
32
33 SketchPlugin_MultiRotation::SketchPlugin_MultiRotation()
34 {
35 }
36
37 void SketchPlugin_MultiRotation::initAttributes()
38 {
39   data()->addAttribute(CENTER_ID(), ModelAPI_AttributeRefAttr::typeId());
40
41   data()->addAttribute(ANGLE_TYPE(),   ModelAPI_AttributeString::typeId());
42   data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
43   data()->addAttribute(NUMBER_OF_OBJECTS_ID(), ModelAPI_AttributeInteger::typeId());
44   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId());
45   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
46   data()->addAttribute(ROTATION_LIST_ID(), ModelAPI_AttributeRefList::typeId());
47   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A());
48   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
49 }
50
51 void SketchPlugin_MultiRotation::execute()
52 {
53   if (!sketch()) {
54     // it is possible, that this method is called before this feature has back reference to sketch
55     // in this case, the execute is performed after this is done
56     return;
57   }
58
59   AttributeRefListPtr aRotationObjectRefs = reflist(ROTATION_LIST_ID());
60   int aNbCopies = integer(NUMBER_OF_OBJECTS_ID())->value() - 1;
61   if (aNbCopies <= 0)
62     return;
63
64   // Obtain center and angle of rotation
65   AttributeRefAttrPtr aCenter = data()->refattr(CENTER_ID());
66   if (!aCenter || !aCenter->isInitialized())
67     return;
68
69   //double anAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
70   //                                                           attribute(ANGLE_ID()))->value();
71
72   // Convert angle to radians
73   //anAngle *= PI / 180.0;
74
75   // Wait all objects being created, then send update events
76   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
77   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
78   if (isUpdateFlushed)
79     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
80
81   std::shared_ptr<ModelAPI_Data> aData = data();
82   AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
83       aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
84   AttributeRefListPtr aRefListOfRotated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
85       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
86   int aCurrentNbCopies = aRefListOfShapes->size() ?
87       aRefListOfRotated->size() / aRefListOfShapes->size() - 1 : 0;
88   std::list<ObjectPtr> anInitialList = aRefListOfShapes->list();
89   std::list<ObjectPtr> aTargetList = aRefListOfRotated->list();
90   std::list<ObjectPtr> anAddition;
91   std::vector<bool> isUsed(anInitialList.size(), false);
92   // collect new items and check the items to remove
93   for(int anInd = 0; anInd < aRotationObjectRefs->size(); anInd++) {
94     ObjectPtr anObject = aRotationObjectRefs->object(anInd);
95     std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
96     std::vector<bool>::iterator aUsedIt = isUsed.begin();
97     for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
98       if (*anIt == anObject) {
99         *aUsedIt = true;
100         break;
101       }
102     if (anIt == anInitialList.end())
103       anAddition.push_back(anObject);
104   }
105   // remove unused items
106   std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
107   std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
108   std::vector<bool>::iterator aUsedIter = isUsed.begin();
109   for (; aUsedIter != isUsed.end(); aUsedIter++) {
110     if (!(*aUsedIter)) {
111       aRefListOfShapes->remove(*anInitIter);
112       aRefListOfRotated->remove(*aTargetIter++);
113       for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
114         aRefListOfRotated->remove(*aTargetIter);
115         // remove the corresponding feature from the sketch
116         ResultConstructionPtr aRC =
117             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
118         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
119         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
120         if (aFeature)
121           aDoc->removeFeature(aFeature);
122       }
123     } else {
124       for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++)
125         aTargetIter++;
126     }
127     if (anInitIter != anInitialList.end())
128       anInitIter++;
129   }
130   // change number of copies
131   if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) {
132     bool isAdd = aNbCopies > aCurrentNbCopies;
133     int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies;
134     int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies;
135     int ind = 0;
136
137     aTargetList = aRefListOfRotated->list();
138     aTargetIter = aTargetList.begin();
139     ObjectPtr anObjToCopy = *aTargetIter;
140     while (aTargetIter != aTargetList.end()) {
141       aRefListOfRotated->remove(*aTargetIter);
142       aTargetIter++;
143       ind++;
144       if (ind > aMinCopies && ind <=aMaxCopies) {
145         while (ind <= aMaxCopies) {
146           if (isAdd) {
147             // Add new shifted item
148             ObjectPtr anObject = copyFeature(anObjToCopy);
149             aTargetList.insert(aTargetIter, anObject);
150           } else {
151             // remove object
152             std::list<ObjectPtr>::iterator aRemoveIt = aTargetIter++;
153             ObjectPtr anObject = *aRemoveIt;
154             aTargetList.erase(aRemoveIt);
155             aRefListOfRotated->remove(anObject);
156             // remove the corresponding feature from the sketch
157             ResultConstructionPtr aRC =
158                 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anObject);
159             DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
160             FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
161             if (aFeature)
162               aDoc->removeFeature(aFeature);
163           }
164           ind++;
165         }
166         ind = 0;
167         if (aTargetIter != aTargetList.end())
168           anObjToCopy = *aTargetIter;
169       }
170     }
171
172     for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++)
173       aRefListOfRotated->append(*aTargetIter);
174   }
175   // add new items
176   std::list<ObjectPtr>::iterator anAddIter = anAddition.begin();
177   for (; anAddIter != anAddition.end(); anAddIter++) {
178     aRefListOfShapes->append(*anAddIter);
179     aRefListOfRotated->append(*anAddIter);
180     for (int i = 0; i < aNbCopies; i++) {
181       ObjectPtr anObject = copyFeature(*anAddIter);
182       aRefListOfRotated->append(anObject);
183     }
184   }
185
186 ////  if (fabs(anAngle) > 1.e-12) {
187 ////    // Recalculate positions of features
188 ////    aTargetList = aRefListOfRotated->list();
189 ////    aTargetIter = aTargetList.begin();
190 ////    while (aTargetIter != aTargetList.end()) {
191 ////      ObjectPtr anInitialObject = *aTargetIter++;
192 ////      for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++)
193 ////        rotateFeature(anInitialObject, *aTargetIter, aCenter->x(), aCenter->y(), anAngle * (i + 1));
194 ////    }
195 ////  }
196
197   // send events to update the sub-features by the solver
198   if (isUpdateFlushed)
199     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
200 }
201
202 AISObjectPtr SketchPlugin_MultiRotation::getAISObject(AISObjectPtr thePrevious)
203 {
204   if (!sketch())
205     return thePrevious;
206
207   AISObjectPtr anAIS = thePrevious;
208   if (!anAIS) {
209     anAIS = SketcherPrs_Factory::rotateConstraint(this, sketch()->coordinatePlane());
210   }
211   return anAIS;
212 }
213
214 void SketchPlugin_MultiRotation::erase()
215 {
216   // Set copy attribute to false on all copied features.
217   AttributeRefListPtr aRefListOfRotated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
218       data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
219
220   if(aRefListOfRotated.get()) {
221     static Events_Loop* aLoop = Events_Loop::loop();
222     static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
223
224     std::list<ObjectPtr> aTargetList = aRefListOfRotated->list();
225     for(std::list<ObjectPtr>::const_iterator aTargetIt = aTargetList.cbegin(); aTargetIt != aTargetList.cend(); aTargetIt++) {
226       if((*aTargetIt).get()) {
227         ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(*aTargetIt);
228         if(aRes.get()) {
229           FeaturePtr aFeature = aRes->document()->feature(aRes);
230           if(aFeature.get()) {
231             AttributeBooleanPtr aBooleanAttr = aFeature->boolean(SketchPlugin_SketchEntity::COPY_ID());
232             if(aBooleanAttr.get()) {
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_MultiRotation::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 = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aFeature, sketch(), true);
254   aNewFeature->execute();
255
256   static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
257   ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
258
259   std::shared_ptr<GeomAPI_Shape> aShapeIn = aResult->shape();
260   const std::list<ResultPtr>& aResults = aNewFeature->results();
261   std::list<ResultPtr>::const_iterator anIt = aResults.begin();
262   for (; anIt != aResults.end(); anIt++) {
263     ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
264     if (!aRC) continue;
265     std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
266     if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
267         (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
268         (aShapeIn->isFace() && aShapeOut->isFace()))
269       return aRC;
270   }
271   return ObjectPtr();
272 }
273
274 /*void SketchPlugin_MultiRotation::rotateFeature(
275     ObjectPtr theInitial, ObjectPtr theTarget,
276     double theCenterX, double theCenterY, double theAngle)
277 {
278   std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(theCenterX, theCenterY));
279   double cosA = std::cos(theAngle);
280   double sinA = std::sin(theAngle);
281
282   FeaturePtr anInitialFeature = ModelAPI_Feature::feature(theInitial);
283   FeaturePtr aTargetFeature = ModelAPI_Feature::feature(theTarget);
284
285   // block feature update
286   aTargetFeature->data()->blockSendAttributeUpdated(true);
287
288   std::list<AttributePtr> anInitAttrList =
289       anInitialFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
290   std::list<AttributePtr> aTargetAttrList =
291       aTargetFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
292   std::list<AttributePtr>::iterator anInitIt = anInitAttrList.begin();
293   std::list<AttributePtr>::iterator aTargetIt = aTargetAttrList.begin();
294   for (; anInitIt != anInitAttrList.end(); anInitIt++, aTargetIt++) {
295     std::shared_ptr<GeomDataAPI_Point2D> aPointFrom =
296         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anInitIt);
297     std::shared_ptr<GeomDataAPI_Point2D> aPointTo =
298         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aTargetIt);
299     std::shared_ptr<GeomAPI_XY> aPnt = aPointFrom->pnt()->xy();
300     if (aPnt->distance(aCenter->xy()) > 1.e-7) {
301       std::shared_ptr<GeomAPI_XY> aDir = aPnt->decreased(aCenter->xy());
302       double dx = cosA * aDir->x() - sinA * aDir->y();
303       double dy = sinA * aDir->x() + cosA * aDir->y();
304       aPnt->setX(aCenter->x() + dx);
305       aPnt->setY(aCenter->y() + dy);
306     }
307     aPointTo->setValue(aPnt->x(), aPnt->y());
308   }
309
310   // unblock feature update
311   aTargetFeature->data()->blockSendAttributeUpdated(false);
312 }*/
313
314
315 void SketchPlugin_MultiRotation::attributeChanged(const std::string& theID)
316 {
317   if (theID == ROTATION_LIST_ID()) {
318     AttributeRefListPtr aRotationObjectRefs = reflist(ROTATION_LIST_ID());
319     if (aRotationObjectRefs->size() == 0) {
320       int aNbCopies = integer(NUMBER_OF_OBJECTS_ID())->value()-1;
321       if (aNbCopies <= 0)
322         return;
323
324       // Clear list of objects
325       AttributeRefListPtr aRefListOfRotated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
326           data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
327       std::list<ObjectPtr> aTargetList = aRefListOfRotated->list();
328       std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
329       while (aTargetIter != aTargetList.end()) {
330         aTargetIter++;
331         for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
332           aRefListOfRotated->remove(*aTargetIter);
333           // remove the corresponding feature from the sketch
334           ResultConstructionPtr aRC =
335             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
336           DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
337           FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
338           if (aFeature)
339             aDoc->removeFeature(aFeature);
340         }
341       }
342       aRefListOfRotated->clear();
343       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
344         data()->attribute(SketchPlugin_Constraint::ENTITY_A()))->clear();
345       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
346         data()->attribute(SketchPlugin_Constraint::ENTITY_B()))->clear();
347     }
348   }
349 }