OPENGL_GAL::DrawArcSegment(): use a better number of segm to approximate the arc.

Previously, the count of segments used a magic number optimized for Pcbnew.
This is not good, and does not work well on Gerbview.
The count uses now a max error acceptable is approximation (5 microns in Gerbview and Pcbnew).
Fixes #9101
https://gitlab.com/kicad/code/kicad/issues/9101
This commit is contained in:
jean-pierre charras 2021-09-06 16:36:28 +02:00
parent 56ccaf6482
commit 36048fa436
7 changed files with 25 additions and 13 deletions

View File

@ -342,8 +342,10 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
double aStartAngle, double aEndAngle, double aWidth )
double aStartAngle, double aEndAngle, double aWidth,
double aMaxError )
{
// Note: aMaxError is not used because Cairo can draw true arcs
if( m_isFillEnabled )
{
m_lineWidth = aWidth;

View File

@ -48,6 +48,7 @@
#include <wx/frame.h>
#include <macros.h>
#include <geometry/geometry_utils.h>
#ifdef KICAD_GAL_PROFILE
#include <profile.h>
@ -850,8 +851,9 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a
}
void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
double aEndAngle, double aWidth )
void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
double aStartAngle, double aEndAngle,
double aWidth, double aMaxError )
{
if( aRadius <= 0 )
{
@ -865,7 +867,10 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, d
// Swap the angles, if start angle is greater than end angle
SWAP( aStartAngle, >, aEndAngle );
double alphaIncrement = calcAngleStep( aRadius );
// Calculate the seg count to approximate the arc with aMaxError or less
int segCount360 = GetArcToSegmentCount( aRadius, aMaxError, 360.0 );
segCount360 = std::max( CIRCLE_POINTS, segCount360 );
double alphaIncrement = 2.0 * M_PI / segCount360;
// Refinement: Use a segment count multiple of 2, because we have a control point
// on the middle of the arc, and the look is better if it is on a segment junction

View File

@ -351,7 +351,7 @@ void GERBVIEW_PAINTER::draw( /*const*/ GERBER_DRAW_ITEM* aItem, int aLayer )
endAngle = startAngle + 2*M_PI;
}
m_gal->DrawArcSegment( center, radius, startAngle, endAngle, width );
m_gal->DrawArcSegment( center, radius, startAngle, endAngle, width, ARC_HIGH_DEF );
#if 0 // Arc Debugging only
m_gal->SetIsFill( false );

View File

@ -82,8 +82,10 @@ public:
double aStartAngle, double aEndAngle ) override;
/// @copydoc GAL::DrawArcSegment()
/// Note: aMaxError is not used in Cairo, because Cairo can draw true arcs
void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
double aStartAngle, double aEndAngle, double aWidth ) override;
double aStartAngle, double aEndAngle, double aWidth,
double aMaxError ) override;
/// @copydoc GAL::DrawRectangle()
void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;

View File

@ -151,9 +151,11 @@ public:
* @param aStartAngle is the start angle of the arc.
* @param aEndAngle is the end angle of the arc.
* @param aWidth is the thickness of the arc (pen size).
* @param aMaxError is the max allowed error to create segments to approximate a circle.
* It has meaning only for back ends that can't draw a true arc, and use segments to approximate.
*/
virtual void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
double aEndAngle, double aWidth ) {};
double aEndAngle, double aWidth, double aMaxError ) {};
/**
* Draw a rectangle.

View File

@ -128,7 +128,8 @@ public:
/// @copydoc GAL::DrawArcSegment()
void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
double aStartAngle, double aEndAngle, double aWidth ) override;
double aStartAngle, double aEndAngle, double aWidth,
double aMaxError ) override;
/// @copydoc GAL::DrawRectangle()
void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;

View File

@ -683,7 +683,7 @@ void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
m_gal->SetIsFill( not outline_mode );
m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth );
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle, width );
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle, width, ARC_HIGH_DEF );
}
// Clearance lines
@ -700,7 +700,7 @@ void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
m_gal->SetStrokeColor( color );
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
width + clearance * 2 );
width + clearance * 2, ARC_HIGH_DEF );
}
// Debug only: enable this code only to test the TransformArcToPolygon function
@ -1081,7 +1081,7 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
std::unique_ptr<PAD> dummyPad;
std::shared_ptr<SHAPE_COMPOUND> shapes;
// Drawing components of compound shapes in outline mode produces a mess.
// Drawing components of compound shapes in outline mode produces a mess.
bool simpleShapes = !m_pcbSettings.m_sketchMode[LAYER_PADS_TH];
if( simpleShapes )
@ -1416,7 +1416,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
m_gal->DrawArcSegment( start, aShape->GetRadius(),
DECIDEG2RAD( aShape->GetArcAngleStart() ),
DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this
thickness );
thickness, ARC_HIGH_DEF );
}
else
{
@ -1426,7 +1426,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
m_gal->DrawArcSegment( start, aShape->GetRadius(),
DECIDEG2RAD( aShape->GetArcAngleStart() ),
DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this
thickness );
thickness, ARC_HIGH_DEF );
}
break;