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 myOriginalFeatures.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 myCopiedFeatures.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 = myCopiedFeatures.begin();
82 for (; anIt != myCopiedFeatures.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);
93 myOriginalFeatures.clear();
94 myCopiedFeatures.clear();
95 return SketchSolver_Constraint::remove();
98 void SketchSolver_ConstraintMulti::update()
101 AttributeRefListPtr anInitialRefList =
102 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
103 AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
104 if (!anInitialRefList || !aNbObjects)
105 return; // the "Multi" constraint is in queue to remove
107 anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
109 // additional check that the features and their copies are changed
110 AttributeRefListPtr aRefList =
111 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
112 if (aRefList && aRefList->size() != 0) {
114 std::list<ObjectPtr> anObjectList = aRefList->list();
115 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
116 for (; anObjIt != anObjectList.end(); ++anObjIt) {
117 aFeature = ModelAPI_Feature::feature(*anObjIt);
118 if (aFeature && myOriginalFeatures.find(aFeature) == myOriginalFeatures.end() &&
119 myCopiedFeatures.find(aFeature) == myCopiedFeatures.end()) {
132 // update derived object
137 void SketchSolver_ConstraintMulti::adjustConstraint()
139 AttributeRefListPtr aRefList =
140 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
141 if (!aRefList || aRefList->size() == 0) {
142 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
146 FeaturePtr anOriginal, aFeature;
147 std::list<double>::iterator aXIt, aYIt;
149 std::list<ObjectPtr> anObjectList = aRefList->list();
150 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
151 while (anObjIt != anObjectList.end()) {
152 anOriginal = ModelAPI_Feature::feature(*anObjIt++);
156 // Fill lists of coordinates of points composing a feature
157 std::list<double> aX, aY;
158 double aXCoord, aYCoord;
159 std::list<AttributePtr> aPoints =
160 anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
161 std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
162 for (; aPtIt != aPoints.end(); ++aPtIt) {
163 AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
164 if (aPoint2D->isInitialized()) {
165 aXCoord = aPoint2D->x();
166 aYCoord = aPoint2D->y();
167 getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
169 aXCoord = aYCoord = 0;
171 aX.push_back(aXCoord);
172 aY.push_back(aYCoord);
175 // Calculate positions of copied features
176 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
177 aFeature = ModelAPI_Feature::feature(*anObjIt);
181 if (myIsEventsBlocked)
182 aFeature->data()->blockSendAttributeUpdated(true);
184 if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
185 aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
186 anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
188 aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
189 for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
190 aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
191 if (!(*aPtIt)->isInitialized())
193 transformRelative(*aXIt, *aYIt);
194 getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
196 AttributePoint2DPtr aPoint2D =
197 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
198 aPoint2D->setValue(aXCoord, aYCoord);
201 // update transformed entity if it exists in the storage
202 if (myStorage->entity(aFeature))
203 myStorage->update(aFeature);
210 void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
211 PlaneGCSSolver_Update*)
213 if (myOriginalFeatures.find(theFeature) == myOriginalFeatures.end() &&
214 myCopiedFeatures.find(theFeature) == myCopiedFeatures.end())
215 return; // the feature is not used by constraint => nothing to update
217 // update derivative object
223 void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
225 myIsEventsBlocked = isBlocked;
227 std::set<FeaturePtr>::iterator anIt = myOriginalFeatures.begin();
228 for (; anIt != myOriginalFeatures.end(); ++anIt)
229 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
230 for (anIt = myCopiedFeatures.begin(); anIt != myCopiedFeatures.end(); ++anIt)
231 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
233 SketchSolver_Constraint::blockEvents(isBlocked);