From 1858b7dca7a6b38d52a6360783d7c4cd02e33c38 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Sat, 1 Dec 2018 21:41:17 -0700 Subject: [PATCH] pcbnew: Allow closed polygons as board edges Like circles, polygons are self-closed elements that define an outline. This allows them to be used as such for board outlines and cutouts. Fixes: lp:1795563 * https://bugs.launchpad.net/kicad/+bug/1795563 --- ...board_items_to_polygon_shape_transform.cpp | 15 ++++++++++ .../convert_drawsegment_list_to_polygon.cpp | 30 ++++++++++++++++++- pcbnew/pcb_painter.cpp | 7 ++++- pcbnew/plot_brditems_plotter.cpp | 26 +++++++++++----- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 0dbd82a497..3fcf0bd6f2 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -578,6 +578,21 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB poly[ii] += offset; } + // On the edge cuts layer, a polygon should be treated as a closed set of lines + if( m_Layer == Edge_Cuts ) + { + auto start = poly[0]; + for( size_t ii = 1; ii < poly.size(); ii++ ) + { + TransformOvalClearanceToPolygon( aCornerBuffer, poly[ii - 1], poly[ii], + linewidth, aCircleToSegmentsCount, aCorrectionFactor ); + } + + TransformOvalClearanceToPolygon( aCornerBuffer, poly[poly.size() - 1], start, + linewidth, aCircleToSegmentsCount, aCorrectionFactor ); + break; + } + // Generate polygons for the outline + clearance // This code is compatible with a polygon with holes linked to external outline // by overlapping segments. diff --git a/pcbnew/convert_drawsegment_list_to_polygon.cpp b/pcbnew/convert_drawsegment_list_to_polygon.cpp index ac73a27b97..e0d6f490d1 100644 --- a/pcbnew/convert_drawsegment_list_to_polygon.cpp +++ b/pcbnew/convert_drawsegment_list_to_polygon.cpp @@ -282,6 +282,21 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE } break; + case S_POLYGON: + { + const auto poly = graphic->GetPolyShape(); + + for( auto iter = poly.CIterate(); iter; iter++ ) + { + if( iter->x < xmin.x ) + { + xmin.x = iter->x; + xmin.y = iter->y; + xmini = i; + } + } + } + break; default: break; } @@ -302,6 +317,10 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_LOW_DEF, 360.0 ); TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps ); } + else if( graphic->GetShape() == S_POLYGON ) + { + aPolygons = graphic->GetPolyShape(); + } else { // Polygon start point. Arbitrarily chosen end of the @@ -465,7 +484,16 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE graphic = (DRAWSEGMENT*) segList[0]; segList.erase( segList.begin() ); - if( graphic->GetShape() == S_CIRCLE ) + // Both circles and polygons on the edge cuts layer are closed items that + // do not connect to other elements, so we process them independently + if( graphic->GetShape() == S_POLYGON ) + { + for( auto it = graphic->GetPolyShape().CIterate(); it; it++ ) + { + aPolygons.Append( *it, -1, hole ); + } + } + else if( graphic->GetShape() == S_CIRCLE ) { // make a circle by segments; wxPoint center = graphic->GetCenter(); diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index dc5c525e24..6c4a743835 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -995,7 +995,12 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer ) } m_gal->SetLineWidth( thickness ); - m_gal->SetIsFill( true ); + + if( aLayer != Edge_Cuts ) + m_gal->SetIsFill( true ); + else + m_gal->SetIsFill( false ); + m_gal->SetIsStroke( true ); m_gal->DrawPolygon( shape ); diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index b3ba678290..819a4ca549 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -762,14 +762,26 @@ void BRDITEMS_PLOTTER::PlotDrawSegment( DRAWSEGMENT* aSeg ) case S_POLYGON: { - m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata ); - // Draw the polygon: only one polygon is expected - // However we provide a multi polygon shape drawing - // ( for the future or to show a non expected shape ) - for( int jj = 0; jj < aSeg->GetPolyShape().OutlineCount(); ++jj ) + if( m_layerMask[ Edge_Cuts ] ) { - SHAPE_LINE_CHAIN& poly = aSeg->GetPolyShape().Outline( jj ); - m_plotter->PlotPoly( poly, FILLED_SHAPE, thickness, &gbr_metadata ); + for( auto it = aSeg->GetPolyShape().IterateSegments( 0 ); it; it++ ) + { + auto seg = it.Get(); + m_plotter->ThickSegment( wxPoint( seg.A ), wxPoint( seg.B ), + thickness, GetPlotMode(), &gbr_metadata ); + } + } + else + { + m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata ); + // Draw the polygon: only one polygon is expected + // However we provide a multi polygon shape drawing + // ( for the future or to show a non expected shape ) + for( int jj = 0; jj < aSeg->GetPolyShape().OutlineCount(); ++jj ) + { + SHAPE_LINE_CHAIN& poly = aSeg->GetPolyShape().Outline( jj ); + m_plotter->PlotPoly( poly, FILLED_SHAPE, thickness, &gbr_metadata ); + } } } break;