X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FPlaneGCSSolver%2FPlaneGCSSolver_UpdateCoincidence.cpp;h=d2f6a625433fe4c63a41d77ec0b18e4f7f82253a;hb=77ce6d35ac8d2f0fdaecb4f23e0870bf74e36103;hp=6b1d358cb6725c8e09b4b2e4e4b3d9584415fe8a;hpb=fe3678a85238df2b57ea18b341003ebef176e287;p=modules%2Fshaper.git diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp index 6b1d358cb..d2f6a6254 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp @@ -1,8 +1,21 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: PlaneGCSSolver_UpdateCoincidence.cpp -// Created: 17 Feb 2017 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2024 CEA, EDF +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include #include @@ -10,20 +23,24 @@ #include #include +#include #include #include +static bool hasSamePoint(const std::set& theList, + const EntityWrapperPtr& thePoint); + + void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserver, const std::string& theType) { if (theType == GROUP()) { std::list::iterator aPlaceToAdd = myObservers.end(); - // point-point coincidence is placed first - if (theObserver->getType() == CONSTRAINT_PT_PT_COINCIDENT) { - for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd) - if ((*aPlaceToAdd)->getType() != CONSTRAINT_PT_PT_COINCIDENT) - break; - } + // point-point coincidence is placed first, + // other constraints are sorted by their type + for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd) + if ((*aPlaceToAdd)->getType() > theObserver->getType()) + break; myObservers.insert(aPlaceToAdd, theObserver); } else myNext->attach(theObserver, theType); @@ -32,6 +49,7 @@ void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserv void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature) { if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() || + theFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID() || theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID() || theFeature->getKind() == SketchPlugin_ConstraintCollinear::ID()) { myCoincident.clear(); @@ -53,39 +71,42 @@ 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 + // first check the external points are equal + EntityWrapperPtr anExternal0 = aFound[0]->externalPoint(); + EntityWrapperPtr anExternal1 = aFound[1]->externalPoint(); + if (anExternal0 && anExternal1) { + std::set anExtList; + anExtList.insert(anExternal0); + if (hasSamePoint(anExtList, anExternal1)) { + // no need to add coincidence, because all points are + // already coincident to correct external points + isAccepted = false; + } } + + // merge + aFound[0]->merge(*aFound[1]); + myCoincident.erase(aFound[1]); } return isAccepted; @@ -95,11 +116,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; @@ -114,150 +131,123 @@ 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; + return theGroup.add(theEntity); +} -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) +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(); - return false; - } else { - myExternalAndConnected[theOtherEntity] = myExternalAndConnected[EntityWrapperPtr()]; - myExternalAndConnected.erase(EntityWrapperPtr()); - 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; +} - if (theEntityExist->isExternal()) { - myExternalAndConnected[theEntityExist].insert(theOtherEntity); - 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); +} - 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::merge( + const CoincidentEntities& theOther) +{ + myExternalPoints.insert(theOther.myExternalPoints.begin(), theOther.myExternalPoints.end()); + myPoints.insert(theOther.myPoints.begin(), theOther.myPoints.end()); + myFeatures.insert(theOther.myFeatures.begin(), theOther.myFeatures.end()); } -bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence( - const EntityWrapperPtr& theEntityExist, - const CoincidentEntities& theOtherGroup, - const EntityWrapperPtr& theEntityInOtherGroup) +bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist( + const EntityWrapperPtr& theEntity) const { - 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()); + if (theEntity->type() == ENTITY_POINT) { + if (theEntity->isExternal()) + return myExternalPoints.find(theEntity) != myExternalPoints.end(); + else + return myPoints.find(theEntity) != myPoints.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; - } + return myFeatures.find(theEntity) != myFeatures.end(); +} - std::map >::const_iterator - aFound = aSource.find(EntityWrapperPtr()); +bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist( + const GCS::Point& thePoint) const +{ + return hasSamePoint(myExternalPoints, thePoint) || hasSamePoint(myPoints, thePoint); +} - 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; +EntityWrapperPtr PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::externalPoint() const +{ + return myExternalPoints.empty() ? EntityWrapperPtr() : *myExternalPoints.begin(); }