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:
parent
dbe5537fa9
commit
afc94fdec3
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue