From 8dd8740fa367d633198ecd965b7abd79d200468f Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 9 Sep 2019 13:44:41 +0100 Subject: [PATCH] Performance enhancement for pad drawing. Fixes: lp:1843065 * https://bugs.launchpad.net/kicad/+bug/1843065 --- 3d-viewer/3d_canvas/create_layer_poly.cpp | 4 +- common/convert_basic_shapes_to_polygon.cpp | 20 +- common/plotters/DXF_plotter.cpp | 7 +- include/convert_basic_shapes_to_polygon.h | 38 +-- ...board_items_to_polygon_shape_transform.cpp | 299 ++++++++---------- pcbnew/pad_custom_shape_functions.cpp | 6 +- 6 files changed, 172 insertions(+), 202 deletions(-) diff --git a/3d-viewer/3d_canvas/create_layer_poly.cpp b/3d-viewer/3d_canvas/create_layer_poly.cpp index cb965b1137..132a4eab82 100644 --- a/3d-viewer/3d_canvas/create_layer_poly.cpp +++ b/3d-viewer/3d_canvas/create_layer_poly.cpp @@ -131,8 +131,8 @@ void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, const VECTOR2I& a = path.CPoint( ii ); const VECTOR2I& b = path.CPoint( ii + 1 ); - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), - wxPoint( b.x, b.y ), ARC_HIGH_DEF, aWidth ); + TransformSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), + wxPoint( b.x, b.y ), ARC_HIGH_DEF, aWidth ); } } diff --git a/common/convert_basic_shapes_to_polygon.cpp b/common/convert_basic_shapes_to_polygon.cpp index 518a0b25ce..5e9a9ca4b6 100644 --- a/common/convert_basic_shapes_to_polygon.cpp +++ b/common/convert_basic_shapes_to_polygon.cpp @@ -59,8 +59,7 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aBuffer, } -void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aCenter, int aRadius, +void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, int aError ) { wxPoint corner_position; @@ -84,9 +83,8 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, } -void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aStart, wxPoint aEnd, int aWidth, - int aError ) +void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, + int aWidth, int aError ) { // To build the polygonal shape outside the actual shape, we use a bigger // radius to build rounded ends. @@ -314,9 +312,9 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, } -void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aStart, wxPoint aEnd, - int aError, int aWidth ) +void TransformSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, + wxPoint aStart, wxPoint aEnd, + int aError, int aWidth ) { int radius = aWidth / 2; wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) @@ -414,13 +412,13 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, { curr_end = arc_start; RotatePoint( &curr_end, aCentre, -ii ); - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, curr_start, curr_end, aError, - aWidth ); + TransformSegmentToPolygon( aCornerBuffer, curr_start, curr_end, aError, + aWidth ); curr_start = curr_end; } if( curr_end != arc_end ) - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, curr_end, arc_end, aError, aWidth ); + TransformSegmentToPolygon( aCornerBuffer, curr_end, arc_end, aError, aWidth ); } diff --git a/common/plotters/DXF_plotter.cpp b/common/plotters/DXF_plotter.cpp index ffb31122ea..927acca80e 100644 --- a/common/plotters/DXF_plotter.cpp +++ b/common/plotters/DXF_plotter.cpp @@ -528,8 +528,8 @@ void DXF_PLOTTER::PlotPoly( const std::vector& aCornerList, // enter outline as polygon: for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) { - TransformRoundedEndsSegmentToPolygon( bufferOutline, - aCornerList[ii-1], aCornerList[ii], GetPlotterArcHighDef(), aWidth ); + TransformSegmentToPolygon( bufferOutline, + aCornerList[ ii - 1 ], aCornerList[ ii ], GetPlotterArcHighDef(), aWidth ); } // enter the initial polygon: @@ -615,8 +615,7 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int { std::vector cornerList; SHAPE_POLY_SET outlineBuffer; - TransformOvalClearanceToPolygon( outlineBuffer, - aStart, aEnd, aWidth, GetPlotterArcHighDef() ); + TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef()); const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline(0 ); for( int jj = 0; jj < path.PointCount(); jj++ ) diff --git a/include/convert_basic_shapes_to_polygon.h b/include/convert_basic_shapes_to_polygon.h index 5d6ac18ed2..76590a5e58 100644 --- a/include/convert_basic_shapes_to_polygon.h +++ b/include/convert_basic_shapes_to_polygon.h @@ -63,9 +63,8 @@ enum RECT_CHAMFER_POSITIONS : int * Note: the polygon is inside the circle, so if you want to have the polygon * outside the circle, you should give aRadius calculated with a correction factor */ -void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aCenter, int aRadius, - int aError ); +void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, + int aError ); /** @@ -82,9 +81,8 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aWidth = the width of the segment * @param aError = the IU allowed for error in approximation */ -void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aStart, wxPoint aEnd, int aWidth, - int aError ); +void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, + int aWidth, int aError ); /** @@ -97,8 +95,8 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aSize = size of the of the round rect. * @param aRotation = rotation of the of the round rect */ -void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, - const wxPoint& aPosition, const wxSize& aSize, double aRotation ); +void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, const wxPoint& aPosition, + const wxSize& aSize, double aRotation ); /** @@ -124,10 +122,10 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, * (must be a multiple of 4 becauseusually arcs are 90 deg. */ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, - const wxPoint& aPosition, const wxSize& aSize, - double aRotation, int aCornerRadius, - double aChamferRatio, int aChamferCorners, - int aApproxErrorMax, int aMinSegPerCircleCount = 16 ); + const wxPoint& aPosition, const wxSize& aSize, + double aRotation, int aCornerRadius, + double aChamferRatio, int aChamferCorners, + int aApproxErrorMax, int aMinSegPerCircleCount = 16 ); /** * Function TransformRoundedEndsSegmentToPolygon @@ -141,10 +139,8 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, * Note: the polygon is inside the arc ends, so if you want to have the polygon * outside the circle, you should give aStart and aEnd calculated with a correction factor */ -void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aStart, wxPoint aEnd, - int aError, - int aWidth ); +void TransformSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, + int aError, int aWidth ); /** @@ -158,9 +154,8 @@ void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aError = the IU allowed for error in approximation * @param aWidth = width (thickness) of the line */ -void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aCentre, wxPoint aStart, double aArcAngle, - int aError, int aWidth ); +void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart, + double aArcAngle, int aError, int aWidth ); /** * Function TransformRingToPolygon @@ -172,8 +167,7 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aError = the IU allowed for error in approximation * @param aWidth = width (thickness) of the ring */ -void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aCentre, int aRadius, - int aError, int aWidth ); +void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius, + int aError, int aWidth ); #endif // CONVERT_BASIC_SHAPES_TO_POLYGON_H diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 29268ba495..faf7a39b9a 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -22,17 +22,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -/*** - * @file board_items_to_polygon_shape_transform.cpp - * @brief function to convert shapes of items ( pads, tracks... ) to polygons - */ - -/* Function to convert pad and track shapes to polygons - * Used to fill zones areas and in 3D viewer - */ -#include - #include +#include #include #include // for IU_PER_MM #include @@ -65,9 +56,9 @@ TSEGM_2_POLY_PRMS prms; static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData ) { TSEGM_2_POLY_PRMS* prm = static_cast( aData ); - TransformRoundedEndsSegmentToPolygon( *prm->m_cornerBuffer, - wxPoint( x0, y0), wxPoint( xf, yf ), - prm->m_error, prm->m_textWidth ); + TransformSegmentToPolygon( *prm->m_cornerBuffer, + wxPoint( x0, y0 ), wxPoint( xf, yf ), + prm->m_error, prm->m_textWidth ); } @@ -95,7 +86,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ for( int ii = 0; ii < GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = GetArea( ii ); - PCB_LAYER_ID zonelayer = zone->GetLayer(); + PCB_LAYER_ID zonelayer = zone->GetLayer(); if( zonelayer == aLayer ) zone->TransformSolidAreasShapesToPolygonSet( aOutlines ); @@ -181,22 +172,20 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, } } -/* generate shapes of graphic items (outlines) on layer aLayer as polygons, - * and adds these polygons to aCornerBuffer - * aCornerBuffer = the buffer to store polygons - * aInflateValue = a value to inflate shapes - * aCircleToSegmentsCount = number of segments to approximate a circle - * aCorrectionFactor = the correction to apply to the circle radius - * to generate the polygon. - * if aCorrectionFactor = 1.0, the polygon is inside the circle - * the radius of circle approximated by segments is - * initial radius * aCorrectionFactor +/** + * Generate shapes of graphic items (outlines) as polygons added to a buffer. + * @aCornerBuffer = the buffer to store polygons + * @aInflateValue = a value to inflate shapes + * @aError = the maximum error to allow when approximating curves with segments + * @aIncludeText = indicates footprint text items (reference, value, etc.) should be included + * in the outline */ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError, bool aIncludeText ) const + SHAPE_POLY_SET& aCornerBuffer, + int aInflateValue, + int aError, bool aIncludeText ) const { std::vector texts; // List of TEXTE_MODULE to convert - EDGE_MODULE* outline; for( auto item : GraphicalItems() ) { @@ -208,17 +197,18 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye if( ( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer ) && text->IsVisible() ) texts.push_back( text ); - - break; } + break; case PCB_MODULE_EDGE_T: - outline = (EDGE_MODULE*) item; + { + EDGE_MODULE* outline = (EDGE_MODULE*) item; if( aLayer != UNDEFINED_LAYER && outline->GetLayer() != aLayer ) break; outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, 0, aError ); + } break; default: @@ -238,9 +228,8 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye prms.m_cornerBuffer = &aCornerBuffer; - for( unsigned ii = 0; ii < texts.size(); ii++ ) + for( TEXTE_MODULE* textmod : texts ) { - TEXTE_MODULE *textmod = texts[ii]; prms.m_textWidth = textmod->GetThickness() + ( 2 * aInflateValue ); prms.m_error = aError; wxSize size = textmod->GetTextSize(); @@ -257,10 +246,10 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye } -// Same as function TransformGraphicShapesWithClearanceToPolygonSet but -// this only render text -void MODULE::TransformGraphicTextWithClearanceToPolygonSet( - PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError ) const +// Same as function TransformGraphicShapesWithClearanceToPolygonSet but this only for text +void MODULE::TransformGraphicTextWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, + SHAPE_POLY_SET& aCornerBuffer, + int aInflateValue, int aError ) const { std::vector texts; // List of TEXTE_MODULE to convert @@ -269,21 +258,20 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet( switch( item->Type() ) { case PCB_MODULE_TEXT_T: - { - TEXTE_MODULE* text = static_cast( item ); + { + TEXTE_MODULE* text = static_cast( item ); - if( text->GetLayer() == aLayer && text->IsVisible() ) - texts.push_back( text ); - - break; - } + if( text->GetLayer() == aLayer && text->IsVisible() ) + texts.push_back( text ); + } + break; case PCB_MODULE_EDGE_T: - // This function does not render this - break; + // This function does not render this + break; - default: - break; + default: + break; } } @@ -296,9 +284,8 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet( prms.m_cornerBuffer = &aCornerBuffer; - for( unsigned ii = 0; ii < texts.size(); ii++ ) + for( TEXTE_MODULE* textmod : texts ) { - TEXTE_MODULE *textmod = texts[ii]; prms.m_textWidth = textmod->GetThickness() + ( 2 * aInflateValue ); prms.m_error = aError; wxSize size = textmod->GetTextSize(); @@ -315,8 +302,8 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet( } -void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( - SHAPE_POLY_SET& aCornerBuffer, int aError ) const +void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, + int aError ) const { if( GetFilledPolysList().IsEmpty() ) return; @@ -338,16 +325,16 @@ void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( { const VECTOR2I& a = path.CPoint( j ); const VECTOR2I& b = path.CPoint( j + 1 ); + int width = GetMinThickness(); - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), - wxPoint( b.x, b.y ), maxError, GetMinThickness() ); + TransformSegmentToPolygon( aCornerBuffer, (wxPoint) a, (wxPoint) b, maxError, width ); } } } -void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( - SHAPE_POLY_SET* aCornerBuffer, int aClearanceValue ) const +void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( SHAPE_POLY_SET* aCornerBuffer, + int aClearanceValue ) const { if( GetText().Length() == 0 ) return; @@ -367,29 +354,24 @@ void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( aCornerBuffer->NewOutline(); - for( int ii = 0; ii < 4; ii++ ) + for( wxPoint& corner : corners ) { // Rotate polygon - RotatePoint( &corners[ii].x, &corners[ii].y, GetTextPos().x, GetTextPos().y, GetTextAngle() ); - aCornerBuffer->Append( corners[ii].x, corners[ii].y ); + RotatePoint( &corner.x, &corner.y, GetTextPos().x, GetTextPos().y, GetTextAngle() ); + aCornerBuffer->Append( corner.x, corner.y ); } } -/* Function TransformShapeWithClearanceToPolygonSet - * Convert the text shape to a set of polygons (one by segment) - * Used in filling zones calculations and 3D view - * Circles and arcs are approximated by segments - * aCornerBuffer = SHAPE_POLY_SET to store the polygon corners - * aClearanceValue = the clearance around the text - * aCircleToSegmentsCount = the number of segments to approximate a circle - * aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) +/** + * Function TransformShapeWithClearanceToPolygonSet + * Convert the text shape to a set of polygons (one per segment). + * @aCornerBuffer = SHAPE_POLY_SET to store the polygon corners + * @aClearanceValue = the clearance around the text + * @aError = the maximum error to allow when approximating curves */ - -void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( - SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError ) const +void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, + int aClearanceValue, int aError ) const { wxSize size = GetTextSize(); @@ -424,36 +406,33 @@ void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( } -void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( - SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const +void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + int aClearanceValue, int aError, + bool ignoreLineWidth ) const { - // The full width of the lines to create: - int linewidth = ignoreLineWidth ? 0 : m_Width; + int width = ignoreLineWidth ? 0 : m_Width; - linewidth += 2 * aClearanceValue; + width += 2 * aClearanceValue; // Creating a reliable clearance shape for circles and arcs is not so easy, due to // the error created by segment approximation. // for a circle this is not so hard: create a polygon from a circle slightly bigger: - // thickness = linewidth + s_error_max, and radius = initial radius + s_error_max/2 + // thickness = width + s_error_max, and radius = initial radius + s_error_max/2 // giving a shape with a suitable internal radius and external radius // For an arc this is more tricky: TODO switch( m_Shape ) { case S_CIRCLE: - TransformRingToPolygon( - aCornerBuffer, GetCenter(), GetRadius(), aError, linewidth ); + TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, width ); break; case S_ARC: - TransformArcToPolygon( - aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, linewidth ); + TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, width ); break; case S_SEGMENT: - TransformOvalClearanceToPolygon( - aCornerBuffer, m_Start, m_End, linewidth, aError ); + TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); break; case S_POLYGON: @@ -472,23 +451,19 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( std::vector< wxPoint> poly; poly = BuildPolyPointsList(); - for( unsigned ii = 0; ii < poly.size(); ii++ ) + for( wxPoint& point : poly ) { - RotatePoint( &poly[ii], orientation ); - poly[ii] += offset; + RotatePoint( &point, orientation ); + point += offset; } // If the polygon is not filled, treat it as a closed set of lines if( !IsPolygonFilled() ) { for( size_t ii = 1; ii < poly.size(); ii++ ) - { - TransformOvalClearanceToPolygon( aCornerBuffer, poly[ii - 1], poly[ii], - linewidth, aError ); - } + TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width, aError ); - TransformOvalClearanceToPolygon( aCornerBuffer, poly.back(), poly.front(), - linewidth, aError ); + TransformOvalToPolygon( aCornerBuffer, poly.back(), poly.front(), width, aError ); break; } @@ -499,24 +474,19 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( // Insert the initial polygon: aCornerBuffer.NewOutline(); - for( unsigned ii = 0; ii < poly.size(); ii++ ) - aCornerBuffer.Append( poly[ii].x, poly[ii].y ); + for( wxPoint& point : poly ) + aCornerBuffer.Append( point.x, point.y ); - if( linewidth ) // Add thick outlines + if( width != 0 ) // Add thick outlines { - wxPoint corner1( poly[poly.size()-1] ); + wxPoint pt1( poly[ poly.size() - 1] ); - for( unsigned ii = 0; ii < poly.size(); ii++ ) + for( wxPoint pt2 : poly ) { - wxPoint corner2( poly[ii] ); + if( pt2 != pt1 ) + TransformSegmentToPolygon( aCornerBuffer, pt1, pt2, aError, width ); - if( corner2 != corner1 ) - { - TransformRoundedEndsSegmentToPolygon( - aCornerBuffer, corner1, corner2, aError, linewidth ); - } - - corner1 = corner2; + pt1 = pt2; } } } @@ -529,10 +499,10 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( std::vector< wxPoint> poly; converter.GetPoly( poly, m_Width ); - for( unsigned ii = 1; ii < poly.size(); ii++ ) + if( width != 0 ) { - TransformRoundedEndsSegmentToPolygon( - aCornerBuffer, poly[ii - 1], poly[ii], aError, linewidth ); + for( unsigned ii = 1; ii < poly.size(); ii++ ) + TransformSegmentToPolygon( aCornerBuffer, poly[ii-1], poly[ii], aError, width ); } } break; @@ -543,31 +513,34 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( } -void TRACK::TransformShapeWithClearanceToPolygon( - SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const +void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + int aClearanceValue, int aError, + bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." ); - int radius = ( m_Width / 2 ) + aClearanceValue; - switch( Type() ) { case PCB_VIA_T: { + int radius = ( m_Width / 2 ) + aClearanceValue; TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError ); } break; default: - TransformOvalClearanceToPolygon( aCornerBuffer, m_Start, m_End, - m_Width + ( 2 * aClearanceValue ), aError ); + { + int width = m_Width + ( 2 * aClearanceValue ); + TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); + } break; } } -void D_PAD::TransformShapeWithClearanceToPolygon( - SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const +void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + int aClearanceValue, int aError, + bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." ); @@ -579,22 +552,21 @@ void D_PAD::TransformShapeWithClearanceToPolygon( int dx = (m_Size.x / 2) + aClearanceValue; int dy = (m_Size.y / 2) + aClearanceValue; - wxPoint padShapePos = ShapePos(); /* Note: for pad having a shape offset, - * the pad position is NOT the shape position */ + wxPoint padShapePos = ShapePos(); // Note: for pad having a shape offset, + // the pad position is NOT the shape position switch( GetShape() ) { case PAD_SHAPE_CIRCLE: - { TransformCircleToPolygon( aCornerBuffer, padShapePos, dx, aError ); - } break; case PAD_SHAPE_OVAL: + { // An oval pad has the same shape as a segment with rounded ends - { - int width; + int width; wxPoint shape_offset; + if( dy > dx ) // Oval pad X/Y ratio for choosing translation axis { shape_offset.y = dy - dx; @@ -609,8 +581,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon( RotatePoint( &shape_offset, angle ); wxPoint start = padShapePos - shape_offset; wxPoint end = padShapePos + shape_offset; - TransformOvalClearanceToPolygon( aCornerBuffer, start, end, width, aError ); - } + TransformOvalToPolygon( aCornerBuffer, start, end, width, aError ); + } break; case PAD_SHAPE_TRAPEZOID: @@ -622,18 +594,20 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET outline; outline.NewOutline(); - for( int ii = 0; ii < 4; ii++ ) + for( wxPoint& corner : corners ) { - corners[ii] += padShapePos; - outline.Append( corners[ii].x, corners[ii].y ); + corner += padShapePos; + outline.Append( corner.x, corner.y ); } - int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), - pad_min_seg_per_circle_count ); - double correction = GetCircletoPolyCorrectionFactor( numSegs ); - - int rounding_radius = KiROUND( aClearanceValue * correction ); - outline.Inflate( rounding_radius, numSegs ); + if( aClearanceValue ) + { + int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), + pad_min_seg_per_circle_count ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + int clearance = KiROUND( aClearanceValue * correction ); + outline.Inflate( clearance, numSegs ); + } aCornerBuffer.Append( outline ); } @@ -647,17 +621,17 @@ void D_PAD::TransformShapeWithClearanceToPolygon( pad_min_seg_per_circle_count ); double correction = GetCircletoPolyCorrectionFactor( numSegs ); int clearance = KiROUND( aClearanceValue * correction ); - int rounding_radius = KiROUND( radius * correction ); wxSize shapesize( m_Size ); + radius = KiROUND( radius * correction ); shapesize.x += clearance * 2; shapesize.y += clearance * 2; bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT; SHAPE_POLY_SET outline; - TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, - rounding_radius, doChamfer ? GetChamferRectRatio() : 0.0, - doChamfer ? GetChamferPositions() : 0, aError ); + TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, radius, + doChamfer ? GetChamferRectRatio() : 0.0, + doChamfer ? GetChamferPositions() : 0, aError ); aCornerBuffer.Append( outline ); } @@ -685,17 +659,13 @@ void D_PAD::TransformShapeWithClearanceToPolygon( /* * Function BuildPadShapePolygon - * Build the Corner list of the polygonal shape, - * depending on shape, extra size (clearance ...) pad and orientation - * Note: for Round and oval pads this function is equivalent to - * TransformShapeWithClearanceToPolygon, but not for other shapes + * Build the corner list of the polygonal shape, depending on shape, clearance and orientation + * Note: for round & oval pads this function is equivalent to TransformShapeWithClearanceToPolygon, + * but not for other shapes */ -void D_PAD::BuildPadShapePolygon( - SHAPE_POLY_SET& aCornerBuffer, wxSize aInflateValue, int aError ) const +void D_PAD::BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer, wxSize aInflateValue, + int aError ) const { - wxPoint corners[4]; - wxPoint padShapePos = ShapePos(); /* Note: for pad having a shape offset, - * the pad position is NOT the shape position */ switch( GetShape() ) { case PAD_SHAPE_CIRCLE: @@ -717,23 +687,30 @@ void D_PAD::BuildPadShapePolygon( case PAD_SHAPE_TRAPEZOID: case PAD_SHAPE_RECT: + { + wxPoint corners[4]; + wxPoint padShapePos = ShapePos(); // Note: for pad having a shape offset, + // the pad position is NOT the shape position + aCornerBuffer.NewOutline(); - BuildPadPolygon( corners, aInflateValue, m_Orient ); - for( int ii = 0; ii < 4; ii++ ) - { - corners[ii] += padShapePos; // Shift origin to position - aCornerBuffer.Append( corners[ii].x, corners[ii].y ); - } + for( wxPoint& corner : corners ) + { + corner += padShapePos; // Shift origin to position + aCornerBuffer.Append( corner.x, corner.y ); + } + } break; case PAD_SHAPE_CUSTOM: - // for a custom shape, that is in fact a polygon (with holes), we can use only a inflate value. - // so use ( aInflateValue.x + aInflateValue.y ) / 2 as polygon inflate value. - // (different values for aInflateValue.x and aInflateValue.y has no sense for a custom pad) - TransformShapeWithClearanceToPolygon( - aCornerBuffer, ( aInflateValue.x + aInflateValue.y ) / 2 ); + { + // For a custom shape, that is in fact a polygon (with holes), we use only a single + // inflate value (different values for X and Y have no definition for a custom pad). + int inflate = ( aInflateValue.x + aInflateValue.y ) / 2; + + TransformShapeWithClearanceToPolygon( aCornerBuffer, inflate ); + } break; } } @@ -759,18 +736,20 @@ bool D_PAD::BuildPadDrillShapePolygon( GetOblongDrillGeometry( start, end, width ); + start += GetPosition(); + end += GetPosition(); width += aInflateValue * 2; - TransformRoundedEndsSegmentToPolygon( - aCornerBuffer, GetPosition() + start, GetPosition() + end, aError, width ); + TransformSegmentToPolygon( aCornerBuffer, start, end, aError, width ); } return true; } -void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( - SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const +void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + int aClearanceValue, int aError, + bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for zones." ); diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp index be6e2ee17c..b99c693523 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -258,15 +258,15 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) for( unsigned ii = 1; ii < poly.size(); ii++ ) { - TransformRoundedEndsSegmentToPolygon( - aux_polyset, poly[ii - 1], poly[ii], aError, bshape.m_Thickness ); + TransformSegmentToPolygon( + aux_polyset, poly[ ii - 1 ], poly[ ii ], aError, bshape.m_Thickness ); } break; } case S_SEGMENT: // usual segment : line with rounded ends { - TransformRoundedEndsSegmentToPolygon( + TransformSegmentToPolygon( aux_polyset, bshape.m_Start, bshape.m_End, aError, bshape.m_Thickness ); break; }