Performance enhancement for pad drawing.

Fixes: lp:1843065
* https://bugs.launchpad.net/kicad/+bug/1843065
This commit is contained in:
Jeff Young 2019-09-09 13:44:41 +01:00
parent 7dc9beaf11
commit 8dd8740fa3
6 changed files with 172 additions and 202 deletions

View File

@ -131,7 +131,7 @@ void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
const VECTOR2I& a = path.CPoint( ii ); const VECTOR2I& a = path.CPoint( ii );
const VECTOR2I& b = path.CPoint( ii + 1 ); const VECTOR2I& b = path.CPoint( ii + 1 );
TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), TransformSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ),
wxPoint( b.x, b.y ), ARC_HIGH_DEF, aWidth ); wxPoint( b.x, b.y ), ARC_HIGH_DEF, aWidth );
} }
} }

View File

@ -59,8 +59,7 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aBuffer,
} }
void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius,
wxPoint aCenter, int aRadius,
int aError ) int aError )
{ {
wxPoint corner_position; wxPoint corner_position;
@ -84,9 +83,8 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer,
} }
void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd,
wxPoint aStart, wxPoint aEnd, int aWidth, int aWidth, int aError )
int aError )
{ {
// To build the polygonal shape outside the actual shape, we use a bigger // To build the polygonal shape outside the actual shape, we use a bigger
// radius to build rounded ends. // radius to build rounded ends.
@ -314,7 +312,7 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
} }
void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer,
wxPoint aStart, wxPoint aEnd, wxPoint aStart, wxPoint aEnd,
int aError, int aWidth ) int aError, int aWidth )
{ {
@ -414,13 +412,13 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer,
{ {
curr_end = arc_start; curr_end = arc_start;
RotatePoint( &curr_end, aCentre, -ii ); RotatePoint( &curr_end, aCentre, -ii );
TransformRoundedEndsSegmentToPolygon( aCornerBuffer, curr_start, curr_end, aError, TransformSegmentToPolygon( aCornerBuffer, curr_start, curr_end, aError,
aWidth ); aWidth );
curr_start = curr_end; curr_start = curr_end;
} }
if( curr_end != arc_end ) if( curr_end != arc_end )
TransformRoundedEndsSegmentToPolygon( aCornerBuffer, curr_end, arc_end, aError, aWidth ); TransformSegmentToPolygon( aCornerBuffer, curr_end, arc_end, aError, aWidth );
} }

View File

