Calculate number of segments based on radius.

Fixes: lp:1754252
* https://bugs.launchpad.net/kicad/+bug/1754252
This commit is contained in:
Jeff Young 2018-03-08 18:03:56 +00:00
parent ab730709c7
commit 8a35e58987
2 changed files with 42 additions and 51 deletions

View File

@ -1425,8 +1425,7 @@ double MODULE::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
// see convert_drawsegment_list_to_polygon.cpp:
extern bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
SHAPE_POLY_SET& aPolygons, int aSegmentsByCircle,
wxString* aErrorText);
SHAPE_POLY_SET& aPolygons, wxString* aErrorText);
bool MODULE::BuildPolyCourtyard()
{
@ -1455,13 +1454,10 @@ bool MODULE::BuildPolyCourtyard()
wxString error_msg;
const int STEPS = 36; // for a segmentation of an arc of 360 degrees
bool success = ConvertOutlineToPolygon( list_front, m_poly_courtyard_front,
STEPS, &error_msg );
bool success = ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, &error_msg );
if( success )
success = ConvertOutlineToPolygon( list_back, m_poly_courtyard_back,
STEPS, &error_msg );
success = ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, &error_msg );
if( !error_msg.IsEmpty() )
{

View File

@ -167,6 +167,17 @@ static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT*
}
#define ARC_ACCURACY ( 0.05 * IU_PER_MM )
int calcArcSteps( int aRadius, int aSweptAngle )
{
int circleSteps = M_PI / acos( ( aRadius - ARC_ACCURACY ) / aRadius );
int arcSteps = circleSteps * fabs( aSweptAngle ) / 3600.0;
return std::max( arcSteps, 1 );
}
/**
* Function ConvertOutlineToPolygon
* build a polygon (with holes) from a DRAWSEGMENT list, which is expected to be
@ -174,12 +185,10 @@ static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT*
* These closed inner outlines are considered as holes in the main outline
* @param aSegList the initial list of drawsegments (only lines, circles and arcs).
* @param aPolygons will contain the complex polygon.
* @param aSegmentsByCircle is the number of segments to approximate a circle.
* @param aErrorText is a wxString to return error message.
*/
bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
SHAPE_POLY_SET& aPolygons, int aSegmentsByCircle,
wxString* aErrorText )
SHAPE_POLY_SET& aPolygons, wxString* aErrorText )
{
if( aSegList.size() == 0 )
@ -229,11 +238,7 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
wxPoint pstart = graphic->GetArcStart();
wxPoint center = graphic->GetCenter();
double angle = -graphic->GetAngle();
int steps = aSegmentsByCircle * fabs(angle) /3600.0;
if( steps == 0 )
steps = 1;
int steps = calcArcSteps( graphic->GetRadius(), angle );
wxPoint pt;
for( int step = 1; step<=steps; ++step )
@ -292,7 +297,8 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
if( graphic->GetShape() == S_CIRCLE )
{
TransformCircleToPolygon( aPolygons, graphic->GetCenter(),
graphic->GetRadius(), aSegmentsByCircle );
graphic->GetRadius(),
calcArcSteps( graphic->GetRadius(), 3600 ) );
}
else
{
@ -320,13 +326,9 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
// very close to it.
if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
{
nextPt = graphic->GetEnd();
}
else
{
nextPt = graphic->GetStart();
}
aPolygons.Append( nextPt );
prevPt = nextPt;
@ -342,10 +344,7 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
wxPoint pend = graphic->GetArcEnd();
wxPoint pcenter = graphic->GetCenter();
double angle = -graphic->GetAngle();
int steps = aSegmentsByCircle * fabs(angle) /3600.0;
if( steps == 0 )
steps = 1;
int steps = calcArcSteps( graphic->GetRadius(), angle );
if( !close_enough( prevPt, pstart, prox ) )
{
@ -437,13 +436,14 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
double angle = 3600.0;
wxPoint start = center;
int radius = graphic->GetRadius();
start.x += radius;
int steps = calcArcSteps( radius, angle );
wxPoint nextPt;
for( int step = 0; step<aSegmentsByCircle; ++step )
start.x += radius;
for( int step = 0; step < steps; ++step )
{
double rotation = ( angle * step ) / aSegmentsByCircle;
double rotation = ( angle * step ) / steps;
nextPt = start;
RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
aPolygons.Append( nextPt, -1, hole );
@ -494,10 +494,7 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
wxPoint pend = graphic->GetArcEnd();
wxPoint pcenter = graphic->GetCenter();
double angle = -graphic->GetAngle();
int steps = aSegmentsByCircle * fabs(angle) /3600.0;
if( steps == 0 )
steps = 1;
int steps = calcArcSteps( graphic->GetRadius(), angle );
if( !close_enough( prevPt, pstart, prox ) )
{
@ -526,8 +523,7 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
default:
if( aErrorText )
{
msg.Printf(
_( "Unsupported DRAWSEGMENT type %s" ),
msg.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( graphic->GetShape() ) ) );
*aErrorText << msg << "\n";
@ -602,8 +598,7 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard,
segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
}
const int STEPS = 36; // for a segmentation of an arc of 360 degrees
bool success = ConvertOutlineToPolygon( segList, aOutlines, STEPS, aErrorText );
bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText );
if( !success || !aOutlines.OutlineCount() )
{