X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintGroup.cpp;h=954c6c5963fb779fba5116bbe9132eab4e6cba89;hb=d34bc15bf8fafedd9188f47ff5962b5a1661d5b0;hp=7c0bd37845879ea5df3015d550a1645a013eefdb;hpb=8fb6099964adb7a3dd335727ce87ddcdbaf9e8da;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp index 7c0bd3784..954c6c596 100644 --- a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp @@ -6,15 +6,18 @@ #include +#include #include #include #include #include #include #include -#include +#include #include +#include +#include #include #include @@ -28,6 +31,8 @@ /// Tolerance for value of parameters const double tolerance = 1.e-10; +const std::string ERROR_SOLVE_CONSTRAINTS = "Conflicting constraints"; + /// This value is used to give unique index to the groups static Slvs_hGroup myGroupIndexer = 0; @@ -116,11 +121,12 @@ bool SketchSolver_ConstraintGroup::isInteract( theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[i]) ); if (!aCAttrRef) continue; - if (!aCAttrRef->isFeature() && + if (!aCAttrRef->isObject() && myEntityAttrMap.find(aCAttrRef->attr()) != myEntityAttrMap.end()) return true; - if (aCAttrRef->isFeature() && - myEntityFeatMap.find(aCAttrRef->feature()) != myEntityFeatMap.end()) + if (aCAttrRef->isObject() && + myEntityFeatMap.find(boost::dynamic_pointer_cast(aCAttrRef->object())) + != myEntityFeatMap.end()) return true; } @@ -160,19 +166,19 @@ bool SketchSolver_ConstraintGroup::changeConstraint( // Create constraint parameters double aDistance = 0.0; // scalar value of the constraint - boost::shared_ptr aDistAttr = + AttributeDoublePtr aDistAttr = boost::dynamic_pointer_cast(theConstraint->data()->attribute(CONSTRAINT_ATTR_VALUE)); if (aDistAttr) { aDistance = aDistAttr->value(); + // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter + if (aConstrType == SLVS_C_DIAMETER) + aDistance *= 2.0; if (aConstrMapIter != myConstraintMap.end() && fabs(aConstrIter->valA - aDistance) > tolerance) { myNeedToSolve = true; aConstrIter->valA = aDistance; } - // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter - if (aConstrType == SLVS_C_DIAMETER) - aDistance *= 2.0; } Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE]; // parameters of the constraint @@ -186,15 +192,17 @@ bool SketchSolver_ConstraintGroup::changeConstraint( if (!aConstrAttr) continue; // For the length constraint the start and end points of the line should be added to the entities list instead of line - if (aConstrType == SLVS_C_PT_PT_DISTANCE && theConstraint->getKind().compare("SketchConstraintLength") == 0) + if (aConstrType == SLVS_C_PT_PT_DISTANCE && theConstraint->getKind().compare(SKETCH_CONSTRAINT_LENGTH_KIND) == 0) { - boost::shared_ptr aData = aConstrAttr->feature()->data(); + boost::shared_ptr aData = aConstrAttr->object()->data(); aConstrEnt[indAttr] = changeEntity(aData->attribute(LINE_ATTR_START)); aConstrEnt[indAttr+1] = changeEntity(aData->attribute(LINE_ATTR_END)); + // measured object is added into the map of objects to avoid problems with interaction betwee constraint and group + myEntityFeatMap[boost::dynamic_pointer_cast(aConstrAttr->object())] = 0; break; // there should be no other entities } - else if (aConstrAttr->isFeature()) - aConstrEnt[indAttr] = changeEntity(aConstrAttr->feature()); + else if (aConstrAttr->isObject()) + aConstrEnt[indAttr] = changeEntity(boost::dynamic_pointer_cast(aConstrAttr->object())); else aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr()); } @@ -203,11 +211,17 @@ bool SketchSolver_ConstraintGroup::changeConstraint( { // Several points may be coincident, it is not necessary to store all constraints between them. // Try to find sequence of coincident points which connects the points of new constraint - if (aConstrType == SLVS_C_POINTS_COINCIDENT && - !addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) + if (aConstrType == SLVS_C_POINTS_COINCIDENT) { - myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes - return false; + if (aConstrEnt[0] == aConstrEnt[1]) // no need to add self coincidence + { + return false; + } + if (!addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) + { + myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes + return false; + } } // Create SolveSpace constraint structure @@ -286,7 +300,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( } // Scalar value (used for the distance entities) - boost::shared_ptr aScalar = + AttributeDoublePtr aScalar = boost::dynamic_pointer_cast(theEntity); if (aScalar) { @@ -315,23 +329,23 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( // Purpose: create/update the element defined by the feature affected by any constraint // ============================================================================ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( - boost::shared_ptr theEntity) + FeaturePtr theEntity) { // If the entity is already in the group, try to find it - std::map, Slvs_hEntity>::const_iterator + std::map::const_iterator aEntIter = myEntityFeatMap.find(theEntity); // defines that the entity already exists const bool isEntExists = (myEntityFeatMap.find(theEntity) != myEntityFeatMap.end()); // SketchPlugin features - boost::shared_ptr aFeature; + boost::shared_ptr aFeature = boost::dynamic_pointer_cast(theEntity); if (aFeature) { // Verify the feature by its kind const std::string& aFeatureKind = aFeature->getKind(); // Line - if (aFeatureKind.compare("SketchLine") == 0) + if (aFeatureKind.compare(SKETCH_LINE_KIND) == 0) { Slvs_hEntity aStart = changeEntity(aFeature->data()->attribute(LINE_ATTR_START)); Slvs_hEntity aEnd = changeEntity(aFeature->data()->attribute(LINE_ATTR_END)); @@ -346,7 +360,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( return aLineEntity.h; } // Circle - else if (aFeatureKind.compare("SketchCircle") == 0) + else if (aFeatureKind.compare(SKETCH_CIRCLE_KIND) == 0) { Slvs_hEntity aCenter = changeEntity(aFeature->data()->attribute(CIRCLE_ATTR_CENTER)); Slvs_hEntity aRadius = changeEntity(aFeature->data()->attribute(CIRCLE_ATTR_RADIUS)); @@ -362,7 +376,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( return aCircleEntity.h; } // Arc - else if (aFeatureKind.compare("SketchArc") == 0) + else if (aFeatureKind.compare(SKETCH_ARC_KIND) == 0) { Slvs_hEntity aCenter = changeEntity(aFeature->data()->attribute(ARC_ATTR_CENTER)); Slvs_hEntity aStart = changeEntity(aFeature->data()->attribute(ARC_ATTR_START)); @@ -378,7 +392,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( return anArcEntity.h; } // Point (it has low probability to be an attribute of constraint, so it is checked at the end) - else if (aFeatureKind.compare("SketchPoint") == 0) + else if (aFeatureKind.compare(SKETCH_POINT_KIND) == 0) { Slvs_hEntity aPoint = changeEntity(aFeature->data()->attribute(POINT_ATTR_COORD)); @@ -461,7 +475,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( bool SketchSolver_ConstraintGroup::addWorkplane( boost::shared_ptr theSketch) { - if (myWorkplane.h || theSketch->getKind().compare("Sketch") != 0) + if (myWorkplane.h || theSketch->getKind().compare(SKETCH_KIND) != 0) return false; // the workplane already exists or the function parameter is not Sketch mySketch = theSketch; @@ -554,9 +568,11 @@ void SketchSolver_ConstraintGroup::resolveConstraints() std::map, Slvs_hEntity>::iterator anEntIter = myEntityAttrMap.begin(); for ( ; anEntIter != myEntityAttrMap.end(); anEntIter++) - updateAttribute(anEntIter->first, anEntIter->second); + if (updateAttribute(anEntIter->first, anEntIter->second)) + updateRelatedConstraints(anEntIter->first); } - /// \todo Implement error handling + else if (!myConstraints.empty()) + Events_Error::send(ERROR_SOLVE_CONSTRAINTS, this); removeTemporaryConstraints(); myNeedToSolve = false; @@ -744,7 +760,7 @@ bool SketchSolver_ConstraintGroup::updateGroup() { if (!aConstrIter->first->data()->isValid()) { - if (aConstrIter->first->getKind().compare("SketchConstraintCoincidence") == 0) + if (aConstrIter->first->getKind().compare(SKETCH_CONSTRAINT_COINCIDENCE_KIND) == 0) isCCRemoved = true; std::map, Slvs_hConstraint>::reverse_iterator aCopyIter = aConstrIter++; @@ -776,7 +792,7 @@ bool SketchSolver_ConstraintGroup::updateGroup() // Class: SketchSolver_ConstraintGroup // Purpose: update features of sketch after resolving constraints // ============================================================================ -void SketchSolver_ConstraintGroup::updateAttribute( +bool SketchSolver_ConstraintGroup::updateAttribute( boost::shared_ptr theAttribute, const Slvs_hEntity& theEntityID) { @@ -791,10 +807,16 @@ void SketchSolver_ConstraintGroup::updateAttribute( boost::dynamic_pointer_cast(theAttribute); if (aPoint) { - aPoint->setValue(myParams[aFirstParamPos].val, - myParams[aFirstParamPos+1].val, - myParams[aFirstParamPos+2].val); - return ; + if (fabs(aPoint->x() - myParams[aFirstParamPos].val) > tolerance || + fabs(aPoint->y() - myParams[aFirstParamPos+1].val) > tolerance || + fabs(aPoint->z() - myParams[aFirstParamPos+2].val) > tolerance) + { + aPoint->setValue(myParams[aFirstParamPos].val, + myParams[aFirstParamPos+1].val, + myParams[aFirstParamPos+2].val); + return true; + } + return false; } // Point in 2D @@ -802,21 +824,31 @@ void SketchSolver_ConstraintGroup::updateAttribute( boost::dynamic_pointer_cast(theAttribute); if (aPoint2D) { - aPoint2D->setValue(myParams[aFirstParamPos].val, - myParams[aFirstParamPos+1].val); - return ; + if (fabs(aPoint2D->x() - myParams[aFirstParamPos].val) > tolerance || + fabs(aPoint2D->y() - myParams[aFirstParamPos+1].val) > tolerance) + { + aPoint2D->setValue(myParams[aFirstParamPos].val, + myParams[aFirstParamPos+1].val); + return true; + } + return false; } // Scalar value - boost::shared_ptr aScalar = + AttributeDoublePtr aScalar = boost::dynamic_pointer_cast(theAttribute); if (aScalar) { - aScalar->setValue(myParams[aFirstParamPos].val); - return ; + if (fabs(aScalar->value() - myParams[aFirstParamPos].val) > tolerance) + { + aScalar->setValue(myParams[aFirstParamPos].val); + return true; + } + return false; } /// \todo Support other types of entities + return false; } // ============================================================================ @@ -852,6 +884,9 @@ void SketchSolver_ConstraintGroup::updateEntityIfPossible( // Restore flag of changes myNeedToSolve = myNeedToSolve || aNeedToSolveCopy; + + if (myNeedToSolve) + updateRelatedConstraints(theEntity); } } @@ -994,13 +1029,13 @@ void SketchSolver_ConstraintGroup::removeConstraint(boost::shared_ptr, Slvs_hEntity>::iterator + std::map::iterator anEntFeatIter = myEntityFeatMap.begin(); while (anEntFeatIter != myEntityFeatMap.end()) { if (anEntToRemove.find(anEntFeatIter->second) != anEntToRemove.end()) { - std::map, Slvs_hEntity>::iterator + std::map::iterator aRemovedIter = anEntFeatIter; anEntFeatIter++; myEntityFeatMap.erase(aRemovedIter); @@ -1087,6 +1122,67 @@ bool SketchSolver_ConstraintGroup::addCoincidentPoints( } +// ============================================================================ +// Function: updateRelatedConstraints +// Class: SketchSolver_ConstraintGroup +// Purpose: emit the signal to update constraints +// ============================================================================ +void SketchSolver_ConstraintGroup::updateRelatedConstraints( + boost::shared_ptr theEntity) const +{ + std::map, Slvs_hConstraint>::const_iterator + aConstrIter = myConstraintMap.begin(); + for ( ; aConstrIter != myConstraintMap.end(); aConstrIter++) + { + std::list< boost::shared_ptr > anAttributes = + aConstrIter->first->data()->attributes(std::string()); + + std::list< boost::shared_ptr >::iterator + anAttrIter = anAttributes.begin(); + for ( ; anAttrIter != anAttributes.end(); anAttrIter++) + { + bool isUpd = (*anAttrIter == theEntity); + boost::shared_ptr aRefAttr = + boost::dynamic_pointer_cast(*anAttrIter); + if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theEntity) + isUpd = true; + + if (isUpd) + { + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent); + break; + } + } + } +} + +void SketchSolver_ConstraintGroup::updateRelatedConstraints( + boost::shared_ptr theFeature) const +{ + std::map, Slvs_hConstraint>::const_iterator + aConstrIter = myConstraintMap.begin(); + for ( ; aConstrIter != myConstraintMap.end(); aConstrIter++) + { + std::list< boost::shared_ptr > anAttributes = + aConstrIter->first->data()->attributes(std::string()); + + std::list< boost::shared_ptr >::iterator + anAttrIter = anAttributes.begin(); + for ( ; anAttrIter != anAttributes.end(); anAttrIter++) + { + boost::shared_ptr aRefAttr = + boost::dynamic_pointer_cast(*anAttrIter); + if (aRefAttr && aRefAttr->isObject() && aRefAttr->object() == theFeature) + { + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent); + break; + } + } + } +} + // ======================================================== @@ -1100,7 +1196,7 @@ int Search(const uint32_t& theEntityID, const std::vector& theEntities) int aVecSize = theEntities.size(); while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID) aResIndex--; - while (aResIndex < aVecSize && theEntities[aResIndex].h < theEntityID) + while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID) aResIndex++; if (aResIndex == -1) aResIndex = aVecSize;