Pcbnew: add a new primitive pad shape: chamfered round rect pad.

Allows 0 to 4 chamfered corners, not only one.

A custom shape allow this kind of shape. However because it is a primitive,
it is easier to edit and it support thermal reliefs.
This commit is contained in:
jean-pierre charras 2018-08-29 09:13:07 +02:00
parent d25d62295a
commit d259459a14
27 changed files with 11700 additions and 9119 deletions

View File

@ -491,6 +491,25 @@ void CINFO3D_VISU::createNewPadWithClearance( const D_PAD* aPad,
} }
break; break;
case PAD_SHAPE_CHAMFERED_RECT:
{
wxSize shapesize( aPad->GetSize() );
shapesize.x += aClearanceValue.x * 2;
shapesize.y += aClearanceValue.y * 2;
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
int corner_radius = aPad->GetRoundRectCornerRadius( shapesize );
TransformRoundChamferedRectToPolygon( polyList, PadShapePos, shapesize, aPad->GetOrientation(),
corner_radius, aPad->GetChamferRectRatio(),
aPad->GetChamferPositions(), 32 );
// Add the PAD polygon
Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, m_biuTo3Dunits, *aPad );
}
break;
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
{ {
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
@ -575,6 +594,7 @@ void CINFO3D_VISU::createNewPad( const D_PAD* aPad,
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
case PAD_SHAPE_OVAL: case PAD_SHAPE_OVAL:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
createNewPadWithClearance( aPad, aDstContainer, aInflateValue ); createNewPadWithClearance( aPad, aDstContainer, aInflateValue );
break; break;

View File

@ -52,6 +52,7 @@ void CINFO3D_VISU::buildPadShapePolygon( const D_PAD* aPad,
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
case PAD_SHAPE_OVAL: case PAD_SHAPE_OVAL:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
{ {
// We are using TransformShapeWithClearanceToPolygon to build the shape. // We are using TransformShapeWithClearanceToPolygon to build the shape.
// Currently, this method uses only the same inflate value for X and Y dirs. // Currently, this method uses only the same inflate value for X and Y dirs.

View File

@ -207,24 +207,19 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius,
aCenters[ii] += aPosition; aCenters[ii] += aPosition;
} }
/**
* Function TransformRoundRectToPolygon void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
* convert a rectangle with rounded corners to a polygon
* Convert arcs to multiple straight lines
* @param aCornerBuffer = a buffer to store the polygon
* @param aPosition = the coordinate of the center of the rectangle
* @param aSize = the size of the rectangle
* @param aCornerRadius = radius of rounded corners
* @param aRotation = rotation in 0.1 degrees of the rectangle
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
*/
void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
const wxPoint& aPosition, const wxSize& aSize, const wxPoint& aPosition, const wxSize& aSize,
double aRotation, int aCornerRadius, double aRotation, int aCornerRadius,
double aChamferRatio, int aChamferCorners,
int aCircleToSegmentsCount ) int aCircleToSegmentsCount )
{ {
// Build the basic shape in orientation 0.0, position 0,0 for chamfered corners
// or in actual position/orientation for round rect only
wxPoint corners[4]; wxPoint corners[4];
GetRoundRectCornerCenters( corners, aCornerRadius, aPosition, aSize, aRotation ); GetRoundRectCornerCenters( corners, aCornerRadius,
aChamferCorners ? wxPoint( 0, 0 ) : aPosition,
aSize, aChamferCorners ? 0.0 : aRotation );
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
outline.NewOutline(); outline.NewOutline();
@ -234,6 +229,68 @@ void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
outline.Inflate( aCornerRadius, aCircleToSegmentsCount ); outline.Inflate( aCornerRadius, aCircleToSegmentsCount );
if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer
{
// Add the outline:
aCornerBuffer.Append( outline );
return;
}
// Now we have the round rect outline, in position 0,0 orientation 0.0.
// Chamfer the corner(s).
int chamfer_value = aChamferRatio * std::min( aSize.x, aSize.y );
SHAPE_POLY_SET chamfered_corner; // corner shape for the current corner to chamfer
int corner_id[4] =
{
RECT_CHAMFER_TOP_LEFT, RECT_CHAMFER_TOP_RIGHT,
RECT_CHAMFER_BOTTOM_LEFT, RECT_CHAMFER_BOTTOM_RIGHT
};
// Depending on the corner position, signX[] and signY[] give the sign of chamfer
// coordinates relative to the corner position
// The first corner is the top left corner, then top right, bottom left and bottom right
int signX[4] = {1, -1, 1,-1 };
int signY[4] = {1, 1, -1,-1 };
for( int ii = 0; ii < 4; ii++ )
{
if( (corner_id[ii] & aChamferCorners) == 0 )
continue;
VECTOR2I corner_pos( -signX[ii]*aSize.x/2, -signY[ii]*aSize.y/2 );
if( aCornerRadius )
{
// We recreate a rectangular area covering the full rounded corner (max size = aSize/2)
// to rebuild the corner before chamfering, to be sure the rounded corner shape does not
// overlap the chamfered corner shape:
chamfered_corner.RemoveAllContours();
chamfered_corner.NewOutline();
chamfered_corner.Append( 0, 0 );
chamfered_corner.Append( 0, signY[ii]*aSize.y/2 );
chamfered_corner.Append( signX[ii]*aSize.x/2, signY[ii]*aSize.y/2 );
chamfered_corner.Append( signX[ii]*aSize.x/2, 0 );
chamfered_corner.Move( corner_pos );
outline.BooleanAdd( chamfered_corner, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
}
// Now chamfer this corner
chamfered_corner.RemoveAllContours();
chamfered_corner.NewOutline();
chamfered_corner.Append( 0, 0 );
chamfered_corner.Append( 0, signY[ii]*chamfer_value );
chamfered_corner.Append( signX[ii]*chamfer_value, 0 );
chamfered_corner.Move( corner_pos );
outline.BooleanSubtract( chamfered_corner, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
}
// Rotate and move the outline:
if( aRotation != 0.0 )
outline.Rotate( DECIDEG2RAD( -aRotation ), VECTOR2I( 0, 0 ) );
outline.Move( VECTOR2I( aPosition ) );
// Add the outline: // Add the outline:
aCornerBuffer.Append( outline ); aCornerBuffer.Append( outline );
} }

View File

@ -44,8 +44,11 @@ blind
blind_buried_vias_allowed blind_buried_vias_allowed
bold bold
bottom bottom
bottom_left
bottom_right
center center
chamfer chamfer
chamfer_ratio
circle circle
clearance clearance
comment comment
@ -176,6 +179,8 @@ thermal_gap
thermal_bridge_width thermal_bridge_width
thickness thickness
top top
top_left
top_right
trace_width trace_width
tracks tracks
trace_min trace_min

View File

@ -747,8 +747,8 @@ void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
const int segmentToCircleCount = 64; const int segmentToCircleCount = 64;
TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
aCornerRadius, segmentToCircleCount ); aCornerRadius, 0.0, 0, segmentToCircleCount );
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundRectToPolygon creates only one convex polygon
SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );

View File

@ -842,8 +842,8 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
// TODO: use Aperture macro and flash it // TODO: use Aperture macro and flash it
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
const int segmentToCircleCount = 64; const int segmentToCircleCount = 64;
TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
aCornerRadius, segmentToCircleCount ); aCornerRadius, 0.0, 0, segmentToCircleCount );
if( aTraceMode != FILLED ) if( aTraceMode != FILLED )
outline.Inflate( -GetCurrentLineWidth()/2, 16 ); outline.Inflate( -GetCurrentLineWidth()/2, 16 );

View File

@ -642,8 +642,8 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz
aCornerRadius = std::min( aCornerRadius, std::min( size.x, size.y ) /2 ); aCornerRadius = std::min( aCornerRadius, std::min( size.x, size.y ) /2 );
} }
TransformRoundRectToPolygon( outline, aPadPos, size, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient,
aCornerRadius, segmentToCircleCount ); aCornerRadius, 0.0, 0, segmentToCircleCount );
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundRectToPolygon creates only one convex polygon
std::vector< wxPoint > cornerList; std::vector< wxPoint > cornerList;

View File

@ -201,8 +201,8 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
const int segmentToCircleCount = 64; const int segmentToCircleCount = 64;
TransformRoundRectToPolygon( outline, aPadPos, size, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient,
aCornerRadius, segmentToCircleCount ); aCornerRadius, 0.0, 0, segmentToCircleCount );
std::vector< wxPoint > cornerList; std::vector< wxPoint > cornerList;
cornerList.reserve( segmentToCircleCount + 5 ); cornerList.reserve( segmentToCircleCount + 5 );

View File

