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 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
20 DataPtr aData = myBaseConstraint->data();
22 // Lists of objects and number of copies
23 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
24 aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
25 myNumberOfObjects = anInitialRefList->size();
26 myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
27 if (myNumberOfCopies <= 0)
30 AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
31 aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
32 if (!aRefList || aRefList->size() == 0) {
33 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
38 std::list<ObjectPtr> anObjectList = aRefList->list();
39 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
40 // execute for the feature is not called yet
41 if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size())
42 myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
44 while (anObjIt != anObjectList.end()) {
45 aFeature = ModelAPI_Feature::feature(*anObjIt++);
49 // the entity is not created, so it is a copy in "multi" constraint, force its creation
50 if (!myStorage->update(aFeature))
51 myStorage->update(aFeature, myGroupID, true);
52 theEntities.push_back(myStorage->entity(aFeature));
53 myFeatures.insert(aFeature);
54 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
55 // just add copied features into the list of objects
56 aFeature = ModelAPI_Feature::feature(*anObjIt);
58 myFeatures.insert(aFeature);
63 bool SketchSolver_ConstraintMulti::remove()
66 return SketchSolver_Constraint::remove();
69 void SketchSolver_ConstraintMulti::update()
74 void SketchSolver_ConstraintMulti::update(bool isForce)
77 AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
78 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
79 AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
80 if (!anInitialRefList || !aNbObjects)
81 return; // the "Multi" constraint is in queue to remove
83 anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
85 // additional check that the features and their copies are changed
86 AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
87 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
88 if (aRefList && aRefList->size() != 0) {
90 std::list<ObjectPtr> anObjectList = aRefList->list();
91 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
92 for (; anObjIt != anObjectList.end(); ++anObjIt) {
93 aFeature = ModelAPI_Feature::feature(*anObjIt);
94 if (aFeature && myFeatures.find(aFeature) == myFeatures.end()) {
108 // update derivative object
115 void SketchSolver_ConstraintMulti::adjustConstraint()
117 AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
118 myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
119 if (!aRefList || aRefList->size() == 0) {
120 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
124 FeaturePtr anOriginal, aFeature;
125 std::list<ObjectPtr> anObjectList = aRefList->list();
126 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
127 while (anObjIt != anObjectList.end()) {
128 anOriginal = ModelAPI_Feature::feature(*anObjIt++);
132 // Fill lists of coordinates of points composing a feature
133 std::list<double> aX, aY;
134 std::list<double>::iterator aXIt, aYIt;
135 double aXCoord, aYCoord;
136 EntityWrapperPtr anEntity = myStorage->entity(anOriginal);
137 std::list<EntityWrapperPtr> aSubs = anEntity->subEntities();
138 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
139 for (; aSIt != aSubs.end(); ++aSIt) {
140 if ((*aSIt)->type() != ENTITY_POINT)
142 AttributePoint2DPtr aPoint =
143 std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSIt)->baseAttribute());
145 aXCoord = aPoint->x();
146 aYCoord = aPoint->y();
148 std::list<ParameterWrapperPtr> aParameters = (*aSIt)->parameters();
149 aXCoord = aParameters.front()->value();
150 aYCoord = aParameters.back()->value();
152 getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
153 aX.push_back(aXCoord);
154 aY.push_back(aYCoord);
157 // Calculate positions of copied features
158 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
159 aFeature = ModelAPI_Feature::feature(*anObjIt);
162 anEntity = myStorage->entity(aFeature);
164 if (!anEntity || !myStorage->isEventsBlocked())
165 aFeature->data()->blockSendAttributeUpdated(true);
167 std::list<AttributePtr> aPoints;
168 if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
169 aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
170 aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::START_ID()));
171 aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::END_ID()));
172 } else if (aFeature->getKind() == SketchPlugin_Line::ID()) {
173 aPoints.push_back(aFeature->attribute(SketchPlugin_Line::START_ID()));
174 aPoints.push_back(aFeature->attribute(SketchPlugin_Line::END_ID()));
175 } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
176 aPoints.push_back(aFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
177 // update circle's radius
178 aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
179 anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
180 } else if (aFeature->getKind() == SketchPlugin_Point::ID() ||
181 aFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
182 aPoints.push_back(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
184 std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
185 for (aXIt = aX.begin(), aYIt = aY.begin(); aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
186 transformRelative(*aXIt, *aYIt);
187 getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
189 std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
190 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
191 aPoint2D->setValue(aXCoord, aYCoord);
194 // update feature in the storage if it is used by another constraints
196 myStorage->update(aFeature);
197 else { // update attributes, if they exist in the storage
198 for (aPtIt = aPoints.begin(); aPtIt != aPoints.end(); ++aPtIt) {
199 EntityWrapperPtr aPntEnt = myStorage->entity(*aPtIt);
201 myStorage->update(*aPtIt);
205 if (!anEntity || !myStorage->isEventsBlocked())
206 aFeature->data()->blockSendAttributeUpdated(false);
213 bool SketchSolver_ConstraintMulti::isUsed(FeaturePtr theFeature) const
215 return theFeature && (myFeatures.find(theFeature) != myFeatures.end() ||
216 SketchSolver_Constraint::isUsed(theFeature));
219 bool SketchSolver_ConstraintMulti::isUsed(AttributePtr theAttribute) const
221 AttributePtr anAttribute = theAttribute;
222 AttributeRefAttrPtr aRefAttr =
223 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
225 if (aRefAttr->isObject())
226 return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
228 anAttribute = aRefAttr->attr();
233 FeaturePtr anOwner = ModelAPI_Feature::feature(anAttribute->owner());
234 return myFeatures.find(anOwner) != myFeatures.end();