+ support Bezier curves for SVG output

This commit is contained in:
wmayer 2015-01-11 16:02:27 +01:00
parent 82edb4b50a
commit 0b904e674b
3 changed files with 89 additions and 1 deletions

View File

@ -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 << "<path d=\"M";
Handle_Geom_BezierCurve bezier = c.Bezier();
Standard_Integer poles = bezier->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 {

View File

@ -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&);
};

View File

@ -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()) {