Commit 17dc3090 authored by charras's avatar charras

fixed: 2 bugs that crashes pcbnew (see changelog)

parent cdbd1b29
......@@ -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:
......
......@@ -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;
......@@ -325,7 +325,7 @@ 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];
......@@ -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 )
/*****************************************************************************/
......@@ -579,13 +577,25 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
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( 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;
}
a_color = CYAN;
......@@ -819,7 +829,7 @@ static void RebuildTrackChain( BOARD* pcb )
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] );
}
......
......@@ -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,11 +77,11 @@ 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() )
......@@ -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();
}
......
......@@ -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 */
......
......@@ -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,7 +227,10 @@ 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
......@@ -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 */
if ( have_poly_to_substract )
{
booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */
/* 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,14 +349,12 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
}
delete booleng;
}
// Remove insulated islands:
// 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
......@@ -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 */
if ( have_poly_to_substract )
{
booleng->Do_Operation( BOOL_A_SUB_B );
/* put these areas in m_FilledPolysList */
/* put these areas in m_FilledPolysList */
m_FilledPolysList.clear();
CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng;
// Remove insulated islands, if any:
// Remove insulated islands, if any:
if( GetNet() > 0 )
Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb );
}
delete booleng;
//#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
......
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