/* Plot oval pad. */ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient, EDA_DRAW_MODE_T trace_mode ) { wxASSERT( outputFile ); int deltaxy, cx, cy; wxSize size( aSize ); /* The pad will be drawn as an oblong shape with size.y > size.x * (Oval vertical orientation 0) */ if( size.x > size.y ) { std::swap( size.x, size.y ); orient = AddAngles( orient, 900 ); } deltaxy = size.y - size.x; // distance between centers of the oval if( trace_mode == FILLED ) { FlashPadRect( pos, wxSize( size.x, deltaxy + KiROUND( penDiameter ) ), orient, trace_mode ); cx = 0; cy = deltaxy / 2; RotatePoint( &cx, &cy, orient ); FlashPadCircle( wxPoint( cx + pos.x, cy + pos.y ), size.x, trace_mode ); cx = 0; cy = -deltaxy / 2; RotatePoint( &cx, &cy, orient ); FlashPadCircle( wxPoint( cx + pos.x, cy + pos.y ), size.x, trace_mode ); } else // Plot in outline mode. { sketchOval( pos, size, orient, KiROUND( penDiameter ) ); } }
void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, EDA_DRAW_MODE_T aTraceMode, void* aData ) { // A Pad custom is plotted as polygon. // A flashed circle @aPadPos is added (anchor pad) // However, because the anchor pad can be circle or rect, we use only // a circle not bigger than the rect. // the main purpose is to print a flashed DCode as pad anchor if( aTraceMode == FILLED ) FlashPadCircle( aPadPos, std::min( aSize.x, aSize.y ), aTraceMode, 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 } SHAPE_POLY_SET polyshape = *aPolygons; if( aTraceMode != FILLED ) { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); polyshape.Inflate( -GetCurrentLineWidth()/2, 16 ); } std::vector< wxPoint > cornerList; for( int cnt = 0; cnt < polyshape.OutlineCount(); ++cnt ) { SHAPE_LINE_CHAIN& poly = polyshape.Outline( cnt ); cornerList.clear(); 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 ); } }
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 GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) { // Currently, a Pad Trapezoid is plotted as polygon. // TODO: use Aperture macro and flash it // polygon corners list std::vector< wxPoint > cornerList; for( int ii = 0; ii < 4; ii++ ) cornerList.push_back( aCorners[ii] ); // Now, flash a pad anchor, if a netlist attribute is set // (remove me when a Aperture macro will be used) if( aData && ( aTrace_Mode == FILLED ) ) { // Calculate the radius of the circle inside the shape // It is the smaller dist from shape pos to edges int radius = INT_MAX; for( unsigned ii = 0, jj = cornerList.size()-1; ii < cornerList.size(); jj = ii, ii++ ) { SEG segment( aCorners[ii], aCorners[jj] ); int dist = segment.LineDistance( VECTOR2I( 0, 0) ); radius = std::min( radius, dist ); } FlashPadCircle( aPadPos, radius*2, aTrace_Mode, aData ); } // Draw the polygon and fill the interior as required for( unsigned ii = 0; ii < 4; ii++ ) { RotatePoint( &cornerList[ii], aPadOrient ); cornerList[ii] += aPadPos; } // Close the polygon cornerList.push_back( cornerList[0] ); GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData ); GBR_METADATA metadata; if( gbr_metadata ) { metadata = *gbr_metadata; // If the pad is drawn on a copper layer, // set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR if( metadata.IsCopper() ) metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); wxString attrname( ".P" ); metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers } SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &metadata ); PlotPoly( cornerList, aTrace_Mode == FILLED ? FILLED_SHAPE : NO_FILL, aTrace_Mode == FILLED ? 0 : GetCurrentLineWidth(), &metadata ); }
void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); wxSize size( aSize ); GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData ); /* Plot a flashed shape. */ if( ( orient == 0 || orient == 900 || orient == 1800 || orient == 2700 ) && trace_mode == FILLED ) { if( orient == 900 || orient == 2700 ) /* orientation turned 90 deg. */ std::swap( size.x, size.y ); DPOINT pos_dev = userToDeviceCoordinates( pos ); int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0; selectAperture( size, APERTURE::Oval, aperture_attrib ); if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); emitDcode( pos_dev, 3 ); } else /* Plot pad as a segment. */ { if( size.x > size.y ) { std::swap( size.x, size.y ); if( orient < 2700 ) orient += 900; else orient -= 2700; } if( trace_mode == FILLED ) { // TODO: use an aperture macro to declare the rotated pad // Flash a pad anchor, if a netlist attribute is set if( aData ) FlashPadCircle( pos, size.x, trace_mode, aData ); // The pad is reduced to an segment with dy > dx int delta = size.y - size.x; int x0 = 0; int y0 = -delta / 2; int x1 = 0; int y1 = delta / 2; RotatePoint( &x0, &y0, orient ); RotatePoint( &x1, &y1, orient ); GBR_METADATA metadata; if( gbr_metadata ) { metadata = *gbr_metadata; // If the pad is drawn on a copper layer, // set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR if( metadata.IsCopper() ) metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); // Clear .P attribute, only allowed for flashed items wxString attrname( ".P" ); metadata.m_NetlistMetadata.ClearAttribute( &attrname ); } ThickSegment( wxPoint( pos.x + x0, pos.y + y0 ), wxPoint( pos.x + x1, pos.y + y1 ), size.x, trace_mode, &metadata ); } else { sketchOval( pos, size, orient, -1 ); } } }