Skip to content

Commit

Permalink
Fix Drawing/TechDraw BSplines
Browse files Browse the repository at this point in the history
In some cases the Geom_BSplineCurve returned by
BrepAdaptor_Curve.BSpline() does not have the
same endpoints as the original Edge and should
not be used in place of Approx_Curve3d.
  • Loading branch information
WandererFan authored and wwmayer committed Jun 28, 2017
1 parent 18ed89a commit a32972e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 69 deletions.
46 changes: 24 additions & 22 deletions src/Mod/Drawing/App/DrawingExport.cpp
Expand Up @@ -359,17 +359,18 @@ void SVGOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& o
{
try {
std::stringstream str;
Handle(Geom_BSplineCurve) spline = c.BSpline();
if (spline->Degree() > 3 || spline->IsRational()) {
Standard_Real tol3D = 0.001;
Standard_Integer maxDegree = 3, maxSegment = 100;
Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
// approximate the curve using a tolerance
Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C0,maxSegment,maxDegree);
if (approx.IsDone() && approx.HasResult()) {
// have the result
spline = approx.Curve();
}
Handle(Geom_BSplineCurve) spline;
Standard_Real tol3D = 0.001;
Standard_Integer maxDegree = 3, maxSegment = 100;
Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
// approximate the curve using a tolerance
Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C0,maxSegment,maxDegree);
if (approx.IsDone() && approx.HasResult()) {
// have the result
spline = approx.Curve();
} else {
printGeneric(c, id, out);
return;
}

GeomConvert_BSplineCurveToBezierCurve crt(spline);
Expand Down Expand Up @@ -659,17 +660,18 @@ void DXFOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& o
{
try {
std::stringstream str;
Handle(Geom_BSplineCurve) spline = c.BSpline();
if (spline->Degree() > 3 || spline->IsRational()) {
Standard_Real tol3D = 0.001;
Standard_Integer maxDegree = 3, maxSegment = 50;
Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
// approximate the curve using a tolerance
Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C0,maxSegment,maxDegree);
if (approx.IsDone() && approx.HasResult()) {
// have the result
spline = approx.Curve();
}
Handle(Geom_BSplineCurve) spline;
Standard_Real tol3D = 0.001;
Standard_Integer maxDegree = 3, maxSegment = 50;
Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
// approximate the curve using a tolerance
Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C0,maxSegment,maxDegree);
if (approx.IsDone() && approx.HasResult()) {
// have the result
spline = approx.Curve();
} else {
printGeneric(c, id, out);
return;
}

//GeomConvert_BSplineCurveToBezierCurve crt(spline);
Expand Down
85 changes: 38 additions & 47 deletions src/Mod/TechDraw/App/Geometry.cpp
Expand Up @@ -42,12 +42,15 @@
#include <Geom_BSplineCurve.hxx>
#include <Geom_BezierCurve.hxx>
#include <GeomConvert_BSplineCurveToBezierCurve.hxx>
#include <GeomAPI_PointsToBSpline.hxx>
#include <Poly_Polygon3D.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColgp_Array1OfPnt.hxx>

#include <cmath>
#endif // #ifndef _PreComp_

Expand Down Expand Up @@ -429,64 +432,52 @@ BSpline::BSpline(const TopoDS_Edge &e)
geomType = BSPLINE;
BRepAdaptor_Curve c(e);
occEdge = e;
Handle(Geom_BSplineCurve) spline = c.BSpline();
bool fail = false;
Handle(Geom_BSplineCurve) spline;
double f,l;
gp_Pnt s,m,ePt;

if (spline->Degree() > 3 || spline->IsRational()) { //if spline is too complex, approximate it
Standard_Real tol3D = 0.001; //1/1000 of a mm? screen can't resolve this
Standard_Integer maxDegree = 3, maxSegment = 100;
Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
// approximate the curve using a tolerance
//Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C2, maxSegment, maxDegree); //gives degree == 5 ==> too many poles ==> buffer overrun
Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C0, maxSegment, maxDegree);
if (approx.IsDone() && approx.HasResult()) {
gp_Pnt s,ePt;

Standard_Real tol3D = 0.001; //1/1000 of a mm? screen can't resolve this
Standard_Integer maxDegree = 3, maxSegment = 100;
Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
// approximate the curve using a tolerance
//Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C2, maxSegment, maxDegree); //gives degree == 5 ==> too many poles ==> buffer overrun
Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C0, maxSegment, maxDegree);
if (approx.IsDone() && approx.HasResult()) {
spline = approx.Curve();
} else {
if (approx.HasResult()) { //result, but not within tolerance
spline = approx.Curve();
Base::Console().Log("Geometry::BSpline - result not within tolerance\n");
} else {
if (approx.HasResult()) { //result, but not within tolerance
spline = approx.Curve();
Base::Console().Log("Geometry::BSpline - result not within tolerance\n");
} else {
fail = true;
f = c.FirstParameter();
l = c.LastParameter();
s = c.Value(f);
m = c.Value((l+f)/2.0);
ePt = c.Value(l);
Base::Console().Log("Error - Geometry::BSpline - no result- from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n",
s.X(),s.Y(),ePt.X(),ePt.Y(),spline->NbPoles());
throw Base::Exception("Geometry::BSpline - could not approximate curve");
}
f = c.FirstParameter();
l = c.LastParameter();
s = c.Value(f);
ePt = c.Value(l);
Base::Console().Log("Error - Geometry::BSpline - no result- from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n",
s.X(),s.Y(),ePt.X(),ePt.Y(),spline->NbPoles());
TColgp_Array1OfPnt controlPoints(0,1);
controlPoints.SetValue(0,s);
controlPoints.SetValue(1,ePt);
spline = GeomAPI_PointsToBSpline(controlPoints,1).Curve();
}
}

GeomConvert_BSplineCurveToBezierCurve crt(spline);

gp_Pnt controlPoint;
if (fail) {
for (Standard_Integer i = 1; i <= crt.NbArcs(); ++i) {
BezierSegment tempSegment;
tempSegment.poles = 3;
tempSegment.degree = 2;
tempSegment.pnts.push_back(Base::Vector2d(s.X(),s.Y()));
tempSegment.pnts.push_back(Base::Vector2d(m.X(),m.Y()));
tempSegment.pnts.push_back(Base::Vector2d(ePt.X(),ePt.Y()));
segments.push_back(tempSegment);
} else {
for (Standard_Integer i = 1; i <= crt.NbArcs(); ++i) {
BezierSegment tempSegment;
Handle(Geom_BezierCurve) bezier = crt.Arc(i);
if (bezier->Degree() > 3) {
Base::Console().Log("Geometry::BSpline - converted curve degree > 3\n");
}
tempSegment.poles = bezier->NbPoles();
tempSegment.degree = bezier->Degree();
for (int pole = 1; pole <= tempSegment.poles; ++pole) {
controlPoint = bezier->Pole(pole);
tempSegment.pnts.push_back(Base::Vector2d(controlPoint.X(), controlPoint.Y()));
}
segments.push_back(tempSegment);
Handle(Geom_BezierCurve) bezier = crt.Arc(i);
if (bezier->Degree() > 3) {
Base::Console().Log("Geometry::BSpline - converted curve degree > 3\n");
}
tempSegment.poles = bezier->NbPoles();
tempSegment.degree = bezier->Degree();
for (int pole = 1; pole <= tempSegment.poles; ++pole) {
controlPoint = bezier->Pole(pole);
tempSegment.pnts.push_back(Base::Vector2d(controlPoint.X(), controlPoint.Y()));
}
segments.push_back(tempSegment);
}
}

Expand Down

0 comments on commit a32972e

Please sign in to comment.