Found why remove unused thermal stubs fails sometimes.Solved

This commit is contained in:
charras 2009-01-18 13:14:50 +00:00
parent 9f8e1d9d1c
commit 0d3fc60155
4 changed files with 135 additions and 102 deletions

View File

@ -5,7 +5,14 @@ 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-Jan-11 UPDATE Wayne Stambaugh <stambaughw@verizon.net> 2009-Jan-17 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
++pcbnew:
Found why remove unused thermal stubs fails sometimes:
Only the first filled area in a zone was tested.
Solved.
2009-Jan-18 UPDATE Wayne Stambaugh <stambaughw@verizon.net>
================================================================================ ================================================================================
++All ++All
* Replace Kicad file history implementation with wxFileHistory. * Replace Kicad file history implementation with wxFileHistory.

View File

@ -48,17 +48,6 @@ enum main_id {
ID_LOAD_PROJECT, ID_LOAD_PROJECT,
ID_LOAD_ONE_SHEET, ID_LOAD_ONE_SHEET,
ID_NEW_PROJECT, ID_NEW_PROJECT,
ID_LOAD_FILE_1,
ID_LOAD_FILE_2,
ID_LOAD_FILE_3,
ID_LOAD_FILE_4,
ID_LOAD_FILE_5,
ID_LOAD_FILE_6,
ID_LOAD_FILE_7,
ID_LOAD_FILE_8,
ID_LOAD_FILE_9,
ID_LOAD_FILE_10,
ID_SAVE_PROJECT, ID_SAVE_PROJECT,
ID_SAVE_ONE_SHEET, ID_SAVE_ONE_SHEET,
ID_SAVE_ONE_SHEET_AS, ID_SAVE_ONE_SHEET_AS,

View File

@ -48,9 +48,9 @@ BEGIN_EVENT_TABLE( WinEDA_PcbFrame, WinEDA_BasePcbFrame )
EVT_MENU( ID_MENU_SAVE_BOARD, WinEDA_PcbFrame::Files_io ) EVT_MENU( ID_MENU_SAVE_BOARD, WinEDA_PcbFrame::Files_io )
EVT_MENU( ID_MENU_APPEND_FILE, WinEDA_PcbFrame::Files_io ) EVT_MENU( ID_MENU_APPEND_FILE, WinEDA_PcbFrame::Files_io )
EVT_MENU( ID_MENU_SAVE_BOARD_AS, WinEDA_PcbFrame::Files_io ) EVT_MENU( ID_MENU_SAVE_BOARD_AS, WinEDA_PcbFrame::Files_io )
EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, WinEDA_PcbFrame::OnFileHistory )
EVT_MENU( ID_GEN_PLOT, WinEDA_PcbFrame::ToPlotter ) EVT_MENU( ID_GEN_PLOT, WinEDA_PcbFrame::ToPlotter )
EVT_MENU_RANGE( ID_LOAD_FILE_1, ID_LOAD_FILE_10,
WinEDA_PcbFrame::Files_io )
EVT_MENU( ID_GEN_EXPORT_SPECCTRA, WinEDA_PcbFrame::ExportToSpecctra ) EVT_MENU( ID_GEN_EXPORT_SPECCTRA, WinEDA_PcbFrame::ExportToSpecctra )
EVT_MENU( ID_GEN_EXPORT_FILE_GENCADFORMAT, WinEDA_PcbFrame::ExportToGenCAD ) EVT_MENU( ID_GEN_EXPORT_FILE_GENCADFORMAT, WinEDA_PcbFrame::ExportToGenCAD )

View File

@ -295,16 +295,31 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
delete booleng; delete booleng;
} }
// 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. // 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
#ifdef REMOVE_UNUSED_THERMAL_STUBS #ifdef REMOVE_UNUSED_THERMAL_STUBS
// first compute endindex for TestPointInsidePolygon
/* First, Create the list of filled areas begin and end indexes.
* Because a zone creates more than one filled sub area,
* we must handle all start and end points of all sub areas
* for TestPointInsidePolygon, to search if a point is in a filled area in zone
*/
std::vector <int> filled_areas_begin_end_index_list;
unsigned int indexstart = 0, indexend; unsigned int indexstart = 0, indexend;
for( indexend = 0; indexend < m_FilledPolysList.size(); indexend++ ) for( indexend = 0; indexend < m_FilledPolysList.size(); indexend++ )
{ {
if( m_FilledPolysList[indexend].end_contour ) // end of a filled sub-area found if( m_FilledPolysList[indexend].end_contour ) // end of a filled sub-area found
{ {
break; filled_areas_begin_end_index_list.push_back( indexstart );
filled_areas_begin_end_index_list.push_back( indexend );
indexstart = indexend + 1;
} }
} }
@ -328,25 +343,21 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() ) for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() )
{ {
// check // check
if( pad->IsOnLayer( GetLayer() ) if( !pad->IsOnLayer( GetLayer() ) )
&& pad->GetNet() == GetNet() continue;
&& m_PadOption == THERMAL_PAD ) if( pad->GetNet() != GetNet() )
{ continue;
item_boundingbox = pad->GetBoundingBox(); item_boundingbox = pad->GetBoundingBox();
item_boundingbox.Inflate( m_ThermalReliefGapValue, m_ThermalReliefGapValue ); item_boundingbox.Inflate( m_ThermalReliefGapValue, m_ThermalReliefGapValue );
if( !( item_boundingbox.Intersects( zone_boundingbox ) ) ) if( !( item_boundingbox.Intersects( zone_boundingbox ) ) )
continue; continue;
// test point // test point
int dx = (pad->m_Size.x / 2) + m_ThermalReliefGapValue + 3; int dx =
int dy = (pad->m_Size.y / 2) + m_ThermalReliefGapValue + 3; ( pad->m_Size.x / 2 ) + m_ThermalReliefGapValue;
int dy =
// compute north, south, west and east points for zone connection. ( pad->m_Size.y / 2 ) + m_ThermalReliefGapValue;
wxPoint ptTest[4];
ptTest[0] = wxPoint(0, dy+m_ZoneMinThickness/2);
ptTest[1] = wxPoint(0, -(dy+m_ZoneMinThickness/2));
ptTest[2] = wxPoint( dx+m_ZoneMinThickness/2, 0);
ptTest[3] = wxPoint(-(dx+m_ZoneMinThickness/2), 0);
// This is CIRCLE pad tweak (for circle pads the thermal stubs are at 45 deg) // This is CIRCLE pad tweak (for circle pads the thermal stubs are at 45 deg)
int fAngle = pad->m_Orient; int fAngle = pad->m_Orient;
@ -357,38 +368,65 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
fAngle = 450; fAngle = 450;
} }
// compute north, south, west and east points for zone connection.
// Add a small value to ensure point is inside zone, not on an edge
wxPoint ptTest[4];
ptTest[0] = wxPoint( 0, 3 + dy + m_ZoneMinThickness / 2 );
ptTest[1] = wxPoint( 0, -(3 + dy + m_ZoneMinThickness / 2) );
ptTest[2] = wxPoint( 3 + dx + m_ZoneMinThickness / 2, 0 );
ptTest[3] = wxPoint( -(3 + dx + m_ZoneMinThickness / 2), 0 );
// Test all sides // Test all sides
for (int i=0; i<4; i++) { for( int i = 0; i<4; i++ )
{
// rotate point // rotate point
RotatePoint( &ptTest[i], fAngle ); RotatePoint( &ptTest[i], fAngle );
// translate point // translate point
ptTest[i] += pad->ReturnShapePos(); ptTest[i] += pad->ReturnShapePos();
if ( TestPointInsidePolygon( m_FilledPolysList, indexstart, bool inside = false;
indexend, ptTest[i].x, ptTest[i].y ) == false) for( unsigned idx = 0;
idx < filled_areas_begin_end_index_list.size() && inside == false;
idx += 2 )
{
indexstart = filled_areas_begin_end_index_list[idx];
indexend = filled_areas_begin_end_index_list[idx + 1];
inside = TestPointInsidePolygon( m_FilledPolysList, indexstart,
indexend, ptTest[i].x, ptTest[i].y );
}
if( inside == false )
{ {
// polygon buffer // polygon buffer
std::vector<wxPoint> corners_buffer; std::vector<wxPoint> corners_buffer;
// polygons are rectangles with width of copper bridge value // polygons are rectangles with width of copper bridge value
const int iDTRC = m_ThermalReliefCopperBridgeValue / 2; const int iDTRC = m_ThermalReliefCopperBridgeValue / 2;
switch (i) {
switch( i )
{
case 0: case 0:
corners_buffer.push_back( wxPoint( -iDTRC, dy ) ); corners_buffer.push_back( wxPoint( -iDTRC, dy ) );
corners_buffer.push_back( wxPoint( +iDTRC, dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, dy ) );
corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) );
break; break;
case 1: case 1:
corners_buffer.push_back( wxPoint( -iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( -iDTRC, -dy ) );
corners_buffer.push_back( wxPoint( +iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, -dy ) );
corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) );
break; break;
case 2: case 2:
corners_buffer.push_back( wxPoint( dx, -iDTRC ) ); corners_buffer.push_back( wxPoint( dx, -iDTRC ) );
corners_buffer.push_back( wxPoint( dx, iDTRC ) ); corners_buffer.push_back( wxPoint( dx, iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) );
break; break;
case 3: case 3:
corners_buffer.push_back( wxPoint( -dx, -iDTRC ) ); corners_buffer.push_back( wxPoint( -dx, -iDTRC ) );
corners_buffer.push_back( wxPoint( -dx, iDTRC ) ); corners_buffer.push_back( wxPoint( -dx, iDTRC ) );
@ -396,6 +434,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) );
break; break;
} }
// add computed polygon to group_B // add computed polygon to group_B
if( booleng->StartPolygonAdd( GROUP_B ) ) if( booleng->StartPolygonAdd( GROUP_B ) )
{ {
@ -413,7 +452,6 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
} }
} }
} }
}
/* compute copper areas */ /* compute copper areas */
booleng->Do_Operation( BOOL_A_SUB_B ); booleng->Do_Operation( BOOL_A_SUB_B );
@ -423,11 +461,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
CopyPolygonsFromBoolengineToFilledPolysList( booleng ); CopyPolygonsFromBoolengineToFilledPolysList( booleng );
delete booleng; delete booleng;
#endif // Remove insulated islands, if any:
// 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 );
#endif
} }