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_AttributeSelectionList.h>
14 #include <ModelAPI_Events.h>
15 #include <ModelAPI_Session.h>
16 #include <ModelAPI_Validator.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 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());
42 void SketchPlugin_ConstraintMirror::execute()
44 AttributeSelectionListPtr aMirrorObjectRefs =
45 selectionList(SketchPlugin_ConstraintMirror::MIRROR_LIST_ID());
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);
51 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
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()) {
71 if (anIt == anInitialList.end())
72 aRefListOfShapes->append(aSelect->context());
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++) {
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();
89 aDoc->removeFeature(aFeature);
92 if (anInitIter != anInitialList.end())
94 if (aMirrorIter != aMirroredList.end())
98 static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
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;
112 aRCIn = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
114 aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(
115 aRCIn->document()->feature(aRCIn));
117 if (aMirrorIter == aMirroredList.end())
118 aFeatureOut = std::shared_ptr<SketchPlugin_Feature>();
120 aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirrorIter);
122 ResultConstructionPtr aRC =
123 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
125 aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(
126 aRC->document()->feature(aRC));
131 break; // the lists are inconsistent
135 if (aMirrorIter != aMirroredList.end())
136 break; // the lists are inconsistent
137 // There is no mirrored object yet, create it
138 FeaturePtr aNewFeature = sketch()->addFeature(aFeatureIn->getKind());
139 aFeatureIn->data()->copyTo(aNewFeature->data());
140 aNewFeature->execute();
141 ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
143 std::shared_ptr<GeomAPI_Shape> aShapeIn = aRCIn->shape();
144 const std::list<ResultPtr>& aResults = aNewFeature->results();
145 std::list<ResultPtr>::const_iterator anIt = aResults.begin();
146 for (; anIt != aResults.end(); anIt++) {
147 ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
149 std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
150 if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
151 (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
152 (aShapeIn->isFace() && aShapeOut->isFace()))
153 aRefListOfMirrored->append(aRC);
157 if (aFeatureIn->getKind() != aFeatureOut->getKind())
158 break; // the lists are inconsistent
159 if (!aFeatureIn->data()->isValid()) {
160 // initial feature was removed, delete it from lists
161 anInvalidInd.insert(indFirstWrong);
165 // Remove from the list objects already deleted before
166 std::set<int>::reverse_iterator anIt = anInvalidInd.rbegin();
167 for ( ; anIt != anInvalidInd.rend(); anIt++) {
168 if (*anIt < indFirstWrong) indFirstWrong--;
169 aRefListOfShapes->remove(aRefListOfShapes->object(*anIt));
170 aRefListOfMirrored->remove(aRefListOfMirrored->object(*anIt));
172 // If the lists inconsistent, remove all objects from mirrored list starting from indFirstWrong
173 if (anInitIter != anInitialList.end()) {
174 while (aRefListOfMirrored->size() > indFirstWrong)
175 aRefListOfMirrored->remove(aRefListOfMirrored->object(indFirstWrong));
176 // Create mirrored features instead of removed
177 anInitialList = aRefListOfShapes->list();
178 anInitIter = anInitialList.begin();
179 for (int i = 0; i < indFirstWrong; i++) anInitIter++;
180 for ( ; anInitIter != anInitialList.end(); anInitIter++) {
181 aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
182 FeaturePtr aNewFeature = aFeatureIn->document()->addFeature(aFeatureIn->getKind());
183 aRefListOfMirrored->append(aNewFeature);
187 // send events to update the sub-features by the solver
189 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
192 AISObjectPtr SketchPlugin_ConstraintMirror::getAISObject(AISObjectPtr thePrevious)
197 AISObjectPtr anAIS = thePrevious;
199 anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane());