From: azv Date: Thu, 23 Jan 2020 15:23:45 +0000 (+0300) Subject: Issue #17347: B-Splines in Sketcher X-Git-Tag: V9_5_0a1~54^2~14 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=b72c6161a24798e2e523f323188fab669cb57f8f;p=modules%2Fshaper.git Issue #17347: B-Splines in Sketcher Implement periodic B-spline curves. --- diff --git a/src/GeomAPI/GeomAPI_BSpline2d.cpp b/src/GeomAPI/GeomAPI_BSpline2d.cpp index 58eb68580..820d4cf15 100644 --- a/src/GeomAPI/GeomAPI_BSpline2d.cpp +++ b/src/GeomAPI/GeomAPI_BSpline2d.cpp @@ -47,9 +47,13 @@ static Handle_Geom2d_BSplineCurve* newBSpline2d( if (theKnots.empty() || theMults.empty()) return newBSpline2d(thePoles, theWeights, theDegree, thePeriodic); + int anAuxPole = 0; + if (thePeriodic && thePoles.front()->distance(thePoles.back()) > Precision::Confusion()) + anAuxPole = 1; + // collect arrays of poles, weights, knots and multiplicities - TColgp_Array1OfPnt2d aPoles(1, (int)thePoles.size()); - TColStd_Array1OfReal aWeights(1, (int)theWeights.size()); + TColgp_Array1OfPnt2d aPoles(1, (int)thePoles.size() + anAuxPole); + TColStd_Array1OfReal aWeights(1, (int)theWeights.size() + anAuxPole); TColStd_Array1OfReal aKnots(1, (int)theKnots.size()); TColStd_Array1OfInteger aMults(1, (int)theMults.size()); @@ -70,6 +74,11 @@ static Handle_Geom2d_BSplineCurve* newBSpline2d( aMIt != theMults.end(); ++aMIt, ++anIndex) aMults.SetValue(anIndex, *aMIt); + if (thePeriodic) { + aPoles.ChangeLast() = aPoles.First(); + aWeights.ChangeLast() = aWeights.First(); + } + Handle(Geom2d_BSplineCurve) aCurve = new Geom2d_BSplineCurve(aPoles, aWeights, aKnots, aMults, theDegree, thePeriodic); return new Handle_Geom2d_BSplineCurve(aCurve); @@ -81,7 +90,21 @@ Handle_Geom2d_BSplineCurve* newBSpline2d( const int theDegree, const bool thePeriodic) { + std::list > aPoles = thePoles; + std::list aWeights = theWeights; + int aMult = theDegree + 1; int aNbKnots = (int)thePoles.size() - theDegree + 1; + if (thePeriodic) { + if (aPoles.front()->distance(aPoles.back()) < Precision::Confusion()) { + aPoles.pop_back(); + aWeights.pop_back(); + } + aPoles.push_back(aPoles.front()); + aWeights.push_back(aWeights.front()); + aMult = 1; + aNbKnots = (int)aPoles.size() + 1; + } + if (aNbKnots < 2) return new Handle_Geom2d_BSplineCurve(); @@ -95,10 +118,10 @@ Handle_Geom2d_BSplineCurve* newBSpline2d( aKnots.push_back(aEndParam); std::list aMults(aNbKnots - 2, 1); - aMults.push_front(theDegree + 1); - aMults.push_back(theDegree + 1); + aMults.push_front(aMult); + aMults.push_back(aMult); - return newBSpline2d(thePoles, theWeights, aKnots, aMults, theDegree, thePeriodic); + return newBSpline2d(aPoles, aWeights, aKnots, aMults, theDegree, thePeriodic); } static Handle_Geom2d_BSplineCurve* newBSpline2d( diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 8063b10ca..9855c5f4c 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -24,6 +24,7 @@ SET(PROJECT_HEADERS SketchPlugin.h SketchPlugin_Arc.h SketchPlugin_BSpline.h + SketchPlugin_BSplinePeriodic.h SketchPlugin_Circle.h SketchPlugin_Constraint.h SketchPlugin_ConstraintAngle.h @@ -76,6 +77,7 @@ SET(PROJECT_HEADERS SET(PROJECT_SOURCES SketchPlugin_Arc.cpp SketchPlugin_BSpline.cpp + SketchPlugin_BSplinePeriodic.cpp SketchPlugin_Circle.cpp SketchPlugin_Constraint.cpp SketchPlugin_ConstraintAngle.cpp diff --git a/src/SketchPlugin/SketchPlugin_BSpline.cpp b/src/SketchPlugin/SketchPlugin_BSpline.cpp index f4aee05a9..a56d5281a 100644 --- a/src/SketchPlugin/SketchPlugin_BSpline.cpp +++ b/src/SketchPlugin/SketchPlugin_BSpline.cpp @@ -160,6 +160,4 @@ void SketchPlugin_BSpline::attributeChanged(const std::string& theID) { std::dynamic_pointer_cast( attribute(END_ID()))->setValue(aPolesArray->pnt(aPolesArray->size() - 1)); } -//// else if (theID == REVERSED_ID() && myParamDelta == 0.0) -//// myParamDelta = 2.0 * PI; } diff --git a/src/SketchPlugin/SketchPlugin_BSplinePeriodic.cpp b/src/SketchPlugin/SketchPlugin_BSplinePeriodic.cpp new file mode 100644 index 000000000..a20ec2abf --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_BSplinePeriodic.cpp @@ -0,0 +1,152 @@ +// Copyright (C) 2019-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + + +SketchPlugin_BSplinePeriodic::SketchPlugin_BSplinePeriodic() + : SketchPlugin_SketchEntity() +{ +} + +void SketchPlugin_BSplinePeriodic::initDerivedClassAttributes() +{ + data()->addAttribute(POLES_ID(), GeomDataAPI_Point2DArray::typeId()); + data()->addAttribute(WEIGHTS_ID(), ModelAPI_AttributeDoubleArray::typeId()); + data()->addAttribute(KNOTS_ID(), ModelAPI_AttributeDoubleArray::typeId()); + data()->addAttribute(MULTS_ID(), ModelAPI_AttributeIntArray::typeId()); + data()->addAttribute(DEGREE_ID(), ModelAPI_AttributeInteger::typeId()); + + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); +} + +void SketchPlugin_BSplinePeriodic::execute() +{ + SketchPlugin_Sketch* aSketch = sketch(); + if(!aSketch) { + return; + } + + AttributePoint2DArrayPtr aPolesArray = + std::dynamic_pointer_cast(attribute(POLES_ID())); + AttributeDoubleArrayPtr aWeightsArray = data()->realArray(WEIGHTS_ID()); + AttributeDoubleArrayPtr aKnotsArray = data()->realArray(KNOTS_ID()); + AttributeIntArrayPtr aMultsArray = data()->intArray(MULTS_ID()); + AttributeIntegerPtr aDegreeAttr = data()->integer(DEGREE_ID()); + + // collect poles + std::list aPoles2D; + for (int anIndex = 0; anIndex < aPolesArray->size(); ++anIndex) { + GeomPnt2dPtr aPole = aPolesArray->pnt(anIndex); + aPoles2D.push_back(aPole); + } + // collect weights + std::list aWeights; + for (int anIndex = 0; anIndex < aWeightsArray->size(); ++anIndex) + aWeights.push_back(aWeightsArray->value(anIndex)); + // collect knots + std::list aKnots; + for (int anIndex = 0; anIndex < aKnotsArray->size(); ++anIndex) + aKnots.push_back(aKnotsArray->value(anIndex)); + // collect multiplicities + std::list aMults; + for (int anIndex = 0; anIndex < aMultsArray->size(); ++anIndex) + aMults.push_back(aMultsArray->value(anIndex)); + + // create result non-periodic B-spline curve + GeomShapePtr anEdge = GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(aSketch->coordinatePlane(), + aPoles2D, aWeights, aKnots, aMults, aDegreeAttr->value(), true); + + ResultConstructionPtr aResult = document()->createConstruction(data(), 0); + aResult->setShape(anEdge); + aResult->setIsInHistory(false); + setResult(aResult, 0); +} + +bool SketchPlugin_BSplinePeriodic::isFixed() { + return data()->selection(EXTERNAL_ID())->context().get() != NULL; +} + +void SketchPlugin_BSplinePeriodic::attributeChanged(const std::string& theID) { + // the second condition for unability to move external segments anywhere + if (theID == EXTERNAL_ID() || isFixed()) { + std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); + if (!aSelection) { + // empty shape in selection shows that the shape is equal to context + ResultPtr anExtRes = selection(EXTERNAL_ID())->context(); + if (anExtRes) + aSelection = anExtRes->shape(); + } +//// // update arguments due to the selection value +//// if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { +//// std::shared_ptr anEdge(new GeomAPI_Edge(aSelection)); +//// std::shared_ptr anEllipse = anEdge->ellipse(); +//// +//// bool aWasBlocked = data()->blockSendAttributeUpdated(true); +//// std::shared_ptr aCenterAttr = +//// std::dynamic_pointer_cast(attribute(CENTER_ID())); +//// aCenterAttr->setValue(sketch()->to2D(anEllipse->center())); +//// +//// std::shared_ptr aFocusAttr = +//// std::dynamic_pointer_cast(attribute(FIRST_FOCUS_ID())); +//// aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus())); +//// +//// std::shared_ptr aStartAttr = +//// std::dynamic_pointer_cast(attribute(START_POINT_ID())); +//// aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint())); +//// +//// std::shared_ptr aEndAttr = +//// std::dynamic_pointer_cast(attribute(END_POINT_ID())); +//// aEndAttr->setValue(sketch()->to2D(anEdge->lastPoint())); +//// +//// real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius()); +//// real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius()); +//// +//// double aStartParam, aMidParam, aEndParam; +//// anEllipse->parameter(anEdge->firstPoint(), tolerance, aStartParam); +//// anEllipse->parameter(anEdge->middlePoint(), tolerance, aMidParam); +//// anEllipse->parameter(anEdge->lastPoint(), tolerance, aEndParam); +//// if (aEndParam < aStartParam) +//// aEndParam += 2.0 * PI; +//// if (aMidParam < aStartParam) +//// aMidParam += 2.0 * PI; +//// boolean(REVERSED_ID())->setValue(aMidParam > aEndParam); +//// +//// data()->blockSendAttributeUpdated(aWasBlocked, false); +//// +//// fillCharacteristicPoints(); +//// } + } +} diff --git a/src/SketchPlugin/SketchPlugin_BSplinePeriodic.h b/src/SketchPlugin/SketchPlugin_BSplinePeriodic.h new file mode 100644 index 000000000..80e6bfaec --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_BSplinePeriodic.h @@ -0,0 +1,99 @@ +// Copyright (C) 2019-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef SketchPlugin_BSplinePeriodic_H_ +#define SketchPlugin_BSplinePeriodic_H_ + +#include +#include + +/**\class SketchPlugin_BSplinePeriodic + * \ingroup Plugins + * \brief Feature for creation of the periodic B-spline curve in the sketch. + */ +class SketchPlugin_BSplinePeriodic : public SketchPlugin_SketchEntity +{ +public: + /// Ellipse feature kind + inline static const std::string& ID() + { + static const std::string ID("SketchBSplinePeriodic"); + return ID; + } + + /// list of B-spline poles + inline static const std::string& POLES_ID() + { + static const std::string ID("poles"); + return ID; + } + + /// list of B-spline weights + inline static const std::string& WEIGHTS_ID() + { + static const std::string ID("weights"); + return ID; + } + + /// attribute to store the degree of B-spline + inline static const std::string& DEGREE_ID() + { + static const std::string ID("degree"); + return ID; + } + + /// list of B-spline knots + inline static const std::string& KNOTS_ID() + { + static const std::string ID("knots"); + return ID; + } + + /// list of B-spline multiplicities + inline static const std::string& MULTS_ID() + { + static const std::string ID("multiplicities"); + return ID; + } + + /// Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_BSplinePeriodic::ID(); + return MY_KIND; + } + + /// Returns true is sketch element is under the rigid constraint + SKETCHPLUGIN_EXPORT virtual bool isFixed(); + + /// Called on change of any argument-attribute of this object + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// Use plugin manager for features creation + SketchPlugin_BSplinePeriodic(); + +protected: + /// \brief Initializes attributes of derived class. + virtual void initDerivedClassAttributes(); +}; + +#endif diff --git a/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp b/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp index 282004946..5f325dedf 100644 --- a/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -67,6 +68,13 @@ SketchPlugin_MacroBSpline::SketchPlugin_MacroBSpline() { } +SketchPlugin_MacroBSpline::SketchPlugin_MacroBSpline(bool isPeriodic) + : SketchPlugin_SketchEntity(), + myDegree(3), + myIsPeriodic(isPeriodic) +{ +} + void SketchPlugin_MacroBSpline::initAttributes() { data()->addAttribute(POLES_ID(), GeomDataAPI_Point2DArray::typeId()); @@ -143,52 +151,55 @@ std::string SketchPlugin_MacroBSpline::processEvent( FeaturePtr SketchPlugin_MacroBSpline::createBSplineFeature() { - FeaturePtr aBSpline = sketch()->addFeature(SketchPlugin_BSpline::ID()); + FeaturePtr aBSpline = sketch()->addFeature( + myIsPeriodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID()); - aBSpline->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(myDegree); + aBSpline->integer(myIsPeriodic ? SketchPlugin_BSplinePeriodic::DEGREE_ID() + : SketchPlugin_BSpline::DEGREE_ID())->setValue(myDegree); AttributePoint2DArrayPtr aPoles = std::dynamic_pointer_cast( - aBSpline->attribute(SketchPlugin_BSpline::POLES_ID())); + aBSpline->attribute(myIsPeriodic ? SketchPlugin_BSplinePeriodic::POLES_ID() + : SketchPlugin_BSpline::POLES_ID())); AttributePoint2DArrayPtr aPolesMacro = std::dynamic_pointer_cast(attribute(POLES_ID())); aPoles->assign(aPolesMacro); - AttributeDoubleArrayPtr aWeights = - aBSpline->data()->realArray(SketchPlugin_BSpline::WEIGHTS_ID()); + AttributeDoubleArrayPtr aWeights = aBSpline->data()->realArray( + myIsPeriodic ? SketchPlugin_BSplinePeriodic::WEIGHTS_ID() + : SketchPlugin_BSpline::WEIGHTS_ID()); AttributeDoubleArrayPtr aWeightsMacro = data()->realArray(WEIGHTS_ID()); int aSize = aWeightsMacro->size(); aWeights->setSize(aSize); for (int index = 0; index < aSize; ++index) aWeights->setValue(index, aWeightsMacro->value(index)); - AttributeDoubleArrayPtr aKnots = - aBSpline->data()->realArray(SketchPlugin_BSpline::KNOTS_ID()); + AttributeDoubleArrayPtr aKnots = aBSpline->data()->realArray( + myIsPeriodic ? SketchPlugin_BSplinePeriodic::KNOTS_ID() : SketchPlugin_BSpline::KNOTS_ID()); aSize = (int)myKnots.size(); aKnots->setSize(aSize); std::list::iterator aKIt = myKnots.begin(); for (int index = 0; index < aSize; ++index, ++aKIt) aKnots->setValue(index, *aKIt); - AttributeIntArrayPtr aMults = - aBSpline->data()->intArray(SketchPlugin_BSpline::MULTS_ID()); + AttributeIntArrayPtr aMults = aBSpline->data()->intArray( + myIsPeriodic ? SketchPlugin_BSplinePeriodic::MULTS_ID() : SketchPlugin_BSpline::MULTS_ID()); aSize = (int)myMultiplicities.size(); aMults->setSize(aSize); std::list::iterator aMIt = myMultiplicities.begin(); for (int index = 0; index < aSize; ++index, ++aMIt) aMults->setValue(index, *aMIt); - SketchPlugin_Sketch* aSketch = - std::dynamic_pointer_cast(aBSpline)->sketch(); - - AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast( - aBSpline->attribute(SketchPlugin_BSpline::START_ID())); - aStartPoint->setValue(aPoles->pnt(0)); + if (!myIsPeriodic) { + AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast( + aBSpline->attribute(SketchPlugin_BSpline::START_ID())); + aStartPoint->setValue(aPoles->pnt(0)); - AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast( - aBSpline->attribute(SketchPlugin_BSpline::END_ID())); - aEndPoint->setValue(aPoles->pnt(aPoles->size() - 1)); + AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast( + aBSpline->attribute(SketchPlugin_BSpline::END_ID())); + aEndPoint->setValue(aPoles->pnt(aPoles->size() - 1)); + } - aBSpline->boolean(SketchPlugin_BSpline::AUXILIARY_ID())->setValue( + aBSpline->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue( boolean(AUXILIARY_ID())->value()); aBSpline->execute(); @@ -208,6 +219,10 @@ void SketchPlugin_MacroBSpline::createControlPolygon(FeaturePtr theBSpline, // segments for (int index = 1; index < aSize; ++index) createAuxiliarySegment(theBSpline, aPoles, index - 1, index); + if (myIsPeriodic) { + // additional segment to close the control polygon + createAuxiliarySegment(theBSpline, aPoles, aSize - 1, 0); + } } void SketchPlugin_MacroBSpline::constraintsForPoles(const std::list& thePoles) @@ -243,8 +258,6 @@ AISObjectPtr SketchPlugin_MacroBSpline::getAISObject(AISObjectPtr thePrevious) if (!aSketch) return AISObjectPtr(); - static const bool PERIODIC = false; - AttributePoint2DArrayPtr aPolesArray = std::dynamic_pointer_cast(attribute(POLES_ID())); AttributeDoubleArrayPtr aWeightsArray = data()->realArray(WEIGHTS_ID()); @@ -273,7 +286,7 @@ AISObjectPtr SketchPlugin_MacroBSpline::getAISObject(AISObjectPtr thePrevious) // create result non-periodic B-spline curve std::shared_ptr aBSplineCurve; try { - aBSplineCurve.reset(new GeomAPI_BSpline2d(aPoles2D, aWeights, PERIODIC)); + aBSplineCurve.reset(new GeomAPI_BSpline2d(aPoles2D, aWeights, myIsPeriodic)); } catch (...) { // cannot build a B-spline curve return AISObjectPtr(); diff --git a/src/SketchPlugin/SketchPlugin_MacroBSpline.h b/src/SketchPlugin/SketchPlugin_MacroBSpline.h index d8a0e5b89..78ef86823 100644 --- a/src/SketchPlugin/SketchPlugin_MacroBSpline.h +++ b/src/SketchPlugin/SketchPlugin_MacroBSpline.h @@ -105,6 +105,9 @@ public: /// Use plugin manager for features creation SketchPlugin_MacroBSpline(); +protected: + SketchPlugin_MacroBSpline(bool isPeriodic); + private: FeaturePtr createBSplineFeature(); @@ -117,4 +120,29 @@ private: bool myIsPeriodic; }; + +/**\class SketchPlugin_MacroBSpline +* \ingroup Plugins +* \brief Feature for creation of the new B-spline in Sketch. +*/ +class SketchPlugin_MacroBSplinePeriodic : public SketchPlugin_MacroBSpline +{ +public: + /// B-spline macro feature kind + inline static const std::string& ID() + { + static const std::string ID("SketchMacroBSplinePeriodic"); + return ID; + } + + /// Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + return SketchPlugin_MacroBSpline::ID(); + } + + /// Use plugin manager for features creation + SketchPlugin_MacroBSplinePeriodic() : SketchPlugin_MacroBSpline(true) {} +}; + #endif diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index a6ef2a190..db8995277 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -207,6 +208,8 @@ FeaturePtr SketchPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new SketchPlugin_Arc); } else if (theFeatureID == SketchPlugin_BSpline::ID()) { return FeaturePtr(new SketchPlugin_BSpline); + } else if (theFeatureID == SketchPlugin_BSplinePeriodic::ID()) { + return FeaturePtr(new SketchPlugin_BSplinePeriodic); } else if (theFeatureID == SketchPlugin_Projection::ID()) { return FeaturePtr(new SketchPlugin_Projection); } else if (theFeatureID == SketchPlugin_ConstraintCoincidence::ID()) { @@ -259,6 +262,8 @@ FeaturePtr SketchPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new SketchPlugin_MacroArc); } else if (theFeatureID == SketchPlugin_MacroBSpline::ID()) { return FeaturePtr(new SketchPlugin_MacroBSpline); + } else if (theFeatureID == SketchPlugin_MacroBSplinePeriodic::ID()) { + return FeaturePtr(new SketchPlugin_MacroBSplinePeriodic); } else if (theFeatureID == SketchPlugin_MacroCircle::ID()) { return FeaturePtr(new SketchPlugin_MacroCircle); } else if (theFeatureID == SketchPlugin_Ellipse::ID()) { @@ -315,6 +320,7 @@ std::shared_ptr SketchPlugin_Plugin aMsg->setState(SketchPlugin_Circle::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_Arc::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_BSpline::ID(), aHasSketchPlane); + aMsg->setState(SketchPlugin_BSplinePeriodic::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_Ellipse::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_EllipticArc::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_Projection::ID(), aHasSketchPlane); @@ -341,6 +347,7 @@ std::shared_ptr SketchPlugin_Plugin aMsg->setState(SketchPlugin_Trim::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_MacroArc::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_MacroBSpline::ID(), aHasSketchPlane); + aMsg->setState(SketchPlugin_MacroBSplinePeriodic::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_MacroCircle::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_MacroEllipse::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_MacroEllipticArc::ID(), aHasSketchPlane); diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 368f3d602..c055b3310 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -6,7 +6,7 @@ nested="SketchPoint SketchIntersectionPoint SketchLine SketchCircle SketchMacroCircle SketchArc SketchMacroArc SketchEllipse SketchMacroEllipse SketchEllipticArc SketchMacroEllipticArc - SketchBSpline SketchMacroBSpline + SketchBSpline SketchMacroBSpline SketchMacroBSplinePeriodic SketchRectangle SketchProjection SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical @@ -620,6 +620,28 @@ change_visual_attributes="true"/> + + + + + + + + + + + + + + + + + diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp index 24659d406..988a3c5a4 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -88,8 +89,10 @@ static EntityWrapperPtr createScalar(const AttributePtr& theAttribute, (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() && anOwner->getKind() == SketchPlugin_MultiRotation::ID())) aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage))); - else if (anOwner->getKind() == SketchPlugin_BSpline::ID() && - theAttribute->id() == SketchPlugin_BSpline::DEGREE_ID()) + else if ((anOwner->getKind() == SketchPlugin_BSpline::ID() && + theAttribute->id() == SketchPlugin_BSpline::DEGREE_ID()) || + (anOwner->getKind() == SketchPlugin_BSplinePeriodic::ID() && + theAttribute->id() == SketchPlugin_BSplinePeriodic::DEGREE_ID())) // Degree of B-spline is not processed by the solver aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr))); else @@ -99,6 +102,13 @@ static EntityWrapperPtr createScalar(const AttributePtr& theAttribute, return aWrapper; } +template +static bool nonSolverAttribute(const FeaturePtr theOwner, const std::string& theAttrId) +{ + return theOwner->getKind() == TYPE::ID() && (theAttrId == TYPE::WEIGHTS_ID() + || theAttrId == TYPE::KNOTS_ID() || theAttrId == TYPE::MULTS_ID()); +} + static EntityWrapperPtr createScalarArray(const AttributePtr& theAttribute, PlaneGCSSolver_Storage* theStorage) { @@ -110,10 +120,8 @@ static EntityWrapperPtr createScalarArray(const AttributePtr& theAttribute, PlaneGCSSolver_Storage* aStorage = theStorage; // Weights, knots and multiplicities of B-spline curve are not processed by the solver FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); - if (anOwner->getKind() == SketchPlugin_BSpline::ID() && - (theAttribute->id() == SketchPlugin_BSpline::WEIGHTS_ID() || - theAttribute->id() == SketchPlugin_BSpline::KNOTS_ID() || - theAttribute->id() == SketchPlugin_BSpline::MULTS_ID())) + if (nonSolverAttribute(anOwner, theAttribute->id()) || + nonSolverAttribute(anOwner, theAttribute->id())) aStorage = 0; int aSize = anArray.size(); diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp index 8db97df1a..e797abad2 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -48,6 +49,7 @@ static EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes, static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes); static EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes, PlaneGCSSolver_Storage* theStorage); +template static EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes); @@ -107,7 +109,9 @@ EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeat aResult = createEllipticArc(myAttributes, myStorage); // B-spline curve else if (aFeatureKind == SketchPlugin_BSpline::ID()) - aResult = createBSpline(myAttributes); + aResult = createBSpline(myAttributes); + else if (aFeatureKind == SketchPlugin_BSplinePeriodic::ID()) + aResult = createBSpline(myAttributes); // 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()) { @@ -294,19 +298,20 @@ EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes, return anEllipseWrapper; } +template EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes) { std::shared_ptr aNewSpline(new GCS::BSplineImpl); aNewSpline->degree = 3; - aNewSpline->periodic = false; + aNewSpline->periodic = std::is_same(); std::map anAdditionalAttributes; AttributeEntityMap::const_iterator anIt = theAttributes.begin(); for (; anIt != theAttributes.end(); ++anIt) { const std::string& anAttrID = anIt->first->id(); - if (anAttrID == SketchPlugin_BSpline::POLES_ID()) { + if (anAttrID == TYPE::POLES_ID()) { PointArrayWrapperPtr anArray = std::dynamic_pointer_cast(anIt->second); @@ -318,7 +323,7 @@ EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes) aNewSpline->start = aNewSpline->poles.front(); aNewSpline->end = aNewSpline->poles.back(); } - else if (anAttrID == SketchPlugin_BSpline::DEGREE_ID()) { + else if (anAttrID == TYPE::DEGREE_ID()) { ScalarWrapperPtr aScalar = std::dynamic_pointer_cast(anIt->second); aNewSpline->degree = (int)aScalar->value(); @@ -330,11 +335,11 @@ EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes) else { ScalarArrayWrapperPtr anArray = std::dynamic_pointer_cast(anIt->second); - if (anAttrID == SketchPlugin_BSpline::WEIGHTS_ID()) + if (anAttrID == TYPE::WEIGHTS_ID()) aNewSpline->weights = anArray->array(); - else if (anAttrID == SketchPlugin_BSpline::KNOTS_ID()) + else if (anAttrID == TYPE::KNOTS_ID()) aNewSpline->knots = anArray->array(); - else if (anAttrID == SketchPlugin_BSpline::MULTS_ID()) { + else if (anAttrID == TYPE::MULTS_ID()) { const GCS::VEC_pD& aValues = anArray->array(); aNewSpline->mult.reserve(aValues.size()); for (GCS::VEC_pD::const_iterator anIt = aValues.begin(); anIt != aValues.end(); ++anIt) diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index c190ae1b9..2605ddf93 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -378,6 +378,8 @@ static void createBSplineConstraints( EdgeWrapperPtr anEdge = std::dynamic_pointer_cast(theCurve); std::shared_ptr aBSpline = std::dynamic_pointer_cast(anEdge->entity()); + if (aBSpline->periodic) + return; // additional constraints are not necessary std::list aBSplineConstraints; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index 939b7a263..e29d23018 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -483,6 +484,13 @@ bool PlaneGCSSolver_Tools::isAttributeApplicable(const std::string& theAttrName, theAttrName == SketchPlugin_BSpline::START_ID() || theAttrName == SketchPlugin_BSpline::END_ID(); } + else if (theOwnerName == SketchPlugin_BSplinePeriodic::ID()) { + return theAttrName == SketchPlugin_BSplinePeriodic::POLES_ID() || + theAttrName == SketchPlugin_BSplinePeriodic::WEIGHTS_ID() || + theAttrName == SketchPlugin_BSplinePeriodic::KNOTS_ID() || + theAttrName == SketchPlugin_BSplinePeriodic::MULTS_ID() || + theAttrName == SketchPlugin_BSplinePeriodic::DEGREE_ID(); + } // suppose that all remaining features are points return theAttrName == SketchPlugin_Point::COORD_ID();