fixed: 2 bugs that crashes pcbnew (see changelog)

This commit is contained in:
charras 2009-03-16 19:51:23 +00:00
parent cdbd1b294e
commit 17dc3090c4
5 changed files with 137 additions and 67 deletions

View File

@ -5,6 +5,20 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
email address.
2009-mar-16 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
++pcbnew:
Fixed:
bug that crashes pcbnew when removing all footprints
(in connection calculations, pointers to pads not reset)
bug that crashes pcbnew when filling a zone
if a module has a trapezoidal pad
(trapezoidal pads are not yet implemented in zone filling,
they are now calculated as rect shape (todo: a better handling) )
2009-mar-12 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
++eeschema:
@ -51,7 +65,7 @@ email address.
so delete track (or edit track width) deletes the track and some others segments (last created)
bug fix 2660689 Unconnected pads in RC4. Also fixed some no deletion of the old track when creating a new track
2009-Feb-25 UPDATE Wayne Stambaugh <stambaughw@verizon.net>
================================================================================
++EESchema

View File

@ -69,14 +69,14 @@ static int Merge_Two_SubNets( TRACK* pt_start_conn, TRACK* pt_end_conn, int old_
{
pt_pad = (D_PAD*) (pt_conn->start);
if( pt_pad->GetSubNet() == old_val )
pt_pad->SetSubNet(pt_conn->GetSubNet());
pt_pad->SetSubNet( pt_conn->GetSubNet() );
}
if( pt_conn->end && (pt_conn->end->Type() == TYPE_PAD) )
{
pt_pad = (D_PAD*) (pt_conn->end);
if( pt_pad->GetSubNet() == old_val )
pt_pad->SetSubNet(pt_conn->GetSubNet());
pt_pad->SetSubNet( pt_conn->GetSubNet() );
}
if( pt_conn == pt_end_conn )
break;
@ -115,11 +115,11 @@ static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn )
pt_conn->SetSubNet( 0 );
PtStruct = pt_conn->start;
if( PtStruct && (PtStruct->Type() == TYPE_PAD) )
( (D_PAD*) PtStruct )->SetSubNet( 0);
( (D_PAD*) PtStruct )->SetSubNet( 0 );
PtStruct = pt_conn->end;
if( PtStruct && (PtStruct->Type() == TYPE_PAD) )
( (D_PAD*) PtStruct )->SetSubNet( 0);
( (D_PAD*) PtStruct )->SetSubNet( 0 );
if( pt_conn == pt_end_conn )
break;
@ -141,17 +141,17 @@ static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn )
pt_pad = (D_PAD*) PtStruct;
if( pt_conn->GetSubNet() ) /* the track segment is already a cluster member */
{
if( pt_pad->GetSubNet() > 0 ) /* The pad is already a cluster member, so we can merge the 2 clusters */
if( pt_pad->GetSubNet() > 0 ) /* The pad is already a cluster member, so we can merge the 2 clusters */
{
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_pad->GetSubNet(), pt_conn->GetSubNet() );
pt_pad->GetSubNet(), pt_conn->GetSubNet() );
}
else /* The pad is not yet attached to a cluster , so we can add this pad to the cluster */
pt_pad->SetSubNet( pt_conn->GetSubNet() );
}
else /* the track segment is not attached to a cluster */
{
if( pt_pad->GetSubNet() > 0 ) /* it is connected to a pad in a cluster, merge this track */
if( pt_pad->GetSubNet() > 0 ) /* it is connected to a pad in a cluster, merge this track */
{
pt_conn->SetSubNet( pt_pad->GetSubNet() );
}
@ -174,7 +174,7 @@ static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn )
if( pt_pad->GetSubNet() > 0 )
{
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_pad->GetSubNet(), pt_conn->GetSubNet() );
pt_pad->GetSubNet(), pt_conn->GetSubNet() );
}
else
pt_pad->SetSubNet( pt_conn->GetSubNet() );
@ -207,7 +207,7 @@ static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn )
if( pt_autre_piste->GetSubNet() ) /* The other track is already a cluster member, so we can merge the 2 clusters */
{
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_autre_piste->GetSubNet(), pt_conn->GetSubNet() );
pt_autre_piste->GetSubNet(), pt_conn->GetSubNet() );
}
else /* The other track is not yet attached to a cluster , so we can add this other track to the cluster */
{
@ -239,7 +239,7 @@ static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn )
if( pt_autre_piste->GetSubNet() )
{
Merge_Two_SubNets( pt_start_conn, pt_end_conn,
pt_autre_piste->GetSubNet(), pt_conn->GetSubNet() );
pt_autre_piste->GetSubNet(), pt_conn->GetSubNet() );
}
else
pt_autre_piste->SetSubNet( pt_conn->GetSubNet() );
@ -291,7 +291,7 @@ void WinEDA_BasePcbFrame::test_connexions( wxDC* DC )
for( TRACK* track = m_Pcb->m_Track; track; )
{
// this is the current net because pt_start_conn is the first segment of the net
int current_net_code = track->GetNet();
int current_net_code = track->GetNet();
// this is the last segment of the current net
TRACK* pt_end_conn = track->GetEndNetCode( current_net_code );
@ -317,7 +317,7 @@ void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
* @param net_code = net code to test
*/
{
wxString msg;
wxString msg;
if( net_code == 0 )
return;
@ -325,11 +325,11 @@ void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
if( (m_Pcb->m_Status_Pcb & LISTE_CHEVELU_OK) == 0 )
Compile_Ratsnest( DC, TRUE );
for( unsigned i=0; i<m_Pcb->m_Pads.size(); ++i )
for( unsigned i = 0; i<m_Pcb->m_Pads.size(); ++i )
{
D_PAD* pad = m_Pcb->m_Pads[i];
int pad_net_code = pad->GetNet();
int pad_net_code = pad->GetNet();
if( pad_net_code < net_code )
continue;
@ -345,8 +345,8 @@ void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
/* Search for the first and the last segment relative to the given net code */
if( m_Pcb->m_Track )
{
TRACK* pt_start_conn;
TRACK* pt_end_conn = NULL;
TRACK* pt_start_conn;
TRACK* pt_end_conn = NULL;
pt_start_conn = m_Pcb->m_Track.GetFirst()->GetStartNetCode( net_code );
if( pt_start_conn )
@ -475,7 +475,7 @@ static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* aPcb, LISTE_PAD* pt_liste,
int nb_pad = aPcb->m_Pads.size();
LISTE_PAD* ptr_pad = pt_liste;
LISTE_PAD* lim = pt_liste + nb_pad - 1;
LISTE_PAD* lim = pt_liste + nb_pad - 1;
ptr_pad = pt_liste;
while( nb_pad )
@ -539,7 +539,6 @@ static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* aPcb, LISTE_PAD* pt_liste,
}
/**
* Function SortPadsByXCoord
* is used to Sort a pad list by x coordinate value.
@ -553,7 +552,6 @@ static int SortPadsByXCoord( const void* pt_ref, const void* pt_comp )
}
/*****************************************************************************/
void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector )
/*****************************************************************************/
@ -575,17 +573,29 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
* We search a connection between a track segment and a pad: if found : this segment netcode is set to the pad netcode
*/
{
TRACK* pt_piste;
TRACK* pt_next;
int a_color;
char new_passe_request = 1, flag;
std::vector<D_PAD*> sortedPads;
BOARD_ITEM* PtStruct;
int masque_layer;
wxString msg;
TRACK* pt_piste;
TRACK* pt_next;
int a_color;
char new_passe_request = 1, flag;
std::vector<D_PAD*> sortedPads;
BOARD_ITEM* PtStruct;
int masque_layer;
wxString msg;
if( m_Pcb->m_Pads.size() == 0 ) // If no pad, reset pointers and netcode, and do nothing else
{
pt_piste = m_Pcb->m_Track;
for( ; pt_piste != NULL; pt_piste = pt_piste->Next() )
{
pt_piste->start = NULL;
pt_piste->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
pt_piste->SetNet( 0 );
pt_piste->end = NULL;
}
if( m_Pcb->m_Pads.size() == 0 )
return;
}
a_color = CYAN;
@ -795,10 +805,10 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
*/
static int Sort_By_NetCode( const void* left, const void* right )
{
TRACK* pt_ref = *(TRACK**) left;
TRACK* pt_ref = *(TRACK**) left;
TRACK* pt_compare = *(TRACK**) right;
int ret = pt_ref->GetNet() - pt_compare->GetNet();
int ret = pt_ref->GetNet() - pt_compare->GetNet();
return ret;
}
@ -815,11 +825,11 @@ static void RebuildTrackChain( BOARD* pcb )
if( pcb->m_Track == NULL )
return;
int nbsegm = pcb->m_Track.GetCount();
int nbsegm = pcb->m_Track.GetCount();
TRACK** array = (TRACK**) MyZMalloc( nbsegm * sizeof(TRACK*) );
for( int i=0; i<nbsegm; ++i )
for( int i = 0; i<nbsegm; ++i )
{
array[i] = pcb->m_Track.PopFront();
wxASSERT( array[i] );
@ -831,7 +841,7 @@ static void RebuildTrackChain( BOARD* pcb )
qsort( array, nbsegm, sizeof(TRACK*), Sort_By_NetCode );
// add them back to the list
for( int i=0; i<nbsegm; ++i )
for( int i = 0; i<nbsegm; ++i )
{
pcb->m_Track.PushBack( array[i] );
}

View File

@ -34,11 +34,14 @@ void WinEDA_PcbGlobalDeleteFrame::AcceptPcbDelete( wxCommandEvent& event )
/***********************************************************************/
{
int track_mask;
bool redraw = FALSE;
bool redraw = false;
bool gen_rastnest = false;
wxClientDC dc( m_Parent->DrawPanel );
m_Parent->DrawPanel->PrepareGraphicContext( &dc );
m_Parent->SetCurItem( NULL );
if( m_DelAlls->GetValue() )
{
m_Parent->Clear_Pcb( TRUE );
@ -49,6 +52,7 @@ void WinEDA_PcbGlobalDeleteFrame::AcceptPcbDelete( wxCommandEvent& event )
if( m_DelZones->GetValue() )
{
m_Parent->Erase_Zones( TRUE );
gen_rastnest = true;
redraw = TRUE;
}
@ -73,12 +77,12 @@ void WinEDA_PcbGlobalDeleteFrame::AcceptPcbDelete( wxCommandEvent& event )
if( m_DelModules->GetValue() )
{
m_Parent->Erase_Modules( TRUE );
gen_rastnest = true;
redraw = TRUE;
}
if( m_DelTracks->GetValue() )
{
{
track_mask = 0;
if( !m_TrackFilterLocked->GetValue() )
track_mask |= SEGM_FIXE;
@ -87,7 +91,7 @@ void WinEDA_PcbGlobalDeleteFrame::AcceptPcbDelete( wxCommandEvent& event )
m_Parent->Erase_Pistes( &dc, track_mask, TRUE );
redraw = TRUE;
}
gen_rastnest = true;
}
if( m_DelMarkers->GetValue() )
@ -95,11 +99,14 @@ void WinEDA_PcbGlobalDeleteFrame::AcceptPcbDelete( wxCommandEvent& event )
m_Parent->Erase_Marqueurs();
redraw = TRUE;
}
if ( gen_rastnest )
m_Parent->Compile_Ratsnest( &dc, true );
}
if( redraw )
{
m_Parent->SetCurItem( NULL );
m_Parent->DrawPanel->Refresh();
}
@ -278,6 +285,7 @@ void WinEDA_PcbFrame::Erase_Modules( bool query )
GetBoard()->m_NbNodes = 0;
GetBoard()->m_NbLinks = 0;
GetBoard()->m_NbNoconnect = 0;
m_Pcb->m_Pads.clear(); // empty the pad list pointers
GetScreen()->SetModify();
}

View File

@ -122,7 +122,7 @@ void WinEDA_BasePcbFrame::Compile_Ratsnest( wxDC* DC, bool display_status_pcb )
msg.Printf( wxT( " %d" ), m_Pcb->m_Equipots.GetCount() );
Affiche_1_Parametre( this, 8, wxT( "Nets" ), msg, CYAN );
reattribution_reference_piste( display_status_pcb );
/* Compute the full ratsnest
@ -446,6 +446,11 @@ void WinEDA_BasePcbFrame::Build_Board_Ratsnest( wxDC* DC )
m_Pcb->m_NbNoconnect = 0;
m_Pcb->m_NbLinks = 0;
if( m_Pcb->m_Ratsnest )
MyFree( m_Pcb->m_Ratsnest );
m_Pcb->m_Ratsnest = NULL;
if( m_Pcb->m_Pads.size() == 0 )
return;
@ -464,13 +469,9 @@ void WinEDA_BasePcbFrame::Build_Board_Ratsnest( wxDC* DC )
/* Allocate memory for buffer ratsnest: there are nb_nodes - 1 ratsnest
* maximum ( 1 node = 1 active pad ).
* Meory is allocated for nb_nodes ratsnests... (+ a bit more, just in case)
* Memory is allocated for nb_nodes ratsnests... (+ a bit more, just in case)
* The real ratsnests count nb_links < nb_nodes
*/
if( m_Pcb->m_Ratsnest )
MyFree( m_Pcb->m_Ratsnest );
m_Pcb->m_Ratsnest = NULL;
if( m_Pcb->m_NbNodes == 0 )
return; /* pas de connexions utiles */

View File

@ -110,6 +110,8 @@ double s_Correction; /* mult coeff used to enlarge rounded and oval pads (an
*/
void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
{
bool have_poly_to_substract = false;
// Set the number of segments in arc approximations
if( m_ArcToSegmentsCount == 32 )
s_CircleToSegmentsCount = 32;
@ -149,6 +151,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng;
if ( m_FilledPolysList.size() == 0 )
return;
/* Second, Add the main (corrected) polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine to do a BOOL_A_SUB_B operation
* All areas to remove will be put in GroupB in Bool_Engine
@ -178,6 +183,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
* First : Add pads. Note: pads having the same net as zone are left in zone.
* Thermal shapes will be created later if necessary
*/
have_poly_to_substract = false;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
@ -189,7 +195,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
{
item_boundingbox = pad->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
AddPadWithClearancePolygon( booleng, *pad, clearance );
have_poly_to_substract = true;
}
continue;
}
@ -197,7 +206,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
{
item_boundingbox = pad->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
AddPadWithClearancePolygon( booleng, *pad, clearance );
have_poly_to_substract = true;
}
}
}
}
@ -214,8 +227,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
continue;
item_boundingbox = track->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) )
{
AddTrackWithClearancePolygon( booleng, *track, clearance );
}
have_poly_to_substract = true;
}
}
// Draw graphic items (copper texts) and board edges
// zone clearance is used here regardless of the g_DesignSettings.m_TrackClearence value
@ -234,6 +250,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
AddRingPolygon( booleng, ( (DRAWSEGMENT*) item )->m_Start, // Circle centre
( (DRAWSEGMENT*) item )->m_End, 3600,
( (DRAWSEGMENT*) item )->m_Width + (2 * m_ZoneClearance) );
have_poly_to_substract = true;
break;
case S_ARC:
@ -241,6 +258,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
( (DRAWSEGMENT*) item )->m_End,
( (DRAWSEGMENT*) item )->m_Angle,
( (DRAWSEGMENT*) item )->m_Width + (2 * m_ZoneClearance) );
have_poly_to_substract = true;
break;
default:
@ -250,6 +268,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
( (DRAWSEGMENT*) item )->m_End,
( (DRAWSEGMENT*) item )->m_Width +
(2 * m_ZoneClearance) );
have_poly_to_substract = true;
break;
}
@ -259,6 +278,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
if( ( (TEXTE_PCB*) item )->GetLength() == 0 )
break;
AddTextBoxWithClearancePolygon( booleng, (TEXTE_PCB*) item, m_ZoneClearance );
have_poly_to_substract = true;
break;
default:
@ -267,23 +287,32 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
}
/* calculates copper areas */
booleng->Do_Operation( BOOL_A_SUB_B );
if ( have_poly_to_substract )
{
booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
}
delete booleng;
// Remove insulated islands:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
// remove thermal gaps if required:
if( m_PadOption != THERMAL_PAD || aPcb->m_Modules == NULL )
return;
// Remove thermal symbols
have_poly_to_substract = false;
if( m_PadOption == THERMAL_PAD )
{
booleng = new Bool_Engine();
ArmBoolEng( booleng, true );
bool have_poly_to_substract = false;
have_poly_to_substract = false;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{
@ -320,15 +349,13 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
}
delete booleng;
// Remove insulated islands:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
}
// Remove insulated islands:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
if( m_PadOption != THERMAL_PAD )
return;
// Now we remove all unused thermal stubs.
//define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations
//#ifdef REMOVE_UNUSED_THERMAL_STUBS
@ -348,6 +375,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
/*
* Test and add polygons to remove thermal stubs.
*/
have_poly_to_substract = false;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
@ -446,6 +474,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
RotatePoint( &cpos, fAngle ); // Rotate according to module orientation
cpos += pad->ReturnShapePos(); // Shift origin to position
booleng->AddPoint( cpos.x, cpos.y );
have_poly_to_substract = true;
}
booleng->EndPolygonAdd();
@ -456,16 +485,19 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
}
/* compute copper areas */
booleng->Do_Operation( BOOL_A_SUB_B );
if ( have_poly_to_substract )
{
booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
// Remove insulated islands, if any:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
}
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng;
// Remove insulated islands, if any:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
//#endif
}
@ -569,7 +601,12 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
break;
}
case PAD_RECT: // Easy implementation for rectangular cutouts with rounded corners
case PAD_TRAPEZOID:
default: /* @todo: the others shapes must be calculated: see trapezoidal shape
* but before this is made, the rect shape is used insteed.
* A polygon *must* be created because we have started a polygon in kbool engine
*/
case PAD_RECT: // Easy implementation for rectangular cutouts with rounded corners // Easy implementation for rectangular cutouts with rounded corners
angle = aPad.m_Orient;
int rounding_radius = (int) ( aClearanceValue * s_Correction ); // Corner rounding radius
int angle_pg; // Polygon increment angle