X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FPlaneGCSSolver%2FPlaneGCSSolver_UpdateCoincidence.cpp;h=8cb6f3ff95f8a6bb4ee26ec556b8868b09cf80e3;hb=87447545000c44e455431ed0d401f850f373374e;hp=01f30a4bf0f8411d254eeae05b13393cdfc5a6ba;hpb=407f8ee4d60b986fc6da2f8a6038787cae7a87ba;p=modules%2Fshaper.git diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp index 01f30a4bf..8cb6f3ff9 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp @@ -1,26 +1,46 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: PlaneGCSSolver_UpdateCoincidence.cpp -// Created: 17 Feb 2017 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2020 CEA/DEN, EDF R&D +// +// 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 +#include #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); @@ -29,7 +49,9 @@ void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserv void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature) { if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() || - theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID()) { + theFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID() || + theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID() || + theFeature->getKind() == SketchPlugin_ConstraintCollinear::ID()) { myCoincident.clear(); // notify listeners and stop procesing std::list::iterator anIt = myObservers.begin(); @@ -39,59 +61,193 @@ void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature) myNext->update(theFeature); } -static bool hasExternalPoint(const std::set& theCoincidences) +static bool hasAnotherExternalPoint(const std::set& theCoincidences, + const EntityWrapperPtr& thePoint) { std::set::const_iterator anIt = theCoincidences.begin(); for (; anIt != theCoincidences.end(); ++anIt) - if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal()) + if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal() && *anIt != thePoint) return true; return false; } -bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence( +bool PlaneGCSSolver_UpdateCoincidence::addCoincidence( const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2) { bool isAccepted = true; + std::list::iterator aFound[2] = { + findGroupOfCoincidence(theEntity1), + findGroupOfCoincidence(theEntity2) + }; - std::list >::iterator anIt = myCoincident.begin(); - std::list >::iterator aFound1 = myCoincident.end(); - std::list >::iterator aFound2 = myCoincident.end(); - for (; anIt != myCoincident.end(); ++anIt) { - if (aFound1 == myCoincident.end() && anIt->find(theEntity1) != anIt->end()) - aFound1 = anIt; - if (aFound2 == myCoincident.end() && anIt->find(theEntity2) != anIt->end()) - aFound2 = anIt; - if (aFound1 != myCoincident.end() && aFound2 != myCoincident.end()) - break; - } - - if (aFound1 == myCoincident.end() && aFound2 == myCoincident.end()) { + if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) { // new group of coincidence - std::set aNewCoinc; - aNewCoinc.insert(theEntity1); - aNewCoinc.insert(theEntity2); - myCoincident.push_back(aNewCoinc); - } else if (aFound1 == aFound2) // same group => already coincident + myCoincident.push_back(CoincidentEntities(theEntity1, theEntity2)); + } 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 (theEntity1->type() == ENTITY_POINT && theEntity2->type() == ENTITY_POINT && - (theEntity1->isExternal() || theEntity2->isExternal())) { - bool hasExternal = aFound1 != myCoincident.end() && hasExternalPoint(*aFound1); - hasExternal = hasExternal || (aFound2 != myCoincident.end() && hasExternalPoint(*aFound2)); - if (hasExternal) + } 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; + } } - if (aFound1 == myCoincident.end()) - aFound2->insert(theEntity1); - else if (aFound2 == myCoincident.end()) - aFound1->insert(theEntity2); - else { // merge two groups - aFound1->insert(aFound2->begin(), aFound2->end()); - myCoincident.erase(aFound2); - } + // merge + aFound[0]->merge(*aFound[1]); + myCoincident.erase(aFound[1]); } return isAccepted; } + +bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity( + const EntityWrapperPtr& thePoint, + const EntityWrapperPtr& theEntity) +{ + std::list::iterator anIt = findGroupOfCoincidence(thePoint); + if (anIt == myCoincident.end()) + return false; + + if (anIt->isExist(theEntity)) + return true; + + if (theEntity->type() == ENTITY_LINE) { + std::shared_ptr aLine = std::dynamic_pointer_cast( + std::dynamic_pointer_cast(theEntity)->entity()); + return anIt->isExist(aLine->p1) || anIt->isExist(aLine->p2); + } + 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); +} + + + + + +static const GCS::Point& toPoint(const EntityWrapperPtr& theEntity) +{ + PointWrapperPtr aPoint = std::dynamic_pointer_cast(theEntity); + return *(aPoint->point()); +} + +static double squareDistance(const GCS::Point& thePoint1, const GCS::Point& thePoint2) +{ + double dx = *thePoint1.x - *thePoint2.x; + double dy = *thePoint1.y - *thePoint2.y; + return dx * dx + dy * dy; +} + +static bool hasSamePoint(const std::set& theList, const GCS::Point& thePoint) +{ + std::set::const_iterator anIt = theList.begin(); + for (; anIt != theList.end(); ++anIt) + if (squareDistance(thePoint, toPoint(*anIt)) < 1.e-14) + return true; + return false; +} + +bool hasSamePoint(const std::set& theList, + const EntityWrapperPtr& thePoint) +{ + return hasSamePoint(theList, toPoint(thePoint)); +} + + +PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities( + const EntityWrapperPtr& theEntity1, + const EntityWrapperPtr& theEntity2) +{ + add(theEntity1); + add(theEntity2); +} + +bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::add( + const EntityWrapperPtr& theEntity) +{ + 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; +} + +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); +} + +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::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(); + } + + return myFeatures.find(theEntity) != myFeatures.end(); +} + +bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist( + const GCS::Point& thePoint) const +{ + return hasSamePoint(myExternalPoints, thePoint) || hasSamePoint(myPoints, thePoint); +} + +EntityWrapperPtr PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::externalPoint() const +{ + return myExternalPoints.empty() ? EntityWrapperPtr() : *myExternalPoints.begin(); +}