router: rework ITEM ownership model.

- prerequisite for holes as first class objects code
- introduced the OWNABLE_ITEM interface that defines the owning container (NODE/other ITEM/ITEM_SET)
- simplified the ITEM_SET interface
- constified a lot of APIs (ownership/JOINT management) as a side effect

Rebased and cleaned up by Jeff Young <jeff@rokeby.ie> 5 April 2023
- some STL cover types removed

(cherry picked from commit 1283c4713f)
This commit is contained in:
Tomasz Wlostowski 2022-08-29 21:21:46 +01:00 committed by Jeff Young
parent 3a6a6097a7
commit 7f593d3999
18 changed files with 243 additions and 266 deletions

View File

@ -56,7 +56,7 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
std::unordered_set<LINKED_ITEM*> seenItems;
auto addLinked =
[&]( SOLID* aSolid, JOINT* aJoint, LINKED_ITEM* aItem, VECTOR2I aOffset = {} )
[&]( SOLID* aSolid, const JOINT* aJoint, LINKED_ITEM* aItem, VECTOR2I aOffset = {} )
{
if( seenItems.count( aItem ) )
return;
@ -66,13 +66,13 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
// Segments that go directly between two linked pads are special-cased
VECTOR2I otherEnd = ( aJoint->Pos() == aItem->Anchor( 0 ) ) ?
aItem->Anchor( 1 ) : aItem->Anchor( 0 );
JOINT* otherJoint = m_world->FindJoint( otherEnd, aItem->Layer(), aItem->Net() );
const JOINT* otherJoint = m_world->FindJoint( otherEnd, aItem->Layer(), aItem->Net() );
if( otherJoint && otherJoint->LinkCount( ITEM::SOLID_T ) )
{
for( const ITEM_SET::ENTRY& otherItem : otherJoint->LinkList() )
for( ITEM* otherItem : otherJoint->LinkList() )
{
if( aPrimitives.Contains( otherItem.item ) )
if( aPrimitives.Contains( otherItem ) )
{
m_fixedItems.insert( aItem );
return;
@ -89,17 +89,17 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
// Lines that go directly between two linked pads are also special-cased
const SHAPE_LINE_CHAIN& line = cn.origLine.CLine();
JOINT* jA = m_world->FindJoint( line.CPoint( 0 ), aItem->Layer(), aItem->Net() );
JOINT* jB = m_world->FindJoint( line.CPoint( -1 ), aItem->Layer(), aItem->Net() );
const JOINT* jA = m_world->FindJoint( line.CPoint( 0 ), aItem->Layer(), aItem->Net() );
const JOINT* jB = m_world->FindJoint( line.CPoint( -1 ), aItem->Layer(), aItem->Net() );
wxASSERT( jA == aJoint || jB == aJoint );
JOINT* jSearch = ( jA == aJoint ) ? jB : jA;
const JOINT* jSearch = ( jA == aJoint ) ? jB : jA;
if( jSearch && jSearch->LinkCount( ITEM::SOLID_T ) )
{
for( const ITEM_SET::ENTRY& otherItem : jSearch->LinkList() )
for( ITEM* otherItem : jSearch->LinkList() )
{
if( aPrimitives.Contains( otherItem.item ) )
if( aPrimitives.Contains( otherItem ) )
{
for( ITEM* item : cn.origLine.Links() )
m_fixedItems.insert( item );
@ -114,22 +114,22 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
for( auto item : aPrimitives.Items() )
{
if( item.item->Kind() != ITEM::SOLID_T )
if( item->Kind() != ITEM::SOLID_T )
continue;
SOLID* solid = static_cast<SOLID*>( item.item );
SOLID* solid = static_cast<SOLID*>( item );
m_solids.insert( solid );
if( !item.item->IsRoutable() )
if( !item->IsRoutable() )
continue;
JOINT* jt = m_world->FindJoint( solid->Pos(), solid );
const JOINT* jt = m_world->FindJoint( solid->Pos(), solid );
for( auto link : jt->LinkList() )
{
if( link.item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
addLinked( solid, jt, static_cast<LINKED_ITEM*>( link.item ) );
if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
addLinked( solid, jt, static_cast<LINKED_ITEM*>( item ) );
}
std::vector<JOINT*> extraJoints;
@ -141,7 +141,7 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
{
if( extraJoint->Net() == jt->Net() && extraJoint->LinkCount() == 1 )
{
LINKED_ITEM* li = static_cast<LINKED_ITEM*>( extraJoint->LinkList()[0].item );
LINKED_ITEM* li = static_cast<LINKED_ITEM*>( extraJoint->LinkList().front() );
if( li->Collide( solid, m_world ) )
addLinked( solid, extraJoint, li, extraJoint->Pos() - solid->Pos() );
@ -160,7 +160,7 @@ bool COMPONENT_DRAGGER::Drag( const VECTOR2I& aP )
m_world->KillChildren();
m_currentNode = m_world->Branch();
for( const ITEM_SET::ENTRY& item : m_initialDraggedItems.Items() )
for( ITEM* item : m_initialDraggedItems )
m_currentNode->Remove( item );
m_draggedItems.Clear();

View File

@ -145,11 +145,11 @@ bool DIFF_PAIR_PLACER::propagateDpHeadForces ( const VECTOR2I& aP, VECTOR2I& aNe
// check proper clearances to the diff pair line. It can be removed if some specialized
// pushout for traces / diff pairs is implemented. Just calling VIA::PushoutForce does not work
// as the via may have different resolved clearance to items than the diff pair should.
int maxIter = 40;
int iter = 0;
bool collided = false;
VECTOR2I force, totalForce;
std::set<ITEM*> handled;
int maxIter = 40;
int iter = 0;
bool collided = false;
VECTOR2I force, totalForce;
std::set<const ITEM*> handled;
while( iter < maxIter )
{
@ -443,8 +443,8 @@ OPT_VECTOR2I getDanglingAnchor( NODE* aNode, ITEM* aItem )
{
SEGMENT* s = static_cast<SEGMENT*>( aItem );
JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
const JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
const JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
if( jA && jA->LinkCount() == 1 )
return s->Seg().A;

View File

@ -90,19 +90,15 @@ VVIA* DRAGGER::checkVirtualVia( const VECTOR2D& aP, SEGMENT* aSeg )
return nullptr;
}
JOINT *jt = m_world->FindJoint( psnap, aSeg );
const JOINT *jt = m_world->FindJoint( psnap, aSeg );
if ( !jt )
{
return nullptr;
}
for( auto& lnk : jt->LinkList() )
for( ITEM* item : jt->LinkList() )
{
if( lnk.item->IsVirtual() && lnk.item->OfKind( ITEM::VIA_T ))
{
return static_cast<VVIA*>( lnk.item );
}
if( item->IsVirtual() && item->OfKind( ITEM::VIA_T ))
return static_cast<VVIA*>( item );
}
return nullptr;
@ -175,7 +171,7 @@ const ITEM_SET DRAGGER::findViaFanoutByHandle ( NODE *aNode, const VIA_HANDLE& h
{
ITEM_SET rv;
JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
const JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
if( !jt )
return rv;

View File

@ -56,13 +56,53 @@ struct COLLISION_SEARCH_OPTIONS
bool m_useClearanceEpsilon = true;
};
/**
* Dummy interface for ITEMs that can own other ITEMs
*/
class ITEM_OWNER {};
/**
* Base class for an item belonging to some container.
*
* Container can be another ITEM, ITEM_SET or a NODE.
*/
class OWNABLE_ITEM
{
public:
OWNABLE_ITEM() :
m_owner( nullptr )
{}
/**
* Return the owner of this item, or NULL if there's none.
*/
const ITEM_OWNER* Owner() const { return m_owner; }
/**
* Set the node that owns this item. An item can belong to a single NODE or be unowned.
*/
void SetOwner( const ITEM_OWNER* aOwner ) { m_owner = aOwner; }
/**
* @return true if the item is owned by the node aNode.
*/
bool BelongsTo( const ITEM_OWNER* aNode ) const
{
return m_owner == aNode;
}
protected:
const ITEM_OWNER *m_owner;
};
/**
* Base class for PNS router board items.
*
* Implements the shared properties of all PCB items net, spanned layers, geometric shape and
* reference to owning model.
*/
class ITEM
class ITEM : public OWNABLE_ITEM, public ITEM_OWNER
{
public:
static const int UnusedNet = INT_MAX;
@ -176,25 +216,7 @@ public:
{
return Layers().Overlaps( aOther->Layers() );
}
/**
* Return the owner of this item, or NULL if there's none.
*/
NODE* Owner() const { return m_owner; }
/**
* Set the node that owns this item. An item can belong to a single NODE or be unowned.
*/
void SetOwner( NODE* aOwner ) { m_owner = aOwner; }
/**
* @return true if the item is owned by the node aNode.
*/
bool BelongsTo( NODE* aNode ) const
{
return m_owner == aNode;
}
/**
* Check for a collision (clearance violation) with between us and item \a aOther.
*

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-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
@ -32,31 +32,33 @@ ITEM_SET::~ITEM_SET()
void ITEM_SET::Add( const LINE& aLine )
{
LINE* copy = aLine.Clone();
m_items.emplace_back( ENTRY( copy, true ) );
copy->SetOwner( this );
m_items.emplace_back( copy );
}
void ITEM_SET::Prepend( const LINE& aLine )
{
LINE* copy = aLine.Clone();
m_items.emplace( m_items.begin(), ENTRY( copy, true ) );
copy->SetOwner( this );
m_items.emplace( m_items.begin(), copy );
}
ITEM_SET& ITEM_SET::FilterLayers( int aStart, int aEnd, bool aInvert )
{
ENTRIES newItems;
LAYER_RANGE l;
std::vector<ITEM*> newItems;
LAYER_RANGE l;
if( aEnd < 0 )
l = LAYER_RANGE( aStart );
else
l = LAYER_RANGE( aStart, aEnd );
for( const ENTRY& ent : m_items )
for( ITEM* item : m_items )
{
if( ent.item->Layers().Overlaps( l ) ^ aInvert )
newItems.push_back( ent );
if( item->Layers().Overlaps( l ) ^ aInvert )
newItems.push_back( item );
}
m_items = newItems;
@ -67,12 +69,12 @@ ITEM_SET& ITEM_SET::FilterLayers( int aStart, int aEnd, bool aInvert )
ITEM_SET& ITEM_SET::FilterKinds( int aKindMask, bool aInvert )
{
ENTRIES newItems;
std::vector<ITEM*> newItems;
for( const ENTRY& ent : m_items )
for( ITEM *item : m_items )
{
if( ent.item->OfKind( aKindMask ) ^ aInvert )
newItems.push_back( ent );
if( item->OfKind( aKindMask ) ^ aInvert )
newItems.push_back( item );
}
m_items = newItems;
@ -83,12 +85,12 @@ ITEM_SET& ITEM_SET::FilterKinds( int aKindMask, bool aInvert )
ITEM_SET& ITEM_SET::FilterMarker( int aMarker, bool aInvert )
{
ENTRIES newItems;
std::vector<ITEM*> newItems;
for( const ENTRY& ent : m_items )
for( ITEM* item : m_items )
{
if( ent.item->Marker() & aMarker )
newItems.push_back( ent );
if( item->Marker() & aMarker )
newItems.push_back( item );
}
m_items = newItems;
@ -99,12 +101,12 @@ ITEM_SET& ITEM_SET::FilterMarker( int aMarker, bool aInvert )
ITEM_SET& ITEM_SET::FilterNet( int aNet, bool aInvert )
{
ENTRIES newItems;
std::vector<ITEM*> newItems;
for( const ENTRY& ent : m_items )
for( ITEM *item : m_items )
{
if( ( ent.item->Net() == aNet ) ^ aInvert )
newItems.push_back( ent );
if( ( item->Net() == aNet ) ^ aInvert )
newItems.push_back( item );
}
m_items = newItems;
@ -115,12 +117,12 @@ ITEM_SET& ITEM_SET::FilterNet( int aNet, bool aInvert )
ITEM_SET& ITEM_SET::ExcludeItem( const ITEM* aItem )
{
ENTRIES newItems;
std::vector<ITEM*> newItems;
for( const ENTRY& ent : m_items )
for( ITEM* item : m_items )
{
if( ent.item != aItem )
newItems.push_back( ent );
if( item != aItem )
newItems.push_back( item );
}
m_items = newItems;

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
@ -33,69 +33,16 @@ namespace PNS {
*/
class LINE;
class ITEM_SET
class ITEM_SET : public ITEM_OWNER
{
public:
struct ENTRY
{
ENTRY( ITEM* aItem, bool aOwned = false ) :
item( aItem ),
owned( aOwned )
{}
ENTRY( const ENTRY& aOther )
{
owned = aOther.owned;
if( aOther.owned )
item = aOther.item->Clone();
else
item = aOther.item;
}
~ENTRY()
{
if( owned )
delete item;
}
bool operator==( const ENTRY& b ) const
{
return item == b.item;
}
bool operator<( const ENTRY& b ) const
{
return item < b.item;
}
ENTRY& operator=( const ENTRY& aOther )
{
owned = aOther.owned;
if( aOther.owned )
item = aOther.item->Clone();
else
item = aOther.item;
return *this;
}
operator ITEM* () const
{
return item;
}
ITEM *item;
bool owned;
};
typedef std::vector<ENTRY> ENTRIES;
ITEM_SET( ITEM* aInitialItem = nullptr, bool aBecomeOwner = false )
{
if( aInitialItem )
m_items.emplace_back( ENTRY( aInitialItem, aBecomeOwner ) );
m_items.emplace_back( aInitialItem );
if( aBecomeOwner )
aInitialItem->SetOwner( this );
}
ITEM_SET( const ITEM_SET& aOther )
@ -107,7 +54,12 @@ public:
ITEM_SET& operator=( const ITEM_SET& aOther )
{
m_items = aOther.m_items;
m_items.clear();
m_items.reserve( aOther.m_items.size() );
for( ITEM* item : aOther.m_items )
m_items.push_back( item );
return *this;
}
@ -132,8 +84,8 @@ public:
return m_items.empty();
}
ENTRIES& Items() { return m_items; }
const ENTRIES& CItems() const { return m_items; }
std::vector<ITEM*>& Items() { return m_items; }
const std::vector<ITEM*>& CItems() const { return m_items; }
ITEM_SET& FilterLayers( int aStart, int aEnd = -1, bool aInvert = false );
ITEM_SET& FilterKinds( int aKindMask, bool aInvert = false );
@ -167,22 +119,28 @@ public:
ITEM* operator[]( size_t aIndex ) const
{
return m_items[aIndex].item;
return m_items[aIndex];
}
ENTRIES::iterator begin() { return m_items.begin(); }
ENTRIES::iterator end() { return m_items.end(); }
ENTRIES::const_iterator cbegin() const { return m_items.cbegin(); }
ENTRIES::const_iterator cend() const { return m_items.cend(); }
std::vector<ITEM*>::iterator begin() { return m_items.begin(); }
std::vector<ITEM*>::iterator end() { return m_items.end(); }
std::vector<ITEM*>::const_iterator cbegin() const { return m_items.cbegin(); }
std::vector<ITEM*>::const_iterator cend() const { return m_items.cend(); }
void Add( ITEM* aItem, bool aBecomeOwner = false )
{
m_items.emplace_back( ENTRY( aItem, aBecomeOwner ) );
m_items.emplace_back( aItem );
if( aBecomeOwner )
aItem->SetOwner( this );
}
void Prepend( ITEM* aItem, bool aBecomeOwner = false )
{
m_items.emplace( m_items.begin(), ENTRY( aItem, aBecomeOwner ) );
m_items.emplace( m_items.begin(), aItem );
if( aBecomeOwner )
aItem->SetOwner( this );
}
void Clear()
@ -192,14 +150,12 @@ public:
bool Contains( ITEM* aItem ) const
{
const ENTRY ent( aItem );
return alg::contains( m_items, ent );
return alg::contains( m_items, aItem );
}
void Erase( ITEM* aItem )
{
ENTRY ent( aItem );
ENTRIES::iterator f = std::find( m_items.begin(), m_items.end(), ent );
std::vector<ITEM*>::iterator f = std::find( m_items.begin(), m_items.end(), aItem );
if( f != m_items.end() )
m_items.erase( f );
@ -225,7 +181,7 @@ public:
}
private:
ENTRIES m_items;
std::vector<ITEM*> m_items;
};
}

View File

@ -42,8 +42,6 @@ namespace PNS {
class JOINT : public ITEM
{
public:
typedef ITEM_SET::ENTRIES LINKED_ITEMS;
///< Joints are hashed by their position, layers and net.
///< Linked items are, obviously, not hashed.
struct HASH_TAG
@ -210,12 +208,12 @@ public:
return static_cast<LINKED_ITEM*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
}
VIA* Via()
VIA* Via() const
{
for( ITEM* item : m_linkedItems.Items() )
for( ITEM* item : m_linkedItems.CItems() )
{
if( item->OfKind( VIA_T ) )
return static_cast<VIA*>( item );
return static_cast<VIA*>( item ); // fixme: const correctness
}
return nullptr;
@ -238,7 +236,7 @@ public:
return m_tag.net;
}
const LINKED_ITEMS& LinkList() const
const std::vector<ITEM*>& LinkList() const
{
return m_linkedItems.CItems();
}

View File

@ -125,7 +125,7 @@ public:
PNS::CONSTRAINT* aConstraint ) override;
virtual wxString NetName( int aNet ) override;
int ClearanceEpsilon() const { return m_clearanceEpsilon; }
int ClearanceEpsilon() const override { return m_clearanceEpsilon; }
void ClearCacheForItem( const PNS::ITEM* aItem ) override;
void ClearCaches() override;
@ -554,13 +554,13 @@ bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedW
return false;
}
PNS::JOINT* jt = static_cast<PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
const PNS::JOINT* jt = static_cast<const PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
assert( jt != nullptr );
int mval = INT_MAX;
PNS::ITEM_SET linkedSegs = jt->Links();
PNS::ITEM_SET linkedSegs( jt->CLinks() );
linkedSegs.ExcludeItem( aItem ).FilterKinds( PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T );
for( PNS::ITEM* item : linkedSegs.Items() )

View File

@ -935,7 +935,7 @@ bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead, LINE& aNewTai
if( m_endItem )
{
// Make sure the springback algorithm won't erase the NODE that owns m_endItem.
m_shove->SetSpringbackDoNotTouchNode( m_endItem->Owner() );
m_shove->SetSpringbackDoNotTouchNode( static_cast<const NODE*>( m_endItem->Owner() ) );
}
LINE newHead( walkSolids );
@ -1268,7 +1268,7 @@ bool LINE_PLACER::SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I
if( !aSeg->OfKind( ITEM::SEGMENT_T ) )
return false;
JOINT* jt = aNode->FindJoint( aP, aSeg );
const JOINT* jt = aNode->FindJoint( aP, aSeg );
if( jt && jt->LinkCount() >= 1 )
return false;
@ -1430,7 +1430,7 @@ bool LINE_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
int eiDepth = -1;
if( aEndItem && aEndItem->Owner() )
eiDepth = static_cast<NODE*>( aEndItem->Owner() )->Depth();
eiDepth = static_cast<const NODE*>( aEndItem->Owner() )->Depth();
if( m_lastNode )
{
@ -1783,7 +1783,7 @@ void LINE_PLACER::simplifyNewLine( NODE* aNode, LINKED_ITEM* aLatest )
std::set<ITEM*> cleanup;
auto processJoint =
[&]( JOINT* aJoint, ITEM* aItem )
[&]( const JOINT* aJoint, ITEM* aItem )
{
if( !aJoint || aJoint->IsLineCorner() )
return;
@ -1792,7 +1792,7 @@ void LINE_PLACER::simplifyNewLine( NODE* aNode, LINKED_ITEM* aLatest )
NODE::ITEM_VECTOR toRemove;
for( ITEM* neighbor : aJoint->Links() )
for( ITEM* neighbor : aJoint->CLinks().CItems() )
{
if( neighbor == aItem
|| !neighbor->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T )
@ -1801,18 +1801,18 @@ void LINE_PLACER::simplifyNewLine( NODE* aNode, LINKED_ITEM* aLatest )
continue;
}
if( static_cast<SEGMENT*>( neighbor )->Width()
!= static_cast<SEGMENT*>( aItem )->Width() )
if( static_cast<const SEGMENT*>( neighbor )->Width()
!= static_cast<const SEGMENT*>( aItem )->Width() )
{
continue;
}
const SEG& testSeg = static_cast<SEGMENT*>( neighbor )->Seg();
const SEG& testSeg = static_cast<const SEGMENT*>( neighbor )->Seg();
if( refSeg.Contains( testSeg ) )
{
JOINT* nA = aNode->FindJoint( neighbor->Anchor( 0 ), neighbor );
JOINT* nB = aNode->FindJoint( neighbor->Anchor( 1 ), neighbor );
const JOINT* nA = aNode->FindJoint( neighbor->Anchor( 0 ), neighbor );
const JOINT* nB = aNode->FindJoint( neighbor->Anchor( 1 ), neighbor );
if( ( nA == aJoint && nB->LinkCount() == 1 ) ||
( nB == aJoint && nA->LinkCount() == 1 ) )
@ -1828,8 +1828,8 @@ void LINE_PLACER::simplifyNewLine( NODE* aNode, LINKED_ITEM* aLatest )
if( !item->OfKind( ITEM::SEGMENT_T ) || cleanup.count( item ) )
continue;
JOINT* jA = aNode->FindJoint( item->Anchor( 0 ), item );
JOINT* jB = aNode->FindJoint( item->Anchor( 1 ), item );
const JOINT* jA = aNode->FindJoint( item->Anchor( 0 ), item );
const JOINT* jB = aNode->FindJoint( item->Anchor( 1 ), item );
processJoint( jA, item );
processJoint( jB, item );

View File

@ -69,7 +69,7 @@ int MEANDER_PLACER_BASE::Clearance()
// Assumption: All tracks are part of the same net class.
// It shouldn't matter which track we pick. They should all have the same clearance if
// they are part of the same net class. Therefore, pick the first one on the list.
ITEM* itemToCheck = Traces().CItems().front().item;
ITEM* itemToCheck = Traces().CItems().front();
PNS::CONSTRAINT constraint;
Router()->GetRuleResolver()->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, itemToCheck,
@ -308,7 +308,7 @@ int MEANDER_PLACER_BASE::GetTotalPadToDieLength( const LINE& aLine ) const
// Extract the length of the pad to die for start and end pads
for( auto& link : start.LinkList() )
{
if( const SOLID* solid = dynamic_cast<const SOLID*>( link.item ) )
if( const SOLID* solid = dyn_cast<const SOLID*>( link ) )
{
// If there are overlapping pads, choose the first with a non-zero length
if( solid->GetPadToDie() > 0 )
@ -321,7 +321,7 @@ int MEANDER_PLACER_BASE::GetTotalPadToDieLength( const LINE& aLine ) const
for( auto& link : end.LinkList() )
{
if( const SOLID* solid = dynamic_cast<const SOLID*>( link.item ) )
if( const SOLID* solid = dyn_cast<const SOLID*>( link ) )
{
if( solid->GetPadToDie() > 0 )
{

View File

@ -48,7 +48,7 @@
namespace PNS {
#ifdef DEBUG
static std::unordered_set<NODE*> allocNodes;
static std::unordered_set<const NODE*> allocNodes;
#endif
NODE::NODE()
@ -784,15 +784,15 @@ void NODE::removeArcIndex( ARC* aArc )
}
void NODE::rebuildJoint( JOINT* aJoint, ITEM* aItem )
void NODE::rebuildJoint( const JOINT* aJoint, const ITEM* aItem )
{
// We have to split a single joint (associated with a via or a pad, binding together multiple
// layers) into multiple independent joints. As I'm a lazy bastard, I simply delete the
// via/solid and all its links and re-insert them.
JOINT::LINKED_ITEMS links( aJoint->LinkList() );
JOINT::HASH_TAG tag;
int net = aItem->Net();
std::vector<ITEM*> links( aJoint->LinkList() );
JOINT::HASH_TAG tag;
int net = aItem->Net();
tag.net = net;
tag.pos = aJoint->Pos();
@ -831,7 +831,7 @@ void NODE::rebuildJoint( JOINT* aJoint, ITEM* aItem )
void NODE::removeViaIndex( VIA* aVia )
{
JOINT* jt = FindJoint( aVia->Pos(), aVia->Layers().Start(), aVia->Net() );
const JOINT* jt = FindJoint( aVia->Pos(), aVia->Layers().Start(), aVia->Net() );
assert( jt );
rebuildJoint( jt, aVia );
}
@ -843,7 +843,7 @@ void NODE::removeSolidIndex( SOLID* aSolid )
return;
// fixme: redundant code
JOINT* jt = FindJoint( aSolid->Pos(), aSolid->Layers().Start(), aSolid->Net() );
const JOINT* jt = FindJoint( aSolid->Pos(), aSolid->Layers().Start(), aSolid->Net() );
assert( jt );
rebuildJoint( jt, aSolid );
}
@ -1123,7 +1123,7 @@ int NODE::FindLinesBetweenJoints( const JOINT& aA, const JOINT& aB, std::vector<
void NODE::FixupVirtualVias()
{
SEGMENT* locked_seg = nullptr;
const SEGMENT* locked_seg = nullptr;
std::vector<VVIA*> vvias;
for( auto& jointPair : m_joints )
@ -1139,17 +1139,17 @@ void NODE::FixupVirtualVias()
bool is_width_change = false;
bool is_locked = false;
for( const auto& lnk : joint.LinkList() )
for( const ITEM* item : joint.LinkList() )
{
if( lnk.item->OfKind( ITEM::VIA_T ) )
if( item->OfKind( ITEM::VIA_T ) )
{
n_vias++;
}
else if( lnk.item->OfKind( ITEM::SOLID_T ) )
else if( item->OfKind( ITEM::SOLID_T ) )
{
n_solid++;
}
else if( const auto t = dyn_cast<PNS::SEGMENT*>( lnk.item ) )
else if( const auto t = dyn_cast<const PNS::SEGMENT*>( item ) )
{
int w = t->Width();
@ -1192,14 +1192,14 @@ void NODE::FixupVirtualVias()
}
JOINT* NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet )
const JOINT* NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ) const
{
JOINT::HASH_TAG tag;
tag.net = aNet;
tag.pos = aPos;
JOINT_MAP::iterator f = m_joints.find( tag ), end = m_joints.end();
JOINT_MAP::const_iterator f = m_joints.find( tag ), end = m_joints.end();
if( f == end && !isRoot() )
{
@ -1524,7 +1524,7 @@ void NODE::RemoveByMarker( int aMarker )
SEGMENT* NODE::findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
int aNet )
{
JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
if( !jtStart )
return nullptr;
@ -1559,7 +1559,7 @@ SEGMENT* NODE::findRedundantSegment( SEGMENT* aSeg )
ARC* NODE::findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
int aNet )
{
JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
if( !jtStart )
return nullptr;

View File

@ -105,10 +105,7 @@ public:
virtual void ClearCacheForItem( const ITEM* aItem ) {}
virtual void ClearCaches() {}
virtual int ClearanceEpsilon() const { return m_clearanceEpsilon; }
protected:
int m_clearanceEpsilon = 0;
virtual int ClearanceEpsilon() const { return 0; }
};
/**
@ -161,7 +158,7 @@ protected:
* - assembly of lines connecting joints, finding loops and unique paths.
* - lightweight cloning/branching (for recursive optimization and shove springback).
**/
class NODE
class NODE : public ITEM_OWNER
{
public:
@ -372,7 +369,7 @@ public:
*
* @return the joint, if found, otherwise empty.
*/
JOINT* FindJoint( const VECTOR2I& aPos, int aLayer, int aNet );
const JOINT* FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ) const;
void LockJoint( const VECTOR2I& aPos, const ITEM* aItem, bool aLock );
@ -381,7 +378,7 @@ public:
*
* @return the joint, if found, otherwise empty.
*/
JOINT* FindJoint( const VECTOR2I& aPos, const ITEM* aItem )
const JOINT* FindJoint( const VECTOR2I& aPos, const ITEM* aItem ) const
{
return FindJoint( aPos, aItem->Layers().Start(), aItem->Net() );
}
@ -463,7 +460,7 @@ private:
void unlinkParent();
void releaseChildren();
void releaseGarbage();
void rebuildJoint( JOINT* aJoint, ITEM* aItem );
void rebuildJoint( const JOINT* aJoint, const ITEM* aItem );
bool isRoot() const
{

View File

@ -930,7 +930,7 @@ OPTIMIZER::BREAKOUT_LIST OPTIMIZER::computeBreakouts( int aWidth, const ITEM* aI
ITEM* OPTIMIZER::findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const
{
JOINT* jt = m_world->FindJoint( aP, aLayer, aNet );
const JOINT* jt = m_world->FindJoint( aP, aLayer, aNet );
if( !jt )
return nullptr;

View File

@ -519,8 +519,8 @@ bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEn
// Otherwise, find the closest anchor to our start point
// Get joint from placer start item
JOINT* jt = lastNode->FindJoint( placer->CurrentStart(), placer->CurrentLayer(),
placer->CurrentNets()[0] );
const JOINT* jt = lastNode->FindJoint( placer->CurrentStart(), placer->CurrentLayer(),
placer->CurrentNets()[0] );
if( !jt )
return false;
@ -816,10 +816,8 @@ void ROUTER::GetUpdatedItems( std::vector<PNS::ITEM*>& aRemoved, std::vector<PNS
node->GetUpdatedItems( aRemoved, aAdded );
for( auto item : current.CItems() )
{
aHeads.push_back( item.item->Clone() );
}
for( const ITEM* item : current.CItems() )
aHeads.push_back( item->Clone() );
}

View File

@ -369,7 +369,7 @@ SHOVE::SHOVE_STATUS SHOVE::shoveLineToHullSet( const LINE& aCurLine, const LINE&
if(( aCurLine.Marker() & MK_HEAD ) && !colliding )
{
JOINT* jtStart = m_currentNode->FindJoint( aCurLine.CPoint( 0 ), &aCurLine );
const JOINT* jtStart = m_currentNode->FindJoint( aCurLine.CPoint( 0 ), &aCurLine );
for( ITEM* item : jtStart->LinkList() )
{
@ -664,7 +664,7 @@ SHOVE::SHOVE_STATUS SHOVE::onCollidingSolid( LINE& aCurrent, ITEM* aObstacle, OB
{
VIA vh = aCurrent.Via();
VIA* via = nullptr;
JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), &aCurrent );
const JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), &aCurrent );
if( !jtStart )
return SH_INCOMPLETE;
@ -868,7 +868,7 @@ SHOVE::SHOVE_STATUS SHOVE::pushOrShoveVia( VIA* aVia, const VECTOR2I& aForce, in
{
LINE_PAIR_VEC draggedLines;
VECTOR2I p0( aVia->Pos() );
JOINT* jt = m_currentNode->FindJoint( p0, aVia );
const JOINT* jt = m_currentNode->FindJoint( p0, aVia );
VECTOR2I p0_pushed( p0 + aForce );
PNS_DBG( Dbg(), Message, wxString::Format( wxT( "via force [%d %d]\n" ), aForce.x, aForce.y ) );
@ -893,7 +893,7 @@ SHOVE::SHOVE_STATUS SHOVE::pushOrShoveVia( VIA* aVia, const VECTOR2I& aForce, in
// make sure pushed via does not overlap with any existing joint
while( true )
{
JOINT* jt_next = m_currentNode->FindJoint( p0_pushed, aVia );
const JOINT* jt_next = m_currentNode->FindJoint( p0_pushed, aVia );
if( !jt_next )
break;
@ -1070,7 +1070,7 @@ SHOVE::SHOVE_STATUS SHOVE::onReverseCollidingVia( LINE& aCurrent, VIA* aObstacle
LINE cur( aCurrent );
cur.ClearLinks();
JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia );
const JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia );
LINE shoved( aCurrent );
shoved.ClearLinks();
@ -1152,7 +1152,7 @@ SHOVE::SHOVE_STATUS SHOVE::onReverseCollidingVia( LINE& aCurrent, VIA* aObstacle
}
void SHOVE::unwindLineStack( LINKED_ITEM* aSeg )
void SHOVE::unwindLineStack( const LINKED_ITEM* aSeg )
{
int d = 0;
@ -1179,15 +1179,17 @@ void SHOVE::unwindLineStack( LINKED_ITEM* aSeg )
}
void SHOVE::unwindLineStack( ITEM* aItem )
void SHOVE::unwindLineStack( const ITEM* aItem )
{
if( aItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
unwindLineStack( static_cast<LINKED_ITEM*>( aItem ) );
if( aItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
{
unwindLineStack( static_cast<const LINKED_ITEM*>( aItem ) );
}
else if( aItem->OfKind( ITEM::LINE_T ) )
{
LINE* l = static_cast<LINE*>( aItem );
const LINE* l = static_cast<const LINE*>( aItem );
for( LINKED_ITEM* seg : l->Links() )
for( const LINKED_ITEM* seg : l->Links() )
unwindLineStack( seg );
}
}
@ -1253,20 +1255,22 @@ bool SHOVE::fixupViaCollisions( const LINE* aCurrent, OBSTACLE& obs )
// our colliding item is a via: just find the max width of the traces connected to it
if( obs.m_item->OfKind( ITEM::VIA_T ) )
{
VIA* v = static_cast<VIA*>( obs.m_item );
int maxw = 0;
JOINT* jv = m_currentNode->FindJoint( v->Pos(), v );
const VIA* v = static_cast<const VIA*>( obs.m_item );
int maxw = 0;
const JOINT* jv = m_currentNode->FindJoint( v->Pos(), v );
for( auto link : jv->Links() )
ITEM_SET links( jv->CLinks() );
for( ITEM* link : links )
{
if( link.item->OfKind( ITEM::SEGMENT_T ) ) // consider segments ...
if( link->OfKind( ITEM::SEGMENT_T ) ) // consider segments ...
{
auto seg = static_cast<SEGMENT*>( link.item );
const SEGMENT* seg = static_cast<const SEGMENT*>( link );
maxw = std::max( seg->Width(), maxw );
}
else if( link.item->OfKind( ITEM::ARC_T ) ) // ... or arcs
else if( link->OfKind( ITEM::ARC_T ) ) // ... or arcs
{
auto arc = static_cast<ARC*>( link.item );
const ARC* arc = static_cast<const ARC*>( link );
maxw = std::max( arc->Width(), maxw );
}
}
@ -1289,10 +1293,10 @@ bool SHOVE::fixupViaCollisions( const LINE* aCurrent, OBSTACLE& obs )
if( !obs.m_item->OfKind( ITEM::SEGMENT_T ) )
return false;
auto s = static_cast<SEGMENT*>( obs.m_item );
const SEGMENT* s = static_cast<const SEGMENT*>( obs.m_item );
JOINT* ja = m_currentNode->FindJoint( s->Seg().A, s );
JOINT* jb = m_currentNode->FindJoint( s->Seg().B, s );
const JOINT* ja = m_currentNode->FindJoint( s->Seg().A, s );
const JOINT* jb = m_currentNode->FindJoint( s->Seg().B, s );
VIA* vias[] = { ja->Via(), jb->Via() };
@ -1753,7 +1757,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveMultiLines( const ITEM_SET& aHeadSet )
static VIA* findViaByHandle ( NODE *aNode, const VIA_HANDLE& handle )
{
JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
const JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
if( !jt )
return nullptr;
@ -2045,7 +2049,7 @@ void SHOVE::DisablePostShoveOptimizations( int aMask )
}
void SHOVE::SetSpringbackDoNotTouchNode( NODE *aNode )
void SHOVE::SetSpringbackDoNotTouchNode( const NODE *aNode )
{
m_springbackDoNotTouchNode = aNode;
}

View File

@ -90,7 +90,7 @@ public:
bool RewindSpringbackTo( NODE* aNode );
bool RewindToLastLockedNode();
void DisablePostShoveOptimizations( int aMask );
void SetSpringbackDoNotTouchNode( NODE *aNode );
void SetSpringbackDoNotTouchNode( const NODE *aNode );
private:
typedef std::vector<SHAPE_LINE_CHAIN> HULL_SET;
@ -139,8 +139,8 @@ private:
OPT_BOX2I totalAffectedArea() const;
void unwindLineStack( LINKED_ITEM* aSeg );
void unwindLineStack( ITEM* aItem );
void unwindLineStack( const LINKED_ITEM* aSeg );
void unwindLineStack( const ITEM* aItem );
void runOptimizer( NODE* aNode );
@ -172,7 +172,7 @@ private:
NODE* m_root;
NODE* m_currentNode;
NODE* m_springbackDoNotTouchNode;
const NODE* m_springbackDoNotTouchNode;
int m_restrictSpringbackTagId;
OPT_LINE m_newHead;

View File

@ -59,26 +59,26 @@ bool TOPOLOGY::SimplifyLine( LINE* aLine )
}
const TOPOLOGY::JOINT_SET TOPOLOGY::ConnectedJoints( JOINT* aStart )
const TOPOLOGY::JOINT_SET TOPOLOGY::ConnectedJoints( const JOINT* aStart )
{
std::deque<JOINT*> searchQueue;
JOINT_SET processed;
std::deque<const JOINT*> searchQueue;
JOINT_SET processed;
searchQueue.push_back( aStart );
processed.insert( aStart );
while( !searchQueue.empty() )
{
JOINT* current = searchQueue.front();
const JOINT* current = searchQueue.front();
searchQueue.pop_front();
for( ITEM* item : current->LinkList() )
{
if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
if( item->OfKind( ITEM::SEGMENT_T ) )
{
JOINT* a = m_world->FindJoint( item->Anchor( 0 ), item );;
JOINT* b = m_world->FindJoint( item->Anchor( 1 ), item );;
JOINT* next = ( *a == *current ) ? b : a;
const JOINT* a = m_world->FindJoint( item->Anchor( 0 ), item );;
const JOINT* b = m_world->FindJoint( item->Anchor( 1 ), item );;
const JOINT* next = ( *a == *current ) ? b : a;
if( processed.find( next ) == processed.end() )
{
@ -105,7 +105,7 @@ bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoi
std::unique_ptr<NODE> tmpNode( m_world->Branch() );
tmpNode->Add( track );
JOINT* jt = tmpNode->FindJoint( track.CPoint( -1 ), &track );
const JOINT* jt = tmpNode->FindJoint( track.CPoint( -1 ), &track );
if( !jt || jt->Net() <= 0 )
return false;
@ -151,7 +151,7 @@ bool TOPOLOGY::LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine )
}
ITEM* TOPOLOGY::NearestUnconnectedItem( JOINT* aStart, int* aAnchor, int aKindMask )
ITEM* TOPOLOGY::NearestUnconnectedItem( const JOINT* aStart, int* aAnchor, int aKindMask )
{
std::set<ITEM*> disconnected;
@ -195,13 +195,13 @@ ITEM* TOPOLOGY::NearestUnconnectedItem( JOINT* aStart, int* aAnchor, int aKindMa
bool TOPOLOGY::followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet,
std::set<ITEM*>& aVisited, JOINT** aTerminalJoint )
std::set<ITEM*>& aVisited, const JOINT** aTerminalJoint )
{
assert( aLine->IsLinked() );
VECTOR2I anchor = aLeft ? aLine->CPoint( 0 ) : aLine->CPoint( -1 );
LINKED_ITEM* last = aLeft ? aLine->Links().front() : aLine->Links().back();
JOINT* jt = m_world->FindJoint( anchor, aLine );
const JOINT* jt = m_world->FindJoint( anchor, aLine );
assert( jt != nullptr );
@ -212,7 +212,9 @@ bool TOPOLOGY::followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet,
ITEM* via = nullptr;
SEGMENT* next_seg = nullptr;
for( ITEM* link : jt->Links().Items() )
ITEM_SET links( jt->CLinks() );
for( ITEM* link : links )
{
if( link->OfKind( ITEM::VIA_T ) )
via = link;
@ -263,7 +265,7 @@ bool TOPOLOGY::followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet,
const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
std::pair<JOINT*, JOINT*>* aTerminalJoints,
std::pair<const JOINT*, const JOINT*>* aTerminalJoints,
bool aFollowLockedSegments )
{
ITEM_SET path;
@ -272,17 +274,19 @@ const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
if( aStart->Kind() == ITEM::VIA_T )
{
VIA* via = static_cast<VIA*>( aStart );
JOINT* jt = m_world->FindJoint( via->Pos(), via );
VIA* via = static_cast<VIA*>( aStart );
const JOINT* jt = m_world->FindJoint( via->Pos(), via );
if( !jt->IsNonFanoutVia() )
return ITEM_SET();
for( const ITEM_SET::ENTRY& entry : jt->Links().Items() )
ITEM_SET links( jt->CLinks() );
for( ITEM* item : links )
{
if( entry.item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
{
seg = static_cast<LINKED_ITEM*>( entry.item );
seg = static_cast<LINKED_ITEM*>( item );
break;
}
}
@ -301,8 +305,8 @@ const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
path.Add( l );
JOINT* jointA = nullptr;
JOINT* jointB = nullptr;
const JOINT* jointA = nullptr;
const JOINT* jointB = nullptr;
followTrivialPath( &l, false, path, visited, &jointB );
followTrivialPath( &l, true, path, visited, &jointA );
@ -319,14 +323,14 @@ const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
const ITEM_SET TOPOLOGY::AssembleTuningPath( ITEM* aStart, SOLID** aStartPad, SOLID** aEndPad )
{
std::pair<JOINT*, JOINT*> joints;
std::pair<const JOINT*, const JOINT*> joints;
ITEM_SET initialPath = AssembleTrivialPath( aStart, &joints, true );
PAD* padA = nullptr;
PAD* padB = nullptr;
auto getPadFromJoint =
[]( JOINT* aJoint, PAD** aTargetPad, SOLID** aTargetSolid )
[]( const JOINT* aJoint, PAD** aTargetPad, SOLID** aTargetSolid )
{
for( ITEM* item : aJoint->LinkList() )
{
@ -403,7 +407,7 @@ const ITEM_SET TOPOLOGY::AssembleTuningPath( ITEM* aStart, SOLID** aStartPad, SO
};
auto processPad =
[&]( JOINT* aJoint, PAD* aPad )
[&]( const JOINT* aJoint, PAD* aPad )
{
const std::shared_ptr<SHAPE_POLY_SET>& shape = aPad->GetEffectivePolygon();
@ -441,7 +445,7 @@ const ITEM_SET TOPOLOGY::AssembleTuningPath( ITEM* aStart, SOLID** aStartPad, SO
}
const ITEM_SET TOPOLOGY::ConnectedItems( JOINT* aStart, int aKindMask )
const ITEM_SET TOPOLOGY::ConnectedItems( const JOINT* aStart, int aKindMask )
{
return ITEM_SET();
}
@ -553,7 +557,7 @@ const std::set<ITEM*> TOPOLOGY::AssembleCluster( ITEM* aStart, int aLayer )
m_world->QueryColliding( top, obstacles, opts ); // only query touching objects
for( OBSTACLE& obs : obstacles )
for( const OBSTACLE& obs : obstacles )
{
bool trackOnTrack = ( obs.m_item->Net() != top->Net() ) && obs.m_item->OfKind( ITEM::SEGMENT_T ) && top->OfKind( ITEM::SEGMENT_T );

View File

@ -39,7 +39,7 @@ class DIFF_PAIR;
class TOPOLOGY
{
public:
typedef std::set<JOINT*> JOINT_SET;
typedef std::set<const JOINT*> JOINT_SET;
TOPOLOGY( NODE* aNode ):
m_world( aNode ) {};
@ -47,15 +47,15 @@ public:
~TOPOLOGY() {};
bool SimplifyLine( LINE *aLine );
ITEM* NearestUnconnectedItem( JOINT* aStart, int* aAnchor = nullptr,
ITEM* NearestUnconnectedItem( const JOINT* aStart, int* aAnchor = nullptr,
int aKindMask = ITEM::ANY_T );
bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint,
LAYER_RANGE& aLayers );
bool LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine );
const JOINT_SET ConnectedJoints( JOINT* aStart );
const ITEM_SET ConnectedItems( JOINT* aStart, int aKindMask = ITEM::ANY_T );
const JOINT_SET ConnectedJoints( const JOINT* aStart );
const ITEM_SET ConnectedItems( const JOINT* aStart, int aKindMask = ITEM::ANY_T );
const ITEM_SET ConnectedItems( ITEM* aStart, int aKindMask = ITEM::ANY_T );
int64_t ShortestConnectionLength( ITEM* aFrom, ITEM* aTo );
@ -68,7 +68,7 @@ public:
* @return a set of items in the path.
*/
const ITEM_SET AssembleTrivialPath( ITEM* aStart,
std::pair<JOINT*, JOINT*>* aTerminalJoints = nullptr,
std::pair<const JOINT*, const JOINT*>* aTerminalJoints = nullptr,
bool aFollowLockedSegments = false );
/**
@ -96,7 +96,7 @@ private:
const int DP_PARALLELITY_THRESHOLD = 5;
bool followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet, std::set<ITEM*>& aVisited,
JOINT** aTerminalJoint = nullptr );
const JOINT** aTerminalJoint = nullptr );
NODE *m_world;
};