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 );
|
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()
|
* Function Remove()
|
||||||
*
|
*
|
||||||
|
@ -307,6 +314,15 @@ SHAPE_INDEX<T>::~SHAPE_INDEX()
|
||||||
delete this->m_tree;
|
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>
|
template <class T>
|
||||||
void SHAPE_INDEX<T>::Add( T aShape )
|
void SHAPE_INDEX<T>::Add( T aShape )
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
namespace PNS {
|
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 );
|
return ArcHull( m_arc, aClearance, aWalkaroundThickness );
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ public:
|
||||||
return SHAPE_LINE_CHAIN( m_arc );
|
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
|
virtual VECTOR2I Anchor( int n ) const override
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2014 CERN
|
* 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>
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pns_index.h"
|
#include "pns_index.h"
|
||||||
|
#include "pns_router.h"
|
||||||
|
|
||||||
namespace PNS {
|
namespace PNS {
|
||||||
|
|
||||||
|
@ -32,7 +33,13 @@ void INDEX::Add( ITEM* aItem )
|
||||||
m_subIndices.resize( 2 * range.End() + 1 ); // +1 handles the 0 case
|
m_subIndices.resize( 2 * range.End() + 1 ); // +1 handles the 0 case
|
||||||
|
|
||||||
for( int i = range.Start(); i <= range.End(); ++i )
|
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 );
|
m_allItems.insert( aItem );
|
||||||
int net = aItem->Net();
|
int net = aItem->Net();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2014 CERN
|
* 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>
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
#include "pns_node.h"
|
#include "pns_node.h"
|
||||||
#include "pns_item.h"
|
#include "pns_item.h"
|
||||||
#include "pns_line.h"
|
#include "pns_line.h"
|
||||||
|
#include "pns_router.h"
|
||||||
|
|
||||||
typedef VECTOR2I::extended_type ecoord;
|
typedef VECTOR2I::extended_type ecoord;
|
||||||
|
|
||||||
|
@ -30,6 +31,9 @@ namespace PNS {
|
||||||
bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I* aMTV,
|
bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I* aMTV,
|
||||||
const NODE* aParentNode, bool aDifferentNetsOnly ) const
|
const NODE* aParentNode, bool aDifferentNetsOnly ) const
|
||||||
{
|
{
|
||||||
|
const SHAPE* shapeA = Shape();
|
||||||
|
const SHAPE* shapeB = aOther->Shape();
|
||||||
|
|
||||||
// same nets? no collision!
|
// same nets? no collision!
|
||||||
if( aDifferentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 )
|
if( aDifferentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 )
|
||||||
return false;
|
return false;
|
||||||
|
@ -38,10 +42,22 @@ bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, VEC
|
||||||
if( !m_layers.Overlaps( aOther->m_layers ) )
|
if( !m_layers.Overlaps( aOther->m_layers ) )
|
||||||
return false;
|
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 )
|
if( aNeedMTV )
|
||||||
return Shape()->Collide( aOther->Shape(), aClearance, aMTV );
|
return shapeA->Collide( shapeB, aClearance, aMTV );
|
||||||
else
|
else
|
||||||
return Shape()->Collide( aOther->Shape(), aClearance );
|
return shapeA->Collide( shapeB, aClearance );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2017 CERN
|
* 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>
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* 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 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.
|
* @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();
|
return SHAPE_LINE_CHAIN();
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,11 @@ public:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const SHAPE* AlternateShape() const
|
||||||
|
{
|
||||||
|
return Shape();
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Mark( int aMarker ) { m_marker = aMarker; }
|
virtual void Mark( int aMarker ) { m_marker = aMarker; }
|
||||||
virtual void Unmark( int aMarker = -1 ) { m_marker &= ~aMarker; }
|
virtual void Unmark( int aMarker = -1 ) { m_marker &= ~aMarker; }
|
||||||
virtual int Marker() const { return m_marker; }
|
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 );
|
std::unique_ptr< PNS::SOLID > solid( new PNS::SOLID );
|
||||||
|
|
||||||
|
if( aPad->GetAttribute() == PAD_ATTRIB_STANDARD )
|
||||||
|
solid->SetAlternateShape( aPad->GetEffectiveHoleShape()->Clone() );
|
||||||
|
|
||||||
solid->SetLayers( layers );
|
solid->SetLayers( layers );
|
||||||
solid->SetNet( aPad->GetNetCode() );
|
solid->SetNet( aPad->GetNetCode() );
|
||||||
solid->SetParent( aPad );
|
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->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
|
||||||
solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
|
solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
|
||||||
|
|
||||||
|
|
||||||
auto shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
|
auto shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
|
||||||
|
|
||||||
if( shapes && shapes->Size() == 1 )
|
if( shapes && shapes->Size() == 1 )
|
||||||
{
|
{
|
||||||
solid->SetShape( shapes->Shapes()[0]->Clone() );
|
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;
|
std::vector<std::unique_ptr<PNS::VIA>> retval;
|
||||||
|
|
||||||
PCB_LAYER_ID top, bottom;
|
PCB_LAYER_ID top, bottom;
|
||||||
aVia->LayerPair( &top, &bottom );
|
aVia->LayerPair( &top, &bottom );
|
||||||
|
|
||||||
for( int layer = top; layer <= bottom; ++layer )
|
std::unique_ptr<PNS::VIA> via( new PNS::VIA(
|
||||||
{
|
aVia->GetPosition(),
|
||||||
int width = aVia->GetWidth();
|
LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ),
|
||||||
|
aVia->GetWidth(),
|
||||||
|
aVia->GetDrillValue(),
|
||||||
|
aVia->GetNetCode(),
|
||||||
|
aVia->GetViaType() )
|
||||||
|
);
|
||||||
|
|
||||||
if( !aVia->IsPadOnLayer( layer ) )
|
via->SetParent( aVia );
|
||||||
width = aVia->GetDrillValue();
|
|
||||||
|
|
||||||
std::unique_ptr<PNS::VIA> via( new PNS::VIA(
|
if( aVia->IsLocked() )
|
||||||
aVia->GetPosition(),
|
via->Mark( PNS::MK_LOCKED );
|
||||||
LAYER_RANGE( layer ),
|
|
||||||
width,
|
|
||||||
aVia->GetDrillValue(),
|
|
||||||
aVia->GetNetCode(),
|
|
||||||
aVia->GetViaType() )
|
|
||||||
);
|
|
||||||
|
|
||||||
via->SetParent( aVia );
|
return std::move( via );
|
||||||
|
|
||||||
if( aVia->IsLocked() )
|
|
||||||
via->Mark( PNS::MK_LOCKED );
|
|
||||||
|
|
||||||
retval.push_back( std::move( via ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 )
|
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
|
// 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 )
|
else if( type == PCB_VIA_T )
|
||||||
{
|
{
|
||||||
auto viavec = syncVia( static_cast<VIA*>( t ) );
|
if( auto via = syncVia( static_cast<VIA*>( t ) ) )
|
||||||
|
|
||||||
for( auto& via : viavec )
|
|
||||||
aWorld->Add( std::move( via ) );
|
aWorld->Add( std::move( via ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
void SetBoard( BOARD* aBoard );
|
void SetBoard( BOARD* aBoard );
|
||||||
void SyncWorld( PNS::NODE* aWorld ) override;
|
void SyncWorld( PNS::NODE* aWorld ) override;
|
||||||
bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) override { return true; };
|
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; }
|
bool IsItemVisible( const PNS::ITEM* aItem ) override { return true; }
|
||||||
void HideItem( PNS::ITEM* aItem ) override {}
|
void HideItem( PNS::ITEM* aItem ) override {}
|
||||||
void DisplayItem( const PNS::ITEM* aItem, int aColor = 0, int aClearance = 0, bool aEdit = false ) 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::SOLID> syncPad( D_PAD* aPad );
|
||||||
std::unique_ptr<PNS::SEGMENT> syncTrack( TRACK* aTrack );
|
std::unique_ptr<PNS::SEGMENT> syncTrack( TRACK* aTrack );
|
||||||
std::unique_ptr<PNS::ARC> syncArc( ARC* aArc );
|
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 syncTextItem( PNS::NODE* aWorld, EDA_TEXT* aText, PCB_LAYER_ID aLayer );
|
||||||
bool syncGraphicalItem( PNS::NODE* aWorld, DRAWSEGMENT* aItem );
|
bool syncGraphicalItem( PNS::NODE* aWorld, DRAWSEGMENT* aItem );
|
||||||
bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone );
|
bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone );
|
||||||
|
@ -105,6 +106,7 @@ public:
|
||||||
void EraseView() override;
|
void EraseView() override;
|
||||||
bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) override;
|
bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) override;
|
||||||
bool IsItemVisible( const PNS::ITEM* aItem ) override;
|
bool IsItemVisible( const PNS::ITEM* aItem ) override;
|
||||||
|
bool IsPadOnLayer( const PNS::ITEM* aItem, int aLayer ) override;
|
||||||
void HideItem( PNS::ITEM* aItem ) override;
|
void HideItem( PNS::ITEM* aItem ) override;
|
||||||
void DisplayItem( const PNS::ITEM* aItem, int aColor = 0, int aClearance = 0, bool aEdit = false ) override;
|
void DisplayItem( const PNS::ITEM* aItem, int aColor = 0, int aClearance = 0, bool aEdit = false ) override;
|
||||||
void Commit() 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);
|
const SEG& a = line.CSegment(i);
|
||||||
bool over = false;
|
bool over = false;
|
||||||
|
|
||||||
|
|
||||||
for( int j = 0; j < aObstacle.SegmentCount(); j++ )
|
for( int j = 0; j < aObstacle.SegmentCount(); j++ )
|
||||||
{
|
{
|
||||||
const SEG& so = aObstacle.CSegment(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++ )
|
for( int j = 0; j < aObstacle.SegmentCount(); j++ )
|
||||||
{
|
{
|
||||||
OPT_VECTOR2I p;
|
OPT_VECTOR2I p;
|
||||||
|
|
||||||
bool cont_a = aObstacle.CSegment(j).Contains( a.A );
|
bool cont_a = aObstacle.CSegment(j).Contains( a.A );
|
||||||
bool cont_b = aObstacle.CSegment(j).Contains( a.B );
|
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 );
|
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 );
|
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() )
|
if( aLine.EndsWithVia() )
|
||||||
{
|
{
|
||||||
|
@ -553,6 +553,7 @@ void NODE::Add( std::unique_ptr< SOLID > aSolid )
|
||||||
void NODE::addVia( VIA* aVia )
|
void NODE::addVia( VIA* aVia )
|
||||||
{
|
{
|
||||||
linkJoint( aVia->Pos(), aVia->Layers(), aVia->Net(), aVia );
|
linkJoint( aVia->Pos(), aVia->Layers(), aVia->Net(), aVia );
|
||||||
|
|
||||||
m_index->Add( aVia );
|
m_index->Add( aVia );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,7 +1227,7 @@ void NODE::GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded )
|
||||||
|
|
||||||
if( m_override.size() )
|
if( m_override.size() )
|
||||||
aRemoved.reserve( m_override.size() );
|
aRemoved.reserve( m_override.size() );
|
||||||
|
|
||||||
if( m_index->Size() )
|
if( m_index->Size() )
|
||||||
aAdded.reserve( m_index->Size() );
|
aAdded.reserve( m_index->Size() );
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,7 @@ enum DRAG_MODE
|
||||||
virtual void RemoveItem( ITEM* aItem ) = 0;
|
virtual void RemoveItem( ITEM* aItem ) = 0;
|
||||||
virtual bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) = 0;
|
virtual bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) = 0;
|
||||||
virtual bool IsItemVisible( const PNS::ITEM* aItem ) = 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 DisplayItem( const ITEM* aItem, int aColor = -1, int aClearance = -1, bool aEdit = false ) = 0;
|
||||||
virtual void HideItem( ITEM* aItem ) = 0;
|
virtual void HideItem( ITEM* aItem ) = 0;
|
||||||
virtual void Commit() = 0;
|
virtual void Commit() = 0;
|
||||||
|
|
|
@ -101,7 +101,7 @@ public:
|
||||||
m_seg.SetSeg( SEG (tmp.B , tmp.A ) );
|
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
|
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) );
|
SHAPE_LINE_CHAIN::POINT_INSIDE_TRACKER checker( aCurrent.CPoint(0) );
|
||||||
checker.AddPolyline( aObstacle.CLine() );
|
checker.AddPolyline( aObstacle.CLine() );
|
||||||
checker.AddPolyline( aShoved.CLine().Reverse() );
|
checker.AddPolyline( aShoved.CLine().Reverse() );
|
||||||
|
|
||||||
bool inside = checker.IsInside();
|
bool inside = checker.IsInside();
|
||||||
|
|
||||||
return !inside;
|
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 )
|
SHOVE::SHOVE_STATUS SHOVE::walkaroundLoneVia( LINE& aCurrent, LINE& aObstacle, LINE& aShoved )
|
||||||
{
|
{
|
||||||
int clearance = getClearance( &aCurrent, &aObstacle );
|
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_cw;
|
||||||
SHAPE_LINE_CHAIN path_ccw;
|
SHAPE_LINE_CHAIN path_ccw;
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ SHOVE::SHOVE_STATUS SHOVE::processHullSet( LINE& aCurrent, LINE& aObstacle,
|
||||||
sprintf(str,"att-%d-shoved", attempt);
|
sprintf(str,"att-%d-shoved", attempt);
|
||||||
Dbg()->AddLine( l.CLine(), 3, 20000, str );
|
Dbg()->AddLine( l.CLine(), 3, 20000, str );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( ( aCurrent.Marker() & MK_HEAD ) && !colliding )
|
if( ( aCurrent.Marker() & MK_HEAD ) && !colliding )
|
||||||
{
|
{
|
||||||
JOINT* jtStart = m_currentNode->FindJoint( aCurrent.CPoint( 0 ), &aCurrent );
|
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;
|
int clearance = getClearance( &aCurrent, &aObstacle ) + 1;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#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
|
#endif
|
||||||
|
|
||||||
HULL_SET hulls;
|
HULL_SET hulls;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2014 CERN
|
* 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>
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* 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_circle.h>
|
||||||
#include <geometry/shape_simple.h>
|
#include <geometry/shape_simple.h>
|
||||||
|
|
||||||
|
#include "pns_router.h"
|
||||||
#include "pns_solid.h"
|
#include "pns_solid.h"
|
||||||
#include "pns_utils.h"
|
#include "pns_utils.h"
|
||||||
|
|
||||||
namespace PNS {
|
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;
|
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:
|
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 );
|
return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl );
|
||||||
}
|
}
|
||||||
|
|
||||||
case SH_CIRCLE:
|
case SH_CIRCLE:
|
||||||
{
|
{
|
||||||
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape );
|
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( shape );
|
||||||
int r = circle->GetRadius();
|
int r = circle->GetRadius();
|
||||||
return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
|
return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
|
||||||
cl + 1, 0.52 * ( r + cl ) );
|
cl + 1, 0.52 * ( r + cl ) );
|
||||||
|
@ -54,13 +59,13 @@ const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness ) c
|
||||||
|
|
||||||
case SH_SEGMENT:
|
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 );
|
return SegmentHull( *seg, aClearance, aWalkaroundThickness );
|
||||||
}
|
}
|
||||||
|
|
||||||
case SH_SIMPLE:
|
case SH_SIMPLE:
|
||||||
{
|
{
|
||||||
SHAPE_SIMPLE* convex = static_cast<SHAPE_SIMPLE*>( m_shape );
|
SHAPE_SIMPLE* convex = static_cast<SHAPE_SIMPLE*>( shape );
|
||||||
|
|
||||||
return ConvexHull( *convex, cl );
|
return ConvexHull( *convex, cl );
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 CERN
|
* 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>
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
@ -35,7 +35,7 @@ namespace PNS {
|
||||||
class SOLID : public ITEM
|
class SOLID : public ITEM
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SOLID() : ITEM( SOLID_T ), m_shape( NULL )
|
SOLID() : ITEM( SOLID_T ), m_shape( NULL ), m_alternateShape( NULL )
|
||||||
{
|
{
|
||||||
m_movable = false;
|
m_movable = false;
|
||||||
m_padToDie = 0;
|
m_padToDie = 0;
|
||||||
|
@ -49,7 +49,14 @@ public:
|
||||||
SOLID( const SOLID& aSolid ) :
|
SOLID( const SOLID& aSolid ) :
|
||||||
ITEM( aSolid )
|
ITEM( aSolid )
|
||||||
{
|
{
|
||||||
|
if( m_shape )
|
||||||
|
delete m_shape;
|
||||||
|
|
||||||
|
if( m_alternateShape )
|
||||||
|
delete m_alternateShape;
|
||||||
|
|
||||||
m_shape = aSolid.m_shape->Clone();
|
m_shape = aSolid.m_shape->Clone();
|
||||||
|
m_alternateShape = aSolid.m_alternateShape->Clone();
|
||||||
m_pos = aSolid.m_pos;
|
m_pos = aSolid.m_pos;
|
||||||
m_padToDie = aSolid.m_padToDie;
|
m_padToDie = aSolid.m_padToDie;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +70,12 @@ public:
|
||||||
|
|
||||||
const SHAPE* Shape() const override { return m_shape; }
|
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 )
|
void SetShape( SHAPE* shape )
|
||||||
{
|
{
|
||||||
|
@ -73,13 +85,21 @@ public:
|
||||||
m_shape = shape;
|
m_shape = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetAlternateShape( SHAPE* shape )
|
||||||
|
{
|
||||||
|
if( m_alternateShape )
|
||||||
|
delete m_alternateShape;
|
||||||
|
|
||||||
|
m_alternateShape = shape;
|
||||||
|
}
|
||||||
|
|
||||||
const VECTOR2I& Pos() const
|
const VECTOR2I& Pos() const
|
||||||
{
|
{
|
||||||
return m_pos;
|
return m_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPos( const VECTOR2I& aCenter );
|
void SetPos( const VECTOR2I& aCenter );
|
||||||
|
|
||||||
int GetPadToDie() const
|
int GetPadToDie() const
|
||||||
{
|
{
|
||||||
return m_padToDie;
|
return m_padToDie;
|
||||||
|
@ -113,6 +133,7 @@ public:
|
||||||
private:
|
private:
|
||||||
VECTOR2I m_pos;
|
VECTOR2I m_pos;
|
||||||
SHAPE* m_shape;
|
SHAPE* m_shape;
|
||||||
|
SHAPE* m_alternateShape;
|
||||||
VECTOR2I m_offset;
|
VECTOR2I m_offset;
|
||||||
int m_padToDie;
|
int m_padToDie;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2014 CERN
|
* 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>
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* 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 cl = ( aClearance + aWalkaroundThickness / 2 );
|
||||||
|
int width = m_diameter;
|
||||||
|
|
||||||
|
if( !ROUTER::GetInstance()->GetInterface()->IsPadOnLayer( this, aLayer ) )
|
||||||
|
width = m_drill;
|
||||||
|
|
||||||
return OctagonalHull( m_pos -
|
return OctagonalHull( m_pos -
|
||||||
VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter, m_diameter ),
|
VECTOR2I( width / 2, width / 2 ), VECTOR2I( width, width ),
|
||||||
cl + 1, ( 2 * cl + m_diameter ) * 0.26 );
|
cl + 1, ( 2 * cl + width ) * 0.26 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2014 CERN
|
* 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>
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
@ -66,6 +66,7 @@ public:
|
||||||
m_diameter = aDiameter;
|
m_diameter = aDiameter;
|
||||||
m_drill = aDrill;
|
m_drill = aDrill;
|
||||||
m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 );
|
m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 );
|
||||||
|
m_alternateShape = SHAPE_CIRCLE( m_pos, aDrill / 2 );
|
||||||
m_viaType = aViaType;
|
m_viaType = aViaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ public:
|
||||||
m_pos = aB.m_pos;
|
m_pos = aB.m_pos;
|
||||||
m_diameter = aB.m_diameter;
|
m_diameter = aB.m_diameter;
|
||||||
m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 );
|
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_marker = aB.m_marker;
|
||||||
m_rank = aB.m_rank;
|
m_rank = aB.m_rank;
|
||||||
m_drill = aB.m_drill;
|
m_drill = aB.m_drill;
|
||||||
|
@ -143,9 +145,14 @@ public:
|
||||||
return &m_shape;
|
return &m_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SHAPE* AlternateShape() const override
|
||||||
|
{
|
||||||
|
return &m_alternateShape;
|
||||||
|
}
|
||||||
|
|
||||||
VIA* Clone() const override;
|
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
|
virtual VECTOR2I Anchor( int n ) const override
|
||||||
{
|
{
|
||||||
|
@ -166,6 +173,7 @@ private:
|
||||||
int m_drill;
|
int m_drill;
|
||||||
VECTOR2I m_pos;
|
VECTOR2I m_pos;
|
||||||
SHAPE_CIRCLE m_shape;
|
SHAPE_CIRCLE m_shape;
|
||||||
|
SHAPE_CIRCLE m_alternateShape;
|
||||||
VIATYPE m_viaType;
|
VIATYPE m_viaType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue