+
+// ============================================================================
+// Function: checkFeatureValidity
+// Class: SketchSolver_Group
+// Purpose: verifies is the feature valid
+// ============================================================================
+bool SketchSolver_Group::checkFeatureValidity(FeaturePtr theFeature)
+{
+ if (!theFeature || !theFeature->data()->isValid())
+ return true;
+
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+ return aFactory->validate(theFeature);
+}
+
+
+
+
+// =========== Auxiliary functions ========================================
+static double featureToVal(FeaturePtr theFeature)
+{
+ if (theFeature->getKind() == SketchPlugin_Sketch::ID())
+ return 0.0; // sketch
+ ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
+ if (!aConstraint)
+ return 1.0; // features (arc, circle, line, point)
+
+ const std::string& anID = aConstraint->getKind();
+ if (anID == SketchPlugin_ConstraintCoincidence::ID()) {
+ AttributeRefAttrPtr anAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeRefAttrPtr anAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ if (anAttrA && anAttrB && (anAttrA->isObject() || anAttrB->isObject()))
+ return 2.0; // point-on-line and point-on-circle should go before points coincidence constraint
+ return 2.5;
+ }
+ if (anID == SketchPlugin_ConstraintDistance::ID() ||
+ anID == SketchPlugin_ConstraintLength::ID() ||
+ anID == SketchPlugin_ConstraintRadius::ID())
+ return 3.0;
+ if (anID == SketchPlugin_ConstraintAngle::ID())
+ return 3.5;
+ if (anID == SketchPlugin_ConstraintHorizontal::ID() ||
+ anID == SketchPlugin_ConstraintVertical::ID() ||
+ anID == SketchPlugin_ConstraintParallel::ID() ||
+ anID == SketchPlugin_ConstraintPerpendicular::ID())
+ return 4.0;
+ if (anID == SketchPlugin_ConstraintEqual::ID())
+ return 5.0;
+ if (anID == SketchPlugin_ConstraintTangent::ID() ||
+ anID == SketchPlugin_ConstraintMirror::ID())
+ return 6.0;
+ if (anID == SketchPlugin_ConstraintRigid::ID())
+ return 7.0;
+ if (anID == SketchPlugin_MultiRotation::ID() ||
+ anID == SketchPlugin_MultiTranslation::ID())
+ return 8.0;
+
+ // all other constraints are placed between Equal and Tangent constraints
+ return 5.5;
+}
+
+static bool isLess(FeaturePtr theFeature1, FeaturePtr theFeature2)
+{
+ return featureToVal(theFeature1) < featureToVal(theFeature2);
+}
+
+std::list<FeaturePtr> SketchSolver_Group::selectApplicableFeatures(const std::set<ObjectPtr>& theObjects)
+{
+ std::list<FeaturePtr> aResult;
+ std::list<FeaturePtr>::iterator aResIt;
+
+ std::set<ObjectPtr>::const_iterator anObjIter = theObjects.begin();
+ for (; anObjIter != theObjects.end(); ++anObjIter) {
+ // Operate sketch itself and SketchPlugin features only.
+ // Also, the Fillet need to be skipped, because there are several separated constraints composing it.
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
+ if (!aFeature)
+ continue;
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+ if ((aFeature->getKind() != SketchPlugin_Sketch::ID() && !aSketchFeature) ||
+ aFeature->getKind() == SketchPlugin_ConstraintFillet::ID())
+ continue;
+
+ // Find the place where to insert a feature
+ for (aResIt = aResult.begin(); aResIt != aResult.end(); ++aResIt)
+ if (isLess(aFeature, *aResIt))
+ break;
+ aResult.insert(aResIt, aFeature);
+ }
+
+ return aResult;
+}
+