Commit 0d3fc601 authored by charras's avatar charras

Found why remove unused thermal stubs fails sometimes.Solved

parent 9f8e1d9d
...@@ -5,7 +5,14 @@ Started 2007-June-11 ...@@ -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.
......
...@@ -48,17 +48,6 @@ enum main_id { ...@@ -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,
......
...@@ -48,9 +48,9 @@ BEGIN_EVENT_TABLE( WinEDA_PcbFrame, WinEDA_BasePcbFrame ) ...@@ -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 )
......
...@@ -95,13 +95,13 @@ double s_Correction; /* mult coeff used to enlarge rounded and oval pads (an ...@@ -95,13 +95,13 @@ double s_Correction; /* mult coeff used to enlarge rounded and oval pads (an
* 11 - Remove new insulated copper islands * 11 - Remove new insulated copper islands
*/ */
/* Important note: /* Important note:
* One can add thermal areas in the step 6, with others items to substract. * One can add thermal areas in the step 6, with others items to substract.
* It is faster. * It is faster.
* But : * But :
* kbool fails sometimes in this case (see comments in AddThermalReliefPadPolygon ) * kbool fails sometimes in this case (see comments in AddThermalReliefPadPolygon )
* The separate step to make thermal shapes allows a more sophisticated algorith (todo) * The separate step to make thermal shapes allows a more sophisticated algorith (todo)
* like remove thermal copper bridges in thermal shapes that are not connected to an area * like remove thermal copper bridges in thermal shapes that are not connected to an area
*/ */
void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
{ {
...@@ -188,7 +188,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -188,7 +188,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
continue; continue;
} }
if ( (m_PadOption == PAD_NOT_IN_ZONE) || (GetNet() == 0) ) if( (m_PadOption == PAD_NOT_IN_ZONE) || (GetNet() == 0) )
{ {
item_boundingbox = pad->GetBoundingBox(); item_boundingbox = pad->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) ) if( item_boundingbox.Intersects( zone_boundingbox ) )
...@@ -280,7 +280,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -280,7 +280,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
} }
} }
if ( have_poly_to_substract ) if( have_poly_to_substract )
{ {
/* Add the main corrected polygon (i.e. the filled area using only one outline) /* Add the main corrected polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine * in GroupA in Bool_Engine
...@@ -295,16 +295,31 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -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
unsigned int indexstart = 0, indexend; /* 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;
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,87 +343,110 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -328,87 +343,110 @@ 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.Inflate( m_ThermalReliefGapValue, m_ThermalReliefGapValue );
if( !( item_boundingbox.Intersects( zone_boundingbox ) ) )
continue;
// test point
int dx =
( pad->m_Size.x / 2 ) + m_ThermalReliefGapValue;
int dy =
( pad->m_Size.y / 2 ) + m_ThermalReliefGapValue;
// This is CIRCLE pad tweak (for circle pads the thermal stubs are at 45 deg)
int fAngle = pad->m_Orient;
if( pad->m_PadShape == PAD_CIRCLE )
{ {
item_boundingbox = pad->GetBoundingBox(); dx = (int) ( dx * s_Correction );
item_boundingbox.Inflate( m_ThermalReliefGapValue, m_ThermalReliefGapValue ); dy = dx;
if( !(item_boundingbox.Intersects( zone_boundingbox )) ) fAngle = 450;
continue; }
// test point // compute north, south, west and east points for zone connection.
int dx = (pad->m_Size.x / 2) + m_ThermalReliefGapValue + 3; // Add a small value to ensure point is inside zone, not on an edge
int dy = (pad->m_Size.y / 2) + m_ThermalReliefGapValue + 3; 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 );
// compute north, south, west and east points for zone connection.
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) // Test all sides
int fAngle = pad->m_Orient; for( int i = 0; i<4; i++ )
if ( pad->m_PadShape == PAD_CIRCLE) {
// rotate point
RotatePoint( &ptTest[i], fAngle );
// translate point
ptTest[i] += pad->ReturnShapePos();
bool inside = false;
for( unsigned idx = 0;
idx < filled_areas_begin_end_index_list.size() && inside == false;
idx += 2 )
{ {
dx = (int) (dx * s_Correction); indexstart = filled_areas_begin_end_index_list[idx];
dy = dx; indexend = filled_areas_begin_end_index_list[idx + 1];
fAngle = 450; inside = TestPointInsidePolygon( m_FilledPolysList, indexstart,
indexend, ptTest[i].x, ptTest[i].y );
} }
// Test all sides if( inside == false )
for (int i=0; i<4; i++) { {
// rotate point // polygon buffer
RotatePoint( &ptTest[i], fAngle ); std::vector<wxPoint> corners_buffer;
// translate point
ptTest[i] += pad->ReturnShapePos(); // polygons are rectangles with width of copper bridge value
if ( TestPointInsidePolygon( m_FilledPolysList, indexstart, const int iDTRC = m_ThermalReliefCopperBridgeValue / 2;
indexend, ptTest[i].x, ptTest[i].y ) == false)
switch( i )
{ {
// polygon buffer case 0:
std::vector<wxPoint> corners_buffer; corners_buffer.push_back( wxPoint( -iDTRC, dy ) );
// polygons are rectangles with width of copper bridge value corners_buffer.push_back( wxPoint( +iDTRC, dy ) );
const int iDTRC = m_ThermalReliefCopperBridgeValue / 2; corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
switch (i) { corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) );
case 0: break;
corners_buffer.push_back( wxPoint( -iDTRC, dy) );
corners_buffer.push_back( wxPoint( +iDTRC, dy) ); case 1:
corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -dy ) );
corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, -dy ) );
break; corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) );
case 1: corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, -dy ) ); break;
corners_buffer.push_back( wxPoint( +iDTRC, -dy ) );
corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); case 2:
corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( dx, -iDTRC ) );
break; corners_buffer.push_back( wxPoint( dx, iDTRC ) );
case 2: corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( dx, -iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) );
corners_buffer.push_back( wxPoint( dx, iDTRC ) ); break;
corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) );
corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); case 3:
break; corners_buffer.push_back( wxPoint( -dx, -iDTRC ) );
case 3: 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( -dx, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) );
corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) ); break;
corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); }
break;
} // add computed polygon to group_B
// add computed polygon to group_B if( booleng->StartPolygonAdd( GROUP_B ) )
if( booleng->StartPolygonAdd( GROUP_B ) ) {
for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
{ {
for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) wxPoint cpos = corners_buffer[ic];
{ RotatePoint( &cpos, fAngle ); // Rotate according to module orientation
wxPoint cpos = corners_buffer[ic]; cpos += pad->ReturnShapePos(); // Shift origin to position
RotatePoint( &cpos, fAngle ); // Rotate according to module orientation booleng->AddPoint( cpos.x, cpos.y );
cpos += pad->ReturnShapePos(); // Shift origin to position
booleng->AddPoint( cpos.x, cpos.y );
}
booleng->EndPolygonAdd();
} }
booleng->EndPolygonAdd();
} }
} }
} }
...@@ -423,11 +461,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -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
} }
......
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