1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <SketchSolver_ConstraintMulti.h>
22 #include <SketchSolver_Error.h>
23 #include <SketchSolver_Manager.h>
25 #include <GeomDataAPI_Point2D.h>
26 #include <ModelAPI_AttributeInteger.h>
27 #include <ModelAPI_AttributeRefAttr.h>
28 #include <ModelAPI_AttributeRefList.h>
29 #include <SketchPlugin_Arc.h>
30 #include <SketchPlugin_Circle.h>
31 #include <SketchPlugin_Line.h>
32 #include <SketchPlugin_Point.h>
33 #include <SketchPlugin_IntersectionPoint.h>
35 static void createCopiedEntity(const FeaturePtr& theFeature, const StoragePtr& theStorage)
37 EntityWrapperPtr anEntity = theStorage->entity(theFeature);
39 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
40 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
41 if (!anEntity->isExternal() && aSketchFeature->isCopy())
42 theStorage->makeExternal(anEntity);
46 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
50 // Lists of objects and number of copies
51 AttributeRefListPtr anInitialRefList =
52 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
53 myNumberOfObjects = anInitialRefList->size();
54 myNumberOfCopies = myBaseConstraint->integer(nameNbObjects())->value() - 1;
55 if (myNumberOfCopies <= 0)
58 AttributeRefListPtr aRefList =
59 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
60 if (!aRefList || aRefList->size() == 0) {
61 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
66 std::list<ObjectPtr> anObjectList = aRefList->list();
67 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
68 // execute for the feature is not called yet
69 if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size())
70 myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
72 while (anObjIt != anObjectList.end()) {
73 aFeature = ModelAPI_Feature::feature(*anObjIt++);
77 // the entity is not created, so it is a copy in "multi" constraint, force its creation
78 if (!myStorage->update(aFeature))
79 myStorage->update(aFeature, true);
80 theEntities.push_back(myStorage->entity(aFeature));
81 myOriginalFeatures.insert(aFeature);
82 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
83 // just add copied features into the list of objects
84 aFeature = ModelAPI_Feature::feature(*anObjIt);
86 createCopiedEntity(aFeature, myStorage);
87 myCopiedFeatures.insert(aFeature);
93 bool SketchSolver_ConstraintMulti::remove()
95 myStorage->unsubscribeUpdates(this);
97 // "Multi" constraint has been removed, thus all copy features become non-copied,
98 // add them once again to be a common feature
99 std::set<FeaturePtr>::iterator anIt = myCopiedFeatures.begin();
100 for (; anIt != myCopiedFeatures.end(); ++anIt) {
101 EntityWrapperPtr anEntity = myStorage->entity(*anIt);
103 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
104 std::dynamic_pointer_cast<SketchPlugin_Feature>(*anIt);
105 if (anEntity->isExternal() && !aSketchFeature->isExternal())
106 myStorage->makeNonExternal(anEntity);
107 } else if ((*anIt)->data() && (*anIt)->data()->isValid())
108 myStorage->update(*anIt, true);
111 myOriginalFeatures.clear();
112 myCopiedFeatures.clear();
113 return SketchSolver_Constraint::remove();
116 void SketchSolver_ConstraintMulti::update()
119 AttributeRefListPtr anInitialRefList =
120 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
121 AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
122 if (!anInitialRefList || !aNbObjects)
123 return; // the "Multi" constraint is in queue to remove
125 anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
127 // additional check that the features and their copies are changed
128 AttributeRefListPtr aRefList =
129 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
130 if (aRefList && aRefList->size() != 0) {
132 std::list<ObjectPtr> anObjectList = aRefList->list();
133 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
134 for (; anObjIt != anObjectList.end(); ++anObjIt) {
135 aFeature = ModelAPI_Feature::feature(*anObjIt);
136 if (aFeature && myOriginalFeatures.find(aFeature) == myOriginalFeatures.end() &&
137 myCopiedFeatures.find(aFeature) == myCopiedFeatures.end()) {
150 // update derived object
155 void SketchSolver_ConstraintMulti::adjustConstraint()
157 AttributeRefListPtr aRefList =
158 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
159 if (!aRefList || aRefList->size() == 0) {
160 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
164 FeaturePtr anOriginal, aFeature;
165 std::list<double>::iterator aXIt, aYIt;
167 std::list<ObjectPtr> anObjectList = aRefList->list();
168 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
169 while (anObjIt != anObjectList.end()) {
170 anOriginal = ModelAPI_Feature::feature(*anObjIt++);
174 // Fill lists of coordinates of points composing a feature
175 std::list<double> aX, aY;
176 double aXCoord, aYCoord;
177 std::list<AttributePtr> aPoints =
178 anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
179 std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
180 for (; aPtIt != aPoints.end(); ++aPtIt) {
181 AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
182 if (aPoint2D->isInitialized()) {
183 aXCoord = aPoint2D->x();
184 aYCoord = aPoint2D->y();
185 getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
187 aXCoord = aYCoord = 0;
189 aX.push_back(aXCoord);
190 aY.push_back(aYCoord);
193 // Calculate positions of copied features
194 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
195 aFeature = ModelAPI_Feature::feature(*anObjIt);
199 if (myIsEventsBlocked)
200 aFeature->data()->blockSendAttributeUpdated(true);
202 if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
203 aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
204 anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
206 aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
207 for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
208 aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
209 if (!(*aPtIt)->isInitialized())
211 transformRelative(*aXIt, *aYIt);
212 getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
214 AttributePoint2DPtr aPoint2D =
215 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
216 aPoint2D->setValue(aXCoord, aYCoord);
219 // update transformed entity if it exists in the storage
220 if (myStorage->entity(aFeature))
221 myStorage->update(aFeature);
228 void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
229 PlaneGCSSolver_Update*)
231 if (myOriginalFeatures.find(theFeature) == myOriginalFeatures.end() &&
232 myCopiedFeatures.find(theFeature) == myCopiedFeatures.end())
233 return; // the feature is not used by constraint => nothing to update
235 if (myIsProcessingNotify)
236 return; // "notify" is already processing
238 // do not adjust "multi"-constraint if the number of objects is changed,
239 // wait until the constraint is updated (issue #2425: changing number of copies by parameter)
240 if (myNumberOfCopies + 1 == myBaseConstraint->integer(nameNbObjects())->value()) {
241 myIsProcessingNotify = true;
243 // update derivative object
248 myIsProcessingNotify = false;
252 void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
254 myIsEventsBlocked = isBlocked;
256 std::set<FeaturePtr>::iterator anIt = myOriginalFeatures.begin();
257 for (; anIt != myOriginalFeatures.end(); ++anIt)
258 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
259 for (anIt = myCopiedFeatures.begin(); anIt != myCopiedFeatures.end(); ++anIt)
260 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
262 SketchSolver_Constraint::blockEvents(isBlocked);