diff --git a/common/plotters/DXF_plotter.cpp b/common/plotters/DXF_plotter.cpp index a22fdcd374..60fcb2c50e 100644 --- a/common/plotters/DXF_plotter.cpp +++ b/common/plotters/DXF_plotter.cpp @@ -732,7 +732,7 @@ void DXF_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize, orient += ANGLE_90; } - sketchOval( aPos, size, orient, USE_DEFAULT_LINE_WIDTH ); + ThickOval( aPos, size, orient, USE_DEFAULT_LINE_WIDTH, aData ); } diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index 137ff07d59..7aeac7fa24 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -1198,8 +1198,7 @@ void GERBER_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, i } else { - SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); - segmentAsOval( start, end, GetCurrentLineWidth(), tracemode ); + PLOTTER::ThickSegment( start, end, width, tracemode, aData ); } } @@ -1383,17 +1382,7 @@ void GERBER_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize, } else // Non filled shape: plot outlines: { - if( size.x > size.y ) - { - std::swap( size.x, size.y ); - - if( orient < ANGLE_270 ) - orient += ANGLE_90; - else - orient -= ANGLE_270; - } - - sketchOval( aPos, size, orient, USE_DEFAULT_LINE_WIDTH ); + ThickOval( aPos, size, orient, USE_DEFAULT_LINE_WIDTH, aData ); } } } diff --git a/common/plotters/PS_plotter.cpp b/common/plotters/PS_plotter.cpp index 4d2ad1e574..b6e4bc8087 100644 --- a/common/plotters/PS_plotter.cpp +++ b/common/plotters/PS_plotter.cpp @@ -115,7 +115,7 @@ void PSLIKE_PLOTTER::FlashPadOval( const VECTOR2I& aPadPos, const VECTOR2I& aSiz if( aTraceMode == FILLED ) ThickSegment( a + aPadPos, b + aPadPos, size.x, aTraceMode, nullptr ); else - sketchOval( aPadPos, size, orient, USE_DEFAULT_LINE_WIDTH ); + ThickOval( aPadPos, size, orient, USE_DEFAULT_LINE_WIDTH, nullptr ); } diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp index 351fc28590..e8f19f5ba7 100644 --- a/common/plotters/plotter.cpp +++ b/common/plotters/plotter.cpp @@ -29,7 +29,6 @@ * with different plot formats. * * There are currently engines for: - * HPGL * POSTSCRIPT * GERBER * DXF @@ -43,6 +42,7 @@ #include #include #include // for KiROUND +#include PLOTTER::PLOTTER( const PROJECT* aProject ) : m_project( aProject ) @@ -482,25 +482,10 @@ void PLOTTER::Marker( const VECTOR2I& position, int diametre, unsigned aShapeId } -void PLOTTER::segmentAsOval( const VECTOR2I& start, const VECTOR2I& end, int aWidth, - OUTLINE_MODE aTraceMode ) +void PLOTTER::ThickOval( const VECTOR2I& aPos, const VECTOR2I& aSize, const EDA_ANGLE& aOrient, + int aWidth, void* aData ) { - VECTOR2I center( ( start.x + end.x ) / 2, ( start.y + end.y ) / 2 ); - VECTOR2I size( end.x - start.x, end.y - start.y ); - EDA_ANGLE orient( size ); - orient = -orient; // this is due to our Y axis orientation - - size.x = size.EuclideanNorm() + aWidth; - size.y = aWidth; - - FlashPadOval( center, size, orient, aTraceMode, nullptr ); -} - - -void PLOTTER::sketchOval( const VECTOR2I& aPos, const VECTOR2I& aSize, const EDA_ANGLE& aOrient, - int aWidth ) -{ - SetCurrentLineWidth( aWidth ); + SetCurrentLineWidth( aWidth, aData ); EDA_ANGLE orient( aOrient ); VECTOR2I size( aSize ); @@ -568,8 +553,21 @@ void PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int widt } else { - SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); - segmentAsOval( start, end, width, tracemode ); + std::vector cornerList; + SHAPE_POLY_SET outlineBuffer; + TransformOvalToPolygon( outlineBuffer, start, end, width, GetPlotterArcHighDef(), ERROR_INSIDE ); + const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 ); + + cornerList.reserve( path.PointCount() ); + + for( int jj = 0; jj < path.PointCount(); jj++ ) + cornerList.emplace_back( path.CPoint( jj ).x, path.CPoint( jj ).y ); + + // Ensure the polygon is closed + if( cornerList[0] != cornerList[cornerList.size() - 1] ) + cornerList.push_back( cornerList[0] ); + + PlotPoly( cornerList, FILL_T::NO_FILL, USE_DEFAULT_LINE_WIDTH, aData ); } } @@ -673,6 +671,12 @@ void PLOTTER::FilledCircle( const VECTOR2I& pos, int diametre, OUTLINE_MODE trac } +void PLOTTER::ThickPoly( const SHAPE_POLY_SET& aPoly, int aWidth, void* aData ) +{ + PlotPoly( aPoly.COutline( 0 ), FILL_T::NO_FILL, aWidth, aData ); +} + + void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int aWidth, void* aData ) { std::vector cornerList; diff --git a/include/plotters/plotter.h b/include/plotters/plotter.h index 136a4e77d7..adca15aff0 100644 --- a/include/plotters/plotter.h +++ b/include/plotters/plotter.h @@ -319,6 +319,10 @@ public: virtual void FilledCircle( const VECTOR2I& pos, int diametre, OUTLINE_MODE tracemode, void* aData ); + virtual void ThickOval( const VECTOR2I& aPos, const VECTOR2I& aSize, const EDA_ANGLE& aOrient, + int aWidth, void* aData ); + + virtual void ThickPoly( const SHAPE_POLY_SET& aPoly, int aWidth, void* aData ); // Flash primitives diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 33df03fab6..00d19da1ff 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -853,6 +853,8 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt ); itemplotter.SetLayerSet( aLayerMask ); + int smallDrill = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ); + SHAPE_POLY_SET outlines; for( PCB_LAYER_ID layer : aLayerMask.Seq( aLayerMask.SeqStackupForPlotting() ) ) @@ -874,36 +876,36 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask const SHAPE_LINE_CHAIN& path = ( kk == 0 ) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 ); - aPlotter->PlotPoly( path, FILL_T::NO_FILL ); + aPlotter->PlotPoly( path, FILL_T::NO_FILL, PLOTTER::USE_DEFAULT_LINE_WIDTH, nullptr ); } } // Plot pad holes if( aPlotOpt.GetDrillMarksType() != DRILL_MARKS::NO_DRILL_SHAPE ) { - int smallDrill = ( aPlotOpt.GetDrillMarksType() == DRILL_MARKS::SMALL_DRILL_SHAPE ) - ? pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) - : INT_MAX; - for( FOOTPRINT* footprint : aBoard->Footprints() ) { for( PAD* pad : footprint->Pads() ) { if( pad->HasHole() ) { - std::shared_ptr slot = pad->GetEffectiveHoleShape(); - - if( slot->GetSeg().A == slot->GetSeg().B ) // circular hole + if( pad->GetDrillSizeX() == pad->GetDrillSizeY() ) { - int drill = std::min( smallDrill, slot->GetWidth() ); - aPlotter->Circle( pad->GetPosition(), drill, FILL_T::NO_FILL, - PLOTTER::USE_DEFAULT_LINE_WIDTH ); + int drill = pad->GetDrillSizeX(); + + if( aPlotOpt.GetDrillMarksType() == DRILL_MARKS::SMALL_DRILL_SHAPE ) + drill = std::min( smallDrill, drill ); + + aPlotter->ThickCircle( pad->ShapePos( layer ), drill, + PLOTTER::USE_DEFAULT_LINE_WIDTH, FILLED, nullptr ); } else { // Note: small drill marks have no significance when applied to slots - aPlotter->ThickSegment( slot->GetSeg().A, slot->GetSeg().B, - slot->GetWidth(), SKETCH, nullptr ); + + aPlotter->ThickOval( pad->ShapePos( layer ), pad->GetSize( layer ), + pad->GetOrientation(), PLOTTER::USE_DEFAULT_LINE_WIDTH, + nullptr ); } } } diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 808db0e1d0..59e993a52b 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -277,7 +277,50 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, PCB_LAYER_ID aLayer, const COLO m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY ); if( aPlotMode == SKETCH ) - m_plotter->SetCurrentLineWidth( GetSketchPadLineWidth(), &metadata ); + { + switch( aPad->GetShape( aLayer ) ) + { + case PAD_SHAPE::CIRCLE: + m_plotter->ThickCircle( shape_pos, aPad->GetSize( aLayer ).x, GetSketchPadLineWidth(), + FILLED, &metadata ); + break; + + case PAD_SHAPE::OVAL: + { + m_plotter->ThickOval( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(), + GetSketchPadLineWidth(), &metadata ); + break; + } + + case PAD_SHAPE::RECTANGLE: + { + VECTOR2I size = aPad->GetSize( aLayer ); + + m_plotter->ThickRect( VECTOR2I( shape_pos.x - ( size.x / 2 ), shape_pos.y - (size.y / 2 ) ), + VECTOR2I( shape_pos.x + ( size.x / 2 ), shape_pos.y + (size.y / 2 ) ), + GetSketchPadLineWidth(), FILLED, &metadata ); + break; + } + + case PAD_SHAPE::ROUNDRECT: + case PAD_SHAPE::TRAPEZOID: + case PAD_SHAPE::CHAMFERED_RECT: + case PAD_SHAPE::CUSTOM: + { + SHAPE_POLY_SET outline; + aPad->TransformShapeToPolygon( outline, aLayer, 0, m_plotter->GetPlotterArcHighDef(), + ERROR_INSIDE, true ); + + m_plotter->ThickPoly( outline, GetSketchPadLineWidth(), &metadata ); + break; + } + + default: + UNIMPLEMENTED_FOR( aPad->ShowPadShape( PADSTACK::ALL_LAYERS ) ); + } + + return; + } switch( aPad->GetShape( aLayer ) ) {