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
This commit is contained in:
Seth Hillbrand 2020-08-16 12:36:58 -07:00
parent dbe5537fa9
commit afc94fdec3
17 changed files with 171 additions and 65 deletions

View File

@ -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<T>::~SHAPE_INDEX()
delete this->m_tree;
}
template <class T>
void SHAPE_INDEX<T>::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 <class T>
void SHAPE_INDEX<T>::Add( T aShape )
{

View File

@ -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 );
}

View File

@ -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
{

View File

@ -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 <tomasz.wlostowski@cern.ch>
*
* 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();

View File

@ -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 <tomasz.wlostowski@cern.ch>
*
* 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 );
}

View File

@ -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 <tomasz.wlostowski@cern.ch>
*
* 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; }

View File

@ -618,6 +618,9 @@ std::unique_ptr<PNS::SOLID> 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::SOLID> 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<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
if( shapes && shapes->Size() == 1 )
{
solid->SetShape( shapes->Shapes()[0]->Clone() );
@ -693,38 +696,28 @@ std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( ARC* aArc )
}
std::vector<std::unique_ptr<PNS::VIA>> PNS_KICAD_IFACE_BASE::syncVia( VIA* aVia )
std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( VIA* aVia )
{
std::vector<std::unique_ptr<PNS::VIA>> retval;
PCB_LAYER_ID top, bottom;
aVia->LayerPair( &top, &bottom );
for( int layer = top; layer <= bottom; ++layer )
{
int width = aVia->GetWidth();
std::unique_ptr<PNS::VIA> 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<PNS::VIA> 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<const VIA*>( aItem->Parent() );
return via->IsPadOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) );
}
case PCB_PAD_T:
{
const D_PAD* pad = static_cast<const D_PAD*>( aItem->Parent() );
return pad->IsPadOnLayer( static_cast<PCB_LAYER_ID>( 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<VIA*>( t ) );
for( auto& via : viavec )
if( auto via = syncVia( static_cast<VIA*>( t ) ) )
aWorld->Add( std::move( via ) );
}
}

View File

@ -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<PNS::SOLID> syncPad( D_PAD* aPad );
std::unique_ptr<PNS::SEGMENT> syncTrack( TRACK* aTrack );
std::unique_ptr<PNS::ARC> syncArc( ARC* aArc );
std::vector<std::unique_ptr<PNS::VIA>> syncVia( VIA* aVia );
std::unique_ptr<PNS::VIA> 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;

View File

@ -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 );
}

View File

@ -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() );

View File

@ -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;

View File

@ -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
{

View File

@ -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;

View File

@ -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 <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
@ -27,26 +27,31 @@
#include <geometry/shape_circle.h>
#include <geometry/shape_simple.h>
#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<SHAPE_RECT*>( m_shape );
SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( shape );
return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl );
}
case SH_CIRCLE:
{
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape );
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( 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<SHAPE_SEGMENT*>( m_shape );
SHAPE_SEGMENT* seg = static_cast<SHAPE_SEGMENT*>( shape );
return SegmentHull( *seg, aClearance, aWalkaroundThickness );
}
case SH_SIMPLE:
{
SHAPE_SIMPLE* convex = static_cast<SHAPE_SIMPLE*>( m_shape );
SHAPE_SIMPLE* convex = static_cast<SHAPE_SIMPLE*>( shape );
return ConvexHull( *convex, cl );
}

View File

@ -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 <tomasz.wlostowski@cern.ch>
*
* 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;
};

View File

@ -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 <tomasz.wlostowski@cern.ch>
*
* 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 );
}

View File

@ -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 <tomasz.wlostowski@cern.ch>
*
* 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;
};