diff --git a/pcbnew/connect.cpp b/pcbnew/connect.cpp index 5e66f666da..db7dfcbd79 100644 --- a/pcbnew/connect.cpp +++ b/pcbnew/connect.cpp @@ -282,6 +282,15 @@ void CONNECTIONS::BuildTracksCandidatesList( TRACK * aBegin, TRACK * aEnd) 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; @@ -290,9 +299,15 @@ int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack ) int layerMask = aTrack->ReturnMaskLayer(); // Search for connections to starting point: +#define USE_EXTENDED_SEARCH +#ifdef USE_EXTENDED_SEARCH + int dist_max = aTrack->GetWidth() / 2; + static std::vector tracks_candidates; +#endif wxPoint position = aTrack->m_Start; for( int kk = 0; kk < 2; kk++ ) { +#ifndef USE_EXTENDED_SEARCH int idx = searchEntryPointInCandidatesList( position ); if ( idx >= 0 ) { @@ -317,6 +332,30 @@ int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack ) 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->ReturnMaskLayer() & layerMask ) == 0 ) + continue; + + if( ctrack == aTrack ) + continue; + + // We have a good candidate: calculate the actual distance + // beteween ends, which should be <= dist max. + wxPoint delta = tracks_candidates[ii]->GetPoint() - position; + int dist = (int) hypot( (double) delta.x, (double) delta.y ); + + if( dist > dist_max ) + continue; + + m_connected.push_back( ctrack ); + } +#endif // Search for connections to ending point: if( aTrack->Type() == PCB_VIA_T ) diff --git a/pcbnew/connect.h b/pcbnew/connect.h index cc836eddf8..aec042dfad 100644 --- a/pcbnew/connect.h +++ b/pcbnew/connect.h @@ -147,14 +147,15 @@ public: /** * Function BuildPadsCandidatesList - * Fills m_Candidates with all pads connecting points (pads position) - * m_sortedPads must be built + * 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 - * Fills m_Connected with tracks/vias connected to aTrack + * 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 ); diff --git a/pcbnew/drag.h b/pcbnew/drag.h index a5f219ae60..20cb2829be 100644 --- a/pcbnew/drag.h +++ b/pcbnew/drag.h @@ -165,10 +165,19 @@ void DrawSegmentWhileMovingFootprint( EDA_DRAW_PANEL* panel, wxDC* DC ); */ void EraseDragList(); -/* - * function used to collect track segments in drag track segment +/** + * function Collect_TrackSegmentsToDrag. + * used to collect track segments in drag track segment + * Build the list of tracks connected to the ref point by calling + * AddSegmentToDragList for each selected track + * Net codes must be up to date, because only tracks having the right net code are tested. + * @param aRefPos = reference point of connection + * @param aLayerMask = layers mask to collect tracks + * @param aNetCode = the net code to consider + * @param aMaxDist = max distance from aRefPos to a track end candidate to collect the track */ -void Collect_TrackSegmentsToDrag( BOARD* aPcb, wxPoint& point, int LayerMask, int net_code ); +void Collect_TrackSegmentsToDrag( BOARD* aPcb, wxPoint& aRefPos, int aLayerMask, + int aNetCode, int aMaxDist ); /* Add aTrack to the drag list * flag = STARTPOINT (if the point to drag is the start point of Track) diff --git a/pcbnew/dragsegm.cpp b/pcbnew/dragsegm.cpp index 44d56192f8..72d3c2c961 100644 --- a/pcbnew/dragsegm.cpp +++ b/pcbnew/dragsegm.cpp @@ -345,29 +345,55 @@ void AddSegmentToDragList( int flag, TRACK* aTrack ) /* Build the list of tracks connected to the ref point * Net codes must be up to date, because only tracks having the right net code are tested. * aRefPos = reference point of connection + * aLayerMask = layers mask to collect tracks + * aNetCode = the net code to consider + * aMaxDist = max distance from aRefPos to a track end candidate to collect the track */ -void Collect_TrackSegmentsToDrag( BOARD* aPcb, wxPoint& aRefPos, int LayerMask, int net_code ) +void Collect_TrackSegmentsToDrag( BOARD* aPcb, wxPoint& aRefPos, int aLayerMask, + int aNetCode, int aMaxDist ) { - TRACK* track = aPcb->m_Track->GetStartNetCode( net_code ); + TRACK* track = aPcb->m_Track->GetStartNetCode( aNetCode ); for( ; track; track = track->Next() ) { - if( track->GetNet() != net_code ) // not the same netcodenet code: all candidates tested + if( track->GetNet() != aNetCode ) // not the same netcodenet code: all candidates tested break; - if( ( LayerMask & track->ReturnMaskLayer() ) == 0 ) + if( ( aLayerMask & track->ReturnMaskLayer() ) == 0 ) continue; // Cannot be connected, not on the same layer if( track->IsDragging() ) continue; // already put in list int flag = 0; + int maxdist = std::max( aMaxDist, track->GetWidth() / 2 ); - if( (track->m_Start == aRefPos) && ((track->GetFlags() & STARTPOINT) == 0) ) - flag |= STARTPOINT; + if( (track->GetFlags() & STARTPOINT) == 0 ) + { + wxPoint delta = track->m_Start - aRefPos; + if( std::abs( delta.x ) <= maxdist && std::abs( delta.y ) <= maxdist ) + { + int dist = (int) hypot( (double) delta.x, (double) delta.y ); + if( dist <= maxdist ) + { + flag |= STARTPOINT; + if( track->Type() == PCB_VIA_T ) + flag |= ENDPOINT; + } + } + } + + if( (track->GetFlags() & ENDPOINT) == 0 ) + { + wxPoint delta = track->m_End - aRefPos; + if( std::abs( delta.x ) <= maxdist && std::abs( delta.y ) <= maxdist ) + { + int dist = (int) hypot( (double) delta.x, (double) delta.y ); + if( dist <= maxdist ) + flag |= ENDPOINT; + } + } - if( track->m_End == aRefPos && ((track->GetFlags() & ENDPOINT) == 0) ) - flag |= ENDPOINT; // Note: vias will be flagged with both STARTPOINT and ENDPOINT // and must not be entered twice. @@ -379,7 +405,7 @@ void Collect_TrackSegmentsToDrag( BOARD* aPcb, wxPoint& aRefPos, int LayerMask, // collect also tracks connected by this via. if( track->Type() == PCB_VIA_T ) Collect_TrackSegmentsToDrag( aPcb, aRefPos, track->ReturnMaskLayer(), - net_code ); + aNetCode, track->GetWidth() / 2 ); } } } diff --git a/pcbnew/move_or_drag_track.cpp b/pcbnew/move_or_drag_track.cpp index 6b65f6095e..b9e6afb293 100644 --- a/pcbnew/move_or_drag_track.cpp +++ b/pcbnew/move_or_drag_track.cpp @@ -632,7 +632,7 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC { Collect_TrackSegmentsToDrag( GetBoard(), aTrack->m_Start, aTrack->ReturnMaskLayer(), - aTrack->GetNet() ); + aTrack->GetNet(), aTrack->GetWidth() / 2 ); } PosInit = aTrack->m_Start; @@ -652,17 +652,17 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC case ID_POPUP_PCB_DRAG_TRACK_SEGMENT: // drag a segment pos = aTrack->m_Start; Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->ReturnMaskLayer(), - aTrack->GetNet() ); + aTrack->GetNet(), aTrack->GetWidth() / 2 ); pos = aTrack->m_End; aTrack->SetFlags( IS_DRAGGED | ENDPOINT | STARTPOINT ); Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->ReturnMaskLayer(), - aTrack->GetNet() ); + aTrack->GetNet(), aTrack->GetWidth() / 2 ); break; case ID_POPUP_PCB_MOVE_TRACK_NODE: // Drag via or move node pos = (diag & STARTPOINT) ? aTrack->m_Start : aTrack->m_End; Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->ReturnMaskLayer(), - aTrack->GetNet() ); + aTrack->GetNet(), aTrack->GetWidth() / 2 ); PosInit = pos; break; }