1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: SketchPlugin_ConstraintMirror.cpp
4 // Created: 17 Mar 2015
5 // Author: Artem ZHIDKOV
7 #include "SketchPlugin_ConstraintMirror.h"
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 #include <ModelAPI_Tools.h>
18 #include <SketchPlugin_Line.h>
19 #include <SketchPlugin_Sketch.h>
21 #include <SketcherPrs_Factory.h>
23 #include <Config_PropManager.h>
25 SketchPlugin_ConstraintMirror::SketchPlugin_ConstraintMirror()
29 void SketchPlugin_ConstraintMirror::initAttributes()
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 data()->addAttribute(SketchPlugin_ConstraintMirror::MIRROR_LIST_ID(), ModelAPI_AttributeRefList::typeId());
35 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
36 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_C());
39 void SketchPlugin_ConstraintMirror::execute()
41 AttributeRefListPtr aMirrorObjectRefs = reflist(SketchPlugin_ConstraintMirror::MIRROR_LIST_ID());
43 // Wait all objects being created, then send update events
44 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
45 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
47 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
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 ObjectPtr anObject = aMirrorObjectRefs->object(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 == anObject) {
67 if (anIt == anInitialList.end())
68 aRefListOfShapes->append(anObject);
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 std::set<FeaturePtr> aFeaturesToBeRemoved;
75 for (; aUsedIter != isUsed.end(); aUsedIter++) {
77 aRefListOfShapes->remove(*anInitIter);
78 if (aMirrorIter != aMirroredList.end()) {
79 aRefListOfMirrored->remove(*aMirrorIter);
80 // remove the corresponding feature from the sketch
81 ResultConstructionPtr aRC =
82 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirrorIter);
83 DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
84 FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr();
86 aFeaturesToBeRemoved.insert(aFeature);
89 if (anInitIter != anInitialList.end())
91 if (aMirrorIter != aMirroredList.end())
94 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
96 static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
98 // Check consistency of initial list and mirrored list
99 anInitialList = aRefListOfShapes->list();
100 anInitIter = anInitialList.begin();
101 aMirrorIter = aMirroredList.begin();
102 int indFirstWrong = 0; // index of element starts difference in the lists
103 std::set<int> anInvalidInd; // list of indices of removed features
104 std::shared_ptr<SketchPlugin_Feature> aFeatureIn, aFeatureOut;
105 for ( ; anInitIter != anInitialList.end(); anInitIter++, indFirstWrong++) {
106 // Add features and store indices of objects to remove
107 aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
108 ResultConstructionPtr aRCIn;
110 aRCIn = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
112 aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(
113 aRCIn->document()->feature(aRCIn));
115 if (aMirrorIter == aMirroredList.end())
116 aFeatureOut = std::shared_ptr<SketchPlugin_Feature>();
118 aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirrorIter);
120 ResultConstructionPtr aRC =
121 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
123 aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(
124 aRC->document()->feature(aRC));
129 break; // the lists are inconsistent
133 if (aMirrorIter != aMirroredList.end())
134 break; // the lists are inconsistent
135 // There is no mirrored object yet, create it
136 FeaturePtr aNewFeature = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aFeatureIn, sketch(), true);
137 aNewFeature->execute();
138 ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
140 std::shared_ptr<GeomAPI_Shape> aShapeIn = aRCIn->shape();
141 const std::list<ResultPtr>& aResults = aNewFeature->results();
142 std::list<ResultPtr>::const_iterator anIt = aResults.begin();
143 for (; anIt != aResults.end(); anIt++) {
144 ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
146 std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
147 if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
148 (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
149 (aShapeIn->isFace() && aShapeOut->isFace()))
150 aRefListOfMirrored->append(aRC);
154 if (aFeatureIn->getKind() != aFeatureOut->getKind())
155 break; // the lists are inconsistent
156 if (!aFeatureIn->data()->isValid()) {
157 // initial feature was removed, delete it from lists
158 anInvalidInd.insert(indFirstWrong);
162 // Remove from the list objects already deleted before
163 std::set<int>::reverse_iterator anIt = anInvalidInd.rbegin();
164 for ( ; anIt != anInvalidInd.rend(); anIt++) {
165 if (*anIt < indFirstWrong) indFirstWrong--;
166 aRefListOfShapes->remove(aRefListOfShapes->object(*anIt));
167 aRefListOfMirrored->remove(aRefListOfMirrored->object(*anIt));
169 // If the lists inconsistent, remove all objects from mirrored list starting from indFirstWrong
170 if (anInitIter != anInitialList.end()) {
171 while (aRefListOfMirrored->size() > indFirstWrong)
172 aRefListOfMirrored->remove(aRefListOfMirrored->object(indFirstWrong));
173 // Create mirrored features instead of removed
174 anInitialList = aRefListOfShapes->list();
175 anInitIter = anInitialList.begin();
176 for (int i = 0; i < indFirstWrong; i++) anInitIter++;
177 for ( ; anInitIter != anInitialList.end(); anInitIter++) {
178 aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
179 FeaturePtr aNewFeature = aFeatureIn->document()->addFeature(aFeatureIn->getKind());
180 aRefListOfMirrored->append(aNewFeature);
184 // send events to update the sub-features by the solver
186 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
189 AISObjectPtr SketchPlugin_ConstraintMirror::getAISObject(AISObjectPtr thePrevious)
194 AISObjectPtr anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane(),
199 void SketchPlugin_ConstraintMirror::erase()
201 // Set copy attribute to false on all copied features.
202 AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
203 data()->attribute(SketchPlugin_Constraint::ENTITY_C()));
205 if(aRefListOfMirrored.get()) {
206 static Events_Loop* aLoop = Events_Loop::loop();
207 static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
209 std::list<ObjectPtr> aTargetList = aRefListOfMirrored->list();
210 for(std::list<ObjectPtr>::const_iterator aTargetIt = aTargetList.cbegin(); aTargetIt != aTargetList.cend(); aTargetIt++) {
211 if((*aTargetIt).get()) {
212 ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(*aTargetIt);
214 FeaturePtr aFeature = aRes->document()->feature(aRes);
216 AttributeBooleanPtr aBooleanAttr = aFeature->boolean(SketchPlugin_SketchEntity::COPY_ID());
217 if(aBooleanAttr.get()) {
218 if (ModelAPI_Session::get()->isOperation()) // if this is not undo or redo
219 aBooleanAttr->setValue(false);
220 // Redisplay object as it is not copy anymore.
221 ModelAPI_EventCreator::get()->sendUpdated(aRes, aRedispEvent);
229 SketchPlugin_ConstraintBase::erase();
232 void SketchPlugin_ConstraintMirror::attributeChanged(const std::string& theID)
234 if (theID == MIRROR_LIST_ID()) {
235 AttributeRefListPtr aMirrorObjectRefs = reflist(MIRROR_LIST_ID());
236 if (aMirrorObjectRefs->size() == 0) {
237 // Clear list of objects
238 AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
239 data()->attribute(SketchPlugin_Constraint::ENTITY_C()));
240 std::list<ObjectPtr> aTargetList = aRefListOfMirrored->list();
241 std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
242 for (; aTargetIter != aTargetList.end(); aTargetIter++) {
243 aRefListOfMirrored->remove(*aTargetIter);
244 // remove the corresponding feature from the sketch
245 ResultConstructionPtr aRC =
246 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
247 DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
248 FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr();
250 aDoc->removeFeature(aFeature);
252 aRefListOfMirrored->clear();
253 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
254 data()->attribute(SketchPlugin_Constraint::ENTITY_B()))->clear();