7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-18 22:11:40 +00:00

Removed legacy connectivity/ratsnest algorithm, replaced with the new one. No legacy autorouting for the moment

This commit is contained in:
Tomasz Włostowski 2017-03-22 14:51:07 +01:00
parent 9ad886344b
commit 3cba1007eb
43 changed files with 500 additions and 2481 deletions

View File

@ -481,7 +481,7 @@ public:
* It shows the connections from a pad to the nearest connected pad
* @param aModule = module to consider.
*/
void build_ratsnest_module( MODULE* aModule );
void build_ratsnest_module( MODULE *mod, wxPoint aMoveVector );
/**
* Function TraceModuleRatsNest
@ -526,7 +526,8 @@ public:
* When aInit = false, aItemRef is not used (can be NULL)
*/
void BuildAirWiresTargetsList( BOARD_CONNECTED_ITEM* aItemRef,
const wxPoint& aPosition, bool aInit );
const wxPoint& aPosition,
int aNet );
/**
* Function TestForActiveLinksInRatsnest

View File

@ -184,25 +184,13 @@ set( PCBNEW_EXPORTERS
exporters/gendrill_gerber_writer.cpp
)
set( PCBNEW_AUTOROUTER_SRCS
autorouter/rect_placement/rect_placement.cpp
autorouter/move_and_route_event_functions.cpp
autorouter/auto_place_footprints.cpp
autorouter/autorout.cpp
autorouter/routing_matrix.cpp
autorouter/dist.cpp
autorouter/queue.cpp
autorouter/spread_footprints.cpp
autorouter/solve.cpp
autorouter/graphpcb.cpp
autorouter/work.cpp
)
set( PCBNEW_MICROWAVE_SRCS
microwave/microwave_inductor.cpp
)
set( PCBNEW_CLASS_SRCS
autorouter/rect_placement/rect_placement.cpp
autorouter/spread_footprints.cpp
board_commit.cpp
tool_modview.cpp
modview_frame.cpp
@ -299,7 +287,6 @@ set( PCBNEW_CLASS_SRCS
zone_filling_algorithm.cpp
zones_functions_for_undo_redo.cpp
zones_polygons_insulated_copper_islands.cpp
zones_polygons_test_connections.cpp
zones_test_and_combine_areas.cpp
class_footprint_wizard.cpp
class_action_plugin.cpp
@ -334,7 +321,6 @@ set( PCBNEW_CLASS_SRCS
)
set( PCBNEW_SRCS
${PCBNEW_AUTOROUTER_SRCS}
${PCBNEW_MICROWAVE_SRCS}
${PCBNEW_CLASS_SRCS}
${PCBNEW_DIALOGS}
@ -622,7 +608,6 @@ add_library( pcbnew_kiface MODULE
${PCBNEW_COMMON_SRCS}
${PCBNEW_SCRIPTING_SRCS}
)
set_target_properties( pcbnew_kiface PROPERTIES
# Decorate OUTPUT_NAME with PREFIX and SUFFIX, creating something like
# _pcbnew.so, _pcbnew.dll, or _pcbnew.kiface

View File

@ -50,6 +50,8 @@
#include <pcbnew.h>
#include <protos.h>
#include <connectivity.h>
#define BLOCK_OUTLINE_COLOR YELLOW
/**
@ -536,6 +538,7 @@ void PCB_EDIT_FRAME::Block_Delete()
{
BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii );
itemsList->SetPickedItemStatus( UR_DELETED, ii );
GetBoard()->GetConnectivity()->Remove( item );
switch( item->Type() )
{
@ -599,6 +602,7 @@ void PCB_EDIT_FRAME::Block_Rotate()
{
BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii );
wxASSERT( item );
itemsList->SetPickedItemStatus( UR_CHANGED, ii );
switch( item->Type() )
@ -642,6 +646,7 @@ void PCB_EDIT_FRAME::Block_Rotate()
BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii );
wxASSERT( item );
item->Rotate( centre, rotAngle );
GetBoard()->GetConnectivity()->Update( item );
}
Compile_Ratsnest( NULL, true );
@ -667,6 +672,7 @@ void PCB_EDIT_FRAME::Block_Flip()
wxASSERT( item );
itemsList->SetPickedItemStatus( UR_FLIPPED, ii );
item->Flip( center );
GetBoard()->GetConnectivity()->Update( item );
// If a connected item is flipped, the ratsnest is no more OK
switch( item->Type() )
@ -721,6 +727,7 @@ void PCB_EDIT_FRAME::Block_Move()
BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii );
itemsList->SetPickedItemStatus( UR_MOVED, ii );
item->Move( MoveVector );
GetBoard()->GetConnectivity()->Update( item );
item->ClearFlags( IS_MOVED );
switch( item->Type() )

View File

@ -596,7 +596,7 @@ bool BOARD_NETLIST_UPDATER::testConnectivity( NETLIST& aNetlist )
if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() )
continue;
int nc = zone->GetNet()->GetNodesCount();
int nc = m_board->GetConnectivity()->GetPadCount( zone->GetNetCode() );
if( nc == 0 )
{
@ -668,7 +668,6 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
if( !m_isDryRun )
{
m_commit.Push( _( "Update netlist" ) );
m_frame->Compile_Ratsnest( NULL, false );
m_board->GetConnectivity()->Build( m_board );
testConnectivity( aNetlist );
}

View File

@ -120,9 +120,6 @@ BOARD::~BOARD()
Delete( area_to_remove );
}
m_FullRatsnest.clear();
m_LocalRatsnest.clear();
DeleteMARKERs();
DeleteZONEOutlines();
@ -1157,20 +1154,8 @@ void BOARD::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() );
aList.push_back( MSG_PANEL_ITEM( _( "Nets" ), txt, RED ) );
/* These parameters are known only if the full ratsnest is available,
* so, display them only if this is the case
*/
if( (m_Status_Pcb & NET_CODES_OK) )
{
txt.Printf( wxT( "%d" ), GetRatsnestsCount() );
aList.push_back( MSG_PANEL_ITEM( _( "Links" ), txt, DARKGREEN ) );
txt.Printf( wxT( "%d" ), GetRatsnestsCount() - GetUnconnectedNetCount() );
aList.push_back( MSG_PANEL_ITEM( _( "Connections" ), txt, DARKGREEN ) );
txt.Printf( wxT( "%d" ), GetUnconnectedNetCount() );
aList.push_back( MSG_PANEL_ITEM( _( "Unconnected" ), txt, BLUE ) );
}
txt.Printf( wxT( "%d" ), GetConnectivity()->GetUnconnectedCount() );
aList.push_back( MSG_PANEL_ITEM( _( "Unconnected" ), txt, BLUE ) );
}
@ -1428,10 +1413,14 @@ MODULE* BOARD::FindModule( const wxString& aRefOrTimeStamp, bool aSearchByTimeSt
// Sort nets by decreasing pad count. For same pad count, sort by alphabetic names
static bool sortNetsByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
{
if( b->GetNodesCount() == a->GetNodesCount() )
return a->GetNetname() < b->GetNetname();
auto connectivity = a->GetParent()->GetConnectivity();
int countA = connectivity->GetPadCount( a->GetNet() );
int countB = connectivity->GetPadCount( b->GetNet() );
return b->GetNodesCount() < a->GetNodesCount();
if( countA == countB )
return a->GetNetname() < b->GetNetname();
else
return countB < countA;
}
// Sort nets by alphabetic names
@ -1619,10 +1608,10 @@ D_PAD* BOARD::GetPad( TRACK* aTrace, ENDPOINT_T aEndPoint )
D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet )
{
for( unsigned i=0; i<GetPadCount(); ++i )
for( auto mod : Modules() )
{
D_PAD* pad = m_NetInfo.GetPad(i);
for ( auto pad : mod->PadsIter() )
{
if( pad->GetPosition() != aPosition )
continue;
@ -1630,8 +1619,9 @@ D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet )
if( ( pad->GetLayerSet() & aLayerSet ).any() )
return pad;
}
}
return NULL;
return nullptr;
}
@ -1744,29 +1734,23 @@ bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp )
void BOARD::GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector, int aNetCode )
{
if( aNetCode < 0 )
for ( auto mod : Modules() )
{
aVector.insert( aVector.end(), m_NetInfo.m_PadsFullList.begin(),
m_NetInfo.m_PadsFullList.end() );
}
else
{
const NETINFO_ITEM* net = m_NetInfo.GetNetItem( aNetCode );
if( net )
for ( auto pad : mod->PadsIter( ) )
{
aVector.insert( aVector.end(), net->m_PadInNetList.begin(),
net->m_PadInNetList.end() );
if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
{
aVector.push_back( pad );
}
}
}
sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
}
void BOARD::PadDelete( D_PAD* aPad )
{
m_NetInfo.DeletePad( aPad );
aPad->DeleteStructure();
}
@ -2830,7 +2814,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() )
continue;
if( zone->GetNet()->GetNodesCount() == 0 )
if( GetConnectivity()->GetPadCount( zone->GetNetCode() ) == 0 )
{
msg.Printf( _( "Copper zone (net name '%s'): net has no pads connected." ),
GetChars( zone->GetNet()->GetNetname() ) );
@ -2900,3 +2884,42 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
{
return m_connectivity->GetRatsnest();
}*/
const std::vector<D_PAD*> BOARD::GetPads()
{
std::vector<D_PAD*> rv;
for ( auto mod: Modules() )
{
for ( auto pad: mod->PadsIter() )
rv.push_back ( pad );
}
return rv;
}
unsigned BOARD::GetPadCount() const
{
return m_connectivity->GetPadCount();
}
/**
* Function GetPad
* @return D_PAD* - at the \a aIndex
*/
D_PAD* BOARD::GetPad( unsigned aIndex ) const
{
unsigned count = 0;
for ( MODULE *mod = m_Modules; mod ; mod = mod->Next() ) // FIXME: const DLIST_ITERATOR
{
for ( D_PAD *pad = mod->Pads(); pad; pad = pad->Next() )
{
if ( count == aIndex )
return pad;
count++;
}
}
return nullptr;
}

View File

@ -257,15 +257,11 @@ public:
DLIST_ITERATOR_WRAPPER<MODULE> Modules() { return DLIST_ITERATOR_WRAPPER<MODULE>(m_Modules); }
DLIST_ITERATOR_WRAPPER<BOARD_ITEM> Drawings() { return DLIST_ITERATOR_WRAPPER<BOARD_ITEM>(m_Drawings); }
// will be deprecated as soon as append board functionality is fixed
DLIST<BOARD_ITEM>& DrawingsList() { return m_Drawings; }
/// Ratsnest list for the BOARD
std::vector<RATSNEST_ITEM> m_FullRatsnest;
/// Ratsnest list relative to a given footprint (used while moving a footprint).
std::vector<RATSNEST_ITEM> m_LocalRatsnest;
/// zone contour currently in progress
ZONE_CONTAINER* m_CurrentZoneContour;
@ -712,15 +708,6 @@ public:
/** Calculate the zone segment count */
int GetNumSegmZone() const;
/**
* Function GetNumRatsnests
* @return int - The number of rats
*/
unsigned GetRatsnestsCount() const
{
return m_FullRatsnest.size();
}
/**
* Function GetNodesCount
* @return the number of pads members of nets (i.e. with netcode > 0)
@ -753,19 +740,13 @@ public:
* Function GetPadCount
* @return the number of pads in board
*/
unsigned GetPadCount() const
{
return m_NetInfo.GetPadCount();
}
unsigned GetPadCount() const;
/**
* Function GetPad
* @return D_PAD* - at the \a aIndex from m_NetInfo
* @return D_PAD* - at the \a aIndex
*/
D_PAD* GetPad( unsigned aIndex ) const
{
return m_NetInfo.GetPad( aIndex );
}
D_PAD* GetPad( unsigned aIndex ) const;
/**
* Function GetPads
@ -774,7 +755,7 @@ public:
* ownership of the respective PADs.
* @return D_PADS - a full list of pads
*/
const D_PADS& GetPads() { return m_NetInfo.m_PadsFullList; }
const std::vector<D_PAD*> GetPads();
void BuildListOfNets()
{
@ -1192,14 +1173,6 @@ public:
int Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine,
bool aCreate_Markers );
/****** function relative to ratsnest calculations: */
/**
* 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 analyze. if -1, analyze all nets
*/
void Test_Connections_To_Copper_Areas( int aNetcode = -1 );
/**
* Function GetViaByPosition

View File

@ -48,15 +48,7 @@ class CN_BOARD_ITEM_DATA;
*/
class BOARD_CONNECTED_ITEM : public BOARD_ITEM
{
friend class CONNECTIONS;
public:
// These 2 members are used for temporary storage during connections calculations:
std::vector<TRACK*> m_TracksConnected; // list of other tracks connected to me
std::vector<D_PAD*> m_PadsConnected; // list of other pads connected to me
BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype );
// Do not create a copy constructor & operator=.

View File

@ -60,61 +60,6 @@ class MSG_PANEL_ITEM;
#define CH_ACTIF 8 /* Not routed. */
#define LOCAL_RATSNEST_ITEM 0x8000 /* Line between two pads of a single module. */
/**
* Class RATSNEST_ITEM
* describes a ratsnest line: a straight line connecting 2 pads
*/
class RATSNEST_ITEM
{
private:
int m_NetCode; // netcode ( = 1.. n , 0 is the value used for not connected items)
public:
int m_Status; // State: see previous defines (CH_ ...)
D_PAD* m_PadStart; // pointer to the starting pad
D_PAD* m_PadEnd; // pointer to ending pad
int m_Length; // length of the line (used in some calculations)
RATSNEST_ITEM();
/**
* Function GetNet
* @return int - the net code.
*/
int GetNet() const
{
return m_NetCode;
}
void SetNet( int aNetCode )
{
m_NetCode = aNetCode;
}
bool IsVisible()
{
return (m_Status & CH_VISIBLE) != 0;
}
bool IsActive()
{
return (m_Status & CH_ACTIF) != 0;
}
bool IsLocal()
{
return (m_Status & LOCAL_RATSNEST_ITEM) != 0;
}
/**
* Function Draw
*/
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode,
const wxPoint& offset );
};
DECL_VEC_FOR_SWIG( D_PADS, D_PAD* )
/**
@ -142,25 +87,6 @@ private:
public:
D_PADS& Pads() { return m_PadInNetList; }
/**
* Function GetNodesCount
* @return int - number of pad nodes in the net
*/
int GetNodesCount() const { return m_PadInNetList.size(); }
D_PADS m_PadInNetList; ///< List of pads connected to this net
unsigned m_RatsnestStartIdx; /* Starting point of ratsnests of this
* net (included) in a general buffer of
* ratsnest (a vector<RATSNEST_ITEM*>
* buffer) */
unsigned m_RatsnestEndIdx; // Ending point of ratsnests of this net
// (excluded) in this buffer
NETINFO_ITEM( BOARD* aParent, const wxString& aNetName = wxEmptyString, int aNetCode = -1 );
~NETINFO_ITEM();
@ -340,12 +266,6 @@ public:
*/
void Clear()
{
m_PadInNetList.clear();
m_RatsnestStartIdx = 0; // Starting point of ratsnests of this net in a
// general buffer of ratsnest
m_RatsnestEndIdx = 0; // Ending point of ratsnests of this net
SetClass( NETCLASSPTR() );
}
@ -540,15 +460,6 @@ public:
* Function GetPadCount
* @return the number of pads in board
*/
unsigned GetPadCount() const { return m_PadsFullList.size(); }
/**
* Function GetPads
* returns a list of all the pads (so long as buildPadsFullList() has
* been recently called). Returned list contains non-owning pointers.
* @return D_PADS& - a full list of pads
*/
const D_PADS& GetPads() const { return m_PadsFullList; }
/// Return the name map, at least for python.
const NETNAMES_MAP& NetsByName() const { return m_netNames; }
@ -556,14 +467,6 @@ public:
/// Return the netcode map, at least for python.
const NETCODES_MAP& NetsByNetcode() const { return m_netCodes; }
/**
* Function GetPad
* @return D_PAD* - the pad from m_PadsFullList or nullptr if bad @a aIdx
*/
D_PAD* GetPad( unsigned aIdx ) const;
bool DeletePad( D_PAD* aPad );
///> Constant that holds the "unconnected net" number (typically 0)
///> all items "connected" to this net are actually not connected items
static const int UNCONNECTED;
@ -680,9 +583,6 @@ private:
NETNAMES_MAP m_netNames; ///< map of <wxString, NETINFO_ITEM*>, is NETINFO_ITEM owner
NETCODES_MAP m_netCodes; ///< map of <int, NETINFO_ITEM*> is NOT owner
D_PADS m_PadsFullList; ///< contains all pads, sorted by pad's netname.
///< can be used in ratsnest calculations.
int m_newNetCode; ///< possible value for new net code assignment
};
@ -695,17 +595,13 @@ private:
#define START_ON_TRACK 0x40
#define END_ON_TRACK 0x80
/* Status bit (OR'ed bits) for class BOARD member .m_Status_Pcb */
enum StatusPcbFlags {
LISTE_PAD_OK = 1, /* Pad list is Ok */
LISTE_RATSNEST_ITEM_OK = 2, /* General Ratsnest is Ok */
RATSNEST_ITEM_LOCAL_OK = 4, /* current MODULE ratsnest is Ok */
CONNEXION_OK = 8, /* List of connections exists. */
NET_CODES_OK = 0x10, /* Bit indicating that Netcode is OK,
* do not change net name. */
DO_NOT_SHOW_GENERAL_RASTNEST = 0x20 /* Do not display the general
* ratsnest (used in module moves) */
};
#endif // CLASS_NETINFO_