@ -36,6 +36,21 @@
#include <macros.h> #include <macros.h>
#include <geometry/shape_poly_set.h> #include <geometry/shape_poly_set.h>
// The chamfer positions of chamfered rect shape.
// the position is relative to a pad with orientation = 0
// we can have 1 to 4 chamfered corners (0 corner = roundrect)
// The position list is the OR of corner to chamfer
enum RECT_CHAMFER_POSITIONS
{
RECT_NO_CHAMFER = 0,
RECT_CHAMFER_TOP_LEFT = 1,
RECT_CHAMFER_TOP_RIGHT = 2,
RECT_CHAMFER_BOTTOM_LEFT = 4,
RECT_CHAMFER_BOTTOM_RIGHT = 8,
};
/** /**
* Function TransformCircleToPolygon * Function TransformCircleToPolygon
* convert a circle to a polygon, using multiple straight lines * convert a circle to a polygon, using multiple straight lines
@ -86,20 +101,29 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius,
const wxPoint& aPosition, const wxSize& aSize, double aRotation ); const wxPoint& aPosition, const wxSize& aSize, double aRotation );
/** /**
* Function TransformRoundRectToPolygon * convert a rectangle with rounded corners and/or chamfered corners to a polygon
* convert a rectangle with rounded corners to a polygon * Convert rounded corners arcs to multiple straight lines
* Convert arcs to multiple straight lines
* @param aCornerBuffer = a buffer to store the polygon * @param aCornerBuffer = a buffer to store the polygon
* @param aPosition = the coordinate of the center of the rectangle * @param aPosition = the coordinate of the center of the rectangle
* @param aSize = the size of the rectangle * @param aSize = the size of the rectangle
* @param aCornerRadius = radius of rounded corners * @param aCornerRadius = radius of rounded corners (can be 0)
* @param aRotation = rotation in 0.1 degrees of the rectangle * @param aRotation = rotation in 0.1 degrees of the rectangle
* @param aChamferRatio = ratio between smaller rect size and chamfer value
* @param aChamferCorners = identifier of the corners to chamfer:
* 0 = no chamfer
* 1 = TOP_LEFT
* 2 = TOP_RIGHT
* 4 = BOTTOM_LEFT
* 8 = BOTTOM_RIGHT
* One can have more than one chamfered corner by ORing the corner identifers
* @param aCircleToSegmentsCount = the number of segments to approximate a circle * @param aCircleToSegmentsCount = the number of segments to approximate a circle
*/ */
void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
const wxPoint& aPosition, const wxSize& aSize, const wxPoint& aPosition, const wxSize& aSize,
double aRotation, int aCornerRadius, double aRotation, int aCornerRadius,
double aChamferRatio, int aChamferCorners,
int aCircleToSegmentsCount ); int aCircleToSegmentsCount );
/** /**

View File

@ -35,6 +35,7 @@ enum PAD_SHAPE_T
PAD_SHAPE_OVAL, PAD_SHAPE_OVAL,
PAD_SHAPE_TRAPEZOID, PAD_SHAPE_TRAPEZOID,
PAD_SHAPE_ROUNDRECT, PAD_SHAPE_ROUNDRECT,
PAD_SHAPE_CHAMFERED_RECT, // Rectangle with a champered corner ( and with rounded other corners)
PAD_SHAPE_CUSTOM // A shape defined by user, using a set of basic shapes PAD_SHAPE_CUSTOM // A shape defined by user, using a set of basic shapes
// (thick segments, circles, arcs, polygons // (thick segments, circles, arcs, polygons
}; };

View File

@ -767,18 +767,22 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
} }
break; break;
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
int pad_radius = GetRoundRectCornerRadius();
int clearance = int( aClearanceValue * aCorrectionFactor ); int clearance = int( aClearanceValue * aCorrectionFactor );
int rounding_radius = pad_radius + clearance; int rounding_radius = GetRoundRectCornerRadius() + clearance;
wxSize shapesize( m_Size ); wxSize shapesize( m_Size );
shapesize.x += clearance*2; shapesize.x += clearance*2;
shapesize.y += clearance*2; shapesize.y += clearance*2;
bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
TransformRoundRectToPolygon( outline, padShapePos, shapesize, angle, TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle,
rounding_radius, aCircleToSegmentsCount ); rounding_radius,
doChamfer ? GetChamferRectRatio() : 0.0,
doChamfer ? GetChamferPositions() : 0,
aCircleToSegmentsCount );
aCornerBuffer.Append( outline ); aCornerBuffer.Append( outline );
} }
@ -819,6 +823,7 @@ void D_PAD::BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer,
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
case PAD_SHAPE_OVAL: case PAD_SHAPE_OVAL:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
{ {
// We are using TransformShapeWithClearanceToPolygon to build the shape. // We are using TransformShapeWithClearanceToPolygon to build the shape.
// Currently, this method uses only the same inflate value for X and Y dirs. // Currently, this method uses only the same inflate value for X and Y dirs.
@ -1172,7 +1177,8 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer,
} }
break; break;
case PAD_SHAPE_ROUNDRECT: // thermal shape is the same for round rect and rect. case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: // thermal shape is the same for rectangular shapes.
case PAD_SHAPE_RECT: case PAD_SHAPE_RECT:
{ {
/* we create 4 copper holes and put them in position 1, 2, 3 and 4 /* we create 4 copper holes and put them in position 1, 2, 3 and 4

View File

@ -79,6 +79,9 @@ D_PAD::D_PAD( MODULE* parent ) :
m_LocalSolderPasteMarginRatio = 0.0; m_LocalSolderPasteMarginRatio = 0.0;
// Parameters for round rect only: // Parameters for round rect only:
m_padRoundRectRadiusScale = 0.25; // from IPC-7351C standard m_padRoundRectRadiusScale = 0.25; // from IPC-7351C standard
// Parameters for chamfered rect only:
m_padChamferRectScale = 0.2; // Size of chamfer: ratio of smallest of X,Y size
m_chamferPositions = RECT_NO_CHAMFER; // No chamfered corner
m_ZoneConnection = PAD_ZONE_CONN_INHERITED; // Use parent setting by default m_ZoneConnection = PAD_ZONE_CONN_INHERITED; // Use parent setting by default
m_ThermalWidth = 0; // Use parent setting by default m_ThermalWidth = 0; // Use parent setting by default
@ -169,6 +172,14 @@ int D_PAD::boundingRadius() const
radius += 1 + KiROUND( EuclideanNorm( wxSize( x - radius, y - radius ))); radius += 1 + KiROUND( EuclideanNorm( wxSize( x - radius, y - radius )));
break; break;
case PAD_SHAPE_CHAMFERED_RECT:
radius = GetRoundRectCornerRadius();
x = m_Size.x >> 1;
y = m_Size.y >> 1;
radius += 1 + KiROUND( EuclideanNorm( wxSize( x - radius, y - radius )));
// TODO: modify radius if the chamfer is smaller than corner radius
break;
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
radius = 0; radius = 0;
@ -293,6 +304,7 @@ const EDA_RECT D_PAD::GetBoundingBox() const
case PAD_SHAPE_RECT: case PAD_SHAPE_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
// Use two opposite corners and track their rotation // Use two opposite corners and track their rotation
// (use symmetry for other points) // (use symmetry for other points)
quadrant1.x = m_Size.x/2; quadrant1.x = m_Size.x/2;
@ -919,13 +931,19 @@ bool D_PAD::HitTest( const wxPoint& aPosition ) const
break; break;
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
{ {
// Check for hit in polygon // Check for hit in polygon
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
const int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; const int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
TransformRoundRectToPolygon( outline, wxPoint(0,0), GetSize(), m_Orient, bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
GetRoundRectCornerRadius(), segmentToCircleCount );
TransformRoundChamferedRectToPolygon( outline, wxPoint(0,0), GetSize(), m_Orient,
GetRoundRectCornerRadius(),
doChamfer ? GetChamferRectRatio() : 0.0,
doChamfer ? GetChamferPositions() : 0,
segmentToCircleCount );
const SHAPE_LINE_CHAIN &poly = outline.COutline( 0 ); const SHAPE_LINE_CHAIN &poly = outline.COutline( 0 );
return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta ); return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta );
@ -978,6 +996,7 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con
return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() ); return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() );
case PAD_SHAPE_RECT: case PAD_SHAPE_RECT:
case PAD_SHAPE_CHAMFERED_RECT: // TODO use a finer shape analysis
shapeRect.SetOrigin( shapePos ); shapeRect.SetOrigin( shapePos );
shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 ); shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 );
return arect.Intersects( shapeRect, m_Orient ); return arect.Intersects( shapeRect, m_Orient );
@ -1082,8 +1101,6 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con
* b) Test intersection of vertical rect * b) Test intersection of vertical rect
* c) Test intersection of each corner * c) Test intersection of each corner
*/ */
r = GetRoundRectCornerRadius(); r = GetRoundRectCornerRadius();
/* Test A - intersection of horizontal rect */ /* Test A - intersection of horizontal rect */
@ -1224,6 +1241,9 @@ wxString D_PAD::ShowPadShape() const
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
return _( "Roundrect" ); return _( "Roundrect" );
case PAD_SHAPE_CHAMFERED_RECT:
return _( "Chamferedrect" );
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
return _( "CustomShape" ); return _( "CustomShape" );

