X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Storage.cpp;h=9fb0369d59208b274ce90c4b7cb47966636bd16b;hb=c02fae5493cc6d56c9a1db3bdcf6d872f88fea07;hp=eecc86653a9c66fc4041ba9c3eb28ce5602686ce;hpb=29d446f4dd2969d80087745fe44adb5638d13de7;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index eecc86653..9fb0369d5 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -1,141 +1,133 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: SketchSolver_Storage.cpp -// Created: 30 Nov 2015 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2019 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 #include - - -/// \brief Verify two vectors of constraints are equal. -/// Vectors differ by the order of elements are equal. -static bool isEqual(const std::list& theCVec1, - const std::list& theCVec2); - - -void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint, - ConstraintWrapperPtr theSolverConstraint) +#include +#include +#include +#include +#include +#include + + +SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver) + : mySketchSolver(theSolver), + myNeedToResolve(false), + myEventsBlocked(false) { - std::list aConstrList(1, theSolverConstraint); - addConstraint(theConstraint, aConstrList); + // create updaters (constraints processed at first) + UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature); + myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater)); } -void SketchSolver_Storage::addConstraint( - ConstraintPtr theConstraint, - std::list theSolverConstraints) +void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint, + ConstraintWrapperPtr theSolverConstraint) { - std::map >::const_iterator + std::map::const_iterator aFound = myConstraintMap.find(theConstraint); - if (aFound == myConstraintMap.end() || !isEqual(aFound->second, theSolverConstraints)) + if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint) setNeedToResolve(true); - // Do not add point-point coincidence, because it is already made by setting - // the same parameters for both points - if (!theSolverConstraints.empty() && - theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) { - std::list::iterator aCIt = theSolverConstraints.begin(); - for (; aCIt != theSolverConstraints.end(); ++aCIt) - update(*aCIt); - } - myConstraintMap[theConstraint] = theSolverConstraints; +//// if (theSolverConstraints.empty()) { +//// // constraint links to the empty list, add its attributes linked to the empty entities +//// std::list aRefAttrs = +//// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); +//// std::list::const_iterator anAttrIt = aRefAttrs.begin(); +//// for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) { +//// AttributeRefAttrPtr aRef = +//// std::dynamic_pointer_cast(*anAttrIt); +//// if (aRef->isObject()) { +//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object()); +//// if (aFeature) addEntity(aFeature, EntityWrapperPtr()); +//// } else +//// addEntity(aRef->attr(), EntityWrapperPtr()); +//// } +//// std::list aRefLists = +//// theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId()); +//// for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) { +//// AttributeRefListPtr aRef = +//// std::dynamic_pointer_cast(*anAttrIt); +//// std::list anObj = aRef->list(); +//// std::list::iterator anIt = anObj.begin(); +//// for (; anIt != anObj.end(); ++anIt) { +//// FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); +//// if (aFeature) addEntity(aFeature, EntityWrapperPtr()); +//// } +//// } +//// } +//// else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) { +//// // Do not add point-point coincidence, because it is already made by setting +//// // the same parameters for both points +//// std::list::iterator aCIt = theSolverConstraints.begin(); +//// for (; aCIt != theSolverConstraints.end(); ++aCIt) +//// update(*aCIt); +//// } + + if (!theSolverConstraint || aFound == myConstraintMap.end()) + myConstraintMap[theConstraint] = theSolverConstraint; + // block events if necessary + if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid()) + theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked); } void SketchSolver_Storage::addEntity(FeaturePtr theFeature, EntityWrapperPtr theSolverEntity) { - std::map::const_iterator aFound = myFeatureMap.find(theFeature); - if (aFound == myFeatureMap.end() || !aFound->second->isEqual(theSolverEntity)) - setNeedToResolve(true); // the entity is new or modified + if (theSolverEntity) { + myFeatureMap[theFeature] = theSolverEntity; + setNeedToResolve(true); + } - myFeatureMap[theFeature] = theSolverEntity; + // block events if necessary + if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid()) + theFeature->data()->blockSendAttributeUpdated(myEventsBlocked); } void SketchSolver_Storage::addEntity(AttributePtr theAttribute, EntityWrapperPtr theSolverEntity) { - std::map::const_iterator aFound = myAttributeMap.find(theAttribute); - if (aFound == myAttributeMap.end() || !aFound->second->isEqual(theSolverEntity)) - setNeedToResolve(true); // the entity is new or modified - - myAttributeMap[theAttribute] = theSolverEntity; -} - - -bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup) -{ - bool isUpdated = false; - EntityWrapperPtr aRelated = entity(theFeature); - if (!aRelated) { // Feature is not exist, create it - std::list aSubs; - // Firstly, create/update its attributes - std::list anAttrs = - theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list::const_iterator anIt = anAttrs.begin(); - for (; anIt != anAttrs.end(); ++anIt) { - isUpdated = update(*anIt, theGroup) || isUpdated; - aSubs.push_back(entity(*anIt)); - } - // If the feature is a circle, add its radius as a sub - if (theFeature->getKind() == SketchPlugin_Circle::ID()) { - AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID()); - isUpdated = update(aRadius, theGroup) || isUpdated; - aSubs.push_back(entity(aRadius)); - } - // If the feature if circle or arc, we need to add normal of the sketch to the list of subs - if (theFeature->getKind() == SketchPlugin_Arc::ID() || - theFeature->getKind() == SketchPlugin_Circle::ID()) { - EntityWrapperPtr aNormal = getNormal(); - if (aNormal) aSubs.push_back(aNormal); - } - // Secondly, convert feature - BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); - aRelated = aBuilder->createFeature(theFeature, aSubs, theGroup); - if (!aRelated) - return false; - addEntity(theFeature, aRelated); - } else if (theGroup != GID_UNKNOWN) - changeGroup(aRelated, theGroup); - return update(aRelated) || isUpdated; -} - -bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup) -{ - AttributePtr anAttribute = theAttribute; - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttribute); - if (aRefAttr) { - if (aRefAttr->isObject()) { - FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); - return update(aFeature, theGroup); - } else - anAttribute = aRefAttr->attr(); + if (theSolverEntity) { + myAttributeMap[theAttribute] = theSolverEntity; + setNeedToResolve(true); } - EntityWrapperPtr aRelated = entity(anAttribute); - if (!aRelated) { // Attribute is not exist, create it - BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); - aRelated = aBuilder->createAttribute(anAttribute, theGroup); - if (!aRelated) - return false; - addEntity(anAttribute, aRelated); - } else if (theGroup != GID_UNKNOWN) - changeGroup(aRelated, theGroup); - return update(aRelated); + // block events if necessary + if (myEventsBlocked && theAttribute->owner() && + theAttribute->owner()->data() && theAttribute->owner()->data()->isValid()) + theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked); } -const std::list& SketchSolver_Storage::constraint( +const ConstraintWrapperPtr& SketchSolver_Storage::constraint( const ConstraintPtr& theConstraint) const { - static std::list aDummy; + static ConstraintWrapperPtr aDummy; - std::map>::const_iterator + std::map::const_iterator aFound = myConstraintMap.find(theConstraint); if (aFound != myConstraintMap.end()) return aFound->second; @@ -144,18 +136,16 @@ const std::list& SketchSolver_Storage::constraint( const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const { - static EntityWrapperPtr aDummy; - std::map::const_iterator aFound = myFeatureMap.find(theFeature); if (aFound != myFeatureMap.end()) return aFound->second; + + static EntityWrapperPtr aDummy; return aDummy; } const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const { - static EntityWrapperPtr aDummy; - std::map::const_iterator aFound = myAttributeMap.find(theAttribute); if (aFound != myAttributeMap.end()) @@ -164,62 +154,40 @@ const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttr AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); if (aRefAttr) { + AttributePtr anAttribute; + if (aRefAttr->isObject()) { - FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); - return entity(aFeature); + /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test + FeaturePtr aFeature; + resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute); + if (aFeature) + return entity(aFeature); } else - return entity(aRefAttr->attr()); + anAttribute = aRefAttr->attr(); + + return entity(anAttribute); } + + static EntityWrapperPtr aDummy; return aDummy; } -bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const + +void SketchSolver_Storage::removeFeature(FeaturePtr theFeature) { - if (!theFeature) - return false; - if (myConstraintMap.empty()) - return true; // empty storage interacts with each feature - - ConstraintPtr aConstraint = std::dynamic_pointer_cast(theFeature); - if (aConstraint) { - if (myConstraintMap.find(aConstraint) != myConstraintMap.end()) - return true; - } else if (myFeatureMap.find(theFeature) != myFeatureMap.end()) - return true; - - std::list anAttrList = theFeature->data()->attributes(std::string()); - std::list::const_iterator anIt = anAttrList.begin(); - for (; anIt != anAttrList.end(); ++anIt) - if (isInteract(*anIt)) - return true; - - return false; + myFeatureMap.erase(theFeature); + myNeedToResolve = true; } -bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const +void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute) { - if (!theAttribute) - return false; - - AttributeRefAttrPtr aRefAttr = - std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return myAttributeMap.find(theAttribute) != myAttributeMap.end(); - if (!aRefAttr->isObject()) - return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end(); - - FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); - return isInteract(aFeature); + myAttributeMap.erase(theAttribute); + myNeedToResolve = true; } -bool SketchSolver_Storage::isConsistent() const + +bool SketchSolver_Storage::areFeaturesValid() const { - // Check the constraints are valid - std::map >::const_iterator - aCIter = myConstraintMap.begin(); - for (; aCIter != myConstraintMap.end(); ++aCIter) - if (!aCIter->first->data() || !aCIter->first->data()->isValid()) - return false; // Check the features are valid std::map::const_iterator aFIter = myFeatureMap.begin(); for (; aFIter != myFeatureMap.end(); aFIter++) @@ -228,72 +196,8 @@ bool SketchSolver_Storage::isConsistent() const return true; } -void SketchSolver_Storage::removeInvalidEntities() -{ - // Remove invalid constraints - std::list anInvalidConstraints; - std::map >::const_iterator - aCIter = myConstraintMap.begin(); - for (; aCIter != myConstraintMap.end(); ++aCIter) - if (!aCIter->first->data() || !aCIter->first->data()->isValid()) - anInvalidConstraints.push_back(aCIter->first); - std::list::const_iterator anInvCIt = anInvalidConstraints.begin(); - for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt) - removeConstraint(*anInvCIt); - // Remove invalid features - std::list anInvalidFeatures; - std::map::const_iterator aFIter = myFeatureMap.begin(); - for (; aFIter != myFeatureMap.end(); aFIter++) - if (!aFIter->first->data() || !aFIter->first->data()->isValid()) - anInvalidFeatures.push_back(aFIter->first); - std::list::const_iterator anInvFIt = anInvalidFeatures.begin(); - for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt) - removeEntity(*anInvFIt); -} - -EntityWrapperPtr SketchSolver_Storage::getNormal() const -{ - EntityWrapperPtr aSketch = sketch(); - if (!aSketch) - return aSketch; - - // Find normal entity - const std::list& aSketchSubs = aSketch->subEntities(); - std::list::const_iterator aSIt = aSketchSubs.begin(); - for (; aSIt != aSketchSubs.end(); ++aSIt) - if ((*aSIt)->type() == ENTITY_NORMAL) - return *aSIt; - return EntityWrapperPtr(); -} - -const EntityWrapperPtr& SketchSolver_Storage::sketch() const -{ - static EntityWrapperPtr aDummySketch; - - std::map::const_iterator aFIt = myFeatureMap.begin(); - for (; aFIt != myFeatureMap.end(); ++aFIt) - if (aFIt->second->type() == ENTITY_SKETCH) - break; - if (aFIt == myFeatureMap.end()) - return aDummySketch; - return aFIt->second; -} - -void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch) +void SketchSolver_Storage::blockEvents(bool isBlocked) { - if (sketch()) - return; - addEntity(FeaturePtr(), theSketch); -} - -void SketchSolver_Storage::blockEvents(bool isBlocked) const -{ - std::map >::const_iterator - aCIter = myConstraintMap.begin(); - for (; aCIter != myConstraintMap.end(); aCIter++) - if (aCIter->first->data() && aCIter->first->data()->isValid()) - aCIter->first->data()->blockSendAttributeUpdated(isBlocked); - std::map::const_iterator aFIter = myFeatureMap.begin(); for (; aFIter != myFeatureMap.end(); aFIter++) if (aFIter->first->data() && aFIter->first->data()->isValid()) @@ -304,37 +208,59 @@ void SketchSolver_Storage::blockEvents(bool isBlocked) const if (anAtIter->first->owner() && anAtIter->first->owner()->data() && anAtIter->first->owner()->data()->isValid()) anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked); -} + myEventsBlocked = isBlocked; +} +std::set SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const +{ + std::set aConflicting; + std::map::const_iterator + aConstrIt = myConstraintMap.begin(); + for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) { + if (theSolver->isConflicting(aConstrIt->second->id())) + aConflicting.insert(aConstrIt->first); + } + return aConflicting; +} +void SketchSolver_Storage::subscribeUpdates( + SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const +{ + myUpdaters->attach(theSubscriber, theGroup); +} +void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const +{ + myUpdaters->detach(theSubscriber); +} +void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const +{ + myUpdaters->update(theFeature); +} -// ============== Auxiliary functions ==================================== -bool isEqual(const std::list& theCVec1, - const std::list& theCVec2) +void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult, + FeaturePtr& theFeature, AttributePtr& theAttribute) { - if (theCVec1.size() != theCVec2.size()) - return false; - - std::list aChecked(theCVec2.size(), false); - std::list::const_iterator anIt1 = theCVec1.begin(); - for (; anIt1 != theCVec1.end(); ++anIt1) { - std::list::const_iterator anIt2 = theCVec2.begin(); - std::list::iterator aCheckIt = aChecked.begin(); - while (aCheckIt != aChecked.end() && *aCheckIt) { - ++aCheckIt; - ++anIt2; + FeaturePtr aFeature = ModelAPI_Feature::feature(theResult); + if (!aFeature) + return; + + // if the feature has several results, we choose which one is referred + const std::list& aResults = aFeature->results(); + if (aResults.size() > 1 && theResult != aFeature->lastResult()) { + // actually, the attribute refers to center of arc or circle, + // but not the edge, get correct attributes + std::string anAttrName; + if (aFeature->getKind() == SketchPlugin_Arc::ID()) + anAttrName = SketchPlugin_Arc::CENTER_ID(); + else if (aFeature->getKind() == SketchPlugin_Circle::ID()) + anAttrName = SketchPlugin_Circle::CENTER_ID(); + if (!anAttrName.empty()) { + theAttribute = aFeature->attribute(anAttrName); + aFeature = FeaturePtr(); } - for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt) - if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) { - *aCheckIt = true; - break; - } - // the same constraint is not found - if (anIt2 == theCVec2.end()) - return false; } - return true; + theFeature = aFeature; }