Enable multi-layer for keepout zones

- Load / save from PCB file correctly
- Doesn't display properly yet
- Keepout only actually applies to one layer (for now)
This commit is contained in:
Oliver Walters 2017-09-22 10:20:20 +10:00 committed by jean-pierre charras
parent 28997e7f37
commit 0f6ec7632b
13 changed files with 236 additions and 20 deletions

View File

@ -563,6 +563,7 @@ LSET FlipLayerMask( LSET aMask, int aCopperLayersCount )
for( int ii = 0; ii < innerLayerCnt; ii++ )
{
//TODO there is a problem with this code
if( internalMask[innerLayerCnt - ii + In1_Cu] )
newMask.set( ii + In1_Cu );
else

View File

@ -129,7 +129,7 @@ public:
* Function GetLayer
* returns the primary layer this item is on.
*/
PCB_LAYER_ID GetLayer() const { return m_Layer; }
virtual PCB_LAYER_ID GetLayer() const { return m_Layer; }
/**
* Function GetLayerSet

View File

@ -176,6 +176,70 @@ const wxPoint& ZONE_CONTAINER::GetPosition() const
}
PCB_LAYER_ID ZONE_CONTAINER::GetLayer() const
{
// Testing only
if( GetIsKeepout() )
{
std::cout << "GetLayer() called for keepout!" << std::endl;
}
return BOARD_ITEM::GetLayer();
}
void ZONE_CONTAINER::SetLayer( PCB_LAYER_ID aLayer )
{
SetLayerSet( LSET( aLayer ) );
m_Layer = aLayer;
}
void ZONE_CONTAINER::SetLayerSet( LSET aLayerSet )
{
if( aLayerSet.count() == 0 )
{
return;
}
if( GetIsKeepout() )
{
// Keepouts can only exist on copper layers
m_layerSet = aLayerSet & LSET::AllCuMask();
std::cout << "Setting layers of keepout: " << aLayerSet.FmtBin() << std::endl;
}
// Set the single layer to the first selected layer
m_Layer = aLayerSet.Seq()[0];
}
LSET ZONE_CONTAINER::GetLayerSet() const
{
if( GetIsKeepout() )
{
return m_layerSet;
}
else
{
return LSET( m_Layer );
}
}
bool ZONE_CONTAINER::IsOnLayer( PCB_LAYER_ID aLayer ) const
{
if( GetIsKeepout() )
{
return m_layerSet.test( aLayer );
}
return BOARD_ITEM::IsOnLayer( aLayer );
}
void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode,
const wxPoint& offset )
{
@ -188,10 +252,75 @@ void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMod
auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
auto color = frame->Settings().Colors().GetLayerColor( m_Layer );
std::cout << "Drawing zone container" << std::endl;
PCB_LAYER_ID draw_layer = UNDEFINED_LAYER;
/* Keepout zones can exist on multiple layers
* Thus, determining which color to use to render them is a bit tricky.
* In descending order of priority:
*
* 1. If in GR_HIGHLIGHT mode:
* a. If zone is on selected layer, use layer color!
* b. Else, use grey
* 1. Not in GR_HIGHLIGHT mode
* a. If zone is on selected layer, use layer color
* b. Else, use color of top-most (visible) layer
*
*/
if( GetIsKeepout() )
{
// At least one layer must be provided!
assert( GetLayerSet().count() > 0 );
// If none of the keepout layers are actually visible, return
LSET layers = GetLayerSet() & brd->GetVisibleLayers();
if( brd->IsLayerVisible( m_Layer ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
return;
// Not on any visible layer?
if( layers.count() == 0 && !( aDrawMode & GR_HIGHLIGHT ) )
{
std::cout << "No visible layers found" << std::endl;
return;
}
// Is keepout zone present on the selected layer?
if( layers.test( curr_layer ) )
{
draw_layer = curr_layer;
std::cout << "Selecting color of selected layer" << std::endl;
}
else
{
std::cout << "Selecting color of first visible layer";
// Select the first (top) visible layer
if( layers.count() > 0 )
{
draw_layer = layers.Seq()[0];
}
else
{
draw_layer = GetLayerSet().Seq()[0];
}
}
}
/* Non-keepout zones are easier to deal with
*/
else
{
if( brd->IsLayerVisible( GetLayer() ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
{
std::cout << "Not on visible layer" << std::endl;
return;
}
draw_layer = GetLayer();
}
assert( draw_layer != UNDEFINED_LAYER );
auto color = frame->Settings().Colors().GetLayerColor( draw_layer );
GRSetDrawMode( DC, aDrawMode );
DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
@ -199,11 +328,15 @@ void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMod
if( displ_opts->m_ContrastModeDisplay )
{
if( !IsOnLayer( curr_layer ) )
{
color = COLOR4D( DARKDARKGRAY );
}
}
if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
{
color.SetToLegacyHighlightColor();
}
color.a = 0.588;
@ -242,6 +375,9 @@ void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMod
void ZONE_CONTAINER::DrawFilledArea( EDA_DRAW_PANEL* panel,
wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset )
{
std::cout << "DrawFilledArea" << std::endl;
static std::vector <wxPoint> CornersBuffer;
DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
@ -262,9 +398,9 @@ void ZONE_CONTAINER::DrawFilledArea( EDA_DRAW_PANEL* panel,
PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
auto color = frame->Settings().Colors().GetLayerColor( m_Layer );
auto color = frame->Settings().Colors().GetLayerColor( GetLayer() );
if( brd->IsLayerVisible( m_Layer ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
if( brd->IsLayerVisible( GetLayer() ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
return;
GRSetDrawMode( DC, aDrawMode );
@ -389,7 +525,7 @@ void ZONE_CONTAINER::DrawWhileCreateOutline( EDA_DRAW_PANEL* panel, wxDC* DC,
PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
auto color = frame->Settings().Colors().GetLayerColor( m_Layer );
auto color = frame->Settings().Colors().GetLayerColor( GetLayer() );
DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
@ -789,7 +925,15 @@ void ZONE_CONTAINER::Flip( const wxPoint& aCentre )
{
Mirror( aCentre );
int copperLayerCount = GetBoard()->GetCopperLayerCount();
SetLayer( FlipLayer( GetLayer(), copperLayerCount ) );
if( GetIsKeepout() )
{
SetLayerSet( FlipLayerMask( GetLayerSet(), copperLayerCount ) );
}
else
{
SetLayer( FlipLayer( GetLayer(), copperLayerCount ) );
}
}

View File

@ -120,6 +120,10 @@ public:
void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) override;
void SetLayerSet( LSET aLayerSet );
virtual LSET GetLayerSet() const override;
/**
* Function Draw
* Draws the zone outline.
@ -178,9 +182,16 @@ public:
*/
bool IsOnCopperLayer() const
{
//TODO fixme!
return IsCopperLayer( GetLayer() );
}
virtual void SetLayer( PCB_LAYER_ID aLayer ) override;
virtual PCB_LAYER_ID GetLayer() const override;
virtual bool IsOnLayer( PCB_LAYER_ID ) const override;
/// How to fill areas: 0 = use filled polygons, 1 => fill with segments.
void SetFillMode( int aFillMode ) { m_FillMode = aFillMode; }
int GetFillMode() const { return m_FillMode; }
@ -725,6 +736,8 @@ private:
int m_cornerSmoothingType;
unsigned int m_cornerRadius;
LSET m_layerSet;
/* Priority: when a zone outline is inside and other zone, if its priority is higher
* the other zone priority, it will be created inside.
* if priorities are equal, a DRC error is set

View File

@ -77,7 +77,6 @@ ZONE_SETTINGS& ZONE_SETTINGS::operator << ( const ZONE_CONTAINER& aSource )
m_ZoneClearance = aSource.GetZoneClearance();
m_ZoneMinThickness = aSource.GetMinThickness();
m_NetcodeSelection = aSource.GetNetCode();
m_CurrentZone_Layer = aSource.GetLayer();
m_Zone_HatchingStyle = aSource.GetHatchStyle();
m_ArcToSegmentsCount = aSource.GetArcSegmentCount();
m_ThermalReliefGap = aSource.GetThermalReliefGap();
@ -90,6 +89,9 @@ ZONE_SETTINGS& ZONE_SETTINGS::operator << ( const ZONE_CONTAINER& aSource )
m_keepoutDoNotAllowVias = aSource.GetDoNotAllowVias();
m_keepoutDoNotAllowTracks = aSource.GetDoNotAllowTracks();
m_CurrentZone_Layer = aSource.GetLayer();
m_Layers = aSource.GetLayerSet();
return *this;
}
@ -114,7 +116,16 @@ void ZONE_SETTINGS::ExportSetting( ZONE_CONTAINER& aTarget, bool aFullExport ) c
{
aTarget.SetPriority( m_ZonePriority );
aTarget.SetNetCode( m_NetcodeSelection );
aTarget.SetLayer( m_CurrentZone_Layer );
// Keepout zones can have multiple layers
if( m_isKeepout )
{
aTarget.SetLayerSet( m_Layers );
}
else
{
aTarget.SetLayer( m_CurrentZone_Layer );
}
}
// call SetHatch last, because hatch lines will be rebuilt,

View File

@ -64,6 +64,8 @@ public:
int m_ZoneMinThickness; ///< Min thickness value in filled areas
int m_NetcodeSelection; ///< Net code selection for the current zone
LSET m_Layers;
PCB_LAYER_ID m_CurrentZone_Layer; ///< Layer used to create the current zone
/// Option to show the zone area (outlines only, short hatches or full hatches

View File

@ -89,7 +89,7 @@ private:
#define LAYER_BITMAP_SIZE_X 20
#define LAYER_BITMAP_SIZE_Y 10
#define LAYER_BITMAP_SIZE_Y 15
ZONE_EDIT_T InvokeKeepoutAreaEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aSettings )
{
@ -155,6 +155,7 @@ void DIALOG_KEEPOUT_AREA_PROPERTIES::initDialog()
// Build copper layer list and append to layer widget
LSET show = LSET::AllCuMask( board->GetCopperLayerCount() );
int imgIdx = 0;
for( LSEQ cu_stack = show.UIOrder(); cu_stack; ++cu_stack, imgIdx++ )
@ -173,7 +174,15 @@ void DIALOG_KEEPOUT_AREA_PROPERTIES::initDialog()
m_LayerSelectionCtrl->GetItemCount(), msg, imgIdx );
if( m_zonesettings.m_CurrentZone_Layer == layer )
{
//m_LayerSelectionCtrl->Select( itemIndex );
}
if( m_zonesettings.m_Layers.test( layer ) )
{
m_LayerSelectionCtrl->Select( itemIndex );
}
}
m_LayerSelectionCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE);
@ -213,6 +222,25 @@ bool DIALOG_KEEPOUT_AREA_PROPERTIES::AcceptOptionsForKeepOut()
return false;
}
// Copy the layers across
LSET layers;
for( int ii = 0; ii < m_LayerSelectionCtrl->GetItemCount(); ii++ )
{
if( m_LayerSelectionCtrl->IsSelected( ii ) )
{
layers.set( ToLAYER_ID( m_layerId[ii] ) );
}
}
if( layers.count() == 0 )
{
DisplayError( NULL, _( "No layers selected." ) );
return false;
}
m_zonesettings.m_Layers = layers;
// Get the layer selection for this zone
int ii = m_LayerSelectionCtrl->GetFirstSelected();
@ -224,6 +252,8 @@ bool DIALOG_KEEPOUT_AREA_PROPERTIES::AcceptOptionsForKeepOut()
m_zonesettings.m_CurrentZone_Layer = ToLAYER_ID( m_layerId[ii] );
// Set zone layers
switch( m_OutlineAppearanceCtrl->GetSelection() )
{
case 0:

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version May 6 2016)
// C++ code generated with wxFormBuilder (version Mar 22 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@ -26,11 +26,11 @@ DIALOG_KEEPOUT_AREA_PROPERTIES_BASE::DIALOG_KEEPOUT_AREA_PROPERTIES_BASE( wxWind
wxBoxSizer* m_layersListSizer;
m_layersListSizer = new wxBoxSizer( wxVERTICAL );
m_staticTextLayerSelection = new wxStaticText( this, wxID_ANY, _("Layer:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextLayerSelection = new wxStaticText( this, wxID_ANY, _("Keepout Zone Layers"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextLayerSelection->Wrap( -1 );
m_layersListSizer->Add( m_staticTextLayerSelection, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_LayerSelectionCtrl = new wxListView( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_ALIGN_LEFT|wxLC_NO_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL );
m_LayerSelectionCtrl = new wxListView( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_ALIGN_LEFT|wxLC_HRULES|wxLC_NO_HEADER|wxLC_REPORT );
m_layersListSizer->Add( m_LayerSelectionCtrl, 1, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );

View File

@ -143,7 +143,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Layer:</property>
<property name="label">Keepout Zone Layers</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
@ -243,7 +243,7 @@
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxLC_ALIGN_LEFT|wxLC_NO_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL</property>
<property name="style">wxLC_ALIGN_LEFT|wxLC_HRULES|wxLC_NO_HEADER|wxLC_REPORT</property>
<property name="subclass">wxListView; </property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version May 6 2016)
// C++ code generated with wxFormBuilder (version Mar 22 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!

View File

@ -1609,7 +1609,15 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
aZone->GetIsKeepout() ? 0 : m_mapping->Translate( aZone->GetNetCode() ),
m_out->Quotew( aZone->GetIsKeepout() ? wxT("") : aZone->GetNetname() ).c_str() );
formatLayer( aZone );
// Keepout zones can exist on multiple layers
if( aZone->GetIsKeepout() && aZone->GetLayerSet().count() > 1 )
{
formatLayers( aZone->GetLayerSet() );
}
else
{
formatLayer( aZone );
}
m_out->Print( 0, " (tstamp %lX)", (unsigned long) aZone->GetTimeStamp() );

View File

@ -43,7 +43,8 @@ class NETINFO_MAPPING;
// // went to 32 Cu layers from 16.
//#define SEXPR_BOARD_FILE_VERSION 20160815 // differential pair settings per net class
//#define SEXPR_BOARD_FILE_VERSION 20170123 // EDA_TEXT refactor, moved 'hide'
#define SEXPR_BOARD_FILE_VERSION 20170920 // long pad names and custom pad shape
//#define SEXPR_BOARD_FILE_VERSION 20170920 // long pad names and custom pad shape
#define SEXPR_BOARD_FILE_VERSION 20170922 // Keepout zones can exist on multiple layers
#define CTL_STD_LAYER_NAMES (1 << 0) ///< Use English Standard layer names
#define CTL_OMIT_NETS (1 << 1) ///< Omit pads net names (useless in library)

View File

@ -2825,6 +2825,12 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER()
NeedRIGHT();
break;
case T_layers:
// If multiple layers are specified, it is a keepout zone
zone->SetIsKeepout( true );
zone->SetLayerSet( parseBoardItemLayersAsMask() );
break;
case T_tstamp:
zone->SetTimeStamp( parseHex() );
NeedRIGHT();
@ -3075,7 +3081,7 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER()
break;
default:
Expecting( "net, layer, tstamp, hatch, priority, connect_pads, min_thickness, "
Expecting( "net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
"fill, polygon, filled_polygon, or fill_segments" );
}
}