zones in pcbnew: some optimizations

This commit is contained in:
charras 2008-10-19 18:18:45 +00:00
parent fff34db7f3
commit 43ee94b7a4
6 changed files with 77 additions and 40 deletions

View File

@ -174,8 +174,8 @@ public:
/** /**
* Function GetBoundingBox * Function GetBoundingBox
* returns the bounding box of this Footprint * returns the bounding box of this pad
* Mainly used to redraw the screen area occuped by the footprint * Mainly used to redraw the screen area occuped by the pad
*/ */
EDA_Rect GetBoundingBox(); EDA_Rect GetBoundingBox();

View File

@ -11,6 +11,8 @@
#include "PolyLine.h" #include "PolyLine.h"
#include "pcbnew.h" #include "pcbnew.h"
#include "trigo.h" #include "trigo.h"
#include "zones.h"
#include "autorout.h"
/************************/ /************************/
@ -21,18 +23,18 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* parent ) :
BOARD_ITEM( parent, TYPEZONE_CONTAINER ) BOARD_ITEM( parent, TYPEZONE_CONTAINER )
{ {
m_NetCode = -1; // Net number for fast comparisons m_NetCode = -1; // Net number for fast comparisons
m_CornerSelection = -1; m_CornerSelection = -1;
m_ZoneClearance = 200; // a reasonnable clerance value m_ZoneClearance = g_DesignSettings.m_ZoneClearence; // a reasonnable clerance value
m_GridFillValue = 50; // a reasonnable grid used for filling m_GridFillValue = g_GridRoutingSize; // a reasonnable grid used for filling
m_PadOption = THERMAL_PAD; m_PadOption = g_Zone_Pad_Options;
utility = 0; // flags used in polygon calculations utility = 0; // flags used in polygon calculations
utility2 = 0; // flags used in polygon calculations utility2 = 0; // flags used in polygon calculations
m_Poly = new CPolyLine(); // Outlines m_Poly = new CPolyLine(); // Outlines
m_ArcToSegmentsCount = 16; // Use 16 segment to convert a circle to a polygon m_ArcToSegmentsCount = g_Zone_Arc_Approximation; // Use 16 or 32segment to convert a circle to a polygon
m_DrawOptions = 0; m_DrawOptions = 0;
m_ThermalReliefGapValue = 200; // tickness of the gap in thermal reliefs m_ThermalReliefGapValue = g_ThermalReliefGapValue; // tickness of the gap in thermal reliefs
m_ThermalReliefCopperBridgeValue = 200; // tickness of the copper bridge in thermal reliefs m_ThermalReliefCopperBridgeValue = g_ThermalReliefCopperBridgeValue; // tickness of the copper bridge in thermal reliefs
} }
@ -141,7 +143,7 @@ bool ZONE_CONTAINER::Save( FILE* aFile ) const
return false; return false;
ret = fprintf( aFile, "ZOptions %d %d %c %d %d\n", m_GridFillValue, m_ArcToSegmentsCount, ret = fprintf( aFile, "ZOptions %d %d %c %d %d\n", m_GridFillValue, m_ArcToSegmentsCount,
m_DrawOptions ? 'S' : 'F' , m_ThermalReliefGapValue, m_ThermalReliefCopperBridgeValue); m_DrawOptions ? 'S' : 'F', m_ThermalReliefGapValue, m_ThermalReliefCopperBridgeValue );
if( ret < 3 ) if( ret < 3 )
return false; return false;
@ -274,8 +276,8 @@ int ZONE_CONTAINER::ReadDescr( FILE* aFile, int* aLineNum )
} }
if( strnicmp( Line, "ZOptions", 8 ) == 0 ) // Options info found if( strnicmp( Line, "ZOptions", 8 ) == 0 ) // Options info found
{ {
int gridsize = 50; int gridsize = 50;
int arcsegmentcount = 16; int arcsegmentcount = 16;
char drawopt = 'F'; char drawopt = 'F';
text = Line + 8; text = Line + 8;
ret = sscanf( text, "%d %d %c %d %d", &gridsize, &arcsegmentcount, &drawopt, ret = sscanf( text, "%d %d %c %d %d", &gridsize, &arcsegmentcount, &drawopt,
@ -587,7 +589,7 @@ void ZONE_CONTAINER::DrawWhileCreateOutline( WinEDA_DrawPanel* panel, wxDC* DC,
// draw the lines // draw the lines
wxPoint start_contour_pos = GetCornerPosition( 0 ); wxPoint start_contour_pos = GetCornerPosition( 0 );
int icmax = GetNumCorners() - 1; int icmax = GetNumCorners() - 1;
for( int ic = 0; ic <= icmax; ic++ ) for( int ic = 0; ic <= icmax; ic++ )
{ {
int xi = GetCornerPosition( ic ).x; int xi = GetCornerPosition( ic ).x;
@ -609,8 +611,9 @@ void ZONE_CONTAINER::DrawWhileCreateOutline( WinEDA_DrawPanel* panel, wxDC* DC,
current_gr_mode = GR_XOR; current_gr_mode = GR_XOR;
xf = start_contour_pos.x; xf = start_contour_pos.x;
yf = start_contour_pos.y; yf = start_contour_pos.y;
// Prepare the next contour for drawing, if exists // Prepare the next contour for drawing, if exists
if ( ic < icmax ) if( ic < icmax )
start_contour_pos = GetCornerPosition( ic + 1 ); start_contour_pos = GetCornerPosition( ic + 1 );
} }
GRSetDrawMode( DC, current_gr_mode ); GRSetDrawMode( DC, current_gr_mode );

View File

@ -61,18 +61,18 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event )
SetFocus(); // Required under wxGTK if we want to demiss the dialog with the ESC key SetFocus(); // Required under wxGTK if we want to demiss the dialog with the ESC key
wxString title = _( "Zone clearance value:" ) + ReturnUnitSymbol( g_UnitMetric ); wxString msg = _( "Zone clearance value:" ) + ReturnUnitSymbol( g_UnitMetric );
m_ClearanceValueTitle->SetLabel( title ); m_ClearanceValueTitle->SetLabel( msg );
title = _( "Grid :" ) + ReturnUnitSymbol( g_UnitMetric ); msg = _( "Grid :" ) + ReturnUnitSymbol( g_UnitMetric );
m_GridCtrl->SetLabel( title ); m_GridCtrl->SetLabel( msg );
if( g_DesignSettings.m_ZoneClearence == 0 ) if( g_DesignSettings.m_ZoneClearence == 0 )
g_DesignSettings.m_ZoneClearence = g_DesignSettings.m_TrackClearence; g_DesignSettings.m_ZoneClearence = g_DesignSettings.m_TrackClearence;
title = ReturnStringFromValue( g_UnitMetric, msg = ReturnStringFromValue( g_UnitMetric,
g_DesignSettings.m_ZoneClearence, g_DesignSettings.m_ZoneClearence,
m_Parent->m_InternalUnits ); m_Parent->m_InternalUnits );
m_ZoneClearanceCtrl->SetValue( title ); m_ZoneClearanceCtrl->SetValue( msg );
if( g_Zone_45_Only ) if( g_Zone_45_Only )
m_OrientEdgesOpt->SetSelection( 1 ); m_OrientEdgesOpt->SetSelection( 1 );
@ -87,7 +87,7 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event )
for( unsigned ii = 0; ii < 4; ii++ ) for( unsigned ii = 0; ii < 4; ii++ )
{ {
wxString msg = ReturnStringFromValue( g_UnitMetric, msg = ReturnStringFromValue( g_UnitMetric,
GridList[ii], GridList[ii],
m_Parent->m_InternalUnits ); m_Parent->m_InternalUnits );
m_GridCtrl->SetString( ii, msg ); m_GridCtrl->SetString( ii, msg );
@ -101,10 +101,10 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event )
if( m_Zone_Container ) if( m_Zone_Container )
{ {
title = ReturnStringFromValue( g_UnitMetric, msg = ReturnStringFromValue( g_UnitMetric,
m_Zone_Container->m_ZoneClearance, m_Zone_Container->m_ZoneClearance,
m_Parent->m_InternalUnits ); m_Parent->m_InternalUnits );
m_ZoneClearanceCtrl->SetValue( title ); m_ZoneClearanceCtrl->SetValue( msg );
switch( m_Zone_Container->m_PadOption ) switch( m_Zone_Container->m_PadOption )
{ {
@ -193,7 +193,6 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event )
int layer_cnt = board->GetCopperLayerCount(); int layer_cnt = board->GetCopperLayerCount();
for( int ii = 0; ii < board->GetCopperLayerCount(); ii++ ) for( int ii = 0; ii < board->GetCopperLayerCount(); ii++ )
{ {
wxString msg;
int layer_number = COPPER_LAYER_N; int layer_number = COPPER_LAYER_N;
if( layer_cnt <= 1 || ii < layer_cnt - 1 ) if( layer_cnt <= 1 || ii < layer_cnt - 1 )

View File

@ -28,6 +28,7 @@ enum zone_cmd {
/* variables used in zone dialogs and functions */ /* variables used in zone dialogs and functions */
/************************************************/ /************************************************/
// @todo: make a class like ZONE_GENERAL_SETTING instead of many global variables
eda_global bool g_Zone_45_Only eda_global bool g_Zone_45_Only
#ifdef MAIN #ifdef MAIN
= FALSE = FALSE

View File

@ -68,6 +68,16 @@ void WinEDA_PcbFrame::Add_Similar_Zone( wxDC* DC, ZONE_CONTAINER* zone_container
return; return;
s_AddCutoutToCurrentZone = false; s_AddCutoutToCurrentZone = false;
s_CurrentZone = zone_container; s_CurrentZone = zone_container;
/* set zones setup to the current zone */
g_Zone_Hatching = zone_container->m_Poly->GetHatchStyle();
g_Zone_Arc_Approximation = zone_container->m_ArcToSegmentsCount;
g_ThermalReliefGapValue = zone_container->m_ThermalReliefGapValue;
g_ThermalReliefCopperBridgeValue = zone_container->m_ThermalReliefCopperBridgeValue;
g_GridRoutingSize = zone_container->m_GridFillValue;
g_Zone_Pad_Options = zone_container->m_PadOption;
// Use the general event handle to set others params (like toolbar) */
wxCommandEvent evt; wxCommandEvent evt;
evt.SetId( ID_PCB_ZONES_BUTT ); evt.SetId( ID_PCB_ZONES_BUTT );
Process_Special_Functions( evt ); Process_Special_Functions( evt );
@ -89,6 +99,16 @@ void WinEDA_PcbFrame::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container
return; return;
s_AddCutoutToCurrentZone = true; s_AddCutoutToCurrentZone = true;
s_CurrentZone = zone_container; s_CurrentZone = zone_container;
/* set zones setup to the current zone */
g_Zone_Hatching = zone_container->m_Poly->GetHatchStyle();
g_Zone_Arc_Approximation = zone_container->m_ArcToSegmentsCount;
g_ThermalReliefGapValue = zone_container->m_ThermalReliefGapValue;
g_ThermalReliefCopperBridgeValue = zone_container->m_ThermalReliefCopperBridgeValue;
g_GridRoutingSize = zone_container->m_GridFillValue;
g_Zone_Pad_Options = zone_container->m_PadOption;
// Use the general event handle to set others params (like toolbar) */
wxCommandEvent evt; wxCommandEvent evt;
evt.SetId( ID_PCB_ZONES_BUTT ); evt.SetId( ID_PCB_ZONES_BUTT );
Process_Special_Functions( evt ); Process_Special_Functions( evt );
@ -909,17 +929,16 @@ int WinEDA_PcbFrame::Fill_Zone( wxDC* DC, ZONE_CONTAINER* zone_container, bool v
wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor) wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor)
int error_level = 0; int error_level = 0;
zone_container->m_FilledPolysList.clear();
if( zone_container->m_GridFillValue == 0 ) if( zone_container->m_GridFillValue == 0 )
{ {
zone_container->m_FilledPolysList.clear();
zone_container->BuildFilledPolysListData( m_Pcb ); zone_container->BuildFilledPolysListData( m_Pcb );
if ( DC ) if ( DC )
DrawPanel->Refresh(); DrawPanel->Refresh();
} }
else else
{ {
zone_container->m_FilledPolysList.clear(); g_GridRoutingSize = zone_container->m_GridFillValue;
zone_container->m_GridFillValue = g_GridRoutingSize;
error_level = zone_container->Fill_Zone( this, DC, verbose ); error_level = zone_container->Fill_Zone( this, DC, verbose );
} }

View File

@ -91,6 +91,12 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
/* Add holes (i.e. tracks and pads areas as polygons outlines) /* Add holes (i.e. tracks and pads areas as polygons outlines)
* in GroupB in Bool_Engine * in GroupB in Bool_Engine
*/
/* items ouside the zone bounding box are skipped */
EDA_Rect item_boundingbox;
EDA_Rect zone_boundingbox = GetBoundingBox();
zone_boundingbox.Inflate(m_ZoneClearance, m_ZoneClearance);
/*
* First : Add pads * First : Add pads
*/ */
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
@ -102,19 +108,26 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
if( pad->GetNet() != GetNet() ) if( pad->GetNet() != GetNet() )
{ {
AddPadWithClearancePolygon( booleng, *pad, m_ZoneClearance ); item_boundingbox = pad->GetBoundingBox();
if ( item_boundingbox.Intersects( zone_boundingbox ) )
AddPadWithClearancePolygon( booleng, *pad, m_ZoneClearance );
continue; continue;
} }
switch( m_PadOption ) switch( m_PadOption )
{ {
case PAD_NOT_IN_ZONE: case PAD_NOT_IN_ZONE:
AddPadWithClearancePolygon( booleng, *pad, m_ZoneClearance ); item_boundingbox = pad->GetBoundingBox();
if ( item_boundingbox.Intersects( zone_boundingbox ) )
AddPadWithClearancePolygon( booleng, *pad, m_ZoneClearance );
break; break;
case THERMAL_PAD: case THERMAL_PAD:
AddThermalReliefPadPolygon( booleng, *pad, item_boundingbox = pad->GetBoundingBox();
m_ThermalReliefGapValue, m_ThermalReliefCopperBridgeValue ); item_boundingbox.Inflate(m_ThermalReliefGapValue, m_ThermalReliefGapValue);
if ( item_boundingbox.Intersects( zone_boundingbox ) )
AddThermalReliefPadPolygon( booleng, *pad,
m_ThermalReliefGapValue, m_ThermalReliefCopperBridgeValue );
break; break;
case PAD_IN_ZONE: case PAD_IN_ZONE:
@ -133,7 +146,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
continue; continue;
if( track->GetNet() == GetNet() ) if( track->GetNet() == GetNet() )
continue; continue;
AddTrackWithClearancePolygon( booleng, *track, m_ZoneClearance ); item_boundingbox = track->GetBoundingBox();
if ( item_boundingbox.Intersects( zone_boundingbox ) )
AddTrackWithClearancePolygon( booleng, *track, m_ZoneClearance );
} }
// Draw graphic items (copper texts) and board edges // Draw graphic items (copper texts) and board edges
@ -501,7 +516,7 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng,
{ {
if( aBooleng->StartPolygonAdd( GROUP_B ) ) if( aBooleng->StartPolygonAdd( GROUP_B ) )
{ {
for( int ic = 0; ic < corners_buffer.size(); ic++ ) for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
{ {
wxPoint cpos = corners_buffer[ic]; wxPoint cpos = corners_buffer[ic];
RotatePoint( &cpos, angle ); RotatePoint( &cpos, angle );
@ -517,11 +532,11 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng,
} }
// Create holes, that are the mirrored from the previous holes // Create holes, that are the mirrored from the previous holes
for( int i = 0; i < corners_buffer.size(); i++ ) for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
{ {
wxPoint swap = corners_buffer[i]; wxPoint swap = corners_buffer[ic];
swap = wxPoint( -swap.x, swap.y ); swap = wxPoint( -swap.x, swap.y );
corners_buffer[i] = swap; corners_buffer[ic] = swap;
} }
// Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg // Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg
@ -530,7 +545,7 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng,
{ {
if( aBooleng->StartPolygonAdd( GROUP_B ) ) if( aBooleng->StartPolygonAdd( GROUP_B ) )
{ {
for( int ic = 0; ic < corners_buffer.size(); ic++ ) for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
{ {
wxPoint cpos = corners_buffer[ic]; wxPoint cpos = corners_buffer[ic];
RotatePoint( &cpos, angle ); RotatePoint( &cpos, angle );