View File

@ -54,10 +54,6 @@ NETINFO_ITEM::NETINFO_ITEM( BOARD* aParent, const wxString& aNetName, int aNetCo
m_NetCode( aNetCode ), m_Netname( aNetName ), m_ShortNetname( m_Netname.AfterLast( '/' ) )
{
m_parent = aParent;
m_RatsnestStartIdx = 0; // Starting point of ratsnests of this net in a
// general buffer of ratsnest
m_RatsnestEndIdx = 0; // Ending point of ratsnests of this net
m_NetClassName = NETCLASS::Default;
}
@ -144,39 +140,4 @@ void NETINFO_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
// Displays the net length of internal ICs connections (wires inside ICs):
txt = ::LengthDoubleToString( lengthPadToDie );
aList.push_back( MSG_PANEL_ITEM( _( "In Package" ), txt, RED ) );
}
/***********************/
/* class RATSNEST_ITEM */
/***********************/
RATSNEST_ITEM::RATSNEST_ITEM()
{
m_NetCode = 0; // netcode ( = 1.. n , 0 is the value used for not
// connected items)
m_Status = 0; // state
m_PadStart = NULL; // pointer to the starting pad
m_PadEnd = NULL; // pointer to ending pad
m_Length = 0; // length of the line (temporary used in some
// calculations)
}
/**
* Function Draw
* Draws a line (a ratsnest) from the starting pad to the ending pad
*/
void RATSNEST_ITEM::Draw( EDA_DRAW_PANEL* panel,
wxDC* DC,
GR_DRAWMODE aDrawMode,
const wxPoint& aOffset )
{
GRSetDrawMode( DC, aDrawMode );
COLOR4D color = g_ColorsSettings.GetItemColor( LAYER_RATSNEST );
GRLine( panel->GetClipBox(), DC,
m_PadStart->GetPosition() - aOffset,
m_PadEnd->GetPosition() - aOffset, 0, color );
}
}

View File

