From 0b904e674bfaede622ffed2a168287c187a30ef2 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 11 Jan 2015 16:02:27 +0100 Subject: [PATCH] + support Bezier curves for SVG output --- src/Mod/Drawing/App/DrawingExport.cpp | 84 +++++++++++++++++++++++++++ src/Mod/Drawing/App/DrawingExport.h | 2 + src/Mod/Drawing/Gui/DrawingView.cpp | 4 +- 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/Mod/Drawing/App/DrawingExport.cpp b/src/Mod/Drawing/App/DrawingExport.cpp index 09b81ef98..d765c0f87 100644 --- a/src/Mod/Drawing/App/DrawingExport.cpp +++ b/src/Mod/Drawing/App/DrawingExport.cpp @@ -145,6 +145,23 @@ TopoDS_Edge DrawingOutput::asCircle(const BRepAdaptor_Curve& c) const return TopoDS_Edge(); } +TopoDS_Edge DrawingOutput::asBSpline(const BRepAdaptor_Curve& c, int maxDegree) const +{ + Standard_Real tol3D = 0.001; + Standard_Integer maxSegment = 10; + 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 + Handle_Geom_BSplineCurve spline = approx.Curve(); + BRepBuilderAPI_MakeEdge mkEdge(spline, spline->FirstParameter(), spline->LastParameter()); + return mkEdge.Edge(); + } + + return TopoDS_Edge(); +} + SVGOutput::SVGOutput() { } @@ -173,6 +190,9 @@ std::string SVGOutput::exportEdges(const TopoDS_Shape& input) printCircle(adapt_circle, result); } } + else if (adapt.GetType() == GeomAbs_BezierCurve) { + printBezier(adapt, i, result); + } // fallback else { printGeneric(adapt, i, result); @@ -255,6 +275,70 @@ void SVGOutput::printEllipse(const BRepAdaptor_Curve& c, int id, std::ostream& o } } +void SVGOutput::printBezier(const BRepAdaptor_Curve& c, int id, std::ostream& out) +{ + try { + std::stringstream str; + str << "NbPoles(); + + // if it's a bezier with degree higher than 3 convert it into a B-spline + if (bezier->Degree() > 3 || bezier->IsRational()) { + TopoDS_Edge edge = asBSpline(c, 3); + if (!edge.IsNull()) { + BRepAdaptor_Curve spline(edge); + printBSpline(spline, id, out); + } + else { + Standard_Failure::Raise("do it the generic way"); + } + + return; + } + + + gp_Pnt p1 = bezier->Pole(1); + str << p1.X() << "," << p1.Y(); + if (bezier->Degree() == 3) { + if (poles != 4) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + gp_Pnt p3 = bezier->Pole(3); + gp_Pnt p4 = bezier->Pole(4); + str << " C" + << p2.X() << "," << p2.Y() << " " + << p3.X() << "," << p3.Y() << " " + << p4.X() << "," << p4.Y() << " "; + } + else if (bezier->Degree() == 2) { + if (poles != 3) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + gp_Pnt p3 = bezier->Pole(3); + str << " Q" + << p2.X() << "," << p2.Y() << " " + << p3.X() << "," << p3.Y() << " "; + } + else if (bezier->Degree() == 1) { + if (poles != 2) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + str << " L" << p2.X() << "," << p2.Y() << " "; + } + else { + Standard_Failure::Raise("do it the generic way"); + } + + str << "\" />"; + out << str.str(); + } + catch (Standard_Failure) { + printGeneric(c, id, out); + } +} + void SVGOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& out) { try { diff --git a/src/Mod/Drawing/App/DrawingExport.h b/src/Mod/Drawing/App/DrawingExport.h index 6f93cc007..e2e295159 100644 --- a/src/Mod/Drawing/App/DrawingExport.h +++ b/src/Mod/Drawing/App/DrawingExport.h @@ -39,6 +39,7 @@ public: // If the curve is approximately a circle it will be returned, // otherwise a null edge is returned. TopoDS_Edge asCircle(const BRepAdaptor_Curve&) const; + TopoDS_Edge asBSpline(const BRepAdaptor_Curve&, int maxDegree) const; }; class DrawingExport SVGOutput : public DrawingOutput @@ -51,6 +52,7 @@ private: void printCircle(const BRepAdaptor_Curve&, std::ostream&); void printEllipse(const BRepAdaptor_Curve&, int id, std::ostream&); void printBSpline(const BRepAdaptor_Curve&, int id, std::ostream&); + void printBezier(const BRepAdaptor_Curve&, int id, std::ostream&); void printGeneric(const BRepAdaptor_Curve&, int id, std::ostream&); }; diff --git a/src/Mod/Drawing/Gui/DrawingView.cpp b/src/Mod/Drawing/Gui/DrawingView.cpp index e1269c985..dc10e6c9a 100644 --- a/src/Mod/Drawing/Gui/DrawingView.cpp +++ b/src/Mod/Drawing/Gui/DrawingView.cpp @@ -332,7 +332,9 @@ void DrawingView::setDocumentObject(const std::string& name) void DrawingView::closeEvent(QCloseEvent* ev) { - ev->accept(); + MDIView::closeEvent(ev); + if (!ev->isAccepted()) + return; // when closing the view from GUI notify the view provider to mark it invisible if (_pcDocument && !m_objectName.empty()) {