Commit ab76e809 authored by Wayne Stambaugh's avatar Wayne Stambaugh

PCBNew trace mark code refactoring and other minor fixes.

* Refactor trace mark functions into the board object.
* Remove track.cpp as it is no longer needed.
* Dead code removal.
parent e4d1fa12
......@@ -182,7 +182,6 @@ set(PCBNEW_SRCS
tool_pcb.cpp
toolbars_update_user_interface.cpp
tracepcb.cpp
track.cpp
tr_modif.cpp
trpiste.cpp
work.cpp
......
......@@ -39,7 +39,7 @@ void PCB_EDIT_FRAME::Attribut_Track( TRACK* track, wxDC* DC, bool Flag_On )
return;
DrawPanel->CrossHairOff( DC ); // Erase cursor shape
Track = MarkTrace( GetBoard(), track, &nb_segm, NULL, NULL, true );
Track = GetBoard()->MarkTrace( track, &nb_segm, NULL, NULL, true );
DrawTraces( DrawPanel, DC, Track, nb_segm, GR_OR | GR_SURBRILL );
for( ; (Track != NULL) && (nb_segm > 0); nb_segm-- )
......
......@@ -79,6 +79,116 @@ BOARD::~BOARD()
}
void BOARD::chainMarkedSegments( wxPoint aPosition, int aLayerMask, TRACK_PTRS* aList )
{
TRACK* segment; // The current segment being analyzed.
TRACK* via; // The via identified, eventually destroy
TRACK* candidate; // The end segment to destroy (or NULL = segment)
int NbSegm;
if( m_Track == NULL )
return;
/* Set the BUSY flag of all connected segments, first search starting at
* aPosition. The search ends when a pad is found (end of a track), a
* segment end has more than one other segment end connected, or when no
* connected item found.
*
* Vias are a special case because they must look for segments connected
* on other layers and they change the layer mask. They can be a track
* end or not. They will be analyzer later and vias on terminal points
* of the track will be considered as part of this track if they do not
* connect segments of an other track together and will be considered as
* part of an other track when removing the via, the segments of that other
* track are disconnected.
*/
for( ; ; )
{
if( GetPadFast( aPosition, aLayerMask ) != NULL )
return;
/* Test for a via: a via changes the layer mask and can connect a lot
* of segments at location aPosition. When found, the via is just
* pushed in list. Vias will be examined later, when all connected
* segment are found and push in list. This is because when a via
* is found we do not know at this time the number of connected items
* and we do not know if this via is on the track or finish the track
*/
via = m_Track->GetVia( NULL, aPosition, aLayerMask );
if( via )
{
aLayerMask = via->ReturnMaskLayer();
aList->push_back( via );
}
/* Now we search all segments connected to point aPosition
* if only 1 segment: this segment is candidate
* if > 1 segment:
* end of track (more than 2 segment connected at this location)
*/
segment = m_Track; candidate = NULL;
NbSegm = 0;
while( ( segment = ::GetTrace( segment, NULL, aPosition, aLayerMask ) ) != NULL )
{
if( segment->GetState( BUSY ) ) // already found and selected: skip it
{
segment = segment->Next();
continue;
}
if( segment == via ) // just previously found: skip it
{
segment = segment->Next();
continue;
}
NbSegm++;
if( NbSegm == 1 ) /* First time we found a connected item: segment is candidate */
{
candidate = segment;
segment = segment->Next();
}
else /* More than 1 segment connected -> this location is an end of the track */
{
return;
}
}
if( candidate ) // A candidate is found: flag it an push it in list
{
/* Initialize parameters to search items connected to this
* candidate:
* we must analyze connections to its other end
*/
aLayerMask = candidate->ReturnMaskLayer();
if( aPosition == candidate->m_Start )
{
aPosition = candidate->m_End;
}
else
{
aPosition = candidate->m_Start;
}
segment = m_Track; /* restart list of tracks to analyze */
/* flag this item an push it in list of selected items */
aList->push_back( candidate );
candidate->SetState( BUSY, ON );
}
else
{
return;
}
}
}
void BOARD::PushHighLight()
{
m_hightLightPrevious = m_hightLight;
......@@ -1665,6 +1775,248 @@ TRACK* BOARD::GetTrace( TRACK* aTrace, const wxPoint& aPosition, int aLayerMask
}
TRACK* BOARD::MarkTrace( TRACK* aTrace,
int* aCount,
int* aTraceLength,
int* aDieLength,
bool aReorder )
{
int NbSegmBusy;
TRACK_PTRS trackList;
if( aCount )
*aCount = 0;
if( aTraceLength )
*aTraceLength = 0;
if( aTrace == NULL )
return NULL;
// Ensure the flag BUSY of all tracks of the board is cleared
// because we use it to mark segments of the track
for( TRACK* track = m_Track; track; track = track->Next() )
track->SetState( BUSY, OFF );
/* Set flags of the initial track segment */
aTrace->SetState( BUSY, ON );
int layerMask = aTrace->ReturnMaskLayer();
trackList.push_back( aTrace );
/* Examine the initial track segment : if it is really a segment, this is
* easy.
* If it is a via, one must search for connected segments.
* If <=2, this via connect 2 segments (or is connected to only one
* segment) and this via and these 2 segments are a part of a track.
* If > 2 only this via is flagged (the track has only this via)
*/
if( aTrace->Type() == TYPE_VIA )
{
TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL;
Segm1 = ::GetTrace( m_Track, NULL, aTrace->m_Start, layerMask );
if( Segm1 )
{
Segm2 = ::GetTrace( Segm1->Next(), NULL, aTrace->m_Start, layerMask );
}
if( Segm2 )
{
Segm3 = ::GetTrace( Segm2->Next(), NULL, aTrace->m_Start, layerMask );
}
if( Segm3 ) // More than 2 segments are connected to this via. the track" is only this via
{
if( aCount )
*aCount = 1;
return aTrace;
}
if( Segm1 ) // search for others segments connected to the initial segment start point
{
layerMask = Segm1->ReturnMaskLayer();
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
}
if( Segm2 ) // search for others segments connected to the initial segment end point
{
layerMask = Segm2->ReturnMaskLayer();
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
}
}
else // mark the chain using both ends of the initial segment
{
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
chainMarkedSegments( aTrace->m_End, layerMask, &trackList );
}
// Now examine selected vias and flag them if they are on the track
// If a via is connected to only one or 2 segments, it is flagged (is on the track)
// If a via is connected to more than 2 segments, it is a track end, and it
// is removed from the list
// go through the list backwards.
for( int i = trackList.size() - 1; i>=0; --i )
{
TRACK* via = trackList[i];
if( via->Type() != TYPE_VIA )
continue;
if( via == aTrace )
continue;
via->SetState( BUSY, ON ); // Try to flag it. the flag will be cleared later if needed
layerMask = via->ReturnMaskLayer();
TRACK* track = ::GetTrace( m_Track, NULL, via->m_Start, layerMask );
// GetTrace does not consider tracks flagged BUSY.
// So if no connected track found, this via is on the current track
// only: keep it
if( track == NULL )
continue;
/* If a track is found, this via connects also others segments of an
* other track. This case happens when the vias ends the selected
* track but must we consider this via is on the selected track, or
* on an other track.
* (this is important when selecting a track for deletion: must this
* via be deleted or not?)
* We consider here this via on the track if others segment connected
* to this via remain connected when removing this via.
* We search for all others segment connected together:
* if there are on the same layer, the via is on the selected track
* if there are on different layers, the via is on an other track
*/
int layer = track->GetLayer();
while( ( track = ::GetTrace( track->Next(), NULL, via->m_Start, layerMask ) ) != NULL )
{
if( layer != track->GetLayer() )
{
// The via connects segments of an other track: it is removed
// from list because it is member of an other track
via->SetState( BUSY, OFF );
break;
}
}
}
/* Rearrange the track list in order to have flagged segments linked
* from firstTrack so the NbSegmBusy segments are consecutive segments
* in list, the first item in the full track list is firstTrack, and
* the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
* are the flagged segments
*/
NbSegmBusy = 0;
TRACK* firstTrack;
for( firstTrack = m_Track; firstTrack; firstTrack = firstTrack->Next() )
{
// Search for the first flagged BUSY segments
if( firstTrack->GetState( BUSY ) )
{
NbSegmBusy = 1;
break;
}
}
if( firstTrack == NULL )
return NULL;
double full_len = 0;
double lenDie = 0;
if( aReorder )
{
DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
wxASSERT( list );
/* Rearrange the chain starting at firstTrack
* All others flagged items are moved from their position to the end
* of the flagged list
*/
TRACK* next;
for( TRACK* track = firstTrack->Next(); track; track = next )
{
next = track->Next();
if( track->GetState( BUSY ) ) // move it!
{
NbSegmBusy++;
track->UnLink();
list->Insert( track, firstTrack->Next() );
if( aTraceLength )
full_len += track->GetLength();
if( aDieLength ) // Add now length die.
{
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
}
else if( aTraceLength )
{
NbSegmBusy = 0;
for( TRACK* track = firstTrack; track; track = track->Next() )
{
if( track->GetState( BUSY ) )
{
NbSegmBusy++;
track->SetState( BUSY, OFF );
full_len += track->GetLength();
// Add now length die.
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
if( aTraceLength )
*aTraceLength = wxRound( full_len );
if( aDieLength )
*aDieLength = wxRound( lenDie );
if( aCount )
*aCount = NbSegmBusy;
return firstTrack;
}
#if defined(DEBUG)
void BOARD::Show( int nestLevel, std::ostream& os )
......
......@@ -15,6 +15,10 @@
class ZONE_CONTAINER;
// buffer of item candidates when search for items on the same track.
typedef std::vector< TRACK* > TRACK_PTRS;
#define HISTORY_MAX_COUNT 8
......@@ -203,6 +207,17 @@ private:
BOARD_DESIGN_SETTINGS* m_boardDesignSettings; // Link to current design settings
COLORS_DESIGN_SETTINGS* m_colorsSettings; // Link to current colors settings
/**
* Function chainMarkedSegments
* is used by MarkTrace() to set the BUSY flag of connected segments of the trace
* segment located at \a aPosition on aLayerMask.
* Vias are put in list but their flags BUSY is not set
* @param aPosition A wxPoint object containing the position of the starting search.
* @param aLayerMask The allowed layers for segments to search.
* @param aList The track list to fill with points of flagged segments.
*/
void chainMarkedSegments( wxPoint aPosition, int aLayerMask, TRACK_PTRS* aList );
public:
BOARD( EDA_ITEM* aParent, PCB_BASE_FRAME* frame );
~BOARD();
......@@ -1154,6 +1169,33 @@ public:
* @return A TRACK object pointer if found otherwise NULL.
*/
TRACK* GetTrace( TRACK* aTrace, const wxPoint& aPosition, int aLayerMask );
/**
* Function MarkTrace
* marks a chain of trace segments, connected to \aaTrace.
* <p>
* Each segment is marked by setting the BUSY bit into m_Flags. Electrical
* continuity is detected by walking each segment, and finally the segments
* are rearranged into a contiguous chain within the given list.
* </p>
*
* @param aTrace The segment within a list of trace segments to test.
* @param aCount A pointer to an integer where to return the number of
* marked segments.
* @param aTraceLength A pointer to an integer where to return the length of the
* trace.
* @param aDieLength A pointer to an integer where to return the extra lengths inside
* integrated circuits from the pads connected to this track to the
* die (if any).
* @param aReorder true for reorder the interesting segments (useful for
* track edition/deletion) in this case the flag BUSY is
* set (the user is responsible of flag clearing). False
* for no reorder : useful when we want just calculate the
* track length in this case, flags are reset
* @return TRACK* The first in the chain of interesting segments.
*/
TRACK* MarkTrace( TRACK* aTrace, int* aCount, int* aTraceLength,
int* aDieLength, bool aReorder );
};
#endif // #ifndef CLASS_BOARD_H
......@@ -979,7 +979,7 @@ void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame )
{
int trackLen = 0;
int lenDie = 0;
MarkTrace( board, this, NULL, &trackLen, &lenDie, false );
board->MarkTrace( this, NULL, &trackLen, &lenDie, false );
msg = frame->CoordinateToString( trackLen );
frame->AppendMsgPanel( _( "Track Len" ), msg, DARKCYAN );
......
......@@ -176,8 +176,8 @@ void PCB_EDIT_FRAME::Remove_One_Track( wxDC* DC, TRACK* pt_segm )
if( pt_segm == NULL )
return;
TRACK* trackList = MarkTrace( GetBoard(), pt_segm, &segments_to_delete_count,
NULL, NULL, true );
TRACK* trackList = GetBoard()->MarkTrace( pt_segm, &segments_to_delete_count,
NULL, NULL, true );
if( segments_to_delete_count == 0 )
return;
......
/***************************************************************
* Tracks and Vias size edition:
* Functions to modify sizes of segment, track, net , all vias and/or all tracks
***************************************************************/
/**
* @file edit_track_width.cpp
* @breif Functions to modify sizes of segment, track, net , all vias and/or all tracks
*/
#include "fctsys.h"
#include "class_drawpanel.h"
......@@ -68,7 +68,8 @@ bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem,
aTrackItem->m_Width = new_width;
if( initial_width < new_width ) /* make a DRC test because the new size is bigger than the old size */
/* make a DRC test because the new size is bigger than the old size */
if( initial_width < new_width )
{
int diagdrc = OK_DRC;
......@@ -82,11 +83,9 @@ bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem,
{
change_ok = true;
}
// if new width == initial_width: do nothing,
// unless a via has its drill value changed
else if( (aTrackItem->Type() == TYPE_VIA) && (initial_drill != new_drill) )
{
// if new width == initial_width: do nothing, unless a via has its drill value changed
change_ok = true;
}
......@@ -166,7 +165,7 @@ void PCB_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment )
if( aTrackSegment == NULL )
return;
pt_track = MarkTrace( GetBoard(), aTrackSegment, &nb_segm, NULL, NULL, true );
pt_track = GetBoard()->MarkTrace( aTrackSegment, &nb_segm, NULL, NULL, true );
PICKED_ITEMS_LIST itemsListPicker;
bool change = false;
......@@ -205,7 +204,7 @@ void PCB_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment )
/**
* Function Change_Net_Tracks_And_Vias_Sizes
* Reset all tracks width and vias diameters and drill
* to their default Netclass value ou current values
* to their default Netclass value or current values
* @param aNetcode : the netcode of the net to edit
* @param aUseNetclassValue : bool. True to use netclass values, false to use current values
*/
......
......@@ -70,8 +70,6 @@ void DrawTraces( EDA_DRAW_PANEL* panel,
MODULE* Locate_Prefered_Module( BOARD* aPcb, const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked = false );
DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int LayerSearch, int typeloc );
/*************/
/* MODULES.C */
/*************/
......@@ -95,53 +93,6 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo
void CalculateSegmentEndPoint( const wxPoint& aPosition, int ox, int oy, int* fx, int* fy );
/***************/
/* TRACK.CPP : */
/***************/
/**
* Function MarkTrace
* marks a chain of track segments, connected to aTrackList.
* Each segment is marked by setting the BUSY bit into m_Flags. Electrical
* continuity is detected by walking each segment, and finally the segments
* are rearranged into a contiguous chain within the given list.
*
* @param aPcb = the board to analyze
* @param aStartSegm - The first interesting segment within a list of track
* segment of aPcb
* @param aSegmCount = a pointer to an integer where to return the number of
* interesting segments
* @param aTrackLen = a pointer to an integer where to return the lenght of the
* track
* @param aLengthDie = a pointer to an integer where to return the extra lengths inside
* integrated circuits from the pads connected to this track to the
* die (if any)
* @param aReorder = true for reorder the interesting segments (useful for
* track edition/deletion) in this case the flag BUSY is
* set (the user is responsible of flag clearing). False
* for no reorder : useful when we want just calculate the
* track length in this case, flags are reset
* @return TRACK* the first in the chain of interesting segments.
*/
TRACK* MarkTrace( BOARD* aPcb,
TRACK* aStartSegm,
int* aSegmCount,
int* aTrackLen,
int* aLengthDie,
bool aReorder );
/* Calculate end coordinate of a trace.
* Returns 1 if OK, 0 if trace looped back on itself.
* The coord are returned StartTrack-> ox, oy
* And EndTrack-> fx, fy if OK
* The segments are drawn consecutively.
*/
int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack );
/***************/
/***************/
/* Routine to find the point "attachment" at the end of a trace.
* This may be a PAD or another trace segment.
* Returns:
......
......@@ -38,7 +38,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
if( aNewTrack->Type() == TYPE_VIA && ( aNewTrackSegmentsCount > 1 ) )
aNewTrack = aNewTrack->Next();
aNewTrack = MarkTrace( GetBoard(), aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
aNewTrack = GetBoard()->MarkTrace( aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
wxASSERT( aNewTrack );
#if 0 && defined(DEBUG)
......@@ -190,7 +190,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
nbconnect--;
pt_del->SetState( IS_LINKED, OFF );
pt_del = MarkTrace( GetBoard(), pt_del, &nb_segm, NULL, NULL, true );
pt_del = GetBoard()->MarkTrace( pt_del, &nb_segm, NULL, NULL, true );
/* Test if the marked track is redundant, i.e. if one of marked segments
* is connected to the starting point of the new track.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment