From 0f6c554592f695617eb698add479039bbeb3b2c1 Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 16 May 2017 15:54:43 +0300 Subject: [PATCH] Fix incorrect processing of the copied entities after the "Multi" constraint has been removed --- .../PlaneGCSSolver_AttributeBuilder.cpp | 6 -- .../PlaneGCSSolver_AttributeBuilder.h | 3 - .../PlaneGCSSolver_EntityBuilder.h | 3 - .../PlaneGCSSolver_EntityDestroyer.cpp | 78 ++--------------- .../PlaneGCSSolver_FeatureBuilder.cpp | 22 +---- .../PlaneGCSSolver_FeatureBuilder.h | 8 -- .../PlaneGCSSolver/PlaneGCSSolver_Solver.cpp | 18 ++++ .../PlaneGCSSolver/PlaneGCSSolver_Solver.h | 2 + .../PlaneGCSSolver/PlaneGCSSolver_Storage.cpp | 86 +++++++++++++++---- .../PlaneGCSSolver/PlaneGCSSolver_Storage.h | 7 ++ .../PlaneGCSSolver/PlaneGCSSolver_Tools.cpp | 79 +++++++++++++++++ .../PlaneGCSSolver/PlaneGCSSolver_Tools.h | 3 + .../SketchSolver_ConstraintMulti.cpp | 29 ++++++- src/SketchSolver/SketchSolver_Storage.h | 5 ++ 14 files changed, 220 insertions(+), 129 deletions(-) diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp index a6feb1f9e..c85a2d163 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp @@ -90,9 +90,3 @@ EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute( aResult->setExternal(true); return aResult; } - -const std::list& PlaneGCSSolver_AttributeBuilder::constraints() const -{ - static std::list aList; - return aList; -} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h index 4c8e44ed6..28c182a2f 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h @@ -28,9 +28,6 @@ public: /// \brief Blank. To be defined in derived class. virtual EntityWrapperPtr createFeature(FeaturePtr) { return EntityWrapperPtr(); } - - /// \brief Blank. To be defined in derived class. - virtual const std::list& constraints() const; }; #endif diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityBuilder.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityBuilder.h index d4eb9d9d2..94279ee81 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityBuilder.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityBuilder.h @@ -37,9 +37,6 @@ public: /// \param theFeature [in] feature to create virtual EntityWrapperPtr createFeature(FeaturePtr) = 0; - /// \brief Return list of constraints necessary to fix feature's extra DoF - virtual const std::list& constraints() const = 0; - protected: PlaneGCSSolver_Storage* myStorage; }; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.cpp index 97a3b83f0..7b93798ff 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityDestroyer.cpp @@ -9,79 +9,13 @@ #include #include #include - -static void destroyScalar(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams) -{ - ScalarWrapperPtr aScalar = std::dynamic_pointer_cast(theEntity); - theParams.insert(aScalar->scalar()); -} - -static void destroyPoint(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams) -{ - std::shared_ptr aPoint = - std::dynamic_pointer_cast(theEntity); - theParams.insert(aPoint->point()->x); - theParams.insert(aPoint->point()->y); -} - -static void destroyLine(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams) -{ - std::shared_ptr anEntity = - std::dynamic_pointer_cast(theEntity); - std::shared_ptr aLine = std::dynamic_pointer_cast(anEntity->entity()); - theParams.insert(aLine->p1.x); - theParams.insert(aLine->p1.y); - theParams.insert(aLine->p2.x); - theParams.insert(aLine->p2.y); -} - -static void destroyCircle(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams) -{ - std::shared_ptr anEntity = - std::dynamic_pointer_cast(theEntity); - std::shared_ptr aCirc = std::dynamic_pointer_cast(anEntity->entity()); - theParams.insert(aCirc->center.x); - theParams.insert(aCirc->center.y); - theParams.insert(aCirc->rad); -} - -static void destroyArc(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams) -{ - std::shared_ptr anEntity = - std::dynamic_pointer_cast(theEntity); - std::shared_ptr anArc = std::dynamic_pointer_cast(anEntity->entity()); - theParams.insert(anArc->center.x); - theParams.insert(anArc->center.y); - theParams.insert(anArc->start.x); - theParams.insert(anArc->start.y); - theParams.insert(anArc->end.x); - theParams.insert(anArc->end.y); - theParams.insert(anArc->startAngle); - theParams.insert(anArc->endAngle); - theParams.insert(anArc->rad); -} +#include void PlaneGCSSolver_EntityDestroyer::remove(const EntityWrapperPtr& theEntity) { - GCS::SET_pD& aParamSet = theEntity->isExternal() ? myParamsOutOfStorage : myParams; - - switch (theEntity->type()) { - case ENTITY_SCALAR: - case ENTITY_ANGLE: - destroyScalar(theEntity, aParamSet); - break; - case ENTITY_POINT: - destroyPoint(theEntity, aParamSet); - break; - case ENTITY_LINE: - destroyLine(theEntity, aParamSet); - break; - case ENTITY_CIRCLE: - destroyCircle(theEntity, aParamSet); - break; - case ENTITY_ARC: - destroyArc(theEntity, aParamSet); - break; - default: break; - } + GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity); + if (theEntity->isExternal()) + myParamsOutOfStorage.insert(aParameters.begin(), aParameters.end()); + else + myParams.insert(aParameters.begin(), aParameters.end()); } diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp index e9cf468a9..035d6c895 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp @@ -25,8 +25,7 @@ static bool isAttributeApplicable(const std::string& theAttrName, static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes); static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes); static EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes, - PlaneGCSSolver_Storage* theStorage, - std::list& theArcConstraints); + PlaneGCSSolver_Storage* theStorage); PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder( @@ -76,7 +75,7 @@ EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeat aResult = createCircle(myAttributes); // Arc else if (aFeatureKind == SketchPlugin_Arc::ID()) - aResult = createArc(myAttributes, myStorage, myFeatureConstraints); + aResult = createArc(myAttributes, myStorage); // Point (it has low probability to be an attribute of constraint, so it is checked at the end) else if (aFeatureKind == SketchPlugin_Point::ID() || aFeatureKind == SketchPlugin_IntersectionPoint::ID()) { @@ -147,8 +146,7 @@ static double* createParameter(PlaneGCSSolver_Storage* theStorage) } EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes, - PlaneGCSSolver_Storage* theStorage, - std::list& theArcConstraints) + PlaneGCSSolver_Storage* theStorage) { std::shared_ptr aNewArc(new GCS::Arc); @@ -189,20 +187,6 @@ EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes, new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y())); *aNewArc->endAngle = OX->angle(aDir); - if (theStorage) { - // Additional constaints to fix arc's extra DoF (if the arc is not external): - // 1. distances from center till start and end points are equal to radius - theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance( - aNewArc->center, aNewArc->start, aNewArc->rad))); - theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance( - aNewArc->center, aNewArc->end, aNewArc->rad))); - // 2. angles of start and end points should be equal to the arc angles - theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle( - aNewArc->center, aNewArc->start, aNewArc->startAngle))); - theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle( - aNewArc->center, aNewArc->end, aNewArc->endAngle))); - } - return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewArc)); } diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.h index af796cda3..fc3a98bea 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.h @@ -32,17 +32,9 @@ public: /// \param theFeature [in] feature to create virtual EntityWrapperPtr createFeature(FeaturePtr theFeature); - /// \brief Return list of constraints necessary to fix feature's extra DoF - virtual const std::list& constraints() const - { return myFeatureConstraints; } - private: /// list of converted attributes (will be cleared when the feature is created) AttributeEntityMap myAttributes; - - /// constraints for the feature - /// (primarily used for constrain arcs, which have 9 parameters but 5 DoF) - std::list myFeatureConstraints; }; #endif diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp index d06446e6f..57529dc35 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp @@ -63,6 +63,22 @@ double* PlaneGCSSolver_Solver::createParameter() return aResult; } +void PlaneGCSSolver_Solver::addParameters(const GCS::SET_pD& theParams) +{ + GCS::SET_pD aParams(theParams); + // leave new parameters only + GCS::VEC_pD::iterator anIt = myParameters.begin(); + for (; anIt != myParameters.end(); ++anIt) + if (aParams.find(*anIt) != aParams.end()) + aParams.erase(*anIt); + + myParameters.insert(myParameters.end(), aParams.begin(), aParams.end()); + if (myConstraints.empty() && myDOF >=0) + myDOF += (int)aParams.size(); // calculate DoF by hand if and only if there is no constraints yet + else + myDiagnoseBeforeSolve = true; +} + void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams) { for (int i = (int)myParameters.size() - 1; i >= 0; --i) @@ -70,6 +86,8 @@ void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams) myParameters.erase(myParameters.begin() + i); --myDOF; } + if (!myConstraints.empty()) + myDiagnoseBeforeSolve = true; } void PlaneGCSSolver_Solver::initialize() diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h index cb195ada3..19faa221b 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h @@ -39,6 +39,8 @@ public: /// \brief Initialize memory for new solver's parameter double* createParameter(); + /// \brief Add parameters created elsewhere + void addParameters(const GCS::SET_pD& theParams); /// \brief Release memory occupied by parameters void removeParameters(const GCS::SET_pD& theParams); diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index 64d9c7fb5..e70ec7337 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -176,17 +177,7 @@ bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce) // (do not want to add several copies of it while adding attributes) aRelated = createFeature(theFeature, &aBuilder); myFeatureMap[theFeature] = aRelated; - - const std::list& aConstraints = aBuilder.constraints(); - if (!aConstraints.empty()) { // the feature is arc - /// TODO: avoid this workaround - ConstraintWrapperPtr aWrapper( - new PlaneGCSSolver_ConstraintWrapper(aConstraints, CONSTRAINT_UNKNOWN)); - aWrapper->setId(++myConstraintLastID); - constraintsToSolver(aWrapper, mySketchSolver); - - myArcConstraintMap[myFeatureMap[theFeature]] = aWrapper; - } + createArcConstraints(aRelated); isUpdated = true; } @@ -263,6 +254,72 @@ bool PlaneGCSSolver_Storage::update(AttributePtr theAttribute, bool theForce) return isUpdated; } +void PlaneGCSSolver_Storage::makeExternal(const EntityWrapperPtr& theEntity) +{ + if (theEntity->isExternal()) + return; + + removeArcConstraints(theEntity); + + GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity); + mySketchSolver->removeParameters(aParameters); + theEntity->setExternal(true); + myNeedToResolve = true; +} + +void PlaneGCSSolver_Storage::makeNonExternal(const EntityWrapperPtr& theEntity) +{ + if (!theEntity->isExternal()) + return; + + GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity); + mySketchSolver->addParameters(aParameters); + theEntity->setExternal(false); + + createArcConstraints(theEntity); + + myNeedToResolve = true; +} + + +void PlaneGCSSolver_Storage::createArcConstraints(const EntityWrapperPtr& theArc) +{ + if (theArc->type() != ENTITY_ARC || theArc->isExternal()) + return; + + EdgeWrapperPtr anEdge = std::dynamic_pointer_cast(theArc); + std::shared_ptr anArc = std::dynamic_pointer_cast(anEdge->entity()); + + // Additional constaints to fix arc's extra DoF (if the arc is not external): + std::list anArcConstraints; + // 1. distances from center till start and end points are equal to radius + anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance( + anArc->center, anArc->start, anArc->rad))); + anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance( + anArc->center, anArc->end, anArc->rad))); + // 2. angles of start and end points should be equal to the arc angles + anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle( + anArc->center, anArc->start, anArc->startAngle))); + anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle( + anArc->center, anArc->end, anArc->endAngle))); + + ConstraintWrapperPtr aWrapper( + new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN)); + aWrapper->setId(++myConstraintLastID); + constraintsToSolver(aWrapper, mySketchSolver); + + myArcConstraintMap[theArc] = aWrapper; +} + +void PlaneGCSSolver_Storage::removeArcConstraints(const EntityWrapperPtr& theArc) +{ + std::map::iterator + aFound = myArcConstraintMap.find(theArc); + if (aFound != myArcConstraintMap.end()) { + mySketchSolver->removeConstraint(aFound->second->id()); + myArcConstraintMap.erase(aFound); + } +} bool PlaneGCSSolver_Storage::removeConstraint(ConstraintPtr theConstraint) @@ -321,12 +378,7 @@ void PlaneGCSSolver_Storage::removeInvalidEntities() aDestroyer.remove(aFIter->second); // remove invalid arc - std::map::iterator - aFound = myArcConstraintMap.find(aFIter->second); - if (aFound != myArcConstraintMap.end()) { - mySketchSolver->removeConstraint(aFound->second->id()); - myArcConstraintMap.erase(aFound); - } + removeArcConstraints(aFIter->second); } std::list::const_iterator anInvFIt = anInvalidFeatures.begin(); for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt) diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h index c7e1d1eda..6b8bc66e3 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h @@ -48,6 +48,10 @@ public: /// \return \c true if the attribute has been created or updated virtual bool update(AttributePtr theAttribute, bool theForce = false); + /// \brief Make entity external + virtual void makeExternal(const EntityWrapperPtr& theEntity); + /// \brief Make entity non-external + virtual void makeNonExternal(const EntityWrapperPtr& theEntity); /// \brief Removes constraint from the storage /// \return \c true if the constraint and all its parameters are removed successfully @@ -77,6 +81,9 @@ private: EntityWrapperPtr createAttribute(const AttributePtr& theAttribute, PlaneGCSSolver_EntityBuilder* theBuilder); + void createArcConstraints(const EntityWrapperPtr& theArc); + void removeArcConstraints(const EntityWrapperPtr& theArc); + private: ConstraintID myConstraintLastID; ///< identifier of last added constraint diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index 63813ba75..35c3ed860 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -88,6 +88,12 @@ static ConstraintWrapperPtr createConstraintMiddlePoint(std::shared_ptr thePoint, std::shared_ptr theEntity); +static GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar); +static GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint); +static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine); +static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle); +static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc); + @@ -242,6 +248,27 @@ std::shared_ptr PlaneGCSSolver_Tools::line(FeaturePtr theFeature) } +GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity) +{ + switch (theEntity->type()) { + case ENTITY_SCALAR: + case ENTITY_ANGLE: + return scalarParameters(GCS_SCALAR_WRAPPER(theEntity)); + case ENTITY_POINT: + return pointParameters(GCS_POINT_WRAPPER(theEntity)); + case ENTITY_LINE: + return lineParameters(GCS_EDGE_WRAPPER(theEntity)); + case ENTITY_CIRCLE: + return circleParameters(GCS_EDGE_WRAPPER(theEntity)); + case ENTITY_ARC: + return arcParameters(GCS_EDGE_WRAPPER(theEntity)); + default: break; + } + return GCS::SET_pD(); +} + + + @@ -454,3 +481,55 @@ ConstraintWrapperPtr createConstraintEqual( aResult->setValueParameter(theIntermed); return aResult; } + +GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar) +{ + GCS::SET_pD aParams; + aParams.insert(theScalar->scalar()); + return aParams; +} + +GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint) +{ + GCS::SET_pD aParams; + aParams.insert(thePoint->point()->x); + aParams.insert(thePoint->point()->y); + return aParams; +} + +GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine) +{ + GCS::SET_pD aParams; + std::shared_ptr aLine = std::dynamic_pointer_cast(theLine->entity()); + aParams.insert(aLine->p1.x); + aParams.insert(aLine->p1.y); + aParams.insert(aLine->p2.x); + aParams.insert(aLine->p2.y); + return aParams; +} + +GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle) +{ + GCS::SET_pD aParams; + std::shared_ptr aCirc = std::dynamic_pointer_cast(theCircle->entity()); + aParams.insert(aCirc->center.x); + aParams.insert(aCirc->center.y); + aParams.insert(aCirc->rad); + return aParams; +} + +GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc) +{ + GCS::SET_pD aParams; + std::shared_ptr anArc = std::dynamic_pointer_cast(theArc->entity()); + aParams.insert(anArc->center.x); + aParams.insert(anArc->center.y); + aParams.insert(anArc->start.x); + aParams.insert(anArc->start.y); + aParams.insert(anArc->end.x); + aParams.insert(anArc->end.y); + aParams.insert(anArc->startAngle); + aParams.insert(anArc->endAngle); + aParams.insert(anArc->rad); + return aParams; +} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h index 4e43206c1..358ac8ae2 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h @@ -56,6 +56,9 @@ namespace PlaneGCSSolver_Tools /// \brief Convert entity to line /// \return empty pointer if the entity is not a line std::shared_ptr line(FeaturePtr theFeature); + + /// brief Return list of parameters for the given entity + GCS::SET_pD parameters(const EntityWrapperPtr& theEntity); }; #endif diff --git a/src/SketchSolver/SketchSolver_ConstraintMulti.cpp b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp index 41289a7fb..c9b1a338b 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMulti.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp @@ -14,6 +14,17 @@ #include #include +static void createCopiedEntity(const FeaturePtr& theFeature, const StoragePtr& theStorage) +{ + EntityWrapperPtr anEntity = theStorage->entity(theFeature); + if (anEntity) { + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(theFeature); + if (!anEntity->isExternal() && aSketchFeature->isCopy()) + theStorage->makeExternal(anEntity); + } +} + void SketchSolver_ConstraintMulti::getEntities(std::list& theEntities) { myAdjusted = false; @@ -53,8 +64,10 @@ void SketchSolver_ConstraintMulti::getEntities(std::list& theE for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) { // just add copied features into the list of objects aFeature = ModelAPI_Feature::feature(*anObjIt); - if (aFeature) + if (aFeature) { + createCopiedEntity(aFeature, myStorage); myFeatures.insert(aFeature); + } } } } @@ -63,6 +76,20 @@ bool SketchSolver_ConstraintMulti::remove() { myStorage->unsubscribeUpdates(this); + // "Multi" constraint has been removed, thus all copy features become non-copied, + // add them once again to be a common feature + std::set::iterator anIt = myFeatures.begin(); + for (; anIt != myFeatures.end(); ++anIt) { + EntityWrapperPtr anEntity = myStorage->entity(*anIt); + if (anEntity) { + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(*anIt); + if (anEntity->isExternal() && !aSketchFeature->isExternal()) + myStorage->makeNonExternal(anEntity); + } else + myStorage->update(*anIt, true); + } + myFeatures.clear(); return SketchSolver_Constraint::remove(); } diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index 6ef8d08b5..e0b2923e4 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -82,6 +82,11 @@ public: /// \brief Returns entity related to corresponding attribute const EntityWrapperPtr& entity(const AttributePtr& theAttribute) const; + /// \brief Make entity external + virtual void makeExternal(const EntityWrapperPtr& theEntity) = 0; + /// \brief Make entity non-external + virtual void makeNonExternal(const EntityWrapperPtr& theEntity) = 0; + /// \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; -- 2.30.2