Process point-on-bspline constraint be the sketch solver.
SET(PROJECT_HEADERS
GeomAPI.h
+ GeomAPI_BSpline2d.h
GeomAPI_Circ.h
GeomAPI_Circ2d.h
GeomAPI_Interface.h
)
SET(PROJECT_SOURCES
+ GeomAPI_BSpline2d.cpp
GeomAPI_Circ.cpp
GeomAPI_Circ2d.cpp
GeomAPI_Interface.cpp
--- /dev/null
+// 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 <GeomAPI_BSpline2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
+#include <Geom2d_BSplineCurve.hxx>
+
+#define MY_BSPLINE (*(implPtr<Handle_Geom2d_BSplineCurve>()))
+
+
+static Handle_Geom2d_BSplineCurve* newBSpline2d(
+ const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+ const std::list<double>& theWeights,
+ const int theDegree,
+ const bool thePeriodic)
+{
+ int aNbKnots = (int)thePoles.size() - theDegree + 1;
+ if (aNbKnots < 2)
+ return new Handle_Geom2d_BSplineCurve();
+
+ // collect arrays of poles, weights, knots and multiplicities
+ TColgp_Array1OfPnt2d aPoles(1, (int)thePoles.size());
+ TColStd_Array1OfReal aWeights(1, (int)theWeights.size());
+ TColStd_Array1OfReal aKnots(1, aNbKnots);
+ TColStd_Array1OfInteger aMults(1, aNbKnots);
+
+ int anIndex = 1;
+ for (std::list<GeomPnt2dPtr>::const_iterator aPIt = thePoles.begin();
+ aPIt != thePoles.end(); ++aPIt, ++anIndex)
+ aPoles.SetValue(anIndex, gp_Pnt2d((*aPIt)->x(), (*aPIt)->y()));
+ anIndex = 1;
+ for (std::list<double>::const_iterator aWIt = theWeights.begin();
+ aWIt != theWeights.end(); ++aWIt, ++anIndex)
+ aWeights.SetValue(anIndex, *aWIt);
+ anIndex = 1;
+ static const double aStartParam = 0.0;
+ static const double aEndParam = 1.0;
+ double aStep = aEndParam / (aNbKnots - 1);
+ for (double aKnot = aStartParam; anIndex < aNbKnots; ++anIndex, aKnot += aStep)
+ aKnots.SetValue(anIndex, aKnot);
+ aKnots.ChangeLast() = aEndParam;
+ anIndex = 1;
+ aMults.SetValue(anIndex, theDegree + 1);
+ for (++anIndex; anIndex < aNbKnots; ++anIndex)
+ aMults.SetValue(anIndex, 1);
+ aMults.SetValue(aNbKnots, theDegree + 1);
+
+ Handle(Geom2d_BSplineCurve) aCurve =
+ new Geom2d_BSplineCurve(aPoles, aWeights, aKnots, aMults, theDegree, thePeriodic);
+ return new Handle_Geom2d_BSplineCurve(aCurve);
+}
+
+static Handle_Geom2d_BSplineCurve* newBSpline2d(
+ const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+ const std::list<double>& theWeights,
+ const bool thePeriodic)
+{
+ int aDegree = 3;
+ if ((int)thePoles.size() <= aDegree)
+ aDegree = (int)thePoles.size() - 1;
+ if (aDegree <= 0)
+ return new Handle_Geom2d_BSplineCurve();
+ return newBSpline2d(thePoles, theWeights, aDegree, thePeriodic);
+}
+
+
+GeomAPI_BSpline2d::GeomAPI_BSpline2d(const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+ const std::list<double>& theWeights,
+ const bool thePeriodic)
+ : GeomAPI_Interface(newBSpline2d(thePoles, theWeights, thePeriodic))
+{
+ if (isNull())
+ throw Standard_ConstructionError("GeomAPI_BSpline2d: Impossible to create B-spline curve");
+}
+
+GeomAPI_BSpline2d::GeomAPI_BSpline2d(const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+ const std::list<double>& theWeights,
+ const int theDegree,
+ const bool thePeriodic)
+ : GeomAPI_Interface(newBSpline2d(thePoles, theWeights, theDegree, thePeriodic))
+{
+ if (isNull())
+ throw Standard_ConstructionError("GeomAPI_BSpline2d: Impossible to create B-spline curve");
+}
+
+bool GeomAPI_BSpline2d::isNull() const
+{
+ return MY_BSPLINE.IsNull();
+}
+
+int GeomAPI_BSpline2d::degree() const
+{
+ return MY_BSPLINE->Degree();
+}
+
+void GeomAPI_BSpline2d::D0(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
+{
+ gp_Pnt2d aPnt;
+ MY_BSPLINE->D0(theU, aPnt);
+ thePoint.reset(new GeomAPI_Pnt2d(aPnt.X(), aPnt.Y()));
+}
+
+void GeomAPI_BSpline2d::D1(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint,
+ std::shared_ptr<GeomAPI_XY>& theDerivative)
+{
+ gp_Pnt2d aPnt;
+ gp_Vec2d aVec;
+ MY_BSPLINE->D1(theU, aPnt, aVec);
+ thePoint.reset(new GeomAPI_Pnt2d(aPnt.X(), aPnt.Y()));
+ theDerivative.reset(new GeomAPI_XY(aVec.X(), aVec.Y()));
+}
--- /dev/null
+// 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 GeomAPI_BSpline2d_H_
+#define GeomAPI_BSpline2d_H_
+
+#include <GeomAPI_Interface.h>
+
+#include <list>
+#include <memory>
+
+class GeomAPI_Pnt2d;
+class GeomAPI_XY;
+
+/** \class GeomAPI_BSpline2d
+ * \ingroup DataModel
+ * \brief B-spline curve in 2D
+ */
+class GeomAPI_BSpline2d : public GeomAPI_Interface
+{
+public:
+ /// Creation of B-spline curve defined by list of poles and weights
+ GEOMAPI_EXPORT GeomAPI_BSpline2d(const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+ const std::list<double>& theWeights,
+ const bool thePeriodic = false);
+
+ /// Creation of B-spline curve defined by list of poles and weights
+ GEOMAPI_EXPORT GeomAPI_BSpline2d(const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+ const std::list<double>& theWeights,
+ const int theDegree,
+ const bool thePeriodic = false);
+
+ /// Returns true if curve is not initialized
+ GEOMAPI_EXPORT bool isNull() const;
+
+ /// Returns degree of the curve
+ GEOMAPI_EXPORT int degree() const;
+
+ /// \brief Calculate point on B-spline curve accrding to the given parameter
+ GEOMAPI_EXPORT void D0(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
+
+ /// \brief Calculate point and first derivative for B-spline curve accrding to the given parameter
+ GEOMAPI_EXPORT void D1(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint,
+ std::shared_ptr<GeomAPI_XY>& theDerivative);
+};
+
+#endif
#include <GeomAlgoAPI_EdgeBuilder.h>
#include <GeomAPI_Ax2.h>
+#include <GeomAPI_BSpline2d.h>
#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Pln.h>
+#include <GeomAPI_Pnt2d.h>
#include <gp_Pln.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS.hxx>
#include <BRep_Tool.hxx>
-#include <Geom_BSplineCurve.hxx>
+#include <Geom2d_BSplineCurve.hxx>
#include <Geom_Plane.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
+#include <GeomLib.hxx>
#include <gp_Ax2.hxx>
#include <gp_Circ.hxx>
return aRes;
}
-GeomEdgePtr GeomAlgoAPI_EdgeBuilder::bspline(const std::vector<GeomPointPtr>& thePoles,
- const std::vector<double>& theWeights,
- const bool thePeriodic)
+GeomEdgePtr GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(
+ const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const std::list<GeomPnt2dPtr>& thePoles,
+ const std::list<double>& theWeights,
+ const bool thePeriodic)
{
- int aDegree = 3;
- if ((int)thePoles.size() <= aDegree)
- aDegree = (int)thePoles.size() - 1;
- if (aDegree <= 0)
- return GeomEdgePtr();
-
- int aNbKnots = (int)thePoles.size() - aDegree + 1;
-
- // collect arrays of poles, weights, knots and multiplicities
- TColgp_Array1OfPnt aPoles(1, (int)thePoles.size());
- TColStd_Array1OfReal aWeights(1, (int)theWeights.size());
- TColStd_Array1OfReal aKnots(1, aNbKnots);
- TColStd_Array1OfInteger aMults(1, aNbKnots);
-
- int anIndex = 1;
- for (std::vector<GeomPointPtr>::const_iterator aPIt = thePoles.begin();
- aPIt != thePoles.end(); ++aPIt, ++anIndex)
- aPoles.SetValue(anIndex, gp_Pnt((*aPIt)->x(), (*aPIt)->y(), (*aPIt)->z()));
- anIndex = 1;
- for (std::vector<double>::const_iterator aWIt = theWeights.begin();
- aWIt != theWeights.end(); ++aWIt, ++anIndex)
- aWeights.SetValue(anIndex, *aWIt);
- anIndex = 1;
- static const double aStartParam = 0.0;
- static const double aEndParam = 1.0;
- double aStep = aEndParam / (aNbKnots - 1);
- for (double aKnot = aStartParam; anIndex < aNbKnots; ++anIndex, aKnot += aStep)
- aKnots.SetValue(anIndex, aKnot);
- aKnots.ChangeLast() = aEndParam;
- anIndex = 1;
- aMults.SetValue(anIndex, aDegree + 1);
- for (++anIndex; anIndex < aNbKnots; ++anIndex)
- aMults.SetValue(anIndex, 1);
- aMults.SetValue(aNbKnots, aDegree + 1);
-
- Handle(Geom_BSplineCurve) aCurve =
- new Geom_BSplineCurve(aPoles, aWeights, aKnots, aMults, aDegree, thePeriodic);
-
- BRepBuilderAPI_MakeEdge anEdgeBuilder(aCurve, aStartParam, aEndParam);
+ std::shared_ptr<GeomAPI_BSpline2d> aBSplineCurve(
+ new GeomAPI_BSpline2d(thePoles, theWeights, thePeriodic));
+ return bsplineOnPlane(thePlane, aBSplineCurve);
+}
+
+GeomEdgePtr GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(
+ const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const std::shared_ptr<GeomAPI_BSpline2d>& theCurve)
+{
+ Handle(Geom_Curve) aCurve3D = GeomLib::To3d(thePlane->impl<gp_Pln>().Position().Ax2(),
+ theCurve->impl<Handle_Geom2d_BSplineCurve>());
+
+ BRepBuilderAPI_MakeEdge anEdgeBuilder(aCurve3D);
GeomEdgePtr aRes(new GeomAPI_Edge);
TopoDS_Edge anEdge = anEdgeBuilder.Edge();
aRes->setImpl(new TopoDS_Shape(anEdge));
#include <memory>
#include <vector>
+class GeomAPI_BSpline2d;
+
/**\class GeomAlgoAPI_EdgeBuilder
* \ingroup DataAlgo
* \brief Allows to create face-shapes by different parameters
const std::shared_ptr<GeomAPI_Pnt>& theStart,
const std::shared_ptr<GeomAPI_Pnt>& theEnd);
- /// Creates B-spline edge
- static GeomEdgePtr bspline(const std::vector<GeomPointPtr>& thePoles,
- const std::vector<double>& theWeights,
- const bool thePeriodic);
+ /// Creates planar B-spline edge
+ static GeomEdgePtr bsplineOnPlane(const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+ const std::list<double>& theWeights,
+ const bool thePeriodic);
+
+ /// Creates planar B-spline edge
+ static GeomEdgePtr bsplineOnPlane(const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const std::shared_ptr<GeomAPI_BSpline2d>& theCurve);
};
#endif
#include <GeomDataAPI_Point2DArray.h>
#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
{
data()->addAttribute(POLES_ID(), GeomDataAPI_Point2DArray::typeId());
data()->addAttribute(WEIGHTS_ID(), ModelAPI_AttributeDoubleArray::typeId());
+ data()->addAttribute(DEGREE_ID(), ModelAPI_AttributeInteger::typeId());
data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(attribute(POLES_ID()));
AttributeDoubleArrayPtr aWeightsArray = data()->realArray(WEIGHTS_ID());
- // convert poles to 3D
- std::vector<GeomPointPtr> aPoles3D;
- aPoles3D.reserve(aPolesArray->size());
+ // collect poles
+ std::list<GeomPnt2dPtr> aPoles2D;
for (int anIndex = 0; anIndex < aPolesArray->size(); ++anIndex) {
GeomPnt2dPtr aPole = aPolesArray->pnt(anIndex);
- aPoles3D.push_back(aSketch->to3D(aPole->x(), aPole->y()));
+ aPoles2D.push_back(aPole);
}
// collect weights
- std::vector<double> aWeights;
- aWeights.reserve(aWeightsArray->size());
+ std::list<double> aWeights;
for (int anIndex = 0; anIndex < aWeightsArray->size(); ++anIndex)
aWeights.push_back(aWeightsArray->value(anIndex));
// create result non-periodic B-spline curve
- GeomShapePtr anEdge = GeomAlgoAPI_EdgeBuilder::bspline(aPoles3D, aWeights, false);
+ GeomShapePtr anEdge =
+ GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(aSketch->plane(), aPoles2D, aWeights, false);
ResultConstructionPtr aResult = document()->createConstruction(data(), 0);
aResult->setShape(anEdge);
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;
+ }
+
/// Returns the kind of a feature
SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
{
#include <GeomAlgoAPI_EdgeBuilder.h>
#include <GeomAlgoAPI_PointBuilder.h>
+#include <GeomAPI_BSpline2d.h>
+
#include <sstream>
// Create Point feature coincident with the B-spline pole
SketchPlugin_MacroBSpline::SketchPlugin_MacroBSpline()
: SketchPlugin_SketchEntity(),
+ myDegree(3),
myIsPeriodic(false)
{
}
{
FeaturePtr aBSpline = sketch()->addFeature(SketchPlugin_BSpline::ID());
+ aBSpline->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(myDegree);
+
AttributePoint2DArrayPtr aPoles = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
aBSpline->attribute(SketchPlugin_BSpline::POLES_ID()));
AttributePoint2DArrayPtr aPolesMacro =
if (!aSketch)
return AISObjectPtr();
+ static const bool PERIODIC = false;
+
AttributePoint2DArrayPtr aPolesArray =
std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(attribute(POLES_ID()));
AttributeDoubleArrayPtr aWeightsArray = data()->realArray(WEIGHTS_ID());
+ if (aPolesArray->size() < 2)
+ return AISObjectPtr();
+
std::list<GeomShapePtr> aShapes;
- // convert poles to 3D and collect weights
- std::vector<GeomPointPtr> aPoles3D;
- aPoles3D.reserve(aPolesArray->size());
- std::vector<double> aWeights;
- aWeights.reserve(aWeightsArray->size());
+ // convert poles to vertices and collect weights
+ std::list<GeomPnt2dPtr> aPoles2D;
+ std::list<double> aWeights;
for (int anIndex = 0; anIndex < aPolesArray->size(); ++anIndex) {
double aWeight = aWeightsArray->value(anIndex);
if (aWeight < 1.e-10)
aWeights.push_back(aWeight);
GeomPnt2dPtr aPole = aPolesArray->pnt(anIndex);
+ aPoles2D.push_back(aPole);
GeomPointPtr aPole3D = aSketch->to3D(aPole->x(), aPole->y());
- aPoles3D.push_back(aPole3D);
aShapes.push_back(GeomAlgoAPI_PointBuilder::vertex(aPole3D));
}
// create result non-periodic B-spline curve
- GeomShapePtr anEdge = GeomAlgoAPI_EdgeBuilder::bspline(aPoles3D, aWeights, false);
+ std::shared_ptr<GeomAPI_BSpline2d> aBSplineCurve;
+ try {
+ aBSplineCurve.reset(new GeomAPI_BSpline2d(aPoles2D, aWeights, PERIODIC));
+ } catch (...) {
+ // cannot build a B-spline curve
+ return AISObjectPtr();
+ }
+ GeomShapePtr anEdge =
+ GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(aSketch->plane(), aBSplineCurve);
if (!anEdge)
return AISObjectPtr();
+ myDegree = aBSplineCurve->degree();
+
aShapes.push_back(anEdge);
GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
void createControlPolygon(FeaturePtr theBSpline, std::list<FeaturePtr>& thePoles);
void constraintsForPoles(const std::list<FeaturePtr>& thePoles);
+ int myDegree;
bool myIsPeriodic;
};
PlaneGCSSolver_AngleWrapper.h
PlaneGCSSolver_BooleanWrapper.h
PlaneGCSSolver_Tools.h
+ PlaneGCSSolver_GeoExtensions.h
)
SET(PLANEGCSSOLVER_SOURCES
PlaneGCSSolver_AngleWrapper.cpp
PlaneGCSSolver_BooleanWrapper.cpp
PlaneGCSSolver_Tools.cpp
+ PlaneGCSSolver_GeoExtensions.cpp
)
SET(PLANEGCSSOLVER_BUILDER_HEADERS
#include <GeomDataAPI_Point2DArray.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <SketchPlugin_BSpline.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_MultiRotation.h>
static EntityWrapperPtr createScalar(const AttributePtr& theAttribute,
PlaneGCSSolver_Storage* theStorage)
{
- AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
- if (!aScalar)
- return EntityWrapperPtr();
+ double aValue = 0.0;
+ AttributeDoublePtr aDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+ if (aDouble)
+ aValue = aDouble->isInitialized() ? aDouble->value() : 0.0;
+ else {
+ AttributeIntegerPtr anInt = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttribute);
+ if (anInt)
+ aValue = anInt->isInitialized() ? anInt->value() : 0.0;
+ else
+ return EntityWrapperPtr();
+ }
ScalarWrapperPtr aWrapper;
// following attributes should be converted from degrees to radians
(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())
+ // Degree of B-spline is not processed by the solver
+ aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr)));
else
aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
- if (aScalar->isInitialized())
- aWrapper->setValue(aScalar->value());
+ aWrapper->setValue(aValue);
return aWrapper;
}
if (!anArray || !anArray->isInitialized())
return EntityWrapperPtr();
+ PlaneGCSSolver_Storage* aStorage = theStorage;
+ // Weights 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())
+ aStorage = 0;
+
int aSize = anArray->size();
GCS::VEC_pD aParameters;
aParameters.reserve(aSize);
for (int index = 0; index < aSize; ++index) {
- double* aParam = createParameter(theStorage);
+ double* aParam = createParameter(aStorage);
*aParam = anArray->value(index);
aParameters.push_back(aParam);
}
//
#include <PlaneGCSSolver_FeatureBuilder.h>
+#include <PlaneGCSSolver_BooleanWrapper.h>
#include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_GeoExtensions.h>
#include <PlaneGCSSolver_PointWrapper.h>
#include <PlaneGCSSolver_PointArrayWrapper.h>
#include <PlaneGCSSolver_ScalarWrapper.h>
#include <PlaneGCSSolver_ScalarArrayWrapper.h>
-#include <PlaneGCSSolver_BooleanWrapper.h>
#include <PlaneGCSSolver_Tools.h>
#include <SketchPlugin_Arc.h>
EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes)
{
- std::shared_ptr<GCS::BSpline> aNewSpline(new GCS::BSpline);
+ std::shared_ptr<GCS::BSplineImpl> aNewSpline(new GCS::BSplineImpl);
aNewSpline->degree = 3;
aNewSpline->periodic = false;
std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(anIt->second);
aNewSpline->weights = anArray->array();
}
+ else if (anAttrID == SketchPlugin_BSpline::DEGREE_ID()) {
+ ScalarWrapperPtr aScalar =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+ aNewSpline->degree = (int)aScalar->value();
+ }
}
return EdgeWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewSpline));
}
else if (theOwnerName == SketchPlugin_BSpline::ID()) {
return theAttrName == SketchPlugin_BSpline::POLES_ID() ||
- theAttrName == SketchPlugin_BSpline::WEIGHTS_ID();
+ theAttrName == SketchPlugin_BSpline::WEIGHTS_ID() ||
+ theAttrName == SketchPlugin_BSpline::DEGREE_ID();
}
// suppose that all remaining features are points
--- /dev/null
+// 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 <PlaneGCSSolver_GeoExtensions.h>
+
+#include <GeomAPI_BSpline2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
+#include <cmath>
+
+namespace GCS
+{
+
+DeriVector2 BSplineImpl::Value(double u, double du, double* derivparam)
+{
+ if (!isCacheValid())
+ rebuildCache();
+
+ std::shared_ptr<GeomAPI_Pnt2d> aValue;
+ std::shared_ptr<GeomAPI_XY> aDeriv;
+ myCurve->D1(u, aValue, aDeriv);
+
+ return DeriVector2(aValue->x(), aValue->y(), aDeriv->x() * du, aDeriv->y() * du);
+}
+
+BSplineImpl* BSplineImpl::Copy()
+{
+ return new BSplineImpl(*this);
+}
+
+
+bool BSplineImpl::isCacheValid() const
+{
+ // curve has to be initialized
+ bool isValid = myCurve.get() && !myCurve->isNull();
+
+ static const double THE_TOLERANCE = 1.e-7;
+ // compare poles
+ isValid = isValid && poles.size() == myCachedPoles.size();
+ std::list<GeomPnt2dPtr>::const_iterator aCachePIt = myCachedPoles.begin();
+ GCS::VEC_P::const_iterator aPolesIt = poles.begin();
+ for (; isValid && aPolesIt != poles.end(); ++aPolesIt, ++aCachePIt) {
+ isValid = isValid && fabs((*aCachePIt)->x() - *aPolesIt->x) < THE_TOLERANCE
+ && fabs((*aCachePIt)->y() - *aPolesIt->y) < THE_TOLERANCE;
+ }
+
+ // compare weights
+ isValid = isValid && weights.size() == myCachedWeights.size();
+ std::list<double>::const_iterator aCacheWIt = myCachedWeights.begin();
+ GCS::VEC_pD::const_iterator aWeightsIt = weights.begin();
+ for (; isValid && aWeightsIt != weights.end(); ++aWeightsIt, ++aCacheWIt)
+ isValid = isValid && fabs(*aCacheWIt - **aWeightsIt) < THE_TOLERANCE;
+
+ return isValid;
+}
+
+void BSplineImpl::rebuildCache()
+{
+ myCachedPoles.clear();
+ myCachedWeights.clear();
+
+ for (GCS::VEC_P::iterator anIt = poles.begin(); anIt != poles.end(); ++anIt)
+ myCachedPoles.push_back(GeomPnt2dPtr(new GeomAPI_Pnt2d(*anIt->x, *anIt->y)));
+ for (GCS::VEC_pD::iterator anIt = weights.begin(); anIt != weights.end(); ++anIt)
+ myCachedWeights.push_back(**anIt);
+
+ myCurve.reset(new GeomAPI_BSpline2d(myCachedPoles, myCachedWeights, degree, periodic));
+}
+
+} // namespace GCS
--- /dev/null
+// 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 PlaneGCSSolver_GeomExtensions_H_
+#define PlaneGCSSolver_GeomExtensions_H_
+
+#include <PlaneGCSSolver_Defs.h>
+
+#include <list>
+#include <memory>
+
+class GeomAPI_BSpline2d;
+class GeomAPI_Pnt2d;
+
+namespace GCS {
+ /// \brife SHAPER's implementation of B-spline curves in PlaneGCS solver
+ class BSplineImpl : public BSpline
+ {
+ public:
+ virtual DeriVector2 Value(double u, double du, double* derivparam = 0);
+
+ virtual BSplineImpl* Copy();
+
+ private:
+ /// Verify the cached curve satisfies to the parameters
+ bool isCacheValid() const;
+ /// Poles or weights are changed, cache curve has to be rebuilt
+ void rebuildCache();
+
+ private:
+ std::shared_ptr<GeomAPI_BSpline2d> myCurve; /// cached B-spline curve
+ std::list<std::shared_ptr<GeomAPI_Pnt2d> > myCachedPoles; /// cached B-spline poles
+ std::list<double> myCachedWeights; /// cached B-spline weights
+ };
+}
+
+#endif
void PlaneGCSSolver_Storage::removeParameters(const GCS::SET_pD& theParams)
{
mySketchSolver->removeParameters(theParams);
+ for (GCS::SET_pD::iterator it = theParams.begin(); it != theParams.end(); ++it)
+ delete *it;
}
// indicates attribute containing in the external feature
static ConstraintWrapperPtr
createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue);
static ConstraintWrapperPtr
createConstraintPointsCollinear(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc);
static GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse);
static GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc);
+static GCS::SET_pD bsplineParameters(const EdgeWrapperPtr& theEdge);
static double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2);
aResult = createConstraintCoincidence(aPoint1, aPoint2);
break;
case CONSTRAINT_PT_ON_CURVE:
- aResult = anEntity1 ? createConstraintPointOnEntity(theType, aPoint1, anEntity1):
- createConstraintPointsCollinear(aPoint1, aPoint2, GCS_POINT_WRAPPER(theEntity1));
+ aResult = anEntity1 ?
+ createConstraintPointOnEntity(theType, aPoint1, anEntity1, GCS_SCALAR_WRAPPER(theValue)) :
+ createConstraintPointsCollinear(aPoint1, aPoint2, GCS_POINT_WRAPPER(theEntity1));
break;
case CONSTRAINT_MIDDLE_POINT:
aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1), aPoint2);
return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
case ENTITY_ELLIPTIC_ARC:
return ellipticArcParameters(GCS_EDGE_WRAPPER(theEntity));
+ case ENTITY_BSPLINE:
+ return bsplineParameters(GCS_EDGE_WRAPPER(theEntity));
default: break;
}
return GCS::SET_pD();
ConstraintWrapperPtr createConstraintPointOnEntity(
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue)
{
GCSConstraintPtr aNewConstr;
new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
break;
}
+ case ENTITY_BSPLINE: {
+ std::list<GCSConstraintPtr> aConstraints;
+ aConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
+ *thePoint->point(), thePoint->point()->x, *theEntity->entity(), theValue->scalar())));
+ aConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
+ *thePoint->point(), thePoint->point()->y, *theEntity->entity(), theValue->scalar())));
+ return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aConstraints, theType));
+ }
default:
return ConstraintWrapperPtr();
}
return aParams;
}
+GCS::SET_pD bsplineParameters(const EdgeWrapperPtr& theEdge)
+{
+ GCS::SET_pD aParams;
+
+ std::shared_ptr<GCS::BSpline> aBSpline =
+ std::dynamic_pointer_cast<GCS::BSpline>(theEdge->entity());
+
+ for (GCS::VEC_P::iterator it = aBSpline->poles.begin(); it != aBSpline->poles.end(); ++it) {
+ aParams.insert(it->x);
+ aParams.insert(it->y);
+ }
+ for (GCS::VEC_pD::iterator it = aBSpline->weights.begin(); it != aBSpline->weights.end(); ++it)
+ aParams.insert(*it);
+
+ return aParams;
+}
+
double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2)
{
double x = *thePnt1.x - *thePnt2.x;
#include <SketchSolver_ConstraintCoincidence.h>
#include <SketchSolver_Error.h>
#include <PlaneGCSSolver_PointArrayWrapper.h>
+#include <PlaneGCSSolver_Storage.h>
#include <PlaneGCSSolver_Tools.h>
#include <PlaneGCSSolver_UpdateCoincidence.h>
mySolverConstraint = PlaneGCSSolver_Tools::createConstraint(
myBaseConstraint, getType(),
- aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
+ myAuxValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
myStorage->notify(myBaseConstraint);
myInSolver = false;
myFeatureExtremities[0] = EntityWrapperPtr();
myFeatureExtremities[1] = EntityWrapperPtr();
+ if (myAuxValue) {
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+ GCS::SET_pD aParams;
+ aParams.insert(myAuxValue->scalar());
+ aStorage->removeParameters(aParams);
+ }
return SketchSolver_Constraint::remove();
}
theAttributes, myFeatureExtremities);
} else if (theAttributes[2]) {
myType = CONSTRAINT_PT_ON_CURVE;
- // obtain extremity points of the coincident feature for further checking of multi-coincidence
- getCoincidentFeatureExtremities(myBaseConstraint, myStorage, myFeatureExtremities);
+ // point-on-bspline requires additional parameter
+ if (theAttributes[2]->type() == ENTITY_BSPLINE) {
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+ myAuxValue.reset(new PlaneGCSSolver_ScalarWrapper(aStorage->createParameter()));
+ }
+ else {
+ // obtain extremity points of the coincident feature for further checking of multi-coincidence
+ getCoincidentFeatureExtremities(myBaseConstraint, myStorage, myFeatureExtremities);
+ }
} else
myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
protected:
bool myInSolver; ///< shows the constraint is added to the solver
EntityWrapperPtr myFeatureExtremities[2]; ///< extremities of a feature, a point is coincident to
+ ScalarWrapperPtr myAuxValue; ///< parameter on B-spline curve
};
#endif