From 8e3ea4b8a0e09cfb299a7a74f97b2df3f7f1b657 Mon Sep 17 00:00:00 2001 From: azv Date: Fri, 18 Dec 2015 11:56:05 +0300 Subject: [PATCH] Correct processing arcs in SketchSolver with SolveSpace (issue #1144) --- src/SketchSolver/SketchSolver_Constraint.cpp | 6 - src/SketchSolver/SketchSolver_Constraint.h | 3 - src/SketchSolver/SketchSolver_Group.cpp | 25 +- src/SketchSolver/SketchSolver_Storage.cpp | 191 ++++++++++++- src/SketchSolver/SketchSolver_Storage.h | 43 +-- .../SolveSpaceSolver_Builder.cpp | 7 +- .../SolveSpaceSolver_EntityWrapper.cpp | 11 + .../SolveSpaceSolver_EntityWrapper.h | 7 + .../SolveSpaceSolver_Storage.cpp | 257 ++---------------- .../SolveSpaceSolver_Storage.h | 57 ++-- 10 files changed, 298 insertions(+), 309 deletions(-) diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index 96051c3d0..1de16cfe7 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -217,9 +217,3 @@ bool SketchSolver_Constraint::isUsed(AttributePtr theAttribute) const return true; return false; } - -void SketchSolver_Constraint::makeTemporary() const -{ - myStorage->setTemporary(myBaseConstraint); -} - diff --git a/src/SketchSolver/SketchSolver_Constraint.h b/src/SketchSolver/SketchSolver_Constraint.h index 6f8a6fd79..817afa58d 100644 --- a/src/SketchSolver/SketchSolver_Constraint.h +++ b/src/SketchSolver/SketchSolver_Constraint.h @@ -57,9 +57,6 @@ public: virtual SketchSolver_ConstraintType getType() const { return myType; } - /// \brief The constraint is made temporary - void makeTemporary() const; - /// \brief Verify the feature or any its attribute is used by constraint bool isUsed(FeaturePtr theFeature) const; /// \brief Verify the attribute is used by constraint diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index ee4c2da05..0959722ee 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -133,6 +133,7 @@ bool SketchSolver_Group::changeConstraint( return false; BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + myStorage->blockEvents(true); bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end(); if (isNewConstraint) { @@ -200,6 +201,7 @@ bool SketchSolver_Group::updateFeature(FeaturePtr theFeature) if (!checkFeatureValidity(theFeature)) return false; + myStorage->blockEvents(true); myStorage->refresh(true); return myStorage->update(theFeature); } @@ -209,6 +211,7 @@ void SketchSolver_Group::moveFeature(FeaturePtr theFeature) BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); // Firstly, revert changes in the fixed entities + myStorage->blockEvents(true); myStorage->refresh(true); // Secondly, search attributes of the feature in the list of the Multi constraints and update them @@ -295,19 +298,17 @@ bool SketchSolver_Group::resolveConstraints() // To avoid overconstraint situation, we will remove temporary constraints one-by-one // and try to find the case without overconstraint bool isLastChance = false; - size_t aNbTemp = myStorage->nbTemporary(); while (true) { aResult = mySketchSolver->solve(); if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET || isLastChance) break; - if (aNbTemp == 0) { - // try to update parameters and resolve once again - ConstraintConstraintMap::iterator aConstrIt = myConstraints.begin(); - for (; aConstrIt != myConstraints.end(); ++aConstrIt) - aConstrIt->second->update(); - isLastChance = true; - } else - aNbTemp = myStorage->removeTemporary(); + // try to update parameters and resolve once again + ConstraintConstraintMap::iterator aConstrIt = myConstraints.begin(); + for (; aConstrIt != myConstraints.end(); ++aConstrIt) + aConstrIt->second->update(); + isLastChance = true; + + removeTemporaryConstraints(); mySketchSolver->calculateFailedConstraints(true); // something failed => need to find it myStorage->initializeSolver(mySketchSolver); } @@ -353,6 +354,7 @@ bool SketchSolver_Group::resolveConstraints() myStorage->refresh(); } removeTemporaryConstraints(); + myStorage->blockEvents(false); myStorage->setNeedToResolve(false); return aResolved; } @@ -497,10 +499,6 @@ void SketchSolver_Group::removeTemporaryConstraints() for (; aTmpIt != myTempConstraints.end(); ++aTmpIt) (*aTmpIt)->remove(); - size_t aNbTemp = myStorage->nbTemporary(); - if (aNbTemp > 0) - myStorage->removeTemporary(aNbTemp); - if (!myTempConstraints.empty()) myStorage->verifyFixed(); myStorage->setNeedToResolve(false); @@ -569,7 +567,6 @@ bool SketchSolver_Group::isComplexConstraint(FeaturePtr theConstraint) // ============================================================================ void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint) { - theConstraint->makeTemporary(); myTempConstraints.insert(theConstraint); } diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index 8db3eaa5c..feae88f9c 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -44,6 +44,9 @@ void SketchSolver_Storage::addConstraint( update(*aCIt); } myConstraintMap[theConstraint] = theSolverConstraints; + // block events if necessary + if (myEventsBlocked && theConstraint->data() && theConstraint->data()->isValid()) + theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked); } void SketchSolver_Storage::addEntity(FeaturePtr theFeature, @@ -54,6 +57,9 @@ void SketchSolver_Storage::addEntity(FeaturePtr theFeature, setNeedToResolve(true); // the entity is new or modified myFeatureMap[theFeature] = theSolverEntity; + // block events if necessary + if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid()) + theFeature->data()->blockSendAttributeUpdated(myEventsBlocked); } void SketchSolver_Storage::addEntity(AttributePtr theAttribute, @@ -64,6 +70,10 @@ void SketchSolver_Storage::addEntity(AttributePtr theAttribute, setNeedToResolve(true); // the entity is new or modified myAttributeMap[theAttribute] = theSolverEntity; + // block events if necessary + if (myEventsBlocked && theAttribute->owner() && + theAttribute->owner()->data() && theAttribute->owner()->data()->isValid()) + theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked); } @@ -73,6 +83,8 @@ bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup EntityWrapperPtr aRelated = entity(theFeature); if (!aRelated) { // Feature is not exist, create it std::list aSubs; + // Reserve the feature in the map of features (do not want to add several copies of it) + myFeatureMap[theFeature] = aRelated; // Firstly, create/update its attributes std::list anAttrs = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); @@ -95,7 +107,8 @@ bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup } // Secondly, convert feature BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); - aRelated = aBuilder->createFeature(theFeature, aSubs, theGroup); + GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID; + aRelated = aBuilder->createFeature(theFeature, aSubs, aGroup); if (!aRelated) return false; addEntity(theFeature, aRelated); @@ -119,7 +132,8 @@ bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theG EntityWrapperPtr aRelated = entity(anAttribute); if (!aRelated) { // Attribute is not exist, create it BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); - aRelated = aBuilder->createAttribute(anAttribute, theGroup); + GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID; + aRelated = aBuilder->createAttribute(anAttribute, aGroup); if (!aRelated) return false; addEntity(anAttribute, aRelated); @@ -173,6 +187,171 @@ const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttr return aDummy; } +bool SketchSolver_Storage::removeConstraint(ConstraintPtr theConstraint) +{ + std::map >::iterator + aFound = myConstraintMap.find(theConstraint); + if (aFound == myConstraintMap.end()) + return true; // no constraint, already deleted + + // Remove constraint + std::list aConstrList = aFound->second; + myConstraintMap.erase(aFound); + // Remove SolveSpace constraints + bool isFullyRemoved = true; + std::list::iterator anIt = aConstrList.begin(); + while (anIt != aConstrList.end()) { + if (remove(*anIt)) { + std::list::iterator aRemoveIt = anIt++; + aConstrList.erase(aRemoveIt); + } else { + isFullyRemoved = false; + ++anIt; + } + } + if (!isFullyRemoved) + myConstraintMap[theConstraint] = aConstrList; + return isFullyRemoved; +} + +template +static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity) +{ + std::list::const_iterator anEntIt = theConstraint->entities().begin(); + for (; anEntIt != theConstraint->entities().end(); ++anEntIt) + if ((*anEntIt)->isBase(theEntity)) + return true; + return false; +} + +static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity) +{ + std::list::const_iterator aSubIt = theFeature->subEntities().begin(); + for (; aSubIt != theFeature->subEntities().end(); ++aSubIt) + if ((*aSubIt)->isBase(theSubEntity)) + return true; + return false; +} + +bool SketchSolver_Storage::isUsed(FeaturePtr theFeature) const +{ + std::map >::const_iterator + aCIt = myConstraintMap.begin(); + std::list::const_iterator aCWIt; + for (; aCIt != myConstraintMap.end(); ++aCIt) + for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt) + if (::isUsed(*aCWIt, theFeature)) + return true; + // check attributes + std::list anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::const_iterator anIt = anAttrList.begin(); + for (; anIt != anAttrList.end(); ++anIt) + if (isUsed(*anIt)) + return true; + return false; +} + +bool SketchSolver_Storage::isUsed(AttributePtr theAttribute) const +{ + AttributePtr anAttribute = theAttribute; + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttribute); + if (aRefAttr) { + if (aRefAttr->isObject()) + return isUsed(ModelAPI_Feature::feature(aRefAttr->object())); + else + anAttribute = aRefAttr->attr(); + } + + std::map >::const_iterator + aCIt = myConstraintMap.begin(); + std::list::const_iterator aCWIt; + for (; aCIt != myConstraintMap.end(); ++aCIt) + for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt) + if (::isUsed(*aCWIt, anAttribute)) + return true; + return false; +} + + +bool SketchSolver_Storage::removeEntity(FeaturePtr theFeature) +{ + std::map::iterator aFound = myFeatureMap.find(theFeature); + if (aFound == myFeatureMap.end()) + return false; // feature not found, nothing to delete + + // Check the feature is not used by constraints + if (isUsed(theFeature)) + return false; // the feature is used, don't remove it + + // Remove feature + EntityWrapperPtr anEntity = aFound->second; + myFeatureMap.erase(aFound); + if (remove(anEntity)) + return true; + // feature is not removed, revert operation + myFeatureMap[theFeature] = anEntity; + return false; +} + +bool SketchSolver_Storage::removeEntity(AttributePtr theAttribute) +{ + std::map::iterator aFound = myAttributeMap.find(theAttribute); + if (aFound == myAttributeMap.end()) + return false; // attribute not found, nothing to delete + + // Check the attribute is not used by constraints + if (isUsed(theAttribute)) + return false; // the attribute is used, don't remove it + // Check the attribute is not used by other features + std::map::const_iterator aFIt = myFeatureMap.begin(); + for (; aFIt != myFeatureMap.end(); ++aFIt) + if (::isUsed(aFIt->second, theAttribute)) // the attribute is used, don't remove it + return false; + + // Remove attribute + EntityWrapperPtr anEntity = aFound->second; + myAttributeMap.erase(aFound); + if (remove(anEntity)) + return true; + // attribute is not removed, revert operation + myAttributeMap[theAttribute] = anEntity; + return false; +} + + +bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint) +{ + bool isFullyRemoved = true; + std::list::const_iterator anIt = theConstraint->entities().begin(); + for (; anIt != theConstraint->entities().end(); ++anIt) { + FeaturePtr aBaseFeature = (*anIt)->baseFeature(); + if (aBaseFeature) + isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved; + else + isFullyRemoved = SketchSolver_Storage::removeEntity((*anIt)->baseAttribute()) && isFullyRemoved; + } + return isFullyRemoved; +} + +bool SketchSolver_Storage::remove(EntityWrapperPtr theEntity) +{ + bool isFullyRemoved = true; + std::list::const_iterator anEntIt = theEntity->subEntities().begin(); + for (; anEntIt != theEntity->subEntities().end(); ++anEntIt) { + FeaturePtr aBaseFeature = (*anEntIt)->baseFeature(); + if (aBaseFeature) + isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved; + else + isFullyRemoved = SketchSolver_Storage::removeEntity((*anEntIt)->baseAttribute()) && isFullyRemoved; + } + + std::list::const_iterator aParIt = theEntity->parameters().begin(); + for (; aParIt != theEntity->parameters().end(); ++aParIt) + isFullyRemoved = remove(*aParIt) && isFullyRemoved; + return isFullyRemoved; +} + + bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const { if (!theFeature) @@ -293,7 +472,7 @@ const EntityWrapperPtr& SketchSolver_Storage::sketch() const std::map::const_iterator aFIt = myFeatureMap.begin(); for (; aFIt != myFeatureMap.end(); ++aFIt) - if (aFIt->second->type() == ENTITY_SKETCH) + if (aFIt->second && aFIt->second->type() == ENTITY_SKETCH) break; if (aFIt == myFeatureMap.end()) return aDummySketch; @@ -307,8 +486,11 @@ void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch) addEntity(FeaturePtr(), theSketch); } -void SketchSolver_Storage::blockEvents(bool isBlocked) const +void SketchSolver_Storage::blockEvents(bool isBlocked) { + if (isBlocked == myEventsBlocked) + return; + std::map >::const_iterator aCIter = myConstraintMap.begin(); for (; aCIter != myConstraintMap.end(); aCIter++) @@ -325,6 +507,7 @@ 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; } diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index ee27e9d14..26ccd019a 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -18,8 +18,10 @@ #include #include + typedef std::map > CoincidentPointsMap; + /** \class SketchSolver_Storage * \ingroup Plugins * \brief Interface to map SketchPlugin features to the entities of corresponding solver. @@ -34,7 +36,8 @@ private: public: SketchSolver_Storage(const GroupID& theGroup) : myGroupID(theGroup), - myNeedToResolve(false) + myNeedToResolve(false), + myEventsBlocked(false) {} /// \brief Change mapping between constraint from SketchPlugin and @@ -85,26 +88,26 @@ public: /// \brief Removes constraint from the storage /// \return \c true if the constraint and all its parameters are removed successfully - virtual bool removeConstraint(ConstraintPtr theConstraint) = 0; + SKETCHSOLVER_EXPORT bool removeConstraint(ConstraintPtr theConstraint); /// \brief Removes feature from the storage /// \return \c true if the feature and its attributes are removed successfully; /// \c false if the feature or any it attribute is used by remaining constraints. - virtual bool removeEntity(FeaturePtr theFeature) = 0; + SKETCHSOLVER_EXPORT bool removeEntity(FeaturePtr theFeature); /// \brief Removes attribute from the storage /// \return \c true if the attribute is not used by remaining features and constraints - virtual bool removeEntity(AttributePtr theAttribute) = 0; + SKETCHSOLVER_EXPORT bool removeEntity(AttributePtr theAttribute); /// \brief Remove all features became invalid SKETCHSOLVER_EXPORT void removeInvalidEntities(); - /// \brief Mark specified constraint as temporary - virtual void setTemporary(ConstraintPtr theConstraint) = 0; - /// \brief Returns number of temporary constraints - virtual size_t nbTemporary() const = 0; - /// \brief Remove temporary constraints - /// \param theNbConstraints [in] number of temporary constraints to be deleted - /// \return number of remaining temporary constraints - virtual size_t removeTemporary(size_t theNbConstraints = 1) = 0; +//// /// \brief Mark specified constraint as temporary +//// virtual void setTemporary(ConstraintPtr theConstraint) = 0; +//// /// \brief Returns number of temporary constraints +//// virtual size_t nbTemporary() const = 0; +//// /// \brief Remove temporary constraints +//// /// \param theNbConstraints [in] number of temporary constraints to be deleted +//// /// \return number of remaining temporary constraints +//// virtual size_t removeTemporary(size_t theNbConstraints = 1) = 0; /// \brief Check whether the feature or its attributes are used by this storage /// \param theFeature [in] feature to be checked @@ -145,6 +148,9 @@ public: virtual EntityWrapperPtr calculateMiddlePoint(EntityWrapperPtr theBase, double theCoeff) = 0; + /// \brief Block or unblock events when refreshing features + SKETCHSOLVER_EXPORT void blockEvents(bool isBlocked); + protected: /// \brief Change mapping feature from SketchPlugin and /// the entity applicable for corresponding solver. @@ -173,10 +179,10 @@ protected: /// \brief Remove constraint /// \return \c true if the constraint and all its parameters are removed successfully - virtual bool remove(ConstraintWrapperPtr theConstraint) = 0; + SKETCHSOLVER_EXPORT virtual bool remove(ConstraintWrapperPtr theConstraint); /// \brief Remove entity /// \return \c true if the entity and all its parameters are removed successfully - virtual bool remove(EntityWrapperPtr theEntity) = 0; + SKETCHSOLVER_EXPORT virtual bool remove(EntityWrapperPtr theEntity); /// \brief Remove parameter /// \return \c true if the parameter has been removed virtual bool remove(ParameterWrapperPtr theParameter) = 0; @@ -186,16 +192,19 @@ protected: /// \brief Update the group for the given parameter virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup) = 0; - /// \brief Block or unblock events when refreshing features - SKETCHSOLVER_EXPORT void blockEvents(bool isBlocked) const; - private: /// \brief Find the normal of the sketch EntityWrapperPtr getNormal() const; + /// \brief Verify the feature or any its attribute is used by constraint + bool isUsed(FeaturePtr theFeature) const; + /// \brief Verify the attribute is used by constraint + bool isUsed(AttributePtr theAttirubute) const; + protected: GroupID myGroupID; ///< identifier of the group, this storage belongs to bool myNeedToResolve; ///< parameters are changed and group needs to be resolved + bool myEventsBlocked; ///< indicates that features do not send events /// map SketchPlugin constraint to a list of solver's constraints std::map > myConstraintMap; diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp index eabf9f6ae..46fc1b20f 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Builder.cpp @@ -311,11 +311,12 @@ EntityWrapperPtr SolveSpaceSolver_Builder::createFeature( if (!aSub) return aDummy; + std::shared_ptr aPointFeature = + std::dynamic_pointer_cast(theFeature); + const Slvs_Entity& aSubEnt = std::dynamic_pointer_cast(aSub)->entity(); - EntityWrapperPtr aNewEntity(new SolveSpaceSolver_EntityWrapper(theFeature, aSubEnt)); - aNewEntity->setSubEntities(std::list(1, aSub)); - return aNewEntity; + return EntityWrapperPtr(new SolveSpaceSolver_EntityWrapper(aPointFeature, aPoint, aSubEnt)); } // wrong entity diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.cpp index 1cb81157d..bd6f61676 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.cpp @@ -20,6 +20,17 @@ SolveSpaceSolver_EntityWrapper::SolveSpaceSolver_EntityWrapper( myBaseAttribute = theAttribute; } +SolveSpaceSolver_EntityWrapper::SolveSpaceSolver_EntityWrapper( + const std::shared_ptr theFeature, + const AttributePtr theAttribute, + const Slvs_Entity& theEntity) + : myEntity(theEntity) +{ + myBaseFeature = FeaturePtr(theFeature); + myBaseAttribute = theAttribute; +} + + EntityID SolveSpaceSolver_EntityWrapper::id() const { return (EntityID)myEntity.h; diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.h index 566625f91..b006251eb 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.h +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_EntityWrapper.h @@ -10,6 +10,8 @@ #include #include +#include + /** * Wrapper providing operations with SolveSpace entities. */ @@ -19,6 +21,11 @@ public: SolveSpaceSolver_EntityWrapper(const FeaturePtr theFeature, const Slvs_Entity& theEntity); SolveSpaceSolver_EntityWrapper(const AttributePtr theAttribute, const Slvs_Entity& theEntity); + /// \brief Constructor useful for SketchPlugin_Point only + SolveSpaceSolver_EntityWrapper(const std::shared_ptr theFeature, + const AttributePtr theAttribute, + const Slvs_Entity& theEntity); + /// \brief Return SolveSpace entity const Slvs_Entity& entity() const { return myEntity; } diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp index 5fe40328e..d48730926 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp @@ -162,6 +162,15 @@ bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity) isUpdated = true; } } + if (theEntity->type() == ENTITY_POINT && aSubEntities.size() == 1) { + // theEntity is based on SketchPlugin_Point => need to substitute its attribute instead + bool isNew = (aSlvsEnt.h == SLVS_E_UNKNOWN); + aSlvsEnt = getEntity(aSlvsEnt.point[0]); + if (isNew) { + anEntity->changeEntity() = aSlvsEnt; + isUpdated = true; + } + } // update entity itself if (aSlvsEnt.wrkpl == SLVS_E_UNKNOWN && myWorkplaneID != SLVS_E_UNKNOWN) @@ -181,8 +190,13 @@ bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity) FeaturePtr aFeature = ModelAPI_Feature::feature(theEntity->baseAttribute()->owner()); if (aFeature->getKind() == SketchPlugin_Arc::ID() && myFeatureMap.find(aFeature) == myFeatureMap.end()) { - myFeatureMap[aFeature] = EntityWrapperPtr(); - return SketchSolver_Storage::update(aFeature, myGroupID); + // Additional checking that all attributes are initialized + if (aFeature->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() && + aFeature->attribute(SketchPlugin_Arc::START_ID())->isInitialized() && + aFeature->attribute(SketchPlugin_Arc::END_ID())->isInitialized()) { + myFeatureMap[aFeature] = EntityWrapperPtr(); + return SketchSolver_Storage::update(aFeature); + } } } } @@ -327,6 +341,8 @@ void SolveSpaceSolver_Storage::replaceInFeatures( { std::map::const_iterator anIt = myFeatureMap.begin(); for (; anIt != myFeatureMap.end(); ++anIt) { + if (!anIt->second) + continue; bool isUpdated = false; std::list aSubs = anIt->second->subEntities(); std::list::iterator aSubIt = aSubs.begin(); @@ -1124,67 +1140,6 @@ void SolveSpaceSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& myFixed = theConstraintID; } -void SolveSpaceSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID) -{ - myTemporaryConstraints.insert(theConstraintID); -} - -void SolveSpaceSolver_Storage::removeAllTemporary() -{ - myTemporaryConstraints.clear(); -} - -size_t SolveSpaceSolver_Storage::removeTemporary(size_t theNbConstraints) -{ - if (myTemporaryConstraints.empty()) - return 0; - // Search the point-on-line or a non-rigid constraint - std::set::iterator aCIt = myTemporaryConstraints.begin(); - for (; aCIt != myTemporaryConstraints.end(); aCIt++) { - int aPos = Search(*aCIt, myConstraints); - if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED) - break; - std::vector::iterator anIt = myConstraints.begin(); - for (; anIt != myConstraints.end(); anIt++) - if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA) - break; - if (anIt != myConstraints.end()) - break; - } - if (aCIt == myTemporaryConstraints.end()) - aCIt = myTemporaryConstraints.begin(); - bool aNewFixed = false; - - size_t aNbRemain = theNbConstraints; - while (aNbRemain > 0 && aCIt != myTemporaryConstraints.end()) { - aNewFixed = aNewFixed || (*aCIt == myFixed); - --aNbRemain; - - std::set::iterator aRemoveIt = aCIt++; - removeConstraint(*aRemoveIt); - myTemporaryConstraints.erase(aRemoveIt); - if (aCIt == myTemporaryConstraints.end()) - aCIt = myTemporaryConstraints.begin(); - } - - if (aNewFixed) { - for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) { - int aPos = Search(*aCIt, myConstraints); - if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) { - myFixed = *aCIt; - break; - } - } - } - return myTemporaryConstraints.size(); -} - -bool SolveSpaceSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const -{ - return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end(); -} - - void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver) { @@ -1280,7 +1235,7 @@ void SolveSpaceSolver_Storage::fixPoint(const Slvs_Entity& thePoint, Slvs_Constraint aConstraint; Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN; bool isFixed = isPointFixed(thePoint.h, aConstrID, true); - bool isForceUpdate = (isFixed && isTemporary(aConstrID)); + bool isForceUpdate = (isFixed /*&& isTemporary(aConstrID)*/); if (!isForceUpdate) { // create new constraint if (isFixed) return; aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl, @@ -1519,142 +1474,6 @@ bool SolveSpaceSolver_Storage::isUsedInEqual( return false; } -void SolveSpaceSolver_Storage::setTemporary(ConstraintPtr theConstraint) -{ - // TODO -} - -bool SolveSpaceSolver_Storage::removeConstraint(ConstraintPtr theConstraint) -{ - std::map >::iterator - aFound = myConstraintMap.find(theConstraint); - if (aFound == myConstraintMap.end()) - return true; // no constraint, already deleted - - // Remove constraint - std::list aConstrList = aFound->second; - myConstraintMap.erase(aFound); - // Remove SolveSpace constraints - bool isFullyRemoved = true; - std::list::iterator anIt = aConstrList.begin(); - while (anIt != aConstrList.end()) { - if (remove(*anIt)) { - std::list::iterator aRemoveIt = anIt++; - aConstrList.erase(aRemoveIt); - } else { - isFullyRemoved = false; - ++anIt; - } - } - if (!isFullyRemoved) - myConstraintMap[theConstraint] = aConstrList; - return isFullyRemoved; -} - -template -static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity) -{ - std::list::const_iterator anEntIt = theConstraint->entities().begin(); - for (; anEntIt != theConstraint->entities().end(); ++anEntIt) - if (std::dynamic_pointer_cast(*anEntIt)->isBase(theEntity)) - return true; - return false; -} - -static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity) -{ - std::list::const_iterator aSubIt = theFeature->subEntities().begin(); - for (; aSubIt != theFeature->subEntities().end(); ++aSubIt) - if (std::dynamic_pointer_cast(*aSubIt)->isBase(theSubEntity)) - return true; - return false; -} - -bool SolveSpaceSolver_Storage::isUsed(FeaturePtr theFeature) const -{ - std::map >::const_iterator - aCIt = myConstraintMap.begin(); - std::list::const_iterator aCWIt; - for (; aCIt != myConstraintMap.end(); ++aCIt) - for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt) - if (::isUsed(*aCWIt, theFeature)) - return true; - // check attributes - std::list anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list::const_iterator anIt = anAttrList.begin(); - for (; anIt != anAttrList.end(); ++anIt) - if (isUsed(*anIt)) - return true; - return false; -} - -bool SolveSpaceSolver_Storage::isUsed(AttributePtr theAttribute) const -{ - AttributePtr anAttribute = theAttribute; - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttribute); - if (aRefAttr) { - if (aRefAttr->isObject()) - return isUsed(ModelAPI_Feature::feature(aRefAttr->object())); - else - anAttribute = aRefAttr->attr(); - } - - std::map >::const_iterator - aCIt = myConstraintMap.begin(); - std::list::const_iterator aCWIt; - for (; aCIt != myConstraintMap.end(); ++aCIt) - for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt) - if (::isUsed(*aCWIt, anAttribute)) - return true; - return false; -} - - -bool SolveSpaceSolver_Storage::removeEntity(FeaturePtr theFeature) -{ - std::map::iterator aFound = myFeatureMap.find(theFeature); - if (aFound == myFeatureMap.end()) - return false; // feature not found, nothing to delete - - // Check the feature is not used by constraints - if (isUsed(theFeature)) - return false; // the feature is used, don't remove it - - // Remove feature - EntityWrapperPtr anEntity = aFound->second; - myFeatureMap.erase(aFound); - if (remove(anEntity)) - return true; - // feature is not removed, revert operation - myFeatureMap[theFeature] = anEntity; - return false; -} - -bool SolveSpaceSolver_Storage::removeEntity(AttributePtr theAttribute) -{ - std::map::iterator aFound = myAttributeMap.find(theAttribute); - if (aFound == myAttributeMap.end()) - return false; // attribute not found, nothing to delete - - // Check the attribute is not used by constraints - if (isUsed(theAttribute)) - return false; // the attribute is used, don't remove it - // Check the attribute is not used by other features - std::map::const_iterator aFIt = myFeatureMap.begin(); - for (; aFIt != myFeatureMap.end(); ++aFIt) - if (::isUsed(aFIt->second, theAttribute)) // the attribute is used, don't remove it - return false; - - // Remove attribute - EntityWrapperPtr anEntity = aFound->second; - myAttributeMap.erase(aFound); - if (remove(anEntity)) - return true; - // attribute is not removed, revert operation - myAttributeMap[theAttribute] = anEntity; - return false; -} - bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint) { @@ -1672,42 +1491,18 @@ bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint) return true; bool isFullyRemoved = removeConstraint((Slvs_hConstraint)aConstraint->id()); - - std::list::const_iterator anIt = aConstraint->entities().begin(); - for (; anIt != aConstraint->entities().end(); ++anIt) { - std::shared_ptr anEntity = - std::dynamic_pointer_cast(*anIt); - FeaturePtr aBaseFeature = anEntity->baseFeature(); - if (aBaseFeature) - isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved; - else - isFullyRemoved = removeEntity(anEntity->baseAttribute()) && isFullyRemoved; - } - - return isFullyRemoved; + return SketchSolver_Storage::remove(theConstraint) && isFullyRemoved; } bool SolveSpaceSolver_Storage::remove(EntityWrapperPtr theEntity) { + if (!theEntity) + return false; + std::shared_ptr anEntity = std::dynamic_pointer_cast(theEntity); bool isFullyRemoved = removeEntity((Slvs_hEntity)anEntity->id()); - - std::list::const_iterator anEntIt = anEntity->subEntities().begin(); - for (; anEntIt != anEntity->subEntities().end(); ++anEntIt) { - std::shared_ptr aSubEntity = - std::dynamic_pointer_cast(*anEntIt); - FeaturePtr aBaseFeature = aSubEntity->baseFeature(); - if (aBaseFeature) - isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved; - else - isFullyRemoved = removeEntity(aSubEntity->baseAttribute()) && isFullyRemoved; - } - - std::list::const_iterator aParIt = anEntity->parameters().begin(); - for (; aParIt != anEntity->parameters().end(); ++aParIt) - isFullyRemoved = remove(*aParIt) && isFullyRemoved; - return isFullyRemoved; + return SketchSolver_Storage::remove(theEntity) && isFullyRemoved; } bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter) @@ -1718,7 +1513,7 @@ bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter) void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const { - blockEvents(true); + //blockEvents(true); std::map::const_iterator anIt = myAttributeMap.begin(); std::list aParams; @@ -1789,7 +1584,7 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const } } - blockEvents(false); + //blockEvents(false); } void SolveSpaceSolver_Storage::verifyFixed() diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h index 04e6790aa..38efa4c13 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h @@ -38,16 +38,16 @@ public: /// \return \c true if the value of parameter is updated virtual bool update(ParameterWrapperPtr& theParameter); - /// \brief Removes constraint from the storage - /// \return \c true if the constraint and all its parameters are remove successfully - virtual bool removeConstraint(ConstraintPtr theConstraint); - /// \brief Removes feature from the storage - /// \return \c true if the feature and its attributes are removed successfully; - /// \c false if the feature or any it attribute is used by remaining constraints. - virtual bool removeEntity(FeaturePtr theFeature); - /// \brief Removes attribute from the storage - /// \return \c true if the attribute is not used by remaining features and constraints - virtual bool removeEntity(AttributePtr theAttribute); +//// /// \brief Removes constraint from the storage +//// /// \return \c true if the constraint and all its parameters are remove successfully +//// virtual bool removeConstraint(ConstraintPtr theConstraint); +//// /// \brief Removes feature from the storage +//// /// \return \c true if the feature and its attributes are removed successfully; +//// /// \c false if the feature or any it attribute is used by remaining constraints. +//// virtual bool removeEntity(FeaturePtr theFeature); +//// /// \brief Removes attribute from the storage +//// /// \return \c true if the attribute is not used by remaining features and constraints +//// virtual bool removeEntity(AttributePtr theAttribute); /// \brief Update SketchPlugin features after resolving constraints /// \param theFixedOnly [in] if \c true the fixed points will be updated only @@ -177,21 +177,21 @@ public: /// \brief Attach constraint SLVS_C_WHERE_DRAGGED to this storage. It need to make precise calculations void addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID); - /// \brief Add transient constraint - void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID); - /// \brief Mark specified constraint as temporary - virtual void setTemporary(ConstraintPtr theConstraint); - /// \brief Remove all transient constraints - void removeAllTemporary(); - /// \brief Remove temporary constraint s. Preferable to remove the points under Point-on-Line constraint - /// \param theNbConstraints [in] number of temporary constraints to be deleted - /// \return Number of remaining temporary constraints - virtual size_t removeTemporary(size_t theNbConstraints); - /// \brief Checks the constraint is temporary - bool isTemporary(const Slvs_hConstraint& theConstraintID) const; - /// \brief Number of temporary constraints - virtual size_t nbTemporary() const - { return myTemporaryConstraints.size(); } +//// /// \brief Add transient constraint +//// void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID); +//// /// \brief Mark specified constraint as temporary +//// virtual void setTemporary(ConstraintPtr theConstraint); +//// /// \brief Remove all transient constraints +//// void removeAllTemporary(); +//// /// \brief Remove temporary constraint s. Preferable to remove the points under Point-on-Line constraint +//// /// \param theNbConstraints [in] number of temporary constraints to be deleted +//// /// \return Number of remaining temporary constraints +//// virtual size_t removeTemporary(size_t theNbConstraints); +//// /// \brief Checks the constraint is temporary +//// bool isTemporary(const Slvs_hConstraint& theConstraintID) const; +//// /// \brief Number of temporary constraints +//// virtual size_t nbTemporary() const +//// { return myTemporaryConstraints.size(); } /// \brief Shows the storage has the same constraint twice virtual bool hasDuplicatedConstraint() const @@ -239,11 +239,6 @@ private: /// \brief Update arc points to be on circle sharp. void adjustArc(const Slvs_Entity& theArc); - /// \brief Verify the feature or any its attribute is used by constraint - bool isUsed(FeaturePtr theFeature) const; - /// \brief Verify the attribute is used by constraint - bool isUsed(AttributePtr theAttirubute) const; - /// \brief Replace sub-entity theSource in all features by theDest void replaceInFeatures(EntityWrapperPtr theSource, EntityWrapperPtr theDest); /// \brief Replace constrained entity theSource by theDest in all constraints; @@ -269,7 +264,7 @@ private: bool myDuplicatedConstraint; ///< shows the storage has same constraint twice - std::set myTemporaryConstraints; ///< list of transient constraints +//// std::set myTemporaryConstraints; ///< list of transient constraints std::set myUpdatedParameters; ///< list of just updated parameters (cleared when isNeedToResolve() called) SameConstraintMap myEqualConstraints; ///< list of groups of equal constraints -- 2.39.2