SET(PROJECT_HEADERS
GeomAPI.h
+ GeomAPI_BSpline.h
GeomAPI_BSpline2d.h
GeomAPI_Circ.h
GeomAPI_Circ2d.h
)
SET(PROJECT_SOURCES
+ GeomAPI_BSpline.cpp
GeomAPI_BSpline2d.cpp
GeomAPI_Circ.cpp
GeomAPI_Circ2d.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_BSpline.h>
+#include <GeomAPI_Pnt.h>
+
+#include <Geom_BSplineCurve.hxx>
+
+#define MY_BSPLINE (*(implPtr<Handle_Geom_BSplineCurve>()))
+
+GeomAPI_BSpline::GeomAPI_BSpline(const GeomCurvePtr& theCurve)
+{
+ GeomCurvePtr anUntrimmedCurve = theCurve->basisCurve();
+ Handle(Geom_Curve) aCurve = anUntrimmedCurve->impl<Handle(Geom_Curve)>();
+ Handle(Geom_BSplineCurve) aBSpl = Handle(Geom_BSplineCurve)::DownCast(aCurve);
+ if (aBSpl.IsNull())
+ throw Standard_ConstructionError("GeomAPI_BSpline: Curve is not a B-spline");
+ setImpl(new Handle_Geom_BSplineCurve(aBSpl));
+}
+
+int GeomAPI_BSpline::degree() const
+{
+ return MY_BSPLINE->Degree();
+}
+
+std::list<GeomPointPtr> GeomAPI_BSpline::poles() const
+{
+ const TColgp_Array1OfPnt& aBSplPoles = MY_BSPLINE->Poles();
+
+ std::list<GeomPointPtr> aPoles;
+ for (int anIndex = aBSplPoles.Lower(); anIndex <= aBSplPoles.Upper(); ++anIndex) {
+ const gp_Pnt& aPoint = aBSplPoles.Value(anIndex);
+ aPoles.push_back(GeomPointPtr(new GeomAPI_Pnt(aPoint.X(), aPoint.Y(), aPoint.Z())));
+ }
+ return aPoles;
+}
+
+std::list<double> GeomAPI_BSpline::weights() const
+{
+ std::list<double> aWeights;
+ const TColStd_Array1OfReal* aBSplWeights = MY_BSPLINE->Weights();
+ if (aBSplWeights)
+ aWeights.assign(aBSplWeights->begin(), aBSplWeights->end());
+ return aWeights;
+}
+
+std::list<double> GeomAPI_BSpline::knots() const
+{
+ const TColStd_Array1OfReal& aBSplKnots = MY_BSPLINE->Knots();
+ return std::list<double>(aBSplKnots.begin(), aBSplKnots.end());
+}
+
+std::list<int> GeomAPI_BSpline::mults() const
+{
+ const TColStd_Array1OfInteger& aBSplMults = MY_BSPLINE->Multiplicities();
+ return std::list<int>(aBSplMults.begin(), aBSplMults.end());
+}
--- /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_BSpline_H_
+#define GeomAPI_BSpline_H_
+
+#include <GeomAPI_Interface.h>
+#include <GeomAPI_Curve.h>
+
+#include <list>
+#include <memory>
+
+class GeomAPI_Pnt;
+
+/**\class GeomAPI_BSpline
+ * \ingroup DataModel
+ * \brief B-spline in 3D
+ */
+class GeomAPI_BSpline : public GeomAPI_Interface
+{
+public:
+ /// Creation of B-spline defined by a curve
+ GEOMAPI_EXPORT GeomAPI_BSpline(const GeomCurvePtr& theCurve);
+
+ /// Degree of B-spline curve
+ GEOMAPI_EXPORT int degree() const;
+
+ /// Poles of B-spline curve
+ GEOMAPI_EXPORT std::list<std::shared_ptr<GeomAPI_Pnt> > poles() const;
+
+ /// Weights of B-spline poles
+ GEOMAPI_EXPORT std::list<double> weights() const;
+
+ /// Knots of B-spline curve
+ GEOMAPI_EXPORT std::list<double> knots() const;
+
+ /// Multiplicities of B-spline knots
+ GEOMAPI_EXPORT std::list<int> mults() const;
+};
+
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_BSpline> GeomBSplinePtr;
+
+#endif
static Handle_Geom2d_BSplineCurve* newBSpline2d(
const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
const std::list<double>& theWeights,
+ const std::list<double>& theKnots,
+ const std::list<int>& theMults,
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);
+ TColStd_Array1OfReal aKnots(1, (int)theKnots.size());
+ TColStd_Array1OfInteger aMults(1, (int)theMults.size());
int anIndex = 1;
for (std::list<GeomPnt2dPtr>::const_iterator aPIt = thePoles.begin();
aWIt != theWeights.end(); ++aWIt, ++anIndex)
aWeights.SetValue(anIndex, *aWIt);
anIndex = 1;
+ for (std::list<double>::const_iterator aKIt = theKnots.begin();
+ aKIt != theKnots.end(); ++aKIt, ++anIndex)
+ aKnots.SetValue(anIndex, *aKIt);
+ anIndex = 1;
+ for (std::list<int>::const_iterator aMIt = theMults.begin();
+ aMIt != theMults.end(); ++aMIt, ++anIndex)
+ aMults.SetValue(anIndex, *aMIt);
+
+ 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 int theDegree,
+ const bool thePeriodic)
+{
+ int aNbKnots = (int)thePoles.size() - theDegree + 1;
+ if (aNbKnots < 2)
+ return new Handle_Geom2d_BSplineCurve();
+
static const double aStartParam = 0.0;
static const double aEndParam = 1.0;
double aStep = aEndParam / (aNbKnots - 1);
+ int anIndex = 1;
+ std::list<double> aKnots;
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);
+ aKnots.push_back(aKnot);
+ aKnots.push_back(aEndParam);
- Handle(Geom2d_BSplineCurve) aCurve =
- new Geom2d_BSplineCurve(aPoles, aWeights, aKnots, aMults, theDegree, thePeriodic);
- return new Handle_Geom2d_BSplineCurve(aCurve);
+ std::list<int> aMults(aNbKnots - 2, 1);
+ aMults.push_front(theDegree + 1);
+ aMults.push_back(theDegree + 1);
+
+ return newBSpline2d(thePoles, theWeights, aKnots, aMults, theDegree, thePeriodic);
}
static Handle_Geom2d_BSplineCurve* newBSpline2d(
throw Standard_ConstructionError("GeomAPI_BSpline2d: Impossible to create B-spline curve");
}
-GeomAPI_BSpline2d::GeomAPI_BSpline2d(const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+GeomAPI_BSpline2d::GeomAPI_BSpline2d(const int theDegree,
+ const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
const std::list<double>& theWeights,
- const int theDegree,
+ const std::list<double>& theKnots,
+ const std::list<int>& theMults,
const bool thePeriodic)
- : GeomAPI_Interface(newBSpline2d(thePoles, theWeights, theDegree, thePeriodic))
+ : GeomAPI_Interface(newBSpline2d(thePoles, theWeights, theKnots, theMults,
+ theDegree, thePeriodic))
{
if (isNull())
throw Standard_ConstructionError("GeomAPI_BSpline2d: Impossible to create B-spline curve");
return MY_BSPLINE->Degree();
}
+std::list<double> GeomAPI_BSpline2d::knots() const
+{
+ const TColStd_Array1OfReal& aBSplKnots = MY_BSPLINE->Knots();
+ return std::list<double>(aBSplKnots.begin(), aBSplKnots.end());
+}
+
+std::list<int> GeomAPI_BSpline2d::mults() const
+{
+ const TColStd_Array1OfInteger& aBSplMults = MY_BSPLINE->Multiplicities();
+ return std::list<int>(aBSplMults.begin(), aBSplMults.end());
+}
+
void GeomAPI_BSpline2d::D0(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
{
gp_Pnt2d aPnt;
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,
+ GEOMAPI_EXPORT GeomAPI_BSpline2d(const int theDegree,
+ const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
const std::list<double>& theWeights,
- const int theDegree,
+ const std::list<double>& theKnots = std::list<double>(),
+ const std::list<int>& theMults = std::list<int>(),
const bool thePeriodic = false);
/// Returns true if curve is not initialized
/// Returns degree of the curve
GEOMAPI_EXPORT int degree() const;
+ /// Knots of the curve
+ GEOMAPI_EXPORT std::list<double> knots() const;
+
+ /// Multiplicities of the knots
+ GEOMAPI_EXPORT std::list<int> mults() 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);
#include <GeomAlgoAPI_EdgeBuilder.h>
#include <GeomAPI_Ax2.h>
+#include <GeomAPI_Ax3.h>
#include <GeomAPI_BSpline2d.h>
#include <GeomAPI_Ellipse.h>
-#include <GeomAPI_Pln.h>
#include <GeomAPI_Pnt2d.h>
#include <gp_Pln.hxx>
}
GeomEdgePtr GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(
- const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane,
const std::list<GeomPnt2dPtr>& thePoles,
const std::list<double>& theWeights,
+ const std::list<double>& theKnots,
+ const std::list<int>& theMults,
+ const int theDegree,
const bool thePeriodic)
{
std::shared_ptr<GeomAPI_BSpline2d> aBSplineCurve(
- new GeomAPI_BSpline2d(thePoles, theWeights, thePeriodic));
+ new GeomAPI_BSpline2d(theDegree, thePoles, theWeights, theKnots, theMults, thePeriodic));
return bsplineOnPlane(thePlane, aBSplineCurve);
}
GeomEdgePtr GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(
- const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane,
const std::shared_ptr<GeomAPI_BSpline2d>& theCurve)
{
- Handle(Geom_Curve) aCurve3D = GeomLib::To3d(thePlane->impl<gp_Pln>().Position().Ax2(),
+ Handle(Geom_Curve) aCurve3D = GeomLib::To3d(thePlane->impl<gp_Ax3>().Ax2(),
theCurve->impl<Handle_Geom2d_BSplineCurve>());
BRepBuilderAPI_MakeEdge anEdgeBuilder(aCurve3D);
#include <memory>
#include <vector>
+class GeomAPI_Ax3;
class GeomAPI_BSpline2d;
/**\class GeomAlgoAPI_EdgeBuilder
const std::shared_ptr<GeomAPI_Pnt>& theEnd);
/// Creates planar B-spline edge
- static GeomEdgePtr bsplineOnPlane(const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ static GeomEdgePtr bsplineOnPlane(const std::shared_ptr<GeomAPI_Ax3>& thePlane,
const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
const std::list<double>& theWeights,
+ const std::list<double>& theKnots,
+ const std::list<int>& theMults,
+ const int theDegree,
const bool thePeriodic);
/// Creates planar B-spline edge
- static GeomEdgePtr bsplineOnPlane(const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ static GeomEdgePtr bsplineOnPlane(const std::shared_ptr<GeomAPI_Ax3>& thePlane,
const std::shared_ptr<GeomAPI_BSpline2d>& theCurve);
};
#include <GeomAlgoAPI_EdgeBuilder.h>
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_Edge.h>
-////#include <GeomAPI_Ellipse.h>
-////#include <GeomAPI_Ellipse2d.h>
#include <GeomAPI_Pnt2d.h>
-////#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2DArray.h>
#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeIntArray.h>
#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
-////#include <cmath>
-////
-////static const double tolerance = 1e-7;
-////static const double paramTolerance = 1.e-4;
-////static const double PI = 3.141592653589793238463;
-
SketchPlugin_BSpline::SketchPlugin_BSpline()
: SketchPlugin_SketchEntity()
{
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());
AttributePoint2DArrayPtr aPolesArray =
std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(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<GeomPnt2dPtr> aPoles2D;
std::list<double> aWeights;
for (int anIndex = 0; anIndex < aWeightsArray->size(); ++anIndex)
aWeights.push_back(aWeightsArray->value(anIndex));
+ // collect knots
+ std::list<double> aKnots;
+ for (int anIndex = 0; anIndex < aKnotsArray->size(); ++anIndex)
+ aKnots.push_back(aKnotsArray->value(anIndex));
+ // collect multiplicities
+ std::list<int> 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->plane(), aPoles2D, aWeights, false);
+ GeomShapePtr anEdge = GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(aSketch->coordinatePlane(),
+ aPoles2D, aWeights, aKnots, aMults, aDegreeAttr->value(), false);
ResultConstructionPtr aResult = document()->createConstruction(data(), 0);
aResult->setShape(anEdge);
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()
{
for (int index = 0; index < aSize; ++index)
aWeights->setValue(index, aWeightsMacro->value(index));
+ AttributeDoubleArrayPtr aKnots =
+ aBSpline->data()->realArray(SketchPlugin_BSpline::KNOTS_ID());
+ aSize = (int)myKnots.size();
+ aKnots->setSize(aSize);
+ std::list<double>::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());
+ aSize = (int)myMultiplicities.size();
+ aMults->setSize(aSize);
+ std::list<int>::iterator aMIt = myMultiplicities.begin();
+ for (int index = 0; index < aSize; ++index, ++aMIt)
+ aMults->setValue(index, *aMIt);
+
aBSpline->boolean(SketchPlugin_BSpline::AUXILIARY_ID())->setValue(
boolean(AUXILIARY_ID())->value());
return AISObjectPtr();
}
GeomShapePtr anEdge =
- GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(aSketch->plane(), aBSplineCurve);
+ GeomAlgoAPI_EdgeBuilder::bsplineOnPlane(aSketch->coordinatePlane(), aBSplineCurve);
if (!anEdge)
return AISObjectPtr();
+ // store transient parameters of B-spline curve
myDegree = aBSplineCurve->degree();
+ myKnots = aBSplineCurve->knots();
+ myMultiplicities = aBSplineCurve->mults();
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);
+ std::list<double> myKnots;
+ std::list<int> myMultiplicities;
int myDegree;
bool myIsPeriodic;
};
#include <SketchPlugin_Projection.h>
#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_BSpline.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_EllipticArc.h>
#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
#include <Events_Loop.h>
+#include <GeomAPI_BSpline.h>
#include <GeomAPI_Circ.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Ellipse.h>
#include <GeomAlgoAPI_EdgeBuilder.h>
#include <GeomAlgoAPI_Projection.h>
#include <GeomDataAPI_Point2D.h>
+#include <GeomDataAPI_Point2DArray.h>
#include <cmath>
return aProj;
}
+static const std::set<std::string>& BSPLINE_PROJECTION()
+{
+ static std::set<std::string> aProj;
+ if (aProj.empty())
+ aProj.insert(SketchPlugin_BSpline::ID());
+ return aProj;
+}
+
static const std::set<std::string>& possibleProjectionTypes(GeomEdgePtr theEdge,
GeomVertexPtr theVertex)
else
return ARC_PROJECTION();
}
+ else
+ return BSPLINE_PROJECTION();
}
static const std::set<std::string> DUMMY;
return DUMMY;
// if the type of feature differs with already selected, remove it and create once again
bool isRebuild = rebuildProjectedFeature(aProjection, aProjType);
- std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
-
ResultConstructionPtr aResult =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(lastResult());
if (!isRebuild && aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) {
keepCurrentFeature();
- if (aVertex) {
- std::shared_ptr<GeomAPI_Pnt> aPrjPnt = aSketchPlane->project(aVertex->point());
- std::shared_ptr<GeomAPI_Pnt2d> aPntInSketch = sketch()->to2D(aPrjPnt);
-
- rebuildProjectedFeature(aProjection, POINT_PROJECTION(), SketchPlugin_Point::ID());
+ bool isProjected = false;
+ if (aVertex)
+ isProjected = projectPoint(aProjection, aVertex->point());
+ else
+ isProjected = projectEdge(aProjection, anEdge);
- // update coordinates of projection
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Point::COORD_ID()))->setValue(aPntInSketch);
- }
- else if (anEdge->isLine()) {
- std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
- std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
-
- std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
- std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
- if (aFirstInSketch->distance(aLastInSketch) < tolerance)
- return; // line is semi-orthogonal to the sketch plane
-
- rebuildProjectedFeature(aProjection, LINE_PROJECTION(), SketchPlugin_Line::ID());
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Line::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Line::END_ID()));
- aStartPnt->setValue(aFirstInSketch);
- aEndPnt->setValue(aLastInSketch);
- }
- else if (anEdge->isCircle() || anEdge->isArc() || anEdge->isEllipse()) {
- GeomAlgoAPI_Projection aProjAlgo(aSketchPlane);
- GeomCurvePtr aProjectedCurve = aProjAlgo.project(anEdge);
-
- if (aProjectedCurve->isCircle()) {
- GeomAPI_Circ aCircle(aProjectedCurve);
- GeomPointPtr aCenter = aSketchPlane->project(aCircle.center());
- GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
-
- if (aProjectedCurve->isTrimmed()) {
- // ARC is a projection
- rebuildProjectedFeature(aProjection, ARC_PROJECTION(), SketchPlugin_Arc::ID());
-
- GeomPointPtr aFirst = aProjectedCurve->getPoint(aProjectedCurve->startParam());
- GeomPointPtr aLast = aProjectedCurve->getPoint(aProjectedCurve->endParam());
- GeomPnt2dPtr aFirstInSketch = sketch()->to2D(aSketchPlane->project(aFirst));
- GeomPnt2dPtr aLastInSketch = sketch()->to2D(aSketchPlane->project(aLast));
-
- double aNormalsDot = aCircle.normal()->dot(aSketchPlane->direction());
- if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
- return; // arc is not in the plane, parallel to the sketch plane
-
- bool isInversed = aNormalsDot < 0.;
-
- bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true);
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aStartPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Arc::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Arc::END_ID()));
- aStartPnt->setValue(aFirstInSketch);
- aEndPnt->setValue(aLastInSketch);
- aCenterPnt->setValue(aCenterInSketch);
- aProjection->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(isInversed);
-
- aProjection->data()->blockSendAttributeUpdated(aWasBlocked);
- }
- else {
- // CIRCLE is a projection
- rebuildProjectedFeature(aProjection, CIRCLE_ELLIPSE_PROJECTION(),
- SketchPlugin_Circle::ID());
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
- aCenterPnt->setValue(aCenterInSketch);
- aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircle.radius());
- }
- }
- else if (aProjectedCurve->isEllipse()) {
- GeomAPI_Ellipse anEllipse(aProjectedCurve);
- GeomPointPtr aCenter = aSketchPlane->project(anEllipse.center());
- GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
- GeomPointPtr aFocus = aSketchPlane->project(anEllipse.firstFocus());
- GeomPnt2dPtr aFocusInSketch = sketch()->to2D(aFocus);
-
- if (aProjectedCurve->isTrimmed()) {
- // ELLIPTIC ARC is a projection
- rebuildProjectedFeature(aProjection, ARC_PROJECTION(), SketchPlugin_EllipticArc::ID());
-
- GeomPointPtr aFirst = aProjectedCurve->getPoint(aProjectedCurve->startParam());
- GeomPointPtr aLast = aProjectedCurve->getPoint(aProjectedCurve->endParam());
- GeomPnt2dPtr aFirstInSketch = sketch()->to2D(aSketchPlane->project(aFirst));
- GeomPnt2dPtr aLastInSketch = sketch()->to2D(aSketchPlane->project(aLast));
-
- double aNormalsDot = anEllipse.normal()->dot(aSketchPlane->direction());
- if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
- return; // arc is not in the plane, parallel to the sketch plane
-
- bool isInversed = aNormalsDot < 0.;
-
- bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true);
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aFocusPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aStartPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
- aStartPnt->setValue(aFirstInSketch);
- aEndPnt->setValue(aLastInSketch);
- aCenterPnt->setValue(aCenterInSketch);
- aFocusPnt->setValue(aFocusInSketch);
- aProjection->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(isInversed);
-
- aProjection->data()->blockSendAttributeUpdated(aWasBlocked);
- }
- else {
- // ELLIPSE is a projection
- rebuildProjectedFeature(aProjection, CIRCLE_ELLIPSE_PROJECTION(),
- SketchPlugin_Ellipse::ID());
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Ellipse::CENTER_ID()));
- aCenterPnt->setValue(aCenterInSketch);
- std::shared_ptr<GeomDataAPI_Point2D> aFocusPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
- aFocusPnt->setValue(aFocusInSketch);
- aProjection->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(
- anEllipse.minorRadius());
- }
- }
- else
- return;
- } else
- return;
+ if (!isProjected)
+ return; // projection is not computed, stop processing
aProjection->boolean(COPY_ID())->setValue(true);
aProjection->execute();
theProjection = sketch()->addFeature(theRequestedFeature);
return isRebuild;
}
+
+bool SketchPlugin_Projection::projectPoint(FeaturePtr& theProjection, const GeomPointPtr& thePoint)
+{
+ std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
+
+ std::shared_ptr<GeomAPI_Pnt> aPrjPnt = aSketchPlane->project(thePoint);
+ std::shared_ptr<GeomAPI_Pnt2d> aPntInSketch = sketch()->to2D(aPrjPnt);
+
+ rebuildProjectedFeature(theProjection, POINT_PROJECTION(), SketchPlugin_Point::ID());
+
+ // update coordinates of projection
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Point::COORD_ID()))->setValue(aPntInSketch);
+ return true;
+}
+
+bool SketchPlugin_Projection::projectSegment(FeaturePtr& theProjection, const GeomEdgePtr& theEdge)
+{
+ std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
+
+ std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(theEdge->firstPoint());
+ std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(theEdge->lastPoint());
+
+ std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
+ std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
+ if (aFirstInSketch->distance(aLastInSketch) < tolerance)
+ return false; // line is semi-orthogonal to the sketch plane
+
+ rebuildProjectedFeature(theProjection, LINE_PROJECTION(), SketchPlugin_Line::ID());
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Line::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Line::END_ID()));
+ aStartPnt->setValue(aFirstInSketch);
+ aEndPnt->setValue(aLastInSketch);
+
+ return true;
+}
+
+bool SketchPlugin_Projection::projectEdge(FeaturePtr& theProjection, const GeomEdgePtr& theEdge)
+{
+ if (theEdge->isLine())
+ return projectSegment(theProjection, theEdge);
+
+ std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
+
+ GeomAlgoAPI_Projection aProjAlgo(aSketchPlane);
+ GeomCurvePtr aProjectedCurve = aProjAlgo.project(theEdge);
+
+ bool isOk = false;
+ if (aProjectedCurve->isCircle()) {
+ if (aProjectedCurve->isTrimmed()) {
+ // ARC is a projection
+ isOk = fillArc(theProjection, aProjectedCurve, aSketchPlane);
+ }
+ else {
+ // CIRCLE is a projection
+ isOk = fillCircle(theProjection, aProjectedCurve, aSketchPlane);
+ }
+ }
+ else if (aProjectedCurve->isEllipse()) {
+ if (aProjectedCurve->isTrimmed()) {
+ // ELLIPTIC ARC is a projection
+ isOk = fillEllipticArc(theProjection, aProjectedCurve, aSketchPlane);
+ }
+ else {
+ // ELLIPSE is a projection
+ isOk = fillEllipse(theProjection, aProjectedCurve, aSketchPlane);
+ }
+ }
+ else
+ isOk = fillBSpline(theProjection, aProjectedCurve, aSketchPlane);
+
+ return isOk;
+}
+
+bool SketchPlugin_Projection::fillArc(FeaturePtr& theProjection,
+ const GeomCurvePtr& theArc,
+ const GeomPlanePtr& thePlane)
+{
+ rebuildProjectedFeature(theProjection, ARC_PROJECTION(), SketchPlugin_Arc::ID());
+
+ GeomAPI_Circ aCircle(theArc);
+
+ double aNormalsDot = aCircle.normal()->dot(thePlane->direction());
+ if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
+ return false; // arc is not in the plane, parallel to the sketch plane
+
+ bool isInversed = aNormalsDot < 0.;
+
+ GeomPointPtr aCenter = thePlane->project(aCircle.center());
+ GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
+
+ GeomPointPtr aFirst = theArc->getPoint(theArc->startParam());
+ GeomPnt2dPtr aFirstInSketch = sketch()->to2D(thePlane->project(aFirst));
+
+ GeomPointPtr aLast = theArc->getPoint(theArc->endParam());
+ GeomPnt2dPtr aLastInSketch = sketch()->to2D(thePlane->project(aLast));
+
+ bool aWasBlocked = theProjection->data()->blockSendAttributeUpdated(true);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Arc::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Arc::END_ID()));
+ aStartPnt->setValue(aFirstInSketch);
+ aEndPnt->setValue(aLastInSketch);
+ aCenterPnt->setValue(aCenterInSketch);
+ theProjection->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(isInversed);
+
+ theProjection->data()->blockSendAttributeUpdated(aWasBlocked);
+ return true;
+}
+
+bool SketchPlugin_Projection::fillCircle(FeaturePtr& theProjection,
+ const GeomCurvePtr& theCircle,
+ const GeomPlanePtr& thePlane)
+{
+ rebuildProjectedFeature(theProjection, CIRCLE_ELLIPSE_PROJECTION(), SketchPlugin_Circle::ID());
+
+ GeomAPI_Circ aCircle(theCircle);
+ GeomPointPtr aCenter = thePlane->project(aCircle.center());
+ GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
+ aCenterPnt->setValue(aCenterInSketch);
+ theProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircle.radius());
+ return true;
+}
+
+bool SketchPlugin_Projection::fillEllipse(FeaturePtr& theProjection,
+ const GeomCurvePtr& theEllipse,
+ const GeomPlanePtr& thePlane)
+{
+ rebuildProjectedFeature(theProjection, CIRCLE_ELLIPSE_PROJECTION(), SketchPlugin_Ellipse::ID());
+
+ GeomAPI_Ellipse anEllipse(theEllipse);
+ GeomPointPtr aCenter = thePlane->project(anEllipse.center());
+ GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
+ GeomPointPtr aFocus = thePlane->project(anEllipse.firstFocus());
+ GeomPnt2dPtr aFocusInSketch = sketch()->to2D(aFocus);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Ellipse::CENTER_ID()));
+ aCenterPnt->setValue(aCenterInSketch);
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
+ aFocusPnt->setValue(aFocusInSketch);
+ theProjection->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(anEllipse.minorRadius());
+ return true;
+}
+
+bool SketchPlugin_Projection::fillEllipticArc(FeaturePtr& theProjection,
+ const GeomCurvePtr& theEllipticArc,
+ const GeomPlanePtr& thePlane)
+{
+ rebuildProjectedFeature(theProjection, ARC_PROJECTION(), SketchPlugin_EllipticArc::ID());
+
+ GeomAPI_Ellipse anEllipse(theEllipticArc);
+
+ double aNormalsDot = anEllipse.normal()->dot(thePlane->direction());
+ if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
+ return false; // arc is not in the plane, parallel to the sketch plane
+
+ bool isInversed = aNormalsDot < 0.;
+
+ GeomPointPtr aCenter = thePlane->project(anEllipse.center());
+ GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
+ GeomPointPtr aFocus = thePlane->project(anEllipse.firstFocus());
+ GeomPnt2dPtr aFocusInSketch = sketch()->to2D(aFocus);
+
+ GeomPointPtr aFirst = theEllipticArc->getPoint(theEllipticArc->startParam());
+ GeomPnt2dPtr aFirstInSketch = sketch()->to2D(thePlane->project(aFirst));
+ GeomPointPtr aLast = theEllipticArc->getPoint(theEllipticArc->endParam());
+ GeomPnt2dPtr aLastInSketch = sketch()->to2D(thePlane->project(aLast));
+
+ bool aWasBlocked = theProjection->data()->blockSendAttributeUpdated(true);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theProjection->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
+ aStartPnt->setValue(aFirstInSketch);
+ aEndPnt->setValue(aLastInSketch);
+ aCenterPnt->setValue(aCenterInSketch);
+ aFocusPnt->setValue(aFocusInSketch);
+ theProjection->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(isInversed);
+
+ theProjection->data()->blockSendAttributeUpdated(aWasBlocked);
+ return true;
+}
+
+bool SketchPlugin_Projection::fillBSpline(FeaturePtr& theProjection,
+ const GeomCurvePtr& theCurve,
+ const GeomPlanePtr& thePlane)
+{
+ rebuildProjectedFeature(theProjection, BSPLINE_PROJECTION(), SketchPlugin_BSpline::ID());
+
+ GeomAPI_BSpline aBSpline(theCurve);
+
+ theProjection->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(aBSpline.degree());
+
+ AttributePoint2DArrayPtr aPolesAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
+ theProjection->attribute(SketchPlugin_BSpline::POLES_ID()));
+ std::list<GeomPointPtr> aPoles = aBSpline.poles();
+ aPolesAttr->setSize((int)aPoles.size());
+ std::list<GeomPointPtr>::iterator anIt = aPoles.begin();
+ for (int anIndex = 0; anIt != aPoles.end(); ++anIt, ++anIndex) {
+ GeomPnt2dPtr aPoleInSketch = sketch()->to2D(*anIt);
+ aPolesAttr->setPnt(anIndex, aPoleInSketch);
+ }
+
+ AttributeDoubleArrayPtr aWeightsAttr =
+ theProjection->data()->realArray(SketchPlugin_BSpline::WEIGHTS_ID());
+ std::list<double> aWeights = aBSpline.weights();
+ if (aWeights.empty()) { // rational B-spline
+ int aSize = (int)aPoles.size();
+ aWeightsAttr->setSize(aSize);
+ for (int anIndex = 0; anIndex < aSize; ++anIndex)
+ aWeightsAttr->setValue(anIndex, 1.0);
+ }
+ else { // non-rational B-spline
+ aWeightsAttr->setSize((int)aWeights.size());
+ std::list<double>::iterator anIt = aWeights.begin();
+ for (int anIndex = 0; anIt != aWeights.end(); ++anIt, ++anIndex)
+ aWeightsAttr->setValue(anIndex, *anIt);
+ }
+
+ AttributeDoubleArrayPtr aKnotsAttr =
+ theProjection->data()->realArray(SketchPlugin_BSpline::KNOTS_ID());
+ std::list<double> aKnots = aBSpline.knots();
+ int aSize = (int)aKnots.size();
+ aKnotsAttr->setSize(aSize);
+ std::list<double>::iterator aKIt = aKnots.begin();
+ for (int index = 0; index < aSize; ++index, ++aKIt)
+ aKnotsAttr->setValue(index, *aKIt);
+
+ AttributeIntArrayPtr aMultsAttr =
+ theProjection->data()->intArray(SketchPlugin_BSpline::MULTS_ID());
+ std::list<int> aMultiplicities = aBSpline.mults();
+ aSize = (int)aMultiplicities.size();
+ aMultsAttr->setSize(aSize);
+ std::list<int>::iterator aMIt = aMultiplicities.begin();
+ for (int index = 0; index < aSize; ++index, ++aMIt)
+ aMultsAttr->setValue(index, *aMIt);
+
+ return true;
+}
#include "SketchPlugin_SketchEntity.h"
+class GeomAPI_Curve;
+
/** \class SketchPlugin_Projection
* \ingroup Plugins
* \brief Feature for creation of external feature as a projection onto the sketch plane.
/// \brief Find projection of a feature onto sketch plane
void computeProjection(const std::string& theID);
+ /// \brief Project point to the sketch plane
+ bool projectPoint(FeaturePtr& theProjection, const std::shared_ptr<GeomAPI_Pnt>& thePoint);
+ /// \brief Project segment to the sketch plane
+ bool projectSegment(FeaturePtr& theProjection, const std::shared_ptr<GeomAPI_Edge>& theEdge);
+ /// \brief Project any edge to sketch plane
+ bool projectEdge(FeaturePtr& theProjection, const std::shared_ptr<GeomAPI_Edge>& theEdge);
+
+ /// \brief Fill attributes of the Arc feature
+ bool fillArc(FeaturePtr& theProjection,
+ const std::shared_ptr<GeomAPI_Curve>& theArc,
+ const std::shared_ptr<GeomAPI_Pln>& thePlane);
+ /// \brief Fill attributes of the Circle feature
+ bool fillCircle(FeaturePtr& theProjection,
+ const std::shared_ptr<GeomAPI_Curve>& theCircle,
+ const std::shared_ptr<GeomAPI_Pln>& thePlane);
+ /// \brief Fill attributes of the Ellipse feature
+ bool fillEllipse(FeaturePtr& theProjection,
+ const std::shared_ptr<GeomAPI_Curve>& theEllipse,
+ const std::shared_ptr<GeomAPI_Pln>& thePlane);
+ /// \brief Fill attributes of the EllipticArc feature
+ bool fillEllipticArc(FeaturePtr& theProjection,
+ const std::shared_ptr<GeomAPI_Curve>& theEllipticArc,
+ const std::shared_ptr<GeomAPI_Pln>& thePlane);
+ /// \brief Fill attributes of the B-spline feature
+ bool fillBSpline(FeaturePtr& theProjection,
+ const std::shared_ptr<GeomAPI_Curve>& theCurve,
+ const std::shared_ptr<GeomAPI_Pln>& thePlane);
+
/// \brief Delete already calculated projected feature
/// if the selection of the projection is changed
/// \param[in/out] theProjection projected feature
std::shared_ptr<GeomAPI_Dir> aNormal = aPlane->direction();
std::shared_ptr<GeomAPI_Pnt> anOrigin = aPlane->location();
+ bool aValid = true;
if (anEdge->isLine()) {
std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
std::shared_ptr<GeomAPI_Dir> aLineDir = aLine->direction();
double aDot = fabs(aNormal->dot(aLineDir));
- bool aValid = fabs(aDot - 1.0) >= tolerance * tolerance;
+ aValid = fabs(aDot - 1.0) >= tolerance * tolerance;
if (!aValid)
theError = "Error: Line is orthogonal to the sketch plane.";
- return aValid;
}
else if (anEdge->isCircle() || anEdge->isArc()) {
std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
std::shared_ptr<GeomAPI_Dir> aCircNormal = aCircle->normal();
double aDot = fabs(aNormal->dot(aCircNormal));
- bool aValid = aDot >= tolerance * tolerance;
+ aValid = aDot >= tolerance * tolerance;
if (!aValid)
theError.arg(anEdge->isCircle() ? "Error: Circle is orthogonal to the sketch plane."
: "Error: Arc is orthogonal to the sketch plane.");
- return aValid;
}
else if (anEdge->isEllipse()) {
std::shared_ptr<GeomAPI_Ellipse> anEllipse = anEdge->ellipse();
std::shared_ptr<GeomAPI_Dir> anEllipseNormal = anEllipse->normal();
double aDot = fabs(aNormal->dot(anEllipseNormal));
- bool aValid = fabs(aDot - 1.0) <= tolerance * tolerance;
+ aValid = fabs(aDot - 1.0) <= tolerance * tolerance;
if (!aValid)
theError.arg(anEdge->isClosed() ? "Error: Ellipse is orthogonal to the sketch plane."
: "Error: Elliptic Arc is orthogonal to the sketch plane.");
- return aValid;
}
- theError = "Error: Selected object is not supported for projection.";
- return false;
+ return aValid;
}
static EntityWrapperPtr createScalarArray(const AttributePtr& theAttribute,
PlaneGCSSolver_Storage* theStorage)
{
- AttributeDoubleArrayPtr anArray =
- std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(theAttribute);
- if (!anArray || !anArray->isInitialized())
+ class ArrayAttribute {
+ public:
+ ArrayAttribute(AttributePtr theAttribute)
+ {
+ myDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(theAttribute);
+ myInteger = std::dynamic_pointer_cast<ModelAPI_AttributeIntArray>(theAttribute);
+ }
+
+ bool isInitialized() const
+ {
+ return (myDouble && myDouble->isInitialized()) || (myInteger && myInteger->isInitialized());
+ }
+
+ int size() const
+ {
+ return myDouble.get() ? myDouble->size() : myInteger->size();
+ }
+
+ double value(const int theIndex) const
+ {
+ return myDouble.get() ? myDouble->value(theIndex) : myInteger->value(theIndex);
+ }
+
+ private:
+ AttributeDoubleArrayPtr myDouble;
+ AttributeIntArrayPtr myInteger;
+ } anArray(theAttribute);
+
+ if (!anArray.isInitialized())
return EntityWrapperPtr();
PlaneGCSSolver_Storage* aStorage = theStorage;
- // Weights of B-spline curve are not processed by the solver
+ // 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::WEIGHTS_ID() ||
+ theAttribute->id() == SketchPlugin_BSpline::KNOTS_ID() ||
+ theAttribute->id() == SketchPlugin_BSpline::MULTS_ID()))
aStorage = 0;
- int aSize = anArray->size();
+ int aSize = anArray.size();
GCS::VEC_pD aParameters;
aParameters.reserve(aSize);
for (int index = 0; index < aSize; ++index) {
double* aParam = createParameter(aStorage);
- *aParam = anArray->value(index);
+ *aParam = anArray.value(index);
aParameters.push_back(aParam);
}
aNewSpline->start = aNewSpline->poles.front();
aNewSpline->end = aNewSpline->poles.back();
}
- else if (anAttrID == SketchPlugin_BSpline::WEIGHTS_ID()) {
- ScalarArrayWrapperPtr anArray =
- 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();
}
+ else {
+ ScalarArrayWrapperPtr anArray =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(anIt->second);
+ if (anAttrID == SketchPlugin_BSpline::WEIGHTS_ID())
+ aNewSpline->weights = anArray->array();
+ else if (anAttrID == SketchPlugin_BSpline::KNOTS_ID())
+ aNewSpline->knots = anArray->array();
+ else if (anAttrID == SketchPlugin_BSpline::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)
+ aNewSpline->mult.push_back((int)(**anIt));
+ }
+ }
}
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::KNOTS_ID() ||
+ theAttrName == SketchPlugin_BSpline::MULTS_ID() ||
theAttrName == SketchPlugin_BSpline::DEGREE_ID();
}
{
myCachedPoles.clear();
myCachedWeights.clear();
+ myCachedKnots.clear();
+ myCachedMultiplicities.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);
+ for (GCS::VEC_pD::iterator anIt = knots.begin(); anIt != knots.end(); ++anIt)
+ myCachedKnots.push_back(**anIt);
+ myCachedMultiplicities.assign(mult.begin(), mult.end());
- myCurve.reset(new GeomAPI_BSpline2d(myCachedPoles, myCachedWeights, degree, periodic));
+ myCurve.reset(new GeomAPI_BSpline2d(degree, myCachedPoles, myCachedWeights,
+ myCachedKnots, myCachedMultiplicities, periodic));
}
} // namespace GCS
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
+ std::list<double> myCachedKnots; /// cached B-spline knots
+ std::list<int> myCachedMultiplicities; /// cached B-spline multiplicities
};
}