+//--------------------------------------------------------------------------------------
+
+std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addSpline(
+ const ModelHighAPI_Selection & external,
+ const int degree,
+ const std::list<PointOrReference>& poles,
+ const std::list<ModelHighAPI_Double>& weights,
+ const std::list<ModelHighAPI_Double>& knots,
+ const std::list<ModelHighAPI_Integer>& multiplicities,
+ const bool periodic)
+{
+ // split poles and references to other shapes
+ bool hasReference = false;
+ std::list<GeomPnt2dPtr> aPoints;
+ std::list<ModelHighAPI_RefAttr> aReferences;
+ for (std::list<PointOrReference>::const_iterator it = poles.begin(); it != poles.end(); ++it) {
+ aPoints.push_back(it->first);
+ aReferences.push_back(it->second);
+ if (!it->second.isEmpty())
+ hasReference = true;
+ }
+
+ BSplinePtr aBSpline;
+ CompositeFeaturePtr aSketch = compositeFeature();
+ if (hasReference) {
+ // use macro-feature to create coincidences to referred features
+ FeaturePtr aMacroFeature = aSketch->addFeature(
+ periodic ? SketchPlugin_MacroBSplinePeriodic::ID() : SketchPlugin_MacroBSpline::ID());
+ AttributePoint2DArrayPtr aPolesAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
+ aMacroFeature->attribute(SketchPlugin_MacroBSpline::POLES_ID()));
+ AttributeDoubleArrayPtr aWeightsAttr =
+ aMacroFeature->data()->realArray(SketchPlugin_MacroBSpline::WEIGHTS_ID());
+ AttributeRefAttrListPtr aPolesRefAttr =
+ aMacroFeature->data()->refattrlist(SketchPlugin_MacroBSpline::REF_POLES_ID());
+ // always generate a control polygon to apply coincidences correctly
+ aMacroFeature->boolean(SketchPlugin_MacroBSpline::CONTROL_POLYGON_ID())->setValue(true);
+ // initialize B-spline attributes
+ fillAttribute(aPoints, aPolesAttr);
+ if (weights.empty())
+ fillAttribute(std::list<ModelHighAPI_Double>(poles.size(), 1.0), aWeightsAttr);
+ else
+ fillAttribute(weights, aWeightsAttr);
+ fillAttribute(aReferences, aPolesRefAttr);
+ apply(); // to kill macro-feature
+
+ // find created B-spline feature
+ const std::string& aKindToFind =
+ periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID();
+ int aNbSubs = aSketch->numberOfSubs();
+ for (int anIndex = aNbSubs - 1; anIndex >= 0; --anIndex) {
+ FeaturePtr aFeature = aSketch->subFeature(anIndex);
+ if (aFeature->getKind() == aKindToFind) {
+ aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature)
+ : new SketchAPI_BSpline(aFeature));
+ aBSpline->execute();
+ break;
+ }
+ }
+ }
+ else {
+ // compute B-spline by parameters
+ FeaturePtr aFeature = aSketch->addFeature(
+ periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID());
+
+ aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature)
+ : new SketchAPI_BSpline(aFeature));
+ if (external.variantType() != ModelHighAPI_Selection::VT_Empty)
+ aBSpline->setByExternal(external);
+ else if (knots.empty() || multiplicities.empty())
+ aBSpline->setByDegreePolesAndWeights(degree, aPoints, weights);
+ else
+ aBSpline->setByParameters(degree, aPoints, weights, knots, multiplicities);
+ }
+ return aBSpline;
+}
+
+//--------------------------------------------------------------------------------------
+static std::shared_ptr<SketchAPI_BSpline> buildInterpolation(
+ const CompositeFeaturePtr& theSketch,
+ const FeaturePtr& theCurveFittingFeature,
+ const std::list<ModelHighAPI_RefAttr>& points,
+ const bool periodic,
+ const bool closed)
+{
+ AttributeBooleanPtr aPeriodicAttr =
+ theCurveFittingFeature->boolean(SketchPlugin_CurveFitting::PERIODIC_ID());
+ fillAttribute(periodic, aPeriodicAttr);
+ AttributeBooleanPtr aClosedAttr =
+ theCurveFittingFeature->boolean(SketchPlugin_CurveFitting::CLOSED_ID());
+ fillAttribute(closed, aClosedAttr);
+ AttributeRefAttrListPtr aPointsAttr =
+ theCurveFittingFeature->refattrlist(SketchPlugin_CurveFitting::POINTS_ID());
+ fillAttribute(points, aPointsAttr);
+ apply(); // to execute and kill the macro-feature
+
+ // find created B-spline feature
+ BSplinePtr aBSpline;
+ const std::string& aKindToFind =
+ periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID();
+ int aNbSubs = theSketch->numberOfSubs();
+ for (int anIndex = aNbSubs - 1; anIndex >= 0; --anIndex) {
+ FeaturePtr aFeature = theSketch->subFeature(anIndex);
+ if (aFeature->getKind() == aKindToFind) {
+ aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature)
+ : new SketchAPI_BSpline(aFeature));
+ aBSpline->execute();
+ break;
+ }
+ }
+ return aBSpline;
+}
+
+std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addInterpolation(
+ const std::list<ModelHighAPI_RefAttr>& points,
+ const bool periodic,
+ const bool closed)
+{
+ CompositeFeaturePtr aSketch = compositeFeature();
+ FeaturePtr anInterpFeature = aSketch->addFeature(SketchPlugin_CurveFitting::ID());
+ anInterpFeature->string(SketchPlugin_CurveFitting::TYPE_ID())
+ ->setValue(SketchPlugin_CurveFitting::TYPE_INTERPOLATION_ID());
+ return buildInterpolation(aSketch, anInterpFeature, points, periodic, closed);
+}
+
+std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addApproximation(
+ const std::list<ModelHighAPI_RefAttr>& points,
+ const ModelHighAPI_Double& precision,
+ const bool periodic,
+ const bool closed)
+{
+ CompositeFeaturePtr aSketch = compositeFeature();
+ FeaturePtr anInterpFeature = aSketch->addFeature(SketchPlugin_CurveFitting::ID());
+ anInterpFeature->string(SketchPlugin_CurveFitting::TYPE_ID())
+ ->setValue(SketchPlugin_CurveFitting::TYPE_APPROXIMATION_ID());
+ fillAttribute(precision, anInterpFeature->real(SketchPlugin_CurveFitting::PRECISION_ID()));
+ return buildInterpolation(aSketch, anInterpFeature, points, periodic, closed);
+}
+
+//--------------------------------------------------------------------------------------