return ResultPoint;
}
-void CurveCreator_Utils::constructShape( const CurveCreator_ICurve* theCurve,
- TopoDS_Shape& theShape )
+//=======================================================================
+// function : constructBSpline
+// purpose :
+// The algorithm builds the cubic B-spline passing through the points that the
+// tangent vector in each given point P is calculated by the following way:
+// if point P is preceded by a point A and is followed by a point B then
+// the tangent vector is equal to (P - A) / |P - A| + (B - P) / |B - P|;
+// if point P is preceded by a point A but is not followed by any point then
+// the tangent vector is equal to P - A;
+// if point P is followed by a point B but is not preceded by any point then
+// the tangent vector is equal to B - P.
+//=======================================================================
+static bool constructBSpline(
+ const Handle(TColgp_HArray1OfPnt)& thePoints,
+ const Standard_Boolean theIsClosed,
+ Handle(Geom_BSplineCurve)& theBSpline)
{
- BRep_Builder aBuilder;
- TopoDS_Compound aComp;
- aBuilder.MakeCompound( aComp );
- for( int iSection = 0 ; iSection < theCurve->getNbSections() ; iSection++ )
+ const int aPointCount = thePoints->Length();
+ if (aPointCount <= 1)
{
- int theISection = iSection;
+ return false;
+ }
- CurveCreator::SectionType aSectType = theCurve->getSectionType( theISection );
- int aPointSize = theCurve->getNbPoints( theISection );
- if ( aPointSize == 0 )
- continue;
+ // Calculate the tangents.
+ TColgp_Array1OfVec aTangents(1, aPointCount);
+ Handle(TColStd_HArray1OfBoolean) aTangentFlags =
+ new TColStd_HArray1OfBoolean(1, aPointCount);
+ GeomAPI_Interpolate aInterpolator(thePoints, theIsClosed, 0);
+ if (aPointCount == 2)
+ {
+ aTangentFlags->SetValue(1, Standard_False);
+ aTangentFlags->SetValue(2, Standard_False);
+ }
+ else
+ {
+ for (Standard_Integer aPN = 1; aPN <= aPointCount; ++aPN)
+ {
+ gp_Vec aTangent;
+ if (aPN != 1 || theIsClosed)
+ {
+ const Standard_Integer aPN1 = (aPN != 1) ? (aPN - 1) : aPointCount;
+ aTangent = gp_Vec(thePoints->Value(aPN1),
+ thePoints->Value(aPN)).Normalized();
+ }
+ if (aPN < aPointCount || theIsClosed)
+ {
+ const Standard_Integer aPN2 = (aPN != aPointCount) ? (aPN + 1) : 1;
+ const gp_Vec aTangent2 = aTangent +
+ gp_Vec(thePoints->Value(aPN), thePoints->Value(aPN2)).Normalized();
+ if (aTangent2.SquareMagnitude() >= Precision::SquareConfusion())
+ {
+ aTangent = aTangent2.Normalized();
+ }
+ else
+ {
+ aTangent = -aTangent;
+ }
+ }
+ aTangents.SetValue(aPN, aTangent);
+ aTangentFlags->SetValue(aPN, Standard_True);
+ }
+ }
- bool aSectIsClosed = theCurve->isClosed( theISection );
- bool isPolyline = aSectType == CurveCreator::Polyline;
-
- int iPoint = 0;
- gp_Pnt aPrevPoint, aPoint;
- // filters the curve points to skip equal points
- std::vector<gp_Pnt> aPoints;
- CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint );
- aPoints.push_back( aPoint );
- aPrevPoint = aPoint;
- iPoint++;
- for( ; iPoint < aPointSize; iPoint++ ) {
- CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint );
- if ( !isEqualPoints( aPrevPoint, aPoint ) )
- aPoints.push_back( aPoint );
- aPrevPoint = aPoint;
+ // Interpolate.
+ aInterpolator.Load(aTangents, aTangentFlags, Standard_False);
+ aInterpolator.Perform();
+ const bool aResult = (aInterpolator.IsDone() == Standard_True);
+ if (aResult)
+ {
+ theBSpline = aInterpolator.Curve();
+ }
+ return aResult;
+}
+
+//=======================================================================
+// function : constructShape
+// purpose :
+//=======================================================================
+void CurveCreator_Utils::constructShape(
+ const CurveCreator_ICurve* theCurve, TopoDS_Shape& theShape)
+{
+ BRep_Builder aBuilder;
+ TopoDS_Compound aShape;
+ aBuilder.MakeCompound(aShape);
+ const int aSectionCount = theCurve->getNbSections();
+ for (int aSectionI = 0; aSectionI < aSectionCount; ++aSectionI)
+ {
+ const int aTmpPointCount = theCurve->getNbPoints(aSectionI);
+ if (aTmpPointCount == 0)
+ {
+ continue;
}
- int aNbPoints = aPoints.size();
- if ( aNbPoints == 1 ) {
- aPoint = aPoints.front();
- TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex();
- aBuilder.Add( aComp, aVertex );
+ // Get the different points.
+ std::vector<gp_Pnt> aTmpPoints;
+ gp_Pnt aFirstPoint;
+ CurveCreator_UtilsICurve::getPoint(theCurve, aSectionI, 0, aFirstPoint);
+ gp_Pnt aPoint = aFirstPoint;
+ aTmpPoints.push_back(aPoint);
+ for (int aPI = 1; aPI < aTmpPointCount; ++aPI)
+ {
+ gp_Pnt aPoint2;
+ CurveCreator_UtilsICurve::getPoint(theCurve, aSectionI, aPI, aPoint2);
+ if (!isEqualPoints(aPoint, aPoint2))
+ {
+ aPoint = aPoint2;
+ aTmpPoints.push_back(aPoint);
+ }
}
- else if ( aNbPoints > 1 ) {
- Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt(1, aNbPoints);
- TColgp_Array1OfVec aTangents(1, aNbPoints);
- Handle(TColStd_HArray1OfBoolean) aTangentFlags = new TColStd_HArray1OfBoolean(1, aNbPoints);
- gp_Vec aNullVec(0, 0, 0);
-
- TopoDS_Edge aPointEdge;
- TopoDS_Vertex aVertex;
-
- std::vector<gp_Pnt>::const_iterator aPointIt = aPoints.begin(), aPointLast = aPoints.end();
- aPoint = *aPointIt;
-
- int aHIndex = 1;
- aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex();
- aBuilder.Add( aComp, aVertex );
- if ( !isPolyline ) {
- aHCurvePoints->SetValue( aHIndex, aPoint );
- aTangents.SetValue( aHIndex, aNullVec );
- aTangentFlags->SetValue( aHIndex, Standard_False );
- aHIndex++;
+ const bool isClosed = theCurve->isClosed(aSectionI);
+ int aPointCount = aTmpPoints.size();
+ if (isClosed)
+ {
+ while (aPointCount > 1 &&
+ isEqualPoints(aFirstPoint, aTmpPoints[aPointCount - 1]))
+ {
+ --aPointCount;
}
+ }
- aPrevPoint = aPoint;
- aPointIt++;
- for( ; aPointIt != aPointLast; aPointIt++ ) {
- aPoint = *aPointIt;
- aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex();
- aBuilder.Add( aComp, aVertex );
- if ( isPolyline ) {
- TopoDS_Edge aPointEdge = BRepBuilderAPI_MakeEdge( aPrevPoint, aPoint ).Edge();
- aBuilder.Add( aComp, aPointEdge );
- }
- else {
- aHCurvePoints->SetValue( aHIndex, aPoint );
- aTangents.SetValue( aHIndex, aNullVec );
- aTangentFlags->SetValue( aHIndex, Standard_False );
- aHIndex++;
- }
- aPrevPoint = aPoint;
+ // Add the vertices to the shape.
+ Handle(TColgp_HArray1OfPnt) aPoints =
+ new TColgp_HArray1OfPnt(1, aPointCount);
+ for (Standard_Integer aPI = 0; aPI < aPointCount; ++aPI)
+ {
+ aPoints->SetValue(aPI + 1, aTmpPoints[aPI]);
+ aBuilder.Add(aShape, BRepBuilderAPI_MakeVertex(aTmpPoints[aPI]));
+ }
+ if (aPointCount == 1)
+ {
+ continue;
+ }
+
+ // Add the edges to the shape.
+ const bool isPolyline =
+ (theCurve->getSectionType(aSectionI) == CurveCreator::Polyline);
+ if (isPolyline)
+ {
+ for (Standard_Integer aPN = 1; aPN < aPointCount; ++aPN)
+ {
+ aBuilder.Add(aShape, BRepBuilderAPI_MakeEdge(
+ BRepBuilderAPI_MakeVertex(aPoints->Value(aPN)),
+ BRepBuilderAPI_MakeVertex(aPoints->Value(aPN + 1))));
}
- if( aSectIsClosed && ( aNbPoints > 2 ) ) {
- aPoint = aPoints.front();
- aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex();
- aBuilder.Add( aComp, aVertex );
- if ( isPolyline ) {
- aPointEdge = BRepBuilderAPI_MakeEdge( aPrevPoint, aPoint ).Edge();
- aBuilder.Add( aComp, aPointEdge );
- }
+ if (isClosed)
+ {
+ aBuilder.Add(aShape, BRepBuilderAPI_MakeEdge(
+ BRepBuilderAPI_MakeVertex(aPoints->Value(aPointCount)),
+ BRepBuilderAPI_MakeVertex(aPoints->Value(1))));
}
- if( !isPolyline ) {
- // compute BSpline
- Handle(Geom_BSplineCurve) aBSplineCurve;
- GeomAPI_Interpolate aGBC(aHCurvePoints, aSectIsClosed, gp::Resolution());
- // correct the spline degree to be as 3 for non-periodic spline if number of points
- // less than 3. It is need to have a knot in each spline point. This knots are used
- // to found a neighbour points when a new point is inserted between two existing.
- if (!aSectIsClosed ) {
- if (aHCurvePoints->Length() == 3)
- aGBC.Load(aTangents, aTangentFlags);
- }
-
- aGBC.Perform();
- if ( aGBC.IsDone() )
- aBSplineCurve = aGBC.Curve();
- TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSplineCurve ).Edge();
- TopoDS_Wire aWire = BRepBuilderAPI_MakeWire( anEdge ).Wire();
- aBuilder.Add( aComp, aWire );
+ }
+ else
+ {
+ Handle(Geom_BSplineCurve) aBSpline;
+ if (constructBSpline(aPoints, isClosed, aBSpline))
+ {
+ aBuilder.Add(aShape,
+ BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(aBSpline)));
}
}
}
- theShape = aComp;
+ theShape = aShape;
}
/**
#include <BRepBuilderAPI_MakeWire.hxx>
#include <ElSLib.hxx>
#include <GeomAPI_Interpolate.hxx>
+#include <TColgp_Array1OfVec.hxx>
#include <TColgp_HArray1OfPnt.hxx>
+#include <TColStd_HArray1OfBoolean.hxx>
#include <TopoDS_Wire.hxx>
const double POINT_CONFUSION_TOLERANCE = 0.0001;
}
//=======================================================================
-// function : MakeInterpolation
-// purpose :
+// function : constructBSpline
+// purpose : See function 'constructBSpline' in file 'CurveCreator_Utils.cxx'.
//=======================================================================
-TopoDS_Shape Sketcher_Utils::MakeInterpolation
- (const std::list <double> &theCoords2D,
- const Standard_Boolean IsClosed,
- const gp_Ax3 &thePlane)
+static bool constructBSpline(
+ const Handle(TColgp_HArray1OfPnt)& thePoints,
+ const Standard_Boolean theIsClosed,
+ Handle(Geom_BSplineCurve)& theBSpline)
{
- std::list <gp_Pnt> aPoints;
- TopoDS_Shape aResult;
-
- To3D(theCoords2D, thePlane, aPoints);
-
- Standard_Integer aNbPnts = aPoints.size();
-
- if (aNbPnts > 1) {
- if (IsClosed &&
- aPoints.front().IsEqual(aPoints.back(), POINT_CONFUSION_TOLERANCE)) {
- // The polyline should be closed, first and last points are confused.
- // Remove the last point.
- aPoints.pop_back();
- --aNbPnts;
- }
+ const int aPointCount = thePoints->Length();
+ if (aPointCount <= 1)
+ {
+ return false;
}
- if (aNbPnts == 1) {
- // The result is vertex.
- aResult = BRepBuilderAPI_MakeVertex(aPoints.front()).Vertex();
- } else if (aNbPnts > 1) {
- std::list <gp_Pnt>::const_iterator anIter = aPoints.begin();
- Handle(TColgp_HArray1OfPnt) aHCurvePoints =
- new TColgp_HArray1OfPnt(1, aNbPnts);
- Standard_Integer i;
-
- for (i = 1; anIter != aPoints.end(); ++anIter, ++i) {
- aHCurvePoints->SetValue(i, *anIter);
+ // Calculate the tangents.
+ TColgp_Array1OfVec aTangents(1, aPointCount);
+ Handle(TColStd_HArray1OfBoolean) aTangentFlags =
+ new TColStd_HArray1OfBoolean(1, aPointCount);
+ GeomAPI_Interpolate aInterpolator(thePoints, theIsClosed, 0);
+ if (aPointCount == 2)
+ {
+ aTangentFlags->SetValue(1, Standard_False);
+ aTangentFlags->SetValue(2, Standard_False);
+ }
+ else
+ {
+ for (Standard_Integer aPN = 1; aPN <= aPointCount; ++aPN)
+ {
+ gp_Vec aTangent;
+ if (aPN != 1 || theIsClosed)
+ {
+ const Standard_Integer aPN1 = (aPN != 1) ? (aPN - 1) : aPointCount;
+ aTangent = gp_Vec(thePoints->Value(aPN1),
+ thePoints->Value(aPN)).Normalized();
+ }
+ if (aPN < aPointCount || theIsClosed)
+ {
+ const Standard_Integer aPN2 = (aPN != aPointCount) ? (aPN + 1) : 1;
+ const gp_Vec aTangent2 = aTangent +
+ gp_Vec(thePoints->Value(aPN), thePoints->Value(aPN2)).Normalized();
+ if (aTangent2.SquareMagnitude() >= Precision::SquareConfusion())
+ {
+ aTangent = aTangent2.Normalized();
+ }
+ else
+ {
+ aTangent = -aTangent;
+ }
+ }
+ aTangents.SetValue(aPN, aTangent);
+ aTangentFlags->SetValue(aPN, Standard_True);
}
+ }
- // Compute BSpline
- Standard_Real aTol = Precision::Confusion();
- GeomAPI_Interpolate aGBC(aHCurvePoints, IsClosed, aTol);
+ // Interpolate.
+ aInterpolator.Load(aTangents, aTangentFlags, Standard_False);
+ aInterpolator.Perform();
+ const bool aResult = (aInterpolator.IsDone() == Standard_True);
+ if (aResult)
+ {
+ theBSpline = aInterpolator.Curve();
+ }
+ return aResult;
+}
- aGBC.Perform();
+//=======================================================================
+// function : MakeInterpolation
+// purpose :
+//=======================================================================
+TopoDS_Shape Sketcher_Utils::MakeInterpolation(
+ const std::list<double>& theCoords2D,
+ const Standard_Boolean theIsClosed,
+ const gp_Ax3& thePlane)
+{
+ if (theCoords2D.size() == 0)
+ {
+ return TopoDS_Shape();
+ }
- if (aGBC.IsDone()) {
- TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aGBC.Curve()).Edge();
- aResult = BRepBuilderAPI_MakeWire(anEdge).Wire();
+ // Get the different points.
+ std::list<gp_Pnt> aTmpPoints;
+ To3D(theCoords2D, thePlane, aTmpPoints);
+ gp_Pnt aFirstPoint = aTmpPoints.front();
+ gp_Pnt aPoint = aFirstPoint;
+ std::list<gp_Pnt>::iterator aPIt = aTmpPoints.begin();
+ for (++aPIt; aPIt != aTmpPoints.cend();)
+ {
+ const gp_Pnt aPoint2 = *aPIt;
+ if (!aPoint.IsEqual(aPoint2, POINT_CONFUSION_TOLERANCE))
+ {
+ aPoint = aPoint2;
+ ++aPIt;
+ }
+ else
+ {
+ aTmpPoints.erase(aPIt);
+ }
+ }
+ if (theIsClosed)
+ {
+ while (--aPIt != aTmpPoints.cbegin() &&
+ aFirstPoint.IsEqual(*aPIt, POINT_CONFUSION_TOLERANCE))
+ {
+ aTmpPoints.erase(aPIt);
}
}
- return aResult;
+ // Process the single point case.
+ const int aPointCount = aTmpPoints.size();
+ if (aPointCount == 1)
+ {
+ return BRepBuilderAPI_MakeVertex(aTmpPoints.front());
+ }
+
+ // Process the other cases.
+ Handle(TColgp_HArray1OfPnt) aPoints =
+ new TColgp_HArray1OfPnt(1, aPointCount);
+ aPIt = aTmpPoints.begin();
+ for (Standard_Integer aPN = 1; aPIt != aTmpPoints.cend(); ++aPIt, ++aPN)
+ {
+ aPoints->SetValue(aPN, *aPIt);
+ }
+ Handle(Geom_BSplineCurve) aBSpline;
+ if (constructBSpline(aPoints, theIsClosed, aBSpline))
+ {
+ return BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(aBSpline));
+ }
+ return TopoDS_Shape();
}
//=======================================================================