void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode ) { SHAPE_POLY_SET outline; const int segmentToCircleCount = 32; wxSize size = aSize; if( aTraceMode == FILLED ) { // in filled mode, the pen diameter is removed from size // to keep the pad size size.x -= KiROUND( penDiameter ) / 2; size.x = std::max( size.x, 0); size.y -= KiROUND( penDiameter ) / 2; size.y = std::max( size.y, 0); // keep aCornerRadius to a value < min size x,y < 2: aCornerRadius = std::min( aCornerRadius, std::min( size.x, size.y ) /2 ); } TransformRoundRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius, segmentToCircleCount ); // TransformRoundRectToPolygon creates only one convex polygon std::vector< wxPoint > cornerList; cornerList.reserve( segmentToCircleCount + 4 ); SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); for( int ii = 0; ii < poly.PointCount(); ++ii ) cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); PlotPoly( cornerList, aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL ); }
void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { GBR_METADATA gbr_metadata; if( aData ) { gbr_metadata = *static_cast<GBR_METADATA*>( aData ); // If the pad is drawn on a copper layer, // set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR if( gbr_metadata.IsCopper() ) gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); wxString attrname( ".P" ); gbr_metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers } if( aTraceMode != FILLED ) SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); // Currently, a Pad RoundRect is plotted as polygon. // TODO: use Aperture macro and flash it SHAPE_POLY_SET outline; const int segmentToCircleCount = 64; TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius, segmentToCircleCount ); if( aTraceMode != FILLED ) outline.Inflate( -GetCurrentLineWidth()/2, 16 ); std::vector< wxPoint > cornerList; // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); cornerList.reserve( poly.PointCount() + 1 ); for( int ii = 0; ii < poly.PointCount(); ++ii ) cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); // Close polygon cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL, aTraceMode == FILLED ? 0 : GetCurrentLineWidth(), &gbr_metadata ); // Now, flash a pad anchor, if a netlist attribute is set // (remove me when a Aperture macro will be used) if( aData && aTraceMode == FILLED ) { int diameter = std::min( aSize.x, aSize.y ); FlashPadCircle( aPadPos, diameter, aTraceMode , aData ); } }
void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { SHAPE_POLY_SET outline; const int segmentToCircleCount = 64; TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius, segmentToCircleCount ); // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) ); for( int ii = 1; ii < poly.PointCount(); ++ii ) LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); FinishTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) ); }
void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { wxSize size( aSize ); if( aTraceMode == FILLED ) SetCurrentLineWidth( 0 ); else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); size.x -= GetCurrentLineWidth(); size.y -= GetCurrentLineWidth(); aCornerRadius -= GetCurrentLineWidth()/2; } SHAPE_POLY_SET outline; const int segmentToCircleCount = 64; TransformRoundRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius, segmentToCircleCount ); std::vector< wxPoint > cornerList; cornerList.reserve( segmentToCircleCount + 5 ); // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); for( int ii = 0; ii < poly.PointCount(); ++ii ) cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); // Close polygon cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, GetCurrentLineWidth() ); }
bool D_PAD::HitTest( const wxPoint& aPosition ) const { int dx, dy; wxPoint shape_pos = ShapePos(); wxPoint delta = aPosition - shape_pos; // first test: a test point must be inside a minimum sized bounding circle. int radius = GetBoundingRadius(); if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) ) return false; dx = m_Size.x >> 1; // dx also is the radius for rounded pads dy = m_Size.y >> 1; switch( GetShape() ) { case PAD_SHAPE_CIRCLE: if( KiROUND( EuclideanNorm( delta ) ) <= dx ) return true; break; case PAD_SHAPE_TRAPEZOID: { wxPoint poly[4]; BuildPadPolygon( poly, wxSize(0,0), 0 ); RotatePoint( &delta, -m_Orient ); return TestPointInsidePolygon( poly, 4, delta ); } case PAD_SHAPE_OVAL: { RotatePoint( &delta, -m_Orient ); // An oval pad has the same shape as a segment with rounded ends // After rotation, the test point is relative to an horizontal pad int dist; wxPoint offset; if( dy > dx ) // shape is a vertical oval { offset.y = dy - dx; dist = dx; } else //if( dy <= dx ) shape is an horizontal oval { offset.x = dy - dx; dist = dy; } return TestSegmentHit( delta, - offset, offset, dist ); } break; case PAD_SHAPE_RECT: RotatePoint( &delta, -m_Orient ); if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) ) return true; break; case PAD_SHAPE_ROUNDRECT: { // Check for hit in polygon SHAPE_POLY_SET outline; const int segmentToCircleCount = 32; TransformRoundRectToPolygon( outline, wxPoint(0,0), GetSize(), m_Orient, GetRoundRectCornerRadius(), segmentToCircleCount ); const SHAPE_LINE_CHAIN &poly = outline.COutline( 0 ); return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta ); } break; case PAD_SHAPE_CUSTOM: // Check for hit in polygon RotatePoint( &delta, -m_Orient ); if( m_customShapeAsPolygon.OutlineCount() ) { const SHAPE_LINE_CHAIN& poly = m_customShapeAsPolygon.COutline( 0 ); return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta ); } break; } return false; }