From 2c9e900f14038dee0ee15778a8f86de3d43cf308 Mon Sep 17 00:00:00 2001 From: azv Date: Sat, 1 Apr 2017 16:15:37 +0300 Subject: [PATCH] Improve updating "Multi" constraints --- src/SketchPlugin/Test/TestMirror.py | 23 ++++++++++++++++++ .../PlaneGCSSolver/PlaneGCSSolver_Storage.cpp | 24 ++++++++++++++++--- .../SketchSolver_ConstraintMultiRotation.cpp | 7 +++++- ...ketchSolver_ConstraintMultiTranslation.cpp | 12 ++++++++-- src/SketchSolver/SketchSolver_Group.cpp | 17 ------------- src/SketchSolver/SketchSolver_Group.h | 3 --- 6 files changed, 60 insertions(+), 26 deletions(-) diff --git a/src/SketchPlugin/Test/TestMirror.py b/src/SketchPlugin/Test/TestMirror.py index 306d02d45..af141ae28 100644 --- a/src/SketchPlugin/Test/TestMirror.py +++ b/src/SketchPlugin/Test/TestMirror.py @@ -208,6 +208,29 @@ assert (aRefListB.size() == 1) assert (aRefListC.size() == 1) checkMirror(aRefListB, aRefListC, aMirrorLine) assert (model.dof(aSketchFeature) == 12) + +#========================================================================= +# Create distance between original and mirrored entities (check the error appears) +#========================================================================= +aSketchErrorAttr = aSketchFeature.string("SolverError") +assert len(aSketchErrorAttr.value()) == 0, "Sketch failed with error: {}".format(aSketchErrorAttr.value()) +aMirroredArc = model.lastSubFeature(aSketchFeature, "SketchArc") +aSession.startOperation() +aConstraint = aSketchFeature.addFeature("SketchConstraintDistance") +refAttrA = aConstraint.refattr("ConstraintEntityA") +refAttrB = aConstraint.refattr("ConstraintEntityB") +anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("start_point")) +aMirroredArcStartPoint = geomDataAPI_Point2D(aMirroredArc.attribute("start_point")) +refAttrA.setAttr(anArcStartPoint) +refAttrB.setAttr(aMirroredArcStartPoint) +aConstraint.real("ConstraintValue").setValue(200.) +aSession.finishOperation() +print "Sketch error : {}".format(aSketchErrorAttr.value()) +assert len(aSketchErrorAttr.value()) != 0, "ERROR: Sketch has not been failed as expected" +aSession.startOperation() +aDocument.removeFeature(aConstraint) +aSession.finishOperation() + #========================================================================= # End of test #========================================================================= diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index 69b62e970..547eaef01 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -358,7 +358,7 @@ void PlaneGCSSolver_Storage::removeParameters(const GCS::SET_pD& theParams) } // indicates attribute containing in the external feature -bool isExternalAttribute(const AttributePtr& theAttribute) +static bool isExternalAttribute(const AttributePtr& theAttribute) { if (!theAttribute) return false; @@ -367,10 +367,19 @@ bool isExternalAttribute(const AttributePtr& theAttribute) return aSketchFeature.get() && aSketchFeature->isExternal(); } +static void addOwnerToSet(const AttributePtr& theAttribute, std::set& theFeatures) +{ + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); + if (anOwner) + theFeatures.insert(anOwner); +} + void PlaneGCSSolver_Storage::refresh() const { const double aTol = 1000. * tolerance; // tolerance to prevent frequent updates + std::set anUpdatedFeatures; + std::map::const_iterator anIt = myAttributeMap.begin(); for (; anIt != myAttributeMap.end(); ++anIt) { // the external feature always should keep the up to date values, so, @@ -385,17 +394,26 @@ void PlaneGCSSolver_Storage::refresh() const std::dynamic_pointer_cast(anIt->second); GCSPointPtr aGCSPoint = aPointWrapper->point(); if (fabs(aPoint2D->x() - (*aGCSPoint->x)) > aTol || - fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol) + fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol) { aPoint2D->setValue(*aGCSPoint->x, *aGCSPoint->y); + addOwnerToSet(anIt->first, anUpdatedFeatures); + } continue; } AttributeDoublePtr aScalar = std::dynamic_pointer_cast(anIt->first); if (aScalar) { ScalarWrapperPtr aScalarWrapper = std::dynamic_pointer_cast(anIt->second); - if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol) + if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol) { aScalar->setValue(aScalarWrapper->value()); + addOwnerToSet(anIt->first, anUpdatedFeatures); + } continue; } } + + // notify listeners about features update + std::set::const_iterator aFIt = anUpdatedFeatures.begin(); + for (; aFIt != anUpdatedFeatures.end(); ++aFIt) + notify(*aFIt); } diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp index 5d857e914..78bf3312e 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp @@ -24,7 +24,7 @@ void SketchSolver_ConstraintMultiRotation::getAttributes( theAngle = aValueBuilder.createAttribute(anAngleAttr); myStorage->addEntity(anAngleAttr, theAngle); - AttributePtr aCenterAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID()); + AttributeRefAttrPtr aCenterAttr = myBaseConstraint->refattr(SketchPlugin_MultiRotation::CENTER_ID()); if (!aCenterAttr || !aCenterAttr->isInitialized()) { myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); return; @@ -40,6 +40,11 @@ void SketchSolver_ConstraintMultiRotation::getAttributes( theFullValue = aMethodTypeAttr->value() != "SingleAngle"; getEntities(theEntities); + + // add owner of central point of Multi-Rotation to the list of monitored features + FeaturePtr anOwner = ModelAPI_Feature::feature(aCenterAttr->attr()->owner()); + if (anOwner) + myFeatures.insert(anOwner); } void SketchSolver_ConstraintMultiRotation::process() diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp index 5244ec6a4..b05827b9d 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp @@ -17,8 +17,8 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes( bool& theFullValue, std::list& theEntities) { DataPtr aData = myBaseConstraint->data(); - AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID()); - AttributePtr aEndPointAttr = aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID()); + AttributeRefAttrPtr aStartPointAttr = aData->refattr(SketchPlugin_MultiTranslation::START_POINT_ID()); + AttributeRefAttrPtr aEndPointAttr = aData->refattr(SketchPlugin_MultiTranslation::END_POINT_ID()); if (!aStartPointAttr || !aStartPointAttr->isInitialized() || !aEndPointAttr || !aEndPointAttr->isInitialized()) { myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); @@ -36,6 +36,14 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes( theFullValue = aMethodTypeAttr->value() != "SingleValue"; getEntities(theEntities); + + // add owner of start and end points of Multi-Translation to the list of monitored features + FeaturePtr anOwner = ModelAPI_Feature::feature(aStartPointAttr->attr()->owner()); + if (anOwner) + myFeatures.insert(anOwner); + anOwner = ModelAPI_Feature::feature(aEndPointAttr->attr()->owner()); + if (anOwner) + myFeatures.insert(anOwner); } void SketchSolver_ConstraintMultiTranslation::process() diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 4f40f1d9c..fb82f2cde 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -185,7 +185,6 @@ bool SketchSolver_Group::resolveConstraints() // additional check that copied entities used in Mirror and other "Multi" constraints // is not connected with their originals by constraints. myMultiConstraintUpdateStack += 1; - updateMultiConstraints(); aResolved = true; if (myStorage->isNeedToResolve()) aResolved = resolveConstraints(); @@ -366,22 +365,6 @@ void SketchSolver_Group::blockEvents(bool isBlocked) myIsEventsBlocked = isBlocked; } -// ============================================================================ -// Function: updateMultiConstraints -// Class: SketchSolver_Group -// Purpose: update multi constraints -// ============================================================================ -void SketchSolver_Group::updateMultiConstraints() -{ - ConstraintConstraintMap::iterator anIt = myConstraints.begin(); - for (; anIt != myConstraints.end(); ++anIt) { - if (anIt->first->getKind() == SketchPlugin_ConstraintMirror::ID() || - anIt->first->getKind() == SketchPlugin_MultiRotation::ID() || - anIt->first->getKind() == SketchPlugin_MultiTranslation::ID()) - anIt->second->update(); - } -} - bool SketchSolver_Group::areConstraintsValid() const { // Check the constraints are valid diff --git a/src/SketchSolver/SketchSolver_Group.h b/src/SketchSolver/SketchSolver_Group.h index 53c881c70..fa5902664 100644 --- a/src/SketchSolver/SketchSolver_Group.h +++ b/src/SketchSolver/SketchSolver_Group.h @@ -98,9 +98,6 @@ private: /// \brief Append given constraint to the group of temporary constraints void setTemporary(SolverConstraintPtr theConstraint); - /// \brief Update dependent (copied) features created by Mirror and other "Multi" constraints - void updateMultiConstraints(); - /// \brief Compute DoF of the sketch and set corresponding field void computeDoF(); -- 2.39.2