1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 #include <SketchSolver_ConstraintMulti.h>
4 #include <SketchSolver_Error.h>
5 #include <SketchSolver_Manager.h>
7 #include <GeomDataAPI_Point2D.h>
8 #include <ModelAPI_AttributeInteger.h>
9 #include <ModelAPI_AttributeRefAttr.h>
10 #include <ModelAPI_AttributeRefList.h>
11 #include <SketchPlugin_Arc.h>
12 #include <SketchPlugin_Circle.h>
13 #include <SketchPlugin_Line.h>
14 #include <SketchPlugin_Point.h>
15 #include <SketchPlugin_IntersectionPoint.h>
17 static void createCopiedEntity(const FeaturePtr& theFeature, const StoragePtr& theStorage)
19 EntityWrapperPtr anEntity = theStorage->entity(theFeature);
21 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
22 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
23 if (!anEntity->isExternal() && aSketchFeature->isCopy())
24 theStorage->makeExternal(anEntity);
28 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
32 // Lists of objects and number of copies
33 AttributeRefListPtr anInitialRefList =
34 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
35 myNumberOfObjects = anInitialRefList->size();
36 myNumberOfCopies = myBaseConstraint->integer(nameNbObjects())->value() - 1;
37 if (myNumberOfCopies <= 0)
40 AttributeRefListPtr aRefList =
41 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
42 if (!aRefList || aRefList->size() == 0) {
43 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
48 std::list<ObjectPtr> anObjectList = aRefList->list();
49 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
50 // execute for the feature is not called yet
51 if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size())
52 myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
54 while (anObjIt != anObjectList.end()) {
55 aFeature = ModelAPI_Feature::feature(*anObjIt++);
59 // the entity is not created, so it is a copy in "multi" constraint, force its creation
60 if (!myStorage->update(aFeature))
61 myStorage->update(aFeature, true);
62 theEntities.push_back(myStorage->entity(aFeature));
63 myFeatures.insert(aFeature);
64 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
65 // just add copied features into the list of objects
66 aFeature = ModelAPI_Feature::feature(*anObjIt);
68 createCopiedEntity(aFeature, myStorage);
69 myFeatures.insert(aFeature);
75 bool SketchSolver_ConstraintMulti::remove()
77 myStorage->unsubscribeUpdates(this);
79 // "Multi" constraint has been removed, thus all copy features become non-copied,
80 // add them once again to be a common feature
81 std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
82 for (; anIt != myFeatures.end(); ++anIt) {
83 EntityWrapperPtr anEntity = myStorage->entity(*anIt);
85 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
86 std::dynamic_pointer_cast<SketchPlugin_Feature>(*anIt);
87 if (anEntity->isExternal() && !aSketchFeature->isExternal())
88 myStorage->makeNonExternal(anEntity);
89 } else if ((*anIt)->data() && (*anIt)->data()->isValid())
90 myStorage->update(*anIt, true);
94 return SketchSolver_Constraint::remove();
97 void SketchSolver_ConstraintMulti::update()
100 AttributeRefListPtr anInitialRefList =
101 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
102 AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
103 if (!anInitialRefList || !aNbObjects)
104 return; // the "Multi" constraint is in queue to remove
106 anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
108 // additional check that the features and their copies are changed
109 AttributeRefListPtr aRefList =
110 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
111 if (aRefList && aRefList->size() != 0) {
113 std::list<ObjectPtr> anObjectList = aRefList->list();
114 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
115 for (; anObjIt != anObjectList.end(); ++anObjIt) {
116 aFeature = ModelAPI_Feature::feature(*anObjIt);
117 if (aFeature && myFeatures.find(aFeature) == myFeatures.end()) {
130 // update derived object
135 void SketchSolver_ConstraintMulti::adjustConstraint()
137 AttributeRefListPtr aRefList =
138 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
139 if (!aRefList || aRefList->size() == 0) {
140 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
144 FeaturePtr anOriginal, aFeature;
145 std::list<double>::iterator aXIt, aYIt;
147 std::list<ObjectPtr> anObjectList = aRefList->list();
148 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
149 while (anObjIt != anObjectList.end()) {
150 anOriginal = ModelAPI_Feature::feature(*anObjIt++);
154 // Fill lists of coordinates of points composing a feature
155 std::list<double> aX, aY;
156 double aXCoord, aYCoord;
157 std::list<AttributePtr> aPoints =
158 anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
159 std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
160 for (; aPtIt != aPoints.end(); ++aPtIt) {
161 AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
162 if (aPoint2D->isInitialized()) {
163 aXCoord = aPoint2D->x();
164 aYCoord = aPoint2D->y();
165 getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
167 aXCoord = aYCoord = 0;
169 aX.push_back(aXCoord);
170 aY.push_back(aYCoord);
173 // Calculate positions of copied features
174 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
175 aFeature = ModelAPI_Feature::feature(*anObjIt);
179 if (myIsEventsBlocked)
180 aFeature->data()->blockSendAttributeUpdated(true);
182 if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
183 aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
184 anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
186 aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
187 for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
188 aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
189 if (!(*aPtIt)->isInitialized())
191 transformRelative(*aXIt, *aYIt);
192 getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
194 AttributePoint2DPtr aPoint2D =
195 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
196 aPoint2D->setValue(aXCoord, aYCoord);
199 // update transformed entity if it exists in the storage
200 if (myStorage->entity(aFeature))
201 myStorage->update(aFeature);
208 void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
209 PlaneGCSSolver_Update*)
211 if (myFeatures.find(theFeature) == myFeatures.end())
212 return; // the feature is not used by constraint => nothing to update
214 // update derivative object
220 void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
222 myIsEventsBlocked = isBlocked;
224 std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
225 for (; anIt != myFeatures.end(); ++anIt)
226 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
228 SketchSolver_Constraint::blockEvents(isBlocked);