@ -62,7 +62,6 @@ void NETINFO_LIST::clear()
for( it = m_netNames.begin(), itEnd = m_netNames.end(); it != itEnd; ++it )
delete it->second;
m_PadsFullList.clear();
m_netNames.clear();
m_netCodes.clear();
m_newNetCode = 0;
@ -143,32 +142,6 @@ void NETINFO_LIST::AppendNet( NETINFO_ITEM* aNewElement )
}
D_PAD* NETINFO_LIST::GetPad( unsigned aIdx ) const
{
if( aIdx < m_PadsFullList.size() )
return m_PadsFullList[aIdx];
else
return NULL;
}
bool NETINFO_LIST::DeletePad( D_PAD* aPad )
{
std::vector<D_PAD*>::iterator it = m_PadsFullList.begin();
std::vector<D_PAD*>::iterator end = m_PadsFullList.end();
for( ; it != end; ++it )
{
if( *it == aPad )
{
m_PadsFullList.erase( it );
return true;
}
}
return false;
}
/* sort function, to sort pad list by netnames
* this is a case sensitive sort.
* DO NOT change it because NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname )
@ -199,47 +172,15 @@ void NETINFO_LIST::buildListOfNets()
D_PAD* pad;
int nodes_count = 0;
// Build the PAD list, sorted by net
buildPadsFullList();
// Restore the initial state of NETINFO_ITEMs
for( NETINFO_LIST::iterator net( begin() ), netEnd( end() ); net != netEnd; ++net )
net->Clear();
// Assign pads to appropriate NETINFO_ITEMs
for( unsigned ii = 0; ii < m_PadsFullList.size(); ii++ )
{
pad = m_PadsFullList[ii];
if( pad->GetNetCode() == NETINFO_LIST::UNCONNECTED ) // pad not connected
continue;
if( !( pad->GetLayerSet() & LSET::AllCuMask() ).any() )
// pad not a copper layer (happens when building complex shapes)
continue;
// Add pad to the appropriate list of pads
NETINFO_ITEM* net = pad->GetNet();
// it should not be possible for BOARD_CONNECTED_ITEM to return NULL as a result of GetNet()
wxASSERT( net );
if( net )
net->m_PadInNetList.push_back( pad );
++nodes_count;
}
m_Parent->SetNodeCount( nodes_count );
m_Parent->SynchronizeNetsAndNetClasses( );
m_Parent->m_Status_Pcb |= NET_CODES_OK;
m_Parent->SetAreasNetCodesFromNetNames();
}
#if defined(DEBUG)
void NETINFO_LIST::Show() const
{
@ -255,46 +196,6 @@ void NETINFO_LIST::Show() const
#endif
void NETINFO_LIST::buildPadsFullList()
{
/*
* initialize:
* m_Pads (list of pads)
* set m_Status_Pcb = LISTE_PAD_OK;
* also clear m_Pcb->m_FullRatsnest that could have bad data
* (m_Pcb->m_FullRatsnest uses pointer to pads)
* Be aware NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname )
* when search a net by its net name does a binary search
* and expects to have a nets list sorted by an alphabetic case sensitive sort
* So do not change the sort function used here
*/
if( m_Parent->m_Status_Pcb & LISTE_PAD_OK )
return;
// empty the old list
m_PadsFullList.clear();
m_Parent->m_FullRatsnest.clear();
// Clear variables used in ratsnest computation
for( MODULE* module = m_Parent->m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
{
m_PadsFullList.push_back( pad );
pad->SetSubRatsnest( 0 );
pad->SetParent( module );
}
}
// Sort pad list per net
sort( m_PadsFullList.begin(), m_PadsFullList.end(), padlistSortByNetnames );
m_Parent->m_Status_Pcb = LISTE_PAD_OK;
}
int NETINFO_LIST::getFreeNetCode()
{
do {
@ -373,4 +274,4 @@ NETINFO_ITEM* NETINFO_MAPPING::iterator::operator->() const
const int NETINFO_LIST::UNCONNECTED = 0;
const int NETINFO_LIST::ORPHANED = -1;
NETINFO_ITEM NETINFO_LIST::ORPHANED_ITEM = NETINFO_ITEM( NULL, wxEmptyString, NETINFO_LIST::UNCONNECTED );
NETINFO_ITEM NETINFO_LIST::ORPHANED_ITEM = NETINFO_ITEM( NULL, wxEmptyString, NETINFO_LIST::UNCONNECTED );

View File

@ -35,14 +35,12 @@
#include <pcbnew.h>
#include <class_board.h>
#include <class_track.h>
#include <connect.h>
#include <dialog_cleaning_options.h>
#include <board_commit.h>
#include <tuple>
#include <connectivity.h>
// Helper class used to clean tracks and vias
class TRACKS_CLEANER: CONNECTIONS
class TRACKS_CLEANER
{
public:
TRACKS_CLEANER( BOARD* aPcb, BOARD_COMMIT& aCommit );
@ -69,7 +67,7 @@ private:
* Removes redundant vias like vias at same location
* or on pad through
*/
bool clean_vias();
bool cleanupVias();
/**
* Removes all the following THT vias on the same position of the
@ -98,12 +96,6 @@ private:
*/
bool clean_segments();
/**
* helper function
* Rebuild list of tracks, and connected tracks
* this info must be rebuilt when tracks are erased
*/
void buildTrackConnectionInfo();
/**
* helper function
@ -147,7 +139,6 @@ void PCB_EDIT_FRAME::Clean_Pcb()
// Clear undo and redo lists to avoid inconsistencies between lists
SetCurItem( NULL );
commit.Push( _( "Board cleanup" ) );
Compile_Ratsnest( NULL, true );
}
m_canvas->Refresh( true );
@ -165,13 +156,12 @@ bool TRACKS_CLEANER::CleanupBoard( bool aRemoveMisConnected,
bool aMergeSegments,
bool aDeleteUnconnected )
{
buildTrackConnectionInfo();
bool modified = false;
// delete redundant vias
if( aCleanVias )
modified |= clean_vias();
modified |= cleanupVias();
// Remove null segments and intermediate points on aligned segments
// If not asked, remove null segments only if remove misconnected is asked
@ -187,7 +177,7 @@ bool TRACKS_CLEANER::CleanupBoard( bool aRemoveMisConnected,
modified = true;
// Refresh track connection info
buildTrackConnectionInfo();
//buildTrackConnectionInfo(); FIXME: update connectivity
}
}
@ -195,7 +185,9 @@ bool TRACKS_CLEANER::CleanupBoard( bool aRemoveMisConnected,
if( aDeleteUnconnected )
{
if( modified ) // Refresh track connection info
buildTrackConnectionInfo();
{
//buildTrackConnectionInfo(); FIXME: update connectivity
}
if( deleteDanglingTracks() )
{
@ -214,101 +206,37 @@ bool TRACKS_CLEANER::CleanupBoard( bool aRemoveMisConnected,
TRACKS_CLEANER::TRACKS_CLEANER( BOARD* aPcb, BOARD_COMMIT& aCommit )
: CONNECTIONS( aPcb ), m_brd( aPcb ), m_commit( aCommit )
: m_brd( aPcb ), m_commit( aCommit )
{
// Be sure pad list is up to date
BuildPadsList();
}
void TRACKS_CLEANER::buildTrackConnectionInfo()
{
BuildTracksCandidatesList( m_brd->m_Track, NULL );
// clear flags and variables used in cleanup
for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() )
{
track->start = NULL;
track->end = NULL;
track->m_PadsConnected.clear();
track->SetState( START_ON_PAD | END_ON_PAD | BUSY, false );
}
// Build connections info tracks to pads
SearchTracksConnectedToPads();
for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() )
{
// Mark track if connected to pads
for( unsigned jj = 0; jj < track->m_PadsConnected.size(); jj++ )
{
D_PAD * pad = track->m_PadsConnected[jj];
if( pad->HitTest( track->GetStart() ) )
{
track->start = pad;
track->SetState( START_ON_PAD, true );
}
if( pad->HitTest( track->GetEnd() ) )
{
track->end = pad;
track->SetState( END_ON_PAD, true );
}
}
}
}
bool TRACKS_CLEANER::removeBadTrackSegments()
{
// The rastsnet is expected to be up to date (Compile_Ratsnest was called)
// Rebuild physical connections.
// the list of physical connected items to a given item is in
// m_PadsConnected and m_TracksConnected members of each item
BuildTracksCandidatesList( m_brd->m_Track );
// build connections between track segments and pads.
SearchTracksConnectedToPads();
TRACK* segment;
// build connections between track ends
for( segment = m_brd->m_Track; segment; segment = segment->Next() )
{
SearchConnectedTracks( segment );
GetConnectedTracks( segment );
}
bool isModified = false;
auto connectivity = m_brd->GetConnectivity();
for( segment = m_brd->m_Track; segment; segment = segment->Next() )
for( auto segment : m_brd->Tracks() )
{
segment->SetState( FLAG0, false );
for( unsigned ii = 0; ii < segment->m_PadsConnected.size(); ++ii )
for( auto testedPad : connectivity->GetConnectedPads( segment ) )
{
if( segment->GetNetCode() != segment->m_PadsConnected[ii]->GetNetCode() )
if( segment->GetNetCode() != testedPad->GetNetCode() )
segment->SetState( FLAG0, true );
}
for( unsigned ii = 0; ii < segment->m_TracksConnected.size(); ++ii )
for( auto testedTrack : connectivity->GetConnectedTracks( segment ) )
{
TRACK* tested = segment->m_TracksConnected[ii];
if( segment->GetNetCode() != tested->GetNetCode() && !tested->GetState( FLAG0 ) )
if( segment->GetNetCode() != testedTrack->GetNetCode() && !testedTrack->GetState( FLAG0 ) )
segment->SetState( FLAG0, true );
}
}
// Remove tracks having a flagged segment
TRACK* next;
for( segment = m_brd->m_Track; segment; segment = next )
for( auto segment : m_brd->Tracks() )
{
next = segment->Next();
if( segment->GetState( FLAG0 ) ) // Segment is flagged to be removed
{
isModified = true;
@ -317,15 +245,6 @@ bool TRACKS_CLEANER::removeBadTrackSegments()
}
}
if( isModified )
{ // some pointers are invalid. Clear the m_TracksConnected list,
// to avoid any issue
for( segment = m_brd->m_Track; segment; segment = segment->Next() )
segment->m_TracksConnected.clear();
m_brd->m_Status_Pcb = 0;
}
return isModified;
}
@ -353,7 +272,7 @@ bool TRACKS_CLEANER::remove_duplicates_of_via( const VIA *aVia )
}
bool TRACKS_CLEANER::clean_vias()
bool TRACKS_CLEANER::cleanupVias()
{
bool modified = false;
@ -376,9 +295,10 @@ bool TRACKS_CLEANER::clean_vias()
/* To delete through Via on THT pads at same location
* Examine the list of connected pads:
* if one through pad is found, the via can be removed */
for( unsigned ii = 0; ii < via->m_PadsConnected.size(); ++ii )
const auto pads = m_brd->GetConnectivity()->GetConnectedPads( via );
for( const auto pad : pads )
{
const D_PAD* pad = via->m_PadsConnected[ii];
const LSET all_cu = LSET::AllCuMask();
if( ( pad->GetLayerSet() & all_cu ) == all_cu )

View File

@ -39,756 +39,63 @@
// Helper classes to handle connection points
#include <connect.h>
const bool g_UseLegacyConnectionAlgo = false;
extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb );
extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
// Local functions
static void RebuildTrackChain( BOARD* pcb );
CONNECTIONS::CONNECTIONS( BOARD * aBrd )
{
m_brd = aBrd;
m_firstTrack = NULL;
m_lastTrack = NULL;
}
/* Fills m_sortedPads with all pads that be connected to tracks
* pads are sorted by X coordinate ( and Y coordinates for same X value )
* aNetcode = net code to filter pads or < 0 to put all pads in list
/*
* Function SortTracksByNetCode used in RebuildTrackChain()
* to sort track segments by net code.
*/
void CONNECTIONS::BuildPadsList( int aNetcode )
static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & compare )
{
// Creates sorted pad list if not exists
m_sortedPads.clear();
m_brd->GetSortedPadListByXthenYCoord( m_sortedPads, aNetcode < 0 ? -1 : aNetcode );
// For items having the same Net, keep the order in list
if( ref->GetNetCode() == compare->GetNetCode())
return ref->m_Param < compare->m_Param;
return ref->GetNetCode() < compare->GetNetCode();
}
/* Explores the list of pads and adds to m_PadsConnected member
* of each pad pads connected to
* Here, connections are due to intersecting pads, not tracks
*/
void CONNECTIONS::SearchConnectionsPadsToIntersectingPads()
{
std::vector<CONNECTED_POINT*> candidates;
BuildPadsCandidatesList();
for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ )
{
D_PAD* pad = m_sortedPads[ii];
pad->m_PadsConnected.clear();
candidates.clear();
CollectItemsNearTo( candidates, pad->ShapePos(), pad->GetBoundingRadius() );
// add pads to pad.m_PadsConnected, if they are connected
for( unsigned jj = 0; jj < candidates.size(); jj++ )
{
CONNECTED_POINT* item = candidates[jj];
D_PAD* candidate_pad = item->GetPad();
if( pad == candidate_pad )
continue;
if( !( pad->GetLayerSet() & candidate_pad->GetLayerSet() ).any() )
continue;
if( pad->HitTest( item->GetPoint() ) )
{
pad->m_PadsConnected.push_back( candidate_pad );
}
}
}
}
/* Explores the list of pads
* Adds to m_PadsConnected member of each track the pad(s) connected to
* Adds to m_TracksConnected member of each pad the track(s) connected to
* D_PAD::m_TracksConnected is cleared before adding items
* TRACK::m_PadsConnected is not cleared
*/
void CONNECTIONS::SearchTracksConnectedToPads( bool add_to_padlist, bool add_to_tracklist)
{
std::vector<CONNECTED_POINT*> candidates;
for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ )
{
D_PAD * pad = m_sortedPads[ii];
pad->m_TracksConnected.clear();
candidates.clear();
CollectItemsNearTo( candidates, pad->GetPosition(), pad->GetBoundingRadius() );
// add this pad to track.m_PadsConnected, if it is connected
for( unsigned jj = 0; jj < candidates.size(); jj++ )
{
CONNECTED_POINT* cp_item = candidates[jj];
if( !( pad->GetLayerSet() & cp_item->GetTrack()->GetLayerSet() ).any() )
continue;
if( pad->HitTest( cp_item->GetPoint() ) )
{
if( add_to_padlist )
cp_item->GetTrack()->m_PadsConnected.push_back( pad );
if( add_to_tracklist )
pad->m_TracksConnected.push_back( cp_item->GetTrack() );
}
}
}
}
void CONNECTIONS::CollectItemsNearTo( std::vector<CONNECTED_POINT*>& aList,
const wxPoint& aPosition, int aDistMax )
{
/* Search items in m_Candidates that position is <= aDistMax from aPosition
* (Rectilinear distance)
* m_Candidates is sorted by X then Y values, so a fast binary search is used
* to locate the "best" entry point in list
* The best entry is a pad having its m_Pos.x == (or near) aPosition.x
* All candidates are near this candidate in list
* So from this entry point, a linear search is made to find all candidates
*/
int idxmax = m_candidates.size()-1;
int delta = m_candidates.size();
int idx = 0; // Starting index is the beginning of list
while( delta )
{
// Calculate half size of remaining interval to test.
// Ensure the computed value is not truncated (too small)
if( (delta & 1) && ( delta > 1 ) )
delta++;
delta /= 2;
CONNECTED_POINT& item = m_candidates[idx];
int dist = item.GetPoint().x - aPosition.x;
if( abs(dist) <= aDistMax )
{
break; // A good entry point is found. The list can be scanned from this point.
}
else if( item.GetPoint().x < aPosition.x ) // We should search after this item
{
idx += delta;
if( idx > idxmax )
idx = idxmax;
}
else // We should search before this item
{
idx -= delta;
if( idx < 0 )
idx = 0;
}
}
/* Now explore the candidate list from the "best" entry point found
* (candidate "near" aPosition.x)
* We explore the list until abs(candidate->m_Point.x - aPosition.x) > aDistMax
* because the list is sorted by X position (and for a given X pos, by Y pos)
* Currently a linear search is made because the number of candidates
* having the right X position is usually small
*/
// search next candidates in list
wxPoint diff;
for( int ii = idx; ii <= idxmax; ii++ )
{
CONNECTED_POINT* item = &m_candidates[ii];
diff = item->GetPoint() - aPosition;
if( abs(diff.x) > aDistMax )
break; // Exit: the distance is to long, we cannot find other candidates
if( abs(diff.y) > aDistMax )
continue; // the y distance is to long, but we can find other candidates
// We have here a good candidate: add it
aList.push_back( item );
}
// search previous candidates in list
for( int ii = idx-1; ii >=0; ii-- )
{
CONNECTED_POINT * item = &m_candidates[ii];
diff = item->GetPoint() - aPosition;
if( abs(diff.x) > aDistMax )
break;
if( abs(diff.y) > aDistMax )
continue;
// We have here a good candidate:add it
aList.push_back( item );
}
}
void CONNECTIONS::BuildPadsCandidatesList()
{
m_candidates.clear();
m_candidates.reserve( m_sortedPads.size() );
for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ )
{
D_PAD * pad = m_sortedPads[ii];
CONNECTED_POINT candidate( pad, pad->GetPosition() );
m_candidates.push_back( candidate );
}
}
/* sort function used to sort .m_Connected by X the Y values
* items are sorted by X coordinate value,
* and for same X value, by Y coordinate value.
*/
static bool sortConnectedPointByXthenYCoordinates( const CONNECTED_POINT & aRef,
const CONNECTED_POINT & aTst )
{
if( aRef.GetPoint().x == aTst.GetPoint().x )
return aRef.GetPoint().y < aTst.GetPoint().y;
return aRef.GetPoint().x < aTst.GetPoint().x;
}
void CONNECTIONS::BuildTracksCandidatesList( TRACK* aBegin, TRACK* aEnd)
{
m_candidates.clear();
m_firstTrack = m_lastTrack = aBegin;
unsigned ii = 0;
// Count candidates ( i.e. end points )
for( const TRACK* track = aBegin; track; track = track->Next() )
{
if( track->Type() == PCB_VIA_T )
ii++;
else
ii += 2;
m_lastTrack = track;
if( track == aEnd )
break;
}
// Build candidate list
m_candidates.reserve( ii );
for( TRACK* track = aBegin; track; track = track->Next() )
{
CONNECTED_POINT candidate( track, track->GetStart() );
m_candidates.push_back( candidate );
if( track->Type() != PCB_VIA_T )
{
CONNECTED_POINT candidate2( track, track->GetEnd());
m_candidates.push_back( candidate2 );
}
if( track == aEnd )
break;
}
// Sort list by increasing X coordinate,
// and for increasing Y coordinate when items have the same X coordinate
// So candidates to the same location are consecutive in list.
sort( m_candidates.begin(), m_candidates.end(), sortConnectedPointByXthenYCoordinates );
}
/* Populates .m_connected with tracks/vias connected to aTrack
* param aTrack = track or via to use as reference
* For calculation time reason, an exhaustive search cannot be made
* and a proximity search is made:
* Only tracks with one end near one end of aTrack are collected.
* near means dist <= aTrack width / 2
* because with this constraint we can make a fast search in track list
* m_candidates is expected to be populated by the track candidates ends list
*/
int CONNECTIONS::SearchConnectedTracks( const TRACK* aTrack )
{
int count = 0;
m_connected.clear();
LSET layerMask = aTrack->GetLayerSet();
// Search for connections to starting point:
#define USE_EXTENDED_SEARCH
#ifdef USE_EXTENDED_SEARCH
int dist_max = aTrack->GetWidth() / 2;
static std::vector<CONNECTED_POINT*> tracks_candidates;
#endif
wxPoint position = aTrack->GetStart();
for( int kk = 0; kk < 2; kk++ )
{
#ifndef USE_EXTENDED_SEARCH
int idx = searchEntryPointInCandidatesList( position );
if( idx >= 0 )
{
// search after:
for( unsigned ii = idx; ii < m_candidates.size(); ii ++ )
{
if( m_candidates[ii].GetTrack() == aTrack )
continue;
if( m_candidates[ii].GetPoint() != position )
break;
if( ( m_candidates[ii].GetTrack()->GetLayerSet() & layerMask ).any() )
m_connected.push_back( m_candidates[ii].GetTrack() );
}
// search before:
for( int ii = idx-1; ii >= 0; ii -- )
{
if( m_candidates[ii].GetTrack() == aTrack )
continue;
if( m_candidates[ii].GetPoint() != position )
break;
if( ( m_candidates[ii].GetTrack()->GetLayerSet() & layerMask ).any() )
m_connected.push_back( m_candidates[ii].GetTrack() );
}
}
#else
tracks_candidates.clear();
CollectItemsNearTo( tracks_candidates, position, dist_max );
for( unsigned ii = 0; ii < tracks_candidates.size(); ii++ )
{
TRACK* ctrack = tracks_candidates[ii]->GetTrack();
if( !( ctrack->GetLayerSet() & layerMask ).any() )
continue;
if( ctrack == aTrack )
continue;
// We have a good candidate: calculate the actual distance
// between ends, which should be <= dist max.
wxPoint delta = tracks_candidates[ii]->GetPoint() - position;
int dist = KiROUND( EuclideanNorm( delta ) );
if( dist > dist_max )
continue;
m_connected.push_back( ctrack );
}
#endif
// Search for connections to ending point:
if( aTrack->Type() == PCB_VIA_T )
break;
position = aTrack->GetEnd();
}
return count;
}
int CONNECTIONS::searchEntryPointInCandidatesList( const wxPoint& aPoint )
{
// Search the aPoint coordinates in m_Candidates
// m_Candidates is sorted by X then Y values, and a fast binary search is used
int idxmax = m_candidates.size()-1;
int delta = m_candidates.size();
int idx = 0; // Starting index is the beginning of list
while( delta )
{
// Calculate half size of remaining interval to test.
// Ensure the computed value is not truncated (too small)
if( ( delta & 1 ) && ( delta > 1 ) )
delta++;
delta /= 2;
CONNECTED_POINT& candidate = m_candidates[idx];
if( candidate.GetPoint() == aPoint ) // candidate found
{
return idx;
}
// Not found: test the middle of the remaining sub list
if( candidate.GetPoint().x == aPoint.x ) // Must search considering Y coordinate
{
if(candidate.GetPoint().y < aPoint.y) // Must search after this item
{
idx += delta;
if( idx > idxmax )
idx = idxmax;
}
else // Must search before this item
{
idx -= delta;
if( idx < 0 )
idx = 0;
}
}
else if( candidate.GetPoint().x < aPoint.x ) // Must search after this item
{
idx += delta;
if( idx > idxmax )
idx = idxmax;
}
else // Must search before this item
{
idx -= delta;
if( idx < 0 )
idx = 0;
}
}
return -1;
}
/* Used after a track change (delete a track ou add a track)
* Connections to pads are recalculated
* Note also aFirstTrack (and aLastTrack ) can be NULL
*/
void CONNECTIONS::Build_CurrNet_SubNets_Connections( TRACK* aFirstTrack, TRACK* aLastTrack, int aNetcode )
{
m_firstTrack = aFirstTrack; // The first track used to build m_Candidates
m_lastTrack = aLastTrack; // The last track used to build m_Candidates
// Pads subnets are expected already cleared, because this function
// does not know the full list of pads
BuildTracksCandidatesList( aFirstTrack, aLastTrack );
TRACK* curr_track;
for( curr_track = aFirstTrack; curr_track != NULL; curr_track = curr_track->Next() )
{
// Clear track subnet id (Pads subnets are cleared outside this function)
curr_track->SetSubNet( 0 );
curr_track->m_TracksConnected.clear();
curr_track->m_PadsConnected.clear();
// Update connections between tracks:
SearchConnectedTracks( curr_track );
curr_track->m_TracksConnected = m_connected;
if( curr_track == aLastTrack )
break;
}
// Update connections between tracks and pads
BuildPadsList( aNetcode );
SearchTracksConnectedToPads();
// Update connections between intersecting pads (no tracks)
SearchConnectionsPadsToIntersectingPads();
// Creates sub nets (clusters) for the current net:
Propagate_SubNets();
}
/**
* Change a subnet value to a new value, in m_sortedPads pad list
* After that, 2 cluster (or subnets) are merged into only one.
* Note: the resulting subnet value is the smallest between aOldSubNet et aNewSubNet
* Helper function RebuildTrackChain
* rebuilds the track segment linked list in order to have a chain
* sorted by increasing netcodes.
* We try to keep order of track segments in list, when possible
* @param pcb = board to rebuild
*/
int CONNECTIONS::Merge_PadsSubNets( int aOldSubNet, int aNewSubNet )
static void RebuildTrackChain( BOARD* pcb )
{
int change_count = 0;
if( pcb->m_Track == NULL )
return;
if( aOldSubNet == aNewSubNet )
return 0;
int item_count = pcb->m_Track.GetCount();
if( (aOldSubNet > 0) && (aOldSubNet < aNewSubNet) )
std::swap( aOldSubNet, aNewSubNet );
std::vector<TRACK*> trackList;
trackList.reserve( item_count );
// Examine connections between intersecting pads
for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ )
// Put track list in a temporary list to sort tracks by netcode
// We try to keep the initial order of track segments in list, when possible
// so we use m_Param (a member variable used for temporary storage)
// to temporary keep trace of the order of segments
// The sort function uses this variable to sort items that
// have the same net code.
// Without this, during sorting, the initial order is sometimes lost
// by the sort algorithm
for( int ii = 0; ii < item_count; ++ii )
{
D_PAD * curr_pad = m_sortedPads[ii];
if( curr_pad->GetSubNet() != aOldSubNet )
continue;
change_count++;
curr_pad->SetSubNet( aNewSubNet );
pcb->m_Track->m_Param = ii;
trackList.push_back( pcb->m_Track.PopFront() );
}
return change_count;
// the list is empty now
wxASSERT( pcb->m_Track == NULL && pcb->m_Track.GetCount()==0 );
sort( trackList.begin(), trackList.end(), SortTracksByNetCode );
// add them back to the list
for( int i = 0; i < item_count; ++i )
pcb->m_Track.PushBack( trackList[i] );
}
/*
* Change a subnet value to a new value, for tracks and pads which are connected to.
* The result is merging 2 clusters (or subnets) into only one cluster.
* Note: the resulting sub net value is the smallest between aOldSubNet et aNewSubNet
*/
int CONNECTIONS::Merge_SubNets( int aOldSubNet, int aNewSubNet )
{
TRACK* curr_track;
int change_count = 0;
if( aOldSubNet == aNewSubNet )
return 0;
if( (aOldSubNet > 0) && (aOldSubNet < aNewSubNet) )
std::swap( aOldSubNet, aNewSubNet );
curr_track = (TRACK*)m_firstTrack;
for( ; curr_track != NULL; curr_track = curr_track->Next() )
{
if( curr_track->GetSubNet() != aOldSubNet )
{
if( curr_track == m_lastTrack )
break;
continue;
}
change_count++;
curr_track->SetSubNet( aNewSubNet );
for( unsigned ii = 0; ii < curr_track->m_PadsConnected.size(); ii++ )
{
D_PAD * pad = curr_track->m_PadsConnected[ii];
if( pad->GetSubNet() == aOldSubNet )
{
pad->SetSubNet( curr_track->GetSubNet() );
}
}
if( curr_track == m_lastTrack )
break;
}
return change_count;
}
/* Test a list of track segments, to create or propagate a sub netcode to pads and
* segments connected together.
* The track list must be sorted by nets, and all segments
* from m_firstTrack to m_lastTrack have the same net
* When 2 items are connected (a track to a pad, or a track to an other track),
* they are grouped in a cluster.
* The .m_Subnet member is the cluster identifier (subnet id)
* For a given net, if all tracks are created, there is only one cluster.
* but if not all tracks are created, there are more than one cluster,
* and some ratsnests will be left active.
* A ratsnest is active when it "connect" 2 items having different subnet id
*/
void CONNECTIONS::Propagate_SubNets()
{
int sub_netcode = 1;
TRACK* curr_track = (TRACK*)m_firstTrack;
if( curr_track )
curr_track->SetSubNet( sub_netcode );
// Examine connections between tracks and pads
for( ; curr_track != NULL; curr_track = curr_track->Next() )
{
// First: handling connections to pads
for( unsigned ii = 0; ii < curr_track->m_PadsConnected.size(); ii++ )
{
D_PAD * pad = curr_track->m_PadsConnected[ii];
if( curr_track->GetSubNet() ) // the track segment is already a cluster member
{
if( pad->GetSubNet() > 0 )
{
// The pad is already a cluster member, so we can merge the 2 clusters
Merge_SubNets( pad->GetSubNet(), curr_track->GetSubNet() );
}
else
{
/* The pad is not yet attached to a cluster , so we can add this pad to
* the cluster */
pad->SetSubNet( curr_track->GetSubNet() );
}
}
else // the track segment is not attached to a cluster
{
if( pad->GetSubNet() > 0 )
{
// it is connected to a pad in a cluster, merge this track
curr_track->SetSubNet( pad->GetSubNet() );
}
else
{
/* it is connected to a pad not in a cluster, so we must create a new
* cluster (only with the 2 items: the track and the pad) */
sub_netcode++;
curr_track->SetSubNet( sub_netcode );
pad->SetSubNet( curr_track->GetSubNet() );
}
}
}
// Test connections between segments
for( unsigned ii = 0; ii < curr_track->m_TracksConnected.size(); ii++ )
{
BOARD_CONNECTED_ITEM* track = curr_track->m_TracksConnected[ii];
if( curr_track->GetSubNet() ) // The current track is already a cluster member
{
// The other track is already a cluster member, so we can merge the 2 clusters
if( track->GetSubNet() )
{
Merge_SubNets( track->GetSubNet(), curr_track->GetSubNet() );
}
else
{
// The other track is not yet attached to a cluster , so we can add this
// other track to the cluster
track->SetSubNet( curr_track->GetSubNet() );
}
}
else // the current track segment is not yet attached to a cluster
{
if( track->GetSubNet() )
{
// The other track is already a cluster member, so we can add
// the current segment to the cluster
curr_track->SetSubNet( track->GetSubNet() );
}
else
{
// it is connected to an other segment not in a cluster, so we must
// create a new cluster (only with the 2 track segments)
sub_netcode++;
curr_track->SetSubNet( sub_netcode );
track->SetSubNet( curr_track->GetSubNet() );
}
}
}
if( curr_track == m_lastTrack )
break;
}
// Examine connections between intersecting pads, and propagate
// sub_netcodes to intersecting pads
for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ )
{
D_PAD* curr_pad = m_sortedPads[ii];
for( unsigned jj = 0; jj < curr_pad->m_PadsConnected.size(); jj++ )
{
D_PAD* pad = curr_pad->m_PadsConnected[jj];
if( curr_pad->GetSubNet() ) // the current pad is already attached to a cluster
{
if( pad->GetSubNet() > 0 )
{
// The pad is already a cluster member, so we can merge the 2 clusters
// Store the initial subnets, which will be modified by Merge_PadsSubNets
int subnet1 = pad->GetSubNet();
int subnet2 = curr_pad->GetSubNet();
// merge subnets of pads only, even those not connected by tracks
Merge_PadsSubNets( subnet1, subnet2 );
// merge subnets of tracks (and pads, which are already merged)
Merge_SubNets( subnet1, subnet2 );
}
else
{
// The pad is not yet attached to a cluster,
// so we can add this pad to the cluster
pad->SetSubNet( curr_pad->GetSubNet() );
}
}
else // the current pad is not attached to a cluster
{
if( pad->GetSubNet() > 0 )
{
// the connected pad is in a cluster,
// so we can add the current pad to the cluster
curr_pad->SetSubNet( pad->GetSubNet() );
}
else
{
// the connected pad is not in a cluster,
// so we must create a new cluster, with the 2 pads.
sub_netcode++;
curr_pad->SetSubNet( sub_netcode );
pad->SetSubNet( curr_pad->GetSubNet() );
}
}
}
}
}
/*
* Test all connections of the board,
* and update subnet variable of pads and tracks
* TestForActiveLinksInRatsnest must be called after this function
* to update active/inactive ratsnest items status
*/
void PCB_BASE_FRAME::TestConnections()
{
// Clear the cluster identifier for all pads
for( unsigned i = 0; i< m_Pcb->GetPadCount(); ++i )
{
D_PAD* pad = m_Pcb->GetPad(i);
pad->SetZoneSubNet( 0 );
pad->SetSubNet( 0 );
}
m_Pcb->Test_Connections_To_Copper_Areas();
// Test existing connections net by net
// note some nets can have no tracks, and pads intersecting
// so Build_CurrNet_SubNets_Connections must be called for each net
CONNECTIONS connections( m_Pcb );
int last_net_tested = 0;
int current_net_code = 0;
for( TRACK* track = m_Pcb->m_Track; track; )
{
// At this point, track is the first track of a given net
current_net_code = track->GetNetCode();
// Get last track of the current net
TRACK* lastTrack = track->GetEndNetCode( current_net_code );
if( current_net_code > 0 ) // do not spend time if net code = 0 ( dummy net )
{
// Test all previous nets having no tracks
for( int net = last_net_tested+1; net < current_net_code; net++ )
connections.Build_CurrNet_SubNets_Connections( NULL, NULL, net );
connections.Build_CurrNet_SubNets_Connections( track, lastTrack, current_net_code );
last_net_tested = current_net_code;
}
track = lastTrack->Next(); // this is now the first track of the next net
}
// Test last nets without tracks, if any
int netsCount = m_Pcb->GetNetCount();
for( int net = last_net_tested+1; net < netsCount; net++ )
connections.Build_CurrNet_SubNets_Connections( NULL, NULL, net );
Merge_SubNets_Connected_By_CopperAreas( m_Pcb );
return;
}
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;
@ -855,98 +162,5 @@ void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode )
SetStatusText( msg );
return;
}
void PCB_BASE_FRAME::ComputeLegacyConnections()
{
// Build the net info list
GetBoard()->BuildListOfNets();
// Reset variables and flags used in computation
for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() )
{
t->m_TracksConnected.clear();
t->m_PadsConnected.clear();
t->start = NULL;
t->end = NULL;
t->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, false );
t->SetZoneSubNet( 0 );
}
// If no pad, reset pointers and netcode, and do nothing else
if( m_Pcb->GetPadCount() == 0 )
return;
CONNECTIONS connections( m_Pcb );
connections.BuildPadsList();
connections.BuildTracksCandidatesList(m_Pcb->m_Track);
// First pass: build connections between track segments and pads.
connections.SearchTracksConnectedToPads();
for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() )
{
connections.SearchConnectedTracks( t );
connections.GetConnectedTracks( t );
}
// Sort the track list by net codes:
RebuildTrackChain( m_Pcb );
}
/*
* Function SortTracksByNetCode used in RebuildTrackChain()
* to sort track segments by net code.
*/
static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & compare )
{
// For items having the same Net, keep the order in list
if( ref->GetNetCode() == compare->GetNetCode())
return ref->m_Param < compare->m_Param;
return ref->GetNetCode() < compare->GetNetCode();
}
/**
* Helper function RebuildTrackChain
* rebuilds the track segment linked list in order to have a chain
* sorted by increasing netcodes.
* We try to keep order of track segments in list, when possible
* @param pcb = board to rebuild
*/
static void RebuildTrackChain( BOARD* pcb )
{
if( pcb->m_Track == NULL )
return;
int item_count = pcb->m_Track.GetCount();
std::vector<TRACK*> trackList;
trackList.reserve( item_count );
// Put track list in a temporary list to sort tracks by netcode
// We try to keep the initial order of track segments in list, when possible
// so we use m_Param (a member variable used for temporary storage)
// to temporary keep trace of the order of segments
// The sort function uses this variable to sort items that
// have the same net code.
// Without this, during sorting, the initial order is sometimes lost
// by the sort algorithm
for( int ii = 0; ii < item_count; ++ii )
{
pcb->m_Track->m_Param = ii;
trackList.push_back( pcb->m_Track.PopFront() );
}
// the list is empty now
wxASSERT( pcb->m_Track == NULL && pcb->m_Track.GetCount()==0 );
sort( trackList.begin(), trackList.end(), SortTracksByNetCode );
// add them back to the list
for( int i = 0; i < item_count; ++i )
pcb->m_Track.PushBack( trackList[i] );
#endif
}

