From 56a17b4e680e8ef1dff7f69a097270197f2b76bf Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 12 Jun 2020 10:22:19 +0200 Subject: [PATCH] Gerber plotter: ensure the gerber region for a round rect pad is always closed. Due to rounding issues, sometimes (especially for rotated pads) the region (4 segments+4 arcs) was incorrectly closed 1 unit (nanometer) mismatch between start point and end point. Although it does not create bad shape, its breaks the round rect pad identification in CAM tools. start point and end point are now the same. From master. --- common/plotters/GERBER_plotter.cpp | 32 +++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index aeb5687912..8b19244d44 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -988,6 +988,9 @@ void GERBER_PLOTTER::plotRoundRectAsRegion( const wxPoint& aRectCenter, const wx rr_outline.push_back( curr_edge ); // Move relative coordinates to the actual location and rotation: + wxPoint arc_last_center; + int arc_last_angle = curr_edge.m_arc_angle_start+arc_angle; + for( RR_EDGE& rr_edge: rr_outline ) { RotatePoint( &rr_edge.m_start, aOrient ); @@ -996,19 +999,38 @@ void GERBER_PLOTTER::plotRoundRectAsRegion( const wxPoint& aRectCenter, const wx rr_edge.m_start += aRectCenter; rr_edge.m_end += aRectCenter; rr_edge.m_center += aRectCenter; + arc_last_center = rr_edge.m_center; } - fputs( "G36*\n", outputFile ); // Start region - fputs( "G01*\n", outputFile ); // Set linear interpolation. - MoveTo( rr_outline[0].m_start ); // Start point of region + // Ensure the region is a closed polygon, i.e. the end point of last segment + // (end of arc) is the same as the first point. Rounding issues can create a + // small difference, mainly for rotated pads. + // calculate last point (end of last arc): + wxPoint last_pt; + last_pt.x = arc_last_center.x + KiROUND( cosdecideg( aCornerRadius, arc_last_angle ) ); + last_pt.y = arc_last_center.y - KiROUND( sindecideg( aCornerRadius, arc_last_angle ) ); + + wxPoint first_pt = rr_outline[0].m_start; + +#if 0 // For test only: + if( last_pt != first_pt ) + wxLogMessage( "first pt %d %d last pt %d %d", + first_pt.x, first_pt.y, last_pt.x, last_pt.y ); +#endif + + fputs( "G36*\n", outputFile ); // Start region + fputs( "G01*\n", outputFile ); // Set linear interpolation. + first_pt = last_pt; + MoveTo( first_pt ); // Start point of region, must be same as end point for( RR_EDGE& rr_edge: rr_outline ) { if( aCornerRadius ) // Guard: ensure we do not create arcs with radius = 0 { // LineTo( rr_edge.m_end ); // made in plotArc() - plotArc( rr_edge.m_center, rr_edge.m_arc_angle_start, rr_edge.m_arc_angle_start+arc_angle, - aCornerRadius, true ); + plotArc( rr_edge.m_center, + rr_edge.m_arc_angle_start, rr_edge.m_arc_angle_start+arc_angle, + aCornerRadius, true ); } else LineTo( rr_edge.m_end );