// solve equations
if (aResult == GCS::Success)
aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters);
- if (aResult == GCS::Success) {
+ if (aResult == GCS::Success || aResult == GCS::Converged) {
// additionally check redundant constraints
GCS::VEC_I aRedundantID;
myEquationSystem.getRedundant(aRedundantID);
// Need to check if there are redundant constraints without these tangencies.
if (!aRedundantID.empty())
aResult = myTangent.empty() ? GCS::Failed : (GCS::SolveStatus)solveWithoutTangent();
+ else
+ aResult = GCS::Success;
}
Events_LongOp::end(this);
// update feature in the storage if it is used by another constraints
if (anEntity)
myStorage->update(aFeature);
+ else { // update attributes, if they exist in the storage
+ for (aPtIt = aPoints.begin(); aPtIt != aPoints.end(); ++aPtIt) {
+ EntityWrapperPtr aPntEnt = myStorage->entity(*aPtIt);
+ if (aPntEnt)
+ myStorage->update(*aPtIt);
+ }
+ }
if (!anEntity || !myStorage->isEventsBlocked())
aFeature->data()->blockSendAttributeUpdated(false);
return myFeatures.find(theFeature) != myFeatures.end() ||
SketchSolver_Constraint::isUsed(theFeature);
}
+
+bool SketchSolver_ConstraintMulti::isUsed(AttributePtr theAttribute) const
+{
+ AttributePtr anAttribute = theAttribute;
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
+ if (aRefAttr) {
+ if (aRefAttr->isObject())
+ return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
+ else
+ anAttribute = aRefAttr->attr();
+ }
+
+ FeaturePtr anOwner = ModelAPI_Feature::feature(anAttribute->owner());
+ return myFeatures.find(anOwner) != myFeatures.end();
+}
/// \brief Check the feature is a source or a copy of Multi-constraint
virtual bool isUsed(FeaturePtr theFeature) const;
+ /// \brief Check the attribute is used in Multi-constraint
+ virtual bool isUsed(AttributePtr theAttribute) const;
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
ConstraintConstraintMap::const_iterator anIt = myConstraints.begin();
for (; !isInteracted && anIt != myConstraints.end(); ++anIt)
if (anIt->first->getKind() == SketchPlugin_MultiRotation::ID() ||
- anIt->first->getKind() == SketchPlugin_MultiTranslation::ID())
+ anIt->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
isInteracted = anIt->second->isUsed(theFeature);
+ if (isInteracted)
+ break;
+ // if theFeature is a constraint, check its attributes
+ ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
+ if (!aConstraint)
+ continue;
+ for (int i = 0; i < 4 && !isInteracted; ++i) {
+ AttributeRefAttrPtr aRefAttr = aConstraint->refattr(aConstraint->ATTRIBUTE(i));
+ if (!aRefAttr)
+ continue;
+ isInteracted = anIt->second->isUsed(aRefAttr);
+ }
+ }
return isInteracted;
}
return false;
}
if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET) { // solution succeeded, store results into correspondent attributes
+ myStorage->setNeedToResolve(false);
myStorage->refresh();
updateMultiConstraints(myConstraints);
+ if (myStorage->isNeedToResolve()) // multi-constraints updated some parameters, need to store them
+ myStorage->refresh();
+
if (myPrevResult != STATUS_OK || myPrevResult == STATUS_UNKNOWN) {
getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
std::set<ObjectPtr> aConflicting = myConflictingConstraints;
GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
// Check attribute of external features
std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(theAttribute->owner());
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(anAttribute->owner());
if (aSketchFeature && (aSketchFeature->isExternal() || isCopyInMulti(aSketchFeature, myConstraintMap)))
aGroup = GID_OUTOFGROUP;
aRelated = aBuilder->createAttribute(anAttribute, aGroup);