Add native Bezier curve plot in SVG plotter.

This commit is contained in:
jean-pierre charras 2019-11-05 14:27:07 +01:00
parent bb9b226744
commit 5f3353cad1
4 changed files with 74 additions and 25 deletions

View File

@ -506,6 +506,29 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
}
void SVG_PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
const wxPoint& aControl2, const wxPoint& aEnd,
int aTolerance, int aLineThickness )
{
#if 1
setFillMode( NO_FILL );
SetCurrentLineWidth( aLineThickness );
DPOINT start = userToDeviceCoordinates( aStart );
DPOINT ctrl1 = userToDeviceCoordinates( aControl1 );
DPOINT ctrl2 = userToDeviceCoordinates( aControl2 );
DPOINT end = userToDeviceCoordinates( aEnd );
// Generate a cubic curve: start point and 3 other control points.
fprintf( outputFile, "<path d=\"M%g,%g C%g,%g %g,%g %g,%g\" />\n",
start.x, start.y, ctrl1.x, ctrl1.y,
ctrl2.x, ctrl2.y, end.x, end.y );
#else
PLOTTER::BezierCurve( aStart, aControl1,aControl2, aEnd,aTolerance, aLineThickness );
#endif
}
void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
FILL_T aFill, int aWidth, void * aData )
{

View File

@ -50,6 +50,7 @@
#include <gr_text.h>
#include <geometry/shape_line_chain.h>
#include <geometry/geometry_utils.h>
#include <bezier_curves.h>
PLOTTER::PLOTTER( )
{
@ -198,6 +199,33 @@ void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int r
}
void PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
const wxPoint& aControl2, const wxPoint& aEnd,
int aTolerance, int aLineThickness )
{
// Generic fallback: Quadratic Bezier curve plotted as a polyline
int minSegLen = aLineThickness; // The segment min length to approximate a bezier curve
std::vector<wxPoint> ctrlPoints;
ctrlPoints.push_back( aStart );
ctrlPoints.push_back( aControl1 );
ctrlPoints.push_back( aControl2 );
ctrlPoints.push_back( aEnd );
BEZIER_POLY bezier_converter( ctrlPoints );
std::vector<wxPoint> approxPoints;
bezier_converter.GetPoly( approxPoints, minSegLen );
MoveTo( aStart );
for( unsigned ii = 1; ii < approxPoints.size()-1; ii++ )
LineTo( approxPoints[ii] );
FinishTo( aEnd );
}
void PLOTTER::PlotImage(const wxImage & aImage, const wxPoint& aPos, double aScaleFactor )
{
wxSize size( aImage.GetWidth() * aScaleFactor,

View File

@ -231,6 +231,16 @@ public:
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
/**
* Generic fallback: Cubic Bezier curve rendered as a polyline
* In Kicad the bezier curves have 4 control points:
* start ctrl1 ctrl2 end
*/
virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
const wxPoint& aControl2, const wxPoint& aEnd,
int aTolerance,
int aLineThickness = USE_DEFAULT_LINE_WIDTH );
/**
* moveto/lineto primitive, moves the 'pen' to the specified direction
* @param pos is the target position
@ -946,6 +956,11 @@ public:
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
const wxPoint& aControl2, const wxPoint& aEnd,
int aTolerance,
int aLineThickness = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH,
void * aData = NULL ) override;

View File

@ -475,7 +475,7 @@ void BRDITEMS_PLOTTER::Plot_1_EdgeModule( EDGE_MODULE* aEdge )
int radius; // Circle/arc radius.
switch( aEdge->Type() )
switch( aEdge->GetShape() )
{
case S_SEGMENT:
m_plotter->ThickSegment( pos, end, thickness, GetPlotMode(), &gbr_metadata );
@ -558,22 +558,13 @@ void BRDITEMS_PLOTTER::Plot_1_EdgeModule( EDGE_MODULE* aEdge )
break;
case S_CURVE:
{
m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
int minSegLen = aEdge->GetWidth(); // The segment min length to approximate a bezier curve
aEdge->RebuildBezierToSegmentsPointsList( minSegLen );
const std::vector<wxPoint>& bezierPoints = aEdge->GetBezierPoints();
for( unsigned i = 1; i < bezierPoints.size(); i++ )
{
m_plotter->ThickSegment( bezierPoints[i - 1], bezierPoints[i],
thickness, GetPlotMode(), &gbr_metadata );
}
}
m_plotter->BezierCurve( aEdge->GetStart(), aEdge->GetBezControl1(),
aEdge->GetBezControl2(), aEdge->GetEnd(),
0, thickness );
break;
default:
wxASSERT_MSG( false, "Unhandled EDGE_MODULE type" );
wxASSERT_MSG( false, "Unhandled EDGE_MODULE shape" );
break;
}
}
@ -765,17 +756,9 @@ void BRDITEMS_PLOTTER::PlotDrawSegment( DRAWSEGMENT* aSeg )
break;
case S_CURVE:
{
m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
aSeg->RebuildBezierToSegmentsPointsList( aSeg->GetWidth() );
const std::vector<wxPoint>& bezierPoints = aSeg->GetBezierPoints();
for( unsigned i = 1; i < bezierPoints.size(); i++ )
{
m_plotter->ThickSegment( bezierPoints[i - 1], bezierPoints[i],
thickness, GetPlotMode(), &gbr_metadata );
}
}
m_plotter->BezierCurve( aSeg->GetStart(), aSeg->GetBezControl1(),
aSeg->GetBezControl2(), aSeg->GetEnd(),
0, thickness );
break;
case S_POLYGON: