From d063c56971a6aad50f9f724fd547d69108123a1e Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 5 Oct 2020 14:55:52 +0100 Subject: [PATCH] Move PNS pad solids to COMPOUND_SHAPE. Also fixes plated holes solids to include plating thickness. --- pcbnew/router/pns_kicad_iface.cpp | 52 ++--- pcbnew/router/router_preview_item.cpp | 265 +++++++++++++++----------- pcbnew/router/router_preview_item.h | 4 +- 3 files changed, 177 insertions(+), 144 deletions(-) diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 4d4849daec..b937107d32 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -37,14 +36,11 @@ #include #include #include -#include #include #include #include -#include -#include #include #include @@ -62,7 +58,6 @@ #include "pns_solid.h" #include "pns_segment.h" #include "pns_node.h" -#include "pns_topology.h" #include "pns_router.h" #include "pns_debug_decorator.h" #include "router_preview_item.h" @@ -137,11 +132,11 @@ PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER_I } // Build clearance cache for pads - for( auto mod : m_board->Modules() ) + for( MODULE* mod : m_board->Modules() ) { - auto moduleClearance = mod->GetLocalClearance(); + int moduleClearance = mod->GetLocalClearance(); - for( auto pad : mod->Pads() ) + for( D_PAD* pad : mod->Pads() ) { int padClearance = pad->GetLocalClearance(); @@ -582,8 +577,7 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncPad( D_PAD* aPad ) LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 ); // ignore non-copper pads except for those with holes - if( ( aPad->GetLayerSet() & LSET::AllCuMask()).none() && - aPad->GetAttribute() != PAD_ATTRIB_NPTH ) + if( ( aPad->GetLayerSet() & LSET::AllCuMask() ).none() && aPad->GetDrillSize().x == 0 ) return NULL; switch( aPad->GetAttribute() ) @@ -624,9 +618,18 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncPad( D_PAD* aPad ) std::unique_ptr< PNS::SOLID > solid( new PNS::SOLID ); - if( aPad->GetAttribute() == PAD_ATTRIB_PTH || - aPad->GetAttribute() == PAD_ATTRIB_NPTH ) - solid->SetAlternateShape( aPad->GetEffectiveHoleShape()->Clone() ); + if( aPad->GetDrillSize().x > 0 ) + { + SHAPE_SEGMENT* slot = (SHAPE_SEGMENT*) aPad->GetEffectiveHoleShape()->Clone(); + + if( aPad->GetAttribute() != PAD_ATTRIB_NPTH ) + { + BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + slot->SetWidth( slot->GetWidth() + bds.GetHolePlatingThickness() * 2 ); + } + + solid->SetAlternateShape( slot ); + } if( aPad->GetAttribute() == PAD_ATTRIB_NPTH ) solid->SetRoutable( false ); @@ -637,7 +640,6 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncPad( D_PAD* aPad ) solid->SetPadToDie( aPad->GetPadToDieLength() ); wxPoint wx_c = aPad->ShapePos(); - wxSize wx_sz = aPad->GetSize(); wxPoint offset = aPad->GetOffset(); VECTOR2I c( wx_c.x, wx_c.y ); @@ -646,27 +648,7 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncPad( D_PAD* aPad ) solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); solid->SetOffset( VECTOR2I( offset.x, offset.y ) ); - - - auto shapes = std::dynamic_pointer_cast( aPad->GetEffectiveShape() ); - - if( shapes && shapes->Size() == 1 ) - { - solid->SetShape( shapes->Shapes()[0]->Clone() ); - } - else - { - // JEY TODO: - // TOM TODO: move to SHAPE_COMPOUND... - - const std::shared_ptr& outline = aPad->GetEffectivePolygon(); - SHAPE_SIMPLE* shape = new SHAPE_SIMPLE(); - - for( auto iter = outline->CIterate( 0 ); iter; iter++ ) - shape->Append( *iter ); - - solid->SetShape( shape ); - } + solid->SetShape( aPad->GetEffectiveShape()->Clone() ); return solid; } diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp index e612695c58..812fcc9ace 100644 --- a/pcbnew/router/router_preview_item.cpp +++ b/pcbnew/router/router_preview_item.cpp @@ -152,135 +152,141 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const } -void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN& aL, KIGFX::GAL* gal ) const +void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN_BASE* aL, KIGFX::GAL* gal ) const { gal->SetIsFill( false ); - for( int s = 0; s < aL.SegmentCount(); s++ ) - gal->DrawLine( aL.CSegment( s ).A, aL.CSegment( s ).B ); + for( int s = 0; s < aL->GetSegmentCount(); s++ ) + gal->DrawLine( aL->GetSegment( s ).A, aL->GetSegment( s ).B ); - for( size_t s = 0; s < aL.ArcCount(); s++ ) + const SHAPE_LINE_CHAIN* lineChain = dynamic_cast( aL ); + + for( size_t s = 0; lineChain && s < lineChain->ArcCount(); s++ ) { - auto arc = aL.CArcs()[s]; + const SHAPE_ARC& arc = lineChain->CArcs()[s]; - auto start_angle = DEG2RAD( arc.GetStartAngle() ); - auto angle = DEG2RAD( arc.GetCentralAngle() ); + double start_angle = DEG2RAD( arc.GetStartAngle() ); + double angle = DEG2RAD( arc.GetCentralAngle() ); gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, start_angle + angle); } - if( aL.IsClosed() ) - gal->DrawLine( aL.CSegment( -1 ).B, aL.CSegment( 0 ).A ); + if( aL->IsClosed() ) + gal->DrawLine( aL->GetSegment( -1 ).B, aL->GetSegment( 0 ).A ); } -void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const +void ROUTER_PREVIEW_ITEM::drawShape( const SHAPE* aShape, KIGFX::GAL* gal ) const { - auto gal = aView->GetGAL(); - //col.Brighten(0.7); - - if( m_type == PR_SHAPE ) + switch( aShape->Type() ) { - if( !m_shape ) - return; + case SH_POLY_SET_TRIANGLE: + { + const SHAPE_LINE_CHAIN_BASE* l = (const SHAPE_LINE_CHAIN_BASE*) aShape; - // N.B. The order of draw here is important - // Cairo doesn't current support z-ordering, so we need - // to draw the clearance first to ensure it is in the background - gal->SetLayerDepth( ClearanceOverlayDepth ); - //TODO(snh) Add configuration option for the color/alpha here - gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) ); - gal->SetFillColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.7 ) ); + if( m_showTrackClearance && m_clearance > 0 ) + { + gal->SetLineWidth( m_width + 2 * m_clearance ); + drawLineChain( l, gal ); + } + + gal->SetLayerDepth( m_depth ); + gal->SetLineWidth( m_width ); + gal->SetStrokeColor( m_color ); + gal->SetFillColor( m_color ); + drawLineChain( l, gal ); + break; + } + + case SH_LINE_CHAIN: + { + const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) aShape; + const int w = l->Width(); + + if( m_showTrackClearance && m_clearance > 0 ) + { + gal->SetLineWidth( w + 2 * m_clearance ); + drawLineChain( l, gal ); + } + + gal->SetLayerDepth( m_depth ); + gal->SetLineWidth( w ); + gal->SetStrokeColor( m_color ); + gal->SetFillColor( m_color ); + drawLineChain( l, gal ); + break; + } + + case SH_SEGMENT: + { + const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) aShape; + const int w = s->GetWidth(); + + if( m_showTrackClearance && m_clearance > 0 ) + { + gal->SetLineWidth( w + 2 * m_clearance ); + gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance ); + } + + gal->SetLayerDepth( m_depth ); + gal->SetLineWidth( w ); + gal->SetStrokeColor( m_color ); + gal->SetFillColor( m_color ); + gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() ); + break; + } + + case SH_CIRCLE: + { + const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) aShape; + gal->SetStrokeColor( m_color ); + + if( m_showViaClearance && m_clearance > 0 ) + { + gal->SetIsStroke( false ); + gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance ); + } + + gal->SetLayerDepth( m_depth ); gal->SetIsStroke( m_width ? true : false ); - gal->SetIsFill( true ); + gal->SetLineWidth( m_width ); + gal->SetFillColor( m_color ); + gal->DrawCircle( c->GetCenter(), c->GetRadius() ); - switch( m_shape->Type() ) + break; + } + + case SH_RECT: + { + const SHAPE_RECT* r = (const SHAPE_RECT*) aShape; + const int w = r->GetWidth(); + gal->SetFillColor( m_color ); + + if( m_clearance > 0 ) { - case SH_LINE_CHAIN: - { - const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) m_shape; - - if( m_showTrackClearance && m_clearance > 0 ) - { - gal->SetLineWidth( m_width + 2 * m_clearance ); - drawLineChain( *l, gal ); - } - - gal->SetLayerDepth( m_depth ); - gal->SetLineWidth( m_width ); - gal->SetStrokeColor( m_color ); - gal->SetFillColor( m_color ); - drawLineChain( *l, gal ); - break; + VECTOR2I p0( r->GetPosition() ), s( r->GetSize() ); + gal->SetIsStroke( true ); + gal->SetLineWidth( 2 * m_clearance ); + gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) ); + gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) ); + gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) ); + gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) ); } - case SH_SEGMENT: - { - const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) m_shape; + gal->SetLayerDepth( m_depth ); + gal->SetIsStroke( w ? true : false ); + gal->SetLineWidth( w ); + gal->SetStrokeColor( m_color ); + gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() ); - if( m_showTrackClearance && m_clearance > 0 ) - { - gal->SetLineWidth( m_width + 2 * m_clearance ); - gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance ); - } - - gal->SetLayerDepth( m_depth ); - gal->SetLineWidth( m_width ); - gal->SetStrokeColor( m_color ); - gal->SetFillColor( m_color ); - gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() ); - break; - } - - case SH_CIRCLE: - { - const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) m_shape; - gal->SetStrokeColor( m_color ); - - if( m_showViaClearance && m_clearance > 0 ) - { - gal->SetIsStroke( false ); - gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance ); - } - - gal->SetLayerDepth( m_depth ); - gal->SetIsStroke( m_width ? true : false ); - gal->SetLineWidth( m_width ); - gal->SetFillColor( m_color ); - gal->DrawCircle( c->GetCenter(), c->GetRadius() ); - - break; - } - - case SH_RECT: - { - const SHAPE_RECT* r = (const SHAPE_RECT*) m_shape; - gal->SetFillColor( m_color ); - - if( m_clearance > 0 ) - { - VECTOR2I p0( r->GetPosition() ), s( r->GetSize() ); - gal->SetIsStroke( true ); - gal->SetLineWidth( 2 * m_clearance ); - gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) ); - gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) ); - gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) ); - gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) ); - } - - gal->SetLayerDepth( m_depth ); - gal->SetIsStroke( m_width ? true : false ); - gal->SetLineWidth( m_width ); - gal->SetStrokeColor( m_color ); - gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() ); - - break; - } + break; + } case SH_SIMPLE: { - const SHAPE_SIMPLE* c = (const SHAPE_SIMPLE*) m_shape; + const SHAPE_SIMPLE* c = (const SHAPE_SIMPLE*) aShape; std::deque polygon = std::deque(); + for( int i = 0; i < c->PointCount(); i++ ) { polygon.push_back( c->CDPoint( i ) ); @@ -307,7 +313,8 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const case SH_ARC: { - const auto arc = static_cast( m_shape ); + const SHAPE_ARC* arc = static_cast( aShape ); + const int w = arc->GetWidth(); auto start_angle = DEG2RAD( arc->GetStartAngle() ); auto angle = DEG2RAD( arc->GetCentralAngle() ); @@ -317,21 +324,63 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const if( m_showTrackClearance && m_clearance > 0 ) { - gal->SetLineWidth( m_width + 2 * m_clearance ); + gal->SetLineWidth( w + 2 * m_clearance ); gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle ); } gal->SetLayerDepth( m_depth ); gal->SetStrokeColor( m_color ); gal->SetFillColor( m_color ); - gal->SetLineWidth( m_width ); + gal->SetLineWidth( w ); gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle ); break; } - case SH_POLY_SET: case SH_COMPOUND: - break; // Not yet in use + wxFAIL_MSG( "Router preview item: nested compound shapes not supported" ); + break; + + case SH_POLY_SET: + wxFAIL_MSG( "Router preview item: SHAPE_POLY_SET not supported" ); + break; + + case SH_NULL: + break; + } +} + + +void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const +{ + GAL* gal = aView->GetGAL(); + //col.Brighten(0.7); + + if( m_type == PR_SHAPE ) + { + if( !m_shape ) + return; + + // N.B. The order of draw here is important + // Cairo doesn't current support z-ordering, so we need + // to draw the clearance first to ensure it is in the background + gal->SetLayerDepth( ClearanceOverlayDepth ); + //TODO(snh) Add configuration option for the color/alpha here + gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) ); + gal->SetFillColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.7 ) ); + gal->SetIsStroke( m_width ? true : false ); + gal->SetIsFill( true ); + + if( m_shape->HasIndexableSubshapes() ) + { + std::vector subshapes; + m_shape->GetIndexableSubshapes( subshapes ); + + for( SHAPE* shape : subshapes ) + drawShape( shape, gal ); + } + else + { + drawShape( m_shape, gal ); } } } diff --git a/pcbnew/router/router_preview_item.h b/pcbnew/router/router_preview_item.h index 05c3aeb4c3..9960a6d815 100644 --- a/pcbnew/router/router_preview_item.h +++ b/pcbnew/router/router_preview_item.h @@ -109,7 +109,9 @@ public: aCount = 1; } - void drawLineChain( const SHAPE_LINE_CHAIN& aL, KIGFX::GAL* aGal ) const; + void drawLineChain( const SHAPE_LINE_CHAIN_BASE* aL, KIGFX::GAL* aGal ) const; + + void drawShape( const SHAPE* aShape, KIGFX::GAL* aGal ) const; private: const KIGFX::COLOR4D assignColor( int aStyle ) const;