Loading pcbnew/class_track.h +1 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ protected: public: BOARD_ITEM* start; // pointers to a connected item (pad or track) BOARD_ITEM* end; std::vector<TRACK*> m_TracksConnected; // list of other tracks connected to me int m_Param; // Auxiliary variable ( used in some computations ) Loading pcbnew/connect.cpp +95 −195 Original line number Diff line number Diff line Loading @@ -3,6 +3,30 @@ * @brief Functions to handle existing tracks in ratsnest calculations. */ /* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2011 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 "fctsys.h" #include "common.h" #include "pcbcommon.h" Loading Loading @@ -38,7 +62,7 @@ public: } }; // A helper class to handle connection calculations: // A helper class to handle connections calculations: class CONNECTIONS { public: Loading Loading @@ -690,28 +714,22 @@ static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* void PCB_BASE_FRAME::RecalculateAllTracksNetcode() { TRACK* pt_trace; TRACK* pt_next; char new_passe_request = 1; TRACK* curr_track; std::vector<D_PAD*> sortedPads; BOARD_ITEM* PtStruct; int layerMask; wxString msg; // Build the net info list GetBoard()->m_NetInfo->BuildListOfNets(); if( m_Pcb->GetPadsCount() == 0 ) // If no pad, reset pointers and netcode, and do nothing else { pt_trace = m_Pcb->m_Track; curr_track = m_Pcb->m_Track; for( ; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( ; curr_track != NULL; curr_track = curr_track->Next() ) { pt_trace->start = NULL; pt_trace->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); pt_trace->SetNet( 0 ); pt_trace->end = NULL; curr_track->start = NULL; curr_track->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); curr_track->SetNet( 0 ); curr_track->end = NULL; } return; Loading @@ -724,40 +742,41 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() m_Pcb->GetSortedPadListByXthenYCoord( sortedPads ); /* Reset variables and flags used in computation */ pt_trace = m_Pcb->m_Track; curr_track = m_Pcb->m_Track; for( ; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( ; curr_track != NULL; curr_track = curr_track->Next() ) { pt_trace->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF ); pt_trace->SetZoneSubNet( 0 ); pt_trace->SetNet( 0 ); // net code = 0 means not connected curr_track->m_TracksConnected.clear(); curr_track->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF ); curr_track->SetZoneSubNet( 0 ); curr_track->SetNet( 0 ); // net code = 0 means not connected } /* First pass: search connection between a track segment and a pad. * if found, set the track net code to the pad netcode */ pt_trace = m_Pcb->m_Track; curr_track = m_Pcb->m_Track; for( ; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( ; curr_track != NULL; curr_track = curr_track->Next() ) { layerMask = g_TabOneLayerMask[pt_trace->GetLayer()]; int layerMask = g_TabOneLayerMask[curr_track->GetLayer()]; /* Search for a pad on the segment starting point */ pt_trace->start = m_Pcb->GetPad( sortedPads, pt_trace->m_Start, layerMask ); curr_track->start = m_Pcb->GetPad( sortedPads, curr_track->m_Start, layerMask ); if( pt_trace->start != NULL ) if( curr_track->start != NULL ) { pt_trace->SetState( BEGIN_ONPAD, ON ); pt_trace->SetNet( ( (D_PAD*) (pt_trace->start) )->GetNet() ); curr_track->SetState( BEGIN_ONPAD, ON ); curr_track->SetNet( ( (D_PAD*) (curr_track->start) )->GetNet() ); } /* Search for a pad on the segment ending point */ pt_trace->end = m_Pcb->GetPad( sortedPads, pt_trace->m_End, layerMask ); curr_track->end = m_Pcb->GetPad( sortedPads, curr_track->m_End, layerMask ); if( pt_trace->end != NULL ) if( curr_track->end != NULL ) { pt_trace->SetState( END_ONPAD, ON ); pt_trace->SetNet( ( (D_PAD*) (pt_trace->end) )->GetNet() ); curr_track->SetState( END_ONPAD, ON ); curr_track->SetNet( ( (D_PAD*) (curr_track->end) )->GetNet() ); } } Loading @@ -765,166 +784,57 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() /* Pass 2: search the connections between track ends */ /*****************************************************/ /* the .start and .end member pointers are updated, only if NULLs * (if not null, the end is already connected to a pad). * the connection (if found) is between segments * when a track has a net code and the other has a null net code, the null net code is changed /* the .start and .end member pointers are updated, and point on connected pads * or are null for tracks whitch are not connection to pads * Now build connections lists to tracks */ #if 0 for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { if( pt_trace->start == NULL ) { pt_trace->start = pt_trace->GetTrace( m_Pcb->m_Track, NULL, START ); } if( pt_trace->end == NULL ) { pt_trace->end = pt_trace->GetTrace( m_Pcb->m_Track, NULL, END ); } } #else CONNECTIONS connections( m_Pcb ); connections.BuildCandidatesList(); for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { if( pt_trace->start != NULL && pt_trace->end != NULL ) continue; connections.SearchConnectedTracks( pt_trace ); for( unsigned ii = 0; ii < connections.m_Connected.size(); ii ++ ) for( curr_track = m_Pcb->m_Track; curr_track != NULL; curr_track = curr_track->Next() ) { TRACK * candidate = connections.m_Connected[ii]; // Do not create a link to an other track already linked // to avoid loops when we have 4 and more ends at the same location // like this case for 4 tracks named A, B, C ,D: // A links B; B links A and C links D; D links C, but never C or D links A or B // Try to find a not already linked track: if( candidate->start == pt_trace || candidate->end == pt_trace ) if( curr_track->start != NULL && curr_track->end != NULL ) continue; // A link is found: if( pt_trace->start == NULL ) { if( ( pt_trace->m_Start == candidate->m_Start ) || ( pt_trace->m_Start == candidate->m_End ) ) pt_trace->start = candidate; connections.SearchConnectedTracks( curr_track ); curr_track->m_TracksConnected = connections.m_Connected; } if( pt_trace->end == NULL ) { if( ( pt_trace->m_End == candidate->m_Start ) || ( pt_trace->m_End == candidate->m_End ) ) pt_trace->end = candidate; } } } #endif /**********************************************************/ /* Propagate net codes from a segment to an other segment */ /**********************************************************/ while( new_passe_request ) // Propagate net codes from a segment to other connected segments bool new_pass_request = true; // is true if a track has its netcode changes from 0 // to a known netcode to re-evaluate netcodes // of connected items while( new_pass_request ) { bool reset_flag = false; new_passe_request = 0; new_pass_request = false; /* look for vias which could be connect many tracks */ for( TRACK* via = m_Pcb->m_Track; via != NULL; via = via->Next() ) for( curr_track = m_Pcb->m_Track; curr_track; curr_track = curr_track->Next() ) { if( via->Type() != PCB_VIA_T ) continue; if( via->GetNet() > 0 ) continue; // Netcode already known // Lock for a connection to a track with a known netcode pt_next = m_Pcb->m_Track; while( ( pt_next = via->GetTrace( pt_next, NULL, START ) ) != NULL ) int netcode = curr_track->GetNet(); if( netcode == 0 ) { // try to find a connected item having a netcode for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ ) { if( pt_next->GetNet() ) int altnetcode = curr_track->m_TracksConnected[kk]->GetNet(); if( altnetcode ) { via->SetNet( pt_next->GetNet() ); new_pass_request = true; netcode = altnetcode; curr_track->SetNet(netcode); break; } pt_next->SetState( BUSY, ON ); reset_flag = true; } } if( reset_flag ) { for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { pt_trace->SetState( BUSY, OFF ); } } /* set the netcode of connected tracks: if at track is connected to a pad, its net * code is already set. * if the current track is connected to an other track: * if a track has a net code, it is used for the other track. * Thus there is a propagation of the netcode from a track to an other. * if none of the 2 track has a net code we do nothing * the iteration is stopped when no new change occurs */ for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { /* look for the connection to the current segment starting point */ PtStruct = (BOARD_ITEM*) pt_trace->start; if( PtStruct && (PtStruct->Type() != PCB_PAD_T) ) { // Begin on an other track segment pt_next = (TRACK*) PtStruct; if( pt_trace->GetNet() ) { if( pt_next->GetNet() == 0 ) { // the current track has a netcode, we use it for the other track // A change is made: a new iteration is requested. new_passe_request = 1; pt_next->SetNet( pt_trace->GetNet() ); } } else if( netcode ) // this track has a netcode { // propagate this netcode to connected tracks having no netcode for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ ) { if( pt_next->GetNet() != 0 ) int altnetcode = curr_track->m_TracksConnected[kk]->GetNet(); if( altnetcode == 0 ) { // the other track has a netcode, we use it for the current track pt_trace->SetNet( pt_next->GetNet() ); new_passe_request = 1; } } } /* look for the connection to the current segment ending point */ PtStruct = pt_trace->end; if( PtStruct && (PtStruct->Type() != PCB_PAD_T) ) { pt_next = (TRACK*) PtStruct; // End on an other track: propagate netcode if possible if( pt_trace->GetNet() ) { if( pt_next->GetNet() == 0 ) { new_passe_request = 1; pt_next->SetNet( pt_trace->GetNet() ); } } else { if( pt_next->GetNet() != 0 ) { pt_trace->SetNet( pt_next->GetNet() ); new_passe_request = 1; curr_track->m_TracksConnected[kk]->SetNet(netcode); new_pass_request = true; } } } Loading @@ -936,22 +846,16 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } /** * Function Sort_By_NetCode * sorts track segments used in RebuildTrackChain() (for the qsort C function) * The sorting is made by net code. /* * Function SortTracksByNetCode used in RebuildTrackChain() * to sort track segments by net code. */ static int Sort_By_NetCode( const void* left, const void* right ) static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & compare ) { TRACK* pt_ref = *(TRACK**) left; TRACK* pt_compare = *(TRACK**) right; int ret = pt_ref->GetNet() - pt_compare->GetNet(); return ret; return ref->GetNet() < compare->GetNet(); } /** * Function RebuildTrackChain * rebuilds the track segment linked list in order to have a chain Loading @@ -963,26 +867,22 @@ static void RebuildTrackChain( BOARD* pcb ) if( pcb->m_Track == NULL ) return; int nbsegm = pcb->m_Track.GetCount(); int item_count = pcb->m_Track.GetCount(); TRACK** array = (TRACK**) MyZMalloc( nbsegm * sizeof(TRACK*) ); std::vector<TRACK*> trackList; trackList.reserve( item_count ); for( int i = 0; i<nbsegm; ++i ) { array[i] = pcb->m_Track.PopFront(); wxASSERT( array[i] ); } for( int i = 0; i<item_count; ++i ) trackList.push_back( pcb->m_Track.PopFront() ); // the list is empty now wxASSERT( pcb->m_Track == NULL && pcb->m_Track.GetCount()==0 ); qsort( array, nbsegm, sizeof(TRACK*), Sort_By_NetCode ); sort( trackList.begin(), trackList.end(), SortTracksByNetCode ); // add them back to the list for( int i = 0; i<nbsegm; ++i ) for( int i = 0; i < item_count; ++i ) { pcb->m_Track.PushBack( array[i] ); pcb->m_Track.PushBack( trackList[i] ); } MyFree( array ); } pcbnew/dialogs/dialog_drc.cpp +28 −7 Original line number Diff line number Diff line ///////////////////////////////////////////////////////////////////////////// // Name: dialog_drc.cpp // Author: jean-pierre Charras // Licence: GPL ///////////////////////////////////////////////////////////////////////////// /** * @file dialog_drc.cpp */ /* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2011 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 "fctsys.h" #include "dialog_drc.h" Loading Loading @@ -153,7 +173,8 @@ void DIALOG_DRC_CONTROL::OnStartdrcClick( wxCommandEvent& event ) // run all the tests, with no UI at this time. m_Messages->Clear(); wxSafeYield(); // Allows time slice to refresh the m_Messages window m_Messages->Refresh(); wxYield(); // Allows time slice to refresh the m_Messages window m_tester->m_pcb->m_Status_Pcb = 0; // Force full connectivity and ratsnest recalculations m_tester->RunTests(m_Messages); Loading pcbnew/drc.cpp +6 −7 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Compile ratsnest...\n" ) ); wxSafeYield(); aMessages->Refresh(); } m_mainWindow->Compile_Ratsnest( NULL, true ); Loading Loading @@ -209,7 +209,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Pad clearances...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testPad2Pad(); Loading @@ -219,9 +219,8 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Track clearances...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testTracks(); // Before testing segments and unconnected, refill all zones: Loading @@ -229,7 +228,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Fill zones...\n" ) ); wxSafeYield(); aMessages->Refresh(); } m_mainWindow->Fill_All_Zones( false ); Loading @@ -238,7 +237,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages && m_doZonesTest ) { aMessages->AppendText( _( "Test zones...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testZones( m_doZonesTest ); Loading @@ -249,7 +248,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Unconnected pads...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testUnconnected(); Loading Loading
pcbnew/class_track.h +1 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ protected: public: BOARD_ITEM* start; // pointers to a connected item (pad or track) BOARD_ITEM* end; std::vector<TRACK*> m_TracksConnected; // list of other tracks connected to me int m_Param; // Auxiliary variable ( used in some computations ) Loading
pcbnew/connect.cpp +95 −195 Original line number Diff line number Diff line Loading @@ -3,6 +3,30 @@ * @brief Functions to handle existing tracks in ratsnest calculations. */ /* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2011 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 "fctsys.h" #include "common.h" #include "pcbcommon.h" Loading Loading @@ -38,7 +62,7 @@ public: } }; // A helper class to handle connection calculations: // A helper class to handle connections calculations: class CONNECTIONS { public: Loading Loading @@ -690,28 +714,22 @@ static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* void PCB_BASE_FRAME::RecalculateAllTracksNetcode() { TRACK* pt_trace; TRACK* pt_next; char new_passe_request = 1; TRACK* curr_track; std::vector<D_PAD*> sortedPads; BOARD_ITEM* PtStruct; int layerMask; wxString msg; // Build the net info list GetBoard()->m_NetInfo->BuildListOfNets(); if( m_Pcb->GetPadsCount() == 0 ) // If no pad, reset pointers and netcode, and do nothing else { pt_trace = m_Pcb->m_Track; curr_track = m_Pcb->m_Track; for( ; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( ; curr_track != NULL; curr_track = curr_track->Next() ) { pt_trace->start = NULL; pt_trace->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); pt_trace->SetNet( 0 ); pt_trace->end = NULL; curr_track->start = NULL; curr_track->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); curr_track->SetNet( 0 ); curr_track->end = NULL; } return; Loading @@ -724,40 +742,41 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() m_Pcb->GetSortedPadListByXthenYCoord( sortedPads ); /* Reset variables and flags used in computation */ pt_trace = m_Pcb->m_Track; curr_track = m_Pcb->m_Track; for( ; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( ; curr_track != NULL; curr_track = curr_track->Next() ) { pt_trace->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF ); pt_trace->SetZoneSubNet( 0 ); pt_trace->SetNet( 0 ); // net code = 0 means not connected curr_track->m_TracksConnected.clear(); curr_track->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF ); curr_track->SetZoneSubNet( 0 ); curr_track->SetNet( 0 ); // net code = 0 means not connected } /* First pass: search connection between a track segment and a pad. * if found, set the track net code to the pad netcode */ pt_trace = m_Pcb->m_Track; curr_track = m_Pcb->m_Track; for( ; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( ; curr_track != NULL; curr_track = curr_track->Next() ) { layerMask = g_TabOneLayerMask[pt_trace->GetLayer()]; int layerMask = g_TabOneLayerMask[curr_track->GetLayer()]; /* Search for a pad on the segment starting point */ pt_trace->start = m_Pcb->GetPad( sortedPads, pt_trace->m_Start, layerMask ); curr_track->start = m_Pcb->GetPad( sortedPads, curr_track->m_Start, layerMask ); if( pt_trace->start != NULL ) if( curr_track->start != NULL ) { pt_trace->SetState( BEGIN_ONPAD, ON ); pt_trace->SetNet( ( (D_PAD*) (pt_trace->start) )->GetNet() ); curr_track->SetState( BEGIN_ONPAD, ON ); curr_track->SetNet( ( (D_PAD*) (curr_track->start) )->GetNet() ); } /* Search for a pad on the segment ending point */ pt_trace->end = m_Pcb->GetPad( sortedPads, pt_trace->m_End, layerMask ); curr_track->end = m_Pcb->GetPad( sortedPads, curr_track->m_End, layerMask ); if( pt_trace->end != NULL ) if( curr_track->end != NULL ) { pt_trace->SetState( END_ONPAD, ON ); pt_trace->SetNet( ( (D_PAD*) (pt_trace->end) )->GetNet() ); curr_track->SetState( END_ONPAD, ON ); curr_track->SetNet( ( (D_PAD*) (curr_track->end) )->GetNet() ); } } Loading @@ -765,166 +784,57 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() /* Pass 2: search the connections between track ends */ /*****************************************************/ /* the .start and .end member pointers are updated, only if NULLs * (if not null, the end is already connected to a pad). * the connection (if found) is between segments * when a track has a net code and the other has a null net code, the null net code is changed /* the .start and .end member pointers are updated, and point on connected pads * or are null for tracks whitch are not connection to pads * Now build connections lists to tracks */ #if 0 for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { if( pt_trace->start == NULL ) { pt_trace->start = pt_trace->GetTrace( m_Pcb->m_Track, NULL, START ); } if( pt_trace->end == NULL ) { pt_trace->end = pt_trace->GetTrace( m_Pcb->m_Track, NULL, END ); } } #else CONNECTIONS connections( m_Pcb ); connections.BuildCandidatesList(); for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { if( pt_trace->start != NULL && pt_trace->end != NULL ) continue; connections.SearchConnectedTracks( pt_trace ); for( unsigned ii = 0; ii < connections.m_Connected.size(); ii ++ ) for( curr_track = m_Pcb->m_Track; curr_track != NULL; curr_track = curr_track->Next() ) { TRACK * candidate = connections.m_Connected[ii]; // Do not create a link to an other track already linked // to avoid loops when we have 4 and more ends at the same location // like this case for 4 tracks named A, B, C ,D: // A links B; B links A and C links D; D links C, but never C or D links A or B // Try to find a not already linked track: if( candidate->start == pt_trace || candidate->end == pt_trace ) if( curr_track->start != NULL && curr_track->end != NULL ) continue; // A link is found: if( pt_trace->start == NULL ) { if( ( pt_trace->m_Start == candidate->m_Start ) || ( pt_trace->m_Start == candidate->m_End ) ) pt_trace->start = candidate; connections.SearchConnectedTracks( curr_track ); curr_track->m_TracksConnected = connections.m_Connected; } if( pt_trace->end == NULL ) { if( ( pt_trace->m_End == candidate->m_Start ) || ( pt_trace->m_End == candidate->m_End ) ) pt_trace->end = candidate; } } } #endif /**********************************************************/ /* Propagate net codes from a segment to an other segment */ /**********************************************************/ while( new_passe_request ) // Propagate net codes from a segment to other connected segments bool new_pass_request = true; // is true if a track has its netcode changes from 0 // to a known netcode to re-evaluate netcodes // of connected items while( new_pass_request ) { bool reset_flag = false; new_passe_request = 0; new_pass_request = false; /* look for vias which could be connect many tracks */ for( TRACK* via = m_Pcb->m_Track; via != NULL; via = via->Next() ) for( curr_track = m_Pcb->m_Track; curr_track; curr_track = curr_track->Next() ) { if( via->Type() != PCB_VIA_T ) continue; if( via->GetNet() > 0 ) continue; // Netcode already known // Lock for a connection to a track with a known netcode pt_next = m_Pcb->m_Track; while( ( pt_next = via->GetTrace( pt_next, NULL, START ) ) != NULL ) int netcode = curr_track->GetNet(); if( netcode == 0 ) { // try to find a connected item having a netcode for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ ) { if( pt_next->GetNet() ) int altnetcode = curr_track->m_TracksConnected[kk]->GetNet(); if( altnetcode ) { via->SetNet( pt_next->GetNet() ); new_pass_request = true; netcode = altnetcode; curr_track->SetNet(netcode); break; } pt_next->SetState( BUSY, ON ); reset_flag = true; } } if( reset_flag ) { for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { pt_trace->SetState( BUSY, OFF ); } } /* set the netcode of connected tracks: if at track is connected to a pad, its net * code is already set. * if the current track is connected to an other track: * if a track has a net code, it is used for the other track. * Thus there is a propagation of the netcode from a track to an other. * if none of the 2 track has a net code we do nothing * the iteration is stopped when no new change occurs */ for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { /* look for the connection to the current segment starting point */ PtStruct = (BOARD_ITEM*) pt_trace->start; if( PtStruct && (PtStruct->Type() != PCB_PAD_T) ) { // Begin on an other track segment pt_next = (TRACK*) PtStruct; if( pt_trace->GetNet() ) { if( pt_next->GetNet() == 0 ) { // the current track has a netcode, we use it for the other track // A change is made: a new iteration is requested. new_passe_request = 1; pt_next->SetNet( pt_trace->GetNet() ); } } else if( netcode ) // this track has a netcode { // propagate this netcode to connected tracks having no netcode for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ ) { if( pt_next->GetNet() != 0 ) int altnetcode = curr_track->m_TracksConnected[kk]->GetNet(); if( altnetcode == 0 ) { // the other track has a netcode, we use it for the current track pt_trace->SetNet( pt_next->GetNet() ); new_passe_request = 1; } } } /* look for the connection to the current segment ending point */ PtStruct = pt_trace->end; if( PtStruct && (PtStruct->Type() != PCB_PAD_T) ) { pt_next = (TRACK*) PtStruct; // End on an other track: propagate netcode if possible if( pt_trace->GetNet() ) { if( pt_next->GetNet() == 0 ) { new_passe_request = 1; pt_next->SetNet( pt_trace->GetNet() ); } } else { if( pt_next->GetNet() != 0 ) { pt_trace->SetNet( pt_next->GetNet() ); new_passe_request = 1; curr_track->m_TracksConnected[kk]->SetNet(netcode); new_pass_request = true; } } } Loading @@ -936,22 +846,16 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } /** * Function Sort_By_NetCode * sorts track segments used in RebuildTrackChain() (for the qsort C function) * The sorting is made by net code. /* * Function SortTracksByNetCode used in RebuildTrackChain() * to sort track segments by net code. */ static int Sort_By_NetCode( const void* left, const void* right ) static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & compare ) { TRACK* pt_ref = *(TRACK**) left; TRACK* pt_compare = *(TRACK**) right; int ret = pt_ref->GetNet() - pt_compare->GetNet(); return ret; return ref->GetNet() < compare->GetNet(); } /** * Function RebuildTrackChain * rebuilds the track segment linked list in order to have a chain Loading @@ -963,26 +867,22 @@ static void RebuildTrackChain( BOARD* pcb ) if( pcb->m_Track == NULL ) return; int nbsegm = pcb->m_Track.GetCount(); int item_count = pcb->m_Track.GetCount(); TRACK** array = (TRACK**) MyZMalloc( nbsegm * sizeof(TRACK*) ); std::vector<TRACK*> trackList; trackList.reserve( item_count ); for( int i = 0; i<nbsegm; ++i ) { array[i] = pcb->m_Track.PopFront(); wxASSERT( array[i] ); } for( int i = 0; i<item_count; ++i ) trackList.push_back( pcb->m_Track.PopFront() ); // the list is empty now wxASSERT( pcb->m_Track == NULL && pcb->m_Track.GetCount()==0 ); qsort( array, nbsegm, sizeof(TRACK*), Sort_By_NetCode ); sort( trackList.begin(), trackList.end(), SortTracksByNetCode ); // add them back to the list for( int i = 0; i<nbsegm; ++i ) for( int i = 0; i < item_count; ++i ) { pcb->m_Track.PushBack( array[i] ); pcb->m_Track.PushBack( trackList[i] ); } MyFree( array ); }
pcbnew/dialogs/dialog_drc.cpp +28 −7 Original line number Diff line number Diff line ///////////////////////////////////////////////////////////////////////////// // Name: dialog_drc.cpp // Author: jean-pierre Charras // Licence: GPL ///////////////////////////////////////////////////////////////////////////// /** * @file dialog_drc.cpp */ /* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2011 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 "fctsys.h" #include "dialog_drc.h" Loading Loading @@ -153,7 +173,8 @@ void DIALOG_DRC_CONTROL::OnStartdrcClick( wxCommandEvent& event ) // run all the tests, with no UI at this time. m_Messages->Clear(); wxSafeYield(); // Allows time slice to refresh the m_Messages window m_Messages->Refresh(); wxYield(); // Allows time slice to refresh the m_Messages window m_tester->m_pcb->m_Status_Pcb = 0; // Force full connectivity and ratsnest recalculations m_tester->RunTests(m_Messages); Loading
pcbnew/drc.cpp +6 −7 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Compile ratsnest...\n" ) ); wxSafeYield(); aMessages->Refresh(); } m_mainWindow->Compile_Ratsnest( NULL, true ); Loading Loading @@ -209,7 +209,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Pad clearances...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testPad2Pad(); Loading @@ -219,9 +219,8 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Track clearances...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testTracks(); // Before testing segments and unconnected, refill all zones: Loading @@ -229,7 +228,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Fill zones...\n" ) ); wxSafeYield(); aMessages->Refresh(); } m_mainWindow->Fill_All_Zones( false ); Loading @@ -238,7 +237,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages && m_doZonesTest ) { aMessages->AppendText( _( "Test zones...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testZones( m_doZonesTest ); Loading @@ -249,7 +248,7 @@ void DRC::RunTests( wxTextCtrl* aMessages ) if( aMessages ) { aMessages->AppendText( _( "Unconnected pads...\n" ) ); wxSafeYield(); aMessages->Refresh(); } testUnconnected(); Loading