1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: SketchSolver_Group.cpp
4 // Created: 27 May 2014
5 // Author: Artem ZHIDKOV
7 #include "SketchSolver_Group.h"
9 #include <SketchSolver_Builder.h>
10 #include <SketchSolver_Constraint.h>
11 #include <SketchSolver_ConstraintCoincidence.h>
12 #include <SketchSolver_Error.h>
14 #include <Events_Error.h>
15 #include <Events_Loop.h>
16 #include <GeomAPI_XY.h>
17 #include <GeomAPI_Dir2d.h>
18 #include <GeomAPI_Pnt2d.h>
19 #include <GeomDataAPI_Dir.h>
20 #include <GeomDataAPI_Point.h>
21 #include <GeomDataAPI_Point2D.h>
22 #include <ModelAPI_AttributeDouble.h>
23 #include <ModelAPI_AttributeRefList.h>
24 #include <ModelAPI_Document.h>
25 #include <ModelAPI_Events.h>
26 #include <ModelAPI_ResultConstruction.h>
28 #include <SketchPlugin_Constraint.h>
29 #include <SketchPlugin_ConstraintFillet.h>
30 #include <SketchPlugin_ConstraintLength.h>
31 #include <SketchPlugin_ConstraintCoincidence.h>
32 #include <SketchPlugin_ConstraintMirror.h>
33 #include <SketchPlugin_ConstraintRigid.h>
35 #include <SketchPlugin_Arc.h>
36 #include <SketchPlugin_Circle.h>
37 #include <SketchPlugin_Line.h>
38 #include <SketchPlugin_Point.h>
39 #include <SketchPlugin_Sketch.h>
45 /// \brief This class is used to give unique index to the groups
49 /// \brief Return vacant index
50 static Slvs_hGroup NEW_GROUP() { return ++myGroupIndex; }
51 /// \brief Removes the index
52 static void REMOVE_GROUP(const Slvs_hGroup& theIndex) {
53 if (myGroupIndex == theIndex)
60 static Slvs_hGroup myGroupIndex; ///< index of the group
63 Slvs_hGroup GroupIndexer::myGroupIndex = 0;
66 /** \brief Search the entity/parameter with specified ID in the list of elements
67 * \param[in] theEntityID unique ID of the element
68 * \param[in] theEntities list of elements
69 * \return position of the found element or -1 if the element is not found
72 static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
74 // ========================================================
75 // ========= SketchSolver_Group ===============
76 // ========================================================
78 SketchSolver_Group::SketchSolver_Group(
79 std::shared_ptr<ModelAPI_CompositeFeature> theWorkplane)
80 : myID(GroupIndexer::NEW_GROUP())
82 // Initialize workplane
83 myWorkplaneID = SLVS_E_UNKNOWN;
85 assert(addWorkplane(theWorkplane));
87 addWorkplane(theWorkplane);
91 SketchSolver_Group::~SketchSolver_Group()
93 myConstraints.clear();
94 GroupIndexer::REMOVE_GROUP(myID);
97 // ============================================================================
98 // Function: isBaseWorkplane
99 // Class: SketchSolver_Group
100 // Purpose: verify the group is based on the given workplane
101 // ============================================================================
102 bool SketchSolver_Group::isBaseWorkplane(CompositeFeaturePtr theWorkplane) const
104 return theWorkplane == mySketch;
107 // ============================================================================
108 // Function: isInteract
109 // Class: SketchSolver_Group
110 // Purpose: verify are there any entities in the group used by given constraint
111 // ============================================================================
112 bool SketchSolver_Group::isInteract(
113 std::shared_ptr<SketchPlugin_Feature> theFeature) const
115 // Empty group interacts with everything
116 if (isEmpty()) return true;
117 ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
119 return myFeatureStorage->isInteract(aConstraint);
120 return myFeatureStorage->isInteract(theFeature);
123 // ============================================================================
124 // Function: getFeatureId
125 // Class: SketchSolver_Group
126 // Purpose: Find the identifier of the feature, if it already exists in the group
127 // ============================================================================
128 Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const
130 if (!myFeatureStorage)
131 return SLVS_E_UNKNOWN;
132 std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theFeature);
133 if (aConstraints.empty())
134 return SLVS_E_UNKNOWN;
135 ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstraints.begin());
136 if (aCIter == myConstraints.end())
137 return SLVS_E_UNKNOWN;
138 return aCIter->second->getId(theFeature);
141 // ============================================================================
142 // Function: getAttributeId
143 // Class: SketchSolver_Group
144 // Purpose: Find the identifier of the attribute, if it already exists in the group
145 // ============================================================================
146 Slvs_hEntity SketchSolver_Group::getAttributeId(AttributePtr theAttribute) const
148 if (!myFeatureStorage)
149 return SLVS_E_UNKNOWN;
150 std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theAttribute);
151 if (aConstraints.empty())
152 return SLVS_E_UNKNOWN;
153 ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstraints.begin());
154 if (aCIter == myConstraints.end())
155 return SLVS_E_UNKNOWN;
156 return aCIter->second->getId(theAttribute);
160 ////// ============================================================================
161 ////// Function: checkConstraintConsistence
162 ////// Class: SketchSolver_Group
163 ////// Purpose: verifies and changes parameters of the constraint
164 ////// ============================================================================
165 ////void SketchSolver_Group::checkConstraintConsistence(Slvs_Constraint& theConstraint)
167 //// if (theConstraint.type == SLVS_C_PT_LINE_DISTANCE) {
168 //// // Get constraint parameters and check the sign of constraint value
170 //// // point coordinates
171 //// int aPtPos = Search(theConstraint.ptA, myEntities);
172 //// int aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
173 //// std::shared_ptr<GeomAPI_XY> aPoint(
174 //// new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val));
176 //// // line coordinates
177 //// int aLnPos = Search(theConstraint.entityA, myEntities);
178 //// aPtPos = Search(myEntities[aLnPos].point[0], myEntities);
179 //// aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
180 //// std::shared_ptr<GeomAPI_XY> aStart(
181 //// new GeomAPI_XY(-myParams[aPtParamPos].val, -myParams[aPtParamPos + 1].val));
182 //// aPtPos = Search(myEntities[aLnPos].point[1], myEntities);
183 //// aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
184 //// std::shared_ptr<GeomAPI_XY> aEnd(
185 //// new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val));
187 //// aEnd = aEnd->added(aStart);
188 //// aPoint = aPoint->added(aStart);
189 //// if (aPoint->cross(aEnd) * theConstraint.valA < 0.0)
190 //// theConstraint.valA *= -1.0;
194 // ============================================================================
195 // Function: changeConstraint
196 // Class: SketchSolver_Group
197 // Purpose: create/update the constraint in the group
198 // ============================================================================
199 bool SketchSolver_Group::changeConstraint(
200 std::shared_ptr<SketchPlugin_Constraint> theConstraint)
202 // There is no workplane yet, something wrong
203 if (myWorkplaneID == SLVS_E_UNKNOWN)
209 if (myConstraints.find(theConstraint) == myConstraints.end()) {
210 // Add constraint to the current group
211 SolverConstraintPtr aConstraint =
212 SketchSolver_Builder::getInstance()->createConstraint(theConstraint);
215 aConstraint->setGroup(this);
216 aConstraint->setStorage(myStorage);
217 if (!aConstraint->error().empty()) {
218 if (aConstraint->error() == SketchSolver_Error::NOT_INITIALIZED())
219 return false; // some attribute are not initialized yet, don't show message
220 Events_Error::send(aConstraint->error(), this);
223 // Additional verification of coincidence of several points
224 if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
225 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
226 for (; aCIter != myConstraints.end(); aCIter++) {
227 std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoincidence =
228 std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aCIter->second);
231 std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoinc2 =
232 std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aConstraint);
233 if (aCoincidence != aCoinc2 && aCoincidence->isCoincide(aCoinc2)) {
234 aCoincidence->attach(aCoinc2);
235 aConstraint = aCoincidence;
239 myConstraints[theConstraint] = aConstraint;
242 myConstraints[theConstraint]->update();
244 if (!myFeatureStorage)
245 myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
246 myFeatureStorage->changeConstraint(theConstraint);
248 //// if (theConstraint) {
249 //// if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID())
250 //// return changeRigidConstraint(theConstraint);
251 //// if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID())
252 //// return changeMirrorConstraint(theConstraint);
253 //// if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID())
254 //// return changeFilletConstraint(theConstraint);
257 //// // Search this constraint in the current group to update it
258 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
259 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
260 //// if (aConstrMapIter != myConstraintMap.end()) {
261 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
262 //// aConstrIter = myConstraints.begin() + aConstrPos;
265 //// // Get constraint type and verify the constraint parameters are correct
266 //// SketchSolver_Constraint aConstraint(theConstraint);
267 //// int aConstrType = aConstraint.getType();
268 //// if (aConstrType == SLVS_C_UNKNOWN
269 //// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
271 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
273 //// // Create constraint parameters
274 //// double aDistance = 0.0; // scalar value of the constraint
275 //// AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
276 //// theConstraint->data()->attribute(SketchPlugin_Constraint::VALUE()));
277 //// if (aDistAttr) {
278 //// aDistance = aDistAttr->value();
279 //// // Issue #196: checking the positivity of the distance constraint
280 //// if (aDistance < tolerance &&
281 //// (aConstrType == SLVS_C_PT_PT_DISTANCE || aConstrType == SLVS_C_PT_LINE_DISTANCE))
283 //// // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter
284 //// if (aConstrType == SLVS_C_DIAMETER)
285 //// aDistance *= 2.0;
286 //// if (aConstrMapIter != myConstraintMap.end()
287 //// && fabs(aConstrIter->valA - aDistance) > tolerance) {
288 //// myNeedToSolve = true;
289 //// aConstrIter->valA = aDistance;
293 //// size_t aNbTmpConstraints = myTempConstraints.size();
294 //// Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE]; // parameters of the constraint
295 //// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
296 //// aConstrEnt[indAttr] = SLVS_E_UNKNOWN;
297 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
298 //// ModelAPI_AttributeRefAttr>(
299 //// theConstraint->data()->attribute(aConstraintAttributes[indAttr]));
300 //// if (!aConstrAttr)
303 //// // Convert the object of the attribute to the feature
304 //// FeaturePtr aFeature;
305 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
306 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
307 //// aConstrAttr->object());
310 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
311 //// aFeature = aDoc->feature(aRC);
314 //// // For the length constraint the start and end points of the line should be added to the entities list instead of line
315 //// if (aConstrType == SLVS_C_PT_PT_DISTANCE
316 //// && theConstraint->getKind().compare(SketchPlugin_ConstraintLength::ID()) == 0) {
317 //// Slvs_hEntity aLineEnt = changeEntityFeature(aFeature);
318 //// int aEntPos = Search(aLineEnt, myEntities);
319 //// aConstrEnt[indAttr++] = myEntities[aEntPos].point[0];
320 //// aConstrEnt[indAttr++] = myEntities[aEntPos].point[1];
321 //// while (indAttr < CONSTRAINT_ATTR_SIZE)
322 //// aConstrEnt[indAttr++] = 0;
323 //// break; // there should be no other entities
324 //// } else if (aConstrAttr->isObject())
325 //// aConstrEnt[indAttr] = changeEntityFeature(aFeature);
327 //// aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr());
330 //// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
331 //// // Several points may be coincident, it is not necessary to store all constraints between them.
332 //// // Try to find sequence of coincident points which connects the points of new constraint
333 //// if (aConstrType == SLVS_C_POINTS_COINCIDENT) {
334 //// if (aConstrEnt[0] == aConstrEnt[1]) // no need to add self coincidence
336 //// if (!addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) {
337 //// myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes
340 //// if (aNbTmpConstraints < myTempConstraints.size()) {
341 //// // There was added temporary constraint. Check that there is no coincident points which already rigid.
343 //// // Get list of already fixed points
344 //// std::set<Slvs_hEntity> anAlreadyFixed;
345 //// std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
346 //// for (; aCIter != myConstraints.end(); aCIter++)
347 //// if (aCIter->type == SLVS_C_WHERE_DRAGGED) {
348 //// std::list<Slvs_hConstraint>::const_iterator aTmpIt = myTempConstraints.begin();
349 //// for (; aTmpIt != myTempConstraints.end(); aTmpIt++)
350 //// if (*aTmpIt == aCIter->h)
352 //// if (aTmpIt == myTempConstraints.end())
353 //// anAlreadyFixed.insert(aCIter->ptA);
356 //// std::set<Slvs_hConstraint> aTmpConstrToDelete;
357 //// std::list<Slvs_hConstraint>::reverse_iterator aTmpIter = myTempConstraints.rbegin();
358 //// size_t aCurSize = myTempConstraints.size();
359 //// for (; aCurSize > aNbTmpConstraints && aTmpIter != myTempConstraints.rend();
360 //// aTmpIter++, aCurSize--) {
361 //// int aConstrPos = Search(*aTmpIter, myConstraints);
362 //// std::vector<std::set<Slvs_hEntity> >::const_iterator
363 //// aCoincIter = myCoincidentPoints.begin();
364 //// for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++)
365 //// if (aCoincIter->find(myConstraints[aConstrPos].ptA) != aCoincIter->end()) {
366 //// std::set<Slvs_hEntity>::const_iterator anIt;
367 //// for (anIt = aCoincIter->begin(); anIt != aCoincIter->end(); anIt++)
368 //// if (anAlreadyFixed.find(*anIt) != anAlreadyFixed.end()) {
369 //// aTmpConstrToDelete.insert(*aTmpIter);
375 //// if (!aTmpConstrToDelete.empty())
376 //// removeTemporaryConstraints(aTmpConstrToDelete);
379 //// // For the tangency constraints it is necessary to identify which points of entities are coincident
380 //// int aSlvsOtherFlag = 0;
381 //// int aSlvsOther2Flag = 0;
382 //// if (aConstrType == SLVS_C_ARC_LINE_TANGENT || aConstrType == SLVS_C_CURVE_CURVE_TANGENT) {
383 //// // Search entities used by constraint
384 //// int anEnt1Pos = Search(aConstrEnt[2], myEntities);
385 //// int anEnt2Pos = Search(aConstrEnt[3], myEntities);
386 //// // Obtain start and end points of entities
387 //// Slvs_hEntity aPointsToFind[4];
388 //// aPointsToFind[0] = myEntities[anEnt1Pos].point[1];
389 //// aPointsToFind[1]= myEntities[anEnt1Pos].point[2];
390 //// bool hasLine = (myEntities[anEnt2Pos].type == SLVS_E_LINE_SEGMENT);
391 //// aPointsToFind[2]= myEntities[anEnt2Pos].point[hasLine ? 0 : 1];
392 //// aPointsToFind[3]= myEntities[anEnt2Pos].point[hasLine ? 1 : 2];
393 //// // Search coincident points
394 //// bool isPointFound[4];
395 //// std::vector<std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
396 //// for ( ; aCPIter != myCoincidentPoints.end(); aCPIter++) {
397 //// for (int i = 0; i < 4; i++)
398 //// isPointFound[i] = (aCPIter->find(aPointsToFind[i]) != aCPIter->end());
399 //// if ((isPointFound[0] || isPointFound[1]) && (isPointFound[2] || isPointFound[3])) {
400 //// // the arc is tangent by end point
401 //// if (isPointFound[1]) aSlvsOtherFlag = 1;
402 //// // the second item is an arc and it is tangent by end point too
403 //// if (!hasLine && isPointFound[3]) aSlvsOther2Flag = 1;
407 //// if (aCPIter == myCoincidentPoints.end()) {
408 //// // There is no coincident points between tangential objects. Generate error message
409 //// Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this);
414 //// // Create SolveSpace constraint structure
415 //// Slvs_Constraint aSlvsConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
416 //// myWorkplane.h, aDistance, aConstrEnt[0],
417 //// aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]);
418 //// if (aSlvsOtherFlag != 0) aSlvsConstr.other = aSlvsOtherFlag;
419 //// if (aSlvsOther2Flag != 0) aSlvsConstr.other2 = aSlvsOther2Flag;
420 //// myConstraints.push_back(aSlvsConstr);
421 //// myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aSlvsConstr.h);
422 //// int aConstrPos = Search(aSlvsConstr.h, myConstraints);
423 //// aConstrIter = myConstraints.begin() + aConstrPos;
424 //// myNeedToSolve = true;
425 //// } else { // Attributes of constraint may be changed => update constraint
426 //// Slvs_hEntity* aCurrentAttr[] = {&aConstrIter->ptA, &aConstrIter->ptB,
427 //// &aConstrIter->entityA, &aConstrIter->entityB,
428 //// &aConstrIter->entityC, &aConstrIter->entityD};
429 //// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
430 //// if (*(aCurrentAttr[indAttr]) != aConstrEnt[indAttr])
432 //// *(aCurrentAttr[indAttr]) = aConstrEnt[indAttr];
433 //// myNeedToSolve = true;
438 //// // Update flags of entities to be used by constraints
439 //// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
440 //// if (aConstrEnt[indAttr] != 0) {
441 //// int aPos = Search(aConstrEnt[indAttr], myEntities);
442 //// myEntOfConstr[aPos] = true;
443 //// // Sub-entities should be used implcitly
444 //// Slvs_hEntity* aEntPtr = myEntities[aPos].point;
445 //// while (*aEntPtr != 0) {
446 //// aPos = Search(*aEntPtr, myEntities);
447 //// myEntOfConstr[aPos] = true;
452 //// checkConstraintConsistence(*aConstrIter);
456 void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
458 std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theFeature);
459 std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
460 for (; aCIter != aConstraints.end(); aCIter++) {
461 ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
462 aSolConIter->second->update();
465 // Temporary rigid constraint
466 SolverConstraintPtr aConstraint =
467 SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
470 aConstraint->setGroup(this);
471 aConstraint->setStorage(myStorage);
472 myTempConstraints.insert(aConstraint);
475 ////// ============================================================================
476 ////// Function: changeRigidConstraint
477 ////// Class: SketchSolver_Group
478 ////// Purpose: create/update the "Rigid" constraint in the group
479 ////// ============================================================================
480 ////bool SketchSolver_Group::changeRigidConstraint(
481 //// std::shared_ptr<SketchPlugin_Constraint> theConstraint)
483 //// // Search this constraint in the current group to update it
484 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
485 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
486 //// if (aConstrMapIter != myConstraintMap.end()) {
487 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
488 //// aConstrIter = myConstraints.begin() + aConstrPos;
491 //// // Get constraint type and verify the constraint parameters are correct
492 //// SketchSolver_Constraint aConstraint(theConstraint);
493 //// int aConstrType = aConstraint.getType();
494 //// if (aConstrType == SLVS_C_UNKNOWN
495 //// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
497 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
499 //// Slvs_hEntity aConstrEnt = SLVS_E_UNKNOWN;
500 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
501 //// ModelAPI_AttributeRefAttr>(
502 //// theConstraint->data()->attribute(aConstraintAttributes[0]));
503 //// if (!aConstrAttr)
506 //// // Convert the object of the attribute to the feature
507 //// FeaturePtr aFeature;
508 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
509 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
510 //// aConstrAttr->object());
513 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
514 //// aFeature = aDoc->feature(aRC);
517 //// aConstrEnt = aConstrAttr->isObject() ? changeEntityFeature(aFeature) : changeEntity(aConstrAttr->attr());
519 //// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
520 //// // Check the fixed entity is not a point.
521 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
522 //// ModelAPI_AttributeRefAttr>(theConstraint->data()->attribute(aConstraintAttributes[0]));
523 //// std::shared_ptr<GeomDataAPI_Point> aPoint =
524 //// std::dynamic_pointer_cast<GeomDataAPI_Point>(aConstrAttr->attr());
525 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
526 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aConstrAttr->attr());
527 //// if (aPoint || aPoint2D) {
528 //// // Create SolveSpace constraint structure
529 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
530 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
531 //// aConstrEnt, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
532 //// myConstraints.push_back(aConstraint);
533 //// myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aConstraint.h);
534 //// int aConstrPos = Search(aConstraint.h, myConstraints);
535 //// aConstrIter = myConstraints.begin() + aConstrPos;
536 //// myNeedToSolve = true;
538 //// myConstraintMap[theConstraint] = std::vector<Slvs_hConstraint>();
540 //// // To avoid SolveSpace problems:
541 //// // * if the circle is rigid, we will fix its center and radius;
542 //// // * if the arc is rigid, we will fix its start and end points and radius.
543 //// double aRadius = 0.0;
544 //// bool isArc = false;
545 //// bool isCircle = false;
547 //// if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
548 //// std::shared_ptr<GeomDataAPI_Point2D> aCenter =
549 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
550 //// aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
551 //// std::shared_ptr<GeomDataAPI_Point2D> aStart =
552 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
553 //// aFeature->data()->attribute(SketchPlugin_Arc::START_ID()));
554 //// aRadius = aStart->pnt()->distance(aCenter->pnt());
556 //// } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
557 //// aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
558 //// aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()))->value();
559 //// isCircle = true;
563 //// // Get list of already fixed points
564 //// std::set<Slvs_hEntity> anAlreadyFixed;
565 //// std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
566 //// for (; aCIter != myConstraints.end(); aCIter++)
567 //// if (aCIter->type == SLVS_C_WHERE_DRAGGED)
568 //// anAlreadyFixed.insert(aCIter->ptA);
570 //// // Create constraints to fix the parameters of the entity
571 //// int aEntPos = Search(aConstrEnt, myEntities);
572 //// Slvs_hEntity* aPointsPtr = myEntities[aEntPos].point;
573 //// if (isArc) aPointsPtr++; // avoid to fix center of arc
574 //// while (*aPointsPtr != 0) {
575 //// // Avoid to create additional "Rigid" constraints for coincident points
576 //// bool isCoincAlreadyFixed = false;
577 //// if (!anAlreadyFixed.empty()) {
578 //// if (anAlreadyFixed.find(*aPointsPtr) != anAlreadyFixed.end())
579 //// isCoincAlreadyFixed = true;
581 //// std::vector<std::set<Slvs_hEntity> >::const_iterator aCoincIter =
582 //// myCoincidentPoints.begin();
583 //// for (; !isCoincAlreadyFixed && aCoincIter != myCoincidentPoints.end(); aCoincIter++) {
584 //// if (aCoincIter->find(*aPointsPtr) == aCoincIter->end())
586 //// std::set<Slvs_hEntity>::const_iterator anIter = anAlreadyFixed.begin();
587 //// for (; !isCoincAlreadyFixed && anIter != anAlreadyFixed.end(); anIter++)
588 //// if (aCoincIter->find(*anIter) != aCoincIter->end())
589 //// isCoincAlreadyFixed = true;
593 //// if (!isCoincAlreadyFixed) {
594 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
595 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
596 //// *aPointsPtr, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
597 //// myConstraints.push_back(aConstraint);
598 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
603 //// if (isArc || isCircle) { // add radius constraint
604 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
605 //// ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, 2.0 * aRadius,
606 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aConstrEnt, SLVS_E_UNKNOWN);
607 //// myConstraints.push_back(aConstraint);
608 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
611 //// // The object is already rigid, so there is no constraints added
612 //// if (myConstraintMap[theConstraint].empty()) {
613 //// myConstraintMap.erase(theConstraint);
614 //// myNeedToSolve = false;
617 //// myNeedToSolve = true;
623 ////// ============================================================================
624 ////// Function: changeMirrorConstraint
625 ////// Class: SketchSolver_Group
626 ////// Purpose: create/update the "Mirror" constraint in the group
627 ////// ============================================================================
628 ////bool SketchSolver_Group::changeMirrorConstraint(
629 //// std::shared_ptr<SketchPlugin_Constraint> theConstraint)
631 //// DataPtr aConstrData = theConstraint->data();
633 //// // Search this constraint in the current group to update it
634 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
635 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
636 //// if (aConstrMapIter != myConstraintMap.end()) {
637 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
638 //// aConstrIter = myConstraints.begin() + aConstrPos;
641 //// // Get constraint type and verify the constraint parameters are correct
642 //// SketchSolver_Constraint aConstraint(theConstraint);
643 //// int aConstrType = aConstraint.getType();
644 //// if (aConstrType == SLVS_C_UNKNOWN
645 //// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
647 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
649 //// Slvs_hEntity aMirrorLineEnt = SLVS_E_UNKNOWN;
650 //// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
651 //// aConstrData->attribute(aConstraintAttributes[0]));
652 //// if (!aConstrAttr)
655 //// // Convert the object of the attribute to the feature
656 //// FeaturePtr aMirrorLineFeat;
657 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
658 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
659 //// aConstrAttr->object());
662 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
663 //// aMirrorLineFeat = aDoc->feature(aRC);
665 //// aMirrorLineEnt = aConstrAttr->isObject() ?
666 //// changeEntityFeature(aMirrorLineFeat) : changeEntity(aConstrAttr->attr());
668 //// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
669 //// // Append symmetric constraint for each point of mirroring features
670 //// AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
671 //// aConstrData->attribute(aConstraintAttributes[1]));
672 //// AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
673 //// aConstrData->attribute(aConstraintAttributes[2]));
674 //// if (!aBaseRefList || !aMirroredRefList)
677 //// std::list<ObjectPtr> aBaseList = aBaseRefList->list();
678 //// std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
679 //// if (aBaseList.size() != aMirroredList.size())
682 //// myConstraintMap[theConstraint] = std::vector<Slvs_hConstraint>();
684 //// FeaturePtr aBaseFeature, aMirrorFeature;
685 //// ResultConstructionPtr aRC;
686 //// std::list<ObjectPtr>::iterator aBaseIter = aBaseList.begin();
687 //// std::list<ObjectPtr>::iterator aMirIter = aMirroredList.begin();
688 //// for ( ; aBaseIter != aBaseList.end(); aBaseIter++, aMirIter++) {
689 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aBaseIter);
690 //// aBaseFeature = aRC ? aRC->document()->feature(aRC) :
691 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aBaseIter);
692 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirIter);
693 //// aMirrorFeature = aRC ? aRC->document()->feature(aRC) :
694 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirIter);
696 //// if (!aBaseFeature || !aMirrorFeature ||
697 //// aBaseFeature->getKind() != aMirrorFeature->getKind())
699 //// Slvs_hEntity aBaseEnt = changeEntityFeature(aBaseFeature);
700 //// Slvs_hEntity aMirrorEnt = changeEntityFeature(aMirrorFeature);
701 //// // Make aMirrorEnt parameters to be symmetric with aBaseEnt
702 //// makeMirrorEntity(aBaseEnt, aMirrorEnt, aMirrorLineEnt);
704 //// if (aBaseFeature->getKind() == SketchPlugin_Point::ID()) {
705 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
706 //// myWorkplane.h, 0.0, aBaseEnt, aMirrorEnt, aMirrorLineEnt, SLVS_E_UNKNOWN);
707 //// myConstraints.push_back(aConstraint);
708 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
710 //// int aBasePos = Search(aBaseEnt, myEntities);
711 //// int aMirrorPos = Search(aMirrorEnt, myEntities);
712 //// if (aBaseFeature->getKind() == SketchPlugin_Line::ID()) {
713 //// for (int ind = 0; ind < 2; ind++) {
714 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
715 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
716 //// myEntities[aBasePos].point[ind], myEntities[aMirrorPos].point[ind],
717 //// aMirrorLineEnt, SLVS_E_UNKNOWN);
718 //// myConstraints.push_back(aConstraint);
719 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
721 //// } else if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
722 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
723 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
724 //// myEntities[aBasePos].point[0], myEntities[aMirrorPos].point[0],
725 //// aMirrorLineEnt, SLVS_E_UNKNOWN);
726 //// myConstraints.push_back(aConstraint);
727 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
728 //// // Additional constraint for equal radii
729 //// Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
730 //// ++myConstrMaxID, myID, SLVS_C_EQUAL_RADIUS, myWorkplane.h, 0.0,
731 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseEnt, aMirrorEnt);
732 //// myConstraints.push_back(anEqRadConstr);
733 //// myConstraintMap[theConstraint].push_back(anEqRadConstr.h);
734 //// } else if (aBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
735 //// // Workaround to avoid problems in SolveSpace.
736 //// // The symmetry of two arcs will be done using symmetry of three points on these arcs:
737 //// // start point, end point, and any other point on the arc
738 //// Slvs_hEntity aBaseArcPoints[3] = {
739 //// myEntities[aBasePos].point[1],
740 //// myEntities[aBasePos].point[2],
741 //// SLVS_E_UNKNOWN};
742 //// Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point
743 //// myEntities[aMirrorPos].point[2],
744 //// myEntities[aMirrorPos].point[1],
745 //// SLVS_E_UNKNOWN};
746 //// Slvs_hEntity aBothArcs[2] = {aBaseEnt, aMirrorEnt};
747 //// Slvs_hEntity aBothMiddlePoints[2];
748 //// for (int i = 0; i < 2; i++) {
750 //// calculateMiddlePoint(aBothArcs[i], x, y);
751 //// std::vector<Slvs_Param>::iterator aParamIter = myParams.end();
752 //// Slvs_hParam u = changeParameter(x, aParamIter);
753 //// Slvs_hParam v = changeParameter(y, aParamIter);
754 //// Slvs_Entity aPoint = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, u, v);
755 //// myEntities.push_back(aPoint);
756 //// aBothMiddlePoints[i] = aPoint.h;
757 //// // additional constraint point-on-curve
758 //// Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
759 //// ++myConstrMaxID, myID, SLVS_C_PT_ON_CIRCLE, myWorkplane.h, 0.0,
760 //// aPoint.h, SLVS_E_UNKNOWN, aBothArcs[i], SLVS_E_UNKNOWN);
761 //// myConstraints.push_back(aPonCircConstr);
762 //// myConstraintMap[theConstraint].push_back(aPonCircConstr.h);
765 //// aBaseArcPoints[2] = aBothMiddlePoints[0];
766 //// aMirrorArcPoints[2] = aBothMiddlePoints[1];
767 //// for (int ind = 0; ind < 3; ind++) {
768 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
769 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
770 //// aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLineEnt, SLVS_E_UNKNOWN);
771 //// myConstraints.push_back(aConstraint);
772 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
778 //// // Set the mirror line unchanged during constraint recalculation
779 //// int aMirrorLinePos = Search(aMirrorLineEnt, myEntities);
780 //// Slvs_Constraint aRigidStart = Slvs_MakeConstraint(
781 //// ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0,
782 //// myEntities[aMirrorLinePos].point[0], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
783 //// myConstraints.push_back(aRigidStart);
784 //// myConstraintMap[theConstraint].push_back(aRigidStart.h);
785 //// Slvs_Constraint aRigidEnd = Slvs_MakeConstraint(
786 //// ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0,
787 //// myEntities[aMirrorLinePos].point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
788 //// myConstraints.push_back(aRigidEnd);
789 //// myConstraintMap[theConstraint].push_back(aRigidEnd.h);
791 //// // Add temporary constraints for initial objects to be unchanged
792 //// for (aBaseIter = aBaseList.begin(); aBaseIter != aBaseList.end(); aBaseIter++) {
793 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aBaseIter);
794 //// aBaseFeature = aRC ? aRC->document()->feature(aRC) :
795 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aBaseIter);
796 //// if (!aBaseFeature) continue;
797 //// std::list<AttributePtr> aPoints = aBaseFeature->data()->attributes(GeomDataAPI_Point2D::type());
798 //// std::list<AttributePtr>::iterator anIt = aPoints.begin();
799 //// for ( ; anIt != aPoints.end(); anIt++) {
800 //// // Arcs are fixed by center and start points only (to avoid solving errors in SolveSpace)
801 //// if (aBaseFeature->getKind() == SketchPlugin_Arc::ID() &&
802 //// (*anIt)->id() == SketchPlugin_Arc::END_ID())
804 //// addTemporaryConstraintWhereDragged(*anIt);
811 ////// ============================================================================
812 ////// Function: changeFilletConstraint
813 ////// Class: SketchSolver_Group
814 ////// Purpose: create/update the "Fillet" constraint in the group
815 ////// ============================================================================
816 ////bool SketchSolver_Group::changeFilletConstraint(
817 //// std::shared_ptr<SketchPlugin_Constraint> theConstraint)
819 //// DataPtr aConstrData = theConstraint->data();
821 //// // Search this constraint in the current group to update it
822 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
823 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
824 //// if (aConstrMapIter != myConstraintMap.end()) {
825 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
826 //// aConstrIter = myConstraints.begin() + aConstrPos;
829 //// // Get constraint type and verify the constraint parameters are correct
830 //// SketchSolver_Constraint aConstraint(theConstraint);
831 //// int aConstrType = aConstraint.getType();
832 //// if (aConstrType == SLVS_C_UNKNOWN)
834 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
836 //// // Obtain hEntity for basic objects of fillet
837 //// Slvs_hEntity aBaseObject[2];
838 //// FeaturePtr aBaseFeature[2];
839 //// for (unsigned int indAttr = 0; indAttr < 2; indAttr++) {
840 //// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
841 //// aConstrData->attribute(aConstraintAttributes[indAttr]));
842 //// if (!aConstrAttr)
844 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
845 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
846 //// aConstrAttr->object());
849 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
850 //// aBaseFeature[indAttr] = aDoc->feature(aRC);
852 //// aBaseObject[indAttr] = aConstrAttr->isObject() ?
853 //// changeEntityFeature(aBaseFeature[indAttr]) : changeEntity(aConstrAttr->attr());
855 //// // Check the base entities have a coincident point
856 //// int aBaseObjInd[2] = {
857 //// Search(aBaseObject[0], myEntities),
858 //// Search(aBaseObject[1], myEntities)
860 //// int aShift[2] = { // shift for calculating correct start and end points for different types of objects
861 //// myEntities[aBaseObjInd[0]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0,
862 //// myEntities[aBaseObjInd[1]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0,
864 //// Slvs_hEntity aFirstObjPoints[2] = { // indices of start and end point of first object
865 //// myEntities[aBaseObjInd[0]].point[aShift[0]],
866 //// myEntities[aBaseObjInd[0]].point[1+aShift[0]]
868 //// Slvs_hEntity aSecondObjPoints[2] = { // indices of start and end point of second object
869 //// myEntities[aBaseObjInd[1]].point[aShift[1]],
870 //// myEntities[aBaseObjInd[1]].point[1+aShift[1]]
872 //// bool isCoincidentFound = false;
873 //// int aBaseCoincInd[2] = {0, 0}; // indices in aFirstObjPoint and aSecondObjPoint identifying coincident points
874 //// std::vector<std::set<Slvs_hEntity> >::iterator aCPIter = myCoincidentPoints.begin();
875 //// for ( ; aCPIter != myCoincidentPoints.end() && !isCoincidentFound; aCPIter++)
876 //// for (int ind1 = 0; ind1 < 2 && !isCoincidentFound; ind1++)
877 //// for (int ind2 = 0; ind2 < 2 && !isCoincidentFound; ind2++)
878 //// if (aCPIter->find(aFirstObjPoints[ind1]) != aCPIter->end() &&
879 //// aCPIter->find(aSecondObjPoints[ind2]) != aCPIter->end()) {
880 //// aBaseCoincInd[0] = ind1;
881 //// aBaseCoincInd[1] = ind2;
882 //// isCoincidentFound = true;
884 //// if (!isCoincidentFound) {
885 //// // There is no coincident points between objects. Generate error message
886 //// Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this);
890 //// // Create fillet entities
891 //// // - first object is placed on the first base
892 //// // - second object is on the second base
893 //// // - third object is a filleting arc
894 //// static const int aNbFilletEnt = 3;
895 //// Slvs_hEntity aFilletEnt[aNbFilletEnt];
896 //// int aFilletObjInd[aNbFilletEnt];
897 //// AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
898 //// aConstrData->attribute(aConstraintAttributes[2]));
899 //// if (!aFilletRefList)
901 //// std::list<ObjectPtr> aFilletList = aFilletRefList->list();
902 //// if (aFilletList.size() < aNbFilletEnt)
904 //// FeaturePtr aFilletFeature;
905 //// ResultConstructionPtr aRC;
906 //// std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
907 //// for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
908 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
909 //// aFilletFeature = aRC ? aRC->document()->feature(aRC) :
910 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFilIter);
911 //// if (!aFilletFeature)
913 //// aFilletEnt[indEnt] = changeEntityFeature(aFilletFeature);
914 //// aFilletObjInd[indEnt] = Search(aFilletEnt[indEnt], myEntities);
916 //// // At first time, for correct result, move floating points of fillet on the middle points of base objects
917 //// if (myConstraintMap.find(theConstraint) == myConstraintMap.end()) {
918 //// double anArcPoints[6];
919 //// for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
920 //// int anIndShift = myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
921 //// int aPointsPos[2] = {
922 //// Search(myEntities[aFilletObjInd[indEnt]].point[anIndShift], myEntities),
923 //// Search(myEntities[aFilletObjInd[indEnt]].point[1+anIndShift], myEntities)
925 //// int aParamPos[2] = {
926 //// Search(myEntities[aPointsPos[0]].param[0], myParams),
927 //// Search(myEntities[aPointsPos[1]].param[0], myParams)
929 //// int anIndex = aParamPos[aBaseCoincInd[indEnt]];
930 //// if (anIndShift == 0) {
931 //// myParams[anIndex].val =
932 //// 0.5 * (myParams[aParamPos[0]].val + myParams[aParamPos[1]].val);
933 //// myParams[1 + anIndex].val =
934 //// 0.5 * (myParams[1 + aParamPos[0]].val + myParams[1 + aParamPos[1]].val);
935 //// } else { // place the changed point on the arc
936 //// double x = 0, y = 0;
937 //// calculateMiddlePoint(aFilletEnt[indEnt], x, y);
938 //// myParams[anIndex].val = x;
939 //// myParams[1 + anIndex].val = y;
941 //// anArcPoints[indEnt*2+2] = myParams[anIndex].val;
942 //// anArcPoints[indEnt*2+3] = myParams[1 + anIndex].val;
944 //// anArcPoints[0] = 0.5 * (anArcPoints[2] + anArcPoints[4]);
945 //// anArcPoints[1] = 0.5 * (anArcPoints[3] + anArcPoints[5]);
946 //// for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
947 //// int aPtPos = Search(myEntities[aFilletObjInd[2]].point[indArcPt], myEntities);
948 //// int aParamPos = Search(myEntities[aPtPos].param[0], myParams);
949 //// myParams[aParamPos].val = anArcPoints[indArcPt * 2];
950 //// myParams[aParamPos + 1].val = anArcPoints[indArcPt * 2 + 1];
954 //// // Check the fillet arc which point to be connected to
955 //// bool isArcInversed = false; // indicates that start and end points of arc should be connected to second and first object respectively
956 //// Slvs_hEntity hEnt = myEntities[aFilletObjInd[2]].point[1];
957 //// int aPos = Search(hEnt, myEntities);
958 //// Slvs_hParam anArcStartPoint = myEntities[aPos].param[0];
959 //// aPos = Search(anArcStartPoint, myParams);
960 //// double anArcPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val};
961 //// double aSqDistances[2];
963 //// for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
964 //// aPtInd = aBaseCoincInd[indEnt]+aShift[indEnt];
965 //// hEnt = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
966 //// aPos = Search(hEnt, myEntities);
967 //// Slvs_hParam anObjectPoint = myEntities[aPos].param[0];
968 //// aPos = Search(anObjectPoint, myParams);
969 //// double aPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val};
970 //// aSqDistances[indEnt] =
971 //// (anArcPtCoord[0] - aPtCoord[0]) * (anArcPtCoord[0] - aPtCoord[0]) +
972 //// (anArcPtCoord[1] - aPtCoord[1]) * (anArcPtCoord[1] - aPtCoord[1]);
974 //// if (aSqDistances[1] < aSqDistances[0])
975 //// isArcInversed = true;
977 //// // Create list of constraints to generate fillet
978 //// std::vector<Slvs_hConstraint> aConstrList;
979 //// bool isExists = myConstraintMap.find(theConstraint) != myConstraintMap.end(); // constraint already exists
980 //// std::vector<Slvs_hConstraint>::iterator aCMapIter =
981 //// isExists ? myConstraintMap[theConstraint].begin() : aConstrList.begin();
982 //// int aCurConstrPos = isExists ? Search(*aCMapIter, myConstraints) : 0;
983 //// for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
984 //// // one point of fillet object should be coincident with the point on base, non-coincident with another base object
985 //// aPtInd = 1-aBaseCoincInd[indEnt]+aShift[indEnt]; // (1-aBaseCoincInd[indEnt]) = index of non-coincident point, aShift is used to process all types of shapes
986 //// Slvs_hEntity aPtBase = myEntities[aBaseObjInd[indEnt]].point[aPtInd];
987 //// Slvs_hEntity aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
989 //// myConstraints[aCurConstrPos].ptA = aPtBase;
990 //// myConstraints[aCurConstrPos].ptB = aPtFillet;
992 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
994 //// Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
995 //// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
996 //// 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
997 //// myConstraints.push_back(aCoincConstr);
998 //// aConstrList.push_back(aCoincConstr.h);
1001 //// // another point of fillet object should be placed on the base object
1002 //// Slvs_Constraint aPonCurveConstr;
1003 //// int aTangentType;
1004 //// if (myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE) {
1005 //// // centers of arcs should be coincident
1006 //// aPtBase = myEntities[aBaseObjInd[indEnt]].point[0];
1007 //// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[0];
1008 //// if (isExists) {
1009 //// myConstraints[aCurConstrPos].ptA = aPtBase;
1010 //// myConstraints[aCurConstrPos].ptB = aPtFillet;
1012 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
1014 //// aPonCurveConstr = Slvs_MakeConstraint(
1015 //// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
1016 //// 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
1018 //// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[1+aBaseCoincInd[indEnt]]; // !!! will be used below
1019 //// aTangentType = SLVS_C_CURVE_CURVE_TANGENT;
1021 //// aPtInd = aBaseCoincInd[indEnt];
1022 //// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
1023 //// if (isExists) {
1024 //// myConstraints[aCurConstrPos].ptA = aPtFillet;
1026 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
1028 //// aPonCurveConstr = Slvs_MakeConstraint(
1029 //// ++myConstrMaxID, myID, SLVS_C_PT_ON_LINE, myWorkplane.h,
1030 //// 0, aPtFillet, SLVS_E_UNKNOWN, aBaseObject[indEnt], SLVS_E_UNKNOWN);
1032 //// aTangentType = SLVS_C_ARC_LINE_TANGENT;
1034 //// if (!isExists) {
1035 //// myConstraints.push_back(aPonCurveConstr);
1036 //// aConstrList.push_back(aPonCurveConstr.h);
1039 //// // Bound point of fillet arc should be tangently coincident with a bound point of fillet object
1040 //// aPtInd = 1 + (isArcInversed ? 1-indEnt : indEnt);
1041 //// Slvs_hEntity aPtArc = myEntities[aFilletObjInd[2]].point[aPtInd];
1042 //// if (isExists) {
1043 //// myConstraints[aCurConstrPos].ptA = aPtArc;
1044 //// myConstraints[aCurConstrPos].ptB = aPtFillet;
1046 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
1047 //// myConstraints[aCurConstrPos].entityA = aFilletEnt[2];
1048 //// myConstraints[aCurConstrPos].entityB = aFilletEnt[indEnt];
1049 //// myConstraints[aCurConstrPos].other = (isArcInversed ? 1-indEnt : indEnt);
1051 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
1053 //// Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
1054 //// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
1055 //// 0, aPtArc, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
1056 //// myConstraints.push_back(aCoincConstr);
1057 //// aConstrList.push_back(aCoincConstr.h);
1058 //// Slvs_Constraint aTangency = Slvs_MakeConstraint(
1059 //// ++myConstrMaxID, myID, aTangentType, myWorkplane.h,
1060 //// 0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], aFilletEnt[indEnt]);
1061 //// aTangency.other = (isArcInversed ? 1-indEnt : indEnt);
1062 //// aTangency.other2 = aTangentType == SLVS_C_CURVE_CURVE_TANGENT ? aBaseCoincInd[indEnt] : 0;
1063 //// myConstraints.push_back(aTangency);
1064 //// aConstrList.push_back(aTangency.h);
1068 //// // Additional constraint for fillet diameter
1069 //// double aRadius = 0.0; // scalar value of the constraint
1070 //// AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
1071 //// aConstrData->attribute(SketchPlugin_Constraint::VALUE()));
1072 //// aRadius = aDistAttr->value();
1073 //// if (isExists) {
1074 //// myConstraints[aCurConstrPos].entityA = aFilletEnt[2];
1075 //// myConstraints[aCurConstrPos].valA = aRadius * 2.0;
1078 //// Slvs_Constraint aDiamConstr = Slvs_MakeConstraint(
1079 //// ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, aRadius * 2.0,
1080 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], SLVS_E_UNKNOWN);
1081 //// myConstraints.push_back(aDiamConstr);
1082 //// aConstrList.push_back(aDiamConstr.h);
1084 //// myConstraintMap[theConstraint] = aConstrList;
1087 //// // Additional temporary constraints for base objects to be fixed
1088 //// for (unsigned int indAttr = 0; indAttr < 2; indAttr++) {
1089 //// if (!aBaseFeature[indAttr]) {
1090 //// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1091 //// aConstrData->attribute(aConstraintAttributes[indAttr]));
1092 //// addTemporaryConstraintWhereDragged(aConstrAttr->attr());
1095 //// std::list<AttributePtr> anAttributes =
1096 //// aBaseFeature[indAttr]->data()->attributes(GeomDataAPI_Point2D::type());
1097 //// std::list<AttributePtr>::iterator anIt = anAttributes.begin();
1098 //// for ( ; anIt != anAttributes.end(); anIt++) {
1099 //// // Arc should be fixed by center and start points only (to avoid "conflicting constraints" message)
1100 //// if (aBaseFeature[indAttr]->getKind() == SketchPlugin_Arc::ID() &&
1101 //// (*anIt)->id() == SketchPlugin_Arc::END_ID())
1103 //// addTemporaryConstraintWhereDragged(*anIt);
1109 ////// ============================================================================
1110 ////// Function: changeEntity
1111 ////// Class: SketchSolver_Group
1112 ////// Purpose: create/update the element affected by any constraint
1113 ////// ============================================================================
1114 ////Slvs_hEntity SketchSolver_Group::changeEntity(
1115 //// std::shared_ptr<ModelAPI_Attribute> theEntity)
1117 //// // If the entity is already in the group, try to find it
1118 //// std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator aEntIter =
1119 //// myEntityAttrMap.find(theEntity);
1121 //// std::vector<Slvs_Param>::const_iterator aParamIter; // looks at first parameter of already existent entity or at the end of vector otherwise
1122 //// if (aEntIter == myEntityAttrMap.end()) // no such entity => should be created
1123 //// aParamIter = myParams.end();
1124 //// else { // the entity already exists
1125 //// aEntPos = Search(aEntIter->second, myEntities);
1126 //// int aParamPos = Search(myEntities[aEntPos].param[0], myParams);
1127 //// aParamIter = myParams.begin() + aParamPos;
1129 //// const bool isEntExists = (aEntIter != myEntityAttrMap.end()); // defines that the entity already exists
1130 //// const bool isNeedToSolve = myNeedToSolve;
1131 //// myNeedToSolve = false;
1133 //// if (isEntExists) {
1134 //// // Verify that the entity is not used by "Rigid" constraint.
1135 //// // If it is used, the object should not move.
1136 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoincIter = myCoincidentPoints.begin();
1137 //// for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++)
1138 //// if (aCoincIter->find(aEntIter->second) != aCoincIter->end())
1140 //// std::set<Slvs_hEntity> aCoincident;
1141 //// if (aCoincIter != myCoincidentPoints.end()) {
1142 //// aCoincident = *aCoincIter;
1143 //// aCoincident.erase(aEntIter->second);
1145 //// std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
1146 //// for (; aConstrIter != myConstraints.end(); aConstrIter++)
1147 //// if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
1148 //// aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
1149 //// myNeedToSolve = true;
1150 //// return aEntIter->second;
1155 //// // Look over supported types of entities
1156 //// Slvs_Entity aNewEntity;
1157 //// aNewEntity.h = SLVS_E_UNKNOWN;
1160 //// std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1163 //// Slvs_hParam aX = changeParameter(aPoint->x(), aParamIter);
1164 //// Slvs_hParam aY = changeParameter(aPoint->y(), aParamIter);
1165 //// Slvs_hParam aZ = changeParameter(aPoint->z(), aParamIter);
1166 //// if (!isEntExists) // New entity
1167 //// aNewEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ);
1169 //// // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
1170 //// if (myWorkplane.h == SLVS_E_UNKNOWN)
1171 //// return SLVS_E_UNKNOWN;
1174 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
1175 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
1176 //// if (aPoint2D) {
1177 //// Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter);
1178 //// Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter);
1179 //// if (!isEntExists) // New entity
1180 //// aNewEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV);
1182 //// // Scalar value (used for the distance entities)
1183 //// AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
1185 //// Slvs_hParam aValue = changeParameter(aScalar->value(), aParamIter);
1186 //// if (!isEntExists) // New entity
1187 //// aNewEntity = Slvs_MakeDistance(++myEntityMaxID, myID, myWorkplane.h, aValue);
1191 //// /// \todo Other types of entities
1193 //// Slvs_hEntity aResult = SLVS_E_UNKNOWN; // Unsupported or wrong entity type
1195 //// if (isEntExists) {
1196 //// myNeedToSolve = myNeedToSolve || isNeedToSolve;
1197 //// aResult = aEntIter->second;
1198 //// } else if (aNewEntity.h != SLVS_E_UNKNOWN) {
1199 //// myEntities.push_back(aNewEntity);
1200 //// myEntOfConstr.push_back(false);
1201 //// myEntityAttrMap[theEntity] = aNewEntity.h;
1202 //// aResult = aNewEntity.h;
1205 //// // If the attribute was changed by the user, we need to fix it before solving
1206 //// if (myNeedToSolve && theEntity->isImmutable())
1207 //// addTemporaryConstraintWhereDragged(theEntity, false);
1209 //// return aResult;
1212 ////// ============================================================================
1213 ////// Function: changeEntity
1214 ////// Class: SketchSolver_Group
1215 ////// Purpose: create/update the element defined by the feature affected by any constraint
1216 ////// ============================================================================
1217 ////Slvs_hEntity SketchSolver_Group::changeEntityFeature(FeaturePtr theEntity)
1219 //// if (!theEntity->data()->isValid())
1220 //// return SLVS_E_UNKNOWN;
1221 //// // If the entity is already in the group, try to find it
1222 //// std::map<FeaturePtr, Slvs_hEntity>::const_iterator aEntIter = myEntityFeatMap.find(theEntity);
1223 //// // defines that the entity already exists
1224 //// const bool isEntExists = (myEntityFeatMap.find(theEntity) != myEntityFeatMap.end());
1226 //// Slvs_Entity aNewEntity;
1227 //// aNewEntity.h = SLVS_E_UNKNOWN;
1229 //// // SketchPlugin features
1230 //// std::shared_ptr<SketchPlugin_Feature> aFeature = std::dynamic_pointer_cast<
1231 //// SketchPlugin_Feature>(theEntity);
1232 //// if (aFeature) { // Verify the feature by its kind
1233 //// const std::string& aFeatureKind = aFeature->getKind();
1234 //// AttributePtr anAttribute;
1237 //// if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) {
1238 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID());
1239 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1240 //// Slvs_hEntity aStart = changeEntity(anAttribute);
1242 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID());
1243 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1244 //// Slvs_hEntity aEnd = changeEntity(anAttribute);
1246 //// if (!isEntExists) // New entity
1247 //// aNewEntity = Slvs_MakeLineSegment(++myEntityMaxID, myID, myWorkplane.h, aStart, aEnd);
1250 //// else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) {
1251 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID());
1252 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1253 //// Slvs_hEntity aCenter = changeEntity(anAttribute);
1255 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID());
1256 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1257 //// Slvs_hEntity aRadius = changeEntity(anAttribute);
1259 //// if (!isEntExists) // New entity
1260 //// aNewEntity = Slvs_MakeCircle(++myEntityMaxID, myID, myWorkplane.h, aCenter,
1261 //// myWorkplane.normal, aRadius);
1264 //// else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) {
1265 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID());
1266 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1267 //// Slvs_hEntity aCenter = changeEntity(anAttribute);
1269 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID());
1270 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1271 //// Slvs_hEntity aStart = changeEntity(anAttribute);
1273 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID());
1274 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1275 //// Slvs_hEntity aEnd = changeEntity(anAttribute);
1277 //// if (!isEntExists)
1278 //// aNewEntity = Slvs_MakeArcOfCircle(++myEntityMaxID, myID, myWorkplane.h,
1279 //// myWorkplane.normal, aCenter, aStart, aEnd);
1281 //// // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
1282 //// else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) {
1283 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID());
1284 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1285 //// Slvs_hEntity aPoint = changeEntity(anAttribute);
1287 //// if (isEntExists)
1288 //// return aEntIter->second;
1290 //// // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
1291 //// myEntityFeatMap[theEntity] = aPoint;
1292 //// myNeedToSolve = true;
1296 //// /// \todo Other types of features
1298 //// if (isEntExists)
1299 //// return aEntIter->second;
1301 //// if (aNewEntity.h != SLVS_E_UNKNOWN) {
1302 //// myEntities.push_back(aNewEntity);
1303 //// myEntOfConstr.push_back(false);
1304 //// myEntityFeatMap[theEntity] = aNewEntity.h;
1305 //// myNeedToSolve = true;
1306 //// return aNewEntity.h;
1309 //// // Unsupported or wrong entity type
1310 //// return SLVS_E_UNKNOWN;
1313 // ============================================================================
1314 // Function: addWorkplane
1315 // Class: SketchSolver_Group
1316 // Purpose: create workplane for the group
1317 // ============================================================================
1318 bool SketchSolver_Group::addWorkplane(CompositeFeaturePtr theSketch)
1320 if (myWorkplaneID != SLVS_E_UNKNOWN || theSketch->getKind() != SketchPlugin_Sketch::ID())
1321 return false; // the workplane already exists or the function parameter is not Sketch
1323 mySketch = theSketch;
1328 // ============================================================================
1329 // Function: updateWorkplane
1330 // Class: SketchSolver_Group
1331 // Purpose: update parameters of workplane
1332 // ============================================================================
1333 bool SketchSolver_Group::updateWorkplane()
1335 if (!myStorage) // Create storage if not exists
1336 myStorage = StoragePtr(new SketchSolver_Storage);
1337 SketchSolver_Builder* aBuilder = SketchSolver_Builder::getInstance();
1339 std::vector<Slvs_Entity> anEntities;
1340 std::vector<Slvs_Param> aParams;
1341 if (!aBuilder->createWorkplane(mySketch, anEntities, aParams))
1344 if (myWorkplaneID == SLVS_E_UNKNOWN) {
1345 myWorkplaneID = anEntities.back().h;
1346 // Add new workplane elements
1347 std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
1348 for (; aParIter != aParams.end(); aParIter++) {
1349 aParIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
1350 aParIter->group = myID;
1351 aParIter->h = myStorage->addParameter(*aParIter);
1353 std::vector<Slvs_Entity>::iterator anEntIter = anEntities.begin();
1354 for (; anEntIter != anEntities.end(); anEntIter++) {
1355 anEntIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
1356 anEntIter->group = myID;
1357 anEntIter->wrkpl = myWorkplaneID;
1358 for (int i = 0; i < 4; i++)
1359 if (anEntIter->param[i] != SLVS_E_UNKNOWN)
1360 anEntIter->param[i] = aParams[anEntIter->param[i]-1].h;
1361 for (int i = 0; i < 4; i++)
1362 if (anEntIter->point[i] != SLVS_E_UNKNOWN)
1363 anEntIter->point[i] = anEntities[anEntIter->point[i]-1].h;
1364 anEntIter->h = myStorage->addEntity(*anEntIter);
1367 // Update existent workplane
1368 const Slvs_Entity& aWP = myStorage->getEntity(myWorkplaneID);
1369 const Slvs_Entity& anOrigin = myStorage->getEntity(aWP.point[0]);
1370 const Slvs_Entity& aNormal = myStorage->getEntity(aWP.normal);
1371 // Get parameters and update them
1372 Slvs_hParam aWPParams[7] = {
1373 anOrigin.param[0], anOrigin.param[1], anOrigin.param[2],
1374 aNormal.param[0], aNormal.param[1], aNormal.param[2], aNormal.param[3]
1376 std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
1377 for (int i = 0; aParIter != aParams.end(); aParIter++, i++) {
1378 Slvs_Param aParam = myStorage->getParameter(aWPParams[i]);
1379 aParam.val = aParIter->val;
1380 myStorage->updateParameter(aParam);
1383 return myWorkplaneID > 0;
1386 ////// ============================================================================
1387 ////// Function: changeParameter
1388 ////// Class: SketchSolver_Group
1389 ////// Purpose: create/update value of parameter
1390 ////// ============================================================================
1391 ////Slvs_hParam SketchSolver_Group::changeParameter(
1392 //// const double& theParam, std::vector<Slvs_Param>::const_iterator& thePrmIter)
1394 //// if (thePrmIter != myParams.end()) { // Parameter should be updated
1395 //// int aParamPos = thePrmIter - myParams.begin();
1396 //// if (fabs(thePrmIter->val - theParam) > tolerance) {
1397 //// myNeedToSolve = true; // parameter is changed, need to resolve constraints
1398 //// myParams[aParamPos].val = theParam;
1401 //// return myParams[aParamPos].h;
1404 //// // Newly created parameter
1405 //// Slvs_Param aParam = Slvs_MakeParam(++myParamMaxID, myID, theParam);
1406 //// myParams.push_back(aParam);
1407 //// myNeedToSolve = true;
1408 //// // The list of parameters is changed, move iterator to the end of the list to avoid problems
1409 //// thePrmIter = myParams.end();
1410 //// return aParam.h;
1413 // ============================================================================
1414 // Function: resolveConstraints
1415 // Class: SketchSolver_Group
1416 // Purpose: solve the set of constraints for the current group
1417 // ============================================================================
1418 bool SketchSolver_Group::resolveConstraints()
1420 if (!myStorage->isNeedToResolve() || isEmpty())
1423 myConstrSolver.setGroupID(myID);
1424 myStorage->initializeSolver(myConstrSolver);
1426 //// theSolver.setDraggedParameters(myTempPointWhereDragged);
1428 int aResult = myConstrSolver.solve();
1429 if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes
1430 ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
1431 for (; aConstrIter != myConstraints.end(); aConstrIter++)
1432 aConstrIter->second->refresh();
1434 //// // Obtain result into the same list of parameters
1435 //// if (!myConstrSolver.getResult(myParams))
1438 //// // We should go through the attributes map, because only attributes have valued parameters
1439 //// std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::iterator anEntIter =
1440 //// myEntityAttrMap.begin();
1441 //// for (; anEntIter != myEntityAttrMap.end(); anEntIter++) {
1442 //// if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get())
1443 //// anEntIter->first->owner()->data()->blockSendAttributeUpdated(true);
1444 //// if (updateAttribute(anEntIter->first, anEntIter->second))
1445 //// updateRelatedConstraints(anEntIter->first);
1447 //// updateFilletConstraints();
1448 //// // unblock all features then
1449 //// for (anEntIter = myEntityAttrMap.begin(); anEntIter != myEntityAttrMap.end(); anEntIter++) {
1450 //// if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get())
1451 //// anEntIter->first->owner()->data()->blockSendAttributeUpdated(false);
1453 } else if (!myConstraints.empty())
1454 Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this);
1456 removeTemporaryConstraints();
1457 //// myNeedToSolve = false;
1458 myStorage->setNeedToResolve(false);
1462 // ============================================================================
1463 // Function: mergeGroups
1464 // Class: SketchSolver_Group
1465 // Purpose: append specified group to the current group
1466 // ============================================================================
1467 void SketchSolver_Group::mergeGroups(const SketchSolver_Group& theGroup)
1469 // If specified group is empty, no need to merge
1470 if (theGroup.isEmpty())
1472 if (!myFeatureStorage)
1473 myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
1475 ConstraintConstraintMap::const_iterator aConstrIter = theGroup.myConstraints.begin();
1476 for (; aConstrIter != theGroup.myConstraints.end(); aConstrIter++)
1477 changeConstraint(aConstrIter->first);
1480 // ============================================================================
1481 // Function: splitGroup
1482 // Class: SketchSolver_Group
1483 // Purpose: divide the group into several subgroups
1484 // ============================================================================
1485 void SketchSolver_Group::splitGroup(std::vector<SketchSolver_Group*>& theCuts)
1487 // Obtain constraints, which should be separated
1488 FeatureStoragePtr aNewFeatStorage(new SketchSolver_FeatureStorage);
1489 std::vector<ConstraintPtr> anUnusedConstraints;
1490 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
1491 for ( ; aCIter != myConstraints.end(); aCIter++) {
1492 std::list<ConstraintPtr> aBaseConstraints = aCIter->second->constraints();
1493 std::list<ConstraintPtr>::iterator anIter = aBaseConstraints.begin();
1494 for (; anIter != aBaseConstraints.end(); anIter++)
1495 if (aNewFeatStorage->isInteract(*anIter)) {
1496 aNewFeatStorage->changeConstraint(*anIter);
1498 anUnusedConstraints.push_back(*anIter);
1501 std::vector<SketchSolver_Group*>::iterator aCutsIter;
1502 std::vector<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
1503 for ( ; aUnuseIt != anUnusedConstraints.end(); aUnuseIt++) {
1504 // Remove unused constraints
1505 removeConstraint(*aUnuseIt);
1506 // Try to append constraint to already existent group
1507 for (aCutsIter = theCuts.begin(); aCutsIter != theCuts.end(); aCutsIter++)
1508 if ((*aCutsIter)->isInteract(*aUnuseIt)) {
1509 (*aCutsIter)->changeConstraint(*aUnuseIt);
1512 if (aCutsIter == theCuts.end()) {
1514 SketchSolver_Group* aGroup = new SketchSolver_Group(mySketch);
1515 aGroup->changeConstraint(*aUnuseIt);
1516 theCuts.push_back(aGroup);
1521 // ============================================================================
1522 // Function: isConsistent
1523 // Class: SketchSolver_Group
1524 // Purpose: search removed entities and constraints
1525 // ============================================================================
1526 bool SketchSolver_Group::isConsistent()
1528 if (!myFeatureStorage) // no one constraint is initialized yet
1531 bool aResult = myFeatureStorage->isConsistent();
1533 // remove invalid entities
1534 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
1535 while (aCIter != myConstraints.end()) {
1536 std::list<ConstraintPtr> aConstraints = aCIter->second->constraints();
1537 std::list<ConstraintPtr>::iterator anIt = aConstraints.begin();
1538 for (; anIt != aConstraints.end(); anIt++)
1539 if (!(*anIt)->data() || !(*anIt)->data()->isValid())
1540 if (aCIter->second->remove(*anIt)) {
1541 // the constraint is fully removed, detach it from the list
1542 ConstraintConstraintMap::iterator aTmpIt = aCIter++;
1543 myFeatureStorage->removeConstraint(aTmpIt->first);
1544 myConstraints.erase(aTmpIt);
1547 if (anIt == aConstraints.end())
1554 ////// ============================================================================
1555 ////// Function: updateAttribute
1556 ////// Class: SketchSolver_Group
1557 ////// Purpose: update features of sketch after resolving constraints
1558 ////// ============================================================================
1559 ////bool SketchSolver_Group::updateAttribute(
1560 //// std::shared_ptr<ModelAPI_Attribute> theAttribute, const Slvs_hEntity& theEntityID)
1562 //// // Search the position of the first parameter of the entity
1563 //// int anEntPos = Search(theEntityID, myEntities);
1564 //// int aFirstParamPos = Search(myEntities[anEntPos].param[0], myParams);
1566 //// // Look over supported types of entities
1569 //// std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1572 //// if (fabs(aPoint->x() - myParams[aFirstParamPos].val) > tolerance
1573 //// || fabs(aPoint->y() - myParams[aFirstParamPos + 1].val) > tolerance
1574 //// || fabs(aPoint->z() - myParams[aFirstParamPos + 2].val) > tolerance) {
1575 //// aPoint->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val,
1576 //// myParams[aFirstParamPos + 2].val);
1583 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
1584 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
1585 //// if (aPoint2D) {
1586 //// if (fabs(aPoint2D->x() - myParams[aFirstParamPos].val) > tolerance
1587 //// || fabs(aPoint2D->y() - myParams[aFirstParamPos + 1].val) > tolerance) {
1588 //// aPoint2D->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val);
1594 //// // Scalar value
1595 //// AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
1597 //// if (fabs(aScalar->value() - myParams[aFirstParamPos].val) > tolerance) {
1598 //// aScalar->setValue(myParams[aFirstParamPos].val);
1604 //// /// \todo Support other types of entities
1608 ////// ============================================================================
1609 ////// Function: updateEntityIfPossible
1610 ////// Class: SketchSolver_Group
1611 ////// Purpose: search the entity in this group and update it
1612 ////// ============================================================================
1613 ////void SketchSolver_Group::updateEntityIfPossible(
1614 //// std::shared_ptr<ModelAPI_Attribute> theEntity)
1616 //// if (myEntityAttrMap.find(theEntity) != myEntityAttrMap.end()) {
1617 //// // If the attribute is a point and it is changed (the group needs to rebuild),
1618 //// // probably user has dragged this point into this position,
1619 //// // so it is necessary to add constraint which will guarantee the point will not change
1621 //// // Store myNeedToSolve flag to verify the entity is really changed
1622 //// bool aNeedToSolveCopy = myNeedToSolve;
1623 //// myNeedToSolve = false;
1625 //// changeEntity(theEntity);
1627 //// if (myNeedToSolve) // the entity is changed
1629 //// // Verify the entity is a point and add temporary constraint of permanency
1630 //// std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1632 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D = std::dynamic_pointer_cast<
1633 //// GeomDataAPI_Point2D>(theEntity);
1634 //// if (aPoint || aPoint2D)
1635 //// addTemporaryConstraintWhereDragged(theEntity);
1638 //// // Restore flag of changes
1639 //// myNeedToSolve = myNeedToSolve || aNeedToSolveCopy;
1641 //// if (myNeedToSolve)
1642 //// updateRelatedConstraints(theEntity);
1646 ////// ============================================================================
1647 ////// Function: addTemporaryConstraintWhereDragged
1648 ////// Class: SketchSolver_Group
1649 ////// Purpose: add transient constraint SLVS_C_WHERE_DRAGGED for the entity,
1650 ////// which was moved by user
1651 ////// ============================================================================
1652 ////void SketchSolver_Group::addTemporaryConstraintWhereDragged(
1653 //// std::shared_ptr<ModelAPI_Attribute> theEntity,
1654 //// bool theAllowToFit)
1656 //// // Find identifier of the entity
1657 //// std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
1658 //// myEntityAttrMap.find(theEntity);
1659 //// if (anEntIter == myEntityAttrMap.end())
1662 //// // Get identifiers of all dragged points
1663 //// std::set<Slvs_hEntity> aDraggedPntID;
1664 //// aDraggedPntID.insert(myTempPointWDrgdID);
1665 //// std::list<Slvs_hConstraint>::const_iterator aTmpCoIter = myTempConstraints.begin();
1666 //// for (; aTmpCoIter != myTempConstraints.end(); aTmpCoIter++) {
1667 //// unsigned int aConstrPos = Search(*aTmpCoIter, myConstraints);
1668 //// if (aConstrPos < myConstraints.size())
1669 //// aDraggedPntID.insert(myConstraints[aConstrPos].ptA);
1671 //// std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
1672 //// for (; aConstrIter != myConstraints.end(); aConstrIter++)
1673 //// if (aConstrIter->type == SLVS_C_WHERE_DRAGGED)
1674 //// aDraggedPntID.insert(aConstrIter->ptA);
1675 //// // Find whether there is a point coincident with theEntity, which already has SLVS_C_WHERE_DRAGGED
1676 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
1677 //// for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) {
1678 //// if (aCoPtIter->find(anEntIter->second) == aCoPtIter->end())
1679 //// continue; // the entity was not found in current set
1681 //// // Find one of already created SLVS_C_WHERE_DRAGGED constraints in current set of coincident points
1682 //// std::set<Slvs_hEntity>::const_iterator aDrgIter = aDraggedPntID.begin();
1683 //// for (; aDrgIter != aDraggedPntID.end(); aDrgIter++)
1684 //// if (aCoPtIter->find(*aDrgIter) != aCoPtIter->end())
1685 //// return; // the SLVS_C_WHERE_DRAGGED constraint already exists
1687 //// if (aDraggedPntID.find(anEntIter->second) != aDraggedPntID.end())
1690 //// // If this is a first dragged point, its parameters should be placed
1691 //// // into Slvs_System::dragged field to avoid system inconsistense
1692 //// if (myTempPointWhereDragged.empty() && theAllowToFit) {
1693 //// int anEntPos = Search(anEntIter->second, myEntities);
1694 //// Slvs_hParam* aDraggedParam = myEntities[anEntPos].param;
1695 //// for (int i = 0; i < 4; i++, aDraggedParam++)
1696 //// if (*aDraggedParam != 0)
1697 //// myTempPointWhereDragged.push_back(*aDraggedParam);
1698 //// myTempPointWDrgdID = myEntities[anEntPos].h;
1702 //// // Create additional SLVS_C_WHERE_DRAGGED constraint if myTempPointWhereDragged field is not empty
1703 //// Slvs_Constraint aWDConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED,
1704 //// myWorkplane.h, 0.0, anEntIter->second, 0, 0, 0);
1705 //// myConstraints.push_back(aWDConstr);
1706 //// myTempConstraints.push_back(aWDConstr.h);
1709 // ============================================================================
1710 // Function: removeTemporaryConstraints
1711 // Class: SketchSolver_Group
1712 // Purpose: remove all transient SLVS_C_WHERE_DRAGGED constraints after
1713 // resolving the set of constraints
1714 // ============================================================================
1715 void SketchSolver_Group::removeTemporaryConstraints()
1717 myTempConstraints.clear();
1718 // Clean lists of removed entities in the storage
1719 std::set<Slvs_hParam> aRemPar;
1720 std::set<Slvs_hEntity> aRemEnt;
1721 std::set<Slvs_hConstraint> aRemCon;
1722 myStorage->getRemoved(aRemPar, aRemEnt, aRemCon);
1725 // ============================================================================
1726 // Function: removeConstraint
1727 // Class: SketchSolver_Group
1728 // Purpose: remove constraint and all unused entities
1729 // ============================================================================
1730 void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
1732 myFeatureStorage->removeConstraint(theConstraint);
1733 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
1734 for (; aCIter != myConstraints.end(); aCIter++)
1735 if (aCIter->second->hasConstraint(theConstraint)) {
1736 if (!aCIter->second->remove(theConstraint)) // the constraint is not fully removed
1737 aCIter = myConstraints.end();
1740 if (aCIter != myConstraints.end())
1741 myConstraints.erase(aCIter);
1744 ////// ============================================================================
1745 ////// Function: removeEntitiesById
1746 ////// Class: SketchSolver_Group
1747 ////// Purpose: Removes specified entities and their parameters
1748 ////// ============================================================================
1749 ////void SketchSolver_Group::removeEntitiesById(const std::set<Slvs_hEntity>& theEntities)
1751 //// std::set<Slvs_hEntity>::const_reverse_iterator aRemIter = theEntities.rbegin();
1752 //// for (; aRemIter != theEntities.rend(); aRemIter++) {
1753 //// unsigned int anEntPos = Search(*aRemIter, myEntities);
1754 //// if (anEntPos >= myEntities.size())
1756 //// if (myEntities[anEntPos].param[0] != 0) {
1757 //// unsigned int aParamPos = Search(myEntities[anEntPos].param[0], myParams);
1758 //// if (aParamPos >= myParams.size())
1760 //// int aNbParams = 0;
1761 //// while (myEntities[anEntPos].param[aNbParams] != 0)
1763 //// if (myEntities[anEntPos].param[aNbParams - 1] == myParamMaxID)
1764 //// myParamMaxID -= aNbParams;
1765 //// myParams.erase(myParams.begin() + aParamPos, myParams.begin() + aParamPos + aNbParams);
1766 //// if (*aRemIter == myEntityMaxID)
1767 //// myEntityMaxID--;
1769 //// myEntities.erase(myEntities.begin() + anEntPos);
1770 //// myEntOfConstr.erase(myEntOfConstr.begin() + anEntPos);
1772 //// // Remove entity's ID from the lists of conincident points
1773 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
1774 //// for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++)
1775 //// aCoPtIter->erase(*aRemIter);
1779 ////// ============================================================================
1780 ////// Function: addCoincidentPoints
1781 ////// Class: SketchSolver_Group
1782 ////// Purpose: add coincident point the appropriate list of such points
1783 ////// ============================================================================
1784 ////bool SketchSolver_Group::addCoincidentPoints(const Slvs_hEntity& thePoint1,
1785 //// const Slvs_hEntity& thePoint2)
1787 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
1788 //// std::vector<std::set<Slvs_hEntity> >::iterator aFirstFound = myCoincidentPoints.end();
1789 //// while (aCoPtIter != myCoincidentPoints.end()) {
1790 //// bool isFound[2] = { // indicate which point ID was already in coincidence constraint
1791 //// aCoPtIter->find(thePoint1) != aCoPtIter->end(), aCoPtIter->find(thePoint2)
1792 //// != aCoPtIter->end(), };
1793 //// if (isFound[0] && isFound[1]) // points are already connected by coincidence constraints => no need additional one
1795 //// if ((isFound[0] && !isFound[1]) || (!isFound[0] && isFound[1])) {
1796 //// if (aFirstFound != myCoincidentPoints.end()) { // there are two groups of coincident points connected by created constraint => merge them
1797 //// int aFirstFoundShift = aFirstFound - myCoincidentPoints.begin();
1798 //// int aCurrentShift = aCoPtIter - myCoincidentPoints.begin();
1799 //// aFirstFound->insert(aCoPtIter->begin(), aCoPtIter->end());
1800 //// myCoincidentPoints.erase(aCoPtIter);
1801 //// aFirstFound = myCoincidentPoints.begin() + aFirstFoundShift;
1802 //// aCoPtIter = myCoincidentPoints.begin() + aCurrentShift;
1805 //// aCoPtIter->insert(isFound[0] ? thePoint2 : thePoint1);
1806 //// aFirstFound = aCoPtIter;
1811 //// // No points were found, need to create new set
1812 //// if (aFirstFound == myCoincidentPoints.end()) {
1813 //// std::set<Slvs_hEntity> aNewSet;
1814 //// aNewSet.insert(thePoint1);
1815 //// aNewSet.insert(thePoint2);
1816 //// myCoincidentPoints.push_back(aNewSet);
1822 ////// ============================================================================
1823 ////// Function: updateRelatedConstraints
1824 ////// Class: SketchSolver_Group
1825 ////// Purpose: emit the signal to update constraints
1826 ////// ============================================================================
1827 ////void SketchSolver_Group::updateRelatedConstraints(
1828 //// std::shared_ptr<ModelAPI_Attribute> theEntity) const
1830 //// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
1831 //// for (; aConstrIter != myConstraintMap.end(); aConstrIter++) {
1832 //// std::list<std::shared_ptr<ModelAPI_Attribute> > anAttributes = aConstrIter->first->data()
1833 //// ->attributes(std::string());
1835 //// std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttributes.begin();
1836 //// for (; anAttrIter != anAttributes.end(); anAttrIter++) {
1837 //// bool isUpd = (*anAttrIter == theEntity);
1838 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr = std::dynamic_pointer_cast<
1839 //// ModelAPI_AttributeRefAttr>(*anAttrIter);
1840 //// if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theEntity)
1844 //// static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
1845 //// ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent);
1852 ////void SketchSolver_Group::updateRelatedConstraintsFeature(
1853 //// std::shared_ptr<ModelAPI_Feature> theFeature) const
1855 //// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
1856 //// for (; aConstrIter != myConstraintMap.end(); aConstrIter++) {
1857 //// std::list<std::shared_ptr<ModelAPI_Attribute> > anAttributes = aConstrIter->first->data()
1858 //// ->attributes(std::string());
1860 //// std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttributes.begin();
1861 //// for (; anAttrIter != anAttributes.end(); anAttrIter++) {
1862 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr = std::dynamic_pointer_cast<
1863 //// ModelAPI_AttributeRefAttr>(*anAttrIter);
1864 //// if (aRefAttr && aRefAttr->isObject() && aRefAttr->object() == theFeature) {
1865 //// static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
1866 //// ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent);
1873 ////// ============================================================================
1874 ////// Function: updateFilletConstraints
1875 ////// Class: SketchSolver_Group
1876 ////// Purpose: change fillet arc to be less than 180 degree
1877 ////// ============================================================================
1878 ////void SketchSolver_Group::updateFilletConstraints()
1880 //// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
1881 //// for (; aConstrIter != myConstraintMap.end(); aConstrIter++)
1882 //// if (aConstrIter->first->getKind() == SketchPlugin_ConstraintFillet::ID()) {
1883 //// AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
1884 //// aConstrIter->first->data()->attribute(SketchPlugin_ConstraintFillet::ENTITY_C()));
1885 //// if (!aFilletRefList)
1887 //// ObjectPtr anArcObj = aFilletRefList->object(2);
1888 //// std::shared_ptr<GeomDataAPI_Point2D> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1889 //// anArcObj->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
1890 //// std::shared_ptr<GeomDataAPI_Point2D> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1891 //// anArcObj->data()->attribute(SketchPlugin_Arc::START_ID()));
1892 //// std::shared_ptr<GeomDataAPI_Point2D> aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1893 //// anArcObj->data()->attribute(SketchPlugin_Arc::END_ID()));
1894 //// double aCosA = aStart->x() - aCenter->x();
1895 //// double aSinA = aStart->y() - aCenter->y();
1896 //// double aCosB = aEnd->x() - aCenter->x();
1897 //// double aSinB = aEnd->y() - aCenter->y();
1898 //// if (aCosA * aSinB - aSinA * aCosB <= 0.0) {
1899 //// anArcObj->data()->blockSendAttributeUpdated(true);
1900 //// double x = aStart->x();
1901 //// double y = aStart->y();
1902 //// aStart->setValue(aEnd->x(), aEnd->y());
1903 //// aEnd->setValue(x, y);
1904 //// // Update constraint data
1905 //// changeFilletConstraint(aConstrIter->first);
1906 //// anArcObj->data()->blockSendAttributeUpdated(false);
1911 ////// ============================================================================
1912 ////// Function: makeMirrorEntity
1913 ////// Class: SketchSolver_Group
1914 ////// Purpose: change entities parameters to make them symmetric relating to the mirror line
1915 ////// ============================================================================
1916 ////void SketchSolver_Group::makeMirrorEntity(const Slvs_hEntity& theBase,
1917 //// const Slvs_hEntity& theMirror,
1918 //// const Slvs_hEntity& theMirrorLine)
1920 //// Slvs_Entity aBase = myEntities[Search(theBase, myEntities)];
1921 //// Slvs_Entity aMirror = myEntities[Search(theMirror, myEntities)];
1923 //// while (aBase.point[i] != 0 && aMirror.point[i] != 0) {
1924 //// makeMirrorEntity(aBase.point[i], aMirror.point[i], theMirrorLine);
1927 //// if (aBase.param[0] != 0 && aMirror.param[0] != 0) { // this is a point, copy it
1928 //// Slvs_Entity aMirrorLine = myEntities[Search(theMirrorLine, myEntities)];
1929 //// std::shared_ptr<GeomAPI_XY> aLinePoints[2];
1930 //// for (i = 0; i < 2; i++) {
1931 //// Slvs_Entity aPoint = myEntities[Search(aMirrorLine.point[i], myEntities)];
1932 //// int aParamPos = Search(aPoint.param[0], myParams);
1933 //// aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
1934 //// new GeomAPI_XY(myParams[aParamPos].val, myParams[1+aParamPos].val));
1936 //// int aBaseParamPos = Search(aBase.param[0], myParams);
1937 //// int aMirrorParamPos = Search(aMirror.param[0], myParams);
1938 //// std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(
1939 //// new GeomAPI_XY(myParams[aBaseParamPos].val, myParams[1+aBaseParamPos].val));
1941 //// // direction of a mirror line
1942 //// std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
1943 //// new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
1944 //// // orthogonal direction
1945 //// aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
1947 //// std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
1948 //// new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
1949 //// double aDist = aVec->dot(aDir->xy());
1950 //// std::shared_ptr<GeomAPI_XY> aMirrorPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
1952 //// myParams[aMirrorParamPos].val = aMirrorPoint->x();
1953 //// myParams[1+aMirrorParamPos].val = aMirrorPoint->y();
1957 ////// ============================================================================
1958 ////// Function: calculateMiddlePoint
1959 ////// Class: SketchSolver_Group
1960 ////// Purpose: calculates middle point on line or arc
1961 ////// ============================================================================
1962 ////void SketchSolver_Group::calculateMiddlePoint(
1963 //// const Slvs_hEntity& theEntity,
1965 //// double& theY) const
1967 //// int anInd = Search(theEntity, myEntities);
1968 //// if (myEntities[anInd].type == SLVS_E_LINE_SEGMENT) {
1969 //// int aLineParams[2];
1970 //// for (int i = 0; i < 2; i++) {
1971 //// int aPtPos = Search(myEntities[anInd].point[i], myEntities);
1972 //// aLineParams[i] = Search(myEntities[aPtPos].param[0], myParams);
1974 //// theX = 0.5 * (myParams[aLineParams[0]].val + myParams[aLineParams[1]].val);
1975 //// theY = 0.5 * (myParams[1 + aLineParams[0]].val + myParams[1 + aLineParams[1]].val);
1976 //// } else if (myEntities[anInd].type == SLVS_E_ARC_OF_CIRCLE) {
1977 //// double anArcPoint[3][2];
1978 //// for (int i = 0; i < 3; i++) {
1979 //// int aPtPos = Search(myEntities[anInd].point[i], myEntities);
1980 //// int anArcParam = Search(myEntities[aPtPos].param[0], myParams);
1981 //// anArcPoint[i][0] = myParams[anArcParam].val;
1982 //// anArcPoint[i][1] = myParams[1 + anArcParam].val;
1984 //// // project last point of arc on the arc
1985 //// double x = anArcPoint[1][0] - anArcPoint[0][0];
1986 //// double y = anArcPoint[1][1] - anArcPoint[0][1];
1987 //// double aRad = sqrt(x*x + y*y);
1988 //// x = anArcPoint[2][0] - anArcPoint[0][0];
1989 //// y = anArcPoint[2][1] - anArcPoint[0][1];
1990 //// double aNorm = sqrt(x*x + y*y);
1991 //// if (aNorm >= tolerance) {
1992 //// anArcPoint[2][0] = anArcPoint[0][0] + x * aRad / aNorm;
1993 //// anArcPoint[2][1] = anArcPoint[0][1] + y * aRad / aNorm;
1996 //// x = anArcPoint[1][0] + anArcPoint[2][0] - 2.0 * anArcPoint[0][0];
1997 //// y = anArcPoint[1][1] + anArcPoint[2][1] - 2.0 * anArcPoint[0][1];
1998 //// aNorm = sqrt(x*x + y*y);
1999 //// if (aNorm >= tolerance) {
2000 //// x *= aRad / aNorm;
2001 //// y *= aRad / aNorm;
2002 //// } else { // obtain orthogonal direction
2003 //// x = 0.5 * (anArcPoint[2][1] - anArcPoint[1][1]);
2004 //// y = -0.5 * (anArcPoint[2][0] - anArcPoint[1][0]);
2006 //// theX = anArcPoint[0][0] + x;
2007 //// theY = anArcPoint[0][1] + y;
2012 // ========================================================
2013 // ========= Auxiliary functions ===============
2014 // ========================================================
2016 template<typename T>
2017 int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
2019 int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
2020 int aVecSize = theEntities.size();
2021 while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
2023 while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
2025 if (aResIndex == -1)
2026 aResIndex = aVecSize;