diff --git a/CHANGELOG.txt b/CHANGELOG.txt index c2ce304c3d..0118e7de18 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,16 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. +2011-Dec-04, UPDATE Jean-Pierre Charras +================================================================================ +Pcbnew: + Enhanced algorithms to calculate board connections: + Previously, a track was seen connected to a pad only if the track end is + exactly on the pad position. + Now a track is seen connected to a pad if the track end is inside the pad shape. + Algorithm to calculate pads connections to track is still very fast. + However some other functions (drag pads, track len calculation ...) + still need the track end exactly on the pad position. 2011-Nov-27 UPDATE Dick Hollenbeck ================================================================================ @@ -40,7 +50,7 @@ Pcbnew: 2011-Sept-01, UPDATE Jean-Pierre Charras ================================================================================ - Add Fabrizio Tappero in contribuotors list. + Add Fabrizio Tappero in contributors list. Eeschema: Graphic texts ans labels: fix fully broken undo/redo code relative to the way undo/redo command handles changes (maintly move) for labels diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index bc612e9442..99fb4085ee 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -933,19 +933,11 @@ public: bool Other_Layer_Route( TRACK* track, wxDC* DC ); void HighlightUnconnectedPads( wxDC* DC ); - /** - * Function DisplayNetStatus - * shows the status of the net at the current mouse position or the - * PCB status if no segment selected. - */ - void DisplayNetStatus( wxDC* DC ); - /** * Function Delete_Segment - * removes 1 segment of track. - * 2 cases: - * If There is evidence of new track: delete new segment. - * Otherwise, delete segment under the cursor. + * removes a track segment. + * If a new track is in progress: delete the current new segment. + * Otherwise, delete segment under the mouse cursor. */ TRACK* Delete_Segment( wxDC* DC, TRACK* Track ); diff --git a/pcbnew/connect.cpp b/pcbnew/connect.cpp index 5d5efdbe73..31809bc16d 100644 --- a/pcbnew/connect.cpp +++ b/pcbnew/connect.cpp @@ -46,39 +46,51 @@ extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ); static void RebuildTrackChain( BOARD* pcb ); -// A helper class to handle connection points +// A helper class to handle connection points (i.e. candidates) for tracks class CONNECTED_POINT { -public: - TRACK * m_Track; // a link to the connected item (track or via) - wxPoint m_Point; // the connection point +private: + TRACK * m_track; // a link to the parent item (track or via) + wxPoint m_point; // the connection point +public: CONNECTED_POINT( TRACK * aTrack, wxPoint & aPoint) { - m_Track = aTrack; - m_Point = aPoint; + m_track = aTrack; + m_point = aPoint; } + + TRACK * GetTrack() const { return m_track; } + const wxPoint & GetPoint() const { return m_point; } }; // A helper class to handle connections calculations: class CONNECTIONS { -public: - std::vector m_Connected; // List of connected tracks/vias - // to a given track or via - std::vector m_Candidates; // List of points to test - // (end points of tracks or vias location ) - private: + std::vector m_connected; // List of connected tracks/vias + // to a given track or via + std::vector 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 m_sortedPads; // list of sorted pads by X (then Y) coordinate public: CONNECTIONS( BOARD * aBrd ); ~CONNECTIONS() {}; - /** Function Build_CurrNet_SubNets_Connections + /** Function BuildPadsList + * Fills m_sortedPads with all pads that be connected to tracks + * pads are sorted by > 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 Build_CurrNet_SubNets_Connections * Connections to pads are assumed to be already initialized, * and are not recalculated * An be called after a track change (delete or add a track): @@ -93,7 +105,8 @@ public: */ void Build_CurrNet_SubNets_Connections( TRACK* aFirstTrack, TRACK* aLastTrack ); - /** Function BuildCandidatesList + /** + * Function BuildCandidatesList * Fills m_Candidates with all connecting points (track ends or via location) * with tracks from aBegin to aEnd. * if aBegin == NULL, use first track in brd list @@ -108,6 +121,37 @@ public: */ 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 SearchConnectedToPads + * Explores the list of pads and adds to m_PadsConnected member + * of each track connected the pad(s) connected to + */ + void SearchConnectedToPads(); + + /** + * function CollectItemsNearTo + * Used by SearchConnectedToPads + * 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& aList, + const wxPoint& aPosition, int aDistMax ); + /** * Function Propagate_SubNets * Test a list of tracks, to create or propagate a sub netcode to pads and @@ -141,7 +185,7 @@ private: * Change a subnet value to a new value, for tracks ans pads which are connected to * corresponding track for pads and tracks, this is the .m_Subnet member that is tested * and modified these members are block numbers (or cluster numbers) for a given net - * The result is merging 2 cluster (or subnets) into only one. + * The result is 2 cluster (or subnets) are merged into only one. * Note: the resulting sub net value is the smallest between aOldSubNet et aNewSubNet * @return modification count * @param aOldSubNet = subnet value to modify @@ -151,6 +195,144 @@ private: }; + +CONNECTIONS::CONNECTIONS( BOARD * aBrd ) +{ + m_brd = aBrd; +} + + +/* 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 + */ +void CONNECTIONS::BuildPadsList( int aNetcode ) +{ + // Creates sorted pad list if not exists + m_sortedPads.clear(); + if( aNetcode < 0 ) + m_brd->GetSortedPadListByXthenYCoord( m_sortedPads ); + else + { + std::vector buffer; + m_brd->GetSortedPadListByXthenYCoord( buffer ); + int icnt = 0; + for( unsigned ii = 0; ii < buffer.size(); ii++ ) + { + if( buffer[ii]->GetNet() == aNetcode ) + icnt++; + } + m_sortedPads.reserve(icnt); + for( unsigned ii = 0; ii < buffer.size(); ii++ ) + { + if( buffer[ii]->GetNet() == aNetcode ) + m_sortedPads.push_back( buffer[ii] ); + } + } +} + + +void CONNECTIONS::SearchConnectedToPads() +{ + std::vector candidates; + + for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ ) + { + D_PAD * pad = m_sortedPads[ii]; + candidates.clear(); + CollectItemsNearTo( candidates, pad->ReturnShapePos(), pad->m_ShapeMaxRadius ); + // add this pad to track.m_PadsConnected, if it is connected + for( unsigned jj = 0; jj < candidates.size(); jj++ ) + { + CONNECTED_POINT * item = candidates[jj]; + if( (pad->m_layerMask & item->GetTrack()->ReturnMaskLayer()) == 0 ) + continue; + if( pad->HitTest( item->GetPoint() ) ) + { + item->GetTrack()->m_PadsConnected.push_back( pad ); + pad->m_TracksConnected.push_back( item->GetTrack() ); + } + } + } +} + +void CONNECTIONS::CollectItemsNearTo( std::vector& 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(); + if( delta & 1 && delta > 1 ) + delta += 1; + delta /= 2; + int idx = delta; // Starting index is the middle of list + while( delta ) + { + if( (delta & 1) && ( delta > 1 ) ) + delta++; + delta /= 2; + + CONNECTED_POINT& item = m_candidates[idx]; + + if( item.GetPoint().x == aPosition.x ) + 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 ); + } +} + /* 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. @@ -158,19 +340,14 @@ private: static bool sortConnectedPointByXthenYCoordinates( const CONNECTED_POINT & aRef, const CONNECTED_POINT & aTst ) { - if( aRef.m_Point.x == aTst.m_Point.x ) - return aRef.m_Point.y < aTst.m_Point.y; - return aRef.m_Point.x < aTst.m_Point.x; -} - -CONNECTIONS::CONNECTIONS( BOARD * aBrd ) -{ - m_brd = aBrd; + if( aRef.GetPoint().x == aTst.GetPoint().x ) + return aRef.GetPoint().y < aTst.GetPoint().y; + return aRef.GetPoint().x < aTst.GetPoint().x; } void CONNECTIONS::BuildCandidatesList( TRACK * aBegin, TRACK * aEnd) { - m_Candidates.clear(); + m_candidates.clear(); if( aBegin == NULL ) aBegin = m_brd->m_Track; @@ -191,16 +368,15 @@ void CONNECTIONS::BuildCandidatesList( TRACK * aBegin, TRACK * aEnd) break; } // Build candidate list - m_Candidates.reserve( ii ); + m_candidates.reserve( ii ); for( TRACK* track = aBegin; track; track = track->Next() ) { CONNECTED_POINT candidate( track, track->m_Start); - m_Candidates.push_back( candidate ); + m_candidates.push_back( candidate ); if( track->Type() != PCB_VIA_T ) { - candidate.m_Track = track; - candidate.m_Point = track->m_End; - m_Candidates.push_back( candidate ); + CONNECTED_POINT candidate2( track, track->m_End); + m_candidates.push_back( candidate2 ); } if( track == aEnd ) @@ -210,13 +386,13 @@ void CONNECTIONS::BuildCandidatesList( TRACK * aBegin, TRACK * aEnd) // 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 ); + sort( m_candidates.begin(), m_candidates.end(), sortConnectedPointByXthenYCoordinates ); } int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack ) { int count = 0; - m_Connected.clear(); + m_connected.clear(); int layerMask = aTrack->ReturnMaskLayer(); @@ -228,24 +404,24 @@ int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack ) if ( idx >= 0 ) { // search after: - for ( unsigned ii = idx; ii < m_Candidates.size(); ii ++ ) + for ( unsigned ii = idx; ii < m_candidates.size(); ii ++ ) { - if( m_Candidates[ii].m_Track == aTrack ) + if( m_candidates[ii].GetTrack() == aTrack ) continue; - if( m_Candidates[ii].m_Point != position ) + if( m_candidates[ii].GetPoint() != position ) break; - if( (m_Candidates[ii].m_Track->ReturnMaskLayer() & layerMask ) != 0 ) - m_Connected.push_back( m_Candidates[ii].m_Track ); + if( (m_candidates[ii].GetTrack()->ReturnMaskLayer() & layerMask ) != 0 ) + m_connected.push_back( m_candidates[ii].GetTrack() ); } // search before: for ( int ii = idx-1; ii >= 0; ii -- ) { - if( m_Candidates[ii].m_Track == aTrack ) + if( m_candidates[ii].GetTrack() == aTrack ) continue; - if( m_Candidates[ii].m_Point != position ) + if( m_candidates[ii].GetPoint() != position ) break; - if( (m_Candidates[ii].m_Track->ReturnMaskLayer() & layerMask ) != 0 ) - m_Connected.push_back( m_Candidates[ii].m_Track ); + if( (m_candidates[ii].GetTrack()->ReturnMaskLayer() & layerMask ) != 0 ) + m_connected.push_back( m_candidates[ii].GetTrack() ); } } @@ -263,9 +439,9 @@ int CONNECTIONS::searchEntryPoint( 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 idxmax = m_candidates.size()-1; - int delta = m_Candidates.size(); + int delta = m_candidates.size(); if( delta & 1 && delta > 1 ) delta += 1; delta /= 2; @@ -276,16 +452,16 @@ int CONNECTIONS::searchEntryPoint( const wxPoint & aPoint) delta++; delta /= 2; - CONNECTED_POINT & candidate = m_Candidates[idx]; - if( candidate.m_Point == aPoint ) // candidate found + 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.m_Point.x == aPoint.x ) // Must search considering Y coordinate + if( candidate.GetPoint().x == aPoint.x ) // Must search considering Y coordinate { - if(candidate.m_Point.y < aPoint.y) // Must search after this item + if(candidate.GetPoint().y < aPoint.y) // Must search after this item { idx += delta; if( idx > idxmax ) @@ -298,7 +474,7 @@ int CONNECTIONS::searchEntryPoint( const wxPoint & aPoint) idx = 0; } } - else if( candidate.m_Point.x < aPoint.x ) // Must search after this item + else if( candidate.GetPoint().x < aPoint.x ) // Must search after this item { idx += delta; if( idx > idxmax ) @@ -338,7 +514,7 @@ void CONNECTIONS::Build_CurrNet_SubNets_Connections( TRACK* aFirstTrack, TRACK* // Update connections between tracks: SearchConnectedTracks( curr_track ); - curr_track->m_TracksConnected = m_Connected; + curr_track->m_TracksConnected = m_connected; if( curr_track == aLastTrack ) break; @@ -381,18 +557,11 @@ int CONNECTIONS::Merge_SubNets( int aOldSubNet, int aNewSubNet ) change_count++; curr_track->SetSubNet( aNewSubNet ); - BOARD_CONNECTED_ITEM * item = curr_track->start; - if( item && ( item->Type() == PCB_PAD_T) ) + for( unsigned ii = 0; ii < curr_track->m_PadsConnected.size(); ii++ ) { - if( item->GetSubNet() == aOldSubNet ) - item->SetSubNet( curr_track->GetSubNet() ); - } - - item = curr_track->end; - if( item && (item->Type() == PCB_PAD_T) ) - { - if( item->GetSubNet() == aOldSubNet ) - item->SetSubNet( curr_track->GetSubNet() ); + D_PAD * pad = curr_track->m_PadsConnected[ii]; + if( pad->GetSubNet() == aOldSubNet ) + pad->SetSubNet( curr_track->GetSubNet() ); } if( curr_track == m_lastTrack ) @@ -427,46 +596,40 @@ void CONNECTIONS::Propagate_SubNets() for( ; curr_track != NULL; curr_track = curr_track->Next() ) { /* First: handling connections to pads */ - BOARD_CONNECTED_ITEM* pad = curr_track->start; - - for( int ii = 0; ii < 2; ii++ ) + for( unsigned ii = 0; ii < curr_track->m_PadsConnected.size(); ii++ ) { - /* The segment starts on a pad */ - if( pad && (pad->Type() == PCB_PAD_T) ) + D_PAD * pad = curr_track->m_PadsConnected[ii]; + + if( curr_track->GetSubNet() ) /* the track segment is already a cluster member */ { - if( curr_track->GetSubNet() ) /* the track segment is already a cluster member */ + if( pad->GetSubNet() > 0 ) { - 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() ); - } + /* The pad is already a cluster member, so we can merge the 2 clusters */ + Merge_SubNets( pad->GetSubNet(), curr_track->GetSubNet() ); } - else /* the track segment is not attached to a cluster */ + else { - 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() ); - } + /* 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() ); } } - - pad = curr_track->end; } /* Test connections between segments */ @@ -534,7 +697,7 @@ void PCB_BASE_FRAME::TestConnections() // Get last track of the current net TRACK* lastTrack = track->GetEndNetCode( current_net_code ); - if( current_net_code ) // do not spend time if net code = 0, this is not a dummy net + if( current_net_code ) // do not spend time if net code = 0 ( dummy net ) connections.Build_CurrNet_SubNets_Connections( track, lastTrack ); track = lastTrack->Next(); // this is now the first track of the next net @@ -560,7 +723,6 @@ void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode ) for( unsigned i = 0; i < m_Pcb->GetPadsCount(); ++i ) { D_PAD* pad = m_Pcb->m_NetInfo->GetPad(i); - int pad_net_code = pad->GetNet(); if( pad_net_code < aNetCode ) @@ -622,16 +784,15 @@ void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode ) void PCB_BASE_FRAME::RecalculateAllTracksNetcode() { TRACK* curr_track; - std::vector sortedPads; // Build the net info list GetBoard()->m_NetInfo->BuildListOfNets(); - // Reset variables and flags used in computation curr_track = m_Pcb->m_Track; for( ; curr_track != NULL; curr_track = curr_track->Next() ) { curr_track->m_TracksConnected.clear(); + curr_track->m_PadsConnected.clear(); curr_track->start = NULL; curr_track->end = NULL; curr_track->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF ); @@ -643,60 +804,32 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() if( m_Pcb->GetPadsCount() == 0 ) return; - // Prepare connections calculations between tracks and pads */ - m_Pcb->GetSortedPadListByXthenYCoord( sortedPads ); + CONNECTIONS connections( m_Pcb ); + connections.BuildPadsList(); + connections.BuildCandidatesList(); - /* First pass: search connection between a track segment and a pad. - * if found, set the track net code to the pad netcode + // First pass: build connections between track segments and pads. + connections.SearchConnectedToPads(); + + /* For tracks connected to at least one pad, + * set the track net code to the pad netcode */ curr_track = m_Pcb->m_Track; - for( ; curr_track != NULL; curr_track = curr_track->Next() ) { - int layerMask = g_TabOneLayerMask[curr_track->GetLayer()]; - - /* Search for a pad on the segment starting point */ - curr_track->start = m_Pcb->GetPad( sortedPads, curr_track->m_Start, layerMask ); - - if( curr_track->start != NULL ) - { - curr_track->SetState( BEGIN_ONPAD, ON ); - curr_track->SetNet( ( (D_PAD*) (curr_track->start) )->GetNet() ); - } - - /* Search for a pad on the segment ending point */ - curr_track->end = m_Pcb->GetPad( sortedPads, curr_track->m_End, layerMask ); - - if( curr_track->end != NULL ) - { - curr_track->SetState( END_ONPAD, ON ); - curr_track->SetNet( ( (D_PAD*) (curr_track->end) )->GetNet() ); - } + if( curr_track->m_PadsConnected.size() ) + curr_track->SetNet( curr_track->m_PadsConnected[0]->GetNet() ); } - /*****************************************************/ - /* Pass 2: search the connections between track ends */ - /*****************************************************/ - - /* 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 - */ - - CONNECTIONS connections( m_Pcb ); - connections.BuildCandidatesList(); + // Pass 2: build connections between track ends for( curr_track = m_Pcb->m_Track; curr_track != NULL; curr_track = curr_track->Next() ) { - - if( curr_track->start != NULL && curr_track->end != NULL ) - continue; - connections.SearchConnectedTracks( curr_track ); - curr_track->m_TracksConnected = connections.m_Connected; + connections.GetConnectedTracks( curr_track ); } // 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 + bool new_pass_request = true; // set to true if a track has its netcode changed from 0 // to a known netcode to re-evaluate netcodes // of connected items while( new_pass_request ) @@ -751,7 +884,7 @@ static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & } /** - * Function RebuildTrackChain + * Helper function RebuildTrackChain * rebuilds the track segment linked list in order to have a chain * sorted by increasing netcodes. * @param pcb = board to rebuild @@ -766,7 +899,7 @@ static void RebuildTrackChain( BOARD* pcb ) std::vector trackList; trackList.reserve( item_count ); - for( int i = 0; im_Track.PopFront() ); // the list is empty now diff --git a/pcbnew/editrack-part2.cpp b/pcbnew/editrack-part2.cpp index 9ad6a9fced..47799a5375 100644 --- a/pcbnew/editrack-part2.cpp +++ b/pcbnew/editrack-part2.cpp @@ -216,21 +216,6 @@ bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) } -void PCB_EDIT_FRAME::DisplayNetStatus( wxDC* DC ) -{ - TRACK* pt_segm; - int layerMask = (1 << getActiveLayer()); - wxPoint pos = GetScreen()->RefPos( true ); - - pt_segm = GetBoard()->GetTrace( GetBoard()->m_Track, pos, layerMask ); - - if( pt_segm == NULL ) - GetBoard()->DisplayInfo( this ); - else - TestNetConnection( DC, pt_segm->GetNet() ); -} - - void PCB_EDIT_FRAME::Show_1_Ratsnest( EDA_ITEM* item, wxDC* DC ) { D_PAD* pt_pad = NULL; diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index 7bff597fc5..046f290079 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -53,13 +53,13 @@ static void EnsureEndTrackOnPad( D_PAD* Pad ); static PICKED_ITEMS_LIST s_ItemsListPicker; -/* Routine to cancel the route if a track is being drawn, or exit the application EDITRACK. +/* Function called to abort a track creation */ static void Abort_Create_Track( EDA_DRAW_PANEL* Panel, wxDC* DC ) { PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Panel->GetParent(); - BOARD * pcb = frame->GetBoard(); - TRACK* track = (TRACK*) frame->GetCurItem(); + BOARD* pcb = frame->GetBoard(); + TRACK* track = (TRACK*) frame->GetCurItem(); if( track && ( track->Type()==PCB_VIA_T || track->Type()==PCB_TRACE_T ) ) { @@ -88,16 +88,19 @@ static void Abort_Create_Track( EDA_DRAW_PANEL* Panel, wxDC* DC ) frame->SetCurItem( NULL ); } - +/* + * This function starts a new track segment. + * If a new track segment is in progress, ends this current new segment, + * and created a new one. + */ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) { - D_PAD* pt_pad = NULL; TRACK* TrackOnStartPoint = NULL; int layerMask = g_TabOneLayerMask[( (PCB_SCREEN*) GetScreen() )->m_Active_Layer]; BOARD_CONNECTED_ITEM* LockPoint; wxPoint pos = GetScreen()->GetCrossHairPosition(); - if( aTrack == NULL ) /* Starting a new track */ + if( aTrack == NULL ) /* Starting a new track segment */ { DrawPanel->SetMouseCapture( ShowNewTrackWhenMovingCursor, Abort_Create_Track ); @@ -118,15 +121,16 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) // Search for a starting point of the new track, a track or pad LockPoint = GetBoard()->GetLockPoint( pos, layerMask ); + D_PAD* pad = NULL; if( LockPoint ) // An item (pad or track) is found { if( LockPoint->Type() == PCB_PAD_T ) { - pt_pad = (D_PAD*) LockPoint; + pad = (D_PAD*) LockPoint; /* A pad is found: put the starting point on pad center */ - pos = pt_pad->m_Pos; - GetBoard()->SetHighLightNet( pt_pad->GetNet() ); + pos = pad->m_Pos; + GetBoard()->SetHighLightNet( pad->GetNet() ); } else /* A track segment is found */ { @@ -171,15 +175,8 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) g_CurrentTrackSegment->m_Start = pos; g_CurrentTrackSegment->m_End = pos; - if( pt_pad ) - { - g_CurrentTrackSegment->start = pt_pad; - g_CurrentTrackSegment->SetState( BEGIN_ONPAD, ON ); - } - else - { - g_CurrentTrackSegment->start = TrackOnStartPoint; - } + if( pad ) + g_CurrentTrackSegment->m_PadsConnected.push_back( pad ); if( g_TwoSegmentTrackBuild ) { @@ -226,7 +223,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) /* Current track is Ok: current segment is kept, and a new one is * created unless the current segment is null, or 2 last are null - * if a 2 segments track build. + * if this is a 2 segments track build. */ bool CanCreateNewSegment = true; @@ -248,11 +245,9 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) D( g_CurrentTrackList.VerifyListIntegrity(); ); if( g_Raccord_45_Auto ) - { Add45DegreeSegment( aDC ); - } - TRACK* oneBeforeLatest = g_CurrentTrackSegment; + TRACK* previousTrack = g_CurrentTrackSegment; TRACK* newTrack = g_CurrentTrackSegment->Copy(); g_CurrentTrackList.PushBack( newTrack ); @@ -260,15 +255,15 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) newTrack->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); - oneBeforeLatest->end = GetBoard()->GetPad( oneBeforeLatest, END ); + D_PAD* pad = GetBoard()->GetPad( previousTrack, END ); - if( oneBeforeLatest->end ) + if( pad ) { - oneBeforeLatest->SetState( END_ONPAD, ON ); - newTrack->SetState( BEGIN_ONPAD, ON ); + newTrack->m_PadsConnected.push_back( pad ); + previousTrack->m_PadsConnected.push_back( pad ); } - newTrack->start = oneBeforeLatest->end; + newTrack->start = previousTrack->end; D( g_CurrentTrackList.VerifyListIntegrity(); ); @@ -277,9 +272,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) newTrack->SetLayer( ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer ); if( !GetBoard()->GetBoardDesignSettings()->m_UseConnectedTrackWidth ) - { newTrack->m_Width = GetBoard()->GetCurrentTrackWidth(); - } D( g_CurrentTrackList.VerifyListIntegrity(); ); @@ -441,37 +434,38 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC ) D( g_CurrentTrackList.VerifyListIntegrity(); ); - /* The track here is non chained to the list of track segments. + /* The track here is now chained to the list of track segments. * It must be seen in the area of net * As close as possible to the segment base (or end), because * This helps to reduce the computing time */ - /* Attaching the end of the track. */ + // Attaching the end point of the new track to a pad or a track BOARD_CONNECTED_ITEM* LockPoint = GetBoard()->GetLockPoint( pos, layerMask ); - if( LockPoint ) /* End of trace is on a pad. */ + if( LockPoint ) { - if( LockPoint->Type() == PCB_PAD_T ) + if( LockPoint->Type() == PCB_PAD_T ) // End of track is on a pad. { EnsureEndTrackOnPad( (D_PAD*) LockPoint ); } - else /* End of is on a different track, it will possibly create an anchor. */ + else // If end point of is on a different track, + // creates a lock point if not exists { TRACK* adr_buf = (TRACK*) LockPoint; GetBoard()->SetHighLightNet( adr_buf->GetNet() ); - /* Possible establishment of a hanging point. */ + // Creates a lock point (if not already exists): LockPoint = GetBoard()->CreateLockPoint( g_CurrentTrackSegment->m_End, adr_buf, &s_ItemsListPicker ); } } - // Delete Null segments: + // Delete null length segments: DeleteNullTrackSegments( GetBoard(), g_CurrentTrackList ); - // Insert new segments if they exist. This can be NULL on a double click - // on the start point + // Insert new segments if they exist. + // g_FirstTrackSegment can be NULL on a double click on the starting point if( g_FirstTrackSegment != NULL ) { int netcode = g_FirstTrackSegment->GetNet(); @@ -491,17 +485,15 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC ) TraceAirWiresToTargets( aDC ); - DrawTraces( DrawPanel, aDC, firstTrack, newCount, GR_OR ); - int i = 0; - for( track = firstTrack; track && iNext() ) + for( track = firstTrack; track && i < newCount; ++i, track = track->Next() ) { track->m_Flags = 0; track->SetState( BUSY, OFF ); } - // erase the old track, if exists + // delete the old track, if it exists and is redundant if( g_AutoDeleteOldTrack ) { EraseRedundantTrack( aDC, firstTrack, newCount, &s_ItemsListPicker ); @@ -510,10 +502,13 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC ) SaveCopyInUndoList( s_ItemsListPicker, UR_UNSPECIFIED ); s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items - /* compute the new ratsnest */ + // compute the new ratsnest TestNetConnection( aDC, netcode ); OnModify(); GetBoard()->DisplayInfo( this ); + + // Redraw the entire new track. + DrawTraces( DrawPanel, aDC, firstTrack, newCount, GR_OR ); } wxASSERT( g_FirstTrackSegment == NULL ); @@ -982,7 +977,7 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount, wxPoint end ) } -/* Delete track segments which have len = 0; after creating a new track +/* Delete track segments which have len = 0 after creating a new track * return a pointer on the first segment (start of track list) */ void DeleteNullTrackSegments( BOARD* pcb, DLIST& aTrackList ) @@ -1034,7 +1029,7 @@ void DeleteNullTrackSegments( BOARD* pcb, DLIST& aTrackList ) firsttrack->start = LockPoint; - if( LockPoint && LockPoint->Type()==PCB_PAD_T ) + if( LockPoint && LockPoint->Type()==PCB_PAD_T ) firsttrack->SetState( BEGIN_ONPAD, ON ); track = firsttrack;