TransformArcToPolygon(): slightly better approximation of arc.

The error between the "right" shape and the polygon is slightly smaller.
The approximations of the inner arc and the outer arc are better, but not perfect.
Also add (for test and debug purpose only) the code to show the polygon when
drawing a PCB_ARC (currently disabled)
This commit is contained in:
jean-pierre charras 2021-06-25 18:46:16 +02:00
parent 1f4a56005e
commit 31d7a0a8d1
2 changed files with 32 additions and 10 deletions

View File

@ -5,7 +5,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -355,43 +355,51 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoi
SHAPE_ARC arc( aStart, aMid, aEnd, aWidth );
SHAPE_LINE_CHAIN arcSpine = arc.ConvertToPolyline( aError );
int radial_offset = ( aWidth + 1 ) / 2;
SHAPE_POLY_SET polyshape;
std::vector<VECTOR2I> outside_pts;
/// We start by making rounded ends on the arc
TransformCircleToPolygon( aCornerBuffer,
TransformCircleToPolygon( polyshape,
wxPoint( arcSpine.GetPoint( 0 ).x, arcSpine.GetPoint( 0 ).y ), radial_offset, aError,
aErrorLoc );
TransformCircleToPolygon( aCornerBuffer,
TransformCircleToPolygon( polyshape,
wxPoint( arcSpine.GetPoint( -1 ).x, arcSpine.GetPoint( -1 ).y ), radial_offset, aError,
aErrorLoc );
if( aErrorLoc == ERROR_OUTSIDE )
radial_offset += aError;
else
radial_offset -= aError;
radial_offset -= aError/2;
if( radial_offset < 0 )
radial_offset = 0;
std::vector<VECTOR2I> outside_pts;
SHAPE_POLY_SET polyshape;
polyshape.NewOutline();
VECTOR2I center = arc.GetCenter();
int radius = ( arc.GetP0() - center ).EuclideanNorm();
int last_index = arcSpine.GetPointCount() -1;
for( std::size_t ii = 0; ii < arcSpine.GetPointCount(); ++ii )
for( std::size_t ii = 0; ii <= last_index; ++ii )
{
VECTOR2I offset = arcSpine.GetPoint( ii ) - center;
int curr_rd = radius;
polyshape.Append( offset.Resize( radius - radial_offset ) + center );
outside_pts.emplace_back( offset.Resize( radius + radial_offset ) + center );
// This correction gives a better position of intermediate points of the sides of arc.
if( ii > 0 && ii < last_index )
curr_rd += aError/2;
polyshape.Append( offset.Resize( curr_rd - radial_offset ) + center );
outside_pts.emplace_back( offset.Resize( curr_rd + radial_offset ) + center );
}
for( auto it = outside_pts.rbegin(); it != outside_pts.rend(); ++it )
polyshape.Append( *it );
// Can be removed, but usefull to display the outline:
polyshape.Simplify( SHAPE_POLY_SET::PM_FAST );
aCornerBuffer.Append( polyshape );
}

View File

@ -700,6 +700,20 @@ void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
width + clearance * 2 );
}
// Debug only: enable this code only to test the TransformArcToPolygon function
// and display the polygon outline created by it.
#if 0
SHAPE_POLY_SET cornerBuffer;
int errorloc = aArc->GetBoard()->GetDesignSettings().m_MaxError;
TransformArcToPolygon( cornerBuffer, aArc->GetStart(), aArc->GetMid(),
aArc->GetEnd(), width, errorloc, ERROR_LOC::ERROR_OUTSIDE );
m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth );
m_gal->SetIsFill( false );
m_gal->SetIsStroke( true );
m_gal->SetStrokeColor( color );
m_gal->DrawPolygon( cornerBuffer );
#endif
}