View File

@ -658,6 +658,48 @@ public:
m_padRoundRectRadiusScale = std::min( aRadiusScale, 0.5 ); m_padRoundRectRadiusScale = std::min( aRadiusScale, 0.5 );
} }
/**
* has meaning only for chamfered rect pads
* @return the ratio between the smaller Y or Y size and the radius
* of the rounded corners.
* Cannot be > 0.5
*/
double GetChamferRectRatio() const
{
return m_padChamferRectScale;
}
/**
* has meaning only for chamfered rect pads
* Set the ratio between the smaller Y or Y size and the radius
* of the rounded corners.
* Cannot be < 0.5 and obviously must be > 0
*/
void SetChamferRectRatio( double aChamferScale )
{
if( aChamferScale < 0.0 )
aChamferScale = 0.0;
m_padChamferRectScale = std::min( aChamferScale, 0.5 );
}
/**
* has meaning only for chamfered rect pads
* @return the position of the chamfer for a 0 orientation
*/
int GetChamferPositions() const { return m_chamferPositions; }
/**
* has meaning only for chamfered rect pads
* set the position of the chamfer for a 0 orientation, one of
* PAD_CHAMFER_TOP_LEFT, PAD_CHAMFER_TOP_RIGHT,
* PAD_CHAMFER_BOTTOM_LEFT, PAD_CHAMFER_BOTTOM_RIGHT
*/
void SetChamferPositions( int aChamferPositions )
{
m_chamferPositions = aChamferPositions;
}
/** /**
* Function GetSubRatsnest * Function GetSubRatsnest
* @return int - the netcode * @return int - the netcode
@ -835,6 +877,9 @@ private: // Private variable members:
double m_padRoundRectRadiusScale; ///< scaling factor from smallest m_Size coord double m_padRoundRectRadiusScale; ///< scaling factor from smallest m_Size coord
///< to corner radius, default 0.25 ///< to corner radius, default 0.25
double m_padChamferRectScale; ///< scaling factor from smallest m_Size coord
///< to chamfer value, default 0.25
int m_chamferPositions; ///< the positions of the chamfered position for a 0 orientation
PAD_SHAPE_T m_anchorPadShape; ///< for custom shaped pads: shape of pad anchor, PAD_SHAPE_T m_anchorPadShape; ///< for custom shaped pads: shape of pad anchor,
///< PAD_SHAPE_RECT, PAD_SHAPE_CIRCLE ///< PAD_SHAPE_RECT, PAD_SHAPE_CIRCLE

View File

@ -43,9 +43,13 @@
#include <pcb_painter.h> #include <pcb_painter.h>
#include <widgets/net_selector.h> #include <widgets/net_selector.h>
#include <dialog_pad_properties.h>
#include <dialog_pad_properties.h> #include <dialog_pad_properties.h>
#include <html_messagebox.h> #include <html_messagebox.h>
#include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
// list of pad shapes, ordered like the pad shape wxChoice in dialog. // list of pad shapes, ordered like the pad shape wxChoice in dialog.
static PAD_SHAPE_T code_shape[] = static PAD_SHAPE_T code_shape[] =
@ -55,6 +59,7 @@ static PAD_SHAPE_T code_shape[] =
PAD_SHAPE_RECT, PAD_SHAPE_RECT,
PAD_SHAPE_TRAPEZOID, PAD_SHAPE_TRAPEZOID,
PAD_SHAPE_ROUNDRECT, PAD_SHAPE_ROUNDRECT,
PAD_SHAPE_CHAMFERED_RECT,
PAD_SHAPE_CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR PAD_SHAPE_CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
PAD_SHAPE_CUSTOM // choice = PAD_SHAPE_CUSTOM_RECT_ANCHOR PAD_SHAPE_CUSTOM // choice = PAD_SHAPE_CUSTOM_RECT_ANCHOR
}; };
@ -68,6 +73,7 @@ enum CODE_CHOICE
CHOICE_SHAPE_RECT, CHOICE_SHAPE_RECT,
CHOICE_SHAPE_TRAPEZOID, CHOICE_SHAPE_TRAPEZOID,
CHOICE_SHAPE_ROUNDRECT, CHOICE_SHAPE_ROUNDRECT,
CHOICE_SHAPE_CHAMFERED_RECT,
CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR, CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR,
CHOICE_SHAPE_CUSTOM_RECT_ANCHOR CHOICE_SHAPE_CUSTOM_RECT_ANCHOR
}; };
@ -452,11 +458,15 @@ void DIALOG_PAD_PROPERTIES::updateRoundRectCornerValues()
{ {
// Note: use m_tcCornerSizeRatio->ChangeValue() to avoid generating a wxEVT_TEXT event // Note: use m_tcCornerSizeRatio->ChangeValue() to avoid generating a wxEVT_TEXT event
if( m_dummyPad->GetShape() == PAD_SHAPE_ROUNDRECT ) if( m_dummyPad->GetShape() == PAD_SHAPE_ROUNDRECT ||
m_dummyPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
{ {
auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 ); auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
m_tcCornerSizeRatio->ChangeValue( ratio ); m_tcCornerSizeRatio->ChangeValue( ratio );
m_cornerRadius.SetValue( m_dummyPad->GetRoundRectCornerRadius() ); m_cornerRadius.SetValue( m_dummyPad->GetRoundRectCornerRadius() );
ratio = wxString::Format( "%.1f", m_dummyPad->GetChamferRectRatio() * 100 );
m_tcChamferRatio->ChangeValue( ratio );
} }
else if( m_dummyPad->GetShape() == PAD_SHAPE_RECT ) else if( m_dummyPad->GetShape() == PAD_SHAPE_RECT )
{ {
@ -473,7 +483,8 @@ void DIALOG_PAD_PROPERTIES::updateRoundRectCornerValues()
void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event ) void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
{ {
if( m_dummyPad->GetShape() != PAD_SHAPE_ROUNDRECT ) if( m_dummyPad->GetShape() != PAD_SHAPE_ROUNDRECT &&
m_dummyPad->GetShape() != PAD_SHAPE_CHAMFERED_RECT )
return; return;
wxString value = m_tcCornerRadius->GetValue(); wxString value = m_tcCornerRadius->GetValue();
@ -499,27 +510,55 @@ void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event ) void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event )
{ {
if( m_dummyPad->GetShape() != PAD_SHAPE_ROUNDRECT ) if( m_dummyPad->GetShape() != PAD_SHAPE_ROUNDRECT &&
m_dummyPad->GetShape() != PAD_SHAPE_CHAMFERED_RECT )
return; return;
wxString value = m_tcCornerSizeRatio->GetValue(); wxString value = m_tcCornerSizeRatio->GetValue();
double rrRadiusRatioPercent; double ratioPercent;
if( value.ToDouble( &rrRadiusRatioPercent ) ) bool asChanged = false;
if( value.ToDouble( &ratioPercent ) )
{ {
// Clamp rrRadiusRatioPercent to acceptable value (0.0 to 50.0) // Clamp ratioPercent to acceptable value (0.0 to 50.0)
if( rrRadiusRatioPercent < 0.0 ) if( ratioPercent < 0.0 )
{ {
rrRadiusRatioPercent = 0.0; ratioPercent = 0.0;
m_tcCornerSizeRatio->ChangeValue( "0.0" ); m_tcCornerSizeRatio->ChangeValue( "0.0" );
} }
if( rrRadiusRatioPercent > 50.0 ) if( ratioPercent > 50.0 )
{ {
rrRadiusRatioPercent = 0.5; ratioPercent = 0.5;
m_tcCornerSizeRatio->ChangeValue( "50.0" ); m_tcCornerSizeRatio->ChangeValue( "50.0" );
} }
asChanged = true;
}
value = m_tcChamferRatio->GetValue();
if( value.ToDouble( &ratioPercent ) )
{
// Clamp ratioPercent to acceptable value (0.0 to 50.0)
if( ratioPercent < 0.0 )
{
ratioPercent = 0.0;
m_tcChamferRatio->ChangeValue( "0.0" );
}
if( ratioPercent > 50.0 )
{
ratioPercent = 0.5;
m_tcChamferRatio->ChangeValue( "50.0" );
}
asChanged = true;
}
if( asChanged )
{
transferDataToPad( m_dummyPad ); transferDataToPad( m_dummyPad );
m_cornerRadius.ChangeValue( m_dummyPad->GetRoundRectCornerRadius() ); m_cornerRadius.ChangeValue( m_dummyPad->GetRoundRectCornerRadius() );
redraw(); redraw();
@ -705,6 +744,7 @@ void DIALOG_PAD_PROPERTIES::initValues()
case PAD_SHAPE_RECT: m_PadShape->SetSelection( CHOICE_SHAPE_RECT ); break; case PAD_SHAPE_RECT: m_PadShape->SetSelection( CHOICE_SHAPE_RECT ); break;
case PAD_SHAPE_TRAPEZOID: m_PadShape->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break; case PAD_SHAPE_TRAPEZOID: m_PadShape->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
case PAD_SHAPE_ROUNDRECT: m_PadShape->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break; case PAD_SHAPE_ROUNDRECT: m_PadShape->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
case PAD_SHAPE_CHAMFERED_RECT: m_PadShape->SetSelection( CHOICE_SHAPE_CHAMFERED_RECT ); break;
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
if( m_dummyPad->GetAnchorPadShape() == PAD_SHAPE_RECT ) if( m_dummyPad->GetAnchorPadShape() == PAD_SHAPE_RECT )
@ -714,6 +754,12 @@ void DIALOG_PAD_PROPERTIES::initValues()
break; break;
} }
m_cbTopLeft->SetValue( (m_dummyPad->GetChamferPositions() & RECT_CHAMFER_TOP_LEFT) );
m_cbTopRight->SetValue( (m_dummyPad->GetChamferPositions() & RECT_CHAMFER_TOP_RIGHT) );
m_cbBottomLeft->SetValue( (m_dummyPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_LEFT) );
m_cbBottomRight->SetValue( (m_dummyPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_RIGHT) );
enablePrimitivePage( PAD_SHAPE_CUSTOM == m_dummyPad->GetShape() ); enablePrimitivePage( PAD_SHAPE_CUSTOM == m_dummyPad->GetShape() );
// Type of pad selection // Type of pad selection
@ -866,6 +912,7 @@ void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
} }
void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event ) void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
{ {
bool is_custom = false; bool is_custom = false;
@ -909,6 +956,7 @@ void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
break; break;
case CHOICE_SHAPE_ROUNDRECT: case CHOICE_SHAPE_ROUNDRECT:
case CHOICE_SHAPE_CHAMFERED_RECT:
m_trapDelta.Enable( false ); m_trapDelta.Enable( false );
m_trapAxisLabel->Enable( false ); m_trapAxisLabel->Enable( false );
m_trapAxisCtrl->Enable( false ); m_trapAxisCtrl->Enable( false );
@ -934,11 +982,20 @@ void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
enablePrimitivePage( is_custom ); enablePrimitivePage( is_custom );
// A few widgets are enabled only for rounded rect pads: // A few widgets are enabled only for rounded rect and chamfered pads:
m_staticTextCornerSizeRatio->Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT ); bool chamfered_rect_enable = m_PadShape->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT;
m_tcCornerSizeRatio->Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT ); bool round_rect_enable = m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT ||
m_staticTextCornerSizeRatioUnit->Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT ); chamfered_rect_enable;
m_cornerRadius.Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT ); m_staticTextCornerSizeRatio->Enable( round_rect_enable );
m_tcCornerSizeRatio->Enable( round_rect_enable );
m_staticTextCornerSizeRatioUnit->Enable( round_rect_enable );
m_cornerRadius.Enable( round_rect_enable );
m_cbTopLeft->Enable( chamfered_rect_enable );
m_cbTopRight->Enable( chamfered_rect_enable );
m_cbBottomLeft->Enable( chamfered_rect_enable );
m_cbBottomRight->Enable( chamfered_rect_enable );
m_tcChamferRatio->Enable( chamfered_rect_enable );
// PAD_SHAPE_CUSTOM type has constraints for zone connection and thermal shape: // PAD_SHAPE_CUSTOM type has constraints for zone connection and thermal shape:
// only not connected or solid connection is allowed to avoid destroying the shape. // only not connected or solid connection is allowed to avoid destroying the shape.
@ -1223,7 +1280,8 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK()
} }
if( m_dummyPad->GetShape() == PAD_SHAPE_ROUNDRECT ) if( m_dummyPad->GetShape() == PAD_SHAPE_ROUNDRECT ||
m_dummyPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
{ {
wxString value = m_tcCornerSizeRatio->GetValue(); wxString value = m_tcCornerSizeRatio->GetValue();
double rrRadiusRatioPercent; double rrRadiusRatioPercent;
@ -1494,6 +1552,8 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
m_currentPad->SetThermalWidth( m_padMaster->GetThermalWidth() ); m_currentPad->SetThermalWidth( m_padMaster->GetThermalWidth() );
m_currentPad->SetThermalGap( m_padMaster->GetThermalGap() ); m_currentPad->SetThermalGap( m_padMaster->GetThermalGap() );
m_currentPad->SetRoundRectRadiusRatio( m_padMaster->GetRoundRectRadiusRatio() ); m_currentPad->SetRoundRectRadiusRatio( m_padMaster->GetRoundRectRadiusRatio() );
m_currentPad->SetChamferRectRatio( m_padMaster->GetChamferRectRatio() );
m_currentPad->SetChamferPositions( m_padMaster->GetChamferPositions() );
if( m_currentPad->GetShape() == PAD_SHAPE_CUSTOM ) if( m_currentPad->GetShape() == PAD_SHAPE_CUSTOM )
{ {
@ -1664,6 +1724,22 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( D_PAD* aPad )
aPad->SetName( m_PadNumCtrl->GetValue() ); aPad->SetName( m_PadNumCtrl->GetValue() );
aPad->SetNetCode( m_PadNetSelector->GetSelectedNetcode() ); aPad->SetNetCode( m_PadNetSelector->GetSelectedNetcode() );
int chamfers = 0;
if( m_cbTopLeft->GetValue() )
chamfers |= RECT_CHAMFER_TOP_LEFT;
if( m_cbTopRight->GetValue() )
chamfers |= RECT_CHAMFER_TOP_RIGHT;
if( m_cbBottomLeft->GetValue() )
chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
if( m_cbBottomRight->GetValue() )
chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
aPad->SetChamferPositions( chamfers );
// Clear some values, according to the pad type and shape // Clear some values, according to the pad type and shape
switch( aPad->GetShape() ) switch( aPad->GetShape() )
{ {
@ -1684,6 +1760,7 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( D_PAD* aPad )
break; break;
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
aPad->SetDelta( wxSize( 0, 0 ) ); aPad->SetDelta( wxSize( 0, 0 ) );
break; break;
@ -1737,13 +1814,18 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( D_PAD* aPad )
break; break;
} }
if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT ) if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT || aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
{ {
wxString value = m_tcCornerSizeRatio->GetValue(); wxString value = m_tcCornerSizeRatio->GetValue();
double rrRadiusRatioPercent; double ratioPercent;
if( value.ToDouble( &rrRadiusRatioPercent ) ) if( value.ToDouble( &ratioPercent ) )
aPad->SetRoundRectRadiusRatio( rrRadiusRatioPercent / 100.0 ); aPad->SetRoundRectRadiusRatio( ratioPercent / 100.0 );
value = m_tcChamferRatio->GetValue();
if( value.ToDouble( &ratioPercent ) )
aPad->SetChamferRectRatio( ratioPercent / 100.0 );
} }
LSET padLayerMask; LSET padLayerMask;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 30 2017) // C++ code generated with wxFormBuilder (version Dec 1 2018)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -75,7 +75,7 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
m_staticText45->Wrap( -1 ); m_staticText45->Wrap( -1 );
fgSizerShapeType->Add( m_staticText45, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 3 ); fgSizerShapeType->Add( m_staticText45, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 3 );
wxString m_PadShapeChoices[] = { _("Circular"), _("Oval"), _("Rectangular"), _("Trapezoidal"), _("Rounded Rectangle"), _("Custom (Circ. Anchor)"), _("Custom (Rect. Anchor)") }; wxString m_PadShapeChoices[] = { _("Circular"), _("Oval"), _("Rectangular"), _("Trapezoidal"), _("Rounded Rectangle"), _("Chamfered Rectangle"), _("Custom (Circ. Anchor)"), _("Custom (Rect. Anchor)") };
int m_PadShapeNChoices = sizeof( m_PadShapeChoices ) / sizeof( wxString ); int m_PadShapeNChoices = sizeof( m_PadShapeChoices ) / sizeof( wxString );
m_PadShape = new wxChoice( m_panelGeneral, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_PadShapeNChoices, m_PadShapeChoices, 0 ); m_PadShape = new wxChoice( m_panelGeneral, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_PadShapeNChoices, m_PadShapeChoices, 0 );
m_PadShape->SetSelection( 0 ); m_PadShape->SetSelection( 0 );
@ -219,17 +219,53 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
m_cornerRadiusLabel->Wrap( -1 ); m_cornerRadiusLabel->Wrap( -1 );
m_cornerRadiusLabel->SetToolTip( _("Corner radius.\nCan be no more than half pad width.\nThe width is the smaller value between size X and size Y.\nNote: IPC norm gives a max value = 0.25mm.") ); m_cornerRadiusLabel->SetToolTip( _("Corner radius.\nCan be no more than half pad width.\nThe width is the smaller value between size X and size Y.\nNote: IPC norm gives a max value = 0.25mm.") );
fgSizerShapeType->Add( m_cornerRadiusLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 3 ); fgSizerShapeType->Add( m_cornerRadiusLabel, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 3 );
m_tcCornerRadius = new wxTextCtrl( m_panelGeneral, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_tcCornerRadius = new wxTextCtrl( m_panelGeneral, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_tcCornerRadius->SetToolTip( _("Corner radius.\nCan be no more than half pad width.\nThe width is the smaller value between size X and size Y\nNote: IPC norm gives a max value = 0.25mm") ); fgSizerShapeType->Add( m_tcCornerRadius, 0, wxALL|wxEXPAND, 3 );
fgSizerShapeType->Add( m_tcCornerRadius, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 3 );
m_cornerRadiusUnits = new wxStaticText( m_panelGeneral, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_cornerRadiusUnits = new wxStaticText( m_panelGeneral, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_cornerRadiusUnits->Wrap( -1 ); m_cornerRadiusUnits->Wrap( -1 );
fgSizerShapeType->Add( m_cornerRadiusUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 ); fgSizerShapeType->Add( m_cornerRadiusUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 );
m_staticTextChamferRatio = new wxStaticText( m_panelGeneral, wxID_ANY, _("Chamfer size:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextChamferRatio->Wrap( -1 );
m_staticTextChamferRatio->SetToolTip( _("Chamfer size in percent of the pad width.\nThe width is the smaller value between size X and size Y.\nThe max value is 50 percent.") );
fgSizerShapeType->Add( m_staticTextChamferRatio, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_tcChamferRatio = new TEXT_CTRL_EVAL( m_panelGeneral, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeType->Add( m_tcChamferRatio, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 3 );
m_staticTextChamferRatioUnit = new wxStaticText( m_panelGeneral, wxID_ANY, _("%"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextChamferRatioUnit->Wrap( -1 );
fgSizerShapeType->Add( m_staticTextChamferRatioUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_staticTextChamferCorner = new wxStaticText( m_panelGeneral, wxID_ANY, _("Chamfered corner:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextChamferCorner->Wrap( -1 );
m_staticTextChamferCorner->SetToolTip( _("Chamfered corners. The position is relative to a pad orientation 0 degree.") );
fgSizerShapeType->Add( m_staticTextChamferCorner, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerChamferedCorners;
bSizerChamferedCorners = new wxBoxSizer( wxVERTICAL );
m_cbTopLeft = new wxCheckBox( m_panelGeneral, wxID_ANY, _("Top left"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbTopLeft->SetValue(true);
bSizerChamferedCorners->Add( m_cbTopLeft, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_cbTopRight = new wxCheckBox( m_panelGeneral, wxID_ANY, _("Top right"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerChamferedCorners->Add( m_cbTopRight, 0, wxRIGHT|wxLEFT, 5 );
m_cbBottomLeft = new wxCheckBox( m_panelGeneral, wxID_ANY, _("Bottom left"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerChamferedCorners->Add( m_cbBottomLeft, 0, wxRIGHT|wxLEFT, 5 );
m_cbBottomRight = new wxCheckBox( m_panelGeneral, wxID_ANY, _("Bottom right"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerChamferedCorners->Add( m_cbBottomRight, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
fgSizerShapeType->Add( bSizerChamferedCorners, 0, wxEXPAND, 5 );
m_LeftBoxSizer->Add( fgSizerShapeType, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); m_LeftBoxSizer->Add( fgSizerShapeType, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
@ -725,6 +761,11 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
m_trapAxisCtrl->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this ); m_trapAxisCtrl->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_tcCornerSizeRatio->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this ); m_tcCornerSizeRatio->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this );
m_tcCornerRadius->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerRadiusChange ), NULL, this ); m_tcCornerRadius->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerRadiusChange ), NULL, this );
m_tcChamferRatio->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this );
m_cbTopLeft->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_cbTopRight->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_cbBottomLeft->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_cbBottomRight->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_holeShapeCtrl->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnDrillShapeSelected ), NULL, this ); m_holeShapeCtrl->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnDrillShapeSelected ), NULL, this );
m_holeXCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this ); m_holeXCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_holeYCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this ); m_holeYCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
@ -773,6 +814,11 @@ DIALOG_PAD_PROPERTIES_BASE::~DIALOG_PAD_PROPERTIES_BASE()
m_trapAxisCtrl->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this ); m_trapAxisCtrl->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_tcCornerSizeRatio->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this ); m_tcCornerSizeRatio->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this );
m_tcCornerRadius->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerRadiusChange ), NULL, this ); m_tcCornerRadius->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerRadiusChange ), NULL, this );
m_tcChamferRatio->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onCornerSizePercentChange ), NULL, this );
m_cbTopLeft->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_cbTopRight->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_cbBottomLeft->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_cbBottomRight->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_holeShapeCtrl->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnDrillShapeSelected ), NULL, this ); m_holeShapeCtrl->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnDrillShapeSelected ), NULL, this );
m_holeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this ); m_holeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_holeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this ); m_holeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
@ -826,7 +872,7 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE::DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE( wx
m_startXLabel->Wrap( -1 ); m_startXLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_startXLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_startXLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_startXCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_startXCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_startXCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_startXCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_startXUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_startXUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
@ -837,7 +883,7 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE::DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE( wx
m_startYLabel->Wrap( -1 ); m_startYLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_startYLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_startYLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_startYCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_startYCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_startYCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_startYCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_startYUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_startYUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
@ -852,7 +898,7 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE::DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE( wx
m_endXLabel->Wrap( -1 ); m_endXLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_endXLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_endXLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_endXCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_endXCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_endXCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_endXCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_endXUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_endXUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
@ -863,7 +909,7 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE::DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE( wx
m_endYLabel->Wrap( -1 ); m_endYLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_endYLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_endYLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_endYCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_endYCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_endYCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_endYCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_endYUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_endYUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
@ -877,7 +923,7 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE::DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE( wx
fgSizerShapeProperties->Add( 0, 0, 1, wxEXPAND, 5 ); fgSizerShapeProperties->Add( 0, 0, 1, wxEXPAND, 5 );
m_radiusCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_radiusCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_radiusCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties->Add( m_radiusCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_radiusUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_radiusUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
@ -965,7 +1011,7 @@ DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE::DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE( wxWi
m_xLabel->Wrap( -1 ); m_xLabel->Wrap( -1 );
fgSizerShapeProperties1->Add( m_xLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 ); fgSizerShapeProperties1->Add( m_xLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_xCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_xCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties1->Add( m_xCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties1->Add( m_xCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_xUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_xUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
@ -976,7 +1022,7 @@ DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE::DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE( wxWi
m_yLabel->Wrap( -1 ); m_yLabel->Wrap( -1 );
fgSizerShapeProperties1->Add( m_yLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); fgSizerShapeProperties1->Add( m_yLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_yCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_yCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties1->Add( m_yCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties1->Add( m_yCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_yUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_yUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
@ -990,7 +1036,7 @@ DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE::DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE( wxWi
fgSizerShapeProperties1->Add( 0, 0, 1, wxEXPAND, 5 ); fgSizerShapeProperties1->Add( 0, 0, 1, wxEXPAND, 5 );
m_rotationCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_rotationCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties1->Add( m_rotationCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); fgSizerShapeProperties1->Add( m_rotationCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_rotationUnits = new wxStaticText( this, wxID_ANY, _("deg"), wxDefaultPosition, wxDefaultSize, 0 ); m_rotationUnits = new wxStaticText( this, wxID_ANY, _("deg"), wxDefaultPosition, wxDefaultSize, 0 );
@ -1098,13 +1144,13 @@ DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE::DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE( wxWi
m_gridCornersList->SetColLabelSize( 22 ); m_gridCornersList->SetColLabelSize( 22 );
m_gridCornersList->SetColLabelValue( 0, _("Pos X") ); m_gridCornersList->SetColLabelValue( 0, _("Pos X") );
m_gridCornersList->SetColLabelValue( 1, _("Pos Y") ); m_gridCornersList->SetColLabelValue( 1, _("Pos Y") );
m_gridCornersList->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); m_gridCornersList->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows // Rows
m_gridCornersList->AutoSizeRows(); m_gridCornersList->AutoSizeRows();
m_gridCornersList->EnableDragRowSize( false ); m_gridCornersList->EnableDragRowSize( false );
m_gridCornersList->SetRowLabelSize( 80 ); m_gridCornersList->SetRowLabelSize( 80 );
m_gridCornersList->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); m_gridCornersList->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Label Appearance // Label Appearance
@ -1115,7 +1161,7 @@ DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE::DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE( wxWi
wxBoxSizer* bSizerRightButts; wxBoxSizer* bSizerRightButts;
bSizerRightButts = new wxBoxSizer( wxHORIZONTAL ); bSizerRightButts = new wxBoxSizer( wxHORIZONTAL );
m_addButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); m_addButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_addButton->SetMinSize( wxSize( 30,30 ) ); m_addButton->SetMinSize( wxSize( 30,30 ) );
bSizerRightButts->Add( m_addButton, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); bSizerRightButts->Add( m_addButton, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
@ -1123,7 +1169,7 @@ DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE::DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE( wxWi
bSizerRightButts->Add( 0, 0, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); bSizerRightButts->Add( 0, 0, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_deleteButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); m_deleteButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_deleteButton->SetMinSize( wxSize( 30,30 ) ); m_deleteButton->SetMinSize( wxSize( 30,30 ) );
bSizerRightButts->Add( m_deleteButton, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); bSizerRightButts->Add( m_deleteButton, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
@ -1141,7 +1187,7 @@ DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE::DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE( wxWi
m_thicknessLabel->Wrap( -1 ); m_thicknessLabel->Wrap( -1 );
fgSizerThickness->Add( m_thicknessLabel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); fgSizerThickness->Add( m_thicknessLabel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
m_thicknessCtrl = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 ); m_thicknessCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizerThickness->Add( m_thicknessCtrl, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); fgSizerThickness->Add( m_thicknessCtrl, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
m_thicknessUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_thicknessUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,11 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 30 2017) // C++ code generated with wxFormBuilder (version Dec 1 2018)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_PAD_PROPERTIES_BASE_H__ #pragma once
#define __DIALOG_PAD_PROPERTIES_BASE_H__
#include <wx/artprov.h> #include <wx/artprov.h>
#include <wx/xrc/xmlres.h> #include <wx/xrc/xmlres.h>
@ -25,12 +24,12 @@ class WX_GRID;
#include <widgets/net_selector.h> #include <widgets/net_selector.h>
#include <wx/choice.h> #include <wx/choice.h>
#include <wx/combobox.h> #include <wx/combobox.h>
#include <wx/checkbox.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/bitmap.h> #include <wx/bitmap.h>
#include <wx/image.h> #include <wx/image.h>
#include <wx/icon.h> #include <wx/icon.h>
#include <wx/statbmp.h> #include <wx/statbmp.h>
#include <wx/checkbox.h>
#include <wx/statbox.h> #include <wx/statbox.h>
#include <wx/panel.h> #include <wx/panel.h>
#include <wx/simplebook.h> #include <wx/simplebook.h>
@ -106,6 +105,14 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM
wxStaticText* m_cornerRadiusLabel; wxStaticText* m_cornerRadiusLabel;
wxTextCtrl* m_tcCornerRadius; wxTextCtrl* m_tcCornerRadius;
wxStaticText* m_cornerRadiusUnits; wxStaticText* m_cornerRadiusUnits;
wxStaticText* m_staticTextChamferRatio;
TEXT_CTRL_EVAL* m_tcChamferRatio;
wxStaticText* m_staticTextChamferRatioUnit;
wxStaticText* m_staticTextChamferCorner;
wxCheckBox* m_cbTopLeft;
wxCheckBox* m_cbTopRight;
wxCheckBox* m_cbBottomLeft;
wxCheckBox* m_cbBottomRight;
wxStaticText* m_holeShapeLabel; wxStaticText* m_holeShapeLabel;
wxChoice* m_holeShapeCtrl; wxChoice* m_holeShapeCtrl;
wxStaticText* m_staticText51; wxStaticText* m_staticText51;
@ -227,20 +234,20 @@ class DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE : public DIALOG_SHIM
protected: protected:
wxStaticText* m_staticTextPosStart; wxStaticText* m_staticTextPosStart;
wxStaticText* m_startXLabel; wxStaticText* m_startXLabel;
wxTextCtrl* m_startXCtrl; TEXT_CTRL_EVAL* m_startXCtrl;
wxStaticText* m_startXUnits; wxStaticText* m_startXUnits;
wxStaticText* m_startYLabel; wxStaticText* m_startYLabel;
wxTextCtrl* m_startYCtrl; TEXT_CTRL_EVAL* m_startYCtrl;
wxStaticText* m_startYUnits; wxStaticText* m_startYUnits;
wxStaticText* m_staticTextPosEnd; wxStaticText* m_staticTextPosEnd;
wxStaticText* m_endXLabel; wxStaticText* m_endXLabel;
wxTextCtrl* m_endXCtrl; TEXT_CTRL_EVAL* m_endXCtrl;
wxStaticText* m_endXUnits; wxStaticText* m_endXUnits;
wxStaticText* m_endYLabel; wxStaticText* m_endYLabel;
wxTextCtrl* m_endYCtrl; TEXT_CTRL_EVAL* m_endYCtrl;
wxStaticText* m_endYUnits; wxStaticText* m_endYUnits;
wxStaticText* m_radiusLabel; wxStaticText* m_radiusLabel;
wxTextCtrl* m_radiusCtrl; TEXT_CTRL_EVAL* m_radiusCtrl;
wxStaticText* m_radiusUnits; wxStaticText* m_radiusUnits;
wxStaticText* m_thicknessLabel; wxStaticText* m_thicknessLabel;
wxTextCtrl* m_thicknessCtrl; wxTextCtrl* m_thicknessCtrl;
@ -268,13 +275,13 @@ class DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE : public DIALOG_SHIM
protected: protected:
wxStaticText* m_staticTextMove; wxStaticText* m_staticTextMove;
wxStaticText* m_xLabel; wxStaticText* m_xLabel;
wxTextCtrl* m_xCtrl; TEXT_CTRL_EVAL* m_xCtrl;
wxStaticText* m_xUnits; wxStaticText* m_xUnits;
wxStaticText* m_yLabel; wxStaticText* m_yLabel;
wxTextCtrl* m_yCtrl; TEXT_CTRL_EVAL* m_yCtrl;
wxStaticText* m_yUnits; wxStaticText* m_yUnits;
wxStaticText* m_rotationLabel; wxStaticText* m_rotationLabel;
wxTextCtrl* m_rotationCtrl; TEXT_CTRL_EVAL* m_rotationCtrl;
wxStaticText* m_rotationUnits; wxStaticText* m_rotationUnits;
wxStaticText* m_scaleLabel; wxStaticText* m_scaleLabel;
TEXT_CTRL_EVAL* m_scaleCtrl; TEXT_CTRL_EVAL* m_scaleCtrl;
@ -304,7 +311,7 @@ class DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE : public DIALOG_SHIM
wxBitmapButton* m_addButton; wxBitmapButton* m_addButton;
wxBitmapButton* m_deleteButton; wxBitmapButton* m_deleteButton;
wxStaticText* m_thicknessLabel; wxStaticText* m_thicknessLabel;
wxTextCtrl* m_thicknessCtrl; TEXT_CTRL_EVAL* m_thicknessCtrl;
wxStaticText* m_thicknessUnits; wxStaticText* m_thicknessUnits;
wxPanel* m_panelPoly; wxPanel* m_panelPoly;
wxStaticBitmap* m_warningIcon; wxStaticBitmap* m_warningIcon;
@ -332,4 +339,3 @@ class DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE : public DIALOG_SHIM
}; };
#endif //__DIALOG_PAD_PROPERTIES_BASE_H__

View File

@ -898,7 +898,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
// priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other
if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE ) if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE )
{ {
// pad ref shape is here oval, rect, roundrect, trapezoid or custom // pad ref shape is here oval, rect, roundrect, chamfered rect, trapezoid or custom
switch( aPad->GetShape() ) switch( aPad->GetShape() )
{ {
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
@ -916,6 +916,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
break; break;
case PAD_SHAPE_TRAPEZOID: case PAD_SHAPE_TRAPEZOID:
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
break; break;
} }
@ -962,6 +963,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
case PAD_SHAPE_TRAPEZOID: case PAD_SHAPE_TRAPEZOID:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_RECT: case PAD_SHAPE_RECT:
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
// pad_angle = pad orient relative to the aRefPad orient // pad_angle = pad orient relative to the aRefPad orient
@ -975,6 +977,17 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ), GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ),
aRefPad->GetSize(), aRefPad->GetOrientation() ); aRefPad->GetSize(), aRefPad->GetOrientation() );
} }
else if( aRefPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
{
// The reference pad can be rotated. calculate the rotated
// coordinates ( note, the ref pad position is the origin of
// coordinates for this drc test)
int padRadius = aRefPad->GetRoundRectCornerRadius();
TransformRoundChamferedRectToPolygon( polysetref, wxPoint( 0, 0 ), aRefPad->GetSize(),
aRefPad->GetOrientation(),
padRadius, aRefPad->GetChamferRectRatio(),
aRefPad->GetChamferPositions(), 64 );
}
else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM ) else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM )
{ {
polysetref.Append( aRefPad->GetCustomShapeAsPolygon() ); polysetref.Append( aRefPad->GetCustomShapeAsPolygon() );
@ -996,6 +1009,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
{ {
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_RECT: case PAD_SHAPE_RECT:
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_TRAPEZOID: case PAD_SHAPE_TRAPEZOID:
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT ) if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
@ -1005,6 +1019,17 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos, GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos,
aPad->GetSize(), aPad->GetOrientation() ); aPad->GetSize(), aPad->GetOrientation() );
} }
else if( aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
{
// The reference pad can be rotated. calculate the rotated
// coordinates ( note, the ref pad position is the origin of
// coordinates for this drc test)
int padRadius = aPad->GetRoundRectCornerRadius();
TransformRoundChamferedRectToPolygon( polysetcompare, relativePadPos, aPad->GetSize(),
aPad->GetOrientation(),
padRadius, aPad->GetChamferRectRatio(),
aPad->GetChamferPositions(), 64 );
}
else if( aPad->GetShape() == PAD_SHAPE_CUSTOM ) else if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
{ {
polysetcompare.Append( aPad->GetCustomShapeAsPolygon() ); polysetcompare.Append( aPad->GetCustomShapeAsPolygon() );
@ -1375,6 +1400,36 @@ bool DRC::checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMi
const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 ); const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
refpoly.PointCount(),
wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
distToLine ) )
return false;
}
break;
case PAD_SHAPE_CHAMFERED_RECT:
{
SHAPE_POLY_SET polyset;
// The pad can be rotated. calculate the coordinates
// relatives to the segment being tested
// Note, the pad position relative to the segment origin
// is m_padToTestPos
int padRadius = aPad->GetRoundRectCornerRadius();
TransformRoundChamferedRectToPolygon( polyset, m_padToTestPos, aPad->GetSize(),
aPad->GetOrientation(),
padRadius, aPad->GetChamferRectRatio(),
aPad->GetChamferPositions(), 64 );
// Rotate also coordinates by m_segmAngle, because the segment orient
// is m_segmAngle.
// we are using a horizontal segment for test, because we know here
// only the lenght and orientation of the segment
// therefore all coordinates of the pad to test must be rotated by
// m_segmAngle (they are already relative to the segment origin)
polyset.Rotate( DECIDEG2RAD( -m_segmAngle ), VECTOR2I( 0, 0 ) );
const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ), if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
refpoly.PointCount(), refpoly.PointCount(),
wxPoint( 0, 0 ), wxPoint(m_segmLength,0), wxPoint( 0, 0 ), wxPoint(m_segmLength,0),

View File

@ -1116,14 +1116,15 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aTinLayer, D_P
break; break;
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
{ {
SHAPE_POLY_SET polySet; SHAPE_POLY_SET polySet;
int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
const int corner_radius = aPad->GetRoundRectCornerRadius( aPad->GetSize() ); const int corner_radius = aPad->GetRoundRectCornerRadius( aPad->GetSize() );
TransformRoundRectToPolygon( polySet, wxPoint( 0, 0 ), aPad->GetSize(), TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), aPad->GetSize(),
0.0, corner_radius, segmentToCircleCount ); 0.0, corner_radius, 0.0, 0, segmentToCircleCount );
std::vector< wxRealPoint > cornerList; std::vector< wxRealPoint > cornerList;
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundChamferedRectToPolygon creates only one convex polygon
SHAPE_LINE_CHAIN poly( polySet.Outline( 0 ) ); SHAPE_LINE_CHAIN poly( polySet.Outline( 0 ) );
for( int ii = 0; ii < poly.PointCount(); ++ii ) for( int ii = 0; ii < poly.PointCount(); ++ii )
@ -1210,9 +1211,6 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aTinLayer, D_P
break; break;
} }
default:
break;
} }
} }

View File

@ -51,6 +51,7 @@
#include <boost/ptr_container/ptr_map.hpp> #include <boost/ptr_container/ptr_map.hpp>
#include <memory.h> #include <memory.h>
#include <connectivity/connectivity_data.h> #include <connectivity/connectivity_data.h>
#include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
using namespace PCB_KEYS_T; using namespace PCB_KEYS_T;
@ -1252,6 +1253,7 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
case PAD_SHAPE_RECT: shape = "rect"; break; case PAD_SHAPE_RECT: shape = "rect"; break;
case PAD_SHAPE_OVAL: shape = "oval"; break; case PAD_SHAPE_OVAL: shape = "oval"; break;
case PAD_SHAPE_TRAPEZOID: shape = "trapezoid"; break; case PAD_SHAPE_TRAPEZOID: shape = "trapezoid"; break;
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: shape = "roundrect"; break; case PAD_SHAPE_ROUNDRECT: shape = "roundrect"; break;
case PAD_SHAPE_CUSTOM: shape = "custom"; break; case PAD_SHAPE_CUSTOM: shape = "custom"; break;
@ -1311,13 +1313,38 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
formatLayers( aPad->GetLayerSet() ); formatLayers( aPad->GetLayerSet() );
// Output the radius ratio for rounded rect pads // Output the radius ratio for rounded and chamfered rect pads
if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT ) if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT || aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT)
{ {
m_out->Print( 0, " (roundrect_rratio %s)", m_out->Print( 0, " (roundrect_rratio %s)",
Double2Str( aPad->GetRoundRectRadiusRatio() ).c_str() ); Double2Str( aPad->GetRoundRectRadiusRatio() ).c_str() );
} }
// Output the chamfer corners for chamfered rect pads
if( aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT)
{
m_out->Print( 0, "\n" );
m_out->Print( aNestLevel+1, "(chamfer_ratio %s)",
Double2Str( aPad->GetChamferRectRatio() ).c_str() );
m_out->Print( 0, " (chamfer" );
if( ( aPad->GetChamferPositions() & RECT_CHAMFER_TOP_LEFT ) )
m_out->Print( 0, " top_left" );
if( ( aPad->GetChamferPositions() & RECT_CHAMFER_TOP_RIGHT ) )
m_out->Print( 0, " top_right" );
if( ( aPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_LEFT ) )
m_out->Print( 0, " bottom_left" );
if( ( aPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_RIGHT ) )
m_out->Print( 0, " bottom_right" );
m_out->Print( 0, ")" );
}
std::string output; std::string output;
// Unconnected pad is default net so don't save it. // Unconnected pad is default net so don't save it.

View File

@ -341,6 +341,7 @@ void D_PAD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDraw_mode,
void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
{ {
#define SEGCOUNT 32 // number of segments to approximate a circle
wxPoint coord[12]; wxPoint coord[12];
double angle = m_Orient; double angle = m_Orient;
int seg_width; int seg_width;
@ -436,42 +437,29 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
} }
break; break;
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
{ {
// Use solder[Paste/Mask]size or pad size to build pad shape to draw // Use solder[Paste/Mask]size or pad size to build pad shape to draw
wxSize size( GetSize() ); wxSize size( GetSize() );
size += aDrawInfo.m_Mask_margin * 2; size += aDrawInfo.m_Mask_margin * 2;
int corner_radius = GetRoundRectCornerRadius( size ); int corner_radius = GetRoundRectCornerRadius( size );
bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, shape_pos, size, GetOrientation(),
corner_radius, GetChamferRectRatio(),
doChamfer ? GetChamferPositions() : 0,
SEGCOUNT );
// Draw the polygon: Inflate creates only one convex polygon // Draw the polygon: Inflate creates only one convex polygon
SHAPE_POLY_SET outline;
bool filled = aDrawInfo.m_ShowPadFilled; bool filled = aDrawInfo.m_ShowPadFilled;
if( filled )
{
wxPoint centers[4];
GetRoundRectCornerCenters( centers, corner_radius, shape_pos,
size, GetOrientation() );
GRClosedPoly( aClipBox, aDC, 4, centers, true, corner_radius*2,
aDrawInfo.m_Color, aDrawInfo.m_Color );
}
else
{
TransformRoundRectToPolygon( outline, shape_pos, size, GetOrientation(),
corner_radius, 64 );
if( outline.OutlineCount() > 0 )
{
SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
if( poly.PointCount() > 0 )
{
GRClosedPoly( aClipBox, aDC, poly.PointCount(), GRClosedPoly( aClipBox, aDC, poly.PointCount(),
(wxPoint*)&poly.Point( 0 ), aDrawInfo.m_ShowPadFilled, 0, (wxPoint*)&poly.Point( 0 ), filled, 0,
aDrawInfo.m_Color, aDrawInfo.m_Color ); aDrawInfo.m_Color, aDrawInfo.m_Color );
}
}
}
if( aDrawInfo.m_PadClearance ) if( aDrawInfo.m_PadClearance )
{ {
@ -481,23 +469,19 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
size.y += aDrawInfo.m_PadClearance * 2; size.y += aDrawInfo.m_PadClearance * 2;
corner_radius = GetRoundRectCornerRadius() + aDrawInfo.m_PadClearance; corner_radius = GetRoundRectCornerRadius() + aDrawInfo.m_PadClearance;
TransformRoundRectToPolygon( outline, shape_pos, size, GetOrientation(), TransformRoundChamferedRectToPolygon( outline, shape_pos, size, GetOrientation(),
corner_radius, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); corner_radius, GetChamferRectRatio(),
doChamfer ? GetChamferPositions() : 0,
SEGCOUNT );
if( outline.OutlineCount() > 0 )
{
// Draw the polygon: Inflate creates only one convex polygon // Draw the polygon: Inflate creates only one convex polygon
SHAPE_LINE_CHAIN& clearance_poly = outline.Outline( 0 ); SHAPE_LINE_CHAIN& clearance_poly = outline.Outline( 0 );
if( clearance_poly.PointCount() > 0 )
{
GRClosedPoly( aClipBox, aDC, clearance_poly.PointCount(), GRClosedPoly( aClipBox, aDC, clearance_poly.PointCount(),
(wxPoint*)&clearance_poly.Point( 0 ), false, 0, (wxPoint*)&clearance_poly.Point( 0 ), false, 0,
aDrawInfo.m_Color, aDrawInfo.m_Color ); aDrawInfo.m_Color, aDrawInfo.m_Color );
} }
} }
}
}
break; break;
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
@ -587,9 +571,6 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
} }
break; break;
} }
default:
break;
} }
// Draw the pad hole // Draw the pad hole

View File

@ -816,13 +816,17 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
break; break;
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
{ {
SHAPE_POLY_SET polySet; SHAPE_POLY_SET polySet;
wxSize prsize( size.x * 2, size.y * 2 ); wxSize prsize( size.x * 2, size.y * 2 ); // size is the half pad area size)
const int segmentToCircleCount = 64; const int segmentToCircleCount = 64;
const int corner_radius = aPad->GetRoundRectCornerRadius( prsize ); const int corner_radius = aPad->GetRoundRectCornerRadius( prsize );
TransformRoundRectToPolygon( polySet, wxPoint( 0, 0 ), prsize, bool doChamfer = shape == PAD_SHAPE_CHAMFERED_RECT;
0.0, corner_radius, segmentToCircleCount );
TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), prsize,
0.0, corner_radius, aPad->GetChamferRectRatio(),
doChamfer ? aPad->GetChamferPositions() : 0, segmentToCircleCount );
m_gal->DrawPolygon( polySet ); m_gal->DrawPolygon( polySet );
break; break;
} }

View File

@ -49,6 +49,7 @@
#include <pcb_plot_params.h> #include <pcb_plot_params.h>
#include <zones.h> #include <zones.h>
#include <pcb_parser.h> #include <pcb_parser.h>
#include <convert_basic_shapes_to_polygon.h> // for RECT_CHAMFER_POSITIONS definition
using namespace PCB_KEYS_T; using namespace PCB_KEYS_T;
@ -2455,6 +2456,8 @@ D_PAD* PCB_PARSER::parseD_PAD( MODULE* aParent )
break; break;
case T_roundrect: case T_roundrect:
// Note: the shape can be PAD_SHAPE_ROUNDRECT or PAD_SHAPE_CHAMFERED_RECT
// (if champfer parameters are found later in pad descr.)
pad->SetShape( PAD_SHAPE_ROUNDRECT ); pad->SetShape( PAD_SHAPE_ROUNDRECT );
break; break;
@ -2636,6 +2639,56 @@ D_PAD* PCB_PARSER::parseD_PAD( MODULE* aParent )
NeedRIGHT(); NeedRIGHT();
break; break;
case T_chamfer_ratio:
pad->SetChamferRectRatio( parseDouble( "chamfer ratio" ) );
if( pad->GetChamferRectRatio() > 0 )
pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
NeedRIGHT();
break;
case T_chamfer:
{
int chamfers = 0;
bool end_list = false;
while( !end_list )
{
token = NextTok();
switch( token )
{
case T_top_left:
chamfers |= RECT_CHAMFER_TOP_LEFT;
break;
case T_top_right:
chamfers |= RECT_CHAMFER_TOP_RIGHT;
break;
case T_bottom_left:
chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
break;
case T_bottom_right:
chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
break;
case T_RIGHT:
pad->SetChamferPositions( chamfers );
end_list = true;
break;
default:
Expecting( "chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
}
}
if( pad->GetChamferPositions() != RECT_NO_CHAMFER )
pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
}
break;
case T_options: case T_options:
parseD_PAD_option( pad.get() ); parseD_PAD_option( pad.get() );
break; break;

View File

@ -443,6 +443,7 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
case PAD_SHAPE_TRAPEZOID: case PAD_SHAPE_TRAPEZOID:
case PAD_SHAPE_RECT: case PAD_SHAPE_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
case PAD_SHAPE_CHAMFERED_RECT:
pad->SetSize( padPlotsSize ); pad->SetSize( padPlotsSize );
itemplotter.PlotPad( pad, color, plotMode ); itemplotter.PlotPad( pad, color, plotMode );
break; break;

View File

@ -7,7 +7,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -45,6 +45,7 @@
#include <class_drawsegment.h> #include <class_drawsegment.h>
#include <class_pcb_target.h> #include <class_pcb_target.h>
#include <class_dimension.h> #include <class_dimension.h>
#include <convert_basic_shapes_to_polygon.h>
#include <pcbnew.h> #include <pcbnew.h>
#include <pcbplot.h> #include <pcbplot.h>
@ -186,6 +187,23 @@ void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPl
aPad->GetOrientation(), aPlotMode, &gbr_metadata ); aPad->GetOrientation(), aPlotMode, &gbr_metadata );
break; break;
case PAD_SHAPE_CHAMFERED_RECT:
{
SHAPE_POLY_SET polygons;
const int segmentToCircleCount = 64;
const int corner_radius = aPad->GetRoundRectCornerRadius( aPad->GetSize() );
TransformRoundChamferedRectToPolygon( polygons, shape_pos, aPad->GetSize(),
aPad->GetOrientation(), corner_radius, aPad->GetChamferRectRatio(),
aPad->GetChamferPositions(), segmentToCircleCount );
if( polygons.OutlineCount() == 0 )
break;
int min_dim = std::min( aPad->GetSize().x, aPad->GetSize().y ) /2;
m_plotter->FlashPadCustom( shape_pos,wxSize( min_dim, min_dim ), &polygons, aPlotMode, &gbr_metadata );
}
break;
case PAD_SHAPE_CUSTOM: case PAD_SHAPE_CUSTOM:
{ {
SHAPE_POLY_SET polygons; SHAPE_POLY_SET polygons;

View File

@ -612,6 +612,7 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE::syncPad( D_PAD* aPad )
break; break;
} }
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
@ -624,9 +625,7 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE::syncPad( D_PAD* aPad )
SHAPE_SIMPLE* shape = new SHAPE_SIMPLE(); SHAPE_SIMPLE* shape = new SHAPE_SIMPLE();
for( int ii = 0; ii < poly.PointCount(); ++ii ) for( int ii = 0; ii < poly.PointCount(); ++ii )
{ shape->Append( poly.Point( ii ) );
shape->Append( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
}
solid->SetShape( shape ); solid->SetShape( shape );
} }
@ -708,6 +707,7 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE::syncPad( D_PAD* aPad )
break; break;
} }
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;

View File

@ -323,7 +323,6 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
switch( aPad->GetShape() ) switch( aPad->GetShape() )
{ {
default:
case PAD_SHAPE_CIRCLE: case PAD_SHAPE_CIRCLE:
{ {
double diameter = scale( aPad->GetSize().x ); double diameter = scale( aPad->GetSize().x );
@ -491,6 +490,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
} }
break; break;
case PAD_SHAPE_CHAMFERED_RECT:
case PAD_SHAPE_ROUNDRECT: case PAD_SHAPE_ROUNDRECT:
{ {
// Export the shape as as polygon, round rect does not exist as primitive // Export the shape as as polygon, round rect does not exist as primitive
@ -511,8 +511,13 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
psize.x += extra_clearance*2; psize.x += extra_clearance*2;
psize.y += extra_clearance*2; psize.y += extra_clearance*2;
rradius += extra_clearance; rradius += extra_clearance;
TransformRoundRectToPolygon( cornerBuffer, wxPoint(0,0), psize, bool doChamfer = aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT;
0, rradius, circleToSegmentsCount );
TransformRoundChamferedRectToPolygon( cornerBuffer, wxPoint(0,0), psize,
0, rradius,
aPad->GetChamferRectRatio(),
doChamfer ? aPad->GetChamferPositions() : 0,
circleToSegmentsCount );
SHAPE_LINE_CHAIN& polygonal_shape = cornerBuffer.Outline( 0 ); SHAPE_LINE_CHAIN& polygonal_shape = cornerBuffer.Outline( 0 );
for( int ndx=0; ndx < reportedLayers; ++ndx ) for( int ndx=0; ndx < reportedLayers; ++ndx )