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 Please add newer entries at the top, list the date and your name with
email address. 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> 2009-mar-12 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================ ================================================================================
++eeschema: ++eeschema:

View File

@ -539,7 +539,6 @@ static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* aPcb, LISTE_PAD* pt_liste,
} }
/** /**
* Function SortPadsByXCoord * Function SortPadsByXCoord
* is used to Sort a pad list by x coordinate value. * 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 ) void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector )
/*****************************************************************************/ /*****************************************************************************/
@ -579,13 +577,25 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
TRACK* pt_next; TRACK* pt_next;
int a_color; int a_color;
char new_passe_request = 1, flag; char new_passe_request = 1, flag;
std::vector<D_PAD*> sortedPads; std::vector<D_PAD*> sortedPads;
BOARD_ITEM* PtStruct; BOARD_ITEM* PtStruct;
int masque_layer; int masque_layer;
wxString msg; wxString msg;
if( m_Pcb->m_Pads.size() == 0 ) 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;
}
return; return;
}
a_color = CYAN; a_color = CYAN;

View File

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

View File

@ -446,6 +446,11 @@ void WinEDA_BasePcbFrame::Build_Board_Ratsnest( wxDC* DC )
m_Pcb->m_NbNoconnect = 0; m_Pcb->m_NbNoconnect = 0;
m_Pcb->m_NbLinks = 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 ) if( m_Pcb->m_Pads.size() == 0 )
return; return;
@ -464,13 +469,9 @@ void WinEDA_BasePcbFrame::Build_Board_Ratsnest( wxDC* DC )
/* Allocate memory for buffer ratsnest: there are nb_nodes - 1 ratsnest /* Allocate memory for buffer ratsnest: there are nb_nodes - 1 ratsnest
* maximum ( 1 node = 1 active pad ). * 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 * 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 ) if( m_Pcb->m_NbNodes == 0 )
return; /* pas de connexions utiles */ 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 ) void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
{ {
bool have_poly_to_substract = false;
// Set the number of segments in arc approximations // Set the number of segments in arc approximations
if( m_ArcToSegmentsCount == 32 ) if( m_ArcToSegmentsCount == 32 )
s_CircleToSegmentsCount = 32; s_CircleToSegmentsCount = 32;
@ -149,6 +151,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
CopyPolygonsFromBoolengineToFilledPolysList( booleng ); CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng; delete booleng;
if ( m_FilledPolysList.size() == 0 )
return;
/* Second, Add the main (corrected) polygon (i.e. the filled area using only one outline) /* 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 * 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 * 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. * First : Add pads. Note: pads having the same net as zone are left in zone.
* Thermal shapes will be created later if necessary * Thermal shapes will be created later if necessary
*/ */
have_poly_to_substract = false;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{ {
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->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(); item_boundingbox = pad->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) ) if( item_boundingbox.Intersects( zone_boundingbox ) )
{
AddPadWithClearancePolygon( booleng, *pad, clearance ); AddPadWithClearancePolygon( booleng, *pad, clearance );
have_poly_to_substract = true;
}
continue; continue;
} }
@ -197,7 +206,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
{ {
item_boundingbox = pad->GetBoundingBox(); item_boundingbox = pad->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) ) if( item_boundingbox.Intersects( zone_boundingbox ) )
{
AddPadWithClearancePolygon( booleng, *pad, clearance ); AddPadWithClearancePolygon( booleng, *pad, clearance );
have_poly_to_substract = true;
}
} }
} }
} }
@ -214,7 +227,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
continue; continue;
item_boundingbox = track->GetBoundingBox(); item_boundingbox = track->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) ) if( item_boundingbox.Intersects( zone_boundingbox ) )
{
AddTrackWithClearancePolygon( booleng, *track, clearance ); AddTrackWithClearancePolygon( booleng, *track, clearance );
have_poly_to_substract = true;
}
} }
// Draw graphic items (copper texts) and board edges // Draw graphic items (copper texts) and board edges
@ -234,6 +250,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
AddRingPolygon( booleng, ( (DRAWSEGMENT*) item )->m_Start, // Circle centre AddRingPolygon( booleng, ( (DRAWSEGMENT*) item )->m_Start, // Circle centre
( (DRAWSEGMENT*) item )->m_End, 3600, ( (DRAWSEGMENT*) item )->m_End, 3600,
( (DRAWSEGMENT*) item )->m_Width + (2 * m_ZoneClearance) ); ( (DRAWSEGMENT*) item )->m_Width + (2 * m_ZoneClearance) );
have_poly_to_substract = true;
break; break;
case S_ARC: case S_ARC:
@ -241,6 +258,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
( (DRAWSEGMENT*) item )->m_End, ( (DRAWSEGMENT*) item )->m_End,
( (DRAWSEGMENT*) item )->m_Angle, ( (DRAWSEGMENT*) item )->m_Angle,
( (DRAWSEGMENT*) item )->m_Width + (2 * m_ZoneClearance) ); ( (DRAWSEGMENT*) item )->m_Width + (2 * m_ZoneClearance) );
have_poly_to_substract = true;
break; break;
default: default:
@ -250,6 +268,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
( (DRAWSEGMENT*) item )->m_End, ( (DRAWSEGMENT*) item )->m_End,
( (DRAWSEGMENT*) item )->m_Width + ( (DRAWSEGMENT*) item )->m_Width +
(2 * m_ZoneClearance) ); (2 * m_ZoneClearance) );
have_poly_to_substract = true;
break; break;
} }
@ -259,6 +278,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
if( ( (TEXTE_PCB*) item )->GetLength() == 0 ) if( ( (TEXTE_PCB*) item )->GetLength() == 0 )
break; break;
AddTextBoxWithClearancePolygon( booleng, (TEXTE_PCB*) item, m_ZoneClearance ); AddTextBoxWithClearancePolygon( booleng, (TEXTE_PCB*) item, m_ZoneClearance );
have_poly_to_substract = true;
break; break;
default: default:
@ -267,23 +287,32 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
} }
/* calculates copper areas */ /* calculates copper areas */
if ( have_poly_to_substract )
{
booleng->Do_Operation( BOOL_A_SUB_B ); booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */ /* put these areas in m_FilledPolysList */
m_FilledPolysList.clear(); m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng ); CopyPolygonsFromBoolengineToFilledPolysList( booleng );
}
delete booleng; delete booleng;
// Remove insulated islands: // Remove insulated islands:
if( GetNet() > 0 ) if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); 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 // Remove thermal symbols
have_poly_to_substract = false;
if( m_PadOption == THERMAL_PAD ) if( m_PadOption == THERMAL_PAD )
{ {
booleng = new Bool_Engine(); booleng = new Bool_Engine();
ArmBoolEng( booleng, true ); ArmBoolEng( booleng, true );
bool have_poly_to_substract = false; have_poly_to_substract = false;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{ {
@ -320,14 +349,12 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
CopyPolygonsFromBoolengineToFilledPolysList( booleng ); CopyPolygonsFromBoolengineToFilledPolysList( booleng );
} }
delete booleng; delete booleng;
}
// Remove insulated islands: // Remove insulated islands:
if( GetNet() > 0 ) if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
if( m_PadOption != THERMAL_PAD ) }
return;
// Now we remove all unused thermal stubs. // Now we remove all unused thermal stubs.
//define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations //define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations
@ -348,6 +375,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
/* /*
* Test and add polygons to remove thermal stubs. * Test and add polygons to remove thermal stubs.
*/ */
have_poly_to_substract = false;
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
{ {
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->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 RotatePoint( &cpos, fAngle ); // Rotate according to module orientation
cpos += pad->ReturnShapePos(); // Shift origin to position cpos += pad->ReturnShapePos(); // Shift origin to position
booleng->AddPoint( cpos.x, cpos.y ); booleng->AddPoint( cpos.x, cpos.y );
have_poly_to_substract = true;
} }
booleng->EndPolygonAdd(); booleng->EndPolygonAdd();
@ -456,16 +485,19 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
} }
/* compute copper areas */ /* compute copper areas */
if ( have_poly_to_substract )
{
booleng->Do_Operation( BOOL_A_SUB_B ); booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */ /* put these areas in m_FilledPolysList */
m_FilledPolysList.clear(); m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng ); CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng;
// Remove insulated islands, if any: // Remove insulated islands, if any:
if( GetNet() > 0 ) if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
}
delete booleng;
//#endif //#endif
} }
@ -569,7 +601,12 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
break; 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; angle = aPad.m_Orient;
int rounding_radius = (int) ( aClearanceValue * s_Correction ); // Corner rounding radius int rounding_radius = (int) ( aClearanceValue * s_Correction ); // Corner rounding radius
int angle_pg; // Polygon increment angle int angle_pg; // Polygon increment angle