From afc94fdec395f0520ba576948531e2cd6f3223ce Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Sun, 16 Aug 2020 12:36:58 -0700 Subject: [PATCH] PNS: Be better about handling multiple layers Rather than adding pads/vias multiple times for each layer, we introduce the "alternate shape" idiom to PNS that allows us to optionally place the collision constraint on the hole instead of the pad for those vias/pads that have inner layers removed. Fixes https://gitlab.com/kicad/code/kicad/issues/5158 Fixes https://gitlab.com/kicad/code/kicad/issues/5198 Fixes https://gitlab.com/kicad/code/kicad/issues/5195 --- libs/kimath/include/geometry/shape_index.h | 16 +++++ pcbnew/router/pns_arc.cpp | 2 +- pcbnew/router/pns_arc.h | 2 +- pcbnew/router/pns_index.cpp | 11 +++- pcbnew/router/pns_item.cpp | 22 ++++++- pcbnew/router/pns_item.h | 9 ++- pcbnew/router/pns_kicad_iface.cpp | 76 ++++++++++++++-------- pcbnew/router/pns_kicad_iface.h | 4 +- pcbnew/router/pns_line.cpp | 6 +- pcbnew/router/pns_node.cpp | 5 +- pcbnew/router/pns_router.h | 1 + pcbnew/router/pns_segment.h | 2 +- pcbnew/router/pns_shove.cpp | 8 +-- pcbnew/router/pns_solid.cpp | 19 ++++-- pcbnew/router/pns_solid.h | 29 +++++++-- pcbnew/router/pns_via.cpp | 12 ++-- pcbnew/router/pns_via.h | 12 +++- 17 files changed, 171 insertions(+), 65 deletions(-) diff --git a/libs/kimath/include/geometry/shape_index.h b/libs/kimath/include/geometry/shape_index.h index 5ba1fe30e2..b0607875f6 100644 --- a/libs/kimath/include/geometry/shape_index.h +++ b/libs/kimath/include/geometry/shape_index.h @@ -217,6 +217,13 @@ class SHAPE_INDEX */ void Add( T aShape ); + /** + * Adds a shape with alternate BBox + * @param aShape Shape (Item) to add + * @param aBbox alternate bounding box. This should be a subset of the item's bbox + */ + void Add( T aShape, const BOX2I& aBbox ); + /** * Function Remove() * @@ -307,6 +314,15 @@ SHAPE_INDEX::~SHAPE_INDEX() delete this->m_tree; } +template +void SHAPE_INDEX::Add( T aShape, const BOX2I& aBbox ) +{ + int min[2] = { aBbox.GetX(), aBbox.GetY() }; + int max[2] = { aBbox.GetRight(), aBbox.GetBottom() }; + + this->m_tree->Insert( min, max, aShape ); +} + template void SHAPE_INDEX::Add( T aShape ) { diff --git a/pcbnew/router/pns_arc.cpp b/pcbnew/router/pns_arc.cpp index 0b1dcb58b4..9ec46eeb9e 100644 --- a/pcbnew/router/pns_arc.cpp +++ b/pcbnew/router/pns_arc.cpp @@ -29,7 +29,7 @@ namespace PNS { -const SHAPE_LINE_CHAIN ARC::Hull( int aClearance, int aWalkaroundThickness ) const +const SHAPE_LINE_CHAIN ARC::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const { return ArcHull( m_arc, aClearance, aWalkaroundThickness ); } diff --git a/pcbnew/router/pns_arc.h b/pcbnew/router/pns_arc.h index fa97ea8c2f..2323f40ad4 100644 --- a/pcbnew/router/pns_arc.h +++ b/pcbnew/router/pns_arc.h @@ -92,7 +92,7 @@ public: return SHAPE_LINE_CHAIN( m_arc ); } - const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const override; + const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const override; virtual VECTOR2I Anchor( int n ) const override { diff --git a/pcbnew/router/pns_index.cpp b/pcbnew/router/pns_index.cpp index 4e64fcba24..bba8bf1827 100644 --- a/pcbnew/router/pns_index.cpp +++ b/pcbnew/router/pns_index.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -20,6 +20,7 @@ */ #include "pns_index.h" +#include "pns_router.h" namespace PNS { @@ -32,7 +33,13 @@ void INDEX::Add( ITEM* aItem ) m_subIndices.resize( 2 * range.End() + 1 ); // +1 handles the 0 case for( int i = range.Start(); i <= range.End(); ++i ) - m_subIndices[i].Add( aItem ); + { + if( ROUTER::GetInstance()->GetInterface()->IsPadOnLayer( aItem, i ) + && aItem->AlternateShape() ) + m_subIndices[i].Add( aItem, aItem->AlternateShape()->BBox() ); + else + m_subIndices[i].Add( aItem ); + } m_allItems.insert( aItem ); int net = aItem->Net(); diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index 3103c12a0d..2197e08efa 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -22,6 +22,7 @@ #include "pns_node.h" #include "pns_item.h" #include "pns_line.h" +#include "pns_router.h" typedef VECTOR2I::extended_type ecoord; @@ -30,6 +31,9 @@ namespace PNS { bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I* aMTV, const NODE* aParentNode, bool aDifferentNetsOnly ) const { + const SHAPE* shapeA = Shape(); + const SHAPE* shapeB = aOther->Shape(); + // same nets? no collision! if( aDifferentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 ) return false; @@ -38,10 +42,22 @@ bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, VEC if( !m_layers.Overlaps( aOther->m_layers ) ) return false; + if( !aOther->Layers().IsMultilayer() + && !ROUTER::GetInstance()->GetInterface()->IsPadOnLayer( this, aOther->Layer() ) ) + { + shapeA = AlternateShape(); + } + + if( !Layers().IsMultilayer() + && !ROUTER::GetInstance()->GetInterface()->IsPadOnLayer( aOther, Layer() ) ) + { + shapeB = aOther->AlternateShape(); + } + if( aNeedMTV ) - return Shape()->Collide( aOther->Shape(), aClearance, aMTV ); + return shapeA->Collide( shapeB, aClearance, aMTV ); else - return Shape()->Collide( aOther->Shape(), aClearance ); + return shapeA->Collide( shapeB, aClearance ); } diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index dd879e4288..a754cc13bd 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2017 CERN - * Copyright (C) 2016-2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -110,7 +110,7 @@ public: * @param aClearance defines how far from the body of the item the hull should be, * @param aWalkaroundThickness is the width of the line that walks around this hull. */ - virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const + virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0, int aLayer = -1 ) const { return SHAPE_LINE_CHAIN(); } @@ -216,6 +216,11 @@ public: return NULL; } + virtual const SHAPE* AlternateShape() const + { + return Shape(); + } + virtual void Mark( int aMarker ) { m_marker = aMarker; } virtual void Unmark( int aMarker = -1 ) { m_marker &= ~aMarker; } virtual int Marker() const { return m_marker; } diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index d39fc2bdea..6a3432fead 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -618,6 +618,9 @@ 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_STANDARD ) + solid->SetAlternateShape( aPad->GetEffectiveHoleShape()->Clone() ); + solid->SetLayers( layers ); solid->SetNet( aPad->GetNetCode() ); solid->SetParent( aPad ); @@ -634,9 +637,9 @@ 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() ); @@ -693,38 +696,28 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncArc( ARC* aArc ) } -std::vector> PNS_KICAD_IFACE_BASE::syncVia( VIA* aVia ) +std::unique_ptr PNS_KICAD_IFACE_BASE::syncVia( VIA* aVia ) { std::vector> retval; PCB_LAYER_ID top, bottom; aVia->LayerPair( &top, &bottom ); - for( int layer = top; layer <= bottom; ++layer ) - { - int width = aVia->GetWidth(); + std::unique_ptr via( new PNS::VIA( + aVia->GetPosition(), + LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ), + aVia->GetWidth(), + aVia->GetDrillValue(), + aVia->GetNetCode(), + aVia->GetViaType() ) + ); - if( !aVia->IsPadOnLayer( layer ) ) - width = aVia->GetDrillValue(); + via->SetParent( aVia ); - std::unique_ptr via( new PNS::VIA( - aVia->GetPosition(), - LAYER_RANGE( layer ), - width, - aVia->GetDrillValue(), - aVia->GetNetCode(), - aVia->GetViaType() ) - ); + if( aVia->IsLocked() ) + via->Mark( PNS::MK_LOCKED ); - via->SetParent( aVia ); - - if( aVia->IsLocked() ) - via->Mark( PNS::MK_LOCKED ); - - retval.push_back( std::move( via ) ); - } - - return retval; + return std::move( via ); } @@ -893,6 +886,35 @@ bool PNS_KICAD_IFACE::IsAnyLayerVisible( const LAYER_RANGE& aLayer ) } +bool PNS_KICAD_IFACE::IsPadOnLayer( const PNS::ITEM* aItem, int aLayer ) +{ + if( !aItem->Parent() || aLayer < 0) + return aItem->Layers().Overlaps( aLayer ); + + switch( aItem->Parent()->Type() ) + { + case PCB_VIA_T: + { + const VIA* via = static_cast( aItem->Parent() ); + + return via->IsPadOnLayer( static_cast( aLayer ) ); + } + + case PCB_PAD_T: + { + const D_PAD* pad = static_cast( aItem->Parent() ); + + return pad->IsPadOnLayer( static_cast( aLayer ) ); + } + + default: + break; + } + + return aItem->Layers().Overlaps( aLayer ); +} + + bool PNS_KICAD_IFACE::IsItemVisible( const PNS::ITEM* aItem ) { // by default, all items are visible (new ones created by the router have parent == NULL as they have not been @@ -1012,9 +1034,7 @@ void PNS_KICAD_IFACE_BASE::SyncWorld( PNS::NODE *aWorld ) } else if( type == PCB_VIA_T ) { - auto viavec = syncVia( static_cast( t ) ); - - for( auto& via : viavec ) + if( auto via = syncVia( static_cast( t ) ) ) aWorld->Add( std::move( via ) ); } } diff --git a/pcbnew/router/pns_kicad_iface.h b/pcbnew/router/pns_kicad_iface.h index 5587d9c8ea..b31aaa06c2 100644 --- a/pcbnew/router/pns_kicad_iface.h +++ b/pcbnew/router/pns_kicad_iface.h @@ -53,6 +53,7 @@ public: void SetBoard( BOARD* aBoard ); void SyncWorld( PNS::NODE* aWorld ) override; bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) override { return true; }; + bool IsPadOnLayer( const PNS::ITEM* aItem, int aLayer ) override { return true; }; bool IsItemVisible( const PNS::ITEM* aItem ) override { return true; } void HideItem( PNS::ITEM* aItem ) override {} void DisplayItem( const PNS::ITEM* aItem, int aColor = 0, int aClearance = 0, bool aEdit = false ) override {} @@ -84,7 +85,7 @@ protected: std::unique_ptr syncPad( D_PAD* aPad ); std::unique_ptr syncTrack( TRACK* aTrack ); std::unique_ptr syncArc( ARC* aArc ); - std::vector> syncVia( VIA* aVia ); + std::unique_ptr syncVia( VIA* aVia ); bool syncTextItem( PNS::NODE* aWorld, EDA_TEXT* aText, PCB_LAYER_ID aLayer ); bool syncGraphicalItem( PNS::NODE* aWorld, DRAWSEGMENT* aItem ); bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone ); @@ -105,6 +106,7 @@ public: void EraseView() override; bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) override; bool IsItemVisible( const PNS::ITEM* aItem ) override; + bool IsPadOnLayer( const PNS::ITEM* aItem, int aLayer ) override; void HideItem( PNS::ITEM* aItem ) override; void DisplayItem( const PNS::ITEM* aItem, int aColor = 0, int aClearance = 0, bool aEdit = false ) override; void Commit() override; diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index d7f26e7c05..926ce0645b 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -184,7 +184,7 @@ bool LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, const SEG& a = line.CSegment(i); bool over = false; - + for( int j = 0; j < aObstacle.SegmentCount(); j++ ) { const SEG& so = aObstacle.CSegment(j); @@ -211,7 +211,7 @@ bool LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre, for( int j = 0; j < aObstacle.SegmentCount(); j++ ) { OPT_VECTOR2I p; - + bool cont_a = aObstacle.CSegment(j).Contains( a.A ); bool cont_b = aObstacle.CSegment(j).Contains( a.B ); @@ -393,7 +393,7 @@ bool LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle, SHAPE_LINE_CHAIN& aPat } -const SHAPE_LINE_CHAIN SEGMENT::Hull( int aClearance, int aWalkaroundThickness ) const +const SHAPE_LINE_CHAIN SEGMENT::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const { return SegmentHull( m_seg, aClearance, aWalkaroundThickness ); } diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index c21193a907..1d16c12ded 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -343,7 +343,7 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aItem, int aKindMask, int clearance = GetClearance( obs.m_item, &aLine ); - SHAPE_LINE_CHAIN hull = obs.m_item->Hull( clearance, aItem->Width() ); + SHAPE_LINE_CHAIN hull = obs.m_item->Hull( clearance, aItem->Width(), aItem->Layer() ); if( aLine.EndsWithVia() ) { @@ -553,6 +553,7 @@ void NODE::Add( std::unique_ptr< SOLID > aSolid ) void NODE::addVia( VIA* aVia ) { linkJoint( aVia->Pos(), aVia->Layers(), aVia->Net(), aVia ); + m_index->Add( aVia ); } @@ -1226,7 +1227,7 @@ void NODE::GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded ) if( m_override.size() ) aRemoved.reserve( m_override.size() ); - + if( m_index->Size() ) aAdded.reserve( m_index->Size() ); diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index e6f20c5337..c7c9af827e 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -100,6 +100,7 @@ enum DRAG_MODE virtual void RemoveItem( ITEM* aItem ) = 0; virtual bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) = 0; virtual bool IsItemVisible( const PNS::ITEM* aItem ) = 0; + virtual bool IsPadOnLayer( const PNS::ITEM* aItem, int aLayer ) = 0; virtual void DisplayItem( const ITEM* aItem, int aColor = -1, int aClearance = -1, bool aEdit = false ) = 0; virtual void HideItem( ITEM* aItem ) = 0; virtual void Commit() = 0; diff --git a/pcbnew/router/pns_segment.h b/pcbnew/router/pns_segment.h index 90bfd500f1..e8c21d92ca 100644 --- a/pcbnew/router/pns_segment.h +++ b/pcbnew/router/pns_segment.h @@ -101,7 +101,7 @@ public: m_seg.SetSeg( SEG (tmp.B , tmp.A ) ); } - const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const override; + const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness, int aLayer = -1 ) const override; virtual VECTOR2I Anchor( int n ) const override { diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index 3f6ef773bb..2fae50c730 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -119,7 +119,7 @@ bool SHOVE::checkBumpDirection( const LINE& aCurrent, const LINE& aObstacle, con SHAPE_LINE_CHAIN::POINT_INSIDE_TRACKER checker( aCurrent.CPoint(0) ); checker.AddPolyline( aObstacle.CLine() ); checker.AddPolyline( aShoved.CLine().Reverse() ); - + bool inside = checker.IsInside(); return !inside; @@ -129,7 +129,7 @@ bool SHOVE::checkBumpDirection( const LINE& aCurrent, const LINE& aObstacle, con SHOVE::SHOVE_STATUS SHOVE::walkaroundLoneVia( LINE& aCurrent, LINE& aObstacle, LINE& aShoved ) { int clearance = getClearance( &aCurrent, &aObstacle ); - const SHAPE_LINE_CHAIN hull = aCurrent.Via().Hull( clearance, aObstacle.Width() ); + const SHAPE_LINE_CHAIN hull = aCurrent.Via().Hull( clearance, aObstacle.Width(), aCurrent.Layer() ); SHAPE_LINE_CHAIN path_cw; SHAPE_LINE_CHAIN path_ccw; @@ -241,7 +241,7 @@ SHOVE::SHOVE_STATUS SHOVE::processHullSet( LINE& aCurrent, LINE& aObstacle, sprintf(str,"att-%d-shoved", attempt); Dbg()->AddLine( l.CLine(), 3, 20000, str ); #endif - + if( ( aCurrent.Marker() & MK_HEAD ) && !colliding ) { JOINT* jtStart = m_currentNode->FindJoint( aCurrent.CPoint( 0 ), &aCurrent ); @@ -302,7 +302,7 @@ SHOVE::SHOVE_STATUS SHOVE::ProcessSingleLine( LINE& aCurrent, LINE& aObstacle, L int clearance = getClearance( &aCurrent, &aObstacle ) + 1; #ifdef DEBUG - Dbg()->Message( wxString::Format( "shove process-single: cur net %d obs %d cl %d", aCurrent.Net(), aObstacle.Net(), clearance ) ); + Dbg()->Message( wxString::Format( "shove process-single: cur net %d obs %d cl %d", aCurrent.Net(), aObstacle.Net(), clearance ) ); #endif HULL_SET hulls; diff --git a/pcbnew/router/pns_solid.cpp b/pcbnew/router/pns_solid.cpp index bb5252764a..8202707e04 100644 --- a/pcbnew/router/pns_solid.cpp +++ b/pcbnew/router/pns_solid.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -27,26 +27,31 @@ #include #include +#include "pns_router.h" #include "pns_solid.h" #include "pns_utils.h" namespace PNS { -const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness ) const +const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const { int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2; + SHAPE* shape = m_shape; - switch( m_shape->Type() ) + if( !ROUTER::GetInstance()->GetInterface()->IsPadOnLayer( this, aLayer ) ) + shape = m_alternateShape; + + switch( shape->Type() ) { case SH_RECT: { - SHAPE_RECT* rect = static_cast( m_shape ); + SHAPE_RECT* rect = static_cast( shape ); return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl ); } case SH_CIRCLE: { - SHAPE_CIRCLE* circle = static_cast( m_shape ); + SHAPE_CIRCLE* circle = static_cast( shape ); int r = circle->GetRadius(); return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), cl + 1, 0.52 * ( r + cl ) ); @@ -54,13 +59,13 @@ const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness ) c case SH_SEGMENT: { - SHAPE_SEGMENT* seg = static_cast( m_shape ); + SHAPE_SEGMENT* seg = static_cast( shape ); return SegmentHull( *seg, aClearance, aWalkaroundThickness ); } case SH_SIMPLE: { - SHAPE_SIMPLE* convex = static_cast( m_shape ); + SHAPE_SIMPLE* convex = static_cast( shape ); return ConvexHull( *convex, cl ); } diff --git a/pcbnew/router/pns_solid.h b/pcbnew/router/pns_solid.h index 77d86d21d0..b06c02c600 100644 --- a/pcbnew/router/pns_solid.h +++ b/pcbnew/router/pns_solid.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013 CERN - * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -35,7 +35,7 @@ namespace PNS { class SOLID : public ITEM { public: - SOLID() : ITEM( SOLID_T ), m_shape( NULL ) + SOLID() : ITEM( SOLID_T ), m_shape( NULL ), m_alternateShape( NULL ) { m_movable = false; m_padToDie = 0; @@ -49,7 +49,14 @@ public: SOLID( const SOLID& aSolid ) : ITEM( aSolid ) { + if( m_shape ) + delete m_shape; + + if( m_alternateShape ) + delete m_alternateShape; + m_shape = aSolid.m_shape->Clone(); + m_alternateShape = aSolid.m_alternateShape->Clone(); m_pos = aSolid.m_pos; m_padToDie = aSolid.m_padToDie; } @@ -63,7 +70,12 @@ public: const SHAPE* Shape() const override { return m_shape; } - const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const override; + const SHAPE* AlternateShape() const override + { + return m_alternateShape; + } + + const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0, int aLayer = -1 ) const override; void SetShape( SHAPE* shape ) { @@ -73,13 +85,21 @@ public: m_shape = shape; } + void SetAlternateShape( SHAPE* shape ) + { + if( m_alternateShape ) + delete m_alternateShape; + + m_alternateShape = shape; + } + const VECTOR2I& Pos() const { return m_pos; } void SetPos( const VECTOR2I& aCenter ); - + int GetPadToDie() const { return m_padToDie; @@ -113,6 +133,7 @@ public: private: VECTOR2I m_pos; SHAPE* m_shape; + SHAPE* m_alternateShape; VECTOR2I m_offset; int m_padToDie; }; diff --git a/pcbnew/router/pns_via.cpp b/pcbnew/router/pns_via.cpp index 5f7b69862e..1a8916e1ae 100644 --- a/pcbnew/router/pns_via.cpp +++ b/pcbnew/router/pns_via.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -71,13 +71,17 @@ bool VIA::PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForc } -const SHAPE_LINE_CHAIN VIA::Hull( int aClearance, int aWalkaroundThickness ) const +const SHAPE_LINE_CHAIN VIA::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const { int cl = ( aClearance + aWalkaroundThickness / 2 ); + int width = m_diameter; + + if( !ROUTER::GetInstance()->GetInterface()->IsPadOnLayer( this, aLayer ) ) + width = m_drill; return OctagonalHull( m_pos - - VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter, m_diameter ), - cl + 1, ( 2 * cl + m_diameter ) * 0.26 ); + VECTOR2I( width / 2, width / 2 ), VECTOR2I( width, width ), + cl + 1, ( 2 * cl + width ) * 0.26 ); } diff --git a/pcbnew/router/pns_via.h b/pcbnew/router/pns_via.h index ef100981e9..58d5e2f562 100644 --- a/pcbnew/router/pns_via.h +++ b/pcbnew/router/pns_via.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -66,6 +66,7 @@ public: m_diameter = aDiameter; m_drill = aDrill; m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 ); + m_alternateShape = SHAPE_CIRCLE( m_pos, aDrill / 2 ); m_viaType = aViaType; } @@ -78,6 +79,7 @@ public: m_pos = aB.m_pos; m_diameter = aB.m_diameter; m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 ); + m_alternateShape = SHAPE_CIRCLE( m_pos, aB.m_drill / 2 ); m_marker = aB.m_marker; m_rank = aB.m_rank; m_drill = aB.m_drill; @@ -143,9 +145,14 @@ public: return &m_shape; } + const SHAPE* AlternateShape() const override + { + return &m_alternateShape; + } + VIA* Clone() const override; - const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const override; + const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0, int aLayer = -1 ) const override; virtual VECTOR2I Anchor( int n ) const override { @@ -166,6 +173,7 @@ private: int m_drill; VECTOR2I m_pos; SHAPE_CIRCLE m_shape; + SHAPE_CIRCLE m_alternateShape; VIATYPE m_viaType; };