From 970921f88b58673093bf21b1d9cccf7e1756dcb0 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 19 Jun 2020 21:46:43 +0100 Subject: [PATCH] Support for filled DRAWSEGMENT::S_RECT and S_CIRCLE. One more step in unifying pad primitives and draw segments. --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 55 ++++++++++++------- .../dialog_graphic_item_properties.cpp | 30 ++++------ pcbnew/pad_custom_shape_functions.cpp | 2 + pcbnew/pcb_painter.cpp | 27 ++++++--- pcbnew/plot_brditems_plotter.cpp | 27 +++++++-- 5 files changed, 91 insertions(+), 50 deletions(-) diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index 3a6001c9ba..4bccbf6685 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -777,32 +777,49 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSe if( inner_radius < 0 ) inner_radius = 0; - aDstContainer->Add( new CRING2D( center3DU, inner_radius, outer_radius, *aDrawSegment ) ); + if( aDrawSegment->GetWidth() > 0 ) + aDstContainer->Add( new CRING2D( center3DU, inner_radius, outer_radius, *aDrawSegment ) ); + else + aDstContainer->Add( new CFILLEDCIRCLE2D( center3DU, outer_radius, *aDrawSegment ) ); } break; case S_RECT: { - std::vector pts; - aDrawSegment->GetRectCorners( &pts ); + if( aDrawSegment->GetWidth() > 0 ) + { + std::vector pts; + aDrawSegment->GetRectCorners( &pts ); - const SFVEC2F topLeft3DU( pts[0].x * m_biuTo3Dunits, -pts[0].y * m_biuTo3Dunits ); - const SFVEC2F topRight3DU( pts[1].x * m_biuTo3Dunits, -pts[1].y * m_biuTo3Dunits ); - const SFVEC2F botRight3DU( pts[2].x * m_biuTo3Dunits, -pts[2].y * m_biuTo3Dunits ); - const SFVEC2F botLeft3DU( pts[3].x * m_biuTo3Dunits, -pts[3].y * m_biuTo3Dunits ); + const SFVEC2F topLeft3DU( pts[0].x * m_biuTo3Dunits, -pts[0].y * m_biuTo3Dunits ); + const SFVEC2F topRight3DU( pts[1].x * m_biuTo3Dunits, -pts[1].y * m_biuTo3Dunits ); + const SFVEC2F botRight3DU( pts[2].x * m_biuTo3Dunits, -pts[2].y * m_biuTo3Dunits ); + const SFVEC2F botLeft3DU( pts[3].x * m_biuTo3Dunits, -pts[3].y * m_biuTo3Dunits ); - aDstContainer->Add( new CROUNDSEGMENT2D( topLeft3DU, topRight3DU, - linewidth * m_biuTo3Dunits, - *aDrawSegment ) ); - aDstContainer->Add( new CROUNDSEGMENT2D( topRight3DU, botRight3DU, - linewidth * m_biuTo3Dunits, - *aDrawSegment ) ); - aDstContainer->Add( new CROUNDSEGMENT2D( botRight3DU, botLeft3DU, - linewidth * m_biuTo3Dunits, - *aDrawSegment ) ); - aDstContainer->Add( new CROUNDSEGMENT2D( botLeft3DU, topLeft3DU, - linewidth * m_biuTo3Dunits, - *aDrawSegment ) ); + aDstContainer->Add( new CROUNDSEGMENT2D( topLeft3DU, topRight3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + aDstContainer->Add( new CROUNDSEGMENT2D( topRight3DU, botRight3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + aDstContainer->Add( new CROUNDSEGMENT2D( botRight3DU, botLeft3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + aDstContainer->Add( new CROUNDSEGMENT2D( botLeft3DU, topLeft3DU, + linewidth * m_biuTo3Dunits, + *aDrawSegment ) ); + } + else + { + SHAPE_POLY_SET polyList; + + aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aClearanceValue ); + + polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); + + Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, m_biuTo3Dunits, + *aDrawSegment ); + } } break; diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp index 1a3d5e1b09..1d625236ae 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp @@ -329,6 +329,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate() // Check angle of arc. if( m_angle.GetValue() == 0 ) error_msgs.Add( _( "The arc angle cannot be zero." ) ); + KI_FALLTHROUGH; case S_CIRCLE: @@ -337,32 +338,23 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate() error_msgs.Add( _( "The radius must be greater than zero." ) ); break; + case S_RECT: + // Check for null rect. + if( m_startX.GetValue() == m_endX.GetValue() && m_startY.GetValue() == m_endY.GetValue() ) + error_msgs.Add( _( "The rectangle can not be empty." ) ); + break; + case S_POLYGON: + case S_SEGMENT: + case S_CURVE: break; default: - // Check start and end are not the same. - if( m_startX.GetValue() == m_endX.GetValue() && m_startY.GetValue() == m_endY.GetValue() ) - error_msgs.Add( _( "The start and end points cannot be the same." ) ); + wxASSERT_MSG( false, "DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate not implemented for shape" + + DRAWSEGMENT::ShowShape( m_item->GetShape() ) ); break; } - // Check the item thickness. Note the polygon outline thickness is allowed - // to be set to 0, because if the shape is exactly the polygon, its outline - // thickness must be 0 - int thickness = m_thickness.GetValue(); - - if( m_item->GetShape() == S_POLYGON ) - { - if( thickness < 0 ) - error_msgs.Add( _( "The polygon outline thickness must be >= 0." ) ); - } - else - { - if( thickness <= 0 ) - error_msgs.Add( _( "The item thickness must be greater than zero." ) ); - } - if( error_msgs.GetCount() ) { HTML_MESSAGE_BOX dlg( this, _( "Error List" ) ); diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp index ac81e891ee..fc8946ae58 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -161,6 +161,7 @@ void D_PAD::AddPrimitivePoly( const SHAPE_POLY_SET& aPoly, int aThickness, bool AddPrimitivePoly( points, aThickness, aMergePrimitives ); } + void D_PAD::AddPrimitivePoly( const std::vector& aPoly, int aThickness, bool aMergePrimitives ) { @@ -260,6 +261,7 @@ bool D_PAD::SetPrimitives( const std::vector& aPrimitivesList return MergePrimitivesAsPolygon(); } + bool D_PAD::AddPrimitives( const std::vector& aPrimitivesList ) { for( const auto& prim : aPrimitivesList ) diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 13cf943bf6..83a9c930b0 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -919,10 +919,23 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer ) std::vector pts; aSegment->GetRectCorners( &pts ); - m_gal->DrawSegment( pts[0], pts[1], thickness ); - m_gal->DrawSegment( pts[1], pts[2], thickness ); - m_gal->DrawSegment( pts[2], pts[3], thickness ); - m_gal->DrawSegment( pts[3], pts[0], thickness ); + if( aSegment->GetWidth() > 0 ) + { + m_gal->DrawSegment( pts[0], pts[1], thickness ); + m_gal->DrawSegment( pts[1], pts[2], thickness ); + m_gal->DrawSegment( pts[2], pts[3], thickness ); + m_gal->DrawSegment( pts[3], pts[0], thickness ); + } + else + { + SHAPE_POLY_SET poly; + poly.NewOutline(); + + for( const wxPoint& pt : pts ) + poly.Append( pt ); + + m_gal->DrawPolygon( poly ); + } } break; @@ -942,15 +955,15 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer ) else { m_gal->SetLineWidth( thickness ); - m_gal->SetIsFill( false ); - m_gal->SetIsStroke( true ); + m_gal->SetIsFill( aSegment->GetWidth() == 0 ); + m_gal->SetIsStroke( aSegment->GetWidth() > 0 ); m_gal->DrawCircle( start, aSegment->GetRadius() ); } break; case S_POLYGON: { - SHAPE_POLY_SET& shape = ((DRAWSEGMENT*)aSegment)->GetPolyShape(); + SHAPE_POLY_SET& shape = const_cast( aSegment )->GetPolyShape(); if( shape.OutlineCount() == 0 ) break; diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 4335ce241f..d5c3ff36cb 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -533,16 +533,33 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItem( EDGE_MODULE* aEdge ) std::vector pts; aEdge->GetRectCorners( &pts ); - m_plotter->ThickSegment( pts[0], pts[1], thickness, GetPlotMode(), &gbr_metadata ); - m_plotter->ThickSegment( pts[1], pts[2], thickness, GetPlotMode(), &gbr_metadata ); - m_plotter->ThickSegment( pts[2], pts[3], thickness, GetPlotMode(), &gbr_metadata ); - m_plotter->ThickSegment( pts[3], pts[0], thickness, GetPlotMode(), &gbr_metadata ); + if( aEdge->GetWidth() > 0 ) + { + m_plotter->ThickSegment( pts[0], pts[1], thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( pts[1], pts[2], thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( pts[2], pts[3], thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( pts[3], pts[0], thickness, GetPlotMode(), &gbr_metadata ); + } + else + { + SHAPE_LINE_CHAIN poly; + + for( const wxPoint& pt : pts ) + poly.Append( pt ); + + m_plotter->PlotPoly( poly, FILLED_SHAPE, -1, &gbr_metadata ); + } } break; case S_CIRCLE: radius = KiROUND( GetLineLength( end, pos ) ); - m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); + + if( aEdge->GetWidth() > 0 ) + m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); + else + m_plotter->Circle( pos, radius * 2, FILLED_SHAPE, -1 ); + break; case S_ARC: