Pcbnew: fix a possible crash after a board cleanup
This commit is contained in:
parent
4b9b2f4e66
commit
38553be4de
130
pcbnew/clean.cpp
130
pcbnew/clean.cpp
|
@ -6,23 +6,24 @@
|
||||||
|
|
||||||
#include "fctsys.h"
|
#include "fctsys.h"
|
||||||
#include "class_drawpanel.h"
|
#include "class_drawpanel.h"
|
||||||
#include "gr_basic.h"
|
//#include "gr_basic.h"
|
||||||
#include "pcbcommon.h"
|
#include "pcbcommon.h"
|
||||||
#include "wxPcbStruct.h"
|
#include "wxPcbStruct.h"
|
||||||
|
|
||||||
#include "pcbnew.h"
|
#include "pcbnew.h"
|
||||||
#include "protos.h"
|
//#include "protos.h"
|
||||||
|
|
||||||
#include "class_board.h"
|
#include "class_board.h"
|
||||||
#include "class_track.h"
|
#include "class_track.h"
|
||||||
|
|
||||||
|
typedef long long int64;
|
||||||
|
|
||||||
/* local functions : */
|
/* local functions : */
|
||||||
static void clean_segments( PCB_EDIT_FRAME* frame );
|
static void clean_segments( PCB_EDIT_FRAME* frame );
|
||||||
static void clean_vias( BOARD* aPcb );
|
static void clean_vias( BOARD* aPcb );
|
||||||
static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame, wxDC* DC );
|
static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame );
|
||||||
static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extremite );
|
static TRACK* MergeColinearSegmentIfPossible( BOARD* aPcb, TRACK* aTrackRef, TRACK* aCandidate, int aEndType );
|
||||||
static void Clean_Pcb_Items( PCB_EDIT_FRAME* frame, wxDC* DC,
|
static void CleanupTracks( PCB_EDIT_FRAME* frame,
|
||||||
bool aCleanVias, bool aMergeSegments,
|
bool aCleanVias, bool aMergeSegments,
|
||||||
bool aDeleteUnconnectedSegm, bool aConnectToPads );
|
bool aDeleteUnconnectedSegm, bool aConnectToPads );
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ static void Clean_Pcb_Items( PCB_EDIT_FRAME* frame, wxDC* DC,
|
||||||
#define CONN2PAD_ENBL
|
#define CONN2PAD_ENBL
|
||||||
|
|
||||||
#ifdef CONN2PAD_ENBL
|
#ifdef CONN2PAD_ENBL
|
||||||
static void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC );
|
static void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame );
|
||||||
static void ConnectDanglingEndToVia( BOARD* pcb );
|
static void ConnectDanglingEndToVia( BOARD* pcb );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ void PCB_EDIT_FRAME::Clean_Pcb( wxDC* DC )
|
||||||
DIALOG_CLEANING_OPTIONS dlg( this );
|
DIALOG_CLEANING_OPTIONS dlg( this );
|
||||||
|
|
||||||
if( dlg.ShowModal() == wxID_OK )
|
if( dlg.ShowModal() == wxID_OK )
|
||||||
Clean_Pcb_Items( this, DC, dlg.cleanVias, dlg.mergeSegments,
|
CleanupTracks( this, dlg.cleanVias, dlg.mergeSegments,
|
||||||
dlg.deleteUnconnectedSegm, dlg.connectToPads );
|
dlg.deleteUnconnectedSegm, dlg.connectToPads );
|
||||||
|
|
||||||
DrawPanel->Refresh( true );
|
DrawPanel->Refresh( true );
|
||||||
|
@ -60,7 +61,7 @@ void PCB_EDIT_FRAME::Clean_Pcb( wxDC* DC )
|
||||||
* Create segments when track ends are incorrectly connected:
|
* Create segments when track ends are incorrectly connected:
|
||||||
* i.e. when a track end covers a pad or a via but is not exactly on the pad or the via center
|
* i.e. when a track end covers a pad or a via but is not exactly on the pad or the via center
|
||||||
*/
|
*/
|
||||||
void Clean_Pcb_Items( PCB_EDIT_FRAME* frame, wxDC* DC,
|
void CleanupTracks( PCB_EDIT_FRAME* frame,
|
||||||
bool aCleanVias, bool aMergeSegments,
|
bool aCleanVias, bool aMergeSegments,
|
||||||
bool aDeleteUnconnectedSegm, bool aConnectToPads )
|
bool aDeleteUnconnectedSegm, bool aConnectToPads )
|
||||||
{
|
{
|
||||||
|
@ -71,6 +72,7 @@ void Clean_Pcb_Items( PCB_EDIT_FRAME* frame, wxDC* DC,
|
||||||
|
|
||||||
// Clear undo and redo lists to avoid inconsistencies between lists
|
// Clear undo and redo lists to avoid inconsistencies between lists
|
||||||
frame->GetScreen()->ClearUndoRedoList();
|
frame->GetScreen()->ClearUndoRedoList();
|
||||||
|
frame->SetCurItem( NULL );
|
||||||
|
|
||||||
/* Rebuild the pad infos (pad list and netcodes) to ensure an up to date info */
|
/* Rebuild the pad infos (pad list and netcodes) to ensure an up to date info */
|
||||||
frame->GetBoard()->m_Status_Pcb = 0;
|
frame->GetBoard()->m_Status_Pcb = 0;
|
||||||
|
@ -90,7 +92,7 @@ void Clean_Pcb_Items( PCB_EDIT_FRAME* frame, wxDC* DC,
|
||||||
frame->SetStatusText( _( "Reconnect pads" ) );
|
frame->SetStatusText( _( "Reconnect pads" ) );
|
||||||
|
|
||||||
/* Create missing segments when a track end covers a pad, but is not on the pad center */
|
/* Create missing segments when a track end covers a pad, but is not on the pad center */
|
||||||
ConnectDanglingEndToPad( frame, DC );
|
ConnectDanglingEndToPad( frame );
|
||||||
|
|
||||||
/* Create missing segments when a track end covers a via, but is not on the via center */
|
/* Create missing segments when a track end covers a via, but is not on the via center */
|
||||||
ConnectDanglingEndToVia( frame->GetBoard() );
|
ConnectDanglingEndToVia( frame->GetBoard() );
|
||||||
|
@ -108,12 +110,12 @@ void Clean_Pcb_Items( PCB_EDIT_FRAME* frame, wxDC* DC,
|
||||||
if( aDeleteUnconnectedSegm )
|
if( aDeleteUnconnectedSegm )
|
||||||
{
|
{
|
||||||
frame->SetStatusText( _( "Delete unconnected tracks" ) );
|
frame->SetStatusText( _( "Delete unconnected tracks" ) );
|
||||||
DeleteUnconnectedTracks( frame, DC );
|
DeleteUnconnectedTracks( frame );
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->SetStatusText( _( "Cleanup finished" ) );
|
frame->SetStatusText( _( "Cleanup finished" ) );
|
||||||
|
|
||||||
frame->Compile_Ratsnest( DC, true );
|
frame->Compile_Ratsnest( NULL, true );
|
||||||
|
|
||||||
frame->OnModify();
|
frame->OnModify();
|
||||||
}
|
}
|
||||||
|
@ -173,7 +175,7 @@ void clean_vias( BOARD * aPcb )
|
||||||
* Vias:
|
* Vias:
|
||||||
* If a via is only connected to a dangling track, it also will be removed
|
* If a via is only connected to a dangling track, it also will be removed
|
||||||
*/
|
*/
|
||||||
static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame, wxDC* DC )
|
static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame )
|
||||||
{
|
{
|
||||||
TRACK* segment;
|
TRACK* segment;
|
||||||
TRACK* other;
|
TRACK* other;
|
||||||
|
@ -372,8 +374,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame, wxDC* DC )
|
||||||
next = startNetcode;
|
next = startNetcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove segment from screen and board
|
// remove segment from board
|
||||||
segment->Draw( frame->DrawPanel, DC, GR_XOR );
|
|
||||||
segment->DeleteStructure();
|
segment->DeleteStructure();
|
||||||
|
|
||||||
if( next == NULL )
|
if( next == NULL )
|
||||||
|
@ -493,7 +494,7 @@ static void clean_segments( PCB_EDIT_FRAME* frame )
|
||||||
|
|
||||||
if( flag ) // We have the starting point of the segment is connected to an other segment
|
if( flag ) // We have the starting point of the segment is connected to an other segment
|
||||||
{
|
{
|
||||||
segDelete = AlignSegment( frame->GetBoard(), segment, segStart, START );
|
segDelete = MergeColinearSegmentIfPossible( frame->GetBoard(), segment, segStart, START );
|
||||||
|
|
||||||
if( segDelete )
|
if( segDelete )
|
||||||
{
|
{
|
||||||
|
@ -533,7 +534,7 @@ static void clean_segments( PCB_EDIT_FRAME* frame )
|
||||||
|
|
||||||
if( flag & 2 ) // We have the ending point of the segment is connected to an other segment
|
if( flag & 2 ) // We have the ending point of the segment is connected to an other segment
|
||||||
{
|
{
|
||||||
segDelete = AlignSegment( frame->GetBoard(), segment, segEnd, END );
|
segDelete = MergeColinearSegmentIfPossible( frame->GetBoard(), segment, segEnd, END );
|
||||||
|
|
||||||
if( segDelete )
|
if( segDelete )
|
||||||
{
|
{
|
||||||
|
@ -551,25 +552,42 @@ static void clean_segments( PCB_EDIT_FRAME* frame )
|
||||||
|
|
||||||
|
|
||||||
/* Function used by clean_segments.
|
/* Function used by clean_segments.
|
||||||
* Test alignment of pt_segm and pt_ref (which must have a common end).
|
* Test alignment of aTrackRef and aCandidate (which must have a common end).
|
||||||
* and see if the common point is not on a pad (i.e. if this common point can be removed).
|
* and see if the common point is not on a pad (i.e. if this common point can be removed).
|
||||||
* the ending point of pt_ref is the start point (extremite == START)
|
* the ending point of pt_ref is the start point (aEndType == START)
|
||||||
* or the end point (extremite == FIN)
|
* or the end point (aEndType != START)
|
||||||
* if the common end can be deleted, this function
|
* if the common point can be deleted, this function
|
||||||
* change the common point coordinate of the pt_ref segm
|
* change the common point coordinate of the aTrackRef segm
|
||||||
* (and therefore connect the 2 other ending points)
|
* (and therefore connect the 2 other ending points)
|
||||||
* and return pt_segm (which can be deleted).
|
* and return aCandidate (which can be deleted).
|
||||||
* else return NULL
|
* else return NULL
|
||||||
*/
|
*/
|
||||||
static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extremite )
|
TRACK* MergeColinearSegmentIfPossible( BOARD* aPcb,
|
||||||
|
TRACK* aTrackRef, TRACK* aCandidate,
|
||||||
|
int aEndType )
|
||||||
{
|
{
|
||||||
int flag = 0;
|
if( aTrackRef->m_Width != aCandidate->m_Width )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
int refdx = pt_ref->m_End.x - pt_ref->m_Start.x;
|
bool is_colinear = false;
|
||||||
int refdy = pt_ref->m_End.y - pt_ref->m_Start.y;
|
|
||||||
|
|
||||||
int segmdx = pt_segm->m_End.x - pt_segm->m_Start.x;
|
// Trivial case: superimposed tracks ( tracks, not vias ):
|
||||||
int segmdy = pt_segm->m_End.y - pt_segm->m_Start.y;
|
if( aTrackRef->Type() == PCB_TRACE_T && aCandidate->Type() == PCB_TRACE_T )
|
||||||
|
{
|
||||||
|
if( aTrackRef->m_Start == aCandidate->m_Start )
|
||||||
|
if( aTrackRef->m_End == aCandidate->m_End )
|
||||||
|
return aCandidate;
|
||||||
|
|
||||||
|
if( aTrackRef->m_Start == aCandidate->m_End )
|
||||||
|
if( aTrackRef->m_End == aCandidate->m_Start )
|
||||||
|
return aCandidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int refdx = aTrackRef->m_End.x - aTrackRef->m_Start.x;
|
||||||
|
int refdy = aTrackRef->m_End.y - aTrackRef->m_Start.y;
|
||||||
|
|
||||||
|
int segmdx = aCandidate->m_End.x - aCandidate->m_Start.x;
|
||||||
|
int segmdy = aCandidate->m_End.y - aCandidate->m_Start.y;
|
||||||
|
|
||||||
// test for vertical alignment (easy to handle)
|
// test for vertical alignment (easy to handle)
|
||||||
if( refdx == 0 )
|
if( refdx == 0 )
|
||||||
|
@ -577,7 +595,7 @@ static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extre
|
||||||
if( segmdx != 0 )
|
if( segmdx != 0 )
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
flag = 1;
|
is_colinear = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for horizontal alignment (easy to handle)
|
// test for horizontal alignment (easy to handle)
|
||||||
|
@ -586,18 +604,18 @@ static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extre
|
||||||
if( segmdy != 0 )
|
if( segmdy != 0 )
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
flag = 2;
|
is_colinear = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test if alignment in other cases
|
/* test if alignment in other cases
|
||||||
* We must have refdy/refdx == (+/-)segmdy/segmdx, (i.e. same orientation) */
|
* We must have refdy/refdx == (+/-)segmdy/segmdx, (i.e. same orientation) */
|
||||||
if( flag == 0 )
|
if( is_colinear == false )
|
||||||
{
|
{
|
||||||
if( (refdy * segmdx != refdx * segmdy)
|
if( ( (int64)refdy * segmdx != (int64)refdx * segmdy )
|
||||||
&& (refdy * segmdx != -refdx * segmdy) )
|
&& ( (int64)refdy * segmdx != -(int64)refdx * segmdy ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
flag = 4;
|
is_colinear = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here we have 2 aligned segments:
|
/* Here we have 2 aligned segments:
|
||||||
|
@ -605,42 +623,42 @@ static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extre
|
||||||
* (this function) is called when there is only 2 connected segments,
|
* (this function) is called when there is only 2 connected segments,
|
||||||
*and if this point is not on a pad, it can be removed and the 2 segments will be merged
|
*and if this point is not on a pad, it can be removed and the 2 segments will be merged
|
||||||
*/
|
*/
|
||||||
if( extremite == START )
|
if( aEndType == START )
|
||||||
{
|
{
|
||||||
/* We do not have a pad */
|
// We must not have a pad, which is a always terminal point for a track
|
||||||
if( Pcb->GetPadFast( pt_ref->m_Start, g_TabOneLayerMask[pt_ref->GetLayer()] ) )
|
if( aPcb->GetPadFast( aTrackRef->m_Start, g_TabOneLayerMask[aTrackRef->GetLayer()] ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* change the common point coordinate of pt_segm to use the other point
|
/* change the common point coordinate of pt_segm to use the other point
|
||||||
* of pt_segm (pt_segm will be removed later) */
|
* of pt_segm (pt_segm will be removed later) */
|
||||||
if( pt_ref->m_Start == pt_segm->m_Start )
|
if( aTrackRef->m_Start == aCandidate->m_Start )
|
||||||
{
|
{
|
||||||
pt_ref->m_Start = pt_segm->m_End;
|
aTrackRef->m_Start = aCandidate->m_End;
|
||||||
return pt_segm;
|
return aCandidate;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pt_ref->m_Start = pt_segm->m_Start;
|
aTrackRef->m_Start = aCandidate->m_Start;
|
||||||
return pt_segm;
|
return aCandidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* extremite == END */
|
else // aEndType == END
|
||||||
{
|
{
|
||||||
/* We do not have a pad */
|
// We must not have a pad, which is a always terminal point for a track
|
||||||
if( Pcb->GetPadFast( pt_ref->m_End, g_TabOneLayerMask[pt_ref->GetLayer()] ) )
|
if( aPcb->GetPadFast( aTrackRef->m_End, g_TabOneLayerMask[aTrackRef->GetLayer()] ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* change the common point coordinate of pt_segm to use the other point
|
/* change the common point coordinate of pt_segm to use the other point
|
||||||
* of pt_segm (pt_segm will be removed later) */
|
* of pt_segm (pt_segm will be removed later) */
|
||||||
if( pt_ref->m_End == pt_segm->m_Start )
|
if( aTrackRef->m_End == aCandidate->m_Start )
|
||||||
{
|
{
|
||||||
pt_ref->m_End = pt_segm->m_End;
|
aTrackRef->m_End = aCandidate->m_End;
|
||||||
return pt_segm;
|
return aCandidate;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pt_ref->m_End = pt_segm->m_Start;
|
aTrackRef->m_End = aCandidate->m_Start;
|
||||||
return pt_segm;
|
return aCandidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,7 +830,7 @@ static void ConnectDanglingEndToVia( BOARD* pcb )
|
||||||
* connected into the center of the pad. This allows faster control of
|
* connected into the center of the pad. This allows faster control of
|
||||||
* connections.
|
* connections.
|
||||||
*/
|
*/
|
||||||
void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
|
void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame )
|
||||||
{
|
{
|
||||||
TRACK* segment;
|
TRACK* segment;
|
||||||
int nb_new_trace = 0;
|
int nb_new_trace = 0;
|
||||||
|
@ -831,7 +849,7 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
|
||||||
|
|
||||||
if( pad )
|
if( pad )
|
||||||
{
|
{
|
||||||
// test if the track is not precisely starting on the found pad
|
// test if the track start point is not exactly starting on the pad
|
||||||
if( segment->m_Start != pad->m_Pos )
|
if( segment->m_Start != pad->m_Pos )
|
||||||
{
|
{
|
||||||
if( segment->GetTrace( frame->GetBoard()->m_Track, NULL, START ) == NULL )
|
if( segment->GetTrace( frame->GetBoard()->m_Track, NULL, START ) == NULL )
|
||||||
|
@ -845,8 +863,6 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
|
||||||
newTrack->end = pad;
|
newTrack->end = pad;
|
||||||
|
|
||||||
nb_new_trace++;
|
nb_new_trace++;
|
||||||
|
|
||||||
newTrack->Draw( frame->DrawPanel, DC, GR_OR );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -855,7 +871,7 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
|
||||||
|
|
||||||
if( pad )
|
if( pad )
|
||||||
{
|
{
|
||||||
// test if the track is not precisely ending on the found pad
|
// test if the track end point is not exactly on the pad
|
||||||
if( segment->m_End != pad->m_Pos )
|
if( segment->m_End != pad->m_Pos )
|
||||||
{
|
{
|
||||||
if( segment->GetTrace( frame->GetBoard()->m_Track, NULL, END ) == NULL )
|
if( segment->GetTrace( frame->GetBoard()->m_Track, NULL, END ) == NULL )
|
||||||
|
|
|
@ -627,35 +627,25 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
|
||||||
// Build the net info list
|
// Build the net info list
|
||||||
GetBoard()->m_NetInfo->BuildListOfNets();
|
GetBoard()->m_NetInfo->BuildListOfNets();
|
||||||
|
|
||||||
if( m_Pcb->GetPadsCount() == 0 ) // If no pad, reset pointers and netcode, and do nothing else
|
|
||||||
{
|
|
||||||
curr_track = m_Pcb->m_Track;
|
|
||||||
|
|
||||||
for( ; curr_track != NULL; curr_track = curr_track->Next() )
|
|
||||||
{
|
|
||||||
curr_track->start = NULL;
|
|
||||||
curr_track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
|
|
||||||
curr_track->SetNet( 0 );
|
|
||||||
curr_track->end = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare connections calculations between tracks and pads */
|
|
||||||
m_Pcb->GetSortedPadListByXthenYCoord( sortedPads );
|
|
||||||
|
|
||||||
// Reset variables and flags used in computation
|
// Reset variables and flags used in computation
|
||||||
curr_track = m_Pcb->m_Track;
|
curr_track = m_Pcb->m_Track;
|
||||||
|
|
||||||
for( ; curr_track != NULL; curr_track = curr_track->Next() )
|
for( ; curr_track != NULL; curr_track = curr_track->Next() )
|
||||||
{
|
{
|
||||||
curr_track->m_TracksConnected.clear();
|
curr_track->m_TracksConnected.clear();
|
||||||
|
curr_track->start = NULL;
|
||||||
|
curr_track->end = NULL;
|
||||||
curr_track->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF );
|
curr_track->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF );
|
||||||
curr_track->SetZoneSubNet( 0 );
|
curr_track->SetZoneSubNet( 0 );
|
||||||
curr_track->SetNet( 0 ); // net code = 0 means not connected
|
curr_track->SetNet( 0 ); // net code = 0 means not connected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no pad, reset pointers and netcode, and do nothing else
|
||||||
|
if( m_Pcb->GetPadsCount() == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Prepare connections calculations between tracks and pads */
|
||||||
|
m_Pcb->GetSortedPadListByXthenYCoord( sortedPads );
|
||||||
|
|
||||||
/* First pass: search connection between a track segment and a pad.
|
/* First pass: search connection between a track segment and a pad.
|
||||||
* if found, set the track net code to the pad netcode
|
* if found, set the track net code to the pad netcode
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue