Connectivity: local ratsnest for both legacy & GAL. Further removal of legacy code
This commit is contained in:
parent
07b7600ae5
commit
c4c329e393
|
@ -62,3 +62,12 @@ demos/**/_autosave-*
|
|||
.*.swp
|
||||
*~
|
||||
.DS_Store
|
||||
*.png
|
||||
*.kiface
|
||||
*.o
|
||||
*.a
|
||||
*.cmake
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.old
|
|
@ -37,8 +37,7 @@
|
|||
#include <connectivity.h>
|
||||
|
||||
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) :
|
||||
BOARD_ITEM( aParent, idtype ), m_netinfo( &NETINFO_LIST::ORPHANED_ITEM ),
|
||||
m_Subnet( 0 ), m_ZoneSubnet( 0 )
|
||||
BOARD_ITEM( aParent, idtype ), m_netinfo( &NETINFO_LIST::ORPHANED_ITEM )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -116,34 +116,6 @@ public:
|
|||
*/
|
||||
bool SetNetCode( int aNetCode, bool aNoAssert=false );
|
||||
|
||||
/**
|
||||
* Function GetSubNet
|
||||
* @return int - the sub net code.
|
||||
*/
|
||||
int GetSubNet() const
|
||||
{
|
||||
return m_Subnet;
|
||||
}
|
||||
|
||||
void SetSubNet( int aSubNetCode )
|
||||
{
|
||||
m_Subnet = aSubNetCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetZoneSubNet
|
||||
* @return int - the sub net code in zone connections.
|
||||
*/
|
||||
int GetZoneSubNet() const
|
||||
{
|
||||
return m_ZoneSubnet;
|
||||
}
|
||||
|
||||
void SetZoneSubNet( int aSubNetCode )
|
||||
{
|
||||
m_ZoneSubnet = aSubNetCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetNetname
|
||||
* @return wxString - the full netname
|
||||
|
@ -189,17 +161,23 @@ public:
|
|||
*/
|
||||
wxString GetNetClassName() const;
|
||||
|
||||
void SetLocalRatsnestVisible( bool aVisible )
|
||||
{
|
||||
m_localRatsnestVisible = aVisible;
|
||||
}
|
||||
|
||||
bool GetLocalRatsnestVisible() const
|
||||
{
|
||||
return m_localRatsnestVisible;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Stores all informations about the net that item belongs to
|
||||
NETINFO_ITEM* m_netinfo;
|
||||
|
||||
private:
|
||||
int m_Subnet; /* In rastnest routines : for the current net, block number
|
||||
* (number common to the current connected items found)
|
||||
*/
|
||||
|
||||
int m_ZoneSubnet; // used in rastnest computations : for the current net,
|
||||
// handle cluster number in zone connection
|
||||
bool m_localRatsnestVisible;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -658,13 +658,6 @@ void D_PAD::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM>& aList )
|
|||
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Net" ), GetNetname(), DARKCYAN ) );
|
||||
|
||||
/* For test and debug only: display m_physical_connexion and
|
||||
* m_logical_connexion */
|
||||
#if 1 // Used only to debug connectivity calculations
|
||||
Line.Printf( wxT( "%d-%d-%d " ), GetSubRatsnest(), GetSubNet(), GetZoneSubNet() );
|
||||
aList.push_back( MSG_PANEL_ITEM( wxT( "L-P-Z" ), Line, DARKGREEN ) );
|
||||
#endif
|
||||
|
||||
board = GetBoard();
|
||||
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Layer" ),
|
||||
|
|
|
@ -1094,7 +1094,7 @@ void TRACK::GetMsgPanelInfoBase_Common( std::vector< MSG_PANEL_ITEM >& aList )
|
|||
aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );
|
||||
|
||||
// Display net code : (useful in test or debug)
|
||||
msg.Printf( wxT( "%d.%d" ), GetNetCode(), GetSubNet() );
|
||||
msg.Printf( wxT( "%d" ), GetNetCode() );
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -95,72 +95,4 @@ static void RebuildTrackChain( BOARD* pcb )
|
|||
|
||||
void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode )
|
||||
{
|
||||
#if 0
|
||||
// Skip dummy net -1, and "not connected" net 0 (grouping all not connected pads)
|
||||
if( aNetCode <= 0 )
|
||||
return;
|
||||
|
||||
if( (m_Pcb->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 )
|
||||
Compile_Ratsnest( aDC, true );
|
||||
|
||||
// Clear the cluster identifier (subnet) of pads for this net
|
||||
// Pads are grouped by netcode (and in netname alphabetic order)
|
||||
for( unsigned i = 0; i < m_Pcb->GetPadCount(); ++i )
|
||||
{
|
||||
D_PAD* pad = m_Pcb->GetPad(i);
|
||||
|
||||
if( m_Pcb->GetPad(i)->GetNetCode() == aNetCode )
|
||||
pad->SetSubNet( 0 );
|
||||
}
|
||||
|
||||
m_Pcb->Test_Connections_To_Copper_Areas( aNetCode );
|
||||
|
||||
// Search for the first and the last segment relative to the given net code
|
||||
if( m_Pcb->m_Track )
|
||||
{
|
||||
CONNECTIONS connections( m_Pcb );
|
||||
|
||||
TRACK* lastTrack = NULL;
|
||||
TRACK* firstTrack = m_Pcb->m_Track.GetFirst()->GetStartNetCode( aNetCode );
|
||||
|
||||
if( firstTrack )
|
||||
lastTrack = firstTrack->GetEndNetCode( aNetCode );
|
||||
|
||||
if( firstTrack && lastTrack ) // i.e. if there are segments
|
||||
{
|
||||
connections.Build_CurrNet_SubNets_Connections( firstTrack, lastTrack, aNetCode );
|
||||
}
|
||||
}
|
||||
|
||||
Merge_SubNets_Connected_By_CopperAreas( m_Pcb, aNetCode );
|
||||
|
||||
// rebuild the active ratsnest for this net
|
||||
DrawGeneralRatsnest( aDC, aNetCode );
|
||||
TestForActiveLinksInRatsnest( aNetCode );
|
||||
DrawGeneralRatsnest( aDC, aNetCode );
|
||||
|
||||
// Display results
|
||||
wxString msg;
|
||||
int net_notconnected_count = 0;
|
||||
NETINFO_ITEM* net = m_Pcb->FindNet( aNetCode );
|
||||
|
||||
if( net ) // Should not occur, but ...
|
||||
{
|
||||
for( unsigned ii = net->m_RatsnestStartIdx; ii < net->m_RatsnestEndIdx; ii++ )
|
||||
{
|
||||
if( m_Pcb->m_FullRatsnest[ii].IsActive() )
|
||||
net_notconnected_count++;
|
||||
}
|
||||
|
||||
msg.Printf( wxT( "links %d nc %d net %d: not conn %d" ),
|
||||
m_Pcb->GetRatsnestsCount(), m_Pcb->GetUnconnectedNetCount(), aNetCode,
|
||||
net_notconnected_count );
|
||||
}
|
||||
else
|
||||
msg.Printf( wxT( "net not found: netcode %d" ), aNetCode );
|
||||
|
||||
SetStatusText( msg );
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -285,6 +285,8 @@ const std::vector<RN_DYNAMIC_LINE>& CONNECTIVITY_DATA::GetDynamicRatsnest() cons
|
|||
|
||||
void CONNECTIVITY_DATA::ClearDynamicRatsnest()
|
||||
{
|
||||
m_connAlgo->ForEachAnchor( [] (CN_ANCHOR_PTR anchor ) { anchor->SetNoLine( false ); } );
|
||||
|
||||
m_dynamicConnectivity.reset();
|
||||
m_dynamicRatsnest.clear();
|
||||
}
|
||||
|
|
|
@ -480,7 +480,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
|
|||
auto zoneItem = static_cast<CN_ZONE *> (item);
|
||||
auto searchZones = std::bind( checkForConnection, _1, zoneItem );
|
||||
|
||||
if( zoneItem->Dirty() )
|
||||
if( zoneItem->Dirty() || m_padList.IsDirty() || m_trackList.IsDirty() || m_viaList.IsDirty() )
|
||||
{
|
||||
totalDirtyCount++;
|
||||
m_viaList.FindNearby( zoneItem->BBox(), searchZones );
|
||||
|
@ -901,3 +901,15 @@ void CN_CONNECTIVITY_ALGO::Clear()
|
|||
m_zoneList.Clear();
|
||||
|
||||
}
|
||||
|
||||
void CN_CONNECTIVITY_ALGO::ForEachAnchor( std::function<void(CN_ANCHOR_PTR)> aFunc )
|
||||
{
|
||||
for ( auto anchor : m_padList.Anchors() )
|
||||
aFunc( anchor );
|
||||
for ( auto anchor : m_viaList.Anchors() )
|
||||
aFunc( anchor );
|
||||
for ( auto anchor : m_trackList.Anchors() )
|
||||
aFunc( anchor );
|
||||
for ( auto anchor : m_zoneList.Anchors() )
|
||||
aFunc( anchor );
|
||||
}
|
||||
|
|
|
@ -504,6 +504,8 @@ public:
|
|||
ITER begin() { return m_items.begin(); };
|
||||
ITER end() { return m_items.end(); };
|
||||
|
||||
std::vector<CN_ANCHOR_PTR>& Anchors() { return m_anchors; }
|
||||
|
||||
template <class T>
|
||||
void FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirtyOnly = false );
|
||||
|
||||
|
@ -940,6 +942,8 @@ public:
|
|||
|
||||
const CLUSTERS& GetClusters();
|
||||
int GetUnconnectedCount();
|
||||
|
||||
void ForEachAnchor( std::function<void(CN_ANCHOR_PTR)> aFunc );
|
||||
};
|
||||
|
||||
bool operator<( const CN_ANCHOR_PTR a, const CN_ANCHOR_PTR b );
|
||||
|
|
|
@ -296,7 +296,6 @@ void PCB_EDIT_FRAME::Change_Side_Module( MODULE* Module, wxDC* DC )
|
|||
|
||||
if( !Module->IsMoving() ) /* This is a simple flip, no other edition in progress */
|
||||
{
|
||||
GetBoard()->m_Status_Pcb &= ~( LISTE_RATSNEST_ITEM_OK | CONNEXION_OK );
|
||||
|
||||
if( DC )
|
||||
{
|
||||
|
|
|
@ -97,7 +97,7 @@ void PCB_BASE_FRAME::DrawGeneralRatsnest( wxDC* aDC, int aNetcode )
|
|||
|
||||
auto connectivity = m_Pcb->GetConnectivity();
|
||||
|
||||
COLOR4D color = g_ColorsSettings.GetItemColor(LAYER_RATSNEST);
|
||||
COLOR4D color = g_ColorsSettings.GetItemColor( LAYER_RATSNEST );
|
||||
|
||||
for( int i = 1; i < connectivity->GetNetCount(); ++i )
|
||||
{
|
||||
|
@ -105,22 +105,23 @@ void PCB_BASE_FRAME::DrawGeneralRatsnest( wxDC* aDC, int aNetcode )
|
|||
|
||||
if( ( aNetcode <= 0 ) || ( aNetcode == i ) )
|
||||
{
|
||||
for ( const auto& edge : net->GetEdges() )
|
||||
{
|
||||
if ( edge.IsVisible() )
|
||||
for( const auto& edge : net->GetEdges() )
|
||||
{
|
||||
auto s = edge.GetSourcePos();
|
||||
auto d = edge.GetTargetPos();
|
||||
auto sn = edge.GetSourceNode();
|
||||
auto dn = edge.GetTargetNode();
|
||||
|
||||
if ( !sn->GetNoLine() && !dn->GetNoLine() )
|
||||
GRLine( m_canvas->GetClipBox(), aDC, wxPoint(s.x, s.y), wxPoint(d.x, d.y), 0, color );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool enable = !sn->GetNoLine() && !dn->GetNoLine();
|
||||
bool show = sn->Parent()->GetLocalRatsnestVisible()
|
||||
|| dn->Parent()->GetLocalRatsnestVisible();
|
||||
|
||||
if( enable && show )
|
||||
GRLine( m_canvas->GetClipBox(), aDC, wxPoint( s.x, s.y ), wxPoint( d.x,
|
||||
d.y ), 0, color );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,7 +134,8 @@ void PCB_BASE_FRAME::TraceModuleRatsNest( wxDC* DC )
|
|||
|
||||
for( const auto& l : GetBoard()->GetConnectivity()->GetDynamicRatsnest() )
|
||||
{
|
||||
GRLine( m_canvas->GetClipBox(), DC, wxPoint(l.a.x, l.a.y), wxPoint(l.b.x, l.b.y), 0, tmpcolor );
|
||||
GRLine( m_canvas->GetClipBox(), DC, wxPoint( l.a.x, l.a.y ), wxPoint( l.b.x,
|
||||
l.b.y ), 0, tmpcolor );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +155,7 @@ void PCB_BASE_FRAME::TraceModuleRatsNest( wxDC* DC )
|
|||
* drawn
|
||||
*/
|
||||
|
||||
static wxPoint s_CursorPos; // Coordinate of the moving point (mouse cursor and
|
||||
static wxPoint s_CursorPos; // Coordinate of the moving point (mouse cursor and
|
||||
// end of current track segment)
|
||||
|
||||
/* Function BuildAirWiresTargetsList
|
||||
|
@ -163,7 +165,7 @@ void PCB_BASE_FRAME::TraceModuleRatsNest( wxDC* DC )
|
|||
* from the current new track to candidates during track creation
|
||||
*/
|
||||
|
||||
static BOARD_CONNECTED_ITEM *s_ref = nullptr;
|
||||
static BOARD_CONNECTED_ITEM* s_ref = nullptr;
|
||||
static int s_refNet = -1;
|
||||
|
||||
void PCB_BASE_FRAME::BuildAirWiresTargetsList( BOARD_CONNECTED_ITEM* aItemRef,
|
||||
|
@ -175,25 +177,24 @@ void PCB_BASE_FRAME::BuildAirWiresTargetsList( BOARD_CONNECTED_ITEM* aItemRef,
|
|||
}
|
||||
|
||||
|
||||
static MODULE movedModule( nullptr );
|
||||
|
||||
|
||||
static MODULE movedModule(nullptr);
|
||||
|
||||
void PCB_BASE_FRAME::build_ratsnest_module( MODULE *mod, wxPoint aMoveVector )
|
||||
void PCB_BASE_FRAME::build_ratsnest_module( MODULE* mod, wxPoint aMoveVector )
|
||||
{
|
||||
auto connectivity = GetBoard()->GetConnectivity();
|
||||
|
||||
movedModule = *mod;
|
||||
movedModule.Move( -aMoveVector );
|
||||
connectivity->ClearDynamicRatsnest();
|
||||
connectivity->BlockRatsnestItems( {mod} );
|
||||
connectivity->ComputeDynamicRatsnest( {&movedModule} );
|
||||
connectivity->BlockRatsnestItems( { mod } );
|
||||
connectivity->ComputeDynamicRatsnest( { &movedModule } );
|
||||
}
|
||||
|
||||
|
||||
void PCB_BASE_FRAME::TraceAirWiresToTargets( wxDC* aDC )
|
||||
{
|
||||
auto connectivity = GetBoard()->GetConnectivity();
|
||||
DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)GetDisplayOptions();
|
||||
DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*) GetDisplayOptions();
|
||||
|
||||
auto targets = connectivity->NearestUnconnectedTargets( s_ref, s_CursorPos, s_refNet );
|
||||
|
||||
|
@ -202,14 +203,14 @@ void PCB_BASE_FRAME::TraceAirWiresToTargets( wxDC* aDC )
|
|||
|
||||
GRSetDrawMode( aDC, GR_XOR );
|
||||
|
||||
for (int i = 0; i < std::min( (int)displ_opts->m_MaxLinksShowed, (int)targets.size() ); i++)
|
||||
for( int i = 0; i < std::min( (int) displ_opts->m_MaxLinksShowed, (int) targets.size() ); i++ )
|
||||
{
|
||||
auto p = targets[i];
|
||||
GRLine( m_canvas->GetClipBox(), aDC, s_CursorPos, wxPoint(p.x, p.y), 0, YELLOW );
|
||||
GRLine( m_canvas->GetClipBox(), aDC, s_CursorPos, wxPoint( p.x, p.y ), 0, YELLOW );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Redraw in XOR mode the outlines of the module.
|
||||
void MODULE::DrawOutlinesWhenMoving( EDA_DRAW_PANEL* panel, wxDC* DC,
|
||||
const wxPoint& aMoveVector )
|
||||
|
@ -218,7 +219,7 @@ void MODULE::DrawOutlinesWhenMoving( EDA_DRAW_PANEL* panel, wxDC* DC,
|
|||
D_PAD* pt_pad;
|
||||
|
||||
DrawEdgesOnly( panel, DC, aMoveVector, GR_XOR );
|
||||
DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
|
||||
DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*) panel->GetDisplayOptions();
|
||||
|
||||
// Show pads in sketch mode to speedu up drawings
|
||||
pad_fill_tmp = displ_opts->m_DisplayPadFill;
|
||||
|
@ -239,101 +240,18 @@ void MODULE::DrawOutlinesWhenMoving( EDA_DRAW_PANEL* panel, wxDC* DC,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::Show_1_Ratsnest( EDA_ITEM* item, wxDC* DC )
|
||||
{
|
||||
if( GetBoard()->IsElementVisible(RATSNEST_VISIBLE) )
|
||||
return;
|
||||
|
||||
Compile_Ratsnest( DC, true );
|
||||
|
||||
printf("show1r: %p\n", item);
|
||||
|
||||
auto connectivity = GetBoard()->GetConnectivity();
|
||||
|
||||
|
||||
// FIXME
|
||||
|
||||
#if 0
|
||||
if( item )
|
||||
if( item->Type() == PCB_MODULE_T )
|
||||
{
|
||||
if( item->Type() == PCB_PAD_T )
|
||||
auto mod = static_cast<MODULE*> (item);
|
||||
|
||||
for( auto pad : mod->PadsIter() )
|
||||
{
|
||||
pt_pad = (D_PAD*) item;
|
||||
Module = pt_pad->GetParent();
|
||||
pad->SetLocalRatsnestVisible( true );
|
||||
}
|
||||
|
||||
if( pt_pad ) // Displaying the ratsnest of the corresponding net.
|
||||
{
|
||||
SetMsgPanel( pt_pad );
|
||||
|
||||
for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
|
||||
{
|
||||
RATSNEST_ITEM* net = &GetBoard()->m_FullRatsnest[ii];
|
||||
|
||||
if( net->GetNet() == pt_pad->GetNetCode() )
|
||||
{
|
||||
if( ( net->m_Status & CH_VISIBLE ) != 0 )
|
||||
continue;
|
||||
|
||||
net->m_Status |= CH_VISIBLE;
|
||||
|
||||
if( ( net->m_Status & CH_ACTIF ) == 0 )
|
||||
continue;
|
||||
|
||||
net->Draw( m_canvas, DC, GR_XOR, wxPoint( 0, 0 ) );
|
||||
m_canvas->Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( item->Type() == PCB_MODULE_TEXT_T )
|
||||
{
|
||||
if( item->GetParent() && ( item->GetParent()->Type() == PCB_MODULE_T ) )
|
||||
Module = static_cast<MODULE*>( item->GetParent() );
|
||||
}
|
||||
else if( item->Type() == PCB_MODULE_T )
|
||||
{
|
||||
Module = static_cast<MODULE*>( item );
|
||||
}
|
||||
|
||||
if( Module )
|
||||
{
|
||||
SetMsgPanel( Module );
|
||||
pt_pad = Module->Pads();
|
||||
|
||||
for( ; pt_pad != NULL; pt_pad = pt_pad->Next() )
|
||||
{
|
||||
for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
|
||||
{
|
||||
RATSNEST_ITEM* net = &GetBoard()->m_FullRatsnest[ii];
|
||||
|
||||
if( ( net->m_PadStart == pt_pad ) || ( net->m_PadEnd == pt_pad ) )
|
||||
{
|
||||
if( net->m_Status & CH_VISIBLE )
|
||||
continue;
|
||||
|
||||
net->m_Status |= CH_VISIBLE;
|
||||
|
||||
if( (net->m_Status & CH_ACTIF) == 0 )
|
||||
continue;
|
||||
|
||||
net->Draw( m_canvas, DC, GR_XOR, wxPoint( 0, 0 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pt_pad = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Erase if no pad or module has been selected.
|
||||
if( ( pt_pad == NULL ) && ( Module == NULL ) )
|
||||
{
|
||||
DrawGeneralRatsnest( DC );
|
||||
|
||||
for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
|
||||
GetBoard()->m_FullRatsnest[ii].m_Status &= ~CH_VISIBLE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -55,16 +55,9 @@ const BOX2I RATSNEST_VIEWITEM::ViewBBox() const
|
|||
return bbox;
|
||||
}
|
||||
|
||||
#include <geometry/seg.h>
|
||||
std::vector<SEG> delEdges;
|
||||
|
||||
void clearDEdges() { delEdges.clear(); }
|
||||
void addDEdge ( SEG edge ) { delEdges.push_back(edge); }
|
||||
|
||||
|
||||
void RATSNEST_VIEWITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
|
||||
{
|
||||
static const double crossSize = 100000.0;
|
||||
constexpr int CROSS_SIZE = 200000;
|
||||
|
||||
auto gal = aView->GetGAL();
|
||||
gal->SetIsStroke( true );
|
||||
|
@ -76,23 +69,19 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
|
|||
int highlightedNet = rs->GetHighlightNetCode();
|
||||
|
||||
gal->SetStrokeColor( color.Brightened( 0.8 ) );
|
||||
for (auto s : delEdges)
|
||||
gal->DrawLine( s.A, s.B );
|
||||
|
||||
|
||||
// Draw the "dynamic" ratsnest (i.e. for objects that may be currently being moved)
|
||||
for( const auto& l : m_data->GetDynamicRatsnest() )
|
||||
{
|
||||
if ( l.a == l.b )
|
||||
{
|
||||
gal->DrawLine( VECTOR2I( l.a.x - crossSize, l.a.y - crossSize ), VECTOR2I( l.b.x + crossSize, l.b.y + crossSize ) );
|
||||
gal->DrawLine( VECTOR2I( l.a.x - crossSize, l.a.y + crossSize ), VECTOR2I( l.b.x + crossSize, l.b.y - crossSize ) );
|
||||
gal->DrawLine( VECTOR2I( l.a.x - CROSS_SIZE, l.a.y - CROSS_SIZE ), VECTOR2I( l.b.x + CROSS_SIZE, l.b.y + CROSS_SIZE ) );
|
||||
gal->DrawLine( VECTOR2I( l.a.x - CROSS_SIZE, l.a.y + CROSS_SIZE ), VECTOR2I( l.b.x + CROSS_SIZE, l.b.y - CROSS_SIZE ) );
|
||||
} else {
|
||||
gal->DrawLine( l.a, l.b );
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic ratsnest (for e.g. dragged items)
|
||||
for( int i = 1; i < m_data->GetNetCount(); ++i )
|
||||
{
|
||||
RN_NET* net = m_data->GetRatsnestForNet( i );
|
||||
|
@ -103,20 +92,21 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
|
|||
|
||||
for( const auto& edge : net->GetUnconnected() )
|
||||
{
|
||||
if ( !edge.IsVisible() )
|
||||
continue;
|
||||
//if ( !edge.IsVisible() )
|
||||
// continue;
|
||||
|
||||
const auto& sourceNode = edge.GetSourceNode();
|
||||
const auto& targetNode = edge.GetTargetNode();
|
||||
const VECTOR2I source( sourceNode->Pos() );
|
||||
const VECTOR2I target( targetNode->Pos() );
|
||||
|
||||
if ( !sourceNode->GetNoLine() && !targetNode->GetNoLine() )
|
||||
bool enable = !sourceNode->GetNoLine() && !targetNode->GetNoLine();
|
||||
bool show = sourceNode->Parent()->GetLocalRatsnestVisible() || targetNode->Parent()->GetLocalRatsnestVisible();
|
||||
|
||||
if ( enable && show )
|
||||
{
|
||||
if ( source == target )
|
||||
{
|
||||
constexpr int CROSS_SIZE = 200000;
|
||||
|
||||
gal->DrawLine( VECTOR2I( source.x - CROSS_SIZE, source.y - CROSS_SIZE ), VECTOR2I( source.x + CROSS_SIZE, source.y + CROSS_SIZE ) );
|
||||
gal->DrawLine( VECTOR2I( source.x - CROSS_SIZE, source.y + CROSS_SIZE ), VECTOR2I( source.x + CROSS_SIZE, source.y - CROSS_SIZE ) );
|
||||
}
|
||||
|
|
|
@ -588,11 +588,6 @@ TOOL_ACTION COMMON_ACTIONS::toBeDone( "pcbnew.Control.toBeDone",
|
|||
AS_GLOBAL, 0, // dialog saying it is not implemented yet
|
||||
"", "" ); // so users are aware of that
|
||||
|
||||
TOOL_ACTION COMMON_ACTIONS::showLocalRatsnest( "pcbnew.Control.showLocalRatsnest",
|
||||
AS_GLOBAL, 0,
|
||||
"", "" );
|
||||
|
||||
|
||||
TOOL_ACTION COMMON_ACTIONS::routerActivateSingle( "pcbnew.InteractiveRouter.SingleTrack",
|
||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_NEW_TRACK ),
|
||||
_( "Interactive Router (Single Tracks)" ),
|
||||
|
|
|
@ -162,7 +162,7 @@ boost::optional<TOOL_EVENT> PCB_ACTIONS::TranslateLegacyId( int aId )
|
|||
return PCB_ACTIONS::appendBoard.MakeEvent();
|
||||
|
||||
case ID_PCB_SHOW_1_RATSNEST_BUTT:
|
||||
return PCB_ACTIONS::toBeDone.MakeEvent();
|
||||
return PCB_ACTIONS::showLocalRatsnest.MakeEvent();
|
||||
|
||||
case ID_PCB_MUWAVE_TOOL_GAP_CMD:
|
||||
return PCB_ACTIONS::microwaveCreateGap.MakeEvent();
|
||||
|
|
|
@ -148,6 +148,10 @@ TOOL_ACTION PCB_ACTIONS::highlightNetCursor( "pcbnew.EditorControl.highlightNetC
|
|||
AS_GLOBAL, 0,
|
||||
"", "" );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::showLocalRatsnest( "pcbnew.Control.showLocalRatsnest",
|
||||
AS_GLOBAL, 0,
|
||||
"", "" );
|
||||
|
||||
|
||||
class ZONE_CONTEXT_MENU : public CONTEXT_MENU
|
||||
{
|
||||
|
@ -1058,25 +1062,45 @@ int PCB_EDITOR_CONTROL::HighlightNetCursor( const TOOL_EVENT& aEvent )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool showLocalRatsnest( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame,
|
||||
KIGFX::ORIGIN_VIEWITEM* aItem, const VECTOR2D& aPosition )
|
||||
static bool showLocalRatsnest( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
|
||||
{
|
||||
aFrame->SetAuxOrigin( wxPoint( aPosition.x, aPosition.y ) );
|
||||
aItem->SetPosition( aPosition );
|
||||
aView->MarkDirty();
|
||||
auto selectionTool = aToolMgr->GetTool<SELECTION_TOOL>();
|
||||
|
||||
aToolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
aToolMgr->RunAction( PCB_ACTIONS::selectionCursor, true );
|
||||
|
||||
const SELECTION& selection = selectionTool->GetSelection();
|
||||
|
||||
if( selection.Empty() )
|
||||
return true;
|
||||
|
||||
for ( auto item : selection )
|
||||
{
|
||||
if ( item->Type() == PCB_MODULE_T )
|
||||
{
|
||||
for ( auto pad : static_cast<MODULE *> (item)->PadsIter() )
|
||||
{
|
||||
pad->SetLocalRatsnestVisible( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int PCB_EDITOR_CONTROL::ShowLocalRatsnest( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
printf("ShowLocalRTool!\n");
|
||||
|
||||
Activate();
|
||||
|
||||
|
||||
|
||||
auto picker = m_toolMgr->GetTool<PICKER_TOOL>();
|
||||
assert( picker );
|
||||
|
||||
m_frame->SetToolID( ID_PCB_SHOW_1_RATSNEST_BUTT, wxCURSOR_PENCIL, _( "Pick Components for Local Ratsnest" ) );
|
||||
//picker->SetClickHandler( std::bind( showLocalRatsnest, m_toolMgr, _1 ) );
|
||||
picker->SetClickHandler( std::bind( showLocalRatsnest, m_toolMgr, _1 ) );
|
||||
picker->SetSnapping( false );
|
||||
picker->Activate();
|
||||
Wait();
|
||||
|
@ -1086,7 +1110,7 @@ int PCB_EDITOR_CONTROL::ShowLocalRatsnest( const TOOL_EVENT& aEvent )
|
|||
|
||||
int PCB_EDITOR_CONTROL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
/* SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const SELECTION& selection = selTool->GetSelection();
|
||||
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
|
||||
|
||||
|
@ -1099,7 +1123,7 @@ int PCB_EDITOR_CONTROL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent )
|
|||
ratsnest->AddSimple( static_cast<BOARD_ITEM*>( item ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -1132,6 +1156,7 @@ void PCB_EDITOR_CONTROL::SetTransitions()
|
|||
Go( &PCB_EDITOR_CONTROL::DrillOrigin, PCB_ACTIONS::drillOrigin.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::HighlightNet, PCB_ACTIONS::highlightNet.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::HighlightNetCursor, PCB_ACTIONS::highlightNetCursor.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::ShowLocalRatsnest, PCB_ACTIONS::showLocalRatsnest.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::UpdateSelectionRatsnest, PCB_ACTIONS::selectionModified.MakeEvent() );
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include <protos.h>
|
||||
#include <zones_functions_for_undo_redo.h>
|
||||
#include <drc_stuff.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
// Outline creation:
|
||||
static void Abort_Zone_Create_Outline( EDA_DRAW_PANEL* Panel, wxDC* DC );
|
||||
|
@ -951,12 +951,12 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* aZone )
|
|||
if( zone->IsFilled() )
|
||||
{
|
||||
Fill_Zone( zone );
|
||||
GetBoard()->GetRatsnest()->Recalculate( zone->GetNetCode() );
|
||||
}
|
||||
}
|
||||
|
||||
commit.Stage( s_PickedList );
|
||||
commit.Push( _( "Modify zone properties" ) );
|
||||
GetBoard()->GetConnectivity()->RecalculateRatsnest();
|
||||
|
||||
s_PickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items
|
||||
}
|
||||
|
|
|
@ -1,409 +0,0 @@
|
|||
/**
|
||||
* @file zones_polygons_test_connections.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <algorithm> // sort
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <common.h>
|
||||
#include <macros.h>
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_track.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
#include <pcbnew.h>
|
||||
#include <zones.h>
|
||||
#include <polygon_test_point_inside.h>
|
||||
|
||||
static bool CmpZoneSubnetValue( const BOARD_CONNECTED_ITEM* a, const BOARD_CONNECTED_ITEM* b );
|
||||
|
||||
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
|
||||
|
||||
// This helper function sort a list of zones by netcode,
|
||||
// and for a given netcode by zone size
|
||||
// zone size = size of the m_FilledPolysList buffer
|
||||
bool sort_areas( const ZONE_CONTAINER* ref, const ZONE_CONTAINER* tst )
|
||||
{
|
||||
if( ref->GetNetCode() == tst->GetNetCode() )
|
||||
return ref->GetFilledPolysList().TotalVertices() <
|
||||
tst->GetFilledPolysList().TotalVertices();
|
||||
else
|
||||
return ref->GetNetCode() < tst->GetNetCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function Test_Connection_To_Copper_Areas
|
||||
* init .m_ZoneSubnet parameter in tracks and pads according to the connections to areas found
|
||||
* @param aNetcode = netcode to analyse. if -1, analyse all nets
|
||||
*/
|
||||
void BOARD::Test_Connections_To_Copper_Areas( int aNetcode )
|
||||
{
|
||||
// list of pads and tracks candidates on this layer and on this net.
|
||||
// It is static to avoid multiple memory realloc.
|
||||
static std::vector <BOARD_CONNECTED_ITEM*> candidates;
|
||||
|
||||
// clear .m_ZoneSubnet parameter for pads
|
||||
for( MODULE* module = m_Modules; module; module = module->Next() )
|
||||
{
|
||||
for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
|
||||
if( aNetcode < 0 || aNetcode == pad->GetNetCode() )
|
||||
pad->SetZoneSubNet( 0 );
|
||||
}
|
||||
|
||||
// clear .m_ZoneSubnet parameter for tracks and vias
|
||||
for( TRACK* track = m_Track; track; track = track->Next() )
|
||||
{
|
||||
if( aNetcode < 0 || aNetcode == track->GetNetCode() )
|
||||
track->SetZoneSubNet( 0 );
|
||||
}
|
||||
|
||||
// examine all zones, net by net:
|
||||
int subnet = 0;
|
||||
|
||||
// Build zones candidates list
|
||||
std::vector<ZONE_CONTAINER*> zones_candidates;
|
||||
|
||||
zones_candidates.reserve( GetAreaCount() );
|
||||
|
||||
for( int index = 0; index < GetAreaCount(); index++ )
|
||||
{
|
||||
ZONE_CONTAINER* zone = GetArea( index );
|
||||
|
||||
if( !zone->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
if( aNetcode >= 0 && aNetcode != zone->GetNetCode() )
|
||||
continue;
|
||||
|
||||
if( zone->GetFilledPolysList().IsEmpty() )
|
||||
continue;
|
||||
|
||||
zones_candidates.push_back( zone );
|
||||
}
|
||||
|
||||
// sort them by netcode then vertices count.
|
||||
// For a given net, examine the smaller zones first slightly speed up calculation
|
||||
// (25% faster)
|
||||
// this is only noticeable with very large boards and depends on board zones topology
|
||||
// This is due to the fact some items are connected by small zones ares,
|
||||
// before examining large zones areas and these items are not tested after a connection is found
|
||||
sort( zones_candidates.begin(), zones_candidates.end(), sort_areas );
|
||||
|
||||
int oldnetcode = -1;
|
||||
for( unsigned idx = 0; idx < zones_candidates.size(); idx++ )
|
||||
{
|
||||
ZONE_CONTAINER* zone = zones_candidates[idx];
|
||||
|
||||
int netcode = zone->GetNetCode();
|
||||
|
||||
// Build a list of candidates connected to the net:
|
||||
// At this point, layers are not considered, because areas on different layers can
|
||||
// be connected by a via or a pad.
|
||||
// (because zones are sorted by netcode, there is made only once per net)
|
||||
NETINFO_ITEM* net = FindNet( netcode );
|
||||
|
||||
wxASSERT( net );
|
||||
if( net == NULL )
|
||||
continue;
|
||||
|
||||
if( oldnetcode != netcode )
|
||||
{
|
||||
oldnetcode = netcode;
|
||||
candidates.clear();
|
||||
|
||||
// Build the list of pads candidates connected to the net:
|
||||
candidates.reserve( net->m_PadInNetList.size() );
|
||||
|
||||
for( unsigned ii = 0; ii < net->m_PadInNetList.size(); ii++ )
|
||||
candidates.push_back( net->m_PadInNetList[ii] );
|
||||
|
||||
// If we have any tracks...
|
||||
if( m_Track.GetCount() > 0 )
|
||||
{
|
||||
// Build the list of track candidates connected to the net:
|
||||
TRACK* track = m_Track.GetFirst()->GetStartNetCode( netcode );
|
||||
|
||||
for( ; track; track = track->Next() )
|
||||
{
|
||||
if( track->GetNetCode() != netcode )
|
||||
break;
|
||||
|
||||
candidates.push_back( track );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test if a candidate is inside a filled area of this zone
|
||||
const SHAPE_POLY_SET& polysList = zone->GetFilledPolysList();
|
||||
|
||||
for( int outline = 0; outline < polysList.OutlineCount(); outline++ )
|
||||
{
|
||||
subnet++;
|
||||
|
||||
for( unsigned ic = 0; ic < candidates.size(); ic++ )
|
||||
{
|
||||
// test if this area is connected to a board item:
|
||||
BOARD_CONNECTED_ITEM* item = candidates[ic];
|
||||
|
||||
if( item->GetZoneSubNet() == subnet ) // Already merged
|
||||
continue;
|
||||
|
||||
if( !item->IsOnLayer( zone->GetLayer() ) )
|
||||
continue;
|
||||
|
||||
wxPoint pos1, pos2;
|
||||
|
||||
if( item->Type() == PCB_PAD_T )
|
||||
{
|
||||
// For pads we use the shape position instead of
|
||||
// the pad position, because the zones are connected
|
||||
// to the center of the shape, not the pad position
|
||||
// (this is important for pads with thermal relief)
|
||||
pos1 = pos2 = ( (D_PAD*) item )->ShapePos();
|
||||
}
|
||||
else if( item->Type() == PCB_VIA_T )
|
||||
{
|
||||
const VIA *via = static_cast<const VIA*>( item );
|
||||
pos1 = via->GetStart();
|
||||
pos2 = pos1;
|
||||
}
|
||||
else if( item->Type() == PCB_TRACE_T )
|
||||
{
|
||||
const TRACK *trk = static_cast<const TRACK*>( item );
|
||||
pos1 = trk->GetStart();
|
||||
pos2 = trk->GetEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool connected = false;
|
||||
|
||||
if( polysList.Contains( VECTOR2I( pos1.x, pos1.y ), outline ) )
|
||||
connected = true;
|
||||
|
||||
if( !connected && ( pos1 != pos2 ) )
|
||||
{
|
||||
if( polysList.Contains( VECTOR2I( pos2.x, pos2.y ), outline ) )
|
||||
connected = true;
|
||||
}
|
||||
|
||||
if( connected )
|
||||
{
|
||||
// Set ZoneSubnet to the current subnet value.
|
||||
// If the previous subnet is not 0, merge all items with old subnet
|
||||
// to the new one
|
||||
int old_subnet = item->GetZoneSubNet();
|
||||
item->SetZoneSubNet( subnet );
|
||||
|
||||
// Merge previous subnet with the current
|
||||
if( (old_subnet > 0) && (old_subnet != subnet) )
|
||||
{
|
||||
for( unsigned jj = 0; jj < candidates.size(); jj++ )
|
||||
{
|
||||
BOARD_CONNECTED_ITEM* item_to_merge = candidates[jj];
|
||||
|
||||
if( old_subnet == item_to_merge->GetZoneSubNet() )
|
||||
{
|
||||
item_to_merge->SetZoneSubNet( subnet );
|
||||
}
|
||||
}
|
||||
} // End if ( old_subnet > 0 )
|
||||
} // End if( connected )
|
||||
}
|
||||
}
|
||||
} // End read all zones candidates
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function Merge_SubNets_Connected_By_CopperAreas(BOARD* aPcb)
|
||||
* Calls Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ) for each
|
||||
* netcode found in zone list
|
||||
* @param aPcb = the current board
|
||||
*/
|
||||
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb )
|
||||
{
|
||||
for( int index = 0; index < aPcb->GetAreaCount(); index++ )
|
||||
{
|
||||
ZONE_CONTAINER* zone = aPcb->GetArea( index );
|
||||
|
||||
if ( ! zone->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
if ( zone->GetNetCode() <= 0 )
|
||||
continue;
|
||||
|
||||
Merge_SubNets_Connected_By_CopperAreas( aPcb, zone->GetNetCode() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function Merge_SubNets_Connected_By_CopperAreas(BOARD* aPcb, int aNetcode)
|
||||
* Used after connections by tracks calculations
|
||||
* Merge subnets, in tracks ans pads when they are connected by a filled copper area
|
||||
* for pads, this is the .m_physical_connexion member which is tested and modified
|
||||
* for tracks, this is the .m_Subnet member which is tested and modified
|
||||
* these members are block numbers (or cluster numbers) for a given net,
|
||||
* calculated by Build_Pads_Info_Connections_By_Tracks()
|
||||
* The result is merging 2 blocks (or subnets)
|
||||
* @param aPcb = the current board
|
||||
* @param aNetcode = netcode to consider
|
||||
*/
|
||||
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode )
|
||||
{
|
||||
// Ensure a zone with the given netcode exists: examine all zones:
|
||||
bool found = false;
|
||||
|
||||
for( int index = 0; index < aPcb->GetAreaCount(); index++ )
|
||||
{
|
||||
ZONE_CONTAINER* zone = aPcb->GetArea( index );
|
||||
|
||||
if( aNetcode == zone->GetNetCode() )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !found ) // No zone with this netcode, therefore no connection by zone
|
||||
return;
|
||||
|
||||
// list of pads and tracks candidates to test:
|
||||
// It is static to avoid multiple memory realloc.
|
||||
static std::vector <BOARD_CONNECTED_ITEM*> Candidates;
|
||||
Candidates.clear();
|
||||
|
||||
// Build the list of pads candidates connected to the net:
|
||||
NETINFO_ITEM* net = aPcb->FindNet( aNetcode );
|
||||
wxASSERT( net );
|
||||
Candidates.reserve( net->m_PadInNetList.size() );
|
||||
for( unsigned ii = 0; ii < net->m_PadInNetList.size(); ii++ )
|
||||
Candidates.push_back( net->m_PadInNetList[ii] );
|
||||
|
||||
// Build the list of track candidates connected to the net:
|
||||
TRACK* track;
|
||||
|
||||
if( aPcb->m_Track.GetCount() > 0 )
|
||||
{
|
||||
track = aPcb->m_Track.GetFirst()->GetStartNetCode( aNetcode );
|
||||
|
||||
for( ; track; track = track->Next() )
|
||||
{
|
||||
if( track->GetNetCode() != aNetcode )
|
||||
break;
|
||||
|
||||
Candidates.push_back( track );
|
||||
}
|
||||
}
|
||||
|
||||
if( Candidates.size() == 0 )
|
||||
return;
|
||||
|
||||
int next_subnet_free_number = 0;
|
||||
for( unsigned ii = 0; ii < Candidates.size(); ii++ )
|
||||
{
|
||||
int subnet = Candidates[ii]->GetSubNet();
|
||||
next_subnet_free_number = std::max( next_subnet_free_number, subnet );
|
||||
}
|
||||
|
||||
next_subnet_free_number++; // This is a subnet we can use with not connected items
|
||||
// by tracks, but connected by zone.
|
||||
|
||||
// Sort by zone_subnet:
|
||||
sort( Candidates.begin(), Candidates.end(), CmpZoneSubnetValue );
|
||||
|
||||
// Some items can be not connected, but they can be connected to a filled area:
|
||||
// give them a subnet common to these items connected only by the area,
|
||||
// and not already used.
|
||||
// a value like next_subnet_free_number+zone_subnet is right
|
||||
for( unsigned jj = 0; jj < Candidates.size(); jj++ )
|
||||
{
|
||||
BOARD_CONNECTED_ITEM* item = Candidates[jj];
|
||||
if ( item->GetSubNet() == 0 && (item->GetZoneSubNet() > 0) )
|
||||
{
|
||||
item->SetSubNet( next_subnet_free_number + item->GetZoneSubNet() );
|
||||
}
|
||||
}
|
||||
|
||||
// Now, for each zone subnet, we search for 2 items with different subnets.
|
||||
// if found, the 2 subnet are merged in the whole candidate list.
|
||||
int old_subnet = 0;
|
||||
int old_zone_subnet = 0;
|
||||
for( unsigned ii = 0; ii < Candidates.size(); ii++ )
|
||||
{
|
||||
BOARD_CONNECTED_ITEM* item = Candidates[ii];
|
||||
int zone_subnet = item->GetZoneSubNet();
|
||||
|
||||
if( zone_subnet == 0 ) // Not connected by a filled area, skip it
|
||||
continue;
|
||||
|
||||
int subnet = item->GetSubNet();
|
||||
|
||||
if( zone_subnet != old_zone_subnet ) // a new zone subnet is found
|
||||
{
|
||||
old_subnet = subnet;
|
||||
old_zone_subnet = zone_subnet;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2 successive items already from the same cluster: nothing to do
|
||||
if( subnet == old_subnet )
|
||||
continue;
|
||||
|
||||
// Here we have 2 items connected by the same area have 2 differents subnets: merge subnets
|
||||
if( (subnet > old_subnet) || ( subnet <= 0) )
|
||||
std::swap( subnet, old_subnet );
|
||||
|
||||
for( unsigned jj = 0; jj < Candidates.size(); jj++ )
|
||||
{
|
||||
BOARD_CONNECTED_ITEM * item_to_merge = Candidates[jj];
|
||||
|
||||
if( item_to_merge->GetSubNet() == old_subnet )
|
||||
item_to_merge->SetSubNet( subnet );
|
||||
}
|
||||
|
||||
old_subnet = subnet;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Compare function used for sorting candidates by increasing zone subnet
|
||||
*/
|
||||
static bool CmpZoneSubnetValue( const BOARD_CONNECTED_ITEM* a, const BOARD_CONNECTED_ITEM* b )
|
||||
{
|
||||
int asubnet, bsubnet;
|
||||
|
||||
asubnet = a->GetZoneSubNet();
|
||||
bsubnet = b->GetZoneSubNet();
|
||||
|
||||
return asubnet < bsubnet;
|
||||
}
|
Loading…
Reference in New Issue