View File

@ -34,230 +34,5 @@
#include <class_board.h>
// Helper classes to handle connection points (i.e. candidates) for tracks
/* class CONNECTED_POINT describes a coordinate having a track or pad parent.
* when a pad is the parent, the coordinate is (obviously) the connection point
* when a track is the parent, the coordinate is the staring point
* or the ending point.
* therefore when building a list of CONNECTED_POINT, a pad or via generates one item,
* and a track generates 2 items.
*/
class CONNECTED_POINT
{
private:
BOARD_CONNECTED_ITEM * m_item; // a link to the parent item (track, via or pad)
wxPoint m_point; // coordinates of this connected point
public:
// ctor to build a CONNECTED_POINT instance, when the parent is a track or via
CONNECTED_POINT( TRACK * aTrack, const wxPoint & aPoint)
{
m_item = aTrack;
m_point = aPoint;
}
// ctor to build a CONNECTED_POINT instance, when the parent is a pad
CONNECTED_POINT( D_PAD * aPad, const wxPoint & aPoint)
{
m_item = aPad;
m_point = aPoint;
}
/**
* Function GetTrack
* @return the parent track or via of this connected point,
* or null if the parent is a pad
*/
TRACK* GetTrack() const
{
return m_item->Type() != PCB_PAD_T ? (TRACK*) m_item : NULL ;
}
/**
* Function GetPad
* @return the parent pad of this connected point,
* or null if the parent is a track or via
*/
D_PAD * GetPad() const
{
return m_item->Type() == PCB_PAD_T ? (D_PAD*) m_item : NULL;
}
const wxPoint & GetPoint() const { return m_point; }
};
// A helper class to handle connections calculations:
class CONNECTIONS
{
private:
std::vector <TRACK*> m_connected; // List of connected tracks/vias
// to a given track or via
std::vector <CONNECTED_POINT> m_candidates; // List of points to test
// (end points of tracks or vias location )
BOARD * m_brd; // the master board.
const TRACK * m_firstTrack; // The first track used to build m_Candidates
const TRACK * m_lastTrack; // The last track used to build m_Candidates
std::vector<D_PAD*> m_sortedPads; // list of sorted pads by X (then Y) coordinate
public:
CONNECTIONS( BOARD * aBrd );
~CONNECTIONS() {};
/**
* Function BuildPadsList
* Fills m_sortedPads with all pads that be connected to tracks
* pads are sorted by X then Y coordinates to allow fast binary search in list
* @param aNetcode = net code to use to filter pads
* if aNetcode < 0, all pads will be put in list (default)
*/
void BuildPadsList( int aNetcode = -1 );
/**
* Function GetPadsList
* @return the pads list used in connections calculations
*/
std::vector<D_PAD*>& GetPadsList() { return m_sortedPads; }
/**
* Function Build_CurrNet_SubNets_Connections
* should be called after a track change (delete or add a track):
* Connections to pads and to tracks are recalculated
* If a track is deleted, the other pointers to pads do not change.
* When a new track is added in track list, its pointers to pads are already initialized
* Builds the subnets inside a net (tracks from aFirstTrack to aFirstTrack).
* subnets are clusters of pads and tracks that are connected together.
* When all tracks are created relative to the net, there is only a cluster
* when not tracks there are a cluster per pad
* @param aFirstTrack = first track of the given net
* @param aLastTrack = last track of the given net
* @param aNetcode = the netcode of the given net
*/
void Build_CurrNet_SubNets_Connections( TRACK* aFirstTrack, TRACK* aLastTrack, int aNetcode );
/**
* Function BuildTracksCandidatesList
* Fills m_Candidates with all connecting points (track ends or via location)
* with tracks from aBegin to aEnd.
* @param aBegin = first track to store in list (should not be NULL)
* @param aEnd = last track to store in list
* if aEnd == NULL, uses all tracks from aBegin
*/
void BuildTracksCandidatesList( TRACK * aBegin, TRACK * aEnd = NULL);
/**
* Function BuildPadsCandidatesList
* Populates m_candidates with all pads connecting points (pads position)
* m_sortedPads is expected to be populated by the pad candidates list
*/
void BuildPadsCandidatesList();
/**
* function SearchConnectedTracks
* Populates .m_connected with tracks/vias connected to aTrack
* m_candidates is expected to be populated by the track candidates ends list
* @param aTrack = track or via to use as reference
*/
int SearchConnectedTracks( const TRACK * aTrack );
/**
* Function GetConnectedTracks
* Copy m_Connected that contains the list of tracks connected
* calculated by SearchConnectedTracks
* in aTrack->m_TracksConnected
* @param aTrack = track or via to fill with connected tracks
*/
void GetConnectedTracks(TRACK * aTrack)
{
aTrack->m_TracksConnected = m_connected;
}
/**
* function SearchConnectionsPadsToIntersectingPads
* Explores the list of pads and adds to m_PadsConnected member
* of each pad pads connected to
* Here, connections are due to intersecting pads, not tracks
* m_sortedPads must be initialized
*/
void SearchConnectionsPadsToIntersectingPads();
/**
* function SearchTracksConnectedToPads
* Explores the list of pads.
* if( add_to_padlist )
* adds to m_PadsConnected member of each track the pad(s) connected to
* if add_to_tracklist
* adds to m_TracksConnected member of each pad the track(s) connected to
* D_PAD::m_TracksConnected is cleared before adding items
* TRACK::m_PadsConnected is not cleared
* @param add_to_padlist = true to fill m_PadsConnected member of each track
* @param add_to_tracklist = true to fill m_TracksConnected member of each pad
*/
void SearchTracksConnectedToPads( bool add_to_padlist = true, bool add_to_tracklist = true);
/**
* function CollectItemsNearTo
* Used by SearchTracksConnectedToPads
* Fills aList with pads near to aPosition
* near means aPosition to pad position <= aDistMax
* @param aList = list to fill
* @param aPosition = aPosition to use as reference
* @param aDistMax = dist max from aPosition to a candidate to select it
*/
void CollectItemsNearTo( std::vector<CONNECTED_POINT*>& aList,
const wxPoint& aPosition, int aDistMax );
/**
* Function Propagate_SubNets
* Test a list of tracks, to create or propagate a sub netcode to pads and
* segments connected together.
* The track list must be sorted by nets, and all segments
* from m_firstTrack to m_lastTrack have the same net.
* When 2 items are connected (a track to a pad, or a track to an other track),
* they are grouped in a cluster.
* For pads, this is the .m_physical_connexion member which is a cluster identifier
* For tracks, this is the .m_Subnet member which is a cluster identifier
* For a given net, if all tracks are created, there is only one cluster.
* but if not all tracks are created, there are more than one cluster,
* and some ratsnests will be left active.
*/
void Propagate_SubNets();
private:
/**
* function searchEntryPointInCandidatesList
* Search an item in m_Connected connected to aPoint
* note m_Connected containts usually more than one candidate
* and searchEntryPointInCandidatesList returns an index to one of these candidates
* Others are neightbor of the indexed item.
* @param aPoint is the reference coordinates
* @return the index of item found or -1 if no candidate
*/
int searchEntryPointInCandidatesList( const wxPoint & aPoint);
/**
* Function Merge_SubNets
* Change a subnet old value to a new value, for tracks and pads which are connected to
* tracks from m_firstTrack to m_lastTrack and their connected pads.
* and modify the subnet parameter (change the old value to the new value).
* After that, 2 cluster (or subnets) are merged into only one.
* Note: the resulting sub net value is the smallest between aOldSubNet and aNewSubNet
* @return modification count
* @param aOldSubNet = subnet value to modify
* @param aNewSubNet = new subnet value for each item which have old_val as subnet value
*/
int Merge_SubNets( int aOldSubNet, int aNewSubNet );
/**
* Function Merge_PadsSubNets
* Change a subnet value to a new value, in m_sortedPads pad list
* After that, 2 cluster (or subnets) are merged into only one.
* Note: the resulting subnet value is the smallest between aOldSubNet et aNewSubNet
* @return modification count
* @param aOldSubNet = subnet value to modify
* @param aNewSubNet = new subnet value for each item which have old_val as subnet value
*/
int Merge_PadsSubNets( int aOldSubNet, int aNewSubNet );
};
#endif // ifndef CONNECT_H

