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);
159 // ============================================================================
160 // Function: changeConstraint
161 // Class: SketchSolver_Group
162 // Purpose: create/update the constraint in the group
163 // ============================================================================
164 bool SketchSolver_Group::changeConstraint(
165 std::shared_ptr<SketchPlugin_Constraint> theConstraint)
167 // There is no workplane yet, something wrong
168 if (myWorkplaneID == SLVS_E_UNKNOWN)
174 if (myConstraints.find(theConstraint) == myConstraints.end()) {
175 // Add constraint to the current group
176 SolverConstraintPtr aConstraint =
177 SketchSolver_Builder::getInstance()->createConstraint(theConstraint);
180 aConstraint->setGroup(this);
181 aConstraint->setStorage(myStorage);
182 if (!aConstraint->error().empty()) {
183 if (aConstraint->error() == SketchSolver_Error::NOT_INITIALIZED())
184 return false; // some attribute are not initialized yet, don't show message
185 Events_Error::send(aConstraint->error(), this);
188 // Additional verification of coincidence of several points
189 if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
190 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
191 for (; aCIter != myConstraints.end(); aCIter++) {
192 std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoincidence =
193 std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aCIter->second);
196 std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoinc2 =
197 std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aConstraint);
198 if (aCoincidence != aCoinc2 && aCoincidence->isCoincide(aCoinc2)) {
199 aCoincidence->attach(aCoinc2);
200 aConstraint = aCoincidence;
204 myConstraints[theConstraint] = aConstraint;
207 myConstraints[theConstraint]->update();
209 if (!myFeatureStorage)
210 myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
211 myFeatureStorage->changeConstraint(theConstraint);
213 //// if (theConstraint) {
214 //// if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID())
215 //// return changeRigidConstraint(theConstraint);
216 //// if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID())
217 //// return changeMirrorConstraint(theConstraint);
218 //// if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID())
219 //// return changeFilletConstraint(theConstraint);
222 //// // Search this constraint in the current group to update it
223 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
224 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
225 //// if (aConstrMapIter != myConstraintMap.end()) {
226 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
227 //// aConstrIter = myConstraints.begin() + aConstrPos;
230 //// // Get constraint type and verify the constraint parameters are correct
231 //// SketchSolver_Constraint aConstraint(theConstraint);
232 //// int aConstrType = aConstraint.getType();
233 //// if (aConstrType == SLVS_C_UNKNOWN
234 //// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
236 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
238 //// // Create constraint parameters
239 //// double aDistance = 0.0; // scalar value of the constraint
240 //// AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
241 //// theConstraint->data()->attribute(SketchPlugin_Constraint::VALUE()));
242 //// if (aDistAttr) {
243 //// aDistance = aDistAttr->value();
244 //// // Issue #196: checking the positivity of the distance constraint
245 //// if (aDistance < tolerance &&
246 //// (aConstrType == SLVS_C_PT_PT_DISTANCE || aConstrType == SLVS_C_PT_LINE_DISTANCE))
248 //// // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter
249 //// if (aConstrType == SLVS_C_DIAMETER)
250 //// aDistance *= 2.0;
251 //// if (aConstrMapIter != myConstraintMap.end()
252 //// && fabs(aConstrIter->valA - aDistance) > tolerance) {
253 //// myNeedToSolve = true;
254 //// aConstrIter->valA = aDistance;
258 //// size_t aNbTmpConstraints = myTempConstraints.size();
259 //// Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE]; // parameters of the constraint
260 //// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
261 //// aConstrEnt[indAttr] = SLVS_E_UNKNOWN;
262 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
263 //// ModelAPI_AttributeRefAttr>(
264 //// theConstraint->data()->attribute(aConstraintAttributes[indAttr]));
265 //// if (!aConstrAttr)
268 //// // Convert the object of the attribute to the feature
269 //// FeaturePtr aFeature;
270 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
271 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
272 //// aConstrAttr->object());
275 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
276 //// aFeature = aDoc->feature(aRC);
279 //// // For the length constraint the start and end points of the line should be added to the entities list instead of line
280 //// if (aConstrType == SLVS_C_PT_PT_DISTANCE
281 //// && theConstraint->getKind().compare(SketchPlugin_ConstraintLength::ID()) == 0) {
282 //// Slvs_hEntity aLineEnt = changeEntityFeature(aFeature);
283 //// int aEntPos = Search(aLineEnt, myEntities);
284 //// aConstrEnt[indAttr++] = myEntities[aEntPos].point[0];
285 //// aConstrEnt[indAttr++] = myEntities[aEntPos].point[1];
286 //// while (indAttr < CONSTRAINT_ATTR_SIZE)
287 //// aConstrEnt[indAttr++] = 0;
288 //// break; // there should be no other entities
289 //// } else if (aConstrAttr->isObject())
290 //// aConstrEnt[indAttr] = changeEntityFeature(aFeature);
292 //// aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr());
295 //// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
296 //// // Several points may be coincident, it is not necessary to store all constraints between them.
297 //// // Try to find sequence of coincident points which connects the points of new constraint
298 //// if (aConstrType == SLVS_C_POINTS_COINCIDENT) {
299 //// if (aConstrEnt[0] == aConstrEnt[1]) // no need to add self coincidence
301 //// if (!addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) {
302 //// myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes
305 //// if (aNbTmpConstraints < myTempConstraints.size()) {
306 //// // There was added temporary constraint. Check that there is no coincident points which already rigid.
308 //// // Get list of already fixed points
309 //// std::set<Slvs_hEntity> anAlreadyFixed;
310 //// std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
311 //// for (; aCIter != myConstraints.end(); aCIter++)
312 //// if (aCIter->type == SLVS_C_WHERE_DRAGGED) {
313 //// std::list<Slvs_hConstraint>::const_iterator aTmpIt = myTempConstraints.begin();
314 //// for (; aTmpIt != myTempConstraints.end(); aTmpIt++)
315 //// if (*aTmpIt == aCIter->h)
317 //// if (aTmpIt == myTempConstraints.end())
318 //// anAlreadyFixed.insert(aCIter->ptA);
321 //// std::set<Slvs_hConstraint> aTmpConstrToDelete;
322 //// std::list<Slvs_hConstraint>::reverse_iterator aTmpIter = myTempConstraints.rbegin();
323 //// size_t aCurSize = myTempConstraints.size();
324 //// for (; aCurSize > aNbTmpConstraints && aTmpIter != myTempConstraints.rend();
325 //// aTmpIter++, aCurSize--) {
326 //// int aConstrPos = Search(*aTmpIter, myConstraints);
327 //// std::vector<std::set<Slvs_hEntity> >::const_iterator
328 //// aCoincIter = myCoincidentPoints.begin();
329 //// for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++)
330 //// if (aCoincIter->find(myConstraints[aConstrPos].ptA) != aCoincIter->end()) {
331 //// std::set<Slvs_hEntity>::const_iterator anIt;
332 //// for (anIt = aCoincIter->begin(); anIt != aCoincIter->end(); anIt++)
333 //// if (anAlreadyFixed.find(*anIt) != anAlreadyFixed.end()) {
334 //// aTmpConstrToDelete.insert(*aTmpIter);
340 //// if (!aTmpConstrToDelete.empty())
341 //// removeTemporaryConstraints(aTmpConstrToDelete);
344 //// // For the tangency constraints it is necessary to identify which points of entities are coincident
345 //// int aSlvsOtherFlag = 0;
346 //// int aSlvsOther2Flag = 0;
347 //// if (aConstrType == SLVS_C_ARC_LINE_TANGENT || aConstrType == SLVS_C_CURVE_CURVE_TANGENT) {
348 //// // Search entities used by constraint
349 //// int anEnt1Pos = Search(aConstrEnt[2], myEntities);
350 //// int anEnt2Pos = Search(aConstrEnt[3], myEntities);
351 //// // Obtain start and end points of entities
352 //// Slvs_hEntity aPointsToFind[4];
353 //// aPointsToFind[0] = myEntities[anEnt1Pos].point[1];
354 //// aPointsToFind[1]= myEntities[anEnt1Pos].point[2];
355 //// bool hasLine = (myEntities[anEnt2Pos].type == SLVS_E_LINE_SEGMENT);
356 //// aPointsToFind[2]= myEntities[anEnt2Pos].point[hasLine ? 0 : 1];
357 //// aPointsToFind[3]= myEntities[anEnt2Pos].point[hasLine ? 1 : 2];
358 //// // Search coincident points
359 //// bool isPointFound[4];
360 //// std::vector<std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
361 //// for ( ; aCPIter != myCoincidentPoints.end(); aCPIter++) {
362 //// for (int i = 0; i < 4; i++)
363 //// isPointFound[i] = (aCPIter->find(aPointsToFind[i]) != aCPIter->end());
364 //// if ((isPointFound[0] || isPointFound[1]) && (isPointFound[2] || isPointFound[3])) {
365 //// // the arc is tangent by end point
366 //// if (isPointFound[1]) aSlvsOtherFlag = 1;
367 //// // the second item is an arc and it is tangent by end point too
368 //// if (!hasLine && isPointFound[3]) aSlvsOther2Flag = 1;
372 //// if (aCPIter == myCoincidentPoints.end()) {
373 //// // There is no coincident points between tangential objects. Generate error message
374 //// Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this);
379 //// // Create SolveSpace constraint structure
380 //// Slvs_Constraint aSlvsConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
381 //// myWorkplane.h, aDistance, aConstrEnt[0],
382 //// aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]);
383 //// if (aSlvsOtherFlag != 0) aSlvsConstr.other = aSlvsOtherFlag;
384 //// if (aSlvsOther2Flag != 0) aSlvsConstr.other2 = aSlvsOther2Flag;
385 //// myConstraints.push_back(aSlvsConstr);
386 //// myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aSlvsConstr.h);
387 //// int aConstrPos = Search(aSlvsConstr.h, myConstraints);
388 //// aConstrIter = myConstraints.begin() + aConstrPos;
389 //// myNeedToSolve = true;
390 //// } else { // Attributes of constraint may be changed => update constraint
391 //// Slvs_hEntity* aCurrentAttr[] = {&aConstrIter->ptA, &aConstrIter->ptB,
392 //// &aConstrIter->entityA, &aConstrIter->entityB,
393 //// &aConstrIter->entityC, &aConstrIter->entityD};
394 //// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
395 //// if (*(aCurrentAttr[indAttr]) != aConstrEnt[indAttr])
397 //// *(aCurrentAttr[indAttr]) = aConstrEnt[indAttr];
398 //// myNeedToSolve = true;
403 //// // Update flags of entities to be used by constraints
404 //// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
405 //// if (aConstrEnt[indAttr] != 0) {
406 //// int aPos = Search(aConstrEnt[indAttr], myEntities);
407 //// myEntOfConstr[aPos] = true;
408 //// // Sub-entities should be used implcitly
409 //// Slvs_hEntity* aEntPtr = myEntities[aPos].point;
410 //// while (*aEntPtr != 0) {
411 //// aPos = Search(*aEntPtr, myEntities);
412 //// myEntOfConstr[aPos] = true;
417 //// checkConstraintConsistence(*aConstrIter);
422 bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
424 std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theFeature);
425 if (aConstraints.empty())
427 std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
428 for (; aCIter != aConstraints.end(); aCIter++) {
429 ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
430 aSolConIter->second->update();
435 void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
437 updateFeature(theFeature);
438 // Temporary rigid constraint
439 SolverConstraintPtr aConstraint =
440 SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
443 aConstraint->setGroup(this);
444 aConstraint->setStorage(myStorage);
445 myTempConstraints.insert(aConstraint);
448 ////// ============================================================================
449 ////// Function: changeRigidConstraint
450 ////// Class: SketchSolver_Group
451 ////// Purpose: create/update the "Rigid" constraint in the group
452 ////// ============================================================================
453 ////bool SketchSolver_Group::changeRigidConstraint(
454 //// std::shared_ptr<SketchPlugin_Constraint> theConstraint)
456 //// // Search this constraint in the current group to update it
457 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
458 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
459 //// if (aConstrMapIter != myConstraintMap.end()) {
460 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
461 //// aConstrIter = myConstraints.begin() + aConstrPos;
464 //// // Get constraint type and verify the constraint parameters are correct
465 //// SketchSolver_Constraint aConstraint(theConstraint);
466 //// int aConstrType = aConstraint.getType();
467 //// if (aConstrType == SLVS_C_UNKNOWN
468 //// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
470 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
472 //// Slvs_hEntity aConstrEnt = SLVS_E_UNKNOWN;
473 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
474 //// ModelAPI_AttributeRefAttr>(
475 //// theConstraint->data()->attribute(aConstraintAttributes[0]));
476 //// if (!aConstrAttr)
479 //// // Convert the object of the attribute to the feature
480 //// FeaturePtr aFeature;
481 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
482 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
483 //// aConstrAttr->object());
486 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
487 //// aFeature = aDoc->feature(aRC);
490 //// aConstrEnt = aConstrAttr->isObject() ? changeEntityFeature(aFeature) : changeEntity(aConstrAttr->attr());
492 //// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
493 //// // Check the fixed entity is not a point.
494 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
495 //// ModelAPI_AttributeRefAttr>(theConstraint->data()->attribute(aConstraintAttributes[0]));
496 //// std::shared_ptr<GeomDataAPI_Point> aPoint =
497 //// std::dynamic_pointer_cast<GeomDataAPI_Point>(aConstrAttr->attr());
498 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
499 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aConstrAttr->attr());
500 //// if (aPoint || aPoint2D) {
501 //// // Create SolveSpace constraint structure
502 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
503 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
504 //// aConstrEnt, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
505 //// myConstraints.push_back(aConstraint);
506 //// myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aConstraint.h);
507 //// int aConstrPos = Search(aConstraint.h, myConstraints);
508 //// aConstrIter = myConstraints.begin() + aConstrPos;
509 //// myNeedToSolve = true;
511 //// myConstraintMap[theConstraint] = std::vector<Slvs_hConstraint>();
513 //// // To avoid SolveSpace problems:
514 //// // * if the circle is rigid, we will fix its center and radius;
515 //// // * if the arc is rigid, we will fix its start and end points and radius.
516 //// double aRadius = 0.0;
517 //// bool isArc = false;
518 //// bool isCircle = false;
520 //// if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
521 //// std::shared_ptr<GeomDataAPI_Point2D> aCenter =
522 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
523 //// aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
524 //// std::shared_ptr<GeomDataAPI_Point2D> aStart =
525 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
526 //// aFeature->data()->attribute(SketchPlugin_Arc::START_ID()));
527 //// aRadius = aStart->pnt()->distance(aCenter->pnt());
529 //// } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
530 //// aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
531 //// aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()))->value();
532 //// isCircle = true;
536 //// // Get list of already fixed points
537 //// std::set<Slvs_hEntity> anAlreadyFixed;
538 //// std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
539 //// for (; aCIter != myConstraints.end(); aCIter++)
540 //// if (aCIter->type == SLVS_C_WHERE_DRAGGED)
541 //// anAlreadyFixed.insert(aCIter->ptA);
543 //// // Create constraints to fix the parameters of the entity
544 //// int aEntPos = Search(aConstrEnt, myEntities);
545 //// Slvs_hEntity* aPointsPtr = myEntities[aEntPos].point;
546 //// if (isArc) aPointsPtr++; // avoid to fix center of arc
547 //// while (*aPointsPtr != 0) {
548 //// // Avoid to create additional "Rigid" constraints for coincident points
549 //// bool isCoincAlreadyFixed = false;
550 //// if (!anAlreadyFixed.empty()) {
551 //// if (anAlreadyFixed.find(*aPointsPtr) != anAlreadyFixed.end())
552 //// isCoincAlreadyFixed = true;
554 //// std::vector<std::set<Slvs_hEntity> >::const_iterator aCoincIter =
555 //// myCoincidentPoints.begin();
556 //// for (; !isCoincAlreadyFixed && aCoincIter != myCoincidentPoints.end(); aCoincIter++) {
557 //// if (aCoincIter->find(*aPointsPtr) == aCoincIter->end())
559 //// std::set<Slvs_hEntity>::const_iterator anIter = anAlreadyFixed.begin();
560 //// for (; !isCoincAlreadyFixed && anIter != anAlreadyFixed.end(); anIter++)
561 //// if (aCoincIter->find(*anIter) != aCoincIter->end())
562 //// isCoincAlreadyFixed = true;
566 //// if (!isCoincAlreadyFixed) {
567 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
568 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
569 //// *aPointsPtr, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
570 //// myConstraints.push_back(aConstraint);
571 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
576 //// if (isArc || isCircle) { // add radius constraint
577 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
578 //// ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, 2.0 * aRadius,
579 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aConstrEnt, SLVS_E_UNKNOWN);
580 //// myConstraints.push_back(aConstraint);
581 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
584 //// // The object is already rigid, so there is no constraints added
585 //// if (myConstraintMap[theConstraint].empty()) {
586 //// myConstraintMap.erase(theConstraint);
587 //// myNeedToSolve = false;
590 //// myNeedToSolve = true;
596 ////// ============================================================================
597 ////// Function: changeMirrorConstraint
598 ////// Class: SketchSolver_Group
599 ////// Purpose: create/update the "Mirror" constraint in the group
600 ////// ============================================================================
601 ////bool SketchSolver_Group::changeMirrorConstraint(
602 //// std::shared_ptr<SketchPlugin_Constraint> theConstraint)
604 //// DataPtr aConstrData = theConstraint->data();
606 //// // Search this constraint in the current group to update it
607 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
608 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
609 //// if (aConstrMapIter != myConstraintMap.end()) {
610 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
611 //// aConstrIter = myConstraints.begin() + aConstrPos;
614 //// // Get constraint type and verify the constraint parameters are correct
615 //// SketchSolver_Constraint aConstraint(theConstraint);
616 //// int aConstrType = aConstraint.getType();
617 //// if (aConstrType == SLVS_C_UNKNOWN
618 //// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
620 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
622 //// Slvs_hEntity aMirrorLineEnt = SLVS_E_UNKNOWN;
623 //// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
624 //// aConstrData->attribute(aConstraintAttributes[0]));
625 //// if (!aConstrAttr)
628 //// // Convert the object of the attribute to the feature
629 //// FeaturePtr aMirrorLineFeat;
630 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
631 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
632 //// aConstrAttr->object());
635 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
636 //// aMirrorLineFeat = aDoc->feature(aRC);
638 //// aMirrorLineEnt = aConstrAttr->isObject() ?
639 //// changeEntityFeature(aMirrorLineFeat) : changeEntity(aConstrAttr->attr());
641 //// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
642 //// // Append symmetric constraint for each point of mirroring features
643 //// AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
644 //// aConstrData->attribute(aConstraintAttributes[1]));
645 //// AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
646 //// aConstrData->attribute(aConstraintAttributes[2]));
647 //// if (!aBaseRefList || !aMirroredRefList)
650 //// std::list<ObjectPtr> aBaseList = aBaseRefList->list();
651 //// std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
652 //// if (aBaseList.size() != aMirroredList.size())
655 //// myConstraintMap[theConstraint] = std::vector<Slvs_hConstraint>();
657 //// FeaturePtr aBaseFeature, aMirrorFeature;
658 //// ResultConstructionPtr aRC;
659 //// std::list<ObjectPtr>::iterator aBaseIter = aBaseList.begin();
660 //// std::list<ObjectPtr>::iterator aMirIter = aMirroredList.begin();
661 //// for ( ; aBaseIter != aBaseList.end(); aBaseIter++, aMirIter++) {
662 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aBaseIter);
663 //// aBaseFeature = aRC ? aRC->document()->feature(aRC) :
664 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aBaseIter);
665 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirIter);
666 //// aMirrorFeature = aRC ? aRC->document()->feature(aRC) :
667 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirIter);
669 //// if (!aBaseFeature || !aMirrorFeature ||
670 //// aBaseFeature->getKind() != aMirrorFeature->getKind())
672 //// Slvs_hEntity aBaseEnt = changeEntityFeature(aBaseFeature);
673 //// Slvs_hEntity aMirrorEnt = changeEntityFeature(aMirrorFeature);
674 //// // Make aMirrorEnt parameters to be symmetric with aBaseEnt
675 //// makeMirrorEntity(aBaseEnt, aMirrorEnt, aMirrorLineEnt);
677 //// if (aBaseFeature->getKind() == SketchPlugin_Point::ID()) {
678 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
679 //// myWorkplane.h, 0.0, aBaseEnt, aMirrorEnt, aMirrorLineEnt, SLVS_E_UNKNOWN);
680 //// myConstraints.push_back(aConstraint);
681 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
683 //// int aBasePos = Search(aBaseEnt, myEntities);
684 //// int aMirrorPos = Search(aMirrorEnt, myEntities);
685 //// if (aBaseFeature->getKind() == SketchPlugin_Line::ID()) {
686 //// for (int ind = 0; ind < 2; ind++) {
687 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
688 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
689 //// myEntities[aBasePos].point[ind], myEntities[aMirrorPos].point[ind],
690 //// aMirrorLineEnt, SLVS_E_UNKNOWN);
691 //// myConstraints.push_back(aConstraint);
692 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
694 //// } else if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
695 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
696 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
697 //// myEntities[aBasePos].point[0], myEntities[aMirrorPos].point[0],
698 //// aMirrorLineEnt, SLVS_E_UNKNOWN);
699 //// myConstraints.push_back(aConstraint);
700 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
701 //// // Additional constraint for equal radii
702 //// Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
703 //// ++myConstrMaxID, myID, SLVS_C_EQUAL_RADIUS, myWorkplane.h, 0.0,
704 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseEnt, aMirrorEnt);
705 //// myConstraints.push_back(anEqRadConstr);
706 //// myConstraintMap[theConstraint].push_back(anEqRadConstr.h);
707 //// } else if (aBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
708 //// // Workaround to avoid problems in SolveSpace.
709 //// // The symmetry of two arcs will be done using symmetry of three points on these arcs:
710 //// // start point, end point, and any other point on the arc
711 //// Slvs_hEntity aBaseArcPoints[3] = {
712 //// myEntities[aBasePos].point[1],
713 //// myEntities[aBasePos].point[2],
714 //// SLVS_E_UNKNOWN};
715 //// Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point
716 //// myEntities[aMirrorPos].point[2],
717 //// myEntities[aMirrorPos].point[1],
718 //// SLVS_E_UNKNOWN};
719 //// Slvs_hEntity aBothArcs[2] = {aBaseEnt, aMirrorEnt};
720 //// Slvs_hEntity aBothMiddlePoints[2];
721 //// for (int i = 0; i < 2; i++) {
723 //// calculateMiddlePoint(aBothArcs[i], x, y);
724 //// std::vector<Slvs_Param>::iterator aParamIter = myParams.end();
725 //// Slvs_hParam u = changeParameter(x, aParamIter);
726 //// Slvs_hParam v = changeParameter(y, aParamIter);
727 //// Slvs_Entity aPoint = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, u, v);
728 //// myEntities.push_back(aPoint);
729 //// aBothMiddlePoints[i] = aPoint.h;
730 //// // additional constraint point-on-curve
731 //// Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
732 //// ++myConstrMaxID, myID, SLVS_C_PT_ON_CIRCLE, myWorkplane.h, 0.0,
733 //// aPoint.h, SLVS_E_UNKNOWN, aBothArcs[i], SLVS_E_UNKNOWN);
734 //// myConstraints.push_back(aPonCircConstr);
735 //// myConstraintMap[theConstraint].push_back(aPonCircConstr.h);
738 //// aBaseArcPoints[2] = aBothMiddlePoints[0];
739 //// aMirrorArcPoints[2] = aBothMiddlePoints[1];
740 //// for (int ind = 0; ind < 3; ind++) {
741 //// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
742 //// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
743 //// aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLineEnt, SLVS_E_UNKNOWN);
744 //// myConstraints.push_back(aConstraint);
745 //// myConstraintMap[theConstraint].push_back(aConstraint.h);
751 //// // Set the mirror line unchanged during constraint recalculation
752 //// int aMirrorLinePos = Search(aMirrorLineEnt, myEntities);
753 //// Slvs_Constraint aRigidStart = Slvs_MakeConstraint(
754 //// ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0,
755 //// myEntities[aMirrorLinePos].point[0], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
756 //// myConstraints.push_back(aRigidStart);
757 //// myConstraintMap[theConstraint].push_back(aRigidStart.h);
758 //// Slvs_Constraint aRigidEnd = Slvs_MakeConstraint(
759 //// ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0,
760 //// myEntities[aMirrorLinePos].point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
761 //// myConstraints.push_back(aRigidEnd);
762 //// myConstraintMap[theConstraint].push_back(aRigidEnd.h);
764 //// // Add temporary constraints for initial objects to be unchanged
765 //// for (aBaseIter = aBaseList.begin(); aBaseIter != aBaseList.end(); aBaseIter++) {
766 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aBaseIter);
767 //// aBaseFeature = aRC ? aRC->document()->feature(aRC) :
768 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aBaseIter);
769 //// if (!aBaseFeature) continue;
770 //// std::list<AttributePtr> aPoints = aBaseFeature->data()->attributes(GeomDataAPI_Point2D::type());
771 //// std::list<AttributePtr>::iterator anIt = aPoints.begin();
772 //// for ( ; anIt != aPoints.end(); anIt++) {
773 //// // Arcs are fixed by center and start points only (to avoid solving errors in SolveSpace)
774 //// if (aBaseFeature->getKind() == SketchPlugin_Arc::ID() &&
775 //// (*anIt)->id() == SketchPlugin_Arc::END_ID())
777 //// addTemporaryConstraintWhereDragged(*anIt);
784 ////// ============================================================================
785 ////// Function: changeFilletConstraint
786 ////// Class: SketchSolver_Group
787 ////// Purpose: create/update the "Fillet" constraint in the group
788 ////// ============================================================================
789 ////bool SketchSolver_Group::changeFilletConstraint(
790 //// std::shared_ptr<SketchPlugin_Constraint> theConstraint)
792 //// DataPtr aConstrData = theConstraint->data();
794 //// // Search this constraint in the current group to update it
795 //// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
796 //// std::vector<Slvs_Constraint>::iterator aConstrIter;
797 //// if (aConstrMapIter != myConstraintMap.end()) {
798 //// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
799 //// aConstrIter = myConstraints.begin() + aConstrPos;
802 //// // Get constraint type and verify the constraint parameters are correct
803 //// SketchSolver_Constraint aConstraint(theConstraint);
804 //// int aConstrType = aConstraint.getType();
805 //// if (aConstrType == SLVS_C_UNKNOWN)
807 //// const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
809 //// // Obtain hEntity for basic objects of fillet
810 //// Slvs_hEntity aBaseObject[2];
811 //// FeaturePtr aBaseFeature[2];
812 //// for (unsigned int indAttr = 0; indAttr < 2; indAttr++) {
813 //// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
814 //// aConstrData->attribute(aConstraintAttributes[indAttr]));
815 //// if (!aConstrAttr)
817 //// if (aConstrAttr->isObject() && aConstrAttr->object()) {
818 //// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
819 //// aConstrAttr->object());
822 //// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
823 //// aBaseFeature[indAttr] = aDoc->feature(aRC);
825 //// aBaseObject[indAttr] = aConstrAttr->isObject() ?
826 //// changeEntityFeature(aBaseFeature[indAttr]) : changeEntity(aConstrAttr->attr());
828 //// // Check the base entities have a coincident point
829 //// int aBaseObjInd[2] = {
830 //// Search(aBaseObject[0], myEntities),
831 //// Search(aBaseObject[1], myEntities)
833 //// int aShift[2] = { // shift for calculating correct start and end points for different types of objects
834 //// myEntities[aBaseObjInd[0]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0,
835 //// myEntities[aBaseObjInd[1]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0,
837 //// Slvs_hEntity aFirstObjPoints[2] = { // indices of start and end point of first object
838 //// myEntities[aBaseObjInd[0]].point[aShift[0]],
839 //// myEntities[aBaseObjInd[0]].point[1+aShift[0]]
841 //// Slvs_hEntity aSecondObjPoints[2] = { // indices of start and end point of second object
842 //// myEntities[aBaseObjInd[1]].point[aShift[1]],
843 //// myEntities[aBaseObjInd[1]].point[1+aShift[1]]
845 //// bool isCoincidentFound = false;
846 //// int aBaseCoincInd[2] = {0, 0}; // indices in aFirstObjPoint and aSecondObjPoint identifying coincident points
847 //// std::vector<std::set<Slvs_hEntity> >::iterator aCPIter = myCoincidentPoints.begin();
848 //// for ( ; aCPIter != myCoincidentPoints.end() && !isCoincidentFound; aCPIter++)
849 //// for (int ind1 = 0; ind1 < 2 && !isCoincidentFound; ind1++)
850 //// for (int ind2 = 0; ind2 < 2 && !isCoincidentFound; ind2++)
851 //// if (aCPIter->find(aFirstObjPoints[ind1]) != aCPIter->end() &&
852 //// aCPIter->find(aSecondObjPoints[ind2]) != aCPIter->end()) {
853 //// aBaseCoincInd[0] = ind1;
854 //// aBaseCoincInd[1] = ind2;
855 //// isCoincidentFound = true;
857 //// if (!isCoincidentFound) {
858 //// // There is no coincident points between objects. Generate error message
859 //// Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this);
863 //// // Create fillet entities
864 //// // - first object is placed on the first base
865 //// // - second object is on the second base
866 //// // - third object is a filleting arc
867 //// static const int aNbFilletEnt = 3;
868 //// Slvs_hEntity aFilletEnt[aNbFilletEnt];
869 //// int aFilletObjInd[aNbFilletEnt];
870 //// AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
871 //// aConstrData->attribute(aConstraintAttributes[2]));
872 //// if (!aFilletRefList)
874 //// std::list<ObjectPtr> aFilletList = aFilletRefList->list();
875 //// if (aFilletList.size() < aNbFilletEnt)
877 //// FeaturePtr aFilletFeature;
878 //// ResultConstructionPtr aRC;
879 //// std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
880 //// for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
881 //// aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
882 //// aFilletFeature = aRC ? aRC->document()->feature(aRC) :
883 //// std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFilIter);
884 //// if (!aFilletFeature)
886 //// aFilletEnt[indEnt] = changeEntityFeature(aFilletFeature);
887 //// aFilletObjInd[indEnt] = Search(aFilletEnt[indEnt], myEntities);
889 //// // At first time, for correct result, move floating points of fillet on the middle points of base objects
890 //// if (myConstraintMap.find(theConstraint) == myConstraintMap.end()) {
891 //// double anArcPoints[6];
892 //// for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
893 //// int anIndShift = myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
894 //// int aPointsPos[2] = {
895 //// Search(myEntities[aFilletObjInd[indEnt]].point[anIndShift], myEntities),
896 //// Search(myEntities[aFilletObjInd[indEnt]].point[1+anIndShift], myEntities)
898 //// int aParamPos[2] = {
899 //// Search(myEntities[aPointsPos[0]].param[0], myParams),
900 //// Search(myEntities[aPointsPos[1]].param[0], myParams)
902 //// int anIndex = aParamPos[aBaseCoincInd[indEnt]];
903 //// if (anIndShift == 0) {
904 //// myParams[anIndex].val =
905 //// 0.5 * (myParams[aParamPos[0]].val + myParams[aParamPos[1]].val);
906 //// myParams[1 + anIndex].val =
907 //// 0.5 * (myParams[1 + aParamPos[0]].val + myParams[1 + aParamPos[1]].val);
908 //// } else { // place the changed point on the arc
909 //// double x = 0, y = 0;
910 //// calculateMiddlePoint(aFilletEnt[indEnt], x, y);
911 //// myParams[anIndex].val = x;
912 //// myParams[1 + anIndex].val = y;
914 //// anArcPoints[indEnt*2+2] = myParams[anIndex].val;
915 //// anArcPoints[indEnt*2+3] = myParams[1 + anIndex].val;
917 //// anArcPoints[0] = 0.5 * (anArcPoints[2] + anArcPoints[4]);
918 //// anArcPoints[1] = 0.5 * (anArcPoints[3] + anArcPoints[5]);
919 //// for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
920 //// int aPtPos = Search(myEntities[aFilletObjInd[2]].point[indArcPt], myEntities);
921 //// int aParamPos = Search(myEntities[aPtPos].param[0], myParams);
922 //// myParams[aParamPos].val = anArcPoints[indArcPt * 2];
923 //// myParams[aParamPos + 1].val = anArcPoints[indArcPt * 2 + 1];
927 //// // Check the fillet arc which point to be connected to
928 //// bool isArcInversed = false; // indicates that start and end points of arc should be connected to second and first object respectively
929 //// Slvs_hEntity hEnt = myEntities[aFilletObjInd[2]].point[1];
930 //// int aPos = Search(hEnt, myEntities);
931 //// Slvs_hParam anArcStartPoint = myEntities[aPos].param[0];
932 //// aPos = Search(anArcStartPoint, myParams);
933 //// double anArcPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val};
934 //// double aSqDistances[2];
936 //// for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
937 //// aPtInd = aBaseCoincInd[indEnt]+aShift[indEnt];
938 //// hEnt = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
939 //// aPos = Search(hEnt, myEntities);
940 //// Slvs_hParam anObjectPoint = myEntities[aPos].param[0];
941 //// aPos = Search(anObjectPoint, myParams);
942 //// double aPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val};
943 //// aSqDistances[indEnt] =
944 //// (anArcPtCoord[0] - aPtCoord[0]) * (anArcPtCoord[0] - aPtCoord[0]) +
945 //// (anArcPtCoord[1] - aPtCoord[1]) * (anArcPtCoord[1] - aPtCoord[1]);
947 //// if (aSqDistances[1] < aSqDistances[0])
948 //// isArcInversed = true;
950 //// // Create list of constraints to generate fillet
951 //// std::vector<Slvs_hConstraint> aConstrList;
952 //// bool isExists = myConstraintMap.find(theConstraint) != myConstraintMap.end(); // constraint already exists
953 //// std::vector<Slvs_hConstraint>::iterator aCMapIter =
954 //// isExists ? myConstraintMap[theConstraint].begin() : aConstrList.begin();
955 //// int aCurConstrPos = isExists ? Search(*aCMapIter, myConstraints) : 0;
956 //// for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
957 //// // one point of fillet object should be coincident with the point on base, non-coincident with another base object
958 //// aPtInd = 1-aBaseCoincInd[indEnt]+aShift[indEnt]; // (1-aBaseCoincInd[indEnt]) = index of non-coincident point, aShift is used to process all types of shapes
959 //// Slvs_hEntity aPtBase = myEntities[aBaseObjInd[indEnt]].point[aPtInd];
960 //// Slvs_hEntity aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
962 //// myConstraints[aCurConstrPos].ptA = aPtBase;
963 //// myConstraints[aCurConstrPos].ptB = aPtFillet;
965 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
967 //// Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
968 //// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
969 //// 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
970 //// myConstraints.push_back(aCoincConstr);
971 //// aConstrList.push_back(aCoincConstr.h);
974 //// // another point of fillet object should be placed on the base object
975 //// Slvs_Constraint aPonCurveConstr;
976 //// int aTangentType;
977 //// if (myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE) {
978 //// // centers of arcs should be coincident
979 //// aPtBase = myEntities[aBaseObjInd[indEnt]].point[0];
980 //// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[0];
982 //// myConstraints[aCurConstrPos].ptA = aPtBase;
983 //// myConstraints[aCurConstrPos].ptB = aPtFillet;
985 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
987 //// aPonCurveConstr = Slvs_MakeConstraint(
988 //// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
989 //// 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
991 //// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[1+aBaseCoincInd[indEnt]]; // !!! will be used below
992 //// aTangentType = SLVS_C_CURVE_CURVE_TANGENT;
994 //// aPtInd = aBaseCoincInd[indEnt];
995 //// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
997 //// myConstraints[aCurConstrPos].ptA = aPtFillet;
999 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
1001 //// aPonCurveConstr = Slvs_MakeConstraint(
1002 //// ++myConstrMaxID, myID, SLVS_C_PT_ON_LINE, myWorkplane.h,
1003 //// 0, aPtFillet, SLVS_E_UNKNOWN, aBaseObject[indEnt], SLVS_E_UNKNOWN);
1005 //// aTangentType = SLVS_C_ARC_LINE_TANGENT;
1007 //// if (!isExists) {
1008 //// myConstraints.push_back(aPonCurveConstr);
1009 //// aConstrList.push_back(aPonCurveConstr.h);
1012 //// // Bound point of fillet arc should be tangently coincident with a bound point of fillet object
1013 //// aPtInd = 1 + (isArcInversed ? 1-indEnt : indEnt);
1014 //// Slvs_hEntity aPtArc = myEntities[aFilletObjInd[2]].point[aPtInd];
1015 //// if (isExists) {
1016 //// myConstraints[aCurConstrPos].ptA = aPtArc;
1017 //// myConstraints[aCurConstrPos].ptB = aPtFillet;
1019 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
1020 //// myConstraints[aCurConstrPos].entityA = aFilletEnt[2];
1021 //// myConstraints[aCurConstrPos].entityB = aFilletEnt[indEnt];
1022 //// myConstraints[aCurConstrPos].other = (isArcInversed ? 1-indEnt : indEnt);
1024 //// aCurConstrPos = Search(*aCMapIter, myConstraints);
1026 //// Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
1027 //// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
1028 //// 0, aPtArc, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
1029 //// myConstraints.push_back(aCoincConstr);
1030 //// aConstrList.push_back(aCoincConstr.h);
1031 //// Slvs_Constraint aTangency = Slvs_MakeConstraint(
1032 //// ++myConstrMaxID, myID, aTangentType, myWorkplane.h,
1033 //// 0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], aFilletEnt[indEnt]);
1034 //// aTangency.other = (isArcInversed ? 1-indEnt : indEnt);
1035 //// aTangency.other2 = aTangentType == SLVS_C_CURVE_CURVE_TANGENT ? aBaseCoincInd[indEnt] : 0;
1036 //// myConstraints.push_back(aTangency);
1037 //// aConstrList.push_back(aTangency.h);
1041 //// // Additional constraint for fillet diameter
1042 //// double aRadius = 0.0; // scalar value of the constraint
1043 //// AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
1044 //// aConstrData->attribute(SketchPlugin_Constraint::VALUE()));
1045 //// aRadius = aDistAttr->value();
1046 //// if (isExists) {
1047 //// myConstraints[aCurConstrPos].entityA = aFilletEnt[2];
1048 //// myConstraints[aCurConstrPos].valA = aRadius * 2.0;
1051 //// Slvs_Constraint aDiamConstr = Slvs_MakeConstraint(
1052 //// ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, aRadius * 2.0,
1053 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], SLVS_E_UNKNOWN);
1054 //// myConstraints.push_back(aDiamConstr);
1055 //// aConstrList.push_back(aDiamConstr.h);
1057 //// myConstraintMap[theConstraint] = aConstrList;
1060 //// // Additional temporary constraints for base objects to be fixed
1061 //// for (unsigned int indAttr = 0; indAttr < 2; indAttr++) {
1062 //// if (!aBaseFeature[indAttr]) {
1063 //// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1064 //// aConstrData->attribute(aConstraintAttributes[indAttr]));
1065 //// addTemporaryConstraintWhereDragged(aConstrAttr->attr());
1068 //// std::list<AttributePtr> anAttributes =
1069 //// aBaseFeature[indAttr]->data()->attributes(GeomDataAPI_Point2D::type());
1070 //// std::list<AttributePtr>::iterator anIt = anAttributes.begin();
1071 //// for ( ; anIt != anAttributes.end(); anIt++) {
1072 //// // Arc should be fixed by center and start points only (to avoid "conflicting constraints" message)
1073 //// if (aBaseFeature[indAttr]->getKind() == SketchPlugin_Arc::ID() &&
1074 //// (*anIt)->id() == SketchPlugin_Arc::END_ID())
1076 //// addTemporaryConstraintWhereDragged(*anIt);
1082 ////// ============================================================================
1083 ////// Function: changeEntity
1084 ////// Class: SketchSolver_Group
1085 ////// Purpose: create/update the element affected by any constraint
1086 ////// ============================================================================
1087 ////Slvs_hEntity SketchSolver_Group::changeEntity(
1088 //// std::shared_ptr<ModelAPI_Attribute> theEntity)
1090 //// // If the entity is already in the group, try to find it
1091 //// std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator aEntIter =
1092 //// myEntityAttrMap.find(theEntity);
1094 //// std::vector<Slvs_Param>::const_iterator aParamIter; // looks at first parameter of already existent entity or at the end of vector otherwise
1095 //// if (aEntIter == myEntityAttrMap.end()) // no such entity => should be created
1096 //// aParamIter = myParams.end();
1097 //// else { // the entity already exists
1098 //// aEntPos = Search(aEntIter->second, myEntities);
1099 //// int aParamPos = Search(myEntities[aEntPos].param[0], myParams);
1100 //// aParamIter = myParams.begin() + aParamPos;
1102 //// const bool isEntExists = (aEntIter != myEntityAttrMap.end()); // defines that the entity already exists
1103 //// const bool isNeedToSolve = myNeedToSolve;
1104 //// myNeedToSolve = false;
1106 //// if (isEntExists) {
1107 //// // Verify that the entity is not used by "Rigid" constraint.
1108 //// // If it is used, the object should not move.
1109 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoincIter = myCoincidentPoints.begin();
1110 //// for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++)
1111 //// if (aCoincIter->find(aEntIter->second) != aCoincIter->end())
1113 //// std::set<Slvs_hEntity> aCoincident;
1114 //// if (aCoincIter != myCoincidentPoints.end()) {
1115 //// aCoincident = *aCoincIter;
1116 //// aCoincident.erase(aEntIter->second);
1118 //// std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
1119 //// for (; aConstrIter != myConstraints.end(); aConstrIter++)
1120 //// if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
1121 //// aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
1122 //// myNeedToSolve = true;
1123 //// return aEntIter->second;
1128 //// // Look over supported types of entities
1129 //// Slvs_Entity aNewEntity;
1130 //// aNewEntity.h = SLVS_E_UNKNOWN;
1133 //// std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1136 //// Slvs_hParam aX = changeParameter(aPoint->x(), aParamIter);
1137 //// Slvs_hParam aY = changeParameter(aPoint->y(), aParamIter);
1138 //// Slvs_hParam aZ = changeParameter(aPoint->z(), aParamIter);
1139 //// if (!isEntExists) // New entity
1140 //// aNewEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ);
1142 //// // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
1143 //// if (myWorkplane.h == SLVS_E_UNKNOWN)
1144 //// return SLVS_E_UNKNOWN;
1147 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
1148 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
1149 //// if (aPoint2D) {
1150 //// Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter);
1151 //// Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter);
1152 //// if (!isEntExists) // New entity
1153 //// aNewEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV);
1155 //// // Scalar value (used for the distance entities)
1156 //// AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
1158 //// Slvs_hParam aValue = changeParameter(aScalar->value(), aParamIter);
1159 //// if (!isEntExists) // New entity
1160 //// aNewEntity = Slvs_MakeDistance(++myEntityMaxID, myID, myWorkplane.h, aValue);
1164 //// /// \todo Other types of entities
1166 //// Slvs_hEntity aResult = SLVS_E_UNKNOWN; // Unsupported or wrong entity type
1168 //// if (isEntExists) {
1169 //// myNeedToSolve = myNeedToSolve || isNeedToSolve;
1170 //// aResult = aEntIter->second;
1171 //// } else if (aNewEntity.h != SLVS_E_UNKNOWN) {
1172 //// myEntities.push_back(aNewEntity);
1173 //// myEntOfConstr.push_back(false);
1174 //// myEntityAttrMap[theEntity] = aNewEntity.h;
1175 //// aResult = aNewEntity.h;
1178 //// // If the attribute was changed by the user, we need to fix it before solving
1179 //// if (myNeedToSolve && theEntity->isImmutable())
1180 //// addTemporaryConstraintWhereDragged(theEntity, false);
1182 //// return aResult;
1185 ////// ============================================================================
1186 ////// Function: changeEntity
1187 ////// Class: SketchSolver_Group
1188 ////// Purpose: create/update the element defined by the feature affected by any constraint
1189 ////// ============================================================================
1190 ////Slvs_hEntity SketchSolver_Group::changeEntityFeature(FeaturePtr theEntity)
1192 //// if (!theEntity->data()->isValid())
1193 //// return SLVS_E_UNKNOWN;
1194 //// // If the entity is already in the group, try to find it
1195 //// std::map<FeaturePtr, Slvs_hEntity>::const_iterator aEntIter = myEntityFeatMap.find(theEntity);
1196 //// // defines that the entity already exists
1197 //// const bool isEntExists = (myEntityFeatMap.find(theEntity) != myEntityFeatMap.end());
1199 //// Slvs_Entity aNewEntity;
1200 //// aNewEntity.h = SLVS_E_UNKNOWN;
1202 //// // SketchPlugin features
1203 //// std::shared_ptr<SketchPlugin_Feature> aFeature = std::dynamic_pointer_cast<
1204 //// SketchPlugin_Feature>(theEntity);
1205 //// if (aFeature) { // Verify the feature by its kind
1206 //// const std::string& aFeatureKind = aFeature->getKind();
1207 //// AttributePtr anAttribute;
1210 //// if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) {
1211 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID());
1212 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1213 //// Slvs_hEntity aStart = changeEntity(anAttribute);
1215 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID());
1216 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1217 //// Slvs_hEntity aEnd = changeEntity(anAttribute);
1219 //// if (!isEntExists) // New entity
1220 //// aNewEntity = Slvs_MakeLineSegment(++myEntityMaxID, myID, myWorkplane.h, aStart, aEnd);
1223 //// else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) {
1224 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID());
1225 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1226 //// Slvs_hEntity aCenter = changeEntity(anAttribute);
1228 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID());
1229 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1230 //// Slvs_hEntity aRadius = changeEntity(anAttribute);
1232 //// if (!isEntExists) // New entity
1233 //// aNewEntity = Slvs_MakeCircle(++myEntityMaxID, myID, myWorkplane.h, aCenter,
1234 //// myWorkplane.normal, aRadius);
1237 //// else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) {
1238 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID());
1239 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1240 //// Slvs_hEntity aCenter = changeEntity(anAttribute);
1242 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID());
1243 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1244 //// Slvs_hEntity aStart = changeEntity(anAttribute);
1246 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID());
1247 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1248 //// Slvs_hEntity aEnd = changeEntity(anAttribute);
1250 //// if (!isEntExists)
1251 //// aNewEntity = Slvs_MakeArcOfCircle(++myEntityMaxID, myID, myWorkplane.h,
1252 //// myWorkplane.normal, aCenter, aStart, aEnd);
1254 //// // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
1255 //// else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) {
1256 //// anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID());
1257 //// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
1258 //// Slvs_hEntity aPoint = changeEntity(anAttribute);
1260 //// if (isEntExists)
1261 //// return aEntIter->second;
1263 //// // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
1264 //// myEntityFeatMap[theEntity] = aPoint;
1265 //// myNeedToSolve = true;
1269 //// /// \todo Other types of features
1271 //// if (isEntExists)
1272 //// return aEntIter->second;
1274 //// if (aNewEntity.h != SLVS_E_UNKNOWN) {
1275 //// myEntities.push_back(aNewEntity);
1276 //// myEntOfConstr.push_back(false);
1277 //// myEntityFeatMap[theEntity] = aNewEntity.h;
1278 //// myNeedToSolve = true;
1279 //// return aNewEntity.h;
1282 //// // Unsupported or wrong entity type
1283 //// return SLVS_E_UNKNOWN;
1286 // ============================================================================
1287 // Function: addWorkplane
1288 // Class: SketchSolver_Group
1289 // Purpose: create workplane for the group
1290 // ============================================================================
1291 bool SketchSolver_Group::addWorkplane(CompositeFeaturePtr theSketch)
1293 if (myWorkplaneID != SLVS_E_UNKNOWN || theSketch->getKind() != SketchPlugin_Sketch::ID())
1294 return false; // the workplane already exists or the function parameter is not Sketch
1296 mySketch = theSketch;
1301 // ============================================================================
1302 // Function: updateWorkplane
1303 // Class: SketchSolver_Group
1304 // Purpose: update parameters of workplane
1305 // ============================================================================
1306 bool SketchSolver_Group::updateWorkplane()
1308 if (!myStorage) // Create storage if not exists
1309 myStorage = StoragePtr(new SketchSolver_Storage);
1310 SketchSolver_Builder* aBuilder = SketchSolver_Builder::getInstance();
1312 std::vector<Slvs_Entity> anEntities;
1313 std::vector<Slvs_Param> aParams;
1314 if (!aBuilder->createWorkplane(mySketch, anEntities, aParams))
1317 if (myWorkplaneID == SLVS_E_UNKNOWN) {
1318 myWorkplaneID = anEntities.back().h;
1319 // Add new workplane elements
1320 std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
1321 for (; aParIter != aParams.end(); aParIter++) {
1322 aParIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
1323 aParIter->group = myID;
1324 aParIter->h = myStorage->addParameter(*aParIter);
1326 std::vector<Slvs_Entity>::iterator anEntIter = anEntities.begin();
1327 for (; anEntIter != anEntities.end(); anEntIter++) {
1328 anEntIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
1329 anEntIter->group = myID;
1330 anEntIter->wrkpl = myWorkplaneID;
1331 for (int i = 0; i < 4; i++)
1332 if (anEntIter->param[i] != SLVS_E_UNKNOWN)
1333 anEntIter->param[i] = aParams[anEntIter->param[i]-1].h;
1334 for (int i = 0; i < 4; i++)
1335 if (anEntIter->point[i] != SLVS_E_UNKNOWN)
1336 anEntIter->point[i] = anEntities[anEntIter->point[i]-1].h;
1337 anEntIter->h = myStorage->addEntity(*anEntIter);
1340 // Update existent workplane
1341 const Slvs_Entity& aWP = myStorage->getEntity(myWorkplaneID);
1342 const Slvs_Entity& anOrigin = myStorage->getEntity(aWP.point[0]);
1343 const Slvs_Entity& aNormal = myStorage->getEntity(aWP.normal);
1344 // Get parameters and update them
1345 Slvs_hParam aWPParams[7] = {
1346 anOrigin.param[0], anOrigin.param[1], anOrigin.param[2],
1347 aNormal.param[0], aNormal.param[1], aNormal.param[2], aNormal.param[3]
1349 std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
1350 for (int i = 0; aParIter != aParams.end(); aParIter++, i++) {
1351 Slvs_Param aParam = myStorage->getParameter(aWPParams[i]);
1352 aParam.val = aParIter->val;
1353 myStorage->updateParameter(aParam);
1356 return myWorkplaneID > 0;
1359 ////// ============================================================================
1360 ////// Function: changeParameter
1361 ////// Class: SketchSolver_Group
1362 ////// Purpose: create/update value of parameter
1363 ////// ============================================================================
1364 ////Slvs_hParam SketchSolver_Group::changeParameter(
1365 //// const double& theParam, std::vector<Slvs_Param>::const_iterator& thePrmIter)
1367 //// if (thePrmIter != myParams.end()) { // Parameter should be updated
1368 //// int aParamPos = thePrmIter - myParams.begin();
1369 //// if (fabs(thePrmIter->val - theParam) > tolerance) {
1370 //// myNeedToSolve = true; // parameter is changed, need to resolve constraints
1371 //// myParams[aParamPos].val = theParam;
1374 //// return myParams[aParamPos].h;
1377 //// // Newly created parameter
1378 //// Slvs_Param aParam = Slvs_MakeParam(++myParamMaxID, myID, theParam);
1379 //// myParams.push_back(aParam);
1380 //// myNeedToSolve = true;
1381 //// // The list of parameters is changed, move iterator to the end of the list to avoid problems
1382 //// thePrmIter = myParams.end();
1383 //// return aParam.h;
1386 // ============================================================================
1387 // Function: resolveConstraints
1388 // Class: SketchSolver_Group
1389 // Purpose: solve the set of constraints for the current group
1390 // ============================================================================
1391 bool SketchSolver_Group::resolveConstraints()
1393 bool aResolved = false;
1394 if (myStorage->isNeedToResolve() && !isEmpty()) {
1395 myConstrSolver.setGroupID(myID);
1396 myStorage->initializeSolver(myConstrSolver);
1398 int aResult = myConstrSolver.solve();
1399 if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes
1400 myFeatureStorage->blockEvents(true);
1401 ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
1402 for (; aConstrIter != myConstraints.end(); aConstrIter++)
1403 aConstrIter->second->refresh();
1404 myFeatureStorage->blockEvents(false);
1405 } else if (!myConstraints.empty())
1406 Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this);
1410 removeTemporaryConstraints();
1411 myStorage->setNeedToResolve(false);
1415 // ============================================================================
1416 // Function: mergeGroups
1417 // Class: SketchSolver_Group
1418 // Purpose: append specified group to the current group
1419 // ============================================================================
1420 void SketchSolver_Group::mergeGroups(const SketchSolver_Group& theGroup)
1422 // If specified group is empty, no need to merge
1423 if (theGroup.isEmpty())
1425 if (!myFeatureStorage)
1426 myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
1428 ConstraintConstraintMap::const_iterator aConstrIter = theGroup.myConstraints.begin();
1429 for (; aConstrIter != theGroup.myConstraints.end(); aConstrIter++)
1430 changeConstraint(aConstrIter->first);
1433 // ============================================================================
1434 // Function: splitGroup
1435 // Class: SketchSolver_Group
1436 // Purpose: divide the group into several subgroups
1437 // ============================================================================
1438 void SketchSolver_Group::splitGroup(std::vector<SketchSolver_Group*>& theCuts)
1440 // Obtain constraints, which should be separated
1441 FeatureStoragePtr aNewFeatStorage(new SketchSolver_FeatureStorage);
1442 std::vector<ConstraintPtr> anUnusedConstraints;
1443 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
1444 for ( ; aCIter != myConstraints.end(); aCIter++) {
1445 std::list<ConstraintPtr> aBaseConstraints = aCIter->second->constraints();
1446 std::list<ConstraintPtr>::iterator anIter = aBaseConstraints.begin();
1447 for (; anIter != aBaseConstraints.end(); anIter++)
1448 if (aNewFeatStorage->isInteract(*anIter)) {
1449 aNewFeatStorage->changeConstraint(*anIter);
1451 anUnusedConstraints.push_back(*anIter);
1454 std::vector<SketchSolver_Group*>::iterator aCutsIter;
1455 std::vector<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
1456 for ( ; aUnuseIt != anUnusedConstraints.end(); aUnuseIt++) {
1457 // Remove unused constraints
1458 removeConstraint(*aUnuseIt);
1459 // Try to append constraint to already existent group
1460 for (aCutsIter = theCuts.begin(); aCutsIter != theCuts.end(); aCutsIter++)
1461 if ((*aCutsIter)->isInteract(*aUnuseIt)) {
1462 (*aCutsIter)->changeConstraint(*aUnuseIt);
1465 if (aCutsIter == theCuts.end()) {
1467 SketchSolver_Group* aGroup = new SketchSolver_Group(mySketch);
1468 aGroup->changeConstraint(*aUnuseIt);
1469 theCuts.push_back(aGroup);
1474 // ============================================================================
1475 // Function: isConsistent
1476 // Class: SketchSolver_Group
1477 // Purpose: search removed entities and constraints
1478 // ============================================================================
1479 bool SketchSolver_Group::isConsistent()
1481 if (!myFeatureStorage) // no one constraint is initialized yet
1484 bool aResult = myFeatureStorage->isConsistent();
1486 // remove invalid entities
1487 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
1488 while (aCIter != myConstraints.end()) {
1489 std::list<ConstraintPtr> aConstraints = aCIter->second->constraints();
1490 std::list<ConstraintPtr>::iterator anIt = aConstraints.begin();
1491 for (; anIt != aConstraints.end(); anIt++)
1492 if (!(*anIt)->data() || !(*anIt)->data()->isValid())
1493 if (aCIter->second->remove(*anIt)) {
1494 // the constraint is fully removed, detach it from the list
1495 ConstraintConstraintMap::iterator aTmpIt = aCIter++;
1496 myFeatureStorage->removeConstraint(aTmpIt->first);
1497 myConstraints.erase(aTmpIt);
1500 if (anIt == aConstraints.end())
1507 ////// ============================================================================
1508 ////// Function: updateAttribute
1509 ////// Class: SketchSolver_Group
1510 ////// Purpose: update features of sketch after resolving constraints
1511 ////// ============================================================================
1512 ////bool SketchSolver_Group::updateAttribute(
1513 //// std::shared_ptr<ModelAPI_Attribute> theAttribute, const Slvs_hEntity& theEntityID)
1515 //// // Search the position of the first parameter of the entity
1516 //// int anEntPos = Search(theEntityID, myEntities);
1517 //// int aFirstParamPos = Search(myEntities[anEntPos].param[0], myParams);
1519 //// // Look over supported types of entities
1522 //// std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1525 //// if (fabs(aPoint->x() - myParams[aFirstParamPos].val) > tolerance
1526 //// || fabs(aPoint->y() - myParams[aFirstParamPos + 1].val) > tolerance
1527 //// || fabs(aPoint->z() - myParams[aFirstParamPos + 2].val) > tolerance) {
1528 //// aPoint->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val,
1529 //// myParams[aFirstParamPos + 2].val);
1536 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
1537 //// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
1538 //// if (aPoint2D) {
1539 //// if (fabs(aPoint2D->x() - myParams[aFirstParamPos].val) > tolerance
1540 //// || fabs(aPoint2D->y() - myParams[aFirstParamPos + 1].val) > tolerance) {
1541 //// aPoint2D->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val);
1547 //// // Scalar value
1548 //// AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
1550 //// if (fabs(aScalar->value() - myParams[aFirstParamPos].val) > tolerance) {
1551 //// aScalar->setValue(myParams[aFirstParamPos].val);
1557 //// /// \todo Support other types of entities
1561 ////// ============================================================================
1562 ////// Function: updateEntityIfPossible
1563 ////// Class: SketchSolver_Group
1564 ////// Purpose: search the entity in this group and update it
1565 ////// ============================================================================
1566 ////void SketchSolver_Group::updateEntityIfPossible(
1567 //// std::shared_ptr<ModelAPI_Attribute> theEntity)
1569 //// if (myEntityAttrMap.find(theEntity) != myEntityAttrMap.end()) {
1570 //// // If the attribute is a point and it is changed (the group needs to rebuild),
1571 //// // probably user has dragged this point into this position,
1572 //// // so it is necessary to add constraint which will guarantee the point will not change
1574 //// // Store myNeedToSolve flag to verify the entity is really changed
1575 //// bool aNeedToSolveCopy = myNeedToSolve;
1576 //// myNeedToSolve = false;
1578 //// changeEntity(theEntity);
1580 //// if (myNeedToSolve) // the entity is changed
1582 //// // Verify the entity is a point and add temporary constraint of permanency
1583 //// std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1585 //// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D = std::dynamic_pointer_cast<
1586 //// GeomDataAPI_Point2D>(theEntity);
1587 //// if (aPoint || aPoint2D)
1588 //// addTemporaryConstraintWhereDragged(theEntity);
1591 //// // Restore flag of changes
1592 //// myNeedToSolve = myNeedToSolve || aNeedToSolveCopy;
1594 //// if (myNeedToSolve)
1595 //// updateRelatedConstraints(theEntity);
1599 ////// ============================================================================
1600 ////// Function: addTemporaryConstraintWhereDragged
1601 ////// Class: SketchSolver_Group
1602 ////// Purpose: add transient constraint SLVS_C_WHERE_DRAGGED for the entity,
1603 ////// which was moved by user
1604 ////// ============================================================================
1605 ////void SketchSolver_Group::addTemporaryConstraintWhereDragged(
1606 //// std::shared_ptr<ModelAPI_Attribute> theEntity,
1607 //// bool theAllowToFit)
1609 //// // Find identifier of the entity
1610 //// std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
1611 //// myEntityAttrMap.find(theEntity);
1612 //// if (anEntIter == myEntityAttrMap.end())
1615 //// // Get identifiers of all dragged points
1616 //// std::set<Slvs_hEntity> aDraggedPntID;
1617 //// aDraggedPntID.insert(myTempPointWDrgdID);
1618 //// std::list<Slvs_hConstraint>::const_iterator aTmpCoIter = myTempConstraints.begin();
1619 //// for (; aTmpCoIter != myTempConstraints.end(); aTmpCoIter++) {
1620 //// unsigned int aConstrPos = Search(*aTmpCoIter, myConstraints);
1621 //// if (aConstrPos < myConstraints.size())
1622 //// aDraggedPntID.insert(myConstraints[aConstrPos].ptA);
1624 //// std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
1625 //// for (; aConstrIter != myConstraints.end(); aConstrIter++)
1626 //// if (aConstrIter->type == SLVS_C_WHERE_DRAGGED)
1627 //// aDraggedPntID.insert(aConstrIter->ptA);
1628 //// // Find whether there is a point coincident with theEntity, which already has SLVS_C_WHERE_DRAGGED
1629 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
1630 //// for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) {
1631 //// if (aCoPtIter->find(anEntIter->second) == aCoPtIter->end())
1632 //// continue; // the entity was not found in current set
1634 //// // Find one of already created SLVS_C_WHERE_DRAGGED constraints in current set of coincident points
1635 //// std::set<Slvs_hEntity>::const_iterator aDrgIter = aDraggedPntID.begin();
1636 //// for (; aDrgIter != aDraggedPntID.end(); aDrgIter++)
1637 //// if (aCoPtIter->find(*aDrgIter) != aCoPtIter->end())
1638 //// return; // the SLVS_C_WHERE_DRAGGED constraint already exists
1640 //// if (aDraggedPntID.find(anEntIter->second) != aDraggedPntID.end())
1643 //// // If this is a first dragged point, its parameters should be placed
1644 //// // into Slvs_System::dragged field to avoid system inconsistense
1645 //// if (myTempPointWhereDragged.empty() && theAllowToFit) {
1646 //// int anEntPos = Search(anEntIter->second, myEntities);
1647 //// Slvs_hParam* aDraggedParam = myEntities[anEntPos].param;
1648 //// for (int i = 0; i < 4; i++, aDraggedParam++)
1649 //// if (*aDraggedParam != 0)
1650 //// myTempPointWhereDragged.push_back(*aDraggedParam);
1651 //// myTempPointWDrgdID = myEntities[anEntPos].h;
1655 //// // Create additional SLVS_C_WHERE_DRAGGED constraint if myTempPointWhereDragged field is not empty
1656 //// Slvs_Constraint aWDConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED,
1657 //// myWorkplane.h, 0.0, anEntIter->second, 0, 0, 0);
1658 //// myConstraints.push_back(aWDConstr);
1659 //// myTempConstraints.push_back(aWDConstr.h);
1662 // ============================================================================
1663 // Function: removeTemporaryConstraints
1664 // Class: SketchSolver_Group
1665 // Purpose: remove all transient SLVS_C_WHERE_DRAGGED constraints after
1666 // resolving the set of constraints
1667 // ============================================================================
1668 void SketchSolver_Group::removeTemporaryConstraints()
1670 myTempConstraints.clear();
1671 // Clean lists of removed entities in the storage
1672 std::set<Slvs_hParam> aRemPar;
1673 std::set<Slvs_hEntity> aRemEnt;
1674 std::set<Slvs_hConstraint> aRemCon;
1675 myStorage->getRemoved(aRemPar, aRemEnt, aRemCon);
1678 // ============================================================================
1679 // Function: removeConstraint
1680 // Class: SketchSolver_Group
1681 // Purpose: remove constraint and all unused entities
1682 // ============================================================================
1683 void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
1685 myFeatureStorage->removeConstraint(theConstraint);
1686 ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
1687 for (; aCIter != myConstraints.end(); aCIter++)
1688 if (aCIter->second->hasConstraint(theConstraint)) {
1689 if (!aCIter->second->remove(theConstraint)) // the constraint is not fully removed
1690 aCIter = myConstraints.end();
1693 if (aCIter != myConstraints.end())
1694 myConstraints.erase(aCIter);
1697 ////// ============================================================================
1698 ////// Function: removeEntitiesById
1699 ////// Class: SketchSolver_Group
1700 ////// Purpose: Removes specified entities and their parameters
1701 ////// ============================================================================
1702 ////void SketchSolver_Group::removeEntitiesById(const std::set<Slvs_hEntity>& theEntities)
1704 //// std::set<Slvs_hEntity>::const_reverse_iterator aRemIter = theEntities.rbegin();
1705 //// for (; aRemIter != theEntities.rend(); aRemIter++) {
1706 //// unsigned int anEntPos = Search(*aRemIter, myEntities);
1707 //// if (anEntPos >= myEntities.size())
1709 //// if (myEntities[anEntPos].param[0] != 0) {
1710 //// unsigned int aParamPos = Search(myEntities[anEntPos].param[0], myParams);
1711 //// if (aParamPos >= myParams.size())
1713 //// int aNbParams = 0;
1714 //// while (myEntities[anEntPos].param[aNbParams] != 0)
1716 //// if (myEntities[anEntPos].param[aNbParams - 1] == myParamMaxID)
1717 //// myParamMaxID -= aNbParams;
1718 //// myParams.erase(myParams.begin() + aParamPos, myParams.begin() + aParamPos + aNbParams);
1719 //// if (*aRemIter == myEntityMaxID)
1720 //// myEntityMaxID--;
1722 //// myEntities.erase(myEntities.begin() + anEntPos);
1723 //// myEntOfConstr.erase(myEntOfConstr.begin() + anEntPos);
1725 //// // Remove entity's ID from the lists of conincident points
1726 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
1727 //// for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++)
1728 //// aCoPtIter->erase(*aRemIter);
1732 ////// ============================================================================
1733 ////// Function: addCoincidentPoints
1734 ////// Class: SketchSolver_Group
1735 ////// Purpose: add coincident point the appropriate list of such points
1736 ////// ============================================================================
1737 ////bool SketchSolver_Group::addCoincidentPoints(const Slvs_hEntity& thePoint1,
1738 //// const Slvs_hEntity& thePoint2)
1740 //// std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
1741 //// std::vector<std::set<Slvs_hEntity> >::iterator aFirstFound = myCoincidentPoints.end();
1742 //// while (aCoPtIter != myCoincidentPoints.end()) {
1743 //// bool isFound[2] = { // indicate which point ID was already in coincidence constraint
1744 //// aCoPtIter->find(thePoint1) != aCoPtIter->end(), aCoPtIter->find(thePoint2)
1745 //// != aCoPtIter->end(), };
1746 //// if (isFound[0] && isFound[1]) // points are already connected by coincidence constraints => no need additional one
1748 //// if ((isFound[0] && !isFound[1]) || (!isFound[0] && isFound[1])) {
1749 //// if (aFirstFound != myCoincidentPoints.end()) { // there are two groups of coincident points connected by created constraint => merge them
1750 //// int aFirstFoundShift = aFirstFound - myCoincidentPoints.begin();
1751 //// int aCurrentShift = aCoPtIter - myCoincidentPoints.begin();
1752 //// aFirstFound->insert(aCoPtIter->begin(), aCoPtIter->end());
1753 //// myCoincidentPoints.erase(aCoPtIter);
1754 //// aFirstFound = myCoincidentPoints.begin() + aFirstFoundShift;
1755 //// aCoPtIter = myCoincidentPoints.begin() + aCurrentShift;
1758 //// aCoPtIter->insert(isFound[0] ? thePoint2 : thePoint1);
1759 //// aFirstFound = aCoPtIter;
1764 //// // No points were found, need to create new set
1765 //// if (aFirstFound == myCoincidentPoints.end()) {
1766 //// std::set<Slvs_hEntity> aNewSet;
1767 //// aNewSet.insert(thePoint1);
1768 //// aNewSet.insert(thePoint2);
1769 //// myCoincidentPoints.push_back(aNewSet);
1775 ////// ============================================================================
1776 ////// Function: updateRelatedConstraints
1777 ////// Class: SketchSolver_Group
1778 ////// Purpose: emit the signal to update constraints
1779 ////// ============================================================================
1780 ////void SketchSolver_Group::updateRelatedConstraints(
1781 //// std::shared_ptr<ModelAPI_Attribute> theEntity) const
1783 //// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
1784 //// for (; aConstrIter != myConstraintMap.end(); aConstrIter++) {
1785 //// std::list<std::shared_ptr<ModelAPI_Attribute> > anAttributes = aConstrIter->first->data()
1786 //// ->attributes(std::string());
1788 //// std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttributes.begin();
1789 //// for (; anAttrIter != anAttributes.end(); anAttrIter++) {
1790 //// bool isUpd = (*anAttrIter == theEntity);
1791 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr = std::dynamic_pointer_cast<
1792 //// ModelAPI_AttributeRefAttr>(*anAttrIter);
1793 //// if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theEntity)
1797 //// static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
1798 //// ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent);
1805 ////void SketchSolver_Group::updateRelatedConstraintsFeature(
1806 //// std::shared_ptr<ModelAPI_Feature> theFeature) const
1808 //// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
1809 //// for (; aConstrIter != myConstraintMap.end(); aConstrIter++) {
1810 //// std::list<std::shared_ptr<ModelAPI_Attribute> > anAttributes = aConstrIter->first->data()
1811 //// ->attributes(std::string());
1813 //// std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttributes.begin();
1814 //// for (; anAttrIter != anAttributes.end(); anAttrIter++) {
1815 //// std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr = std::dynamic_pointer_cast<
1816 //// ModelAPI_AttributeRefAttr>(*anAttrIter);
1817 //// if (aRefAttr && aRefAttr->isObject() && aRefAttr->object() == theFeature) {
1818 //// static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
1819 //// ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent);
1826 ////// ============================================================================
1827 ////// Function: updateFilletConstraints
1828 ////// Class: SketchSolver_Group
1829 ////// Purpose: change fillet arc to be less than 180 degree
1830 ////// ============================================================================
1831 ////void SketchSolver_Group::updateFilletConstraints()
1833 //// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
1834 //// for (; aConstrIter != myConstraintMap.end(); aConstrIter++)
1835 //// if (aConstrIter->first->getKind() == SketchPlugin_ConstraintFillet::ID()) {
1836 //// AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
1837 //// aConstrIter->first->data()->attribute(SketchPlugin_ConstraintFillet::ENTITY_C()));
1838 //// if (!aFilletRefList)
1840 //// ObjectPtr anArcObj = aFilletRefList->object(2);
1841 //// std::shared_ptr<GeomDataAPI_Point2D> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1842 //// anArcObj->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
1843 //// std::shared_ptr<GeomDataAPI_Point2D> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1844 //// anArcObj->data()->attribute(SketchPlugin_Arc::START_ID()));
1845 //// std::shared_ptr<GeomDataAPI_Point2D> aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1846 //// anArcObj->data()->attribute(SketchPlugin_Arc::END_ID()));
1847 //// double aCosA = aStart->x() - aCenter->x();
1848 //// double aSinA = aStart->y() - aCenter->y();
1849 //// double aCosB = aEnd->x() - aCenter->x();
1850 //// double aSinB = aEnd->y() - aCenter->y();
1851 //// if (aCosA * aSinB - aSinA * aCosB <= 0.0) {
1852 //// anArcObj->data()->blockSendAttributeUpdated(true);
1853 //// double x = aStart->x();
1854 //// double y = aStart->y();
1855 //// aStart->setValue(aEnd->x(), aEnd->y());
1856 //// aEnd->setValue(x, y);
1857 //// // Update constraint data
1858 //// changeFilletConstraint(aConstrIter->first);
1859 //// anArcObj->data()->blockSendAttributeUpdated(false);
1864 ////// ============================================================================
1865 ////// Function: makeMirrorEntity
1866 ////// Class: SketchSolver_Group
1867 ////// Purpose: change entities parameters to make them symmetric relating to the mirror line
1868 ////// ============================================================================
1869 ////void SketchSolver_Group::makeMirrorEntity(const Slvs_hEntity& theBase,
1870 //// const Slvs_hEntity& theMirror,
1871 //// const Slvs_hEntity& theMirrorLine)
1873 //// Slvs_Entity aBase = myEntities[Search(theBase, myEntities)];
1874 //// Slvs_Entity aMirror = myEntities[Search(theMirror, myEntities)];
1876 //// while (aBase.point[i] != 0 && aMirror.point[i] != 0) {
1877 //// makeMirrorEntity(aBase.point[i], aMirror.point[i], theMirrorLine);
1880 //// if (aBase.param[0] != 0 && aMirror.param[0] != 0) { // this is a point, copy it
1881 //// Slvs_Entity aMirrorLine = myEntities[Search(theMirrorLine, myEntities)];
1882 //// std::shared_ptr<GeomAPI_XY> aLinePoints[2];
1883 //// for (i = 0; i < 2; i++) {
1884 //// Slvs_Entity aPoint = myEntities[Search(aMirrorLine.point[i], myEntities)];
1885 //// int aParamPos = Search(aPoint.param[0], myParams);
1886 //// aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
1887 //// new GeomAPI_XY(myParams[aParamPos].val, myParams[1+aParamPos].val));
1889 //// int aBaseParamPos = Search(aBase.param[0], myParams);
1890 //// int aMirrorParamPos = Search(aMirror.param[0], myParams);
1891 //// std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(
1892 //// new GeomAPI_XY(myParams[aBaseParamPos].val, myParams[1+aBaseParamPos].val));
1894 //// // direction of a mirror line
1895 //// std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
1896 //// new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
1897 //// // orthogonal direction
1898 //// aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
1900 //// std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
1901 //// new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
1902 //// double aDist = aVec->dot(aDir->xy());
1903 //// std::shared_ptr<GeomAPI_XY> aMirrorPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
1905 //// myParams[aMirrorParamPos].val = aMirrorPoint->x();
1906 //// myParams[1+aMirrorParamPos].val = aMirrorPoint->y();
1910 ////// ============================================================================
1911 ////// Function: calculateMiddlePoint
1912 ////// Class: SketchSolver_Group
1913 ////// Purpose: calculates middle point on line or arc
1914 ////// ============================================================================
1915 ////void SketchSolver_Group::calculateMiddlePoint(
1916 //// const Slvs_hEntity& theEntity,
1918 //// double& theY) const
1920 //// int anInd = Search(theEntity, myEntities);
1921 //// if (myEntities[anInd].type == SLVS_E_LINE_SEGMENT) {
1922 //// int aLineParams[2];
1923 //// for (int i = 0; i < 2; i++) {
1924 //// int aPtPos = Search(myEntities[anInd].point[i], myEntities);
1925 //// aLineParams[i] = Search(myEntities[aPtPos].param[0], myParams);
1927 //// theX = 0.5 * (myParams[aLineParams[0]].val + myParams[aLineParams[1]].val);
1928 //// theY = 0.5 * (myParams[1 + aLineParams[0]].val + myParams[1 + aLineParams[1]].val);
1929 //// } else if (myEntities[anInd].type == SLVS_E_ARC_OF_CIRCLE) {
1930 //// double anArcPoint[3][2];
1931 //// for (int i = 0; i < 3; i++) {
1932 //// int aPtPos = Search(myEntities[anInd].point[i], myEntities);
1933 //// int anArcParam = Search(myEntities[aPtPos].param[0], myParams);
1934 //// anArcPoint[i][0] = myParams[anArcParam].val;
1935 //// anArcPoint[i][1] = myParams[1 + anArcParam].val;
1937 //// // project last point of arc on the arc
1938 //// double x = anArcPoint[1][0] - anArcPoint[0][0];
1939 //// double y = anArcPoint[1][1] - anArcPoint[0][1];
1940 //// double aRad = sqrt(x*x + y*y);
1941 //// x = anArcPoint[2][0] - anArcPoint[0][0];
1942 //// y = anArcPoint[2][1] - anArcPoint[0][1];
1943 //// double aNorm = sqrt(x*x + y*y);
1944 //// if (aNorm >= tolerance) {
1945 //// anArcPoint[2][0] = anArcPoint[0][0] + x * aRad / aNorm;
1946 //// anArcPoint[2][1] = anArcPoint[0][1] + y * aRad / aNorm;
1949 //// x = anArcPoint[1][0] + anArcPoint[2][0] - 2.0 * anArcPoint[0][0];
1950 //// y = anArcPoint[1][1] + anArcPoint[2][1] - 2.0 * anArcPoint[0][1];
1951 //// aNorm = sqrt(x*x + y*y);
1952 //// if (aNorm >= tolerance) {
1953 //// x *= aRad / aNorm;
1954 //// y *= aRad / aNorm;
1955 //// } else { // obtain orthogonal direction
1956 //// x = 0.5 * (anArcPoint[2][1] - anArcPoint[1][1]);
1957 //// y = -0.5 * (anArcPoint[2][0] - anArcPoint[1][0]);
1959 //// theX = anArcPoint[0][0] + x;
1960 //// theY = anArcPoint[0][1] + y;
1965 // ========================================================
1966 // ========= Auxiliary functions ===============
1967 // ========================================================
1969 template<typename T>
1970 int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
1972 int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
1973 int aVecSize = theEntities.size();
1974 while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
1976 while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
1978 if (aResIndex == -1)
1979 aResIndex = aVecSize;