From: azv Date: Thu, 4 May 2017 08:03:03 +0000 (+0300) Subject: Issues #2150 and #2151: Frequently appeared "Conflicting constraints" message for... X-Git-Tag: V_2.7.1~36 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=15cea9df7b45e3e1fb5581b538bc820e82f106d3;p=modules%2Fshaper.git Issues #2150 and #2151: Frequently appeared "Conflicting constraints" message for valid sketch. Improve processing of multi-coincidence by placing coincident points into different groups. Since now it is taken into account only the points to form the group (on the other works, the feature cannot be an initializer of the coincidence group). --- diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp index 1b7252e2b..4ea868a11 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp @@ -52,39 +52,38 @@ static bool hasAnotherExternalPoint(const std::set& theCoincid return false; } -bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence( +bool PlaneGCSSolver_UpdateCoincidence::addCoincidence( const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2) { bool isAccepted = true; - - std::list::iterator anIt = myCoincident.begin(); - std::list::iterator - aFound[2] = {myCoincident.end(), myCoincident.end()}; - - for (; anIt != myCoincident.end(); ++anIt) { - if (anIt->isExist(theEntity1)) - aFound[0] = anIt; - if (anIt->isExist(theEntity2)) - aFound[1] = anIt; - if (aFound[0] != myCoincident.end() && aFound[1] != myCoincident.end()) - break; - } + std::list::iterator aFound[2] = { + findGroupOfCoincidence(theEntity1), + findGroupOfCoincidence(theEntity2) + }; if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) { // new group of coincidence myCoincident.push_back(CoincidentEntities(theEntity1, theEntity2)); - } else if (aFound[0] == aFound[1]) // same group => already coincident + } else if (aFound[0] == myCoincident.end()) { + isAccepted = addToGroupOfCoincidence(*aFound[1], theEntity1); + } else if (aFound[1] == myCoincident.end()) { + isAccepted = addToGroupOfCoincidence(*aFound[0], theEntity2); + } else if (aFound[0] == aFound[1]) { // same group => already coincident isAccepted = false; - else { - if (aFound[0] == myCoincident.end()) - isAccepted = aFound[1]->isNewCoincidence(theEntity2, theEntity1); - else if (aFound[1] == myCoincident.end()) - isAccepted = aFound[0]->isNewCoincidence(theEntity1, theEntity2); - else { // merge two groups - isAccepted = aFound[0]->isNewCoincidence(theEntity1, *(aFound[1]), theEntity2); - myCoincident.erase(aFound[1]); + } else { // merge two groups + EntityWrapperPtr anEntityToAdd = theEntity1; + if (theEntity1->isExternal()) { // swap found groups; + anEntityToAdd = theEntity2; + std::list::iterator aTempIt = aFound[0]; + aFound[0] = aFound[1]; + aFound[1] = aTempIt; } + + aFound[1]->remove(anEntityToAdd); + aFound[0]->merge(*aFound[1]); + isAccepted = aFound[0]->add(anEntityToAdd); + myCoincident.erase(aFound[1]); } return isAccepted; @@ -94,11 +93,7 @@ bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity( const EntityWrapperPtr& thePoint, const EntityWrapperPtr& theEntity) { - std::list::iterator anIt = myCoincident.begin(); - for (; anIt != myCoincident.end(); ++anIt) - if (anIt->isExist(thePoint)) - break; - + std::list::iterator anIt = findGroupOfCoincidence(thePoint); if (anIt == myCoincident.end()) return false; @@ -113,156 +108,119 @@ bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity( return false; } +std::list::iterator + PlaneGCSSolver_UpdateCoincidence::findGroupOfCoincidence(const EntityWrapperPtr& theEntity) +{ + if (theEntity->type() != ENTITY_POINT) + return myCoincident.end(); + std::list::iterator aFound = myCoincident.begin(); + for (; aFound != myCoincident.end(); ++aFound) + if (aFound->isExist(theEntity)) + break; + return aFound; +} +bool PlaneGCSSolver_UpdateCoincidence::addToGroupOfCoincidence( + CoincidentEntities& theGroup, const EntityWrapperPtr& theEntity) +{ + if (theGroup.isExist(theEntity)) + return false; + theGroup.add(theEntity); + return true; +} -PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities( - const EntityWrapperPtr& theEntity1, - const EntityWrapperPtr& theEntity2) + + + + +static const GCS::Point& toPoint(const EntityWrapperPtr& theEntity) { - if (theEntity1->isExternal() && theEntity2->isExternal()) { - myExternalAndConnected[theEntity1] = std::set(); - myExternalAndConnected[theEntity2] = std::set(); - } else if (theEntity1->isExternal()) - myExternalAndConnected[theEntity1].insert(theEntity2); - else if (theEntity2->isExternal()) - myExternalAndConnected[theEntity2].insert(theEntity1); - else { - std::set aGroup; - aGroup.insert(theEntity1); - aGroup.insert(theEntity2); - myExternalAndConnected[EntityWrapperPtr()] = aGroup; - } + PointWrapperPtr aPoint = std::dynamic_pointer_cast(theEntity); + return *(aPoint->point()); } -bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::hasExternal() const +static double squareDistance(const GCS::Point& thePoint1, const GCS::Point& thePoint2) { - return myExternalAndConnected.size() != 1 || - myExternalAndConnected.find(EntityWrapperPtr()) == myExternalAndConnected.end(); + double dx = *thePoint1.x - *thePoint2.x; + double dy = *thePoint1.y - *thePoint2.y; + return dx * dx + dy * dy; } -bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist( - const EntityWrapperPtr& theEntity) const +static bool hasSamePoint(const std::set& theList, const GCS::Point& thePoint) { - std::map >::const_iterator - anIt = myExternalAndConnected.begin(); - for (; anIt != myExternalAndConnected.end(); ++anIt) - if (anIt->first == theEntity || - anIt->second.find(theEntity) != anIt->second.end()) + std::set::const_iterator anIt = theList.begin(); + for (; anIt != theList.end(); ++anIt) + if (squareDistance(thePoint, toPoint(*anIt)) < 1.e-14) return true; return false; } -static bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2) +static bool hasSamePoint(const std::set& theList, const EntityWrapperPtr& thePoint) { - return thePoint1.x == thePoint2.x && thePoint1.y == thePoint2.y; + return hasSamePoint(theList, toPoint(thePoint)); } -bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist( - const GCS::Point& thePoint) const -{ - std::map >::const_iterator - anIt = myExternalAndConnected.begin(); - for (; anIt != myExternalAndConnected.end(); ++anIt) { - if (anIt->first && anIt->first->type() == ENTITY_POINT) { - const GCSPointPtr& aPoint = - std::dynamic_pointer_cast(anIt->first)->point(); - if (isEqual(*aPoint, thePoint)) - return true; - } - std::set::const_iterator anEntIt = anIt->second.begin(); - for (; anEntIt != anIt->second.end(); ++anEntIt) - if ((*anEntIt)->type() == ENTITY_POINT) { - const GCSPointPtr& aPoint = - std::dynamic_pointer_cast(*anEntIt)->point(); - if (isEqual(*aPoint, thePoint)) - return true; - } - } - return false; +PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities( + const EntityWrapperPtr& theEntity1, + const EntityWrapperPtr& theEntity2) +{ + add(theEntity1); + add(theEntity2); } -bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence( - const EntityWrapperPtr& theEntityExist, - const EntityWrapperPtr& theOtherEntity) +bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::add( + const EntityWrapperPtr& theEntity) { - if (theOtherEntity->isExternal()) { - if (hasExternal()) { - if (myExternalAndConnected.find(theOtherEntity) == myExternalAndConnected.end()) - myExternalAndConnected[theOtherEntity] = std::set(); - // check whether all external entities are edges - bool isNewCoinc = true; - std::map >::iterator - anIt = myExternalAndConnected.begin(); - for (; anIt != myExternalAndConnected.end() && isNewCoinc; ++anIt) - isNewCoinc = (anIt->first->type() != ENTITY_POINT); - return isNewCoinc; - } else { - myExternalAndConnected[theOtherEntity] = myExternalAndConnected[EntityWrapperPtr()]; - myExternalAndConnected.erase(EntityWrapperPtr()); - return true; - } - } - - if (theEntityExist->isExternal()) { - myExternalAndConnected[theEntityExist].insert(theOtherEntity); - return true; - } + bool isAdded = true; + if (theEntity->type() == ENTITY_POINT) { + if (theEntity->isExternal()) { + isAdded = !hasSamePoint(myExternalPoints, theEntity); + myExternalPoints.insert(theEntity); + } else + myPoints.insert(theEntity); + } else + myFeatures.insert(theEntity); + return isAdded; +} - std::map >::iterator - anIt = myExternalAndConnected.begin(); - for (; anIt != myExternalAndConnected.end(); ++anIt) - if (anIt->second.find(theEntityExist) != anIt->second.end()) { - anIt->second.insert(theOtherEntity); - break; - } - return true; +void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::remove( + const EntityWrapperPtr& theEntity) +{ + if (theEntity->type() == ENTITY_POINT) { + if (theEntity->isExternal()) + myExternalPoints.erase(theEntity); + else + myPoints.erase(theEntity); + } else + myFeatures.erase(theEntity); } -bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence( - const EntityWrapperPtr& theEntityExist, - const CoincidentEntities& theOtherGroup, - const EntityWrapperPtr& theEntityInOtherGroup) +void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::merge( + const CoincidentEntities& theOther) { - bool hasExt[2] = {hasExternal(), theOtherGroup.hasExternal()}; - if (hasExt[0] && hasExt[1]) { - myExternalAndConnected.insert(theOtherGroup.myExternalAndConnected.begin(), - theOtherGroup.myExternalAndConnected.end()); - return false; - } else if (!hasExt[0] && !hasExt[1]) { - std::map >::const_iterator - aFound = theOtherGroup.myExternalAndConnected.find(EntityWrapperPtr()); + myExternalPoints.insert(theOther.myExternalPoints.begin(), theOther.myExternalPoints.end()); + myPoints.insert(theOther.myPoints.begin(), theOther.myPoints.end()); + myFeatures.insert(theOther.myFeatures.begin(), theOther.myFeatures.end()); +} - myExternalAndConnected[EntityWrapperPtr()].insert( - aFound->second.begin(), aFound->second.end()); - return true; - } else { - std::map > aSource, aDest; - EntityWrapperPtr aTarget; - if (hasExt[0]) { - aDest = myExternalAndConnected; - aSource = theOtherGroup.myExternalAndConnected; - aTarget = theEntityExist; - } else { - aSource = myExternalAndConnected; - aDest = theOtherGroup.myExternalAndConnected; - aTarget = theEntityInOtherGroup; - } +bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist( + const EntityWrapperPtr& theEntity) const +{ + if (theEntity->type() == ENTITY_POINT) { + if (theEntity->isExternal()) + return myExternalPoints.find(theEntity) != myExternalPoints.end(); + else + return myPoints.find(theEntity) != myPoints.end(); + } - std::map >::const_iterator - aFound = aSource.find(EntityWrapperPtr()); + return myFeatures.find(theEntity) != myFeatures.end(); +} - std::map >::iterator anIt = aDest.begin(); - for (; anIt != aDest.end(); ++anIt) - if (anIt->first == aTarget || - anIt->second.find(aTarget) != anIt->second.end()) { - anIt->second.insert(aFound->second.begin(), aFound->second.end()); - break; - } - return true; - } - // impossible case - return false; +bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist( + const GCS::Point& thePoint) const +{ + return hasSamePoint(myExternalPoints, thePoint) || hasSamePoint(myPoints, thePoint); } diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h index 558756492..d5acf494a 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.h @@ -43,9 +43,9 @@ public: /// \brief Send notification about update of the feature to all interested virtual void update(const FeaturePtr& theFeature); - /// \brief Verifies the entities are not coincident yet - /// \return \c true if the entities does not coincident - bool checkCoincidence(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2); + /// \brief Set coincidence between two given entities + /// \return \c true if the entities does not coincident yet + bool addCoincidence(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2); /// \brief Verifies the point is coincident to the feature /// \return \c true if the point is on the feature @@ -63,21 +63,31 @@ private: bool isExist(const EntityWrapperPtr& theEntity) const; /// Verify the point is already in the list bool isExist(const GCS::Point& thePoint) const; - /// Check the coincidence is not in list yet - bool isNewCoincidence(const EntityWrapperPtr& theEntityExist, - const EntityWrapperPtr& theOtherEntity); - bool isNewCoincidence(const EntityWrapperPtr& theEntityExist, - const CoincidentEntities& theOtherGroup, - const EntityWrapperPtr& theEntityInOtherGroup); - private: - bool hasExternal() const; + /// Add entity to group + bool add(const EntityWrapperPtr& theEntity); + + /// Remove entity from group + void remove(const EntityWrapperPtr& theEntity); + + /// Merge two groups + void merge(const CoincidentEntities& theOther); private: - /// external entity and set of entities connected to it - std::map > myExternalAndConnected; + std::set myPoints; ///< coincident points + std::set myExternalPoints; //< external points coincident to other points + std::set myFeatures; ///< other entities containing points }; + /// \brief Search the group of coincidences containing given entity. + /// Searches points only. + std::list::iterator findGroupOfCoincidence(const EntityWrapperPtr& theEntity); + + /// \brief Add entity to group of coincidences + /// \reutrn \c true if the entity is added, thus the coincidence is new + bool addToGroupOfCoincidence(CoincidentEntities& theGroup, const EntityWrapperPtr& theEntity); + +private: std::list myCoincident; ///< list of coincidences }; diff --git a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp index 81130989b..4c589919a 100644 --- a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp @@ -99,7 +99,7 @@ void SketchSolver_ConstraintCoincidence::notify(const FeaturePtr& theFeatur { PlaneGCSSolver_UpdateCoincidence* anUpdater = static_cast(theUpdater); - bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back()); + bool isAccepted = anUpdater->addCoincidence(myAttributes.front(), myAttributes.back()); // additionally check the point is coincident to extremity of coincident feature if (myFeatureExtremities[0] && myFeatureExtremities[1]) { diff --git a/src/SketchSolver/SketchSolver_ConstraintMiddle.cpp b/src/SketchSolver/SketchSolver_ConstraintMiddle.cpp index 6680004c8..e5388276c 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMiddle.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMiddle.cpp @@ -16,7 +16,7 @@ void SketchSolver_ConstraintMiddle::notify(const FeaturePtr& theFeature, { PlaneGCSSolver_UpdateCoincidence* anUpdater = static_cast(theUpdater); - bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back()); + bool isAccepted = anUpdater->addCoincidence(myAttributes.front(), myAttributes.back()); if (isAccepted) { if (!myInSolver) { myInSolver = true;