Found why remove unused thermal stubs fails sometimes.Solved
This commit is contained in:
parent
9f8e1d9d1c
commit
0d3fc60155
|
@ -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.
|
||||||
|
|
11
include/id.h
11
include/id.h
|
@ -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 )
|
||||||
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
|
||||||
* 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 )
|
||||||
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 )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 )
|
||||||
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 )
|
||||||
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();
|
|
||||||
if ( TestPointInsidePolygon( m_FilledPolysList, indexstart,
|
|
||||||
indexend, ptTest[i].x, ptTest[i].y ) == false)
|
|
||||||
{
|
|
||||||
// polygon buffer
|
|
||||||
std::vector<wxPoint> corners_buffer;
|
|
||||||
// polygons are rectangles with width of copper bridge value
|
|
||||||
const int iDTRC = m_ThermalReliefCopperBridgeValue / 2;
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
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 ) );
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
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 ) );
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
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 ) );
|
|
||||||
break;
|
|
||||||
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( -iDTRC, -iDTRC ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// add computed polygon to group_B
|
|
||||||
if( booleng->StartPolygonAdd( GROUP_B ) )
|
|
||||||
{
|
|
||||||
for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
|
|
||||||
{
|
|
||||||
wxPoint cpos = corners_buffer[ic];
|
|
||||||
RotatePoint( &cpos, fAngle ); // Rotate according to module orientation
|
|
||||||
cpos += pad->ReturnShapePos(); // Shift origin to position
|
|
||||||
booleng->AddPoint( cpos.x, cpos.y );
|
|
||||||
}
|
|
||||||
|
|
||||||
booleng->EndPolygonAdd();
|
// polygons are rectangles with width of copper bridge value
|
||||||
|
const int iDTRC = m_ThermalReliefCopperBridgeValue / 2;
|
||||||
|
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
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 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
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 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
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 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
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( -iDTRC, -iDTRC ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add computed polygon to group_B
|
||||||
|
if( booleng->StartPolygonAdd( GROUP_B ) )
|
||||||
|
{
|
||||||
|
for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
|
||||||
|
{
|
||||||
|
wxPoint cpos = corners_buffer[ic];
|
||||||
|
RotatePoint( &cpos, fAngle ); // Rotate according to module orientation
|
||||||
|
cpos += pad->ReturnShapePos(); // Shift origin to position
|
||||||
|
booleng->AddPoint( cpos.x, cpos.y );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
booleng->EndPolygonAdd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue