1 // Copyright (C) 2014-2019 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 email : webmaster.salome@opencascade.com
20 #include <SketchSolver_ConstraintMulti.h>
21 #include <SketchSolver_Error.h>
22 #include <SketchSolver_Manager.h>
24 #include <GeomDataAPI_Point2D.h>
25 #include <ModelAPI_AttributeInteger.h>
26 #include <ModelAPI_AttributeRefAttr.h>
27 #include <ModelAPI_AttributeRefList.h>
28 #include <SketchPlugin_Arc.h>
29 #include <SketchPlugin_Circle.h>
30 #include <SketchPlugin_Line.h>
31 #include <SketchPlugin_Point.h>
32 #include <SketchPlugin_IntersectionPoint.h>
34 static void createCopiedEntity(const FeaturePtr& theFeature, const StoragePtr& theStorage)
36 EntityWrapperPtr anEntity = theStorage->entity(theFeature);
38 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
39 std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
40 if (!anEntity->isExternal() && aSketchFeature->isCopy())
41 theStorage->makeExternal(anEntity);
45 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
49 // Lists of objects and number of copies
50 AttributeRefListPtr anInitialRefList =
51 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
52 myNumberOfObjects = anInitialRefList->size();
53 myNumberOfCopies = myBaseConstraint->integer(nameNbObjects())->value() - 1;
54 if (myNumberOfCopies <= 0)
57 AttributeRefListPtr aRefList =
58 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
59 if (!aRefList || aRefList->size() == 0) {
60 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
65 std::list<ObjectPtr> anObjectList = aRefList->list();
66 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
67 // execute for the feature is not called yet
68 if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size())
69 myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
71 while (anObjIt != anObjectList.end()) {
72 aFeature = ModelAPI_Feature::feature(*anObjIt++);
76 // the entity is not created, so it is a copy in "multi" constraint, force its creation
77 if (!myStorage->update(aFeature))
78 myStorage->update(aFeature, true);
79 theEntities.push_back(myStorage->entity(aFeature));
80 myOriginalFeatures.insert(aFeature);
81 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
82 // just add copied features into the list of objects
83 aFeature = ModelAPI_Feature::feature(*anObjIt);
85 createCopiedEntity(aFeature, myStorage);
86 myCopiedFeatures.insert(aFeature);
92 bool SketchSolver_ConstraintMulti::remove()
94 myStorage->unsubscribeUpdates(this);
96 // "Multi" constraint has been removed, thus all copy features become non-copied,
97 // add them once again to be a common feature
98 std::set<FeaturePtr>::iterator anIt = myCopiedFeatures.begin();
99 for (; anIt != myCopiedFeatures.end(); ++anIt) {
100 EntityWrapperPtr anEntity = myStorage->entity(*anIt);
102 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
103 std::dynamic_pointer_cast<SketchPlugin_Feature>(*anIt);
104 if (anEntity->isExternal() && !aSketchFeature->isExternal())
105 myStorage->makeNonExternal(anEntity);
106 } else if ((*anIt)->data() && (*anIt)->data()->isValid())
107 myStorage->update(*anIt, true);
110 myOriginalFeatures.clear();
111 myCopiedFeatures.clear();
112 return SketchSolver_Constraint::remove();
115 void SketchSolver_ConstraintMulti::update()
118 AttributeRefListPtr anInitialRefList =
119 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
120 AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
121 if (!anInitialRefList || !aNbObjects)
122 return; // the "Multi" constraint is in queue to remove
124 anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
126 // additional check that the features and their copies are changed
127 AttributeRefListPtr aRefList =
128 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
129 if (aRefList && aRefList->size() != 0) {
131 std::list<ObjectPtr> anObjectList = aRefList->list();
132 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
133 for (; anObjIt != anObjectList.end(); ++anObjIt) {
134 aFeature = ModelAPI_Feature::feature(*anObjIt);
135 if (aFeature && myOriginalFeatures.find(aFeature) == myOriginalFeatures.end() &&
136 myCopiedFeatures.find(aFeature) == myCopiedFeatures.end()) {
149 // update derived object
154 void SketchSolver_ConstraintMulti::adjustConstraint()
156 AttributeRefListPtr aRefList =
157 myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
158 if (!aRefList || aRefList->size() == 0) {
159 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
163 FeaturePtr anOriginal, aFeature;
164 std::list<double>::iterator aXIt, aYIt;
166 std::list<ObjectPtr> anObjectList = aRefList->list();
167 std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
168 while (anObjIt != anObjectList.end()) {
169 anOriginal = ModelAPI_Feature::feature(*anObjIt++);
173 // Fill lists of coordinates of points composing a feature
174 std::list<double> aX, aY;
175 double aXCoord, aYCoord;
176 std::list<AttributePtr> aPoints =
177 anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
178 std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
179 for (; aPtIt != aPoints.end(); ++aPtIt) {
180 AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
181 if (aPoint2D->isInitialized()) {
182 aXCoord = aPoint2D->x();
183 aYCoord = aPoint2D->y();
184 getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
186 aXCoord = aYCoord = 0;
188 aX.push_back(aXCoord);
189 aY.push_back(aYCoord);
192 // Calculate positions of copied features
193 for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
194 aFeature = ModelAPI_Feature::feature(*anObjIt);
198 if (myIsEventsBlocked)
199 aFeature->data()->blockSendAttributeUpdated(true);
201 if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
202 aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
203 anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
205 aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
206 for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
207 aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
208 if (!(*aPtIt)->isInitialized())
210 transformRelative(*aXIt, *aYIt);
211 getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
213 AttributePoint2DPtr aPoint2D =
214 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
215 aPoint2D->setValue(aXCoord, aYCoord);
218 // update transformed entity if it exists in the storage
219 if (myStorage->entity(aFeature))
220 myStorage->update(aFeature);
227 void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
228 PlaneGCSSolver_Update*)
230 if (myOriginalFeatures.find(theFeature) == myOriginalFeatures.end() &&
231 myCopiedFeatures.find(theFeature) == myCopiedFeatures.end())
232 return; // the feature is not used by constraint => nothing to update
234 if (myIsProcessingNotify)
235 return; // "notify" is already processing
237 // do not adjust "multi"-constraint if the number of objects is changed,
238 // wait until the constraint is updated (issue #2425: changing number of copies by parameter)
239 if (myNumberOfCopies + 1 == myBaseConstraint->integer(nameNbObjects())->value()) {
240 myIsProcessingNotify = true;
242 // update derivative object
247 myIsProcessingNotify = false;
251 void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
253 myIsEventsBlocked = isBlocked;
255 std::set<FeaturePtr>::iterator anIt = myOriginalFeatures.begin();
256 for (; anIt != myOriginalFeatures.end(); ++anIt)
257 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
258 for (anIt = myCopiedFeatures.begin(); anIt != myCopiedFeatures.end(); ++anIt)
259 (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
261 SketchSolver_Constraint::blockEvents(isBlocked);