router: further changes to the ownership model

- LINEs now own their vias optionally (depending whether a LINE with its VIA belongs to a node)
- get rid of unique_ptr on the internal NODE::Add API (and also made it private)
- make sure stack pointers are not added to the node
- use rvalue reference for NODE::Add/NODE::Replace

Manually rebased by Jeff Young <jeff@rokeby.ie> 5 April 2023

(cherry picked from commit d961cdce3f)
This commit is contained in:
Tomasz Wlostowski 2022-09-11 22:17:45 +01:00 committed by Jeff Young
parent c1274e24b0
commit de60d5467c
14 changed files with 141 additions and 217 deletions

View File

@ -19,6 +19,7 @@ set( PCBNEW_PNS_SRCS
pns_diff_pair_placer.cpp
pns_dp_meander_placer.cpp
pns_dragger.cpp
pns_hole.cpp
pns_index.cpp
pns_item.cpp
pns_itemset.cpp

View File

@ -1,7 +1,7 @@
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*

View File

@ -1,7 +1,7 @@
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 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,13 +35,14 @@ namespace PNS {
static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles )
{
printf("&&&& %d obstacles: \n", obstacles.size() );
printf( "&&&& %lu obstacles: \n", obstacles.size() );
for( const auto& obs : obstacles )
{
printf("%p [%s] - %p [%s], clearance %d\n", obs.m_head, obs.m_head->KindStr().c_str(),
obs.m_item, obs.m_item->KindStr().c_str(),
obs.m_clearance );
printf( "%p [%s] - %p [%s], clearance %d\n",
obs.m_head, obs.m_head->KindStr().c_str(),
obs.m_item, obs.m_item->KindStr().c_str(),
obs.m_clearance );
}
}
@ -59,7 +60,7 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
int clearanceEpsilon = aNode->GetRuleResolver()->ClearanceEpsilon();
bool collisionsFound = false;
printf("******************** CollideSimple %d\n", aCtx->obstacles.size() );
printf( "******************** CollideSimple %lu\n", aCtx->obstacles.size() );
//printf( "h %p n %p t %p ctx %p\n", aHead, aNode, this, aCtx );
@ -301,11 +302,11 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
obs.m_item = const_cast<ITEM*>( this );
obs.m_clearance = clearance;
//printf("i %p h %p ih %p hh %p\n", this ,aHead, holeI, holeH);
printf("HCHX %d %d\n", clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon);
//printf("pushc %p %p cl %d cle %d\n", obs.m_head, obs.m_item, clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon );
//printf("SH %s\n", shapeH->Format().c_str(), aHead );
//printf("SI %s\n", shapeI->Format().c_str(), this );
//printf( "i %p h %p ih %p hh %p\n", this ,aHead, holeI, holeH );
printf( "HCHX %d %d\n", clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon);
//printf( "pushc %p %p cl %d cle %d\n", obs.m_head, obs.m_item, clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon );
//printf( "SH %s\n", shapeH->Format().c_str(), aHead );
//printf( "SI %s\n", shapeI->Format().c_str(), this );
aCtx->obstacles.insert( obs );
@ -375,112 +376,6 @@ ITEM::~ITEM()
{
}
HOLE::~HOLE()
{
delete m_holeShape;
}
HOLE* HOLE::Clone() const
{
HOLE* h = new HOLE( m_parentPadVia, m_holeShape->Clone() );
h->SetNet( Net() );
h->SetLayers( Layers() );
h->m_rank = m_rank;
h->m_marker = m_marker;
h->m_parent = m_parent;
h->m_isVirtual = m_isVirtual;
return h;
}
const SHAPE_LINE_CHAIN HOLE::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const
{
if( !m_holeShape )
return SHAPE_LINE_CHAIN();
if( m_holeShape->Type() == SH_CIRCLE )
{
auto cir = static_cast<SHAPE_CIRCLE*>( m_holeShape );
int cl = ( aClearance + aWalkaroundThickness / 2 );
int width = cir->GetRadius() * 2;
// Chamfer = width * ( 1 - sqrt(2)/2 ) for equilateral octagon
return OctagonalHull( cir->GetCenter() - VECTOR2I( width / 2, width / 2 ), VECTOR2I( width, width ), cl,
( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) );
}
else if( m_holeShape->Type() == SH_COMPOUND )
{
SHAPE_COMPOUND* cmpnd = static_cast<SHAPE_COMPOUND*>( m_holeShape );
if ( cmpnd->Shapes().size() == 1 )
{
return BuildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance,
aWalkaroundThickness );
}
else
{
SHAPE_POLY_SET hullSet;
for( SHAPE* shape : cmpnd->Shapes() )
{
hullSet.AddOutline( BuildHullForPrimitiveShape( shape, aClearance,
aWalkaroundThickness ) );
}
hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
return hullSet.Outline( 0 );
}
}
else
{
return BuildHullForPrimitiveShape( m_holeShape, aClearance, aWalkaroundThickness );
}
}
bool HOLE::IsCircular() const
{
return m_holeShape->Type() == SH_CIRCLE;
}
int HOLE::Radius() const
{
assert( m_holeShape->Type() == SH_CIRCLE );
return static_cast<const SHAPE_CIRCLE*>( m_holeShape )->GetRadius();
}
const VECTOR2I HOLE::Pos() const
{
return VECTOR2I( 0, 0 ); // fixme holes
}
void HOLE::SetCenter( const VECTOR2I& aCenter )
{
assert( m_holeShape->Type() == SH_CIRCLE );
static_cast<SHAPE_CIRCLE*>( m_holeShape )->SetCenter( aCenter );
}
void HOLE::SetRadius( int aRadius )
{
assert( m_holeShape->Type() == SH_CIRCLE );
static_cast<SHAPE_CIRCLE*>( m_holeShape )->SetRadius( aRadius );
}
void HOLE::Move( const VECTOR2I& delta )
{
m_holeShape->Move( delta );
}
HOLE* HOLE::MakeCircularHole( const VECTOR2I& pos, int radius )
{
auto circle = new SHAPE_CIRCLE( pos, radius );
auto hole = new HOLE( nullptr, circle );
hole->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
return hole;
}
const std::string ITEM::Format() const
{

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*

View File

@ -60,7 +60,8 @@ public:
bool IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const override;
bool IsItemVisible( const PNS::ITEM* aItem ) const override { return true; };
void HideItem( PNS::ITEM* aItem ) override {}
void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false, bool aIsHeadTrace = false ) override {}
void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false,
bool aIsHeadTrace = false ) override {}
void DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance ) override {}
void DisplayRatline( const SHAPE_LINE_CHAIN& aRatline, int aNetCode ) override {}
void AddItem( PNS::ITEM* aItem ) override;

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 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
@ -44,8 +44,15 @@ LINE::LINE( const LINE& aOther )
m_net = aOther.m_net;
m_movable = aOther.m_movable;
m_layers = aOther.m_layers;
m_via = aOther.m_via;
m_hasVia = aOther.m_hasVia;
m_via = nullptr;
if( aOther.m_via )
{
m_via = aOther.m_via->Clone();
m_via->SetOwner( this );
}
m_marker = aOther.m_marker;
m_rank = aOther.m_rank;
m_blockingObstacle = aOther.m_blockingObstacle;
@ -56,6 +63,8 @@ LINE::LINE( const LINE& aOther )
LINE::~LINE()
{
if( m_via && m_via->BelongsTo( this ) )
delete m_via;
}
@ -66,8 +75,15 @@ LINE& LINE::operator=( const LINE& aOther )
m_net = aOther.m_net;
m_movable = aOther.m_movable;
m_layers = aOther.m_layers;
m_via = aOther.m_via;
m_hasVia = aOther.m_hasVia;
m_via = nullptr;
if( aOther.m_via )
{
m_via = aOther.m_via->Clone();
m_via->SetOwner( this );
}
m_marker = aOther.m_marker;
m_rank = aOther.m_rank;
m_owner = aOther.m_owner;
@ -1043,9 +1059,9 @@ void LINE::AppendVia( const VIA& aVia )
Reverse();
}
m_hasVia = true;
m_via = aVia;
m_via.SetNet( m_net );
m_via = aVia.Clone();
m_via->SetOwner( this );
m_via->SetNet( m_net );
}
@ -1251,11 +1267,24 @@ bool LINE::HasLockedSegments() const
void LINE::Clear()
{
m_hasVia = false;
if( m_via && m_via->BelongsTo( this ) )
{
delete m_via;
m_via = nullptr;
}
m_line.Clear();
}
void LINE::RemoveVia()
{
if( m_via && m_via->BelongsTo( this ) )
delete m_via;
m_via = nullptr;
}
const std::string SEGMENT::Format( ) const
{
std::stringstream ss;
@ -1266,3 +1295,4 @@ const std::string SEGMENT::Format( ) const
}

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -67,9 +67,9 @@ public:
LINK_HOLDER( LINE_T ),
m_blockingObstacle( nullptr )
{
m_hasVia = false;
m_width = 1; // Dummy value
m_snapThreshhold = 0;
m_via = nullptr;
}
LINE( const LINE& aOther );
@ -86,7 +86,7 @@ public:
{
m_net = aBase.m_net;
m_layers = aBase.m_layers;
m_hasVia = false;
m_via = nullptr;
}
/**
@ -96,8 +96,7 @@ public:
LINK_HOLDER( LINE_T ),
m_blockingObstacle( nullptr )
{
m_hasVia = true;
m_via = aVia;
m_via = aVia.Clone();
m_width = aVia.Diameter();
m_net = aVia.Net();
m_layers = aVia.Layers();
@ -127,11 +126,6 @@ public:
{
m_line = aLine;
m_line.SetWidth( m_width );
if( m_hasVia && m_line.PointCount() > 0 )
{
m_via.SetPos( m_line.CPoint( -1 ) );
}
}
///< Return the shape of the line.
@ -191,16 +185,16 @@ public:
///< Print out all linked segments.
void ShowLinks() const;
bool EndsWithVia() const { return m_hasVia; }
bool EndsWithVia() const { return m_via != nullptr; }
void AppendVia( const VIA& aVia );
void RemoveVia() { m_hasVia = false; }
void RemoveVia();
VIA& Via() { return m_via; }
const VIA& Via() const { return m_via; }
VIA& Via() { return *m_via; }
const VIA& Via() const { return *m_via; }
void SetViaDiameter( int aDiameter ) { m_via.SetDiameter( aDiameter ); }
void SetViaDrill( int aDrill ) { m_via.SetDrill( aDrill ); }
void SetViaDiameter( int aDiameter ) { assert(m_via); m_via->SetDiameter( aDiameter ); }
void SetViaDrill( int aDrill ) { assert(m_via); m_via->SetDrill( aDrill ); }
virtual void Mark( int aMarker ) const override;
virtual void Unmark( int aMarker = -1 ) const override;
@ -250,8 +244,7 @@ private:
int m_snapThreshhold; ///< Width to smooth out jagged segments.
bool m_hasVia; ///< Optional via at the end point.
VIA m_via;
VIA* m_via;
ITEM* m_blockingObstacle; ///< For mark obstacle mode.
};

View File

@ -539,17 +539,18 @@ const ITEM_SET NODE::HitTest( const VECTOR2I& aPoint ) const
void NODE::addSolid( SOLID* aSolid )
{
if( aSolid->HasHole() )
if( aSolid->HasHole() && aSolid->Hole()->BelongsTo( aSolid ) )
addHole( aSolid->Hole() );
if( aSolid->IsRoutable() )
linkJoint( aSolid->Pos(), aSolid->Layers(), aSolid->Net(), aSolid );
aSolid->SetOwner( this );
m_index->Add( aSolid );
}
void NODE::Add( std::unique_ptr< SOLID > aSolid )
void NODE::Add( std::unique_ptr< SOLID >&& aSolid )
{
aSolid->SetOwner( this );
addSolid( aSolid.release() );
@ -558,10 +559,11 @@ void NODE::Add( std::unique_ptr< SOLID > aSolid )
void NODE::addVia( VIA* aVia )
{
if( aVia->HasHole() )
if( aVia->HasHole() && aVia->Hole()->BelongsTo( aVia ) )
addHole( aVia->Hole() );
linkJoint( aVia->Pos(), aVia->Layers(), aVia->Net(), aVia );
aVia->SetOwner( this );
m_index->Add( aVia );
}
@ -572,20 +574,18 @@ void NODE::addHole( HOLE* aHole )
// do we need holes in the connection graph?
//linkJoint( aHole->Pos(), aHole->Layers(), aHole->Net(), aHole );
aHole->SetOwner( this );
m_index->Add( aHole );
}
void NODE::Add( std::unique_ptr< VIA > aVia )
void NODE::Add( std::unique_ptr< VIA >&& aVia )
{
aVia->SetOwner( this );
addVia( aVia.release() );
}
void NODE::Add( ITEM* aItem, bool aAllowRedundant )
void NODE::add( ITEM* aItem, bool aAllowRedundant )
{
aItem->SetOwner( this );
switch( aItem->Kind() )
{
case ITEM::ARC_T:
@ -660,6 +660,8 @@ void NODE::Add( LINE& aLine, bool aAllowRedundant )
void NODE::addSegment( SEGMENT* aSeg )
{
aSeg->SetOwner( this );
linkJoint( aSeg->Seg().A, aSeg->Layers(), aSeg->Net(), aSeg );
linkJoint( aSeg->Seg().B, aSeg->Layers(), aSeg->Net(), aSeg );
@ -667,7 +669,7 @@ void NODE::addSegment( SEGMENT* aSeg )
}
bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant )
bool NODE::Add( std::unique_ptr< SEGMENT >&& aSegment, bool aAllowRedundant )
{
if( aSegment->Seg().A == aSegment->Seg().B )
{
@ -679,7 +681,6 @@ bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant )
if( !aAllowRedundant && findRedundantSegment( aSegment.get() ) )
return false;
aSegment->SetOwner( this );
addSegment( aSegment.release() );
return true;
@ -688,6 +689,8 @@ bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant )
void NODE::addArc( ARC* aArc )
{
aArc->SetOwner( this );
linkJoint( aArc->Anchor( 0 ), aArc->Layers(), aArc->Net(), aArc );
linkJoint( aArc->Anchor( 1 ), aArc->Layers(), aArc->Net(), aArc );
@ -695,7 +698,7 @@ void NODE::addArc( ARC* aArc )
}
bool NODE::Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant )
bool NODE::Add( std::unique_ptr< ARC >&& aArc, bool aAllowRedundant )
{
const SHAPE_ARC& arc = aArc->CArc();
@ -705,12 +708,12 @@ bool NODE::Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant )
return false;
}
aArc->SetOwner( this );
addArc( aArc.release() );
return true;
}
#if 0 // JEY TODO: clean up
void NODE::Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant )
{
switch( aItem->Kind() )
@ -718,6 +721,8 @@ void NODE::Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant )
case ITEM::SOLID_T: Add( ItemCast<SOLID>( std::move( aItem ) ) ); break;
case ITEM::SEGMENT_T: Add( ItemCast<SEGMENT>( std::move( aItem ) ), aAllowRedundant ); break;
case ITEM::VIA_T: Add( ItemCast<VIA>( std::move( aItem ) ) ); break;
case ITEM::HOLE_T:
break; // ignore holes, they don't exist as independent objects
case ITEM::ARC_T:
//todo(snh): Add redundant search
@ -725,21 +730,11 @@ void NODE::Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant )
break;
case ITEM::LINE_T:
{
// fixme(twl): I don't like unique_ptr in this methods as the router has its own garbage
// collecting mechanism. This particular case is used exclusively in
// ROUTER::GetUpdatedItems() for dumping debug logs. Please don't call Add ( up<LINE> )
// otherwise, dragons live here.
LINE *l = static_cast<LINE*>( aItem.get() );
Add( *l );
break;
}
default:
assert( false );
}
}
#endif
void NODE::AddEdgeExclusion( std::unique_ptr<SHAPE> aShape )
{
@ -766,7 +761,7 @@ void NODE::doRemove( ITEM* aItem )
if( aItem->BelongsTo( m_root ) && !isRoot() )
{
m_override.insert( aItem );
if( aItem->HasHole() )
m_override.insert( aItem->Hole() );
}
@ -793,7 +788,7 @@ void NODE::doRemove( ITEM* aItem )
if( hole )
{
m_index->Remove( hole ); // hole is not directly owned by NODE but by the parent SOLID/VIA.
hole->SetOwner( nullptr );
hole->SetOwner( hole->ParentPadVia() );
}
}
}
@ -878,10 +873,10 @@ void NODE::removeSolidIndex( SOLID* aSolid )
}
void NODE::Replace( ITEM* aOldItem, std::unique_ptr< ITEM > aNewItem )
void NODE::Replace( ITEM* aOldItem, std::unique_ptr< ITEM >&& aNewItem )
{
Remove( aOldItem );
Add( std::move( aNewItem ) );
add( aNewItem.release() );
}
@ -1482,7 +1477,7 @@ void NODE::Commit( NODE* aNode )
{
item->SetRank( -1 );
item->Unmark();
Add( std::unique_ptr<ITEM>( item ) );
add( item );
}
releaseChildren();

View File

@ -314,17 +314,14 @@ public:
* at the same coordinates as an existing one).
* @return true if added
*/
bool Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant = false );
void Add( std::unique_ptr< SOLID > aSolid );
void Add( std::unique_ptr< VIA > aVia );
bool Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant = false );
bool Add( std::unique_ptr< SEGMENT >&& aSegment, bool aAllowRedundant = false );
void Add( std::unique_ptr< SOLID >&& aSolid );
void Add( std::unique_ptr< VIA >&& aVia );
bool Add( std::unique_ptr< ARC >&& aArc, bool aAllowRedundant = false );
void Add( LINE& aLine, bool aAllowRedundant = false );
void Add( ITEM* aItem, bool aAllowRedundant = false );
void AddEdgeExclusion( std::unique_ptr<SHAPE> aShape );
bool QueryEdgeExclusions( const VECTOR2I& aPos ) const;
/**
@ -349,7 +346,7 @@ public:
* @param aOldItem item to be removed
* @param aNewItem item add instead
*/
void Replace( ITEM* aOldItem, std::unique_ptr< ITEM > aNewItem );
void Replace( ITEM* aOldItem, std::unique_ptr< ITEM >&& aNewItem );
void Replace( LINE& aOldLine, LINE& aNewLine );
/**
@ -462,9 +459,13 @@ public:
return m_collisionQueryScope;
}
void Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant = false );
void AddRaw( ITEM* aItem, bool aAllowRedundant = false )
{
add( aItem, aAllowRedundant );
}
private:
void add( ITEM* aItem, bool aAllowRedundant = false );
/// nodes are not copyable
NODE( const NODE& aB );

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 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
@ -1800,7 +1800,8 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( const VIA_HANDLE aOldVia, const VEC
VIA headVia ( *viaToDrag );
headVia.SetPos( aWhere );
headSet.Add( headVia );
headSet.Add( &headVia, false ); // headVia is on stack
VIA_HANDLE prevViaHandle;
NODE* parent = reduceSpringback( headSet, prevViaHandle );

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 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
@ -36,7 +36,7 @@ bool VIA::PushoutForce( NODE* aNode, const ITEM* aOther, VECTOR2I& aForce )
VECTOR2I elementForces[4], force;
size_t nf = 0;
#if 0
#if 0 // JEY TODO: why is this commented out? Needs replacing, or deleting?
if( aNode->GetCollisionQueryScope() == NODE::CQS_ALL_RULES )
{
int holeClearance = aNode->GetHoleClearance( this, aOther );
@ -161,12 +161,12 @@ const SHAPE_LINE_CHAIN VIA::Hull( int aClearance, int aWalkaroundThickness, int
// Chamfer = width * ( 1 - sqrt(2)/2 ) for equilateral octagon
return OctagonalHull( m_pos - VECTOR2I( width / 2, width / 2 ),
VECTOR2I( width, width ),
cl, ( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) );
VECTOR2I( width, width ),
cl, ( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) );
}
#if 0
#if 0 // JEY TODO: is this no longer needed?
const SHAPE_LINE_CHAIN VIA::HoleHull( int aClearance, int aWalkaroundThickness, int aLayer ) const
{
int cl = ( aClearance + aWalkaroundThickness / 2 );

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 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
@ -73,6 +73,7 @@ public:
m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 );
m_hole = HOLE::MakeCircularHole( m_pos, aDrill / 2 );
m_hole->SetNet( aNet );
m_hole->SetOwner( this );
m_viaType = aViaType;
m_isFree = false;
m_isVirtual = false;
@ -87,6 +88,7 @@ public:
m_diameter = aB.m_diameter;
m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 );
m_hole = aB.m_hole->Clone();
m_hole->SetOwner( this );
m_marker = aB.m_marker;
m_rank = aB.m_rank;
m_drill = aB.m_drill;
@ -97,8 +99,10 @@ public:
virtual ~VIA()
{
if ( m_hole )
if ( m_hole && m_hole->BelongsTo( this ) )
{
delete m_hole;
}
}
static inline bool ClassOf( const ITEM* aItem )
@ -167,9 +171,9 @@ public:
virtual void SetHole( HOLE* aHole ) override
{
if( m_hole )
if( m_hole && m_hole->Owner() == this )
{
assert( m_hole->Owner() == nullptr );
delete m_hole;
}
m_hole = aHole;

View File

@ -89,7 +89,8 @@ public:
virtual ~MOCK_RULE_RESOLVER() {}
virtual int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB ) override
virtual int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
bool aUseClearanceEpsilon = true ) override
{
PNS::CONSTRAINT constraint;
int rv = -1;
@ -192,15 +193,15 @@ public:
bool operator<( const ITEM_KEY& other ) const
{
if( a < other.a )
{
return true;
}
else if ( a == other.a )
{
if( b < other.b )
return true;
else if ( b == other.b )
{
return type < other.type;
}
}
return false;
@ -211,7 +212,7 @@ public:
virtual bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
const PNS::ITEM* aCollidingItem ) override
{
return false;
return false;
}
void AddMockRule( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
@ -232,8 +233,7 @@ public:
private:
std::map<ITEM_KEY, PNS::CONSTRAINT> m_ruleMap;
int m_clearanceEpsilon;
int m_clearanceEpsilon;
};
struct PNS_TEST_FIXTURE;
@ -242,11 +242,14 @@ class MOCK_PNS_KICAD_IFACE : public PNS_KICAD_IFACE_BASE
{
public:
MOCK_PNS_KICAD_IFACE( PNS_TEST_FIXTURE *aFixture ) :
m_testFixture( aFixture ) {}
m_testFixture( aFixture )
{}
~MOCK_PNS_KICAD_IFACE() {}
void HideItem( PNS::ITEM* aItem ) override {};
void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false ) override {};
void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false,
bool aIsHeadTrace = false ) override {};
PNS::RULE_RESOLVER* GetRuleResolver() override;
private:
@ -256,17 +259,18 @@ private:
struct PNS_TEST_FIXTURE
{
PNS_TEST_FIXTURE() : m_settingsManager( true /* headless */ )
PNS_TEST_FIXTURE() :
m_settingsManager( true /* headless */ )
{
m_router = new PNS::ROUTER;
m_iface = new MOCK_PNS_KICAD_IFACE( this );
m_router->SetInterface( m_iface );
}
SETTINGS_MANAGER m_settingsManager;
PNS::ROUTER* m_router;
MOCK_RULE_RESOLVER m_ruleResolver;
MOCK_PNS_KICAD_IFACE *m_iface;
SETTINGS_MANAGER m_settingsManager;
PNS::ROUTER* m_router;
MOCK_RULE_RESOLVER m_ruleResolver;
MOCK_PNS_KICAD_IFACE* m_iface;
//std::unique_ptr<BOARD> m_board;
};
@ -278,18 +282,19 @@ PNS::RULE_RESOLVER* MOCK_PNS_KICAD_IFACE::GetRuleResolver()
static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles )
{
for ( const auto& obs : obstacles )
for( const PNS::OBSTACLE& obs : obstacles )
{
printf("%p [%s] - %p [%s], clearance %d\n", obs.m_head, obs.m_head->KindStr().c_str(),
obs.m_item, obs.m_item->KindStr().c_str(),
obs.m_clearance );
printf( "%p [%s] - %p [%s], clearance %d\n",
obs.m_head, obs.m_head->KindStr().c_str(),
obs.m_item, obs.m_item->KindStr().c_str(),
obs.m_clearance );
}
}
BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE )
{
PNS::VIA* v1 = new PNS::VIA ( VECTOR2I( 0, 1000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 );
PNS::VIA* v2 = new PNS::VIA ( VECTOR2I( 0, 2000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 );
PNS::VIA* v1 = new PNS::VIA( VECTOR2I( 0, 1000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 );
PNS::VIA* v2 = new PNS::VIA( VECTOR2I( 0, 2000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 );
std::unique_ptr<PNS::NODE> world ( new PNS::NODE );
@ -331,8 +336,6 @@ BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE )
world->QueryColliding( v1, obstacles );
dumpObstacles( obstacles );
BOOST_CHECK_EQUAL( obstacles.size(), 2 );
auto iter = obstacles.begin();
const auto first = *iter++;