@ -528,8 +528,8 @@ void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
// enter outline as polygon: // enter outline as polygon:
for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
{ {
TransformRoundedEndsSegmentToPolygon( bufferOutline, TransformSegmentToPolygon( bufferOutline,
aCornerList[ii-1], aCornerList[ii], GetPlotterArcHighDef(), aWidth ); aCornerList[ ii - 1 ], aCornerList[ ii ], GetPlotterArcHighDef(), aWidth );
} }
// enter the initial polygon: // enter the initial polygon:
@ -615,8 +615,7 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int
{ {
std::vector<wxPoint> cornerList; std::vector<wxPoint> cornerList;
SHAPE_POLY_SET outlineBuffer; SHAPE_POLY_SET outlineBuffer;
TransformOvalClearanceToPolygon( outlineBuffer, TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef());
aStart, aEnd, aWidth, GetPlotterArcHighDef() );
const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline(0 ); const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline(0 );
for( int jj = 0; jj < path.PointCount(); jj++ ) for( int jj = 0; jj < path.PointCount(); jj++ )

View File

@ -63,8 +63,7 @@ enum RECT_CHAMFER_POSITIONS : int
* Note: the polygon is inside the circle, so if you want to have the polygon * 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 * outside the circle, you should give aRadius calculated with a correction factor
*/ */
void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius,
wxPoint aCenter, int aRadius,
int aError ); int aError );
@ -82,9 +81,8 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer,
* @param aWidth = the width of the segment * @param aWidth = the width of the segment
* @param aError = the IU allowed for error in approximation * @param aError = the IU allowed for error in approximation
*/ */
void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd,
wxPoint aStart, wxPoint aEnd, int aWidth, int aWidth, int aError );
int aError );
/** /**
@ -97,8 +95,8 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
* @param aSize = size of the of the round rect. * @param aSize = size of the of the round rect.
* @param aRotation = rotation of the of the round rect * @param aRotation = rotation of the of the round rect
*/ */
void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, const wxPoint& aPosition,
const wxPoint& aPosition, const wxSize& aSize, double aRotation ); const wxSize& aSize, double aRotation );
/** /**
@ -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 * 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 * outside the circle, you should give aStart and aEnd calculated with a correction factor
*/ */
void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd,
wxPoint aStart, wxPoint aEnd, int aError, int aWidth );
int aError,
int aWidth );
/** /**
@ -158,9 +154,8 @@ void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer,
* @param aError = the IU allowed for error in approximation * @param aError = the IU allowed for error in approximation
* @param aWidth = width (thickness) of the line * @param aWidth = width (thickness) of the line
*/ */
void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart,
wxPoint aCentre, wxPoint aStart, double aArcAngle, double aArcAngle, int aError, int aWidth );
int aError, int aWidth );
/** /**
* Function TransformRingToPolygon * Function TransformRingToPolygon
@ -172,8 +167,7 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer,
* @param aError = the IU allowed for error in approximation * @param aError = the IU allowed for error in approximation
* @param aWidth = width (thickness) of the ring * @param aWidth = width (thickness) of the ring
*/ */
void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius,
wxPoint aCentre, int aRadius,
int aError, int aWidth ); int aError, int aWidth );
#endif // CONVERT_BASIC_SHAPES_TO_POLYGON_H #endif // CONVERT_BASIC_SHAPES_TO_POLYGON_H

View File

@ -22,17 +22,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 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 <vector>
#include <fctsys.h> #include <fctsys.h>
#include <vector>
#include <bezier_curves.h> #include <bezier_curves.h>
#include <base_units.h> // for IU_PER_MM #include <base_units.h> // for IU_PER_MM
#include <gr_text.h> #include <gr_text.h>
@ -65,8 +56,8 @@ TSEGM_2_POLY_PRMS prms;
static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData ) static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData )
{ {
TSEGM_2_POLY_PRMS* prm = static_cast<TSEGM_2_POLY_PRMS*>( aData ); TSEGM_2_POLY_PRMS* prm = static_cast<TSEGM_2_POLY_PRMS*>( aData );
TransformRoundedEndsSegmentToPolygon( *prm->m_cornerBuffer, TransformSegmentToPolygon( *prm->m_cornerBuffer,
wxPoint( x0, y0), wxPoint( xf, yf ), wxPoint( x0, y0 ), wxPoint( xf, yf ),
prm->m_error, prm->m_textWidth ); prm->m_error, prm->m_textWidth );
} }
@ -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 * Generate shapes of graphic items (outlines) as polygons added to a buffer.
* aCornerBuffer = the buffer to store polygons * @aCornerBuffer = the buffer to store polygons
* aInflateValue = a value to inflate shapes * @aInflateValue = a value to inflate shapes
* aCircleToSegmentsCount = number of segments to approximate a circle * @aError = the maximum error to allow when approximating curves with segments
* aCorrectionFactor = the correction to apply to the circle radius * @aIncludeText = indicates footprint text items (reference, value, etc.) should be included
* to generate the polygon. * in the outline
* if aCorrectionFactor = 1.0, the polygon is inside the circle
* the radius of circle approximated by segments is
* initial radius * aCorrectionFactor
*/ */
void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, 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<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert std::vector<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert
EDGE_MODULE* outline;
for( auto item : GraphicalItems() ) for( auto item : GraphicalItems() )
{ {
@ -208,17 +197,18 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye
if( ( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer ) && text->IsVisible() ) if( ( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer ) && text->IsVisible() )
texts.push_back( text ); texts.push_back( text );
break;
} }
break;
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
outline = (EDGE_MODULE*) item; {
EDGE_MODULE* outline = (EDGE_MODULE*) item;
if( aLayer != UNDEFINED_LAYER && outline->GetLayer() != aLayer ) if( aLayer != UNDEFINED_LAYER && outline->GetLayer() != aLayer )
break; break;
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, 0, aError ); outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, 0, aError );
}
break; break;
default: default:
@ -238,9 +228,8 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye
prms.m_cornerBuffer = &aCornerBuffer; 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_textWidth = textmod->GetThickness() + ( 2 * aInflateValue );
prms.m_error = aError; prms.m_error = aError;
wxSize size = textmod->GetTextSize(); wxSize size = textmod->GetTextSize();
@ -257,10 +246,10 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye
} }
// Same as function TransformGraphicShapesWithClearanceToPolygonSet but // Same as function TransformGraphicShapesWithClearanceToPolygonSet but this only for text
// this only render text void MODULE::TransformGraphicTextWithClearanceToPolygonSet( PCB_LAYER_ID aLayer,
void MODULE::TransformGraphicTextWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError ) const int aInflateValue, int aError ) const
{ {
std::vector<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert std::vector<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert
@ -274,9 +263,8 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet(
if( text->GetLayer() == aLayer && text->IsVisible() ) if( text->GetLayer() == aLayer && text->IsVisible() )
texts.push_back( text ); texts.push_back( text );
break;
} }
break;
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
// This function does not render this // This function does not render this
@ -296,9 +284,8 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet(
prms.m_cornerBuffer = &aCornerBuffer; 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_textWidth = textmod->GetThickness() + ( 2 * aInflateValue );
prms.m_error = aError; prms.m_error = aError;
wxSize size = textmod->GetTextSize(); wxSize size = textmod->GetTextSize();
@ -315,8 +302,8 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet(
} }
void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aError ) const int aError ) const
{ {
if( GetFilledPolysList().IsEmpty() ) if( GetFilledPolysList().IsEmpty() )
return; return;
@ -338,16 +325,16 @@ void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet(
{ {
const VECTOR2I& a = path.CPoint( j ); const VECTOR2I& a = path.CPoint( j );
const VECTOR2I& b = path.CPoint( j + 1 ); const VECTOR2I& b = path.CPoint( j + 1 );
int width = GetMinThickness();
TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), TransformSegmentToPolygon( aCornerBuffer, (wxPoint) a, (wxPoint) b, maxError, width );
wxPoint( b.x, b.y ), maxError, GetMinThickness() );
} }
} }
} }
void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( SHAPE_POLY_SET* aCornerBuffer,
SHAPE_POLY_SET* aCornerBuffer, int aClearanceValue ) const int aClearanceValue ) const
{ {
if( GetText().Length() == 0 ) if( GetText().Length() == 0 )
return; return;
@ -367,29 +354,24 @@ void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon(
aCornerBuffer->NewOutline(); aCornerBuffer->NewOutline();
for( int ii = 0; ii < 4; ii++ ) for( wxPoint& corner : corners )
{ {
// Rotate polygon // Rotate polygon
RotatePoint( &corners[ii].x, &corners[ii].y, GetTextPos().x, GetTextPos().y, GetTextAngle() ); RotatePoint( &corner.x, &corner.y, GetTextPos().x, GetTextPos().y, GetTextAngle() );
aCornerBuffer->Append( corners[ii].x, corners[ii].y ); aCornerBuffer->Append( corner.x, corner.y );
} }
} }
/* Function TransformShapeWithClearanceToPolygonSet /**
* Convert the text shape to a set of polygons (one by segment) * Function TransformShapeWithClearanceToPolygonSet
* Used in filling zones calculations and 3D view * Convert the text shape to a set of polygons (one per segment).
* Circles and arcs are approximated by segments * @aCornerBuffer = SHAPE_POLY_SET to store the polygon corners
* aCornerBuffer = SHAPE_POLY_SET to store the polygon corners * @aClearanceValue = the clearance around the text
* aClearanceValue = the clearance around the text * @aError = the maximum error to allow when approximating curves
* 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)
*/ */
void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( int aClearanceValue, int aError ) const
SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError ) const
{ {
wxSize size = GetTextSize(); wxSize size = GetTextSize();
@ -424,36 +406,33 @@ void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet(
} }
void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const int aClearanceValue, int aError,
bool ignoreLineWidth ) const
{ {
// The full width of the lines to create: int width = ignoreLineWidth ? 0 : m_Width;
int linewidth = 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 // Creating a reliable clearance shape for circles and arcs is not so easy, due to
// the error created by segment approximation. // the error created by segment approximation.
// for a circle this is not so hard: create a polygon from a circle slightly bigger: // 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 // giving a shape with a suitable internal radius and external radius
// For an arc this is more tricky: TODO // For an arc this is more tricky: TODO
switch( m_Shape ) switch( m_Shape )
{ {
case S_CIRCLE: case S_CIRCLE:
TransformRingToPolygon( TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, width );
aCornerBuffer, GetCenter(), GetRadius(), aError, linewidth );
break; break;
case S_ARC: case S_ARC:
TransformArcToPolygon( TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, width );
aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, linewidth );
break; break;
case S_SEGMENT: case S_SEGMENT:
TransformOvalClearanceToPolygon( TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError );
aCornerBuffer, m_Start, m_End, linewidth, aError );
break; break;
case S_POLYGON: case S_POLYGON:
@ -472,23 +451,19 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon(
std::vector< wxPoint> poly; std::vector< wxPoint> poly;
poly = BuildPolyPointsList(); poly = BuildPolyPointsList();
for( unsigned ii = 0; ii < poly.size(); ii++ ) for( wxPoint& point : poly )
{ {
RotatePoint( &poly[ii], orientation ); RotatePoint( &point, orientation );
poly[ii] += offset; point += offset;
} }
// If the polygon is not filled, treat it as a closed set of lines // If the polygon is not filled, treat it as a closed set of lines
if( !IsPolygonFilled() ) if( !IsPolygonFilled() )
{ {
for( size_t ii = 1; ii < poly.size(); ii++ ) for( size_t ii = 1; ii < poly.size(); ii++ )
{ TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width, aError );
TransformOvalClearanceToPolygon( aCornerBuffer, poly[ii - 1], poly[ii],
linewidth, aError );
}
TransformOvalClearanceToPolygon( aCornerBuffer, poly.back(), poly.front(), TransformOvalToPolygon( aCornerBuffer, poly.back(), poly.front(), width, aError );
linewidth, aError );
break; break;
} }
@ -499,24 +474,19 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon(
// Insert the initial polygon: // Insert the initial polygon:
aCornerBuffer.NewOutline(); aCornerBuffer.NewOutline();
for( unsigned ii = 0; ii < poly.size(); ii++ ) for( wxPoint& point : poly )
aCornerBuffer.Append( poly[ii].x, poly[ii].y ); 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 ) pt1 = pt2;
{
TransformRoundedEndsSegmentToPolygon(
aCornerBuffer, corner1, corner2, aError, linewidth );
}
corner1 = corner2;
} }
} }
} }
@ -529,10 +499,10 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon(
std::vector< wxPoint> poly; std::vector< wxPoint> poly;
converter.GetPoly( poly, m_Width ); converter.GetPoly( poly, m_Width );
for( unsigned ii = 1; ii < poly.size(); ii++ ) if( width != 0 )
{ {
TransformRoundedEndsSegmentToPolygon( for( unsigned ii = 1; ii < poly.size(); ii++ )
aCornerBuffer, poly[ii - 1], poly[ii], aError, linewidth ); TransformSegmentToPolygon( aCornerBuffer, poly[ii-1], poly[ii], aError, width );
} }
} }
break; break;
@ -543,31 +513,34 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon(
} }
void TRACK::TransformShapeWithClearanceToPolygon( void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const int aClearanceValue, int aError,
bool ignoreLineWidth ) const
{ {
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." ); wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." );
int radius = ( m_Width / 2 ) + aClearanceValue;
switch( Type() ) switch( Type() )
{ {
case PCB_VIA_T: case PCB_VIA_T:
{ {
int radius = ( m_Width / 2 ) + aClearanceValue;
TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError ); TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError );
} }
break; break;
default: 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; break;
} }
} }
void D_PAD::TransformShapeWithClearanceToPolygon( void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const int aClearanceValue, int aError,
bool ignoreLineWidth ) const
{ {
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." ); 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 dx = (m_Size.x / 2) + aClearanceValue;
int dy = (m_Size.y / 2) + aClearanceValue; int dy = (m_Size.y / 2) + aClearanceValue;
wxPoint padShapePos = ShapePos(); /* Note: for pad having a shape offset, wxPoint padShapePos = ShapePos(); // Note: for pad having a shape offset,
* the pad position is NOT the shape position */ // the pad position is NOT the shape position
switch( GetShape() ) switch( GetShape() )
{ {
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
{
TransformCircleToPolygon( aCornerBuffer, padShapePos, dx, aError ); TransformCircleToPolygon( aCornerBuffer, padShapePos, dx, aError );
}
break; break;
case PAD_SHAPE_OVAL: case PAD_SHAPE_OVAL:
// An oval pad has the same shape as a segment with rounded ends
{ {
// An oval pad has the same shape as a segment with rounded ends
int width; int width;
wxPoint shape_offset; wxPoint shape_offset;
if( dy > dx ) // Oval pad X/Y ratio for choosing translation axis if( dy > dx ) // Oval pad X/Y ratio for choosing translation axis
{ {
shape_offset.y = dy - dx; shape_offset.y = dy - dx;
@ -609,7 +581,7 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
RotatePoint( &shape_offset, angle ); RotatePoint( &shape_offset, angle );
wxPoint start = padShapePos - shape_offset; wxPoint start = padShapePos - shape_offset;
wxPoint end = padShapePos + shape_offset; wxPoint end = padShapePos + shape_offset;
TransformOvalClearanceToPolygon( aCornerBuffer, start, end, width, aError ); TransformOvalToPolygon( aCornerBuffer, start, end, width, aError );
} }
break; break;
@ -622,18 +594,20 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
outline.NewOutline(); outline.NewOutline();
for( int ii = 0; ii < 4; ii++ ) for( wxPoint& corner : corners )
{ {
corners[ii] += padShapePos; corner += padShapePos;
outline.Append( corners[ii].x, corners[ii].y ); outline.Append( corner.x, corner.y );
} }
if( aClearanceValue )
{
int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
pad_min_seg_per_circle_count ); pad_min_seg_per_circle_count );
double correction = GetCircletoPolyCorrectionFactor( numSegs ); double correction = GetCircletoPolyCorrectionFactor( numSegs );
int clearance = KiROUND( aClearanceValue * correction );
int rounding_radius = KiROUND( aClearanceValue * correction ); outline.Inflate( clearance, numSegs );
outline.Inflate( rounding_radius, numSegs ); }
aCornerBuffer.Append( outline ); aCornerBuffer.Append( outline );
} }
@ -647,16 +621,16 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
pad_min_seg_per_circle_count ); pad_min_seg_per_circle_count );
double correction = GetCircletoPolyCorrectionFactor( numSegs ); double correction = GetCircletoPolyCorrectionFactor( numSegs );
int clearance = KiROUND( aClearanceValue * correction ); int clearance = KiROUND( aClearanceValue * correction );
int rounding_radius = KiROUND( radius * correction );
wxSize shapesize( m_Size ); wxSize shapesize( m_Size );
radius = KiROUND( radius * correction );
shapesize.x += clearance * 2; shapesize.x += clearance * 2;
shapesize.y += clearance * 2; shapesize.y += clearance * 2;
bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT; bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, radius,
rounding_radius, doChamfer ? GetChamferRectRatio() : 0.0, doChamfer ? GetChamferRectRatio() : 0.0,
doChamfer ? GetChamferPositions() : 0, aError ); doChamfer ? GetChamferPositions() : 0, aError );
aCornerBuffer.Append( outline ); aCornerBuffer.Append( outline );
@ -685,17 +659,13 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
/* /*
* Function BuildPadShapePolygon * Function BuildPadShapePolygon
* Build the Corner list of the polygonal shape, * Build the corner list of the polygonal shape, depending on shape, clearance and orientation
* depending on shape, extra size (clearance ...) pad and orientation * Note: for round & oval pads this function is equivalent to TransformShapeWithClearanceToPolygon,
* Note: for Round and oval pads this function is equivalent to * but not for other shapes
* TransformShapeWithClearanceToPolygon, but not for other shapes
*/ */
void D_PAD::BuildPadShapePolygon( void D_PAD::BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer, wxSize aInflateValue,
SHAPE_POLY_SET& aCornerBuffer, wxSize aInflateValue, int aError ) const 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() ) switch( GetShape() )
{ {
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
@ -717,23 +687,30 @@ void D_PAD::BuildPadShapePolygon(
case PAD_SHAPE_TRAPEZOID: case PAD_SHAPE_TRAPEZOID:
case PAD_SHAPE_RECT: case PAD_SHAPE_RECT:
aCornerBuffer.NewOutline();
BuildPadPolygon( corners, aInflateValue, m_Orient );
for( int ii = 0; ii < 4; ii++ )
{ {
corners[ii] += padShapePos; // Shift origin to position wxPoint corners[4];
aCornerBuffer.Append( corners[ii].x, corners[ii].y ); 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( wxPoint& corner : corners )
{
corner += padShapePos; // Shift origin to position
aCornerBuffer.Append( corner.x, corner.y );
}
}
break; break;
case PAD_SHAPE_CUSTOM: 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. // For a custom shape, that is in fact a polygon (with holes), we use only a single
// (different values for aInflateValue.x and aInflateValue.y has no sense for a custom pad) // inflate value (different values for X and Y have no definition for a custom pad).
TransformShapeWithClearanceToPolygon( int inflate = ( aInflateValue.x + aInflateValue.y ) / 2;
aCornerBuffer, ( aInflateValue.x + aInflateValue.y ) / 2 );
TransformShapeWithClearanceToPolygon( aCornerBuffer, inflate );
}
break; break;
} }
} }
@ -759,18 +736,20 @@ bool D_PAD::BuildPadDrillShapePolygon(
GetOblongDrillGeometry( start, end, width ); GetOblongDrillGeometry( start, end, width );
start += GetPosition();
end += GetPosition();
width += aInflateValue * 2; width += aInflateValue * 2;
TransformRoundedEndsSegmentToPolygon( TransformSegmentToPolygon( aCornerBuffer, start, end, aError, width );
aCornerBuffer, GetPosition() + start, GetPosition() + end, aError, width );
} }
return true; return true;
} }
void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const int aClearanceValue, int aError,
bool ignoreLineWidth ) const
{ {
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for zones." ); wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for zones." );

View File

@ -258,15 +258,15 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError )
for( unsigned ii = 1; ii < poly.size(); ii++ ) for( unsigned ii = 1; ii < poly.size(); ii++ )
{ {
TransformRoundedEndsSegmentToPolygon( TransformSegmentToPolygon(
aux_polyset, poly[ii - 1], poly[ii], aError, bshape.m_Thickness ); aux_polyset, poly[ ii - 1 ], poly[ ii ], aError, bshape.m_Thickness );
} }
break; break;
} }
case S_SEGMENT: // usual segment : line with rounded ends case S_SEGMENT: // usual segment : line with rounded ends
{ {
TransformRoundedEndsSegmentToPolygon( TransformSegmentToPolygon(
aux_polyset, bshape.m_Start, bshape.m_End, aError, bshape.m_Thickness ); aux_polyset, bshape.m_Start, bshape.m_End, aError, bshape.m_Thickness );
break; break;
} }