View File

@ -21,8 +21,6 @@
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define PROFILE
#ifdef PROFILE
#include <profile.h>
#endif
@ -127,7 +125,6 @@ void CONNECTIVITY_DATA::updateRatsnest()
#ifdef PROFILE
rnUpdate.Show();
#endif /* PROFILE */
printf( "Dirty: %d\n", nDirty );
}
@ -165,6 +162,7 @@ void CONNECTIVITY_DATA::RecalculateRatsnest()
for( auto c : clusters )
{
int net = c->OriginNet();
@ -181,7 +179,7 @@ void CONNECTIVITY_DATA::RecalculateRatsnest()
}
void CONNECTIVITY_DATA::blockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems )
void CONNECTIVITY_DATA::BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems )
{
std::vector<BOARD_CONNECTED_ITEM*> citems;
@ -231,7 +229,7 @@ void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector<BOARD_ITEM*>&
m_dynamicRatsnest.clear();
blockRatsnestItems( aItems );
BlockRatsnestItems( aItems );
for( unsigned int nc = 1; nc < m_dynamicConnectivity->m_nets.size(); nc++ )
{
@ -333,45 +331,182 @@ const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetConnectedItems(
const KICAD_T aTypes[] ) const
{
std::list<BOARD_CONNECTED_ITEM*> rv;
const auto clusters = m_connAlgo->SearchClusters( CN_CONNECTIVITY_ALGO::CSM_CONNECTIVITY_CHECK, aTypes, aItem->GetNetCode() );
const auto clusters = m_connAlgo->SearchClusters( CN_CONNECTIVITY_ALGO::CSM_CONNECTIVITY_CHECK,
aTypes, aItem->GetNetCode() );
for ( auto cl : clusters )
if ( cl->Contains (aItem ) )
for( auto cl : clusters )
if( cl->Contains( aItem ) )
{
for ( const auto item : *cl )
for( const auto item : *cl )
rv.push_back( item->Parent() );
}
return rv;
}
const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetNetItems(
int aNetCode,
const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetNetItems( int aNetCode,
const KICAD_T aTypes[] ) const
{
}
bool CONNECTIVITY_DATA::CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport )
{
RecalculateRatsnest();
for ( auto net : m_nets )
for( auto net : m_nets )
{
if ( net )
if( net )
{
for ( const auto& edge: net->GetEdges() )
for( const auto& edge : net->GetEdges() )
{
CN_DISJOINT_NET_ENTRY ent;
ent.net = edge.GetSourceNode()->Parent()->GetNetCode();
ent.a = edge.GetSourceNode()->Parent();
ent.b = edge.GetTargetNode()->Parent();
ent.a = edge.GetSourceNode()->Parent();
ent.b = edge.GetTargetNode()->Parent();
ent.anchorA = edge.GetSourceNode()->Pos();
ent.anchorB = edge.GetTargetNode()->Pos();
aReport.push_back( ent );
}
}
}
return aReport.empty();
}
const std::vector<TRACK*> CONNECTIVITY_DATA::GetConnectedTracks( const BOARD_CONNECTED_ITEM* aItem )
const
{
auto& entry = m_connAlgo->ItemEntry( aItem );
std::set<TRACK*> tracks;
std::vector<TRACK*> rv;
for( auto citem : entry.GetItems() )
{
for( auto connected : citem->ConnectedItems() )
{
if( connected->Parent()->Type() == PCB_TRACE_T )
tracks.insert( static_cast<TRACK*> ( connected->Parent() ) );
}
}
std::copy( tracks.begin(), tracks.end(), std::back_inserter( rv ) );
return rv;
}
const std::vector<D_PAD*> CONNECTIVITY_DATA::GetConnectedPads( const BOARD_CONNECTED_ITEM* aItem )
const
{
auto& entry = m_connAlgo->ItemEntry( aItem );
std::set<D_PAD*> pads;
std::vector<D_PAD*> rv;
for( auto citem : entry.GetItems() )
{
for( auto connected : citem->ConnectedItems() )
{
if( connected->Parent()->Type() == PCB_PAD_T )
pads.insert( static_cast<D_PAD*> ( connected->Parent() ) );
}
}
std::copy( pads.begin(), pads.end(), std::back_inserter( rv ) );
return rv;
}
unsigned int CONNECTIVITY_DATA::GetLinksCount() const
{
return 0;
assert( false );
}
unsigned int CONNECTIVITY_DATA::GetConnectedCount() const
{
return 0;
assert( false );
}
unsigned int CONNECTIVITY_DATA::GetNodeCount( int aNet ) const
{
return 0;
assert( false );
}
unsigned int CONNECTIVITY_DATA::GetPadCount( int aNet ) const
{
return 0;
assert( false );
}
const std::vector<VECTOR2I> CONNECTIVITY_DATA::NearestUnconnectedTargets(
const BOARD_CONNECTED_ITEM* aRef,
const VECTOR2I& aPos,
int aNet )
{
CN_CLUSTER_PTR refCluster;
int refNet = -1;
if( aRef )
refNet = aRef->GetNetCode();
if( aNet >= 0 )
refNet = aNet;
if( aRef )
{
for( auto cl : m_connAlgo->GetClusters() )
{
if( cl->Contains( aRef ) )
{
refCluster = cl;
break;
}
}
}
std::set <VECTOR2I> anchors;
for( auto cl : m_connAlgo->GetClusters() )
{
if( cl != refCluster )
{
for( auto item : *cl )
{
if( item->Parent()->GetNetCode() == refNet
&& item->Parent()->Type() != PCB_ZONE_AREA_T )
for( auto anchor : item->Anchors() )
{
anchors.insert( anchor->Pos() );
}
}
}
}
std::vector<VECTOR2I> rv;
std::copy( anchors.begin(), anchors.end(), std::back_inserter( rv ) );
std::sort( rv.begin(), rv.end(), [aPos] ( const VECTOR2I& a, const VECTOR2I& b )
{
auto da = (a - aPos).EuclideanNorm();
auto db = (b - aPos).EuclideanNorm();
return da < db;
} );
return rv;
}

View File

@ -44,6 +44,8 @@ class BOARD_ITEM;
class ZONE_CONTAINER;
class RN_DATA;
class RN_NET;
class TRACK;
class D_PAD;
struct CN_DISJOINT_NET_ENTRY
{
@ -130,7 +132,7 @@ public:
*/
void PropagateNets();
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport );
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport );
/**
* Function FindIsolatedCopperIslands()
@ -152,6 +154,18 @@ public:
*/
unsigned int GetUnconnectedCount() const;
unsigned int GetLinksCount() const;
unsigned int GetConnectedCount() const;
unsigned int GetNodeCount( int aNet = -1 ) const;
unsigned int GetPadCount( int aNet = -1 ) const;
const std::vector<TRACK*> GetConnectedTracks( const BOARD_CONNECTED_ITEM* aItem ) const;
const std::vector<D_PAD*> GetConnectedPads( const BOARD_CONNECTED_ITEM* aItem ) const;
/**
* Function ClearDynamicRatsnest()
@ -188,11 +202,16 @@ public:
const std::list<BOARD_CONNECTED_ITEM*> GetNetItems( int aNetCode,
const KICAD_T aTypes[] ) const;
const std::vector<VECTOR2I> NearestUnconnectedTargets( const BOARD_CONNECTED_ITEM* aRef,
const VECTOR2I& aPos,
int aMaxCount = -1 );
void BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems );
private:
void updateRatsnest();
void addRatsnestCluster( std::shared_ptr<CN_CLUSTER> aCluster );
void blockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems );
std::unique_ptr<CONNECTIVITY_DATA> m_dynamicConnectivity;
std::shared_ptr<CN_CONNECTIVITY_ALGO> m_connAlgo;

View File

@ -160,10 +160,31 @@ public:
void SetTargetNode( const CN_ANCHOR_PTR& aNode ) { m_target = aNode; }
void SetWeight( unsigned int weight ) { m_weight = weight; }
void SetVisible( bool aVisible )
{
m_visible = aVisible;
}
bool IsVisible() const
{
return m_visible;
}
const VECTOR2I GetSourcePos() const
{
return m_source->Pos();
}
const VECTOR2I GetTargetPos() const
{
return m_target->Pos();
}
private:
CN_ANCHOR_PTR m_source;
CN_ANCHOR_PTR m_target;
unsigned int m_weight = 0;
bool m_visible = true;
};
class CN_CLUSTER

View File

@ -238,10 +238,6 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
if( gen_rastnest )
m_Parent->Compile_Ratsnest( NULL, true );
// There is a chance that some of tracks have changed their nets, so rebuild ratsnest from scratch
if( m_Parent->IsGalCanvasActive() )
pcb->GetRatsnest()->ProcessBoard();
else
m_Parent->GetCanvas()->Refresh();
// There is a chance that some of tracks have changed their nets, so rebuild ratsnest from scratch
m_Parent->GetCanvas()->Refresh();
}

View File

@ -42,6 +42,7 @@
#include <view/view.h>
#include <view/view_controls.h>
#include <pcb_painter.h>
#include <connectivity.h>
#define COL_NETNAME 0
#define COL_NETINFO 1
@ -141,7 +142,9 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
continue;
}
if( !m_cbShowZeroPad->IsChecked() && net->m_PadInNetList.size() == 0 )
unsigned nPads = m_brd->GetConnectivity()->GetPadCount( netcode );
if( !m_cbShowZeroPad->IsChecked() && nPads == 0 )
continue;
if( m_netsListGrid->GetNumberRows() <= row_idx )
@ -154,7 +157,7 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
if( netcode )
{
txt.Printf( wxT( "%u" ), (unsigned) net->m_PadInNetList.size() );
txt.Printf( wxT( "%u" ), nPads );
m_netsListGrid->SetCellValue( row_idx, COL_NETINFO, txt );
}
else // For the net 0 (unconnected pads), the pad count is not known

View File

@ -150,7 +150,7 @@ private:
/** Fills m_DragList with of track segments connected to pads in aConnections
* For each selected track segment the EDIT flag is set
*/
void fillList( CONNECTIONS& aConnections );
void fillList( std::vector<D_PAD*>& aList );
};

