Skip to content

Commit

Permalink
+ fixes #1898: Drawing workbench draws cylinder in orthographic proje…
Browse files Browse the repository at this point in the history
…ction wrong
  • Loading branch information
wwmayer committed Jan 11, 2015
1 parent 9cb8471 commit 0a31beb
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 3 deletions.
76 changes: 75 additions & 1 deletion src/Mod/Drawing/App/DrawingExport.cpp
Expand Up @@ -25,6 +25,7 @@

#ifndef _PreComp_
# include <sstream>
# include <cmath>
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Circle.hxx>
# include <gp_Circ.hxx>
Expand All @@ -33,6 +34,7 @@

#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <HLRBRep_Algo.hxx>
#include <TopoDS_Shape.hxx>
Expand Down Expand Up @@ -71,13 +73,78 @@
#include <GeomConvert_BSplineCurveToBezierCurve.hxx>
#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <BRepLProp_CLProps.hxx>

#include "DrawingExport.h"
#include <Base/Tools.h>
#include <Base/Vector3D.h>

using namespace Drawing;

TopoDS_Edge DrawingOutput::asCircle(const BRepAdaptor_Curve& c) const
{
double curv=0;
gp_Pnt pnt, center;

// approximate the circle center from three positions
BRepLProp_CLProps prop(c,c.FirstParameter(),2,Precision::Confusion());
curv += prop.Curvature();
prop.CentreOfCurvature(pnt);
center.ChangeCoord().Add(pnt.Coord());

prop.SetParameter(0.5*(c.FirstParameter()+c.LastParameter()));
curv += prop.Curvature();
prop.CentreOfCurvature(pnt);
center.ChangeCoord().Add(pnt.Coord());

prop.SetParameter(c.LastParameter());
curv += prop.Curvature();
prop.CentreOfCurvature(pnt);
center.ChangeCoord().Add(pnt.Coord());

center.ChangeCoord().Divide(3);
curv /= 3;

// get circle from curvature information
double radius = 1 / curv;

TopLoc_Location location;
Handle(Poly_Polygon3D) polygon = BRep_Tool::Polygon3D(c.Edge(), location);
if (!polygon.IsNull()) {
const TColgp_Array1OfPnt& nodes = polygon->Nodes();
for (int i = nodes.Lower(); i <= nodes.Upper(); i++) {
gp_Pnt p = nodes(i);
double dist = p.Distance(center);
if (std::abs(dist - radius) > 0.001)
return TopoDS_Edge();
}

gp_Circ circ;
circ.SetLocation(center);
circ.SetRadius(radius);
gp_Pnt p1 = nodes(nodes.Lower());
gp_Pnt p2 = nodes(nodes.Upper());
double dist = p1.Distance(p2);

if (dist < Precision::Confusion()) {
BRepBuilderAPI_MakeEdge mkEdge(circ);
return mkEdge.Edge();
}
else {
gp_Vec dir1(center, p1);
dir1.Normalize();
gp_Vec dir2(center, p2);
dir2.Normalize();
p1 = gp_Pnt(center.XYZ() + radius * dir1.XYZ());
p2 = gp_Pnt(center.XYZ() + radius * dir2.XYZ());
BRepBuilderAPI_MakeEdge mkEdge(circ, p1, p2);
return mkEdge.Edge();
}
}

return TopoDS_Edge();
}

SVGOutput::SVGOutput()
{
}
Expand All @@ -97,7 +164,14 @@ std::string SVGOutput::exportEdges(const TopoDS_Shape& input)
printEllipse(adapt, i, result);
}
else if (adapt.GetType() == GeomAbs_BSplineCurve) {
printBSpline(adapt, i, result);
TopoDS_Edge circle = asCircle(adapt);
if (circle.IsNull()) {
printBSpline(adapt, i, result);
}
else {
BRepAdaptor_Curve adapt_circle(circle);
printCircle(adapt_circle, result);
}
}
// fallback
else {
Expand Down
13 changes: 11 additions & 2 deletions src/Mod/Drawing/App/DrawingExport.h
Expand Up @@ -25,14 +25,23 @@
#define DRAWING_EXPORT_H

#include <string>
#include <TopoDS_Edge.hxx>

class TopoDS_Shape;
class BRepAdaptor_Curve;

namespace Drawing
{

class DrawingExport SVGOutput
class DrawingExport DrawingOutput
{
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;
};

class DrawingExport SVGOutput : public DrawingOutput
{
public:
SVGOutput();
Expand All @@ -46,7 +55,7 @@ class DrawingExport SVGOutput
};

/* dxf output section - Dan Falck 2011/09/25 */
class DrawingExport DXFOutput
class DrawingExport DXFOutput : public DrawingOutput
{
public:
DXFOutput();
Expand Down

0 comments on commit 0a31beb

Please sign in to comment.