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

View File

@ -149,7 +149,7 @@ bool DIFF_PAIR_PLACER::propagateDpHeadForces ( const VECTOR2I& aP, VECTOR2I& aNe
int iter = 0; int iter = 0;
bool collided = false; bool collided = false;
VECTOR2I force, totalForce; VECTOR2I force, totalForce;
std::set<ITEM*> handled; std::set<const ITEM*> handled;
while( iter < maxIter ) while( iter < maxIter )
{ {
@ -443,8 +443,8 @@ OPT_VECTOR2I getDanglingAnchor( NODE* aNode, ITEM* aItem )
{ {
SEGMENT* s = static_cast<SEGMENT*>( aItem ); SEGMENT* s = static_cast<SEGMENT*>( aItem );
JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem ); const JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem ); const JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
if( jA && jA->LinkCount() == 1 ) if( jA && jA->LinkCount() == 1 )
return s->Seg().A; return s->Seg().A;

View File

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

View File

@ -56,13 +56,53 @@ struct COLLISION_SEARCH_OPTIONS
bool m_useClearanceEpsilon = true; 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. * Base class for PNS router board items.
* *
* Implements the shared properties of all PCB items net, spanned layers, geometric shape and * Implements the shared properties of all PCB items net, spanned layers, geometric shape and
* reference to owning model. * reference to owning model.
*/ */
class ITEM class ITEM : public OWNABLE_ITEM, public ITEM_OWNER
{ {
public: public:
static const int UnusedNet = INT_MAX; static const int UnusedNet = INT_MAX;
@ -177,24 +217,6 @@ public:
return Layers().Overlaps( aOther->Layers() ); 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. * 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 * 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-2023 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
@ -32,20 +32,22 @@ ITEM_SET::~ITEM_SET()
void ITEM_SET::Add( const LINE& aLine ) void ITEM_SET::Add( const LINE& aLine )
{ {
LINE* copy = aLine.Clone(); 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 ) void ITEM_SET::Prepend( const LINE& aLine )
{ {
LINE* copy = aLine.Clone(); 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 ) ITEM_SET& ITEM_SET::FilterLayers( int aStart, int aEnd, bool aInvert )
{ {
ENTRIES newItems; std::vector<ITEM*> newItems;
LAYER_RANGE l; LAYER_RANGE l;
if( aEnd < 0 ) if( aEnd < 0 )
@ -53,10 +55,10 @@ ITEM_SET& ITEM_SET::FilterLayers( int aStart, int aEnd, bool aInvert )
else else
l = LAYER_RANGE( aStart, aEnd ); l = LAYER_RANGE( aStart, aEnd );
for( const ENTRY& ent : m_items ) for( ITEM* item : m_items )
{ {
if( ent.item->Layers().Overlaps( l ) ^ aInvert ) if( item->Layers().Overlaps( l ) ^ aInvert )
newItems.push_back( ent ); newItems.push_back( item );
} }
m_items = newItems; 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 ) 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 ) if( item->OfKind( aKindMask ) ^ aInvert )
newItems.push_back( ent ); newItems.push_back( item );
} }
m_items = newItems; 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 ) 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 ) if( item->Marker() & aMarker )
newItems.push_back( ent ); newItems.push_back( item );
} }
m_items = newItems; 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 ) 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 ) if( ( item->Net() == aNet ) ^ aInvert )
newItems.push_back( ent ); newItems.push_back( item );
} }
m_items = newItems; m_items = newItems;
@ -115,12 +117,12 @@ ITEM_SET& ITEM_SET::FilterNet( int aNet, bool aInvert )
ITEM_SET& ITEM_SET::ExcludeItem( const ITEM* aItem ) 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 ) if( item != aItem )
newItems.push_back( ent ); newItems.push_back( item );
} }
m_items = newItems; m_items = newItems;

View File

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

View File

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

View File

@ -125,7 +125,7 @@ public:
PNS::CONSTRAINT* aConstraint ) override; PNS::CONSTRAINT* aConstraint ) override;
virtual wxString NetName( int aNet ) 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 ClearCacheForItem( const PNS::ITEM* aItem ) override;
void ClearCaches() override; void ClearCaches() override;
@ -554,13 +554,13 @@ bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedW
return false; 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 ); assert( jt != nullptr );
int mval = INT_MAX; 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 ); linkedSegs.ExcludeItem( aItem ).FilterKinds( PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T );
for( PNS::ITEM* item : linkedSegs.Items() ) 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 ) if( m_endItem )
{ {
// Make sure the springback algorithm won't erase the NODE that owns 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 ); LINE newHead( walkSolids );
@ -1268,7 +1268,7 @@ bool LINE_PLACER::SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I
if( !aSeg->OfKind( ITEM::SEGMENT_T ) ) if( !aSeg->OfKind( ITEM::SEGMENT_T ) )
return false; return false;
JOINT* jt = aNode->FindJoint( aP, aSeg ); const JOINT* jt = aNode->FindJoint( aP, aSeg );
if( jt && jt->LinkCount() >= 1 ) if( jt && jt->LinkCount() >= 1 )
return false; return false;
@ -1430,7 +1430,7 @@ bool LINE_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
int eiDepth = -1; int eiDepth = -1;
if( aEndItem && aEndItem->Owner() ) if( aEndItem && aEndItem->Owner() )
eiDepth = static_cast<NODE*>( aEndItem->Owner() )->Depth(); eiDepth = static_cast<const NODE*>( aEndItem->Owner() )->Depth();
if( m_lastNode ) if( m_lastNode )
{ {
@ -1783,7 +1783,7 @@ void LINE_PLACER::simplifyNewLine( NODE* aNode, LINKED_ITEM* aLatest )
std::set<ITEM*> cleanup; std::set<ITEM*> cleanup;
auto processJoint = auto processJoint =
[&]( JOINT* aJoint, ITEM* aItem ) [&]( const JOINT* aJoint, ITEM* aItem )
{ {
if( !aJoint || aJoint->IsLineCorner() ) if( !aJoint || aJoint->IsLineCorner() )
return; return;
@ -1792,7 +1792,7 @@ void LINE_PLACER::simplifyNewLine( NODE* aNode, LINKED_ITEM* aLatest )
NODE::ITEM_VECTOR toRemove; NODE::ITEM_VECTOR toRemove;
for( ITEM* neighbor : aJoint->Links() ) for( ITEM* neighbor : aJoint->CLinks().CItems() )
{ {
if( neighbor == aItem if( neighbor == aItem
|| !neighbor->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) || !neighbor->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T )
@ -1801,18 +1801,18 @@ void LINE_PLACER::simplifyNewLine( NODE* aNode, LINKED_ITEM* aLatest )
continue; continue;
} }
if( static_cast<SEGMENT*>( neighbor )->Width() if( static_cast<const SEGMENT*>( neighbor )->Width()
!= static_cast<SEGMENT*>( aItem )->Width() ) != static_cast<const SEGMENT*>( aItem )->Width() )
{ {
continue; continue;
} }
const SEG& testSeg = static_cast<SEGMENT*>( neighbor )->Seg(); const SEG& testSeg = static_cast<const SEGMENT*>( neighbor )->Seg();
if( refSeg.Contains( testSeg ) ) if( refSeg.Contains( testSeg ) )
{ {
JOINT* nA = aNode->FindJoint( neighbor->Anchor( 0 ), neighbor ); const JOINT* nA = aNode->FindJoint( neighbor->Anchor( 0 ), neighbor );
JOINT* nB = aNode->FindJoint( neighbor->Anchor( 1 ), neighbor ); const JOINT* nB = aNode->FindJoint( neighbor->Anchor( 1 ), neighbor );
if( ( nA == aJoint && nB->LinkCount() == 1 ) || if( ( nA == aJoint && nB->LinkCount() == 1 ) ||
( nB == aJoint && nA->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 ) ) if( !item->OfKind( ITEM::SEGMENT_T ) || cleanup.count( item ) )
continue; continue;
JOINT* jA = aNode->FindJoint( item->Anchor( 0 ), item ); const JOINT* jA = aNode->FindJoint( item->Anchor( 0 ), item );
JOINT* jB = aNode->FindJoint( item->Anchor( 1 ), item ); const JOINT* jB = aNode->FindJoint( item->Anchor( 1 ), item );
processJoint( jA, item ); processJoint( jA, item );
processJoint( jB, 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. // 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 // 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. // 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; PNS::CONSTRAINT constraint;
Router()->GetRuleResolver()->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, itemToCheck, 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 // Extract the length of the pad to die for start and end pads
for( auto& link : start.LinkList() ) 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 there are overlapping pads, choose the first with a non-zero length
if( solid->GetPadToDie() > 0 ) if( solid->GetPadToDie() > 0 )
@ -321,7 +321,7 @@ int MEANDER_PLACER_BASE::GetTotalPadToDieLength( const LINE& aLine ) const
for( auto& link : end.LinkList() ) 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 ) if( solid->GetPadToDie() > 0 )
{ {

View File

@ -48,7 +48,7 @@
namespace PNS { namespace PNS {
#ifdef DEBUG #ifdef DEBUG
static std::unordered_set<NODE*> allocNodes; static std::unordered_set<const NODE*> allocNodes;
#endif #endif
NODE::NODE() NODE::NODE()
@ -784,13 +784,13 @@ 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 // 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 // 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. // via/solid and all its links and re-insert them.
JOINT::LINKED_ITEMS links( aJoint->LinkList() ); std::vector<ITEM*> links( aJoint->LinkList() );
JOINT::HASH_TAG tag; JOINT::HASH_TAG tag;
int net = aItem->Net(); int net = aItem->Net();
@ -831,7 +831,7 @@ void NODE::rebuildJoint( JOINT* aJoint, ITEM* aItem )
void NODE::removeViaIndex( VIA* aVia ) 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 ); assert( jt );
rebuildJoint( jt, aVia ); rebuildJoint( jt, aVia );
} }
@ -843,7 +843,7 @@ void NODE::removeSolidIndex( SOLID* aSolid )
return; return;
// fixme: redundant code // 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 ); assert( jt );
rebuildJoint( jt, aSolid ); rebuildJoint( jt, aSolid );
} }
@ -1123,7 +1123,7 @@ int NODE::FindLinesBetweenJoints( const JOINT& aA, const JOINT& aB, std::vector<
void NODE::FixupVirtualVias() void NODE::FixupVirtualVias()
{ {
SEGMENT* locked_seg = nullptr; const SEGMENT* locked_seg = nullptr;
std::vector<VVIA*> vvias; std::vector<VVIA*> vvias;
for( auto& jointPair : m_joints ) for( auto& jointPair : m_joints )
@ -1139,17 +1139,17 @@ void NODE::FixupVirtualVias()
bool is_width_change = false; bool is_width_change = false;
bool is_locked = 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++; n_vias++;
} }
else if( lnk.item->OfKind( ITEM::SOLID_T ) ) else if( item->OfKind( ITEM::SOLID_T ) )
{ {
n_solid++; 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(); 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; JOINT::HASH_TAG tag;
tag.net = aNet; tag.net = aNet;
tag.pos = aPos; 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() ) 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, SEGMENT* NODE::findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
int aNet ) int aNet )
{ {
JOINT* jtStart = FindJoint( A, lr.Start(), aNet ); const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
if( !jtStart ) if( !jtStart )
return nullptr; return nullptr;
@ -1559,7 +1559,7 @@ SEGMENT* NODE::findRedundantSegment( SEGMENT* aSeg )
ARC* NODE::findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr, ARC* NODE::findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
int aNet ) int aNet )
{ {
JOINT* jtStart = FindJoint( A, lr.Start(), aNet ); const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
if( !jtStart ) if( !jtStart )
return nullptr; return nullptr;

View File

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

View File

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

View File

@ -369,7 +369,7 @@ SHOVE::SHOVE_STATUS SHOVE::shoveLineToHullSet( const LINE& aCurLine, const LINE&
if(( aCurLine.Marker() & MK_HEAD ) && !colliding ) 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() ) for( ITEM* item : jtStart->LinkList() )
{ {
@ -664,7 +664,7 @@ SHOVE::SHOVE_STATUS SHOVE::onCollidingSolid( LINE& aCurrent, ITEM* aObstacle, OB
{ {
VIA vh = aCurrent.Via(); VIA vh = aCurrent.Via();
VIA* via = nullptr; VIA* via = nullptr;
JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), &aCurrent ); const JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), &aCurrent );
if( !jtStart ) if( !jtStart )
return SH_INCOMPLETE; return SH_INCOMPLETE;
@ -868,7 +868,7 @@ SHOVE::SHOVE_STATUS SHOVE::pushOrShoveVia( VIA* aVia, const VECTOR2I& aForce, in
{ {
LINE_PAIR_VEC draggedLines; LINE_PAIR_VEC draggedLines;
VECTOR2I p0( aVia->Pos() ); VECTOR2I p0( aVia->Pos() );
JOINT* jt = m_currentNode->FindJoint( p0, aVia ); const JOINT* jt = m_currentNode->FindJoint( p0, aVia );
VECTOR2I p0_pushed( p0 + aForce ); VECTOR2I p0_pushed( p0 + aForce );
PNS_DBG( Dbg(), Message, wxString::Format( wxT( "via force [%d %d]\n" ), aForce.x, aForce.y ) ); 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 // make sure pushed via does not overlap with any existing joint
while( true ) while( true )
{ {
JOINT* jt_next = m_currentNode->FindJoint( p0_pushed, aVia ); const JOINT* jt_next = m_currentNode->FindJoint( p0_pushed, aVia );
if( !jt_next ) if( !jt_next )
break; break;
@ -1070,7 +1070,7 @@ SHOVE::SHOVE_STATUS SHOVE::onReverseCollidingVia( LINE& aCurrent, VIA* aObstacle
LINE cur( aCurrent ); LINE cur( aCurrent );
cur.ClearLinks(); cur.ClearLinks();
JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia ); const JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia );
LINE shoved( aCurrent ); LINE shoved( aCurrent );
shoved.ClearLinks(); 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; 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 ) ) if( aItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
unwindLineStack( static_cast<LINKED_ITEM*>( aItem ) ); {
unwindLineStack( static_cast<const LINKED_ITEM*>( aItem ) );
}
else if( aItem->OfKind( ITEM::LINE_T ) ) 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 ); 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 // 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 ) ) if( obs.m_item->OfKind( ITEM::VIA_T ) )
{ {
VIA* v = static_cast<VIA*>( obs.m_item ); const VIA* v = static_cast<const VIA*>( obs.m_item );
int maxw = 0; int maxw = 0;
JOINT* jv = m_currentNode->FindJoint( v->Pos(), v ); 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 ); 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 ); 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 ) ) if( !obs.m_item->OfKind( ITEM::SEGMENT_T ) )
return false; 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 ); const JOINT* ja = m_currentNode->FindJoint( s->Seg().A, s );
JOINT* jb = m_currentNode->FindJoint( s->Seg().B, s ); const JOINT* jb = m_currentNode->FindJoint( s->Seg().B, s );
VIA* vias[] = { ja->Via(), jb->Via() }; 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 ) 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 ) if( !jt )
return nullptr; 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; m_springbackDoNotTouchNode = aNode;
} }

View File

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

View File

@ -59,9 +59,9 @@ 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; std::deque<const JOINT*> searchQueue;
JOINT_SET processed; JOINT_SET processed;
searchQueue.push_back( aStart ); searchQueue.push_back( aStart );
@ -69,16 +69,16 @@ const TOPOLOGY::JOINT_SET TOPOLOGY::ConnectedJoints( JOINT* aStart )
while( !searchQueue.empty() ) while( !searchQueue.empty() )
{ {
JOINT* current = searchQueue.front(); const JOINT* current = searchQueue.front();
searchQueue.pop_front(); searchQueue.pop_front();
for( ITEM* item : current->LinkList() ) 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 );; const JOINT* a = m_world->FindJoint( item->Anchor( 0 ), item );;
JOINT* b = m_world->FindJoint( item->Anchor( 1 ), item );; const JOINT* b = m_world->FindJoint( item->Anchor( 1 ), item );;
JOINT* next = ( *a == *current ) ? b : a; const JOINT* next = ( *a == *current ) ? b : a;
if( processed.find( next ) == processed.end() ) 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() ); std::unique_ptr<NODE> tmpNode( m_world->Branch() );
tmpNode->Add( track ); 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 ) if( !jt || jt->Net() <= 0 )
return false; 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; 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, 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() ); assert( aLine->IsLinked() );
VECTOR2I anchor = aLeft ? aLine->CPoint( 0 ) : aLine->CPoint( -1 ); VECTOR2I anchor = aLeft ? aLine->CPoint( 0 ) : aLine->CPoint( -1 );
LINKED_ITEM* last = aLeft ? aLine->Links().front() : aLine->Links().back(); 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 ); assert( jt != nullptr );
@ -212,7 +212,9 @@ bool TOPOLOGY::followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet,
ITEM* via = nullptr; ITEM* via = nullptr;
SEGMENT* next_seg = 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 ) ) if( link->OfKind( ITEM::VIA_T ) )
via = link; via = link;
@ -263,7 +265,7 @@ bool TOPOLOGY::followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet,
const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart, const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
std::pair<JOINT*, JOINT*>* aTerminalJoints, std::pair<const JOINT*, const JOINT*>* aTerminalJoints,
bool aFollowLockedSegments ) bool aFollowLockedSegments )
{ {
ITEM_SET path; ITEM_SET path;
@ -273,16 +275,18 @@ const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
if( aStart->Kind() == ITEM::VIA_T ) if( aStart->Kind() == ITEM::VIA_T )
{ {
VIA* via = static_cast<VIA*>( aStart ); VIA* via = static_cast<VIA*>( aStart );
JOINT* jt = m_world->FindJoint( via->Pos(), via ); const JOINT* jt = m_world->FindJoint( via->Pos(), via );
if( !jt->IsNonFanoutVia() ) if( !jt->IsNonFanoutVia() )
return ITEM_SET(); 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; break;
} }
} }
@ -301,8 +305,8 @@ const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
path.Add( l ); path.Add( l );
JOINT* jointA = nullptr; const JOINT* jointA = nullptr;
JOINT* jointB = nullptr; const JOINT* jointB = nullptr;
followTrivialPath( &l, false, path, visited, &jointB ); followTrivialPath( &l, false, path, visited, &jointB );
followTrivialPath( &l, true, path, visited, &jointA ); 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 ) 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 ); ITEM_SET initialPath = AssembleTrivialPath( aStart, &joints, true );
PAD* padA = nullptr; PAD* padA = nullptr;
PAD* padB = nullptr; PAD* padB = nullptr;
auto getPadFromJoint = auto getPadFromJoint =
[]( JOINT* aJoint, PAD** aTargetPad, SOLID** aTargetSolid ) []( const JOINT* aJoint, PAD** aTargetPad, SOLID** aTargetSolid )
{ {
for( ITEM* item : aJoint->LinkList() ) for( ITEM* item : aJoint->LinkList() )
{ {
@ -403,7 +407,7 @@ const ITEM_SET TOPOLOGY::AssembleTuningPath( ITEM* aStart, SOLID** aStartPad, SO
}; };
auto processPad = auto processPad =
[&]( JOINT* aJoint, PAD* aPad ) [&]( const JOINT* aJoint, PAD* aPad )
{ {
const std::shared_ptr<SHAPE_POLY_SET>& shape = aPad->GetEffectivePolygon(); 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(); 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 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 ); 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 class TOPOLOGY
{ {
public: public:
typedef std::set<JOINT*> JOINT_SET; typedef std::set<const JOINT*> JOINT_SET;
TOPOLOGY( NODE* aNode ): TOPOLOGY( NODE* aNode ):
m_world( aNode ) {}; m_world( aNode ) {};
@ -47,15 +47,15 @@ public:
~TOPOLOGY() {}; ~TOPOLOGY() {};
bool SimplifyLine( LINE *aLine ); bool SimplifyLine( LINE *aLine );
ITEM* NearestUnconnectedItem( JOINT* aStart, int* aAnchor = nullptr, ITEM* NearestUnconnectedItem( const JOINT* aStart, int* aAnchor = nullptr,
int aKindMask = ITEM::ANY_T ); int aKindMask = ITEM::ANY_T );
bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint,
LAYER_RANGE& aLayers ); LAYER_RANGE& aLayers );
bool LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine ); bool LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine );
const JOINT_SET ConnectedJoints( JOINT* aStart ); const JOINT_SET ConnectedJoints( const JOINT* aStart );
const ITEM_SET ConnectedItems( JOINT* aStart, int aKindMask = ITEM::ANY_T ); const ITEM_SET ConnectedItems( const JOINT* aStart, int aKindMask = ITEM::ANY_T );
const ITEM_SET ConnectedItems( ITEM* aStart, int aKindMask = ITEM::ANY_T ); const ITEM_SET ConnectedItems( ITEM* aStart, int aKindMask = ITEM::ANY_T );
int64_t ShortestConnectionLength( ITEM* aFrom, ITEM* aTo ); int64_t ShortestConnectionLength( ITEM* aFrom, ITEM* aTo );
@ -68,7 +68,7 @@ public:
* @return a set of items in the path. * @return a set of items in the path.
*/ */
const ITEM_SET AssembleTrivialPath( ITEM* aStart, const ITEM_SET AssembleTrivialPath( ITEM* aStart,
std::pair<JOINT*, JOINT*>* aTerminalJoints = nullptr, std::pair<const JOINT*, const JOINT*>* aTerminalJoints = nullptr,
bool aFollowLockedSegments = false ); bool aFollowLockedSegments = false );
/** /**
@ -96,7 +96,7 @@ private:
const int DP_PARALLELITY_THRESHOLD = 5; const int DP_PARALLELITY_THRESHOLD = 5;
bool followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet, std::set<ITEM*>& aVisited, bool followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet, std::set<ITEM*>& aVisited,
JOINT** aTerminalJoint = nullptr ); const JOINT** aTerminalJoint = nullptr );
NODE *m_world; NODE *m_world;
}; };