View File

@ -41,8 +41,7 @@
#include <class_module.h>
#include <class_board.h>
#include <connect.h>
#include <connectivity.h>
/* a list of DRAG_SEGM_PICKER items used to move or drag tracks */
std::vector<DRAG_SEGM_PICKER> g_DragSegmentList;
@ -61,7 +60,6 @@ DRAG_SEGM_PICKER::DRAG_SEGM_PICKER( TRACK* aTrack )
m_Flipped = false;
}
void DRAG_SEGM_PICKER::SetAuxParameters()
{
MODULE* module = NULL;
@ -155,16 +153,14 @@ void DRAG_LIST::BuildDragListe( MODULE* aModule )
m_Pad = NULL;
m_Module = aModule;
// Build connections info
CONNECTIONS connections( m_Brd );
std::vector<D_PAD*>&padList = connections.GetPadsList();
std::vector<D_PAD*> padList;
for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
for ( auto pad : aModule->PadsIter() )
padList.push_back( pad );
sort( padList.begin(), padList.end(), sortPadsByXthenYCoord );
fillList( connections );
fillList( padList );
}
@ -174,11 +170,10 @@ void DRAG_LIST::BuildDragListe( D_PAD* aPad )
m_Module = NULL;
// Build connections info
CONNECTIONS connections( m_Brd );
std::vector<D_PAD*>&padList = connections.GetPadsList();
std::vector<D_PAD*> padList;
padList.push_back( aPad );
fillList( connections );
fillList( padList );
}
@ -188,26 +183,18 @@ bool sort_tracklist( const DRAG_SEGM_PICKER& ref, const DRAG_SEGM_PICKER& tst )
return ref.m_Track < tst.m_Track;
}
void DRAG_LIST::fillList( CONNECTIONS& aConnections )
void DRAG_LIST::fillList( std::vector<D_PAD*>& aList )
{
aConnections.BuildTracksCandidatesList( m_Brd->m_Track, NULL);
// Build connections info tracks to pads
// Rebuild pads to track info only)
aConnections.SearchTracksConnectedToPads( false, true );
std::vector<D_PAD*>padList = aConnections.GetPadsList();
printf("FillList!\n");
// clear flags and variables of selected tracks
for( unsigned ii = 0; ii < padList.size(); ii++ )
for( auto pad : aList )
{
D_PAD * pad = padList[ii];
auto connectedTracks = m_Brd->GetConnectivity()->GetConnectedTracks( pad );
// store track connected to the pad
for( unsigned jj = 0; jj < pad->m_TracksConnected.size(); jj++ )
for ( auto track : connectedTracks )
{
TRACK * track = pad->m_TracksConnected[jj];
track->start = NULL;
track->end = NULL;
track->SetState( START_ON_PAD|END_ON_PAD|BUSY, false );
@ -215,14 +202,13 @@ void DRAG_LIST::fillList( CONNECTIONS& aConnections )
}
// store tracks connected to pads
for( unsigned ii = 0; ii < padList.size(); ii++ )
for( auto pad : aList )
{
D_PAD * pad = padList[ii];
auto connectedTracks = m_Brd->GetConnectivity()->GetConnectedTracks( pad );
// store track connected to the pad
for( unsigned jj = 0; jj < pad->m_TracksConnected.size(); jj++ )
for ( auto track : connectedTracks )
{
TRACK * track = pad->m_TracksConnected[jj];
if( pad->HitTest( track->GetStart() ) )
{

View File

@ -196,19 +196,6 @@ void DRC::RunTests( wxTextCtrl* aMessages )
// ( the board can be reloaded )
m_pcb = m_pcbEditorFrame->GetBoard();
// Ensure ratsnest is up to date:
if( (m_pcb->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 )
{
if( aMessages )
{
aMessages->AppendText( _( "Compile ratsnest...\n" ) );
wxSafeYield();
}
m_pcbEditorFrame->Compile_Ratsnest( NULL, true );
//m_pcb->GetRatsnest()->ProcessBoard();
}
// someone should have cleared the two lists before calling this.
if( !testNetClasses() )
@ -636,7 +623,7 @@ void DRC::testZones()
// perhaps a "dead" net, which happens when all pads in this net were removed
// Remark: a netcode < 0 should not happen (this is more a bug somewhere)
int pads_in_net = (test_area->GetNetCode() > 0) ?
test_area->GetNet()->GetNodesCount() : 1;
m_pcb->GetConnectivity()->GetPadCount( test_area->GetNetCode() ) : 1;
if( ( netcode < 0 ) || pads_in_net == 0 )
{

View File

@ -663,8 +663,6 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
}
SetCurItem( NULL ); // CurItem might be deleted by this command, clear the pointer
TestConnections();
TestForActiveLinksInRatsnest( 0 ); // Recalculate the active ratsnest, i.e. the unconnected links
OnModify();
SetMsgPanel( GetBoard() );
m_canvas->Refresh();
@ -673,7 +671,6 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_PCB_FILL_ZONE:
m_canvas->MoveCursorToCrossHair();
Fill_Zone( (ZONE_CONTAINER*) GetCurItem() );
TestNetConnection( NULL, ( (ZONE_CONTAINER*) GetCurItem() )->GetNetCode() );
SetMsgPanel( GetBoard() );
m_canvas->Refresh();
break;
@ -1449,11 +1446,7 @@ void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent )
SetToolID( id, wxCURSOR_PENCIL, _( "Add tracks" ) );
else
SetToolID( id, wxCURSOR_QUESTION_ARROW, _( "Add tracks" ) );
if( (GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 )
{
Compile_Ratsnest( &dc, true );
}
break;
@ -1523,8 +1516,7 @@ void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent )
case ID_PCB_SHOW_1_RATSNEST_BUTT:
SetToolID( id, wxCURSOR_HAND, _( "Select rats nest" ) );
if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 )
Compile_Ratsnest( &dc, true );
Compile_Ratsnest( &dc, true );
break;

View File

@ -227,9 +227,9 @@ void PCB_EDIT_FRAME::Show_1_Ratsnest( EDA_ITEM* item, wxDC* DC )
if( GetBoard()->IsElementVisible( LAYER_RATSNEST ) )
return;
if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 )
Compile_Ratsnest( DC, true );
Compile_Ratsnest( DC, true );
#if 0
if( item )
{
if( item->Type() == PCB_PAD_T )
@ -311,4 +311,5 @@ void PCB_EDIT_FRAME::Show_1_Ratsnest( EDA_ITEM* item, wxDC* DC )
for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
GetBoard()->m_FullRatsnest[ii].m_Status &= ~CH_VISIBLE;
}
#endif
}

View File

@ -41,6 +41,7 @@
#include <class_board.h>
#include <class_track.h>
#include <class_zone.h>
#include <connectivity.h>
static void Abort_Create_Track( EDA_DRAW_PANEL* panel, wxDC* DC );
@ -158,7 +159,11 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC )
DBG( g_CurrentTrackList.VerifyListIntegrity() );
BuildAirWiresTargetsList( lockPoint, wxPoint( 0, 0 ), true );
int net = -1;
if (lockPoint)
net = lockPoint->GetNetCode();
BuildAirWiresTargetsList( lockPoint, wxPoint( 0, 0 ), net );
DBG( g_CurrentTrackList.VerifyListIntegrity() );
@ -183,7 +188,6 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC )
if( pad )
{
g_CurrentTrackSegment->m_PadsConnected.push_back( pad );
// Useful to display track length, if the pad has a die length:
g_CurrentTrackSegment->SetState( BEGIN_ONPAD, true );
g_CurrentTrackSegment->start = pad;
@ -268,12 +272,6 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC )
D_PAD* pad = GetBoard()->GetPad( previousTrack, ENDPOINT_END );
if( pad )
{
newTrack->m_PadsConnected.push_back( pad );
previousTrack->m_PadsConnected.push_back( pad );
}
newTrack->start = previousTrack->end;
DBG( g_CurrentTrackList.VerifyListIntegrity(); );
@ -489,6 +487,7 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC )
ITEM_PICKER picker( track, UR_NEW );
s_ItemsListPicker.PushItem( picker );
GetBoard()->m_Track.Insert( track, insertBeforeMe );
GetBoard()->GetConnectivity()->Add( track );
}
TraceAirWiresToTargets( aDC );
@ -534,6 +533,8 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC )
m_canvas->SetMouseCapture( NULL, NULL );
SetCurItem( NULL );
GetBoard()->GetConnectivity()->RecalculateRatsnest();
return true;
}
@ -825,7 +826,7 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo
displ_opts->m_ShowTrackClearanceMode = showTrackClearanceMode;
displ_opts->m_DisplayPcbTrackFill = tmp;
frame->BuildAirWiresTargetsList( NULL, g_CurrentTrackSegment->GetEnd(), false );
frame->BuildAirWiresTargetsList( NULL, g_CurrentTrackSegment->GetEnd(), g_CurrentTrackSegment->GetNetCode() );
frame->TraceAirWiresToTargets( aDC );
}

View File

@ -701,8 +701,6 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
backupFileName = create_backup_file( aFileName );
}
GetBoard()->m_Status_Pcb &= ~CONNEXION_OK;
GetBoard()->SynchronizeNetsAndNetClasses();
// Select default Netclass before writing file.
@ -787,7 +785,6 @@ bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName )
return false;
}
GetBoard()->m_Status_Pcb &= ~CONNEXION_OK;
GetBoard()->SynchronizeNetsAndNetClasses();
// Select default Netclass before writing file.

Some files were not shown because too many files have changed in this diff Show More