Reorganize layer numbering

F_Cu = 0
B_Cu = 2
Remaining internal copper layers are even and incrementing

Non-copper layers are odd and incrementing.

This means that we can no longer do things like:
for( PCB_LAYER_ID layer = F_Cu; layer <= B_Cu; ++layer)
Instead, we have the class LAYER_RANGE:
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu) )

Similarly, gt/lt tests should not refer to the integer value of the
layer.  We have functions such as IsCopperLayer to test whether a layer
is copper or not.

When using the connectivity RTree, the third dimension is layer, so we
provide B_Cu with the special INT_MAX value, ensuring that elements
between F_Cu and B_Cu will be identified.  There is a new, special
function GetBoardLayer() for interfacing with CN_ITEMS

Similarly, PNS layers remain unchanged and sequential.  A set of
interface functions is provided to map PNS layers to Board layers and
back.  This allows the PNS_LAYER_RANGE to function as expected
This commit is contained in:
Seth Hillbrand 2024-07-21 10:49:18 -07:00
parent b99a43bec2
commit 5e0abadb23
107 changed files with 6682 additions and 1105 deletions

View File

@ -31,6 +31,7 @@
#include <3d_rendering/raytracing/shapes2D/polygon_2d.h>
#include <board.h>
#include <dialogs/dialog_color_picker.h>
#include <layer_range.h>
#include <3d_math.h>
#include "3d_fastmath.h"
#include <geometry/geometry_utils.h>
@ -434,14 +435,16 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
// Top = Bottom - m_copperThickness
unsigned int layer;
LSET copperLayers = LSET::AllCuMask();
for( layer = 0; layer < m_copperLayersCount; ++layer )
for( auto layer : LAYER_RANGE( F_Cu, B_Cu, m_copperLayersCount ) )
{
// This approximates internal layer positions (because we're treating all the dielectric
// layers as having the same thickness). But we don't render them anyway so it doesn't
// really matter.
m_layerZcoordBottom[layer] = m_boardBodyThickness3DU / 2.0f -
(m_boardBodyThickness3DU * layer / (m_copperLayersCount - 1) );
m_layerZcoordBottom[layer] = m_boardBodyThickness3DU / 2.0f
- ( m_boardBodyThickness3DU * static_cast<int>( layer )
/ ( 2 * ( m_copperLayersCount - 1 ) ) );
if( layer < (m_copperLayersCount / 2) )
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_frontCopperThickness3DU;
@ -452,20 +455,13 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
#define layerThicknessMargin 1.1
const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
// Fill remaining unused copper layers and back layer zpos with -m_boardBodyThickness / 2.0
for( ; layer < MAX_CU_LAYERS; layer++ )
{
m_layerZcoordBottom[layer] = -( m_boardBodyThickness3DU / 2.0f );
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_backCopperThickness3DU;
}
// This is the top of the copper layer thickness.
const float zpos_copperTop_back = m_layerZcoordTop[B_Cu];
const float zpos_copperTop_front = m_layerZcoordTop[F_Cu];
// calculate z position for each non copper layer
// Solder mask and Solder paste have the same Z position
for( int layer_id = MAX_CU_LAYERS; layer_id < PCB_LAYER_ID_COUNT; ++layer_id )
for( PCB_LAYER_ID layer_id : { B_Adhes, B_Mask, B_Paste, F_Adhes, F_Mask, F_Paste, B_SilkS, F_SilkS } )
{
float zposTop;
float zposBottom;
@ -513,12 +509,10 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
break;
default:
zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset;
zposBottom = zposTop - m_nonCopperLayerThickness3DU;
break;
}
m_layerZcoordTop[layer_id] = zposTop;
m_layerZcoordTop[layer_id] = zposTop;
m_layerZcoordBottom[layer_id] = zposBottom;
}
@ -957,9 +951,17 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
float BOARD_ADAPTER::GetFootprintZPos( bool aIsFlipped ) const
{
if( aIsFlipped )
return m_layerZcoordBottom[B_Paste];
{
if( auto it = m_layerZcoordBottom.find( B_Paste ); it != m_layerZcoordBottom.end() )
return it->second;
}
else
return m_layerZcoordTop[F_Paste];
{
if( auto it = m_layerZcoordTop.find( F_Paste ); it != m_layerZcoordTop.end() )
return it->second;
}
return 0.0;
}

View File

@ -236,7 +236,12 @@ public:
*/
float GetLayerTopZPos( PCB_LAYER_ID aLayerId ) const noexcept
{
return m_layerZcoordTop[aLayerId];
auto it = m_layerZcoordTop.find( aLayerId );
if( it != m_layerZcoordTop.end() )
return it->second;
else
return -( m_boardBodyThickness3DU / 2.0f );
}
/**
@ -247,7 +252,12 @@ public:
*/
float GetLayerBottomZPos( PCB_LAYER_ID aLayerId ) const noexcept
{
return m_layerZcoordBottom[aLayerId];
auto it = m_layerZcoordBottom.find( aLayerId );
if( it != m_layerZcoordBottom.end() )
return it->second;
else
return -( m_boardBodyThickness3DU / 2.0f ) - m_backCopperThickness3DU;
}
/**
@ -488,11 +498,11 @@ private:
double m_biuTo3Dunits; ///< Scale factor to convert board internal units
///< to 3D units normalized between -1.0 and 1.0.
std::array<float, PCB_LAYER_ID_COUNT> m_layerZcoordTop; ///< Top (End) Z position of each
///< layer in 3D units.
std::map<PCB_LAYER_ID, float> m_layerZcoordTop; ///< Top (End) Z position of each
///< layer in 3D units.
std::array<float, PCB_LAYER_ID_COUNT> m_layerZcoordBottom; ///< Bottom (Start) Z position of
///< each layer in 3D units.
std::map<PCB_LAYER_ID, float> m_layerZcoordBottom; ///< Bottom (Start) Z position of
///< each layer in 3D units.
float m_frontCopperThickness3DU;
float m_backCopperThickness3DU;

View File

@ -38,6 +38,7 @@
#include <board_design_settings.h>
#include <board.h>
#include <footprint.h>
#include <layer_range.h>
#include <lset.h>
#include <pad.h>
#include <pcb_text.h>
@ -162,9 +163,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
int64_t start_Time = stats_startCopperLayersTime;
#endif
PCB_LAYER_ID cu_seq[MAX_CU_LAYERS];
LSET cu_set = LSET::AllCuMask( m_copperLayersCount );
EDA_3D_VIEWER_SETTINGS::RENDER_SETTINGS& cfg = m_Cfg->m_Render;
std::bitset<LAYER_3D_END> visibilityFlags = GetVisibleLayers();
@ -220,10 +218,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
layer_ids.clear();
layer_ids.reserve( m_copperLayersCount );
for( unsigned i = 0; i < arrayDim( cu_seq ); ++i )
cu_seq[i] = ToLAYER_ID( B_Cu - i );
for( PCB_LAYER_ID layer : cu_set.Seq( cu_seq, arrayDim( cu_seq ) ) )
for( PCB_LAYER_ID layer : LAYER_RANGE( B_Cu, F_Cu, m_copperLayersCount ) )
{
if( !Is3dLayerEnabled( layer, visibilityFlags ) ) // Skip non enabled layers
continue;
@ -795,7 +790,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// draw graphic items, on technical layers
static const PCB_LAYER_ID techLayerList[] = {
LSEQ techLayerList = LSET::AllNonCuMask().Seq( {
B_Adhes,
F_Adhes,
B_Paste,
@ -810,7 +805,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
Cmts_User,
Eco1_User,
Eco2_User
};
} );
std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
@ -820,7 +815,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
enabledFlags.set( LAYER_3D_SOLDERMASK_BOTTOM );
}
for( PCB_LAYER_ID layer : LSET::AllNonCuMask().Seq( techLayerList, arrayDim( techLayerList ) ) )
for( PCB_LAYER_ID layer : techLayerList )
{
if( aStatusReporter )
aStatusReporter->Report( wxString::Format( _( "Build Tech layer %d" ), (int) layer ) );

View File

@ -604,7 +604,8 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
if( layerFlags.test( LAYER_3D_BOARD ) && m_boardAdapter.m_BoardBodyColor.a > opacity_min )
{
if( layer > F_Cu && layer < B_Cu )
// B_Cu is layer 2 and all inner layers are higher values
if( layer > B_Cu )
continue;
}

View File

@ -280,6 +280,7 @@ target_include_directories( kicommon
PUBLIC
.
${CMAKE_BINARY_DIR}
$<TARGET_PROPERTY:dynamic_bitset,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:magic_enum,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:pegtl,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:expected,INTERFACE_INCLUDE_DIRECTORIES>

View File

@ -102,6 +102,10 @@ wxString LayerName( int aLayer )
case PCB_LAYER_ID::User_7: return wxT( "User.7" );
case PCB_LAYER_ID::User_8: return wxT( "User.8" );
case PCB_LAYER_ID::User_9: return wxT( "User.9" );
case 57: return wxT( "User.10" );
case 59: return wxT( "User.11" );
case 61: return wxT( "User.12" );
case 63: return wxT( "User.13" );
// Rescue
case PCB_LAYER_ID::Rescue: return _( "Rescue" );

View File

@ -28,9 +28,11 @@
#include <cstdarg>
#include <iostream> // for string, endl, basic_ost...
#include <cstddef> // for size_t
#include <map>
#include <core/arraydim.h>
#include <layer_ids.h> // for PCB_LAYER_ID
#include <layer_range.h>
#include <lseq.h>
#include <macros.h> // for arrayDim
#include <wx/debug.h> // for wxASSERT, wxASSERT_MSG
@ -55,49 +57,128 @@ LSET::LSET( const LSEQ& aSeq ) :
}
LSET::LSET( const LAYER_RANGE& aRange )
{
for( PCB_LAYER_ID layer : aRange )
set( layer );
}
int LSET::LayerCount( PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, int aCopperLayerCount )
{
int start = aStart;
int end = aEnd;
// Both layers need to be copper
wxCHECK( IsCopperLayer( aStart ) && IsCopperLayer( aEnd ), aCopperLayerCount );
if( aStart == B_Cu )
std::swap( start, end );
if( aStart == aEnd )
return 1;
if( aStart == F_Cu )
{
if ( aEnd == B_Cu )
return aCopperLayerCount;
else
return ( end - start ) / 2 - 1;
}
else if ( aEnd == B_Cu )
{
// Add 1 for the B_Cu layer
return aCopperLayerCount - start / 2 + 1;
}
return ( end - start ) / 2;
}
int LSET::NameToLayer( wxString& aName )
{
std::map<wxString, PCB_LAYER_ID> layerMap = {
{ "F.Cu", F_Cu },
{ "B.Cu", B_Cu },
{ "F.Adhes", F_Adhes },
{ "B.Adhes", B_Adhes },
{ "F.Paste", F_Paste },
{ "B.Paste", B_Paste },
{ "F.SilkS", F_SilkS },
{ "B.SilkS", B_SilkS },
{ "F.Mask", F_Mask },
{ "B.Mask", B_Mask },
{ "Dwgs.User", Dwgs_User },
{ "Cmts.User", Cmts_User },
{ "Eco1.User", Eco1_User },
{ "Eco2.User", Eco2_User },
{ "Edge.Cuts", Edge_Cuts },
{ "Margin", Margin },
{ "F.CrtYd", F_CrtYd },
{ "B.CrtYd", B_CrtYd },
{ "F.Fab", F_Fab },
{ "B.Fab", B_Fab },
{ "Rescue", Rescue },
{ "B.Cu", B_Cu },
};
if( auto it = layerMap.find( aName ); it != layerMap.end() )
return static_cast<int>( it->second );
if( aName.StartsWith( "User." ) )
{
long offset;
if( aName.Mid( 5 ).ToLong( &offset ) && offset > 0 )
return static_cast<int>( User_1 ) + ( offset - 1 ) * 2;
}
if( aName.StartsWith( "In" ) )
{
long offset;
wxString str_num = aName.Mid( 2 );
str_num.RemoveLast( 3 ); // Removes .Cu
if( str_num.ToLong( &offset ) && offset > 0 )
return static_cast<int>( In1_Cu ) + ( offset - 1 ) * 2;
}
return -1;
}
bool LSET::IsBetween( PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, PCB_LAYER_ID aLayer )
{
if( aLayer == aStart || aLayer == aEnd )
return true;
int start = std::min( aStart, aEnd );
int end = std::max( aStart, aEnd );
int layer = aLayer;
if( end == B_Cu )
{
//Reassign the end layer to the largest possible positive even number
end = std::numeric_limits<PCB_LAYER_ID>::max() & ~1;
}
return !( layer & 1 ) && ( layer >= start ) && ( layer <= end );
}
/**
* NOTE: These names must not be translated or changed. They are used as tokens in the board
* file format because the ordinal value of the PCB_LAYER_ID enum was not stable over time.
* @see LayerName() for what should be used to display the default name of a layer in the GUI.
*/
const wxChar* LSET::Name( PCB_LAYER_ID aLayerId )
wxString LSET::Name( PCB_LAYER_ID aLayerId )
{
const wxChar* txt;
wxString txt;
// using a switch to explicitly show the mapping more clearly
switch( aLayerId )
{
case F_Cu: txt = wxT( "F.Cu" ); break;
case In1_Cu: txt = wxT( "In1.Cu" ); break;
case In2_Cu: txt = wxT( "In2.Cu" ); break;
case In3_Cu: txt = wxT( "In3.Cu" ); break;
case In4_Cu: txt = wxT( "In4.Cu" ); break;
case In5_Cu: txt = wxT( "In5.Cu" ); break;
case In6_Cu: txt = wxT( "In6.Cu" ); break;
case In7_Cu: txt = wxT( "In7.Cu" ); break;
case In8_Cu: txt = wxT( "In8.Cu" ); break;
case In9_Cu: txt = wxT( "In9.Cu" ); break;
case In10_Cu: txt = wxT( "In10.Cu" ); break;
case In11_Cu: txt = wxT( "In11.Cu" ); break;
case In12_Cu: txt = wxT( "In12.Cu" ); break;
case In13_Cu: txt = wxT( "In13.Cu" ); break;
case In14_Cu: txt = wxT( "In14.Cu" ); break;
case In15_Cu: txt = wxT( "In15.Cu" ); break;
case In16_Cu: txt = wxT( "In16.Cu" ); break;
case In17_Cu: txt = wxT( "In17.Cu" ); break;
case In18_Cu: txt = wxT( "In18.Cu" ); break;
case In19_Cu: txt = wxT( "In19.Cu" ); break;
case In20_Cu: txt = wxT( "In20.Cu" ); break;
case In21_Cu: txt = wxT( "In21.Cu" ); break;
case In22_Cu: txt = wxT( "In22.Cu" ); break;
case In23_Cu: txt = wxT( "In23.Cu" ); break;
case In24_Cu: txt = wxT( "In24.Cu" ); break;
case In25_Cu: txt = wxT( "In25.Cu" ); break;
case In26_Cu: txt = wxT( "In26.Cu" ); break;
case In27_Cu: txt = wxT( "In27.Cu" ); break;
case In28_Cu: txt = wxT( "In28.Cu" ); break;
case In29_Cu: txt = wxT( "In29.Cu" ); break;
case In30_Cu: txt = wxT( "In30.Cu" ); break;
case B_Cu: txt = wxT( "B.Cu" ); break;
// Technicals
@ -124,24 +205,23 @@ const wxChar* LSET::Name( PCB_LAYER_ID aLayerId )
case F_Fab: txt = wxT( "F.Fab" ); break;
case B_Fab: txt = wxT( "B.Fab" ); break;
// User definable layers.
case User_1: txt = wxT( "User.1" ); break;
case User_2: txt = wxT( "User.2" ); break;
case User_3: txt = wxT( "User.3" ); break;
case User_4: txt = wxT( "User.4" ); break;
case User_5: txt = wxT( "User.5" ); break;
case User_6: txt = wxT( "User.6" ); break;
case User_7: txt = wxT( "User.7" ); break;
case User_8: txt = wxT( "User.8" ); break;
case User_9: txt = wxT( "User.9" ); break;
// Rescue
case Rescue: txt = wxT( "Rescue" ); break;
default:
std::cout << aLayerId << std::endl;
wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) );
txt = wxT( "BAD INDEX!" ); break;
if( static_cast<int>( aLayerId ) & 1 )
{
int offset = ( aLayerId - Rescue ) / 2;
txt = wxString::Format( wxT( "User.%d" ), offset );
}
else
{
int offset = ( aLayerId - B_Cu ) / 2;
txt = wxString::Format( wxT( "In%d.Cu" ), offset );
}
}
return txt;
@ -150,98 +230,24 @@ const wxChar* LSET::Name( PCB_LAYER_ID aLayerId )
LSEQ LSET::CuStack() const
{
// desired sequence
static const PCB_LAYER_ID sequence[] = {
F_Cu,
In1_Cu,
In2_Cu,
In3_Cu,
In4_Cu,
In5_Cu,
In6_Cu,
In7_Cu,
In8_Cu,
In9_Cu,
In10_Cu,
In11_Cu,
In12_Cu,
In13_Cu,
In14_Cu,
In15_Cu,
In16_Cu,
In17_Cu,
In18_Cu,
In19_Cu,
In20_Cu,
In21_Cu,
In22_Cu,
In23_Cu,
In24_Cu,
In25_Cu,
In26_Cu,
In27_Cu,
In28_Cu,
In29_Cu,
In30_Cu,
B_Cu, // 31
};
LSEQ ret;
return Seq( sequence, arrayDim( sequence ) );
}
ret.reserve( 32 );
for( auto it = copper_layers_begin(); it != copper_layers_end(); ++it )
ret.push_back( *it );
LSEQ LSET::Technicals( LSET aSetToOmit ) const
{
// desired sequence
static const PCB_LAYER_ID sequence[] = {
F_Adhes,
B_Adhes,
F_Paste,
B_Paste,
F_SilkS,
B_SilkS,
F_Mask,
B_Mask,
F_CrtYd,
B_CrtYd,
F_Fab,
B_Fab,
};
LSET subset = ~aSetToOmit & *this;
return subset.Seq( sequence, arrayDim( sequence ) );
}
LSEQ LSET::Users() const
{
// desired
static const PCB_LAYER_ID sequence[] = {
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User,
Edge_Cuts,
Margin,
User_1,
User_2,
User_3,
User_4,
User_5,
User_6,
User_7,
User_8,
User_9
};
return Seq( sequence, arrayDim( sequence ) );
return ret;
}
LSEQ LSET::TechAndUserUIOrder() const
{
static const PCB_LAYER_ID sequence[] = {
LSEQ ret;
ret.reserve( 32 );
ret = Seq( {
F_Adhes,
B_Adhes,
F_Paste,
@ -259,19 +265,16 @@ LSEQ LSET::TechAndUserUIOrder() const
F_CrtYd,
B_CrtYd,
F_Fab,
B_Fab,
User_1,
User_2,
User_3,
User_4,
User_5,
User_6,
User_7,
User_8,
User_9
};
B_Fab
} );
return Seq( sequence, arrayDim( sequence ) );
for( auto it = non_copper_layers_begin(); it != non_copper_layers_end(); ++it )
{
if( *it >= User_1 )
ret.push_back( *it );
}
return ret;
}
@ -389,40 +392,6 @@ int LSET::ParseHex( const char* aStart, int aCount )
}
LSEQ LSET::Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const
{
LSEQ ret;
#if defined(DEBUG) && 0
LSET dup_detector;
for( unsigned i=0; i<aCount; ++i )
{
PCB_LAYER_ID id = aWishListSequence[i];
if( test( id ) )
{
wxASSERT_MSG( !dup_detector[id], wxT( "Duplicate in aWishListSequence" ) );
dup_detector[id] = true;
ret.push_back( id );
}
}
#else
for( unsigned i=0; i<aCount; ++i )
{
PCB_LAYER_ID id = aWishListSequence[i];
if( test( id ) )
ret.push_back( id );
}
#endif
return ret;
}
LSEQ LSET::Seq( const LSEQ& aSequence ) const
{
LSEQ ret;
@ -455,69 +424,48 @@ LSEQ LSET::Seq() const
LSEQ LSET::SeqStackupTop2Bottom( PCB_LAYER_ID aSelectedLayer ) const
{
static const PCB_LAYER_ID sequence[] = {
LSEQ base_sequence = Seq( {
Edge_Cuts,
Margin,
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User,
User_1,
User_2,
User_3,
User_4,
User_5,
User_6,
User_7,
User_8,
User_9,
Eco2_User
} );
LSEQ top_tech_sequence = Seq( {
F_Fab,
F_SilkS,
F_Paste,
F_Adhes,
F_Mask,
F_CrtYd,
F_Cu,
In1_Cu,
In2_Cu,
In3_Cu,
In4_Cu,
In5_Cu,
In6_Cu,
In7_Cu,
In8_Cu,
In9_Cu,
In10_Cu,
In11_Cu,
In12_Cu,
In13_Cu,
In14_Cu,
In15_Cu,
In16_Cu,
In17_Cu,
In18_Cu,
In19_Cu,
In20_Cu,
In21_Cu,
In22_Cu,
In23_Cu,
In24_Cu,
In25_Cu,
In26_Cu,
In27_Cu,
In28_Cu,
In29_Cu,
In30_Cu,
B_Cu,
} );
LSEQ bottom_tech_sequence = Seq( {
B_CrtYd,
B_Mask,
B_Adhes,
B_Paste,
B_SilkS,
B_Fab,
};
} );
LSEQ seq = Seq( sequence, arrayDim( sequence ) );
LSEQ seq = Seq( base_sequence );
for( auto it = non_copper_layers_begin(); it != non_copper_layers_end(); ++it )
{
if( *it >= User_1 )
seq.push_back( *it );
}
std::copy( top_tech_sequence.begin(), top_tech_sequence.end(), std::back_inserter( seq ) );
for( auto it = copper_layers_begin(); it != copper_layers_end(); ++it )
seq.push_back( *it );
std::copy( bottom_tech_sequence.begin(), bottom_tech_sequence.end(), std::back_inserter( seq ) );
if( aSelectedLayer != UNDEFINED_LAYER )
{
@ -539,7 +487,7 @@ LSEQ LSET::SeqStackupForPlotting() const
// bottom-to-top stack-up layers
// Note that the bottom technical layers are flipped so that when plotting a bottom-side view,
// they appear in the correct sequence.
static const PCB_LAYER_ID sequence[] = {
LSEQ bottom_tech_sequence = Seq( {
B_Cu,
B_Mask,
B_Paste,
@ -547,61 +495,71 @@ LSEQ LSET::SeqStackupForPlotting() const
B_Adhes,
B_CrtYd,
B_Fab,
In30_Cu,
In29_Cu,
In28_Cu,
In27_Cu,
In26_Cu,
In25_Cu,
In24_Cu,
In23_Cu,
In22_Cu,
In21_Cu,
In20_Cu,
In19_Cu,
In18_Cu,
In17_Cu,
In16_Cu,
In15_Cu,
In14_Cu,
In13_Cu,
In12_Cu,
In11_Cu,
In10_Cu,
In9_Cu,
In8_Cu,
In7_Cu,
In6_Cu,
In5_Cu,
In4_Cu,
In3_Cu,
In2_Cu,
In1_Cu,
F_Cu,
} );
// Copper layers go here
LSEQ top_tech_sequence = Seq( {
F_Mask,
F_Paste,
F_SilkS,
F_Adhes,
F_CrtYd,
F_Fab,
} );
LSEQ user_sequence = Seq( {
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User,
User_1,
User_2,
User_3,
User_4,
User_5,
User_6,
User_7,
User_8,
User_9,
} );
// User layers go here
LSEQ base_sequence = Seq( {
Margin,
Edge_Cuts,
};
} );
return Seq( sequence, arrayDim( sequence ) );
LSEQ seq = Seq( bottom_tech_sequence );
std::vector<PCB_LAYER_ID> temp_layers;
// We are going to reverse the copper layers and then add them to the sequence
// because the plotting order is bottom-to-top
for( auto it = copper_layers_begin(); it != copper_layers_end(); ++it )
{
// Skip B_Cu because it is already in the sequence (if it exists)
if( *it != B_Cu )
temp_layers.push_back( *it );
}
for( auto it = temp_layers.rbegin(); it != temp_layers.rend(); ++it )
seq.push_back( *it );
std::copy( top_tech_sequence.begin(), top_tech_sequence.end(), std::back_inserter( seq ) );
std::copy( user_sequence.begin(), user_sequence.end(), std::back_inserter( seq ) );
temp_layers.clear();
for( auto it = non_copper_layers_begin(); it != non_copper_layers_end(); ++it )
{
if( *it >= User_1 )
temp_layers.push_back( *it );
}
for( auto it = temp_layers.rbegin(); it != temp_layers.rend(); ++it )
{
seq.push_back( *it );
}
std::copy( base_sequence.begin(), base_sequence.end(), std::back_inserter( seq ) );
return seq;
}
@ -611,70 +569,41 @@ LSET& LSET::Flip( int aCopperLayersCount )
reset();
if( oldMask.test( B_Cu ) )
set( F_Cu );
// Mapping for Copper and Non-Copper layers
const std::map<PCB_LAYER_ID, PCB_LAYER_ID> flip_map =
{
{F_Cu, B_Cu},
{B_Cu, F_Cu},
{F_SilkS, B_SilkS},
{B_SilkS, F_SilkS},
{F_Adhes, B_Adhes},
{B_Adhes, F_Adhes},
{F_Mask, B_Mask},
{B_Mask, F_Mask},
{F_Paste, B_Paste},
{B_Paste, F_Paste},
{F_CrtYd, B_CrtYd},
{B_CrtYd, F_CrtYd},
{F_Fab, B_Fab},
{B_Fab, F_Fab}
};
if( oldMask.test( F_Cu ) )
set( B_Cu );
for( const auto& pair : flip_map )
{
if( oldMask.test( pair.first ) )
set( pair.second );
}
if( oldMask.test( B_SilkS ) )
set( F_SilkS );
if( oldMask.test( F_SilkS ) )
set( B_SilkS );
if( oldMask.test( B_Adhes ) )
set( F_Adhes );
if( oldMask.test( F_Adhes ) )
set( B_Adhes );
if( oldMask.test( B_Mask ) )
set( F_Mask );
if( oldMask.test( F_Mask ) )
set( B_Mask );
if( oldMask.test( B_Paste ) )
set( F_Paste );
if( oldMask.test( F_Paste ) )
set( B_Paste );
if( oldMask.test( B_Adhes ) )
set( F_Adhes );
if( oldMask.test( F_Adhes ) )
set( B_Adhes );
if( oldMask.test( B_CrtYd ) )
set( F_CrtYd );
if( oldMask.test( F_CrtYd ) )
set( B_CrtYd );
if( oldMask.test( B_Fab ) )
set( F_Fab );
if( oldMask.test( F_Fab ) )
set( B_Fab );
if( aCopperLayersCount >= 4 ) // Internal layers exist
if( aCopperLayersCount >= 4 )
{
LSET internalMask = oldMask & InternalCuMask();
int innerLayerCnt = aCopperLayersCount - 2;
int innerLayerCount = aCopperLayersCount - 2;
// the flipped mask is the innerLayerCnt bits rewritten in reverse order
// ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt )
for( int ii = 0; ii < innerLayerCnt; ii++ )
for( int ii = 0; ii < innerLayerCount; ii++ )
{
if( internalMask[innerLayerCnt - ii] )
if( internalMask.test( innerLayerCount - ii * 2 + In1_Cu ) )
{
set( ii + In1_Cu );
}
else
{
reset( ii + In1_Cu );
set( ii * 2 + In1_Cu );
}
}
}
@ -731,20 +660,10 @@ LSET LSET::InternalCuMask()
LSET LSET::AllCuMask( int aCuLayerCount )
{
// retain all in static as the full set, which is a common case.
static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
LSET ret;
if( aCuLayerCount == MAX_CU_LAYERS )
return all;
// subtract out some Cu layers not wanted in the mask.
LSET ret = all;
int clear_count = MAX_CU_LAYERS - aCuLayerCount;
clear_count = std::clamp( clear_count, 0, MAX_CU_LAYERS - 2 );
for( int elem = In30_Cu; clear_count; --elem, --clear_count )
ret.set( elem, false );
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, aCuLayerCount ) )
ret.set( layer );
return ret;
}
@ -866,6 +785,7 @@ LSEQ LSET::UIOrder() const
{
LSEQ order = CuStack();
LSEQ techuser = TechAndUserUIOrder();
order.insert( order.end(), techuser.begin(), techuser.end() );
return order;
@ -874,6 +794,10 @@ LSEQ LSET::UIOrder() const
PCB_LAYER_ID ToLAYER_ID( int aLayer )
{
// We use std::numeric_limits<int>::max() to represent B_Cu for the connectivity_rtree
if( aLayer == std::numeric_limits<int>::max() )
return B_Cu;
wxASSERT( aLayer < GAL_LAYER_ID_END );
return PCB_LAYER_ID( aLayer );
}
@ -946,3 +870,100 @@ GAL_SET GAL_SET::DefaultVisible()
static const GAL_SET saved( visible, arrayDim( visible ) );
return saved;
}
#ifndef SWIG // Skip SWIG generators for the iterators because it requires a default constructor
// Custom iterators for Copper and Non-Copper layers
LSET::copper_layers_iterator::copper_layers_iterator( const BASE_SET& set, size_t index ) :
BASE_SET::set_bits_iterator( set, index )
{
m_index = ( index + 1 ) & ~1;
advance_to_next_set_copper_bit();
}
PCB_LAYER_ID LSET::copper_layers_iterator::operator*() const
{
return static_cast<PCB_LAYER_ID>( m_index );
}
LSET::copper_layers_iterator& LSET::copper_layers_iterator::operator++()
{
next_copper_layer();
advance_to_next_set_copper_bit();
return *this;
}
void LSET::copper_layers_iterator::next_copper_layer()
{
if( m_index == F_Cu )
{
m_index += 4;
}
else if( m_index == B_Cu )
{
m_index = m_baseSet.size();
return;
}
else
{
m_index += 2;
if( m_index >= m_baseSet.size() )
m_index = B_Cu;
}
}
void LSET::copper_layers_iterator::advance_to_next_set_copper_bit()
{
while( m_index < m_baseSet.size() && !m_baseSet.test( m_index ) )
next_copper_layer();
}
LSET::non_copper_layers_iterator::non_copper_layers_iterator( const BASE_SET& set, size_t index ) :
BASE_SET::set_bits_iterator( set, index )
{
advance_to_next_set_non_copper_bit();
}
PCB_LAYER_ID LSET::non_copper_layers_iterator::operator*() const
{
return static_cast<PCB_LAYER_ID>( m_index );
}
LSET::non_copper_layers_iterator& LSET::non_copper_layers_iterator::operator++()
{
++m_index;
advance_to_next_set_non_copper_bit();
return *this;
}
void LSET::non_copper_layers_iterator::advance_to_next_set_non_copper_bit()
{
while( m_index < m_baseSet.size() && ( m_index % 2 != 1 || !m_baseSet.test( m_index ) ) )
{
++m_index;
}
}
LSET::copper_layers_iterator LSET::copper_layers_begin() const
{
return copper_layers_iterator( *this, 0 );
}
LSET::copper_layers_iterator LSET::copper_layers_end() const
{
return copper_layers_iterator( *this, size() );
}
LSET::non_copper_layers_iterator LSET::non_copper_layers_begin() const
{
return non_copper_layers_iterator( *this, 0 );
}
LSET::non_copper_layers_iterator LSET::non_copper_layers_end() const
{
return non_copper_layers_iterator( *this, size() );
}
#endif

View File

@ -147,6 +147,10 @@ static const std::map<int, COLOR4D> s_defaultTheme =
{ GERBVIEW_LAYER_ID_START + 57, CSS_COLOR( 127, 200, 127, 1 ) },
{ GERBVIEW_LAYER_ID_START + 58, CSS_COLOR( 206, 125, 44, 1 ) },
{ GERBVIEW_LAYER_ID_START + 59, CSS_COLOR( 79, 203, 203, 1 ) },
{ GERBVIEW_LAYER_ID_START + 60, CSS_COLOR( 219, 98, 139, 1 ) },
{ GERBVIEW_LAYER_ID_START + 61, CSS_COLOR( 167, 165, 198, 1 ) },
{ GERBVIEW_LAYER_ID_START + 62, CSS_COLOR( 40, 204, 217, 1 ) },
{ GERBVIEW_LAYER_ID_START + 63, CSS_COLOR( 232, 178, 167, 1 ) },
{ LAYER_ANCHOR, CSS_COLOR( 255, 38, 226, 1 ) },
{ LAYER_LOCKED_ITEM_SHADOW, CSS_COLOR( 255, 38, 226, 0.5 ) },

View File

@ -59,7 +59,7 @@ bool GERBVIEW_PRINTOUT::OnPrintPage( int aPage )
// objects when using only one page is tricky
// Enable only one layer to create a printout
m_settings.m_LayerSet = LSET( layerId );
m_settings.m_LayerSet = LSET( { layerId } );
GERBER_FILE_IMAGE_LIST& gbrImgList = GERBER_FILE_IMAGE_LIST::GetImagesList();
GERBER_FILE_IMAGE* gbrImage = gbrImgList.GetGbrImage( layerId );

View File

@ -24,7 +24,7 @@
#include <limits>
#include <ostream>
#include <stdexcept>
#include <vector>
#include <dynamic_bitset.h>
#include <core/kicad_algo.h>
#include <import_export.h>
@ -37,176 +37,182 @@
typedef SSIZE_T ssize_t;
#endif
class APIEXPORT BASE_SET
class APIEXPORT BASE_SET : public sul::dynamic_bitset<uint64_t>
{
public:
using iterator = std::vector<int>::iterator;
using const_iterator = std::vector<int>::const_iterator;
BASE_SET( size_t size ) : m_bits( size, 0 ) {}
bool test( size_t pos ) const
class iterator
{
if( pos >= m_bits.size() )
return false;
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = bool;
using difference_type = std::ptrdiff_t;
using pointer = void;
using reference = bool;
return m_bits[pos] == 1;
}
bool any() const { return std::any_of( m_bits.begin(), m_bits.end(), []( int bit ) { return bit == 1; } ); }
bool all() const { return std::all_of( m_bits.begin(), m_bits.end(), []( int bit ) { return bit == 1; } ); }
bool none() const { return std::none_of( m_bits.begin(), m_bits.end(), []( int bit ) { return bit == 1; } ); }
BASE_SET& set( size_t pos = std::numeric_limits<size_t>::max(), bool value = true )
{
if( pos == std::numeric_limits<size_t>::max() )
iterator( BASE_SET* set, size_t pos ) : m_set( set ), m_pos( pos ) {}
bool operator*() const { return m_set->test( m_pos ); }
iterator& operator++()
{
std::fill( m_bits.begin(), m_bits.end(), value ? 1 : 0 );
++m_pos;
return *this;
}
iterator operator+( difference_type n ) const
{
return iterator( m_set, m_pos + n );
}
difference_type operator-( const iterator& other ) const
{
return static_cast<difference_type>(m_pos) - static_cast<difference_type>(other.m_pos);
}
auto operator<=>( const iterator& ) const = default;
if( pos >= m_bits.size() )
m_bits.resize( pos + 1, 0 );
private:
BASE_SET* m_set;
size_t m_pos;
};
m_bits[pos] = value ? 1 : 0;
class const_iterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = bool;
using difference_type = std::ptrdiff_t;
using pointer = void;
using reference = bool;
const_iterator( const BASE_SET* set, size_t pos ) : m_set( set ), m_pos( pos ) {}
bool operator*() const { return m_set->test( m_pos ); }
const_iterator& operator++()
{
++m_pos;
return *this;
}
const_iterator operator+( difference_type n ) const
{
return const_iterator( m_set, m_pos + n );
}
difference_type operator-( const const_iterator& other ) const
{
return static_cast<difference_type>(m_pos) - static_cast<difference_type>(other.m_pos);
}
auto operator<=>( const const_iterator& ) const = default;
private:
const BASE_SET* m_set;
size_t m_pos;
};
iterator begin() { return iterator(this, 0); }
iterator end() { return iterator(this, size()); }
const_iterator begin() const { return const_iterator(this, 0); }
const_iterator end() const { return const_iterator(this, size()); }
BASE_SET( size_t size = 64 ) : sul::dynamic_bitset<uint64_t>( size ) {}
// Overloads for set, reset, and flip operations
// Set a bit at the specified position
BASE_SET& set(size_t pos)
{
if( pos >= size() )
sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
sul::dynamic_bitset<uint64_t>::set(pos);
return *this;
}
BASE_SET& reset( size_t pos = std::numeric_limits<size_t>::max() )
// Set a bit at the specified position to a given value
BASE_SET& set(size_t pos, bool value)
{
if( pos == std::numeric_limits<size_t>::max() )
{
std::fill( m_bits.begin(), m_bits.end(), 0 );
return *this;
}
if( pos >= size() )
sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
if( pos >= m_bits.size() )
m_bits.resize( pos + 1, 0 );
m_bits[pos] = 0;
sul::dynamic_bitset<uint64_t>::set(pos, value);
return *this;
}
BASE_SET& flip( size_t pos = std::numeric_limits<size_t>::max() )
// Set all bits to 1
BASE_SET& set()
{
if( pos == std::numeric_limits<size_t>::max() )
{
std::transform( m_bits.begin(), m_bits.end(), m_bits.begin(), []( int bit ) { return bit ^ 1; } );
return *this;
}
if( pos >= m_bits.size() )
m_bits.resize( pos + 1, 0 );
m_bits[pos] ^= 1;
sul::dynamic_bitset<uint64_t>::set();
return *this;
}
size_t count() const { return std::count( m_bits.begin(), m_bits.end(), 1 ); }
// Reset (clear) a bit at the specified position
BASE_SET& reset(size_t pos)
{
if( pos >= size() )
sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
size_t size() const { return m_bits.size(); }
sul::dynamic_bitset<uint64_t>::reset(pos);
return *this;
}
void resize( size_t newSize ) { m_bits.resize( newSize, 0 ); }
// Reset (clear) all bits
BASE_SET& reset()
{
sul::dynamic_bitset<uint64_t>::reset();
return *this;
}
int& operator[]( size_t pos ) { return m_bits[pos]; }
// Flip a bit at the specified position
BASE_SET& flip(size_t pos)
{
if( pos >= size() )
sul::dynamic_bitset<uint64_t>::resize( pos + 1 );
const int& operator[]( size_t pos ) const { return m_bits[pos]; }
sul::dynamic_bitset<uint64_t>::flip(pos);
return *this;
}
// Flip all bits
BASE_SET& flip()
{
sul::dynamic_bitset<uint64_t>::flip();
return *this;
}
// Overloads for boolean operators
// Bitwise NOT operator
BASE_SET operator~() const
{
BASE_SET result(*this);
result.flip();
return result;
}
// Compound assignment AND operator
BASE_SET& operator&=(const BASE_SET& other)
{
sul::dynamic_bitset<uint64_t>::operator&=(other);
return *this;
}
// Compound assignment OR operator
BASE_SET& operator|=(const BASE_SET& other)
{
sul::dynamic_bitset<uint64_t>::operator|=(other);
return *this;
}
// Compound assignment XOR operator
BASE_SET& operator^=(const BASE_SET& other)
{
sul::dynamic_bitset<uint64_t>::operator^=(other);
return *this;
}
int compare( const BASE_SET& other ) const
{
return alg::lexicographical_compare_3way( m_bits, other.m_bits );
}
iterator begin() { return m_bits.begin(); }
iterator end() { return m_bits.end(); }
const_iterator begin() const { return m_bits.begin(); }
const_iterator end() const { return m_bits.end(); }
// Define equality operator
bool operator==( const BASE_SET& other ) const
{
std::size_t minSize = std::min( size(), other.size() );
if( !std::equal( m_bits.begin(), m_bits.begin() + minSize, other.m_bits.begin() ) )
return false;
if( std::any_of( m_bits.begin() + minSize, m_bits.end(), []( int bit ) { return bit != 0; } ) )
return false;
if( std::any_of( other.m_bits.begin() + minSize, other.m_bits.end(), []( int bit ) { return bit != 0; } ) )
return false;
return true;
auto result = std::lexicographical_compare_three_way( begin(), end(), other.begin(), other.end() );
return result == std::strong_ordering::equal ? 0 : ( result == std::strong_ordering::less ? -1 : 1 );
}
// Define less-than operator for comparison
bool operator<( const BASE_SET& other ) const
{
return std::lexicographical_compare( m_bits.begin(), m_bits.end(), other.m_bits.begin(), other.m_bits.end() );
}
// Define output operator
friend std::ostream& operator<<( std::ostream& os, const BASE_SET& set )
{
return os << set.to_string();
}
// to_string method
template <typename CharT = char>
std::basic_string<CharT> to_string( CharT zero = CharT( '0' ), CharT one = CharT( '1' ) ) const
{
std::basic_string<CharT> result( size(), zero );
for( size_t i = 0; i < size(); ++i )
{
if( test( i ) )
{
result[size() - 1 - i] = one; // Reverse order to match std::bitset behavior
}
}
return result;
}
// Boolean operators
BASE_SET& operator&=( const BASE_SET& rhs )
{
assert( m_bits.size() == rhs.m_bits.size() );
for( size_t i = 0; i < m_bits.size(); ++i )
m_bits[i] &= rhs.m_bits[i];
return *this;
}
BASE_SET& operator|=( const BASE_SET& rhs )
{
assert( m_bits.size() == rhs.m_bits.size() );
for( size_t i = 0; i < m_bits.size(); ++i )
m_bits[i] |= rhs.m_bits[i];
return *this;
}
BASE_SET& operator^=( const BASE_SET& rhs )
{
assert( m_bits.size() == rhs.m_bits.size() );
for( size_t i = 0; i < m_bits.size(); ++i )
m_bits[i] ^= rhs.m_bits[i];
return *this;
}
BASE_SET operator~() const
{
BASE_SET result = *this;
for( size_t i = 0; i < m_bits.size(); ++i )
result.m_bits[i] = !m_bits[i];
return result;
return std::lexicographical_compare( begin(), end(), other.begin(), other.end() );
}
// Custom iterator to iterate over set bits
@ -238,7 +244,7 @@ public:
bool operator==( const set_bits_iterator& other ) const { return m_index == other.m_index; }
private:
protected:
void advance_to_next_set_bit()
{
while( m_index < m_baseSet.size() && !m_baseSet.test( m_index ) )
@ -284,7 +290,7 @@ public:
return m_index == other.m_index;
}
private:
protected:
void advance_to_previous_set_bit()
{
while( m_index >= 0 && !m_baseSet.test( m_index ) )
@ -298,19 +304,17 @@ public:
};
set_bits_iterator set_bits_begin() const { return set_bits_iterator( *this, 0 ); }
set_bits_iterator set_bits_end() const { return set_bits_iterator( *this, m_bits.size() ); }
set_bits_iterator set_bits_end() const { return set_bits_iterator( *this, size() ); }
set_bits_reverse_iterator set_bits_rbegin() const
{
return set_bits_reverse_iterator( *this, m_bits.size() - 1 );
return set_bits_reverse_iterator( *this, size() - 1 );
}
set_bits_reverse_iterator set_bits_rend() const
{
return set_bits_reverse_iterator( *this, -1 );
}
private:
std::vector<int> m_bits;
};
inline BASE_SET operator&( const BASE_SET& lhs, const BASE_SET& rhs )

View File

@ -239,6 +239,21 @@ public:
*/
virtual PCB_LAYER_ID GetLayer() const { return m_layer; }
/**
* Return the total number of layers for the board that this item resides on.
*/
virtual int BoardLayerCount() const;
/**
* Return the total number of copper layers for the board that this item resides on.
*/
virtual int BoardCopperLayerCount() const;
/**
* Return the LSET for the board that this item resides on.
*/
virtual LSET BoardLayerSet() const;
/**
* Return a std::bitset of all layers on which the item physically resides.
*/
@ -247,7 +262,7 @@ public:
if( m_layer == UNDEFINED_LAYER )
return LSET();
else
return LSET( m_layer );
return LSET( { m_layer } );
}
virtual void SetLayerSet( const LSET& aLayers )

View File

@ -62,84 +62,82 @@ enum PCB_LAYER_ID: int
UNSELECTED_LAYER = -2,
F_Cu = 0,
In1_Cu,
In2_Cu,
In3_Cu,
In4_Cu,
In5_Cu,
In6_Cu,
In7_Cu,
In8_Cu,
In9_Cu,
In10_Cu,
In11_Cu,
In12_Cu,
In13_Cu,
In14_Cu,
In15_Cu,
In16_Cu,
In17_Cu,
In18_Cu,
In19_Cu,
In20_Cu,
In21_Cu,
In22_Cu,
In23_Cu,
In24_Cu,
In25_Cu,
In26_Cu,
In27_Cu,
In28_Cu,
In29_Cu,
In30_Cu,
B_Cu, // 31
B_Cu = 2,
In1_Cu = 4,
In2_Cu = 6,
In3_Cu = 8,
In4_Cu = 10,
In5_Cu = 12,
In6_Cu = 14,
In7_Cu = 16,
In8_Cu = 18,
In9_Cu = 20,
In10_Cu = 22,
In11_Cu = 24,
In12_Cu = 26,
In13_Cu = 28,
In14_Cu = 30,
In15_Cu = 32,
In16_Cu = 34,
In17_Cu = 36,
In18_Cu = 38,
In19_Cu = 40,
In20_Cu = 42,
In21_Cu = 44,
In22_Cu = 46,
In23_Cu = 48,
In24_Cu = 50,
In25_Cu = 52,
In26_Cu = 54,
In27_Cu = 56,
In28_Cu = 58,
In29_Cu = 60,
In30_Cu = 62,
B_Adhes,
F_Adhes,
F_Mask = 1,
B_Mask = 3,
B_Paste,
F_Paste,
F_SilkS = 5,
B_SilkS = 7,
F_Adhes = 9,
B_Adhes = 11,
F_Paste = 13,
B_Paste = 15,
B_SilkS,
F_SilkS,
Dwgs_User = 17,
Cmts_User = 19,
Eco1_User = 21,
Eco2_User = 23,
B_Mask,
F_Mask, // 39
Edge_Cuts = 25,
Margin = 27,
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User,
Edge_Cuts,
Margin, // 45
B_CrtYd = 29,
F_CrtYd = 31,
B_CrtYd,
F_CrtYd,
B_Fab = 33,
F_Fab = 35,
B_Fab,
F_Fab, // 49
Rescue = 37,
// User definable layers.
User_1,
User_2,
User_3,
User_4,
User_5,
User_6,
User_7,
User_8,
User_9,
User_1 = 39,
User_2 = 41,
User_3 = 43,
User_4 = 45,
User_5 = 47,
User_6 = 49,
User_7 = 51,
User_8 = 53,
User_9 = 55,
Rescue, // 59
// Four reserved layers (60 - 63) for future expansion within the 64 bit integer limit.
PCB_LAYER_ID_COUNT
PCB_LAYER_ID_COUNT = 64
};
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START = F_Cu;
#define MAX_CU_LAYERS (B_Cu - F_Cu + 1)
#define MAX_CU_LAYERS 32
/**
* Enum used during connectivity building to ensure we do not query connectivity while building
@ -531,7 +529,7 @@ inline bool IsPcbLayer( int aLayer )
*/
inline bool IsCopperLayer( int aLayerId )
{
return aLayerId >= F_Cu && aLayerId <= B_Cu;
return !( aLayerId & 1 ) && aLayerId <= PCB_LAYER_ID_COUNT;
}
/**
@ -542,7 +540,7 @@ inline bool IsCopperLayer( int aLayerId )
*/
inline bool IsNonCopperLayer( int aLayerId )
{
return aLayerId > B_Cu && aLayerId <= PCB_LAYER_ID_COUNT;
return ( aLayerId & 1 ) && aLayerId <= PCB_LAYER_ID_COUNT;
}
/**

143
include/layer_range.h Normal file
View File

@ -0,0 +1,143 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <layer_ids.h>
#ifndef LAYER_RANGE_H
#define LAYER_RANGE_H
class LAYER_RANGE
{
private:
PCB_LAYER_ID m_start;
PCB_LAYER_ID m_stop;
int m_layer_count;
class LAYER_RANGE_ITERATOR
{
private:
int m_current;
int m_stop;
int m_layer_count;
bool m_reverse;
int next_layer( int aLayer )
{
if( m_reverse )
{
if( aLayer == B_Cu )
aLayer = m_layer_count == 2 ? F_Cu : static_cast<int>( F_Cu ) + 2 * ( m_layer_count - 2 ) + 2;
else if( aLayer == m_stop || aLayer == UNDEFINED_LAYER )
aLayer = UNDEFINED_LAYER;
else if( aLayer == In1_Cu )
aLayer = F_Cu;
else
aLayer = static_cast<int>( aLayer ) - 2;
}
else
{
if( aLayer == F_Cu && m_layer_count == 2 )
aLayer = B_Cu;
else if( aLayer == m_stop || aLayer == UNDEFINED_LAYER )
aLayer = UNDEFINED_LAYER;
else if( aLayer == static_cast<int>( F_Cu ) + 2 * ( m_layer_count - 2 ) + 2)
aLayer = B_Cu;
else if( aLayer == F_Cu )
aLayer = In1_Cu;
else
aLayer = static_cast<int>( aLayer ) + 2;
}
return aLayer;
}
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = PCB_LAYER_ID;
using difference_type = std::ptrdiff_t;
using pointer = PCB_LAYER_ID*;
using reference = PCB_LAYER_ID&;
LAYER_RANGE_ITERATOR( PCB_LAYER_ID start, PCB_LAYER_ID stop, int layer_count ) :
m_current( start ), m_stop( stop ), m_layer_count( layer_count )
{
if( start & 1 || stop & 1 )
throw std::invalid_argument( "Only works for copper layers" );
m_layer_count = m_layer_count & ~1;
if( stop == B_Cu || m_stop >= m_current )
m_reverse = false;
else
m_reverse = true;
}
PCB_LAYER_ID operator*() const { return static_cast<PCB_LAYER_ID>( m_current ); }
LAYER_RANGE_ITERATOR& operator++()
{
m_current = next_layer( m_current );
return *this;
}
LAYER_RANGE_ITERATOR operator++( int )
{
LAYER_RANGE_ITERATOR tmp = *this;
++( *this );
return tmp;
}
bool operator==( const LAYER_RANGE_ITERATOR& other ) const
{
return m_current == other.m_current;
}
bool operator!=( const LAYER_RANGE_ITERATOR& other ) const { return !( *this == other ); }
};
public:
LAYER_RANGE( PCB_LAYER_ID start, PCB_LAYER_ID stop, int layer_count ) :
m_start( start ), m_stop( stop ), m_layer_count( layer_count )
{
if( start & 1 || stop & 1 )
throw std::invalid_argument( "Only works for copper layers" );
}
LAYER_RANGE_ITERATOR begin() const { return LAYER_RANGE_ITERATOR( m_start, m_stop, m_layer_count ); }
LAYER_RANGE_ITERATOR end() const { auto it = LAYER_RANGE_ITERATOR( m_stop, m_stop, m_layer_count ); return ++it; }
static bool Contains( int aStart_layer, int aEnd_layer, int aTest_layer )
{
if( aStart_layer == B_Cu )
aStart_layer = INT_MAX;
if( aEnd_layer == B_Cu )
aEnd_layer = INT_MAX;
return aTest_layer >= aStart_layer && aTest_layer <= aEnd_layer;
}
bool Contains( int aTest_layer )
{
return Contains( m_start, m_stop, aTest_layer );
}
};
#endif // LAYER_RANGE_H

View File

@ -24,6 +24,7 @@
#include <base_set.h>
class LSEQ;
class LAYER_RANGE;
/**
* LSET is a set of PCB_LAYER_IDs. It can be converted to numerous purpose LSEQs using
@ -35,39 +36,19 @@ class KICOMMON_API LSET : public BASE_SET
{
public:
// The constructor flavors are carefully chosen to prevent LSET( int ) from compiling.
// That excludes "LSET s = 0;" and excludes "LSET s = -1;", etc.
// LSET s = 0; needs to be removed from the code, this accomplishes that.
// Remember LSET( PCB_LAYER_ID(0) ) sets bit 0, so "LSET s = 0;" is illegal
// to prevent that surprise. Therefore LSET's constructor suite is significantly
// different than the base class from which it is derived.
// Other member functions (non-constructor functions) are identical to the base
// class's and therefore are re-used from the base class.
/**
* Create an empty (cleared) set.
*/
LSET() :
BASE_SET( PCB_LAYER_ID_COUNT ) // all bits are set to zero in BASE_SET()
{
}
LSET() : BASE_SET( PCB_LAYER_ID_COUNT ) {} // all bits are set to zero in BASE_SET()
LSET( const BASE_SET& aOther ) :
BASE_SET( aOther )
{
}
LSET( PCB_LAYER_ID aLayer ) :
BASE_SET( PCB_LAYER_ID_COUNT )
{
set( aLayer );
}
LSET( const BASE_SET& aOther ) : BASE_SET( aOther ) {}
LSET( std::initializer_list<PCB_LAYER_ID> aList );
LSET( const LSEQ& aSeq );
LSET( const LAYER_RANGE& aRange );
LSET( unsigned long __val ) = delete;
/**
@ -91,7 +72,18 @@ public:
/**
* Return the fixed name association with aLayerId.
*/
static const wxChar* Name( PCB_LAYER_ID aLayerId );
static wxString Name( PCB_LAYER_ID aLayerId );
/**
* Return the layer number from a layer name.
*/
static int NameToLayer( wxString& aName );
/**
* Return true if aLayer is between aStart and aEnd, inclusive. Takes into
* account the direction of the layers and the fact that B_Cu comes before In*_Cu
*/
static bool IsBetween( PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, PCB_LAYER_ID aLayer );
/**
* Return a complete set of internal copper layers which is all Cu layers
@ -192,24 +184,20 @@ public:
/**
* Return a sequence of copper layers in starting from the front/top
* and extending to the back/bottom. This specific sequence is depended upon
* in numerous places.
* and extending to the back/bottom.
*/
LSEQ CuStack() const;
/**
* Return a sequence of technical layers. A sequence provides a certain order.
* Returns the technical and user layers in the order shown in layer widget
*
* @param aSubToOmit is the subset of the technical layers to omit, defaults to none.
*/
LSEQ Technicals( LSET aSubToOmit = LSET() ) const;
/// *_User layers.
LSEQ Users() const;
/// Returns the technical and user layers in the order shown in layer widget
LSEQ TechAndUserUIOrder() const;
/**
* Returns the copper, technical and user layers in the order shown in layer widget
*
*/
LSEQ UIOrder() const;
/**
@ -217,10 +205,7 @@ public:
* element will be in the same sequence as aWishListSequence if they are present.
* @param aWishListSequence establishes the order of the returned LSEQ, and the LSEQ will only
* contain PCB_LAYER_IDs which are present in this set.
* @param aCount is the length of aWishListSequence array.
*/
LSEQ Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const;
LSEQ Seq( const LSEQ& aSequence ) const;
/**
@ -295,5 +280,63 @@ public:
*/
LSET& Flip( int aCopperLayersCount = 0 );
/**
* Return the number of layers between aStart and aEnd, inclusive.
*/
static int LayerCount( PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, int aCopperLayerCount );
#ifndef SWIG
// Custom iterator to iterate over all set bits
class all_set_layers_iterator : public BASE_SET::set_bits_iterator
{
public:
all_set_layers_iterator( const BASE_SET& set, size_t index ) :
BASE_SET::set_bits_iterator( set, index )
{
}
PCB_LAYER_ID operator*() const { return PCB_LAYER_ID( BASE_SET::set_bits_iterator::operator*() ); }
all_set_layers_iterator& operator++()
{
BASE_SET::set_bits_iterator::operator++();
return *this;
}
};
all_set_layers_iterator begin() const { return all_set_layers_iterator( *this, 0 ); }
all_set_layers_iterator end() const { return all_set_layers_iterator( *this, size() ); }
// Custom iterators for Copper and Non-Copper layers
class copper_layers_iterator : public BASE_SET::set_bits_iterator
{
public:
copper_layers_iterator( const BASE_SET& set, size_t index );
PCB_LAYER_ID operator*() const;
copper_layers_iterator& operator++();
private:
void advance_to_next_set_copper_bit();
void next_copper_layer();
};
class non_copper_layers_iterator : public BASE_SET::set_bits_iterator
{
public:
non_copper_layers_iterator( const BASE_SET& set, size_t index );
PCB_LAYER_ID operator*() const;
non_copper_layers_iterator& operator++();
private:
void advance_to_next_set_non_copper_bit();
};
copper_layers_iterator copper_layers_begin() const;
copper_layers_iterator copper_layers_end() const;
non_copper_layers_iterator non_copper_layers_begin() const;
non_copper_layers_iterator non_copper_layers_end() const;
#endif
};
#endif // LSET_H

View File

@ -50,9 +50,9 @@ CLI::PCB_EXPORT_BASE_COMMAND::PCB_EXPORT_BASE_COMMAND( const std::string& aName,
//m_layerIndices[untranslated] = PCB_LAYER_ID( layer );
// Add layer name used in pcb files
m_layerMasks[untranslated] = LSET( PCB_LAYER_ID( layer ) );
m_layerMasks[untranslated] = LSET( { PCB_LAYER_ID( layer ) } );
// Add layer name using GUI canonical layer name
m_layerGuiMasks[ TO_UTF8(LayerName( layer ) ) ] = LSET( PCB_LAYER_ID( layer ) );
m_layerGuiMasks[ TO_UTF8(LayerName( layer ) ) ] = LSET( { PCB_LAYER_ID( layer ) } );
}
// Add list of grouped layer names used in pcb files

View File

@ -571,7 +571,7 @@ int AR_AUTOPLACER::getOptimalFPPlacement( FOOTPRINT* aFootprint )
if( m_matrix.m_RoutingLayersCount > 1 )
{
LSET other( aFootprint->GetLayer() == B_Cu ? F_Cu : B_Cu );
LSET other( { aFootprint->GetLayer() == B_Cu ? F_Cu : B_Cu } );
for( PAD* pad : aFootprint->Pads() )
{

View File

@ -2121,7 +2121,7 @@ PAD* BOARD::GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const
{
const VECTOR2I& aPosition = aTrace->GetEndPoint( aEndPoint );
LSET lset( aTrace->GetLayer() );
LSET lset( { aTrace->GetLayer() } );
return GetPad( aPosition, lset );
}

View File

@ -103,6 +103,39 @@ const KIFONT::METRICS& BOARD_ITEM::GetFontMetrics() const
}
int BOARD_ITEM::BoardLayerCount() const
{
const BOARD* board = GetBoard();
if( board )
return board->GetLayerSet().count();
return 64;
}
int BOARD_ITEM::BoardCopperLayerCount() const
{
const BOARD* board = GetBoard();
if( board )
return board->GetCopperLayerCount();
return 32;
}
LSET BOARD_ITEM::BoardLayerSet() const
{
const BOARD* board = GetBoard();
if( board )
return board->GetLayerSet();
return LSET::AllLayersMask();
}
wxString BOARD_ITEM::GetLayerName() const
{
if( const BOARD* board = GetBoard() )

View File

@ -703,7 +703,7 @@ void CN_CONNECTIVITY_ALGO::FillIsolatedIslandsMap(
{
for( CN_ITEM* item : *cluster )
{
if( item->Parent() == zone && item->Layer() == layer )
if( item->Parent() == zone && item->GetBoardLayer() == layer )
{
CN_ZONE_LAYER* z = static_cast<CN_ZONE_LAYER*>( item );

View File

@ -447,7 +447,7 @@ bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, i
CN_ZONE_LAYER* zoneLayer = dynamic_cast<CN_ZONE_LAYER*>( connected );
if( connected->Valid()
&& connected->Layers().Overlaps( aLayer )
&& connected->StartLayer() <= aLayer && connected->EndLayer() >= aLayer
&& matchType( connected->Parent()->Type() )
&& connected->Net() == aItem->GetNetCode() )
{

View File

@ -152,7 +152,7 @@ CN_ITEM* CN_LIST::Add( PAD* pad )
auto item = new CN_ITEM( pad, false, 1 );
item->AddAnchor( pad->ShapePos() );
item->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
item->SetLayers( F_Cu, B_Cu );
switch( pad->GetAttribute() )
{
@ -160,16 +160,11 @@ CN_ITEM* CN_LIST::Add( PAD* pad )
case PAD_ATTRIB::NPTH:
case PAD_ATTRIB::CONN:
{
LSET lmsk = pad->GetLayerSet();
LSEQ lmsk = pad->GetLayerSet().CuStack();
if( !lmsk.empty() )
item->SetLayer( lmsk.front() );
for( int i = 0; i <= MAX_CU_LAYERS; i++ )
{
if( lmsk[i] )
{
item->SetLayer( i );
break;
}
}
break;
}
default:
@ -216,7 +211,7 @@ CN_ITEM* CN_LIST::Add( PCB_VIA* via )
m_items.push_back( item );
item->AddAnchor( via->GetStart() );
item->SetLayers( LAYER_RANGE( via->TopLayer(), via->BottomLayer() ) );
item->SetLayers( via->TopLayer(), via->BottomLayer() );
addItemtoTree( item );
SetDirty();
return item;
@ -358,7 +353,7 @@ bool CN_ANCHOR::IsDangling() const
{
ZONE* zone = static_cast<ZONE*>( item->Parent() );
if( zone->HitTestFilledArea( ToLAYER_ID( item->Layer() ), Pos(), accuracy ) )
if( zone->HitTestFilledArea( item->GetBoardLayer(), Pos(), accuracy ) )
connected_count++;
}
else if( item->Parent()->HitTest( Pos(), accuracy ) )
@ -384,7 +379,7 @@ int CN_ANCHOR::ConnectedItemsCount() const
{
ZONE* zone = static_cast<ZONE*>( item->Parent() );
if( zone->HitTestFilledArea( ToLAYER_ID( item->Layer() ), Pos() ) )
if( zone->HitTestFilledArea( item->GetBoardLayer(), Pos() ) )
connected_count++;
}
else if( item->Parent()->HitTest( Pos() ) )

View File

@ -142,7 +142,8 @@ public:
m_valid = true;
m_dirty = true;
m_anchors.reserve( std::max( 6, aAnchorCount ) );
m_layers = LAYER_RANGE( 0, PCB_LAYER_ID_COUNT );
m_start_layer = 0;
m_end_layer = std::numeric_limits<int>::max();
m_connected.reserve( 8 );
}
@ -167,26 +168,55 @@ public:
bool Dirty() const { return m_dirty; }
/**
* Set the layers spanned by the item to aLayers.
* Set the layers spanned by the item to aStartLayer and aEndLayer.
*/
void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
void SetLayers( int aStartLayer, int aEndLayer )
{
// B_Cu is nominally layer 2 but we reset it to INT_MAX to ensure that it is
// always greater than any other layer in the RTree
if( aStartLayer == B_Cu )
aStartLayer = std::numeric_limits<int>::max();
if( aEndLayer == B_Cu )
aEndLayer = std::numeric_limits<int>::max();
m_start_layer = aStartLayer;
m_end_layer = aEndLayer;
}
/**
* Set the layers spanned by the item to a single layer aLayer.
*/
void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
void SetLayer( int aLayer ) { SetLayers( aLayer, aLayer ); }
/**
* Return the contiguous set of layers spanned by the item.
*/
const LAYER_RANGE& Layers() const { return m_layers; }
int StartLayer() const { return m_start_layer; }
int EndLayer() const { return m_end_layer; }
/**
* Return the item's layer, for single-layered items only.
* N.B. This should only be used inside connectivity as B_Cu
* is mapped to a large int
*/
virtual int Layer() const
{
return Layers().Start();
return StartLayer();
}
/**
* When using CN_ITEM layers to compare against board items,
* use this function which correctly remaps the B_Cu layer
*/
PCB_LAYER_ID GetBoardLayer() const
{
int layer = Layer();
if( layer == std::numeric_limits<int>::max() )
layer = B_Cu;
return ToLAYER_ID( layer );
}
const BOX2I& BBox()
@ -232,7 +262,8 @@ public:
protected:
bool m_dirty; ///< used to identify recently added item not yet
///< scanned into the connectivity search
LAYER_RANGE m_layers; ///< layer range over which the item exists
int m_start_layer; ///< start layer of the item N.B. B_Cu is set to INT_MAX
int m_end_layer; ///< end layer of the item N.B. B_Cu is set to INT_MAX
BOX2I m_bbox; ///< bounding box for the item
private:
@ -264,7 +295,7 @@ public:
m_layer( aLayer )
{
m_fillPoly = aParent->GetFilledPolysList( aLayer );
SetLayers( aLayer );
SetLayers( aLayer, aLayer );
}
void BuildRTree()
@ -399,7 +430,7 @@ public:
template <class T>
void FindNearby( CN_ITEM* aItem, T aFunc )
{
m_index.Query( aItem->BBox(), aItem->Layers(), aFunc );
m_index.Query( aItem->BBox(), aItem->StartLayer(), aItem->EndLayer(), aFunc );
}
void SetHasInvalid( bool aInvalid = true ) { m_hasInvalid = aInvalid; }

View File

@ -56,11 +56,10 @@ public:
*/
void Insert( T aItem )
{
const BOX2I& bbox = aItem->BBox();
const LAYER_RANGE layers = aItem->Layers();
const BOX2I& bbox = aItem->BBox();
const int mmin[3] = { layers.Start(), bbox.GetX(), bbox.GetY() };
const int mmax[3] = { layers.End(), bbox.GetRight(), bbox.GetBottom() };
const int mmin[3] = { aItem->StartLayer(), bbox.GetX(), bbox.GetY() };
const int mmax[3] = { aItem->EndLayer(), bbox.GetRight(), bbox.GetBottom() };
m_tree->Insert( mmin, mmax, aItem );
}
@ -75,9 +74,9 @@ public:
// First, attempt to remove the item using its given BBox
const BOX2I& bbox = aItem->BBox();
const LAYER_RANGE layers = aItem->Layers();
const int mmin[3] = { layers.Start(), bbox.GetX(), bbox.GetY() };
const int mmax[3] = { layers.End(), bbox.GetRight(), bbox.GetBottom() };
const int mmin[3] = { aItem->StartLayer(), bbox.GetX(), bbox.GetY() };
const int mmax[3] = { aItem->EndLayer(), bbox.GetRight(), bbox.GetBottom() };
// If we are not successful ( 1 == not found ), then we expand
// the search to the full tree
@ -107,10 +106,13 @@ public:
* with aBounds.
*/
template <class Visitor>
void Query( const BOX2I& aBounds, const LAYER_RANGE& aRange, Visitor& aVisitor ) const
void Query( const BOX2I& aBounds, int aStartLayer, int aEndLayer, Visitor& aVisitor ) const
{
const int mmin[3] = { aRange.Start(), aBounds.GetX(), aBounds.GetY() };
const int mmax[3] = { aRange.End(), aBounds.GetRight(), aBounds.GetBottom() };
int start_layer = aStartLayer == B_Cu ? INT_MAX : aStartLayer;
int end_layer = aEndLayer == B_Cu ? INT_MAX : aEndLayer;
const int mmin[3] = { start_layer, aBounds.GetX(), aBounds.GetY() };
const int mmax[3] = { end_layer, aBounds.GetRight(), aBounds.GetBottom() };
m_tree->Search( mmin, mmax, aVisitor );
}

View File

@ -510,7 +510,7 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
WINDOW_THAWER thawer( m_frame );
if( principalLayer > UNDEFINED_LAYER && ( violationLayers & board->GetVisibleLayers() ) == 0 )
if( principalLayer > UNDEFINED_LAYER && ( violationLayers & board->GetVisibleLayers() ).none() )
m_frame->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
if( principalLayer > UNDEFINED_LAYER && board->GetVisibleLayers().test( principalLayer ) )

View File

@ -292,7 +292,7 @@ void DIALOG_FOOTPRINT_CHECKER::OnSelectItem( wxDataViewEvent& aEvent )
m_frame->FocusOnItem( item );
m_frame->GetCanvas()->Refresh();
if( ( violationLayers & board->GetVisibleLayers() ) == 0 )
if( ( violationLayers & board->GetVisibleLayers() ).none() )
{
m_frame->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
m_frame->GetCanvas()->Refresh();

View File

@ -500,7 +500,7 @@ void DIALOG_PLOT::OnRightClickLayers( wxMouseEvent& event )
{
for( unsigned i = 0; i < m_layerList.size(); i++ )
{
LSET layermask( m_layerList[ i ] );
LSET layermask( { m_layerList[ i ] } );
if( ( layermask & fab_layer_set ).any() )
m_layerCheckListBox->Check( i, true );

View File

@ -358,7 +358,7 @@ void DIALOG_PRINT_PCBNEW::onPopUpLayers( wxCommandEvent& event )
case ID_SELECT_FAB_LAYERS: // Select layers usually needed to build a board
for( unsigned i = 0; i < m_layerList.size(); i++ )
{
LSET layermask( m_layerList[ i ] );
LSET layermask( { m_layerList[ i ] } );
if( ( layermask & fab_layer_set ).any() )
m_layerCheckListBox->Check( i, true );

View File

@ -31,7 +31,7 @@
class LAYER_GRID_TABLE : public wxGridTableBase
{
int m_layers[MAX_CU_LAYERS][2];
std::vector<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>> m_layers;
int m_layerCount;
public:
@ -56,12 +56,25 @@ public:
long GetValueAsLong( int row, int col ) override
{
return m_layers[ row ][ col ];
if( row < 0 || row >= m_layerCount )
return -1;
if( col < 0 || col >= 2 )
return -1;
return col == 0 ? m_layers[ row ].first : m_layers[ row ].second;
}
void SetValueAsLong( int row, int col, long value ) override
{
m_layers[ row ][ col ] = value;
if( row < 0 || col < 0 || col >= 2 )
return;
if( row >= m_layerCount )
m_layers.resize( row + 1 );
col == 0 ? m_layers[row].first = ToLAYER_ID( value )
: m_layers[row].second = ToLAYER_ID( value );
}
};

View File

@ -907,7 +907,7 @@ void PANEL_SETUP_LAYERS::addUserDefinedLayer( wxCommandEvent& aEvent )
wxCHECK( layer >= User_1 && layer <= User_9, /* void */ );
LSET newLayer( layer );
LSET newLayer( { layer } );
m_enabledLayers |= newLayer;

View File

@ -25,6 +25,7 @@
#include <math_for_graphics.h>
#include <board_design_settings.h>
#include <footprint.h>
#include <layer_range.h>
#include <pcb_shape.h>
#include <pad.h>
#include <pcb_track.h>
@ -113,7 +114,7 @@ private:
: layers(), has_error( false ) {}
checked( PCB_LAYER_ID aLayer )
: layers( aLayer ), has_error( false ) {}
: layers( { aLayer } ), has_error( false ) {}
LSET layers;
bool has_error;
@ -1280,10 +1281,10 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
return invalid_result;
};
for( int layer_id = F_Cu; layer_id <= B_Cu; ++layer_id )
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, m_board->GetCopperLayerCount() ) )
{
PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( layer_id );
int zone2zoneClearance;
int zone2zoneClearance;
// Skip over layers not used on the current board
if( !m_board->IsLayerEnabled( layer ) )

View File

@ -39,6 +39,7 @@
#include <board.h>
#include <board_design_settings.h>
#include <footprint.h>
#include <layer_range.h>
#include <pad.h>
#include <pcb_track.h>
#include <vector>
@ -72,7 +73,7 @@ static int compute_pad_access_code( BOARD *aPcb, LSET aLayerMask )
// OK, we have an inner-layer only pad (and I have no idea about
// what could be used for); anyway, find the first copper layer
// it's on
for( int layer = In1_Cu; layer < B_Cu; ++layer )
for( PCB_LAYER_ID layer : LAYER_RANGE( In1_Cu, B_Cu, aPcb->GetCopperLayerCount() ) )
{
if( aLayerMask[layer] )
return layer + 1;

View File

@ -88,42 +88,6 @@ static std::string GenCADLayerName( int aCuCount, PCB_LAYER_ID aId )
}
static const PCB_LAYER_ID gc_seq[] = {
B_Cu,
In30_Cu,
In29_Cu,
In28_Cu,
In27_Cu,
In26_Cu,
In25_Cu,
In24_Cu,
In23_Cu,
In22_Cu,
In21_Cu,
In20_Cu,
In19_Cu,
In18_Cu,
In17_Cu,
In16_Cu,
In15_Cu,
In14_Cu,
In13_Cu,
In12_Cu,
In11_Cu,
In10_Cu,
In9_Cu,
In8_Cu,
In7_Cu,
In6_Cu,
In5_Cu,
In4_Cu,
In3_Cu,
In2_Cu,
In1_Cu,
F_Cu,
};
// flipped layer name for Gencad export (to make CAM350 imports correct)
static std::string GenCADLayerNameFlipped( int aCuCount, PCB_LAYER_ID aId )
{
@ -300,6 +264,9 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
padstacks.resize( 1 ); // We count pads from 1
LSEQ gc_seq = m_board->GetEnabledLayers().CuStack();
std::reverse(gc_seq.begin(), gc_seq.end());
// The master layermask (i.e. the enabled layers) for padstack generation
LSET master_layermask = m_board->GetDesignSettings().GetEnabledLayers();
int cu_count = m_board->GetCopperLayerCount();
@ -589,7 +556,7 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
fmt_mask( mask ).c_str(),
via->GetDrillValue() / SCALE_FACTOR );
for( PCB_LAYER_ID layer : mask.Seq( gc_seq, arrayDim( gc_seq ) ) )
for( PCB_LAYER_ID layer : mask.Seq( gc_seq ) )
{
fprintf( m_file, "PAD V%d.%d.%s %s 0 0\n",
via->GetWidth(), via->GetDrillValue(),
@ -613,7 +580,7 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
LSET pad_set = pad->GetLayerSet() & master_layermask;
// the special gc_seq
for( PCB_LAYER_ID layer : pad_set.Seq( gc_seq, arrayDim( gc_seq ) ) )
for( PCB_LAYER_ID layer : pad_set.Seq( gc_seq ) )
{
fprintf( m_file, "PAD P%u %s 0 0\n", i, GenCADLayerName( cu_count, layer ).c_str() );
}

View File

@ -44,7 +44,7 @@ bool EXPORT_SVG::Plot( BOARD* aBoard, const PCB_PLOT_SVG_OPTIONS& aSvgPlotOption
plot_opts.SetCrossoutDNPFPsOnFabLayers( aSvgPlotOptions.m_crossoutDNPFPsOnFabLayers );
// Adding drill marks, for copper layers
if( ( LSET( aSvgPlotOptions.m_printMaskLayer ) & LSET::AllCuMask() ).any() )
if( ( LSET( { aSvgPlotOptions.m_printMaskLayer } ) & LSET::AllCuMask() ).any() )
{
switch( aSvgPlotOptions.m_drillShapeOption )
{

View File

@ -105,7 +105,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
// Calculate dimensions and center of PCB. The Edge_Cuts layer must be visible
// to calculate the board edges bounding box
LSET visibleLayers = m_pcb->GetVisibleLayers();
m_pcb->SetVisibleLayers( visibleLayers | LSET( Edge_Cuts ) );
m_pcb->SetVisibleLayers( visibleLayers | LSET( { Edge_Cuts } ) );
BOX2I bbbox = m_pcb->GetBoardEdgesBoundingBox();
m_pcb->SetVisibleLayers( visibleLayers );
@ -236,7 +236,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
BRDITEMS_PLOTTER itemplotter( plotter, m_pcb, plot_opts );
// Use attributes of a drawing layer (we are not really draw the Edge.Cuts layer)
itemplotter.SetLayerSet( Dwgs_User );
itemplotter.SetLayerSet( { Dwgs_User } );
for( BOARD_ITEM* item : m_pcb->Drawings() )
{

View File

@ -338,7 +338,7 @@ void GERBER_JOBFILE_WRITER::addJSONFilesAttributes()
nlohmann::ordered_json file_json;
if( layer <= B_Cu )
if( IsCopperLayer( layer ) )
{
gbr_layer_id = wxT( "Copper,L" );

View File

@ -124,7 +124,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
// defined size for component outlines
int line_thickness = pcbIUScale.mmToIU( 0.1 );
brd_plotter.SetLayerSet( LSET( aLayer ) );
brd_plotter.SetLayerSet( LSET( { aLayer } ) );
int cmp_count = 0;
const bool allowUtf8 = true;
const bool quoteOption = false;
@ -291,9 +291,9 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
// Plot board outlines, if requested
if( aIncludeBrdEdges )
{
brd_plotter.SetLayerSet( LSET( Edge_Cuts ) );
brd_plotter.SetLayerSet( LSET( { Edge_Cuts } ) );
// Plot edge layer and graphic items
// Plot edge layer and graphic items
for( const BOARD_ITEM* item : m_pcb->Drawings() )
brd_plotter.PlotBoardGraphicItem( item );

View File

@ -1301,7 +1301,7 @@ bool PCB_TUNING_PATTERN::Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COM
KIGFX::VIEW* view = aTool->GetManager()->GetView();
PNS::ROUTER* router = aTool->Router();
PNS_KICAD_IFACE* iface = aTool->GetInterface();
int layer = GetLayer();
PCB_LAYER_ID layer = GetLayer();
auto hideRemovedItems = [&]( bool aHide )
{
@ -1318,7 +1318,7 @@ bool PCB_TUNING_PATTERN::Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COM
}
};
iface->SetStartLayer( layer );
iface->SetStartLayerFromPCBNew( layer );
if( router->RoutingInProgress() )
{
@ -1984,7 +1984,9 @@ std::vector<EDA_ITEM*> PCB_TUNING_PATTERN::GetPreviewItems( GENERATOR_TOOL* aToo
PNS::ITEM_SET items = placer->TunedPath();
for( PNS::ITEM* item : items )
previewItems.push_back( new ROUTER_PREVIEW_ITEM( item, view, PNS_HOVER_ITEM ) );
previewItems.push_back( new ROUTER_PREVIEW_ITEM( item,
aTool->Router()->GetInterface(),
view, PNS_HOVER_ITEM ) );
}
TUNING_STATUS_VIEW_ITEM* statusItem = new TUNING_STATUS_VIEW_ITEM( aFrame );

View File

@ -222,7 +222,7 @@ FOOTPRINT* MICROWAVE_TOOL::createBaseFootprint( const wxString& aValue,
pad->SetPosition( footprint->GetPosition() );
pad->SetShape( PAD_SHAPE::RECTANGLE );
pad->SetAttribute( PAD_ATTRIB::SMD );
pad->SetLayerSet( F_Cu );
pad->SetLayerSet( { F_Cu } );
pad->SetNumber( wxString::Format( wxT( "%d" ), pad_num ) );
pad_num++;

View File

@ -437,7 +437,7 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN&
pad->SetSize( VECTOR2I( aInductorPattern.m_Width, aInductorPattern.m_Width ) );
pad->SetLayerSet( LSET( footprint->GetLayer() ) );
pad->SetLayerSet( LSET( { footprint->GetLayer() } ) );
pad->SetAttribute( PAD_ATTRIB::SMD );
pad->SetShape( PAD_SHAPE::CIRCLE );

View File

@ -34,6 +34,7 @@
#include <geometry/shape_rect.h>
#include <geometry/shape_compound.h>
#include <geometry/shape_null.h>
#include <layer_range.h>
#include <string_utils.h>
#include <i18n_utility.h>
#include <view/view.h>
@ -102,7 +103,8 @@ PAD::PAD( FOOTPRINT* parent ) :
SetDirty();
m_effectiveBoundingRadius = 0;
m_zoneLayerOverrides.fill( ZLO_NONE );
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, BoardCopperLayerCount() ) )
m_zoneLayerOverrides[layer] = ZLO_NONE;
}
@ -185,6 +187,30 @@ bool PAD::Deserialize( const google::protobuf::Any &aContainer )
}
void PAD::ClearZoneLayerOverrides()
{
std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, BoardCopperLayerCount() ) )
m_zoneLayerOverrides[layer] = ZLO_NONE;
}
const ZONE_LAYER_OVERRIDE& PAD::GetZoneLayerOverride( PCB_LAYER_ID aLayer ) const
{
static const ZONE_LAYER_OVERRIDE defaultOverride = ZLO_NONE;
auto it = m_zoneLayerOverrides.find( aLayer );
return it != m_zoneLayerOverrides.end() ? it->second : defaultOverride;
}
void PAD::SetZoneLayerOverride( PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride )
{
std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
m_zoneLayerOverrides[aLayer] = aOverride;
}
bool PAD::CanHaveNumber() const
{
// Aperture pads don't get a number
@ -268,7 +294,7 @@ LSET PAD::UnplatedHoleMask()
LSET PAD::ApertureMask()
{
static LSET saved( F_Paste );
static LSET saved( { F_Paste } );
return saved;
}
@ -360,12 +386,19 @@ bool PAD::FlashLayer( int aLayer, bool aOnlyCheckIfPermitted ) const
static std::initializer_list<KICAD_T> types = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
PCB_PAD_T };
if( m_zoneLayerOverrides[ aLayer ] == ZLO_FORCE_FLASHED )
if( auto it = m_zoneLayerOverrides.find( static_cast<PCB_LAYER_ID>( aLayer ) );
it != m_zoneLayerOverrides.end() && it->second == ZLO_FORCE_FLASHED )
{
return true;
}
else if( aOnlyCheckIfPermitted )
{
return true;
}
else
{
return board->GetConnectivity()->IsConnectedOnLayer( this, aLayer, types );
}
}
}
@ -2138,7 +2171,7 @@ void PAD::CheckPad( UNITS_PROVIDER* aUnitsProvider,
LSET padlayers_mask = GetLayerSet();
if( padlayers_mask == 0 )
if( padlayers_mask.none() )
aErrorHandler( DRCE_PADSTACK_INVALID, _( "(Pad has no layer)" ) );
if( GetAttribute() == PAD_ATTRIB::PTH && !IsOnCopperLayer() )

View File

@ -805,21 +805,11 @@ public:
virtual const BOX2I ViewBBox() const override;
void ClearZoneLayerOverrides()
{
m_zoneLayerOverrides.fill( ZLO_NONE );
}
void ClearZoneLayerOverrides();
const ZONE_LAYER_OVERRIDE& GetZoneLayerOverride( PCB_LAYER_ID aLayer ) const
{
return m_zoneLayerOverrides.at( aLayer );
}
const ZONE_LAYER_OVERRIDE& GetZoneLayerOverride( PCB_LAYER_ID aLayer ) const;
void SetZoneLayerOverride( PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride )
{
std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
m_zoneLayerOverrides.at( aLayer ) = aOverride;
}
void SetZoneLayerOverride( PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride );
void CheckPad( UNITS_PROVIDER* aUnitsProvider,
const std::function<void( int aErrorCode,
@ -871,8 +861,8 @@ private:
int m_lengthPadToDie; // Length net from pad to die, inside the package
std::mutex m_zoneLayerOverridesMutex;
std::array<ZONE_LAYER_OVERRIDE, MAX_CU_LAYERS> m_zoneLayerOverrides;
std::mutex m_zoneLayerOverridesMutex;
std::map<PCB_LAYER_ID, ZONE_LAYER_OVERRIDE> m_zoneLayerOverrides;
};
#endif // PAD_H

View File

@ -161,7 +161,7 @@ bool PCB_GENERATOR::AddItem( BOARD_ITEM* aItem )
LSET PCB_GENERATOR::GetLayerSet() const
{
return PCB_GROUP::GetLayerSet() | LSET( GetLayer() );
return PCB_GROUP::GetLayerSet() | LSET( { GetLayer() } );
}

View File

@ -30,6 +30,7 @@
#include <board.h>
#include <board_design_settings.h>
#include <layer_range.h>
#include <pcb_dimension.h>
#include <pad.h>
#include <pcb_shape.h>
@ -240,10 +241,11 @@ std::vector<PCB_LAYER_ID> ALTIUM_PCB::GetKicadLayersToIterate( ALTIUM_LAYER aAlt
if( aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER || aAltiumLayer == ALTIUM_LAYER::KEEP_OUT_LAYER )
{
int layerCount = m_board ? m_board->GetCopperLayerCount() : 32;
std::vector<PCB_LAYER_ID> layers;
layers.reserve( MAX_CU_LAYERS );
layers.reserve( layerCount );
for( PCB_LAYER_ID layer : LSET::AllCuMask().Seq() )
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, layerCount ) )
{
if( !m_board || m_board->IsLayerEnabled( layer ) )
layers.emplace_back( layer );
@ -268,7 +270,7 @@ std::vector<PCB_LAYER_ID> ALTIUM_PCB::GetKicadLayersToIterate( ALTIUM_LAYER aAlt
}
klayer = Eco1_User;
m_board->SetEnabledLayers( m_board->GetEnabledLayers() | LSET( klayer ) );
m_board->SetEnabledLayers( m_board->GetEnabledLayers() | LSET( { klayer } ) );
}
return { klayer };
@ -1154,7 +1156,7 @@ void ALTIUM_PCB::remapUnsureLayers( std::vector<ABOARD6_LAYER_STACKUP>& aStackup
ALTIUM_LAYER altiumID = altiumLayerNameMap.at( layerPair.first );
m_layermap.insert_or_assign( altiumID, layerPair.second );
enabledLayers |= LSET( layerPair.second );
enabledLayers |= LSET( { layerPair.second } );
}
m_board->SetEnabledLayers( enabledLayers );
@ -3485,7 +3487,7 @@ void ALTIUM_PCB::ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, con
default:
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
pad->SetLayer( klayer );
pad->SetLayerSet( LSET( klayer ) );
pad->SetLayerSet( LSET( { klayer } ) );
break;
}

View File

@ -725,7 +725,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::remapUnsureLayers()
LAYER_ID cadstarLayerID = cadstarLayerNameMap.at( layerPair.first );
m_layermap.at( cadstarLayerID ) = layerPair.second;
enabledLayers |= LSET( layerPair.second );
enabledLayers |= LSET( { layerPair.second } );
}
m_board->SetEnabledLayers( enabledLayers );
@ -1119,7 +1119,7 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
// prevent DRC errors.
// TODO: This could be a custom padstack, update when KiCad supports padstacks
pad->SetAttribute( PAD_ATTRIB::SMD );
pad->SetLayerSet( LSET( F_Mask ) );
pad->SetLayerSet( LSET( { F_Mask } ) );
}
// zero sized pads seems to break KiCad so lets make it very small instead
@ -4177,7 +4177,7 @@ LSET CADSTAR_PCB_ARCHIVE_LOADER::getKiCadLayerSet( const LAYER_ID& aCadstarLayer
| LSET::AllBoardTechMask();
default:
return LSET( getKiCadLayer( aCadstarLayerID ) );
return LSET( { getKiCadLayer( aCadstarLayerID ) } );
}
}

View File

@ -154,7 +154,7 @@ void PCB_IO_EAGLE::setKeepoutSettingsToZone( ZONE* aZone, int aLayer ) const
aZone->SetDoNotAllowPads( false );
aZone->SetDoNotAllowFootprints( false );
aZone->SetLayerSet( kicad_layer( aLayer ) );
aZone->SetLayerSet( { kicad_layer( aLayer ) } );
}
}
@ -3008,7 +3008,7 @@ std::tuple<PCB_LAYER_ID, LSET, bool> PCB_IO_EAGLE::defaultKicadLayer( int aEagle
case EAGLE_LAYER::DIMENSION:
kiLayer = Edge_Cuts;
required = true;
permittedLayers = LSET( Edge_Cuts );
permittedLayers = LSET( { Edge_Cuts } );
break;
case EAGLE_LAYER::TPLACE:

View File

@ -984,7 +984,7 @@ void PCB_IO_EASYEDA_PARSER::ParseToBoardItemContainer(
else
{
pad->SetLayer( klayer );
pad->SetLayerSet( LSET( klayer ) );
pad->SetLayerSet( LSET( { klayer } ) );
pad->SetAttribute( PAD_ATTRIB::SMD );
}

View File

@ -686,39 +686,9 @@ void PCB_IO_KICAD_SEXPR::formatBoardLayers( const BOARD* aBoard, int aNestLevel
}
// Save used non-copper layers in the order they are defined.
// desired sequence for non Cu BOARD layers.
static const PCB_LAYER_ID non_cu[] =
{
B_Adhes, // 32
F_Adhes,
B_Paste,
F_Paste,
B_SilkS,
F_SilkS,
B_Mask,
F_Mask,
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User,
Edge_Cuts,
Margin,
B_CrtYd,
F_CrtYd,
B_Fab,
F_Fab,
User_1,
User_2,
User_3,
User_4,
User_5,
User_6,
User_7,
User_8,
User_9
};
LSEQ seq = aBoard->GetEnabledLayers().TechAndUserUIOrder();
for( PCB_LAYER_ID layer : aBoard->GetEnabledLayers().Seq( non_cu, arrayDim( non_cu ) ) )
for( PCB_LAYER_ID layer : seq )
{
m_out->Print( aNestLevel+1, "(%d %s",
layer,

View File

@ -104,10 +104,10 @@ void PCB_IO_KICAD_SEXPR_PARSER::init()
// The English name will survive if parsing only a footprint.
for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
{
std::string untranslated = TO_UTF8( wxString( LSET::Name( PCB_LAYER_ID( layer ) ) ) );
std::string untranslated = TO_UTF8( LSET::Name( PCB_LAYER_ID( layer ) ) );
m_layerIndices[ untranslated ] = PCB_LAYER_ID( layer );
m_layerMasks[ untranslated ] = LSET( PCB_LAYER_ID( layer ) );
m_layerIndices[untranslated] = PCB_LAYER_ID( layer );
m_layerMasks[untranslated] = LSET( { PCB_LAYER_ID( layer ) } );
}
m_layerMasks[ "*.Cu" ] = LSET::AllCuMask();
@ -130,7 +130,7 @@ void PCB_IO_KICAD_SEXPR_PARSER::init()
{
std::string key = StrPrintf( "Inner%d.Cu", i );
m_layerMasks[ key ] = LSET( PCB_LAYER_ID( In15_Cu - i ) );
m_layerMasks[key] = LSET( { PCB_LAYER_ID( In15_Cu - 2 * i ) } );
}
}
@ -1716,7 +1716,7 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseBoardStackup()
type = BS_ITEM_TYPE_SOLDERPASTE;
else if( layerId == UNDEFINED_LAYER )
type = BS_ITEM_TYPE_DIELECTRIC;
else if( layerId >= F_Cu && layerId <= B_Cu )
else if( !( layerId & 1 ) )
type = BS_ITEM_TYPE_COPPER;
BOARD_STACKUP_ITEM* item = nullptr;
@ -1942,26 +1942,34 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseLayers()
{
// Rework the layer numbers, which changed when the Cu stack
// was flipped. So we instead use position in the list.
for( size_t i = 1; i < cu.size() - 1; i++ )
{
int tmpLayer = LSET::NameToLayer( cu[i].m_name );
if( i < 0 )
tmpLayer = ( i + 1 ) * 2;
cu[i].m_number = tmpLayer;
}
cu[0].m_number = F_Cu;
cu[cu.size()-1].m_number = B_Cu;
for( unsigned i=0; i < cu.size()-1; ++i )
cu[i].m_number = i;
for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
for( auto& cu_layer : cu )
{
enabledLayers.set( it->m_number );
enabledLayers.set( cu_layer.m_number );
if( it->m_visible )
visibleLayers.set( it->m_number );
if( cu_layer.m_visible )
visibleLayers.set( cu_layer.m_number );
else
anyHidden = true;
m_board->SetLayerDescr( PCB_LAYER_ID( it->m_number ), *it );
m_board->SetLayerDescr( PCB_LAYER_ID( cu_layer.m_number ), cu_layer );
UTF8 name = it->m_name;
UTF8 name = cu_layer.m_name;
m_layerIndices[ name ] = PCB_LAYER_ID( it->m_number );
m_layerMasks[ name ] = LSET( PCB_LAYER_ID( it->m_number ) );
m_layerIndices[ name ] = PCB_LAYER_ID( cu_layer.m_number );
m_layerMasks[ name ] = LSET( { PCB_LAYER_ID( cu_layer.m_number ) } );
}
copperLayerCount = cu.size();
@ -1994,7 +2002,7 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseLayers()
// If we are here, then we have found a translated layer name. Put it in the maps
// so that items on this layer get the appropriate layer ID number.
m_layerIndices[ UTF8( layer.m_name ) ] = it->second;
m_layerMasks[ UTF8( layer.m_name ) ] = it->second;
m_layerMasks[ UTF8( layer.m_name ) ] = LSET( { it->second } );
layer.m_name = it->first;
}
@ -2034,11 +2042,21 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseLayers()
}
template<class T, class M>
T PCB_IO_KICAD_SEXPR_PARSER::lookUpLayer( const M& aMap )
LSET PCB_IO_KICAD_SEXPR_PARSER::lookUpLayerSet( const LSET_MAP& aMap )
{
LSET_MAP::const_iterator it = aMap.find( curText );
if( it == aMap.end() )
return LSET( { Rescue } );
return it->second;
}
PCB_LAYER_ID PCB_IO_KICAD_SEXPR_PARSER::lookUpLayer( const LAYER_ID_MAP& aMap )
{
// avoid constructing another std::string, use lexer's directly
typename M::const_iterator it = aMap.find( curText );
LAYER_ID_MAP::const_iterator it = aMap.find( curText );
if( it == aMap.end() )
{
@ -2061,7 +2079,7 @@ PCB_LAYER_ID PCB_IO_KICAD_SEXPR_PARSER::parseBoardItemLayer()
NextTok();
PCB_LAYER_ID layerIndex = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
PCB_LAYER_ID layerIndex = lookUpLayer( m_layerIndices );
// Handle closing ) in object parser.
@ -2078,8 +2096,7 @@ LSET PCB_IO_KICAD_SEXPR_PARSER::parseBoardItemLayersAsMask()
for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
{
LSET mask = lookUpLayer<LSET>( m_layerMasks );
layerMask |= mask;
layerMask |= lookUpLayerSet( m_layerMasks );
}
return layerMask;
@ -5263,9 +5280,9 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent )
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
PCB_LAYER_ID layer = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
PCB_LAYER_ID layer = lookUpLayer( m_layerIndices );
if( layer < F_Cu || layer > B_Cu )
if( !IsCopperLayer( layer ) )
Expecting( "copper layer name" );
pad->SetZoneLayerOverride( layer, ZLO_FORCE_FLASHED );
@ -5864,10 +5881,14 @@ PCB_VIA* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_VIA()
{
PCB_LAYER_ID layer1, layer2;
NextTok();
layer1 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
layer1 = lookUpLayer( m_layerIndices );
NextTok();
layer2 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
layer2 = lookUpLayer( m_layerIndices );
via->SetLayerPair( layer1, layer2 );
if( layer1 == UNDEFINED_LAYER || layer2 == UNDEFINED_LAYER )
Expecting( "layer name" );
NeedRIGHT();
break;
}
@ -5908,9 +5929,9 @@ PCB_VIA* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_VIA()
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
PCB_LAYER_ID layer = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
PCB_LAYER_ID layer = lookUpLayer( m_layerIndices );
if( layer < F_Cu || layer > B_Cu )
if( !IsCopperLayer( layer ) )
Expecting( "copper layer name" );
via->SetZoneLayerOverride( layer, ZLO_FORCE_FLASHED );

View File

@ -76,6 +76,11 @@ class TEARDROP_PARAMETERS;
class PCB_IO_KICAD_SEXPR_PARSER : public PCB_LEXER
{
public:
typedef std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP;
typedef std::unordered_map< std::string, LSET > LSET_MAP;
typedef std::unordered_map< wxString, KIID > KIID_MAP;
PCB_IO_KICAD_SEXPR_PARSER( LINE_READER* aReader, BOARD* aAppendToMe,
std::function<bool( wxString, int, wxString, wxString )> aQueryUserCallback,
PROGRESS_REPORTER* aProgressReporter = nullptr, unsigned aLineCount = 0 ) :
@ -249,8 +254,8 @@ private:
* @throw IO_ERROR if the layer is not valid.
* @throw PARSE_ERROR if the layer syntax is incorrect.
*/
template<class T, class M>
T lookUpLayer( const M& aMap );
PCB_LAYER_ID lookUpLayer( const LAYER_ID_MAP& aMap );
LSET lookUpLayerSet( const LSET_MAP& aMap );
/**
* Parse the layer definition of a #BOARD_ITEM object.
@ -374,10 +379,6 @@ private:
*/
void resolveGroups( BOARD_ITEM* aParent );
typedef std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP;
typedef std::unordered_map< std::string, LSET > LSET_MAP;
typedef std::unordered_map< wxString, KIID > KIID_MAP;
///< The type of progress bar timeout
using TIMEOUT = std::chrono::milliseconds;

View File

@ -31,6 +31,7 @@
#include <convert_basic_shapes_to_polygon.h>
#include <pcb_track.h>
#include <base_units.h>
#include <layer_range.h>
#include <lset.h>
#include <string_utils.h>
#include <view/view.h>
@ -98,7 +99,8 @@ PCB_VIA::PCB_VIA( BOARD_ITEM* aParent ) :
// For now, vias are always circles
m_padStack.SetShape( PAD_SHAPE::CIRCLE );
m_zoneLayerOverrides.fill( ZLO_NONE );
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, BoardCopperLayerCount() ) )
m_zoneLayerOverrides[layer] = ZLO_NONE;
m_isFree = false;
}
@ -867,7 +869,7 @@ bool PCB_VIA::IsOnLayer( PCB_LAYER_ID aLayer ) const
return GetLayerSet().test( aLayer );
#endif
if( aLayer >= Padstack().Drill().start && aLayer <= Padstack().Drill().end )
if( LAYER_RANGE::Contains( Padstack().Drill().start, Padstack().Drill().end, aLayer ) )
return true;
if( aLayer == F_Mask )
@ -899,13 +901,17 @@ LSET PCB_VIA::GetLayerSet() const
return layermask;
if( GetViaType() == VIATYPE::THROUGH )
layermask = LSET::AllCuMask();
{
layermask = LSET::AllCuMask( BoardCopperLayerCount() );
}
else
wxASSERT( Padstack().Drill().start <= Padstack().Drill().end );
{
LAYER_RANGE range( Padstack().Drill().start, Padstack().Drill().end, BoardCopperLayerCount() );
// PCB_LAYER_IDs are numbered from front to back, this is top to bottom.
for( int id = Padstack().Drill().start; id <= Padstack().Drill().end; ++id )
layermask.set( id );
// PCB_LAYER_IDs are numbered from front to back, this is top to bottom.
for( PCB_LAYER_ID id : range )
layermask.set( id );
}
if( !IsTented( F_Mask ) && layermask.test( F_Cu ) )
layermask.set( F_Mask );
@ -1064,10 +1070,34 @@ bool PCB_VIA::FlashLayer( int aLayer ) const
static std::initializer_list<KICAD_T> connectedTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
PCB_PAD_T };
if( m_zoneLayerOverrides[ aLayer ] == ZLO_FORCE_FLASHED )
if( GetZoneLayerOverride( static_cast<PCB_LAYER_ID>( aLayer ) ) == ZLO_FORCE_FLASHED )
return true;
else
return board->GetConnectivity()->IsConnectedOnLayer( this, aLayer, connectedTypes );
return board->GetConnectivity()->IsConnectedOnLayer( this, static_cast<PCB_LAYER_ID>( aLayer ), connectedTypes );
}
void PCB_VIA::ClearZoneLayerOverrides()
{
std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, BoardCopperLayerCount() ) )
m_zoneLayerOverrides[layer] = ZLO_NONE;
}
const ZONE_LAYER_OVERRIDE& PCB_VIA::GetZoneLayerOverride( PCB_LAYER_ID aLayer ) const
{
static const ZONE_LAYER_OVERRIDE defaultOverride = ZLO_NONE;
auto it = m_zoneLayerOverrides.find( aLayer );
return it != m_zoneLayerOverrides.end() ? it->second : defaultOverride;
}
void PCB_VIA::SetZoneLayerOverride( PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride )
{
std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
m_zoneLayerOverrides[aLayer] = aOverride;
}
@ -1084,7 +1114,7 @@ void PCB_VIA::GetOutermostConnectedLayers( PCB_LAYER_ID* aTopmost,
{
bool connected = false;
if( m_zoneLayerOverrides[ layer ] == ZLO_FORCE_FLASHED )
if( GetZoneLayerOverride( static_cast<PCB_LAYER_ID>( layer ) ) == ZLO_FORCE_FLASHED )
connected = true;
else if( GetBoard()->GetConnectivity()->IsConnectedOnLayer( this, layer, connectedTypes ) )
connected = true;

View File

@ -605,21 +605,11 @@ public:
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
void ClearZoneLayerOverrides()
{
m_zoneLayerOverrides.fill( ZLO_NONE );
}
void ClearZoneLayerOverrides();
const ZONE_LAYER_OVERRIDE& GetZoneLayerOverride( PCB_LAYER_ID aLayer ) const
{
return m_zoneLayerOverrides.at( aLayer );
}
const ZONE_LAYER_OVERRIDE& GetZoneLayerOverride( PCB_LAYER_ID aLayer ) const;
void SetZoneLayerOverride( PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride )
{
std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
m_zoneLayerOverrides.at( aLayer ) = aOverride;
}
void SetZoneLayerOverride( PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride );
double Similarity( const BOARD_ITEM& aOther ) const override;
@ -641,8 +631,8 @@ private:
bool m_isFree; ///< "Free" vias don't get their nets auto-updated
std::mutex m_zoneLayerOverridesMutex;
std::array<ZONE_LAYER_OVERRIDE, MAX_CU_LAYERS> m_zoneLayerOverrides;
std::mutex m_zoneLayerOverridesMutex;
std::map<PCB_LAYER_ID, ZONE_LAYER_OVERRIDE> m_zoneLayerOverrides;
};

View File

@ -660,7 +660,7 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob )
aGerberJob->m_layersIncludeOnAll = plotOnAllLayersSelection;
}
for( PCB_LAYER_ID layer : LSET( aGerberJob->m_printMaskLayer ).UIOrder() )
for( PCB_LAYER_ID layer : LSET( { aGerberJob->m_printMaskLayer } ).UIOrder() )
{
LSEQ plotSequence;

View File

@ -105,7 +105,7 @@ bool PCBNEW_PRINTOUT::OnPrintPage( int aPage )
// aPage starts at 1, not 0
if( unsigned( aPage - 1 ) < seq.size() )
m_settings.m_LayerSet = LSET( seq[ aPage - 1] );
m_settings.m_LayerSet = LSET( { seq[aPage - 1] } );
}
if( !m_settings.m_LayerSet.any() )

View File

@ -68,7 +68,7 @@ void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
for( PCB_LAYER_ID layer : aLayers )
{
// copper layers with drill marks will be plotted after all other layers
if( layer <= B_Cu && plot_mark )
if( IsCopperLayer( layer ) && plot_mark )
continue;
PlotOneBoardLayer( aBoard, aPlotter, layer, aPlotOptions );
@ -79,7 +79,7 @@ void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
for( PCB_LAYER_ID layer : aLayers )
{
if( layer > B_Cu ) // already plotted
if( !IsCopperLayer( layer ) )
continue;
PlotOneBoardLayer( aBoard, aPlotter, layer, aPlotOptions );
@ -177,7 +177,7 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
// Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
// contents of the currently specified layer.
LSET layer_mask( aLayer );
LSET layer_mask( { aLayer } );
if( IsCopperLayer( aLayer ) )
{
@ -238,9 +238,9 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
&& plotOpt.GetSubtractMaskFromSilk() )
{
if( aLayer == F_SilkS )
layer_mask = LSET( F_Mask );
layer_mask = LSET( { F_Mask } );
else
layer_mask = LSET( B_Mask );
layer_mask = LSET( { B_Mask } );
// Create the mask to subtract by creating a negative layer polarity
aPlotter->SetLayerPolarity( false );
@ -290,8 +290,8 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
bool onCopperLayer = ( LSET::AllCuMask() & aLayerMask ).any();
bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & aLayerMask ).any();
bool onSolderPasteLayer = ( LSET( { F_Paste, B_Paste } ) & aLayerMask ).any();
bool onFrontFab = ( LSET( F_Fab ) & aLayerMask ).any();
bool onBackFab = ( LSET( B_Fab ) & aLayerMask ).any();
bool onFrontFab = ( LSET( { F_Fab } ) & aLayerMask ).any();
bool onBackFab = ( LSET( { B_Fab } ) & aLayerMask ).any();
bool sketchPads = ( onFrontFab || onBackFab ) && aPlotOpt.GetSketchPadsOnFabLayers();
// Plot edge layer and graphic items

View File

@ -349,7 +349,7 @@ void RN_NET::OptimizeRNEdges()
CN_ZONE_LAYER* zoneLayer = dynamic_cast<CN_ZONE_LAYER*>( item );
if( zoneLayer && aLayerSet.test( zoneLayer->Layer() ) )
if( zoneLayer && aLayerSet.test( zoneLayer->GetBoardLayer() ) )
{
const std::vector<VECTOR2I>& pts = zoneLayer->GetOutline().CPoints();

View File

@ -70,7 +70,7 @@ void DIFF_PAIR_PLACER::setWorld( NODE* aWorld )
const VIA DIFF_PAIR_PLACER::makeVia( const VECTOR2I& aP, NET_HANDLE aNet )
{
const LAYER_RANGE layers( m_sizes.GetLayerTop(), m_sizes.GetLayerBottom() );
const PNS_LAYER_RANGE layers( m_sizes.GetLayerTop(), m_sizes.GetLayerBottom() );
VIA v( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), aNet, m_sizes.ViaType() );

View File

@ -133,7 +133,7 @@ HOLE* HOLE::MakeCircularHole( const VECTOR2I& pos, int radius )
SHAPE_CIRCLE* circle = new SHAPE_CIRCLE( pos, radius );
HOLE* hole = new HOLE( circle );
hole->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
hole->SetLayers( PNS_LAYER_RANGE( F_Cu, B_Cu ) );
return hole;
}

View File

@ -27,7 +27,7 @@ namespace PNS {
void INDEX::Add( ITEM* aItem )
{
const LAYER_RANGE& range = aItem->Layers();
const PNS_LAYER_RANGE& range = aItem->Layers();
assert( range.Start() != -1 && range.End() != -1 );
if( m_subIndices.size() <= static_cast<size_t>( range.End() ) )
@ -46,7 +46,7 @@ void INDEX::Add( ITEM* aItem )
void INDEX::Remove( ITEM* aItem )
{
const LAYER_RANGE& range = aItem->Layers();
const PNS_LAYER_RANGE& range = aItem->Layers();
assert( range.Start() != -1 && range.End() != -1 );
if( m_subIndices.size() <= static_cast<size_t>( range.End() ) )

View File

@ -144,7 +144,7 @@ int INDEX::Query( const ITEM* aItem, int aMinDistance, Visitor& aVisitor ) const
wxCHECK( aItem->Kind() != ITEM::INVALID_T, 0 );
const LAYER_RANGE& layers = aItem->Layers();
const PNS_LAYER_RANGE& layers = aItem->Layers();
for( int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle( i, aItem->Shape(), aMinDistance, aVisitor );

View File

@ -193,10 +193,10 @@ public:
void SetNet( NET_HANDLE aNet ) { m_net = aNet; }
virtual NET_HANDLE Net() const { return m_net; }
const LAYER_RANGE& Layers() const { return m_layers; }
void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
const PNS_LAYER_RANGE& Layers() const { return m_layers; }
void SetLayers( const PNS_LAYER_RANGE& aLayers ) { m_layers = aLayers; }
void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
void SetLayer( int aLayer ) { m_layers = PNS_LAYER_RANGE( aLayer, aLayer ); }
virtual int Layer() const { return Layers().Start(); }
/**
@ -285,7 +285,7 @@ protected:
PnsKind m_kind;
BOARD_ITEM* m_parent;
LAYER_RANGE m_layers;
PNS_LAYER_RANGE m_layers;
bool m_movable;
NET_HANDLE m_net;

View File

@ -48,12 +48,12 @@ void ITEM_SET::Prepend( const LINE& aLine )
ITEM_SET& ITEM_SET::FilterLayers( int aStart, int aEnd, bool aInvert )
{
std::vector<ITEM*> newItems;
LAYER_RANGE l;
PNS_LAYER_RANGE l;
if( aEnd < 0 )
l = LAYER_RANGE( aStart );
l = PNS_LAYER_RANGE( aStart );
else
l = LAYER_RANGE( aStart, aEnd );
l = PNS_LAYER_RANGE( aStart, aEnd );
for( ITEM* item : m_items )
{

View File

@ -67,7 +67,7 @@ public:
JOINT() :
ITEM( JOINT_T ), m_tag(), m_locked( false ) {}
JOINT( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HANDLE aNet = nullptr ) :
JOINT( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet = nullptr ) :
ITEM( JOINT_T )
{
m_tag.pos = aPos;

View File

@ -24,6 +24,7 @@
#include <board_design_settings.h>
#include <netinfo.h>
#include <footprint.h>
#include <layer_range.h>
#include <pad.h>
#include <pcb_track.h>
#include <zone.h>
@ -62,6 +63,7 @@
#include "pns_arc.h"
#include "pns_sizes_settings.h"
#include "pns_item.h"
#include "pns_layerset.h"
#include "pns_line.h"
#include "pns_solid.h"
#include "pns_segment.h"
@ -215,7 +217,8 @@ bool PNS_PCBNEW_RULE_RESOLVER::IsNetTieExclusion( const PNS::ITEM* aItem,
if( drcEngine )
{
return drcEngine->IsNetTieExclusion( NetCode( aItem->Net() ), ToLAYER_ID( aItem->Layer() ),
return drcEngine->IsNetTieExclusion( NetCode( aItem->Net() ),
ToLAYER_ID( m_routerIface->GetBoardLayerFromPNSLayer( aItem->Layer() ) ),
aCollisionPos, collidingItem );
}
@ -333,12 +336,12 @@ bool PNS_PCBNEW_RULE_RESOLVER::IsNonPlatedSlot( const PNS::ITEM* aItem )
}
BOARD_ITEM* PNS_PCBNEW_RULE_RESOLVER::getBoardItem( const PNS::ITEM* aItem, int aLayer, int aIdx )
BOARD_ITEM* PNS_PCBNEW_RULE_RESOLVER::getBoardItem( const PNS::ITEM* aItem, int aBoardLayer, int aIdx )
{
switch( aItem->Kind() )
{
case PNS::ITEM::ARC_T:
m_dummyArcs[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
m_dummyArcs[aIdx].SetLayer( ToLAYER_ID( aBoardLayer ) );
m_dummyArcs[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
m_dummyArcs[aIdx].SetStart( aItem->Anchor( 0 ) );
m_dummyArcs[aIdx].SetEnd( aItem->Anchor( 1 ) );
@ -346,14 +349,14 @@ BOARD_ITEM* PNS_PCBNEW_RULE_RESOLVER::getBoardItem( const PNS::ITEM* aItem, int
case PNS::ITEM::VIA_T:
case PNS::ITEM::HOLE_T:
m_dummyVias[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
m_dummyVias[aIdx].SetLayer( ToLAYER_ID( aBoardLayer ) );
m_dummyVias[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
m_dummyVias[aIdx].SetStart( aItem->Anchor( 0 ) );
return &m_dummyVias[aIdx];
case PNS::ITEM::SEGMENT_T:
case PNS::ITEM::LINE_T:
m_dummyTracks[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
m_dummyTracks[aIdx].SetLayer( ToLAYER_ID( aBoardLayer ) );
m_dummyTracks[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
m_dummyTracks[aIdx].SetStart( aItem->Anchor( 0 ) );
m_dummyTracks[aIdx].SetEnd( aItem->Anchor( 1 ) );
@ -367,7 +370,7 @@ BOARD_ITEM* PNS_PCBNEW_RULE_RESOLVER::getBoardItem( const PNS::ITEM* aItem, int
bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
int aLayer, PNS::CONSTRAINT* aConstraint )
int aPNSLayer, PNS::CONSTRAINT* aConstraint )
{
std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
@ -395,17 +398,18 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
BOARD_ITEM* parentA = aItemA ? aItemA->BoardItem() : nullptr;
BOARD_ITEM* parentB = aItemB ? aItemB->BoardItem() : nullptr;
int board_layer = m_routerIface->GetBoardLayerFromPNSLayer( aPNSLayer );
DRC_CONSTRAINT hostConstraint;
// A track being routed may not have a BOARD_ITEM associated yet.
if( aItemA && !parentA )
parentA = getBoardItem( aItemA, aLayer, 0 );
parentA = getBoardItem( aItemA, board_layer, 0 );
if( aItemB && !parentB )
parentB = getBoardItem( aItemB, aLayer, 1 );
parentB = getBoardItem( aItemB, board_layer, 1 );
if( parentA )
hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, ToLAYER_ID( aLayer ) );
hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, ToLAYER_ID( board_layer ) );
if( hostConstraint.IsNull() )
return false;
@ -502,7 +506,7 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
PNS::CONSTRAINT constraint;
int rv = 0;
LAYER_RANGE layers;
PNS_LAYER_RANGE layers;
if( !aB )
layers = aA->Layers();
@ -514,7 +518,7 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
layers = aA->Layers().Intersection( aB->Layers() );
// Normalize layer range (no -1 magic numbers)
layers = layers.Intersection( LAYER_RANGE( PCBNEW_LAYER_ID_START, PCB_LAYER_ID_COUNT - 1 ) );
layers = layers.Intersection( PNS_LAYER_RANGE( PCBNEW_LAYER_ID_START, PCB_LAYER_ID_COUNT - 1 ) );
for( int layer = layers.Start(); layer <= layers.End(); ++layer )
{
@ -859,7 +863,8 @@ int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) con
BOARD_STACKUP& stackup = m_board->GetDesignSettings().GetStackupDescriptor();
return stackup.GetLayerDistance( ToLAYER_ID( aFirstLayer ), ToLAYER_ID( aSecondLayer ) );
return stackup.GetLayerDistance( GetPCBLayerIDFromPNSLayer( aFirstLayer ),
GetPCBLayerIDFromPNSLayer( aSecondLayer ) );
}
@ -935,14 +940,13 @@ bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( const PNS::ITEM* aItem, PNS::NET_HANDL
class PNS_PCBNEW_DEBUG_DECORATOR: public PNS::DEBUG_DECORATOR
{
public:
PNS_PCBNEW_DEBUG_DECORATOR( KIGFX::VIEW* aView = nullptr ) :
PNS_PCBNEW_DEBUG_DECORATOR( PNS::ROUTER_IFACE* aIface ) :
PNS::DEBUG_DECORATOR(),
m_iface( aIface ),
m_view( nullptr ),
m_items( nullptr ),
m_depth( 0 )
{
SetView( aView );
}
{}
~PNS_PCBNEW_DEBUG_DECORATOR()
{
@ -993,7 +997,7 @@ public:
if( !m_view || !aItem )
return;
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_iface, m_view );
pitem->SetColor( aColor.WithAlpha( 0.5 ) );
pitem->SetWidth( aOverrideWidth );
@ -1029,7 +1033,7 @@ public:
if( !m_view || !aShape )
return;
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_view );
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_iface, m_view );
pitem->SetColor( aColor.WithAlpha( 0.5 ) );
pitem->SetWidth( aOverrideWidth );
@ -1064,6 +1068,7 @@ private:
return m_depth;
}
PNS::ROUTER_IFACE* m_iface;
KIGFX::VIEW* m_view;
KIGFX::VIEW_GROUP* m_items;
@ -1115,10 +1120,11 @@ PNS_KICAD_IFACE::~PNS_KICAD_IFACE()
std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
{
LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 );
PNS_LAYER_RANGE layers( 0, aPad->BoardCopperLayerCount() );
LSEQ lmsk = aPad->GetLayerSet().CuStack();
// ignore non-copper pads except for those with holes
if( ( aPad->GetLayerSet() & LSET::AllCuMask() ).none() && aPad->GetDrillSize().x == 0 )
if( lmsk.empty() && aPad->GetDrillSize().x == 0 )
return nullptr;
switch( aPad->GetAttribute() )
@ -1130,20 +1136,12 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
case PAD_ATTRIB::CONN:
case PAD_ATTRIB::SMD:
{
LSET lmsk = aPad->GetLayerSet();
bool is_copper = false;
for( int i = 0; i < MAX_CU_LAYERS; i++ )
if( !lmsk.empty() && aPad->GetAttribute() != PAD_ATTRIB::NPTH )
{
if( lmsk[i] )
{
is_copper = true;
if( aPad->GetAttribute() != PAD_ATTRIB::NPTH )
layers = LAYER_RANGE( i );
break;
}
layers = SetLayersFromPCBNew( lmsk.front(), lmsk.front() );
is_copper = true;
}
if( !is_copper )
@ -1216,7 +1214,7 @@ std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack
aTrack->GetNet() );
segment->SetWidth( aTrack->GetWidth() );
segment->SetLayers( LAYER_RANGE( aTrack->GetLayer() ) );
segment->SetLayer( GetPNSLayerFromBoardLayer( aTrack->GetLayer() ) );
segment->SetParent( aTrack );
if( aTrack->IsLocked() )
@ -1238,7 +1236,7 @@ std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
aArc->GetEnd(), aArc->GetWidth() ),
aArc->GetNet() );
arc->SetLayers( LAYER_RANGE( aArc->GetLayer() ) );
arc->SetLayer( GetPNSLayerFromBoardLayer( aArc->GetLayer() ) );
arc->SetParent( aArc );
if( aArc->IsLocked() )
@ -1260,7 +1258,7 @@ std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
aVia->LayerPair( &top, &bottom );
auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ),
SetLayersFromPCBNew( aVia->TopLayer(), aVia->BottomLayer() ),
aVia->GetWidth(),
aVia->GetDrillValue(),
aVia->GetNet(),
@ -1311,7 +1309,7 @@ bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_
return false;
}
for( int layer = F_Cu; layer <= B_Cu; layer++ )
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, m_board->GetCopperLayerCount() ) )
{
if( !layers[ layer ] )
continue;
@ -1332,7 +1330,7 @@ bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_
std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
solid->SetLayer( layer );
solid->SetLayer( GetPNSLayerFromBoardLayer( layer ) );
solid->SetNet( nullptr );
solid->SetParent( aZone );
solid->SetShape( triShape );
@ -1356,7 +1354,7 @@ bool PNS_KICAD_IFACE_BASE::syncTextItem( PNS::NODE* aWorld, PCB_TEXT* aText, PCB
std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
solid->SetLayer( aLayer );
solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
solid->SetNet( nullptr );
solid->SetParent( aText );
solid->SetShape( shape ); // takes ownership
@ -1393,12 +1391,12 @@ bool PNS_KICAD_IFACE_BASE::syncGraphicalItem( PNS::NODE* aWorld, PCB_SHAPE* aIte
if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
{
solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
solid->SetLayers( PNS_LAYER_RANGE( 0, m_board->GetCopperLayerCount() ) );
solid->SetRoutable( false );
}
else
{
solid->SetLayer( aItem->GetLayer() );
solid->SetLayer( GetPNSLayerFromBoardLayer( aItem->GetLayer() ) );
}
if( aItem->GetLayer() == Edge_Cuts )
@ -1437,7 +1435,7 @@ void PNS_KICAD_IFACE_BASE::SetBoard( BOARD* aBoard )
}
bool PNS_KICAD_IFACE::IsAnyLayerVisible( const LAYER_RANGE& aLayer ) const
bool PNS_KICAD_IFACE::IsAnyLayerVisible( const PNS_LAYER_RANGE& aLayer ) const
{
if( !m_view )
return false;
@ -1466,14 +1464,14 @@ bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer
{
const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
return via->FlashLayer( ToLAYER_ID( aLayer ) );
return via->FlashLayer( GetPCBLayerIDFromPNSLayer( aLayer ) );
}
case PCB_PAD_T:
{
const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
return pad->FlashLayer( ToLAYER_ID( aLayer ) );
return pad->FlashLayer( GetPCBLayerIDFromPNSLayer( aLayer ) );
}
default:
@ -1486,9 +1484,9 @@ bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer
bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem,
const LAYER_RANGE& aLayer ) const
const PNS_LAYER_RANGE& aLayer ) const
{
LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
PNS_LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
if( aItem->Parent() )
{
@ -1500,7 +1498,7 @@ bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem,
for( int layer = test.Start(); layer <= test.End(); ++layer )
{
if( via->FlashLayer( ToLAYER_ID( layer ) ) )
if( via->FlashLayer( GetPCBLayerIDFromPNSLayer( layer ) ) )
return true;
}
@ -1513,7 +1511,7 @@ bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem,
for( int layer = test.Start(); layer <= test.End(); ++layer )
{
if( pad->FlashLayer( ToLAYER_ID( layer ) ) )
if( pad->FlashLayer( GetPCBLayerIDFromPNSLayer( layer ) ) )
return true;
}
@ -1703,7 +1701,7 @@ void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool
aFlags |= PNS_SEMI_SOLID;
}
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view, aFlags );
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, this, m_view, aFlags );
// Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
static int tracks = PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T | PNS::ITEM::LINE_T;
@ -1743,7 +1741,7 @@ void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool
void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
{
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, m_view );
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, this, m_view );
pitem->SetDepth( pitem->GetOriginDepth() - ROUTER_PREVIEW_ITEM::PathOverlayDepth );
COLOR4D color;
@ -1762,7 +1760,7 @@ void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImpor
void PNS_KICAD_IFACE::DisplayRatline( const SHAPE_LINE_CHAIN& aRatline, PNS::NET_HANDLE aNet )
{
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, m_view );
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, this, m_view );
KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
@ -1910,8 +1908,8 @@ void PNS_KICAD_IFACE::modifyBoardItem( PNS::ITEM* aItem )
via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
via_board->SetIsFree( via->IsFree() );
via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
ToLAYER_ID( via->Layers().End() ) );
via_board->SetLayerPair( GetPCBLayerIDFromPNSLayer( via->Layers().Start() ),
GetPCBLayerIDFromPNSLayer( via->Layers().End() ) );
break;
}
@ -1960,7 +1958,7 @@ BOARD_CONNECTED_ITEM* PNS_KICAD_IFACE::createBoardItem( PNS::ITEM* aItem )
PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape() ) );
new_arc->SetWidth( arc->Width() );
new_arc->SetLayer( ToLAYER_ID( arc->Layers().Start() ) );
new_arc->SetLayer( GetPCBLayerIDFromPNSLayer( arc->Layers().Start() ) );
new_arc->SetNet( net );
newBoardItem = new_arc;
break;
@ -1974,7 +1972,7 @@ BOARD_CONNECTED_ITEM* PNS_KICAD_IFACE::createBoardItem( PNS::ITEM* aItem )
track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
track->SetWidth( seg->Width() );
track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
track->SetLayer( GetPCBLayerIDFromPNSLayer( seg->Layers().Start() ) );
track->SetNet( net );
newBoardItem = track;
break;
@ -1990,8 +1988,8 @@ BOARD_CONNECTED_ITEM* PNS_KICAD_IFACE::createBoardItem( PNS::ITEM* aItem )
via_board->SetNet( net );
via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
via_board->SetIsFree( via->IsFree() );
via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
ToLAYER_ID( via->Layers().End() ) );
via_board->SetLayerPair( GetPCBLayerIDFromPNSLayer( via->Layers().Start() ),
GetPCBLayerIDFromPNSLayer( via->Layers().End() ) );
newBoardItem = via_board;
break;
}
@ -2088,7 +2086,7 @@ void PNS_KICAD_IFACE::SetView( KIGFX::VIEW* aView )
delete m_debugDecorator;
auto dec = new PNS_PCBNEW_DEBUG_DECORATOR();
auto dec = new PNS_PCBNEW_DEBUG_DECORATOR( this );
m_debugDecorator = dec;
dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
@ -2139,3 +2137,52 @@ void PNS_KICAD_IFACE::SetHostTool( PCB_TOOL_BASE* aTool )
m_tool = aTool;
m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
}
int PNS_KICAD_IFACE_BASE::GetBoardLayerFromPNSLayer( int aLayer ) const
{
if( aLayer < 0 )
return -1;
if( aLayer == 0 )
return F_Cu;
if( aLayer == m_board->GetCopperLayerCount() - 1 )
return B_Cu;
return ( aLayer + 1 ) * 2;
}
int PNS_KICAD_IFACE_BASE::GetPNSLayerFromBoardLayer( int aLayer ) const
{
if( aLayer < 0 )
return -1;
if( aLayer == F_Cu )
return 0;
if( aLayer == B_Cu )
return m_board->GetCopperLayerCount() - 1;
return ( aLayer / 2 ) - 1;
}
PCB_LAYER_ID PNS_KICAD_IFACE_BASE::GetPCBLayerIDFromPNSLayer( int aLayer ) const
{
return static_cast<PCB_LAYER_ID>( GetBoardLayerFromPNSLayer( aLayer ) );
}
void PNS_KICAD_IFACE_BASE::SetStartLayerFromPCBNew( PCB_LAYER_ID aLayer )
{
m_startLayer = GetPNSLayerFromBoardLayer( aLayer );
}
PNS_LAYER_RANGE PNS_KICAD_IFACE_BASE::SetLayersFromPCBNew( PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer )
{
return PNS_LAYER_RANGE( GetPNSLayerFromBoardLayer( aStartLayer ),
GetPNSLayerFromBoardLayer( aEndLayer ) );
}

View File

@ -57,9 +57,9 @@ public:
void EraseView() override {};
void SetBoard( BOARD* aBoard );
void SyncWorld( PNS::NODE* aWorld ) override;
bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) const override { return true; };
bool IsAnyLayerVisible( const PNS_LAYER_RANGE& aLayer ) const override { return true; };
bool IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const override;
bool IsFlashedOnLayer( const PNS::ITEM* aItem, const LAYER_RANGE& aLayer ) const override;
bool IsFlashedOnLayer( const PNS::ITEM* aItem, const PNS_LAYER_RANGE& aLayer ) const override;
bool IsItemVisible( const PNS::ITEM* aItem ) const override { return true; };
void HideItem( PNS::ITEM* aItem ) override {}
void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false,
@ -81,7 +81,14 @@ public:
void SetDebugDecorator( PNS::DEBUG_DECORATOR* aDec );
void SetStartLayer( int aLayer ) { m_startLayer = aLayer; }
int GetBoardLayerFromPNSLayer( int aLayer ) const override;
int GetPNSLayerFromBoardLayer( int aLayer ) const override;
PCB_LAYER_ID GetPCBLayerIDFromPNSLayer( int aLayer ) const;
void SetStartLayerFromPCBNew( PCB_LAYER_ID aLayer );
void SetStartLayerFromPNS( int aLayer ) { m_startLayer = aLayer; }
PNS_LAYER_RANGE SetLayersFromPCBNew( PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer );
virtual PNS::NODE* GetWorld() const override { return m_world; };
@ -108,7 +115,7 @@ protected:
protected:
PNS::NODE* m_world;
BOARD* m_board;
int m_startLayer;
int m_startLayer; // The starting layer, in PNS layer coordinates
};
class PNS_KICAD_IFACE : public PNS_KICAD_IFACE_BASE
@ -121,7 +128,7 @@ public:
void SetView( KIGFX::VIEW* aView );
void EraseView() override;
bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) const override;
bool IsAnyLayerVisible( const PNS_LAYER_RANGE& aLayer ) const override;
bool IsItemVisible( const PNS::ITEM* aItem ) const override;
void HideItem( PNS::ITEM* aItem ) override;
void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false,

View File

@ -28,15 +28,15 @@
/**
* Represent a contiguous set of PCB layers.
*/
class LAYER_RANGE
class PNS_LAYER_RANGE
{
public:
LAYER_RANGE() :
PNS_LAYER_RANGE() :
m_start( -1 ),
m_end( -1 )
{};
LAYER_RANGE( int aStart, int aEnd )
PNS_LAYER_RANGE( int aStart, int aEnd )
{
if( aStart > aEnd )
std::swap( aStart, aEnd );
@ -45,26 +45,26 @@ public:
m_end = aEnd;
}
LAYER_RANGE( int aLayer )
PNS_LAYER_RANGE( int aLayer )
{
m_start = m_end = aLayer;
}
LAYER_RANGE( const LAYER_RANGE& aB ) :
PNS_LAYER_RANGE( const PNS_LAYER_RANGE& aB ) :
m_start( aB.m_start ),
m_end( aB.m_end )
{}
~LAYER_RANGE() {};
~PNS_LAYER_RANGE() {};
LAYER_RANGE& operator=( const LAYER_RANGE& aB )
PNS_LAYER_RANGE& operator=( const PNS_LAYER_RANGE& aB )
{
m_start = aB.m_start;
m_end = aB.m_end;
return *this;
}
bool Overlaps( const LAYER_RANGE& aOther ) const
bool Overlaps( const PNS_LAYER_RANGE& aOther ) const
{
return m_end >= aOther.m_start && m_start <= aOther.m_end;
}
@ -89,7 +89,7 @@ public:
return m_end;
}
void Merge( const LAYER_RANGE& aOther )
void Merge( const PNS_LAYER_RANGE& aOther )
{
if( m_start < 0 || m_end < 0 )
{
@ -105,9 +105,9 @@ public:
m_end = aOther.m_end;
}
LAYER_RANGE Intersection( const LAYER_RANGE& aOther ) const
PNS_LAYER_RANGE Intersection( const PNS_LAYER_RANGE& aOther ) const
{
LAYER_RANGE overlap;
PNS_LAYER_RANGE overlap;
overlap.m_start = std::max( m_start, aOther.m_start );
@ -122,17 +122,17 @@ public:
}
///< Shortcut for comparisons/overlap tests
static LAYER_RANGE All()
static PNS_LAYER_RANGE All()
{
return LAYER_RANGE( 0, 256 ); // fixme: use layer IDs header
return PNS_LAYER_RANGE( 0, 256 ); // fixme: use layer IDs header
}
bool operator==( const LAYER_RANGE& aOther ) const
bool operator==( const PNS_LAYER_RANGE& aOther ) const
{
return ( m_start == aOther.m_start ) && ( m_end == aOther.m_end );
}
bool operator!=( const LAYER_RANGE& aOther ) const
bool operator!=( const PNS_LAYER_RANGE& aOther ) const
{
return ( m_start != aOther.m_start ) || ( m_end != aOther.m_end );
}

View File

@ -72,7 +72,7 @@ void LINE_PLACER::setWorld( NODE* aWorld )
const VIA LINE_PLACER::makeVia( const VECTOR2I& aP )
{
const LAYER_RANGE layers( m_sizes.ViaType() == VIATYPE::THROUGH ? F_Cu : m_sizes.GetLayerTop(),
const PNS_LAYER_RANGE layers( m_sizes.ViaType() == VIATYPE::THROUGH ? F_Cu : m_sizes.GetLayerTop(),
m_sizes.ViaType() == VIATYPE::THROUGH ? B_Cu : m_sizes.GetLayerBottom() );
return VIA( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), nullptr, m_sizes.ViaType() );

View File

@ -1249,7 +1249,7 @@ void NODE::LockJoint( const VECTOR2I& aPos, const ITEM* aItem, bool aLock )
}
JOINT& NODE::touchJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HANDLE aNet )
JOINT& NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet )
{
JOINT::HASH_TAG tag;
@ -1310,7 +1310,7 @@ void JOINT::Dump() const
}
void NODE::linkJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HANDLE aNet,
void NODE::linkJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet,
ITEM* aWhere )
{
JOINT& jt = touchJoint( aPos, aLayers, aNet );
@ -1319,7 +1319,7 @@ void NODE::linkJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HAND
}
void NODE::unlinkJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HANDLE aNet,
void NODE::unlinkJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet,
ITEM* aWhere )
{
// fixme: remove dangling joints
@ -1556,7 +1556,7 @@ void NODE::RemoveByMarker( int aMarker )
}
SEGMENT* NODE::findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
SEGMENT* NODE::findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const PNS_LAYER_RANGE& lr,
NET_HANDLE aNet )
{
const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
@ -1591,7 +1591,7 @@ SEGMENT* NODE::findRedundantSegment( SEGMENT* aSeg )
}
ARC* NODE::findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
ARC* NODE::findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const PNS_LAYER_RANGE& lr,
NET_HANDLE aNet )
{
const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
@ -1626,7 +1626,7 @@ ARC* NODE::findRedundantArc( ARC* aArc )
}
int NODE::QueryJoints( const BOX2I& aBox, std::vector<JOINT*>& aJoints, LAYER_RANGE aLayerMask,
int NODE::QueryJoints( const BOX2I& aBox, std::vector<JOINT*>& aJoints, PNS_LAYER_RANGE aLayerMask,
int aKindMask )
{
int n = 0;

View File

@ -272,7 +272,7 @@ public:
const COLLISION_SEARCH_OPTIONS& aOpts = COLLISION_SEARCH_OPTIONS() ) const;
int QueryJoints( const BOX2I& aBox, std::vector<JOINT*>& aJoints,
LAYER_RANGE aLayerMask = LAYER_RANGE::All(), int aKindMask = ITEM::ANY_T );
PNS_LAYER_RANGE aLayerMask = PNS_LAYER_RANGE::All(), int aKindMask = ITEM::ANY_T );
/**
* Follow the line in search of an obstacle that is nearest to the starting to the line's
@ -482,14 +482,14 @@ private:
NODE& operator=( const NODE& aB );
///< Try to find matching joint and creates a new one if not found.
JOINT& touchJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HANDLE aNet );
JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet );
///< Touch a joint and links it to an m_item.
void linkJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HANDLE aNet,
void linkJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet,
ITEM* aWhere );
///< Unlink an item from a joint.
void unlinkJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, NET_HANDLE aNet,
void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet,
ITEM* aWhere );
///< Helpers for adding/removing items.
@ -515,11 +515,11 @@ private:
return m_parent == nullptr;
}
SEGMENT* findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
SEGMENT* findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const PNS_LAYER_RANGE& lr,
NET_HANDLE aNet );
SEGMENT* findRedundantSegment( SEGMENT* aSeg );
ARC* findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
ARC* findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const PNS_LAYER_RANGE& lr,
NET_HANDLE aNet );
ARC* findRedundantArc( ARC* aSeg );

View File

@ -134,7 +134,7 @@ const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP, int aSlopRadius )
COLLISION_SEARCH_OPTIONS opts;
test.SetWidth( 1 );
test.SetLayers( LAYER_RANGE::All() );
test.SetLayers( PNS_LAYER_RANGE::All() );
opts.m_differentNetsOnly = false;
opts.m_overrideClearance = aSlopRadius;
@ -474,7 +474,7 @@ bool ROUTER::Move( const VECTOR2I& aP, ITEM* endItem )
}
bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEndLayers,
bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, PNS_LAYER_RANGE& aOtherEndLayers,
ITEM*& aOtherEndItem )
{
// Can't finish something with no connections
@ -542,7 +542,7 @@ bool ROUTER::Finish()
// Get our current line and position and nearest ratsnest to them if it exists
VECTOR2I otherEnd;
LAYER_RANGE otherEndLayers;
PNS_LAYER_RANGE otherEndLayers;
ITEM* otherEndItem = nullptr;
// Get the anchor nearest to the end of the trace the user is routing
@ -588,7 +588,7 @@ bool ROUTER::ContinueFromEnd( ITEM** aNewStartItem )
int currentLayer = GetCurrentLayer();
VECTOR2I currentEnd = placer->CurrentEnd();
VECTOR2I otherEnd;
LAYER_RANGE otherEndLayers;
PNS_LAYER_RANGE otherEndLayers;
ITEM* otherEndItem = nullptr;
// Get the anchor nearest to the end of the trace the user is routing

View File

@ -93,10 +93,10 @@ enum DRAG_MODE
virtual void AddItem( ITEM* aItem ) = 0;
virtual void UpdateItem( ITEM* aItem ) = 0;
virtual void RemoveItem( ITEM* aItem ) = 0;
virtual bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) const = 0;
virtual bool IsAnyLayerVisible( const PNS_LAYER_RANGE& aLayer ) const = 0;
virtual bool IsItemVisible( const PNS::ITEM* aItem ) const = 0;
virtual bool IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const = 0;
virtual bool IsFlashedOnLayer( const PNS::ITEM* aItem, const LAYER_RANGE& aLayer ) const = 0;
virtual bool IsFlashedOnLayer( const PNS::ITEM* aItem, const PNS_LAYER_RANGE& aLayer ) const = 0;
virtual void DisplayItem( const ITEM* aItem, int aClearance, bool aEdit = false,
int aFlags = 0 ) = 0;
virtual void DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance ) = 0;
@ -115,6 +115,9 @@ enum DRAG_MODE
virtual RULE_RESOLVER* GetRuleResolver() = 0;
virtual DEBUG_DECORATOR* GetDebugDecorator() = 0;
virtual int GetBoardLayerFromPNSLayer( int aLayer ) const = 0;
virtual int GetPNSLayerFromBoardLayer( int aLayer ) const = 0;
};
class ROUTER
@ -232,7 +235,7 @@ private:
void markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved );
bool isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aItem, int aLayer );
bool getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEndLayers,
bool getNearestRatnestAnchor( VECTOR2I& aOtherEnd, PNS_LAYER_RANGE& aOtherEndLayers,
ITEM*& aOtherEndItem );

View File

@ -95,7 +95,7 @@ const TOPOLOGY::JOINT_SET TOPOLOGY::ConnectedJoints( const JOINT* aStart )
bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint,
LAYER_RANGE& aLayers, ITEM*& aItem )
PNS_LAYER_RANGE& aLayers, ITEM*& aItem )
{
LINE track( *aTrack );
VECTOR2I end;
@ -142,7 +142,7 @@ bool TOPOLOGY::LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine )
{
VECTOR2I end;
// Ratline doesn't care about the layer
LAYER_RANGE layers;
PNS_LAYER_RANGE layers;
ITEM* unusedItem;
if( !NearestUnconnectedAnchorPoint( aTrack, end, layers, unusedItem ) )

View File

@ -50,7 +50,7 @@ public:
ITEM* NearestUnconnectedItem( const JOINT* aStart, int* aAnchor = nullptr,
int aKindMask = ITEM::ANY_T );
bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, LAYER_RANGE& aLayers,
bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, PNS_LAYER_RANGE& aLayers,
ITEM*& aItem );
bool LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine );

View File

@ -43,7 +43,7 @@ struct VIA_HANDLE
{
bool valid = false;
VECTOR2I pos;
LAYER_RANGE layers;
PNS_LAYER_RANGE layers;
NET_HANDLE net = nullptr;
};
@ -62,7 +62,7 @@ public:
SetHole( HOLE::MakeCircularHole( m_pos, m_drill / 2 ) );
}
VIA( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, int aDiameter, int aDrill,
VIA( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, int aDiameter, int aDrill,
NET_HANDLE aNet = nullptr, VIATYPE aViaType = VIATYPE::THROUGH ) :
LINKED_ITEM( VIA_T ),
m_hole( nullptr )
@ -218,7 +218,7 @@ class VVIA : public VIA
{
public:
VVIA( const VECTOR2I& aPos, int aLayer, int aDiameter, NET_HANDLE aNet ) :
VIA( aPos, LAYER_RANGE( aLayer, aLayer ), aDiameter, aDiameter / 2, aNet )
VIA( aPos, PNS_LAYER_RANGE( aLayer, aLayer ), aDiameter, aDiameter / 2, aNet )
{
m_isVirtual = true;
}

View File

@ -34,12 +34,15 @@
#include "pns_line.h"
#include "pns_segment.h"
#include "pns_via.h"
#include "pns_kicad_iface.h"
using namespace KIGFX;
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* aView, int aFlags ) :
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, PNS::ROUTER_IFACE* aIface,
KIGFX::VIEW* aView, int aFlags ) :
EDA_ITEM( NOT_USED ),
m_iface( aIface ),
m_view( aView ),
m_shape( nullptr ),
m_hole( nullptr ),
@ -76,12 +79,13 @@ ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* a
}
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aView ) :
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const SHAPE& aShape, PNS::ROUTER_IFACE* aIface,
KIGFX::VIEW* aView ) :
EDA_ITEM( NOT_USED ),
m_iface( aIface ),
m_view( aView ),
m_flags( 0 )
{
m_view = aView;
m_shape = aShape.Clone();
m_hole = nullptr;
@ -106,7 +110,7 @@ ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM()
void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
{
m_originLayer = aItem->Layers().Start();
m_originLayer = m_iface->GetBoardLayerFromPNSLayer( aItem->Layers().Start() );
if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( aItem ) )
{
@ -119,7 +123,8 @@ void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
return;
}
assert( m_originLayer >= 0 );
if( m_originLayer < 0 )
m_originLayer = 0;
m_layer = m_originLayer;
m_color = getLayerColor( m_originLayer );

View File

@ -42,6 +42,7 @@ namespace PNS {
class ITEM;
class ROUTER;
class ROUTER_IFACE;
}
@ -75,8 +76,8 @@ public:
static constexpr double LayerDepthFactor = 0.0001;
static constexpr double PathOverlayDepth = LayerDepthFactor * static_cast<double>( LAYER_ZONE_END );
ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aView = nullptr );
ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem = nullptr, KIGFX::VIEW* aView = nullptr,
ROUTER_PREVIEW_ITEM( const SHAPE& aShape, PNS::ROUTER_IFACE* aIface, KIGFX::VIEW* aView );
ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, PNS::ROUTER_IFACE* aIface, KIGFX::VIEW* aView,
int aFlags = 0 );
~ROUTER_PREVIEW_ITEM();
@ -123,6 +124,8 @@ private:
private:
KIGFX::VIEW* m_view;
PNS::ROUTER_IFACE* m_iface;
SHAPE* m_shape;
SHAPE* m_hole;

View File

@ -688,7 +688,7 @@ int ROUTER_TOOL::getStartLayer( const PNS::ITEM* aItem )
if( m_startItem )
{
const LAYER_RANGE& ls = m_startItem->Layers();
const PNS_LAYER_RANGE& ls = m_startItem->Layers();
if( ls.Overlaps( tl ) )
return tl;
@ -702,7 +702,7 @@ int ROUTER_TOOL::getStartLayer( const PNS::ITEM* aItem )
void ROUTER_TOOL::switchLayerOnViaPlacement()
{
int activeLayer = frame()->GetActiveLayer();
int activeLayer = m_iface->GetPNSLayerFromBoardLayer( frame()->GetActiveLayer() );
int currentLayer = m_router->GetCurrentLayer();
if( currentLayer != activeLayer )
@ -721,7 +721,8 @@ void ROUTER_TOOL::switchLayerOnViaPlacement()
}
void ROUTER_TOOL::updateSizesAfterRouterEvent( PCB_LAYER_ID targetLayer, const VECTOR2I& aPos )
// N.B. aTargetLayer is a PNS layer, not a PCB_LAYER_ID
void ROUTER_TOOL::updateSizesAfterRouterEvent( int aTargetLayer, const VECTOR2I& aPos )
{
std::vector<PNS::NET_HANDLE> nets = m_router->GetCurrentNets();
@ -729,6 +730,7 @@ void ROUTER_TOOL::updateSizesAfterRouterEvent( PCB_LAYER_ID targetLayer, const V
BOARD_DESIGN_SETTINGS& bds = board()->GetDesignSettings();
std::shared_ptr<DRC_ENGINE>& drcEngine = bds.m_DRCEngine;
DRC_CONSTRAINT constraint;
PCB_LAYER_ID targetLayer = m_iface->GetPCBLayerIDFromPNSLayer( aTargetLayer );
PCB_TRACK dummyTrack( board() );
dummyTrack.SetFlags( ROUTER_TRANSIENT );
@ -875,20 +877,23 @@ int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
BOARD* brd = board();
LSET enabledLayers = LSET::AllCuMask( brd->GetDesignSettings().GetCopperLayerCount() );
LSEQ layers = enabledLayers.Seq();
PCB_LAYER_ID currentLayer = (PCB_LAYER_ID) m_router->GetCurrentLayer();
PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
// These layers are in Board Layer order not PNS layer order
PCB_LAYER_ID currentLayer = m_iface->GetPCBLayerIDFromPNSLayer( m_router->GetCurrentLayer() );
PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
if( aEvent.IsAction( &PCB_ACTIONS::layerNext ) )
{
if( m_lastTargetLayer == UNDEFINED_LAYER )
m_lastTargetLayer = currentLayer;
m_lastTargetLayer = m_iface->GetPNSLayerFromBoardLayer( currentLayer );
size_t idx = 0;
size_t target_idx = 0;
PCB_LAYER_ID lastTargetLayer = m_iface->GetPCBLayerIDFromPNSLayer( m_lastTargetLayer );
for( size_t i = 0; i < layers.size(); i++ )
{
if( layers[i] == m_lastTargetLayer )
if( layers[i] == lastTargetLayer )
{
idx = i;
break;
@ -926,10 +931,11 @@ int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
size_t idx = 0;
size_t target_idx = 0;
PCB_LAYER_ID lastTargetLayer = m_iface->GetPCBLayerIDFromPNSLayer( m_lastTargetLayer );
for( size_t i = 0; i < layers.size(); i++ )
{
if( layers[i] == m_lastTargetLayer )
if( layers[i] == lastTargetLayer )
{
idx = i;
break;
@ -977,7 +983,7 @@ int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
if( targetLayer != UNDEFINED_LAYER )
{
m_lastTargetLayer = targetLayer;
m_lastTargetLayer = m_iface->GetPNSLayerFromBoardLayer( targetLayer );
if( targetLayer == currentLayer )
return 0;
@ -1121,14 +1127,15 @@ int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
}
sizes.SetViaType( viaType );
sizes.AddLayerPair( currentLayer, targetLayer );
sizes.AddLayerPair( m_iface->GetPNSLayerFromBoardLayer( currentLayer ),
m_iface->GetPNSLayerFromBoardLayer( targetLayer ) );
m_router->UpdateSizes( sizes );
if( !m_router->IsPlacingVia() )
m_router->ToggleViaPlacement();
m_lastTargetLayer = targetLayer;
m_lastTargetLayer = m_iface->GetPNSLayerFromBoardLayer( targetLayer );
if( m_router->RoutingInProgress() )
{
@ -1166,12 +1173,12 @@ bool ROUTER_TOOL::prepareInteractive( VECTOR2D aStartPosition )
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
m_iface->SetStartLayer( routingLayer );
m_iface->SetStartLayerFromPNS( routingLayer );
frame()->GetBoard()->GetDesignSettings().m_TempOverrideTrackWidth = false;
m_iface->ImportSizes( sizes, m_startItem, nullptr, aStartPosition );
sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
frame()->GetScreen()->m_Route_Layer_BOTTOM );
sizes.AddLayerPair( m_iface->GetPNSLayerFromBoardLayer( frame()->GetScreen()->m_Route_Layer_TOP ),
m_iface->GetPNSLayerFromBoardLayer( frame()->GetScreen()->m_Route_Layer_BOTTOM ) );
m_router->UpdateSizes( sizes );
@ -1225,7 +1232,7 @@ bool ROUTER_TOOL::finishInteractive()
m_startItem = nullptr;
m_endItem = nullptr;
frame()->SetActiveLayer( m_originalActiveLayer );
frame()->SetActiveLayer( m_iface->GetPCBLayerIDFromPNSLayer( m_originalActiveLayer ) );
UpdateMessagePanel();
frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
controls()->SetAutoPan( false );

View File

@ -79,7 +79,7 @@ private:
int getStartLayer( const PNS::ITEM* aItem );
void switchLayerOnViaPlacement();
void updateSizesAfterRouterEvent( PCB_LAYER_ID targetLayer, const VECTOR2I& aPos );
void updateSizesAfterRouterEvent( int targetLayer, const VECTOR2I& aPos );
int onLayerCommand( const TOOL_EVENT& aEvent );
int onViaCommand( const TOOL_EVENT& aEvent );
@ -94,7 +94,7 @@ private:
std::shared_ptr<ACTION_MENU> m_trackViaMenu;
int m_lastTargetLayer;
PCB_LAYER_ID m_originalActiveLayer;
int m_originalActiveLayer;
bool m_inRouterTool; // Re-entrancy guard
};

View File

@ -443,7 +443,7 @@ public:
{
}
void SetLayerId( const char* aLayerId )
void SetLayerId( std::string& aLayerId )
{
layer_id = aLayerId;
}
@ -596,7 +596,7 @@ public:
POINTS& GetPoints() {return points; }
void SetLayerId( const char* aLayerId )
void SetLayerId( const std::string& aLayerId )
{
layer_id = aLayerId;
}
@ -753,7 +753,7 @@ public:
out->Print( 0, ")%s", newline );
}
void SetLayerId( const char* aLayerId )
void SetLayerId( const std::string& aLayerId )
{
layer_id = aLayerId;
}
@ -801,7 +801,7 @@ public:
out->Print( 0, ")%s", newline );
}
void SetLayerId( const char* aLayerId )
void SetLayerId( std::string& aLayerId )
{
layer_id = aLayerId;
}

View File

@ -225,7 +225,7 @@ static PATH* makePath( const POINT& aStart, const POINT& aEnd, const std::string
path->AppendPoint( aStart );
path->AppendPoint( aEnd );
path->SetLayerId( aLayerName.c_str() );
path->SetLayerId( aLayerName );
return path;
}
@ -245,27 +245,25 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, PAD* aPad )
PADSTACK* padstack = new PADSTACK();
int reportedLayers = 0; // how many in reported padstack
const char* layerName[MAX_CU_LAYERS];
uniqifier = '[';
static const LSET all_cu = LSET::AllCuMask();
const int copperCount = aBoard->GetCopperLayerCount();
static const LSET all_cu = LSET::AllCuMask( copperCount );
int reportedLayers = 0;
std::vector<std::string> layerName( copperCount );
bool onAllCopperLayers = ( (aPad->GetLayerSet() & all_cu) == all_cu );
if( onAllCopperLayers )
uniqifier += 'A'; // A for all layers
const int copperCount = aBoard->GetCopperLayerCount();
for( int layer=0; layer<copperCount; ++layer )
{
PCB_LAYER_ID kilayer = m_pcbLayer2kicad[layer];
if( onAllCopperLayers || aPad->IsOnLayer( kilayer ) )
{
layerName[reportedLayers++] = m_layerIds[layer].c_str();
layerName[reportedLayers++] = m_layerIds[layer];
if( !onAllCopperLayers )
{
@ -640,7 +638,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, FOOTPRINT* aFootprint )
circle->SetDiameter( diameter );
circle->SetVertex( vertex );
circle->SetLayerId( m_layerIds[layer].c_str() );
circle->SetLayerId( m_layerIds[layer] );
}
}
else // else if() could there be a square keepout here?
@ -998,7 +996,7 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter,
shape->SetShape( circle );
circle->SetDiameter( dsnDiameter );
circle->SetLayerId( m_layerIds[layer].c_str() );
circle->SetLayerId( m_layerIds[layer] );
}
snprintf( name, sizeof( name ), "Via[%d-%d]_%.6g:%.6g_um",

View File

@ -698,7 +698,7 @@ int DRAWING_TOOL::PlaceCharacteristics( const TOOL_EVENT& aEvent )
PCB_LAYER_ID layer = m_frame->GetActiveLayer();
if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
if( ( layerSet & LSET( { layer } ) ).count() ) // if layer is a forbidden layer
m_frame->SetActiveLayer( Cmts_User );
std::vector<BOARD_ITEM*> table = DrawBoardCharacteristics( { 0, 0 }, m_frame->GetActiveLayer(),
@ -761,7 +761,7 @@ int DRAWING_TOOL::PlaceStackup( const TOOL_EVENT& aEvent )
PCB_LAYER_ID layer = m_frame->GetActiveLayer();
PCB_LAYER_ID savedLayer = layer;
if( ( layerSet & LSET( layer ) ).count() ) // if layer is a forbidden layer
if( ( layerSet & LSET( { layer } ) ).count() ) // if layer is a forbidden layer
{
m_frame->SetActiveLayer( Cmts_User );
layer = Cmts_User;

View File

@ -621,10 +621,10 @@ int DRAWING_TOOL::PlaceReferenceImage( const TOOL_EVENT& aEvent )
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
cursorPos =
GetClampedCoords( grid.BestSnapAnchor( m_controls->GetMousePosition(),
m_frame->GetActiveLayer(), GRID_GRAPHICS ),
COORDS_PADDING );
cursorPos = GetClampedCoords( grid.BestSnapAnchor( m_controls->GetMousePosition(),
{ m_frame->GetActiveLayer() },
GRID_GRAPHICS ),
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
@ -858,7 +858,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
VECTOR2I cursorPos =
GetClampedCoords( grid.BestSnapAnchor( m_controls->GetMousePosition(),
m_frame->GetActiveLayer(), GRID_TEXT ),
{ m_frame->GetActiveLayer() }, GRID_TEXT ),
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
@ -1095,7 +1095,7 @@ int DRAWING_TOOL::DrawTable( const TOOL_EVENT& aEvent )
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
VECTOR2I cursorPos =
GetClampedCoords( grid.BestSnapAnchor( m_controls->GetMousePosition(),
m_frame->GetActiveLayer(), GRID_TEXT ),
{ m_frame->GetActiveLayer() }, GRID_TEXT ),
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
@ -1865,7 +1865,7 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
cursorPos = GetClampedCoords(
grid.BestSnapAnchor( m_controls->GetMousePosition(), layer, GRID_GRAPHICS ),
grid.BestSnapAnchor( m_controls->GetMousePosition(), { layer }, GRID_GRAPHICS ),
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
@ -2141,7 +2141,7 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
cursorPos = GetClampedCoords(
grid.BestSnapAnchor( m_controls->GetMousePosition(), m_layer, GRID_GRAPHICS ),
grid.BestSnapAnchor( m_controls->GetMousePosition(), { m_layer }, GRID_GRAPHICS ),
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
@ -2857,7 +2857,7 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
{
setCursor();
LSET layers( m_frame->GetActiveLayer() );
LSET layers( { m_frame->GetActiveLayer() } );
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );

View File

@ -424,7 +424,7 @@ bool EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, BOARD_COMMIT* aCommit
VECTOR2D bboxMovement;
BOX2I originalBBox;
bool updateBBox = true;
LSET layers( editFrame->GetActiveLayer() );
LSET layers( { editFrame->GetActiveLayer() } );
PCB_GRID_HELPER grid( m_toolMgr, editFrame->GetMagneticItemsSettings() );
TOOL_EVENT copy = aEvent;
TOOL_EVENT* evt = &copy;

View File

@ -1186,7 +1186,7 @@ PCB_GRID_HELPER::ANCHOR* PCB_GRID_HELPER::nearestAnchor( const VECTOR2I& aPos, i
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( a.item );
if( !m_magneticSettings->allLayers && ( ( aMatchLayers & item->GetLayerSet() ) == 0 ) )
if( !m_magneticSettings->allLayers && ( ( aMatchLayers & item->GetLayerSet() ).none() ) )
continue;
if( ( aFlags & a.flags ) != aFlags )

View File

@ -1908,7 +1908,7 @@ void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
break;
case ID_HIDE_ALL_BUT_ACTIVE:
preset.layers = presetNoLayers.layers | LSET( current );
preset.layers = presetNoLayers.layers | LSET( { current } );
ApplyLayerPreset( preset );
break;

View File

@ -107,9 +107,9 @@ PCB_NET_INSPECTOR_PANEL::~PCB_NET_INSPECTOR_PANEL()
/*****************************************************************************************
*
*
* Grid / model columns configuration
*
*
* ***************************************************************************************/
@ -385,9 +385,9 @@ wxDataViewColumn* PCB_NET_INSPECTOR_PANEL::getDisplayedColumnForModelField( int
/*****************************************************************************************
*
*
* Nets list generation
*
*
* ***************************************************************************************/
@ -633,6 +633,7 @@ PCB_NET_INSPECTOR_PANEL::buildNewItem( NETINFO_ITEM* aNet, unsigned int aPadCoun
std::unique_ptr<LIST_ITEM> new_item = std::make_unique<LIST_ITEM>( aNet );
new_item->SetPadCount( aPadCount );
new_item->SetLayerCount( m_brd->GetCopperLayerCount() );
const auto cn_items = std::equal_range( aCNItems.begin(), aCNItems.end(), aNet->GetNetCode(),
NETCODE_CMP_LESS() );
@ -647,8 +648,7 @@ PCB_NET_INSPECTOR_PANEL::buildNewItem( NETINFO_ITEM* aNet, unsigned int aPadCoun
}
else if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
{
new_item->AddLayerWireLength( track->GetLength(),
static_cast<int>( track->GetLayer() ) );
new_item->AddLayerWireLength( track->GetLength(), track->GetLayer() );
if( item->Type() == PCB_VIA_T )
{
@ -789,10 +789,7 @@ void PCB_NET_INSPECTOR_PANEL::updateNet( NETINFO_ITEM* aNet )
// update fields only
cur_list_item->SetPadCount( new_list_item->GetPadCount() );
cur_list_item->SetViaCount( new_list_item->GetViaCount() );
for( size_t ii = 0; ii < MAX_CU_LAYERS; ++ii )
cur_list_item->SetLayerWireLength( new_list_item->GetLayerWireLength( ii ), ii );
cur_list_item->SetLayerWireLength( new_list_item->GetLayerWireLength() );
cur_list_item->SetPadDieLength( new_list_item->GetPadDieLength() );
updateDisplayedRowValues( cur_net_row );
@ -801,9 +798,9 @@ void PCB_NET_INSPECTOR_PANEL::updateNet( NETINFO_ITEM* aNet )
/*****************************************************************************************
*
*
* Formatting helpers
*
*
* ***************************************************************************************/
@ -852,9 +849,9 @@ void PCB_NET_INSPECTOR_PANEL::updateDisplayedRowValues( const std::optional<LIST
/*****************************************************************************************
*
*
* BOARD_LISTENER event handling
*
*
* ***************************************************************************************/
@ -893,6 +890,7 @@ void PCB_NET_INSPECTOR_PANEL::OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* aBoar
// the new net could have some pads already assigned, count them.
new_item->SetPadCount( m_brd->GetNodesCount( net->GetNetCode() ) );
new_item->SetLayerCount( m_brd->GetCopperLayerCount() );
m_data_model->addItem( std::move( new_item ) );
}
@ -909,7 +907,7 @@ void PCB_NET_INSPECTOR_PANEL::OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* aBoar
const std::unique_ptr<LIST_ITEM>& list_item = *r.value();
int len = track->GetLength();
list_item->AddLayerWireLength( len, static_cast<int>( track->GetLayer() ) );
list_item->AddLayerWireLength( len, track->GetLayer() );
if( track->Type() == PCB_VIA_T )
{
@ -949,6 +947,7 @@ void PCB_NET_INSPECTOR_PANEL::OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* aBoar
list_item->AddPadCount( 1 );
list_item->AddPadDieLength( len );
list_item->SetLayerCount( m_brd->GetCopperLayerCount() );
if( list_item->GetPadCount() == 0 && !m_show_zero_pad_nets )
m_data_model->deleteItem( r );
@ -1024,7 +1023,7 @@ void PCB_NET_INSPECTOR_PANEL::OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM* aBo
const std::unique_ptr<LIST_ITEM>& list_item = *r.value();
int len = track->GetLength();
list_item->SubLayerWireLength( len, static_cast<int>( track->GetLayer() ) );
list_item->SubLayerWireLength( len, track->GetLayer() );
if( track->Type() == PCB_VIA_T )
{
@ -1143,9 +1142,9 @@ void PCB_NET_INSPECTOR_PANEL::OnBoardHighlightNetChanged( BOARD& aBoard )
/*****************************************************************************************
*
*
* UI-generated event handling
*
*
* ***************************************************************************************/
void PCB_NET_INSPECTOR_PANEL::OnShowPanel()
@ -1881,9 +1880,9 @@ void PCB_NET_INSPECTOR_PANEL::onDeleteSelectedNet()
}
/*****************************************************************************************
*
*
* Application-generated event handling
*
*
* ***************************************************************************************/
@ -1903,9 +1902,9 @@ void PCB_NET_INSPECTOR_PANEL::onUnitsChanged( wxCommandEvent& event )
/*****************************************************************************************
*
*
* Settings persistence
*
*
* ***************************************************************************************/

View File

@ -25,7 +25,7 @@
/**
* Primary data item for entries in the Net Inspector list.
*
*
* This class tracks all data for a given net entry in the net inspector list.
*/
class PCB_NET_INSPECTOR_PANEL::LIST_ITEM
@ -44,7 +44,7 @@ public:
m_net_name( aGroupName )
{
m_group_name = aGroupName;
m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + MAX_CU_LAYERS, 0 );
m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + 2, 0 ); // 2 for default layer count
}
LIST_ITEM( NETINFO_ITEM* aNet ) :
@ -54,10 +54,10 @@ public:
wxASSERT( aNet );
m_net_name = UnescapeString( aNet->GetNetname() );
m_net_class = UnescapeString( aNet->GetNetClass()->GetName() );
m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + MAX_CU_LAYERS, 0 );
m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + 2, 0 );
}
LIST_ITEM() { m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + MAX_CU_LAYERS, 0 ); }
LIST_ITEM() { m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + 2, 0 ); }
LIST_ITEM& operator=( const LIST_ITEM& ) = delete;
@ -70,6 +70,11 @@ public:
auto ChildrenEnd() const { return m_children.end(); }
unsigned int ChildrenCount() const { return m_children.size(); }
void SetLayerCount( unsigned int aValue )
{
m_column_changed.resize( COLUMN_LAST_STATIC_COL + 1 + aValue, 0 );
}
NETINFO_ITEM* GetNet() const { return m_net; }
int GetNetCode() const
@ -182,37 +187,46 @@ public:
{
uint64_t retval = 0;
for( uint64_t val : m_layer_wire_length )
retval += val;
for( auto& [layer, length] : m_layer_wire_length )
retval += length;
return retval;
}
uint64_t GetLayerWireLength( size_t aLayer ) const
uint64_t GetLayerWireLength( PCB_LAYER_ID aLayer ) const
{
wxCHECK_MSG( aLayer < m_layer_wire_length.size(), 0, wxT( "Invalid layer specified" ) );
return m_layer_wire_length[aLayer];
auto it = m_layer_wire_length.find( aLayer );
return it != m_layer_wire_length.end() ? it->second : 0;
}
bool BoardWireLengthChanged() const { return m_column_changed[COLUMN_BOARD_LENGTH]; }
void SetLayerWireLength( const uint64_t aValue, size_t aLayer )
void SetLayerWireLength( const uint64_t aValue, PCB_LAYER_ID aLayer )
{
wxCHECK_RET( aLayer < m_layer_wire_length.size(), wxT( "Invalid layer specified" ) );
auto it = m_layer_wire_length.find( aLayer );
wxCHECK_RET( it != m_layer_wire_length.end(), wxT( "Invalid layer specified" ) );
auto& [_, length] = *it;
if( m_parent )
{
m_parent->SetLayerWireLength( m_parent->GetBoardWireLength()
- m_layer_wire_length[aLayer] + aValue,
aLayer );
m_parent->SetLayerWireLength( m_parent->GetBoardWireLength() - length + aValue,
aLayer );
}
m_column_changed[COLUMN_BOARD_LENGTH] |= ( m_layer_wire_length[aLayer] != aValue );
m_layer_wire_length[aLayer] = aValue;
m_column_changed[COLUMN_BOARD_LENGTH] |= ( length != aValue );
length = aValue;
}
void AddLayerWireLength( const uint64_t aValue, size_t aLayer )
std::map<PCB_LAYER_ID, uint64_t> GetLayerWireLength() const { return m_layer_wire_length; }
void SetLayerWireLength( const std::map<PCB_LAYER_ID, uint64_t>& aValue )
{
m_layer_wire_length = aValue;
}
void AddLayerWireLength( const uint64_t aValue, PCB_LAYER_ID aLayer )
{
if( m_parent )
m_parent->AddLayerWireLength( aValue, aLayer );
@ -221,7 +235,7 @@ public:
m_layer_wire_length[aLayer] += aValue;
}
void SubLayerWireLength( const uint64_t aValue, size_t aLayer )
void SubLayerWireLength( const uint64_t aValue, PCB_LAYER_ID aLayer )
{
if( m_parent )
m_parent->SubLayerWireLength( aValue, aLayer );
@ -285,8 +299,8 @@ public:
m_parent->SubViaCount( GetViaCount() );
m_parent->SubViaLength( GetViaLength() );
for( size_t ii = 0; ii < m_layer_wire_length.size(); ++ii )
m_parent->SubLayerWireLength( m_layer_wire_length[ii], ii );
for( auto& [layer, length] : m_layer_wire_length )
m_parent->SubLayerWireLength( length, layer );
m_parent->SubPadDieLength( GetPadDieLength() );
@ -302,8 +316,8 @@ public:
m_parent->AddViaCount( GetViaCount() );
m_parent->AddViaLength( GetViaLength() );
for( size_t ii = 0; ii < m_layer_wire_length.size(); ++ii )
m_parent->AddLayerWireLength( m_layer_wire_length[ii], ii );
for( auto& [layer, length] : m_layer_wire_length )
m_parent->AddLayerWireLength( length, layer );
m_parent->AddPadDieLength( GetPadDieLength() );
@ -323,7 +337,7 @@ private:
uint64_t m_via_length = 0;
uint64_t m_pad_die_length = 0;
std::array<uint64_t, MAX_CU_LAYERS> m_layer_wire_length{};
std::map<PCB_LAYER_ID, uint64_t> m_layer_wire_length{};
// Dirty bits to record when some attribute has changed, in order to avoid unnecessary sort
// operations.
@ -577,7 +591,7 @@ public:
/**
* Adds all custom group-by entries to the items table
*
*
* Note this assumes that m_items is empty prior to adding these groups
*/
void addCustomGroups()
@ -590,6 +604,7 @@ public:
std::unique_ptr<LIST_ITEM>& group = m_items.emplace_back( std::make_unique<LIST_ITEM>(
groupId, rule->GetPattern(), LIST_ITEM::GROUP_TYPE::USER_DEFINED ) );
m_custom_group_map[ rule->GetPattern() ] = group.get();
group->SetLayerCount( m_parent.m_brd->GetCopperLayerCount() );
ItemAdded( wxDataViewItem( group->Parent() ), wxDataViewItem( group.get() ) );
++groupId;
}

View File

@ -278,7 +278,7 @@ bool ZONE::IsOnCopperLayer() const
void ZONE::SetLayer( PCB_LAYER_ID aLayer )
{
SetLayerSet( LSET( aLayer ) );
SetLayerSet( LSET( { aLayer } ) );
}

View File

@ -3,14 +3,17 @@
"3dviewports": [],
"design_settings": {
"defaults": {
"board_outline_line_width": 0.049999999999999996,
"copper_line_width": 0.19999999999999998,
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.05,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"courtyard_line_width": 0.05,
"dimension_precision": 1,
"dimension_units": 0,
"dimensions": {
@ -21,13 +24,13 @@
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_line_width": 0.1,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
@ -73,9 +76,12 @@
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"hole_to_hole": "warning",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
@ -122,15 +128,15 @@
"min_copper_edge_clearance": 0.01,
"min_hole_clearance": 0.0,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.7999999999999999,
"min_text_height": 0.8,
"min_text_thickness": 0.12,
"min_through_hole_diameter": 0.39999999999999997,
"min_through_hole_diameter": 0.4,
"min_track_width": 0.19812,
"min_via_annular_width": 0.049999999999999996,
"min_via_annular_width": 0.05,
"min_via_diameter": 0.5,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
@ -183,6 +189,32 @@
0.3,
0.4
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
@ -192,6 +224,13 @@
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},

View File

@ -3,14 +3,17 @@
"3dviewports": [],
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.1,
"copper_line_width": 0.3,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.30479999999999996,
"copper_text_thickness": 0.3048,
"copper_text_upright": true,
"courtyard_line_width": 0.049999999999999996,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
@ -21,13 +24,13 @@
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_line_width": 0.1,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
@ -73,9 +76,12 @@
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"hole_to_hole": "warning",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
@ -118,7 +124,7 @@
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.20099999999999998,
"min_connection": 0.201,
"min_copper_edge_clearance": 0.01,
"min_hole_clearance": 0.0,
"min_hole_to_hole": 0.25,
@ -126,11 +132,11 @@
"min_microvia_drill": 0.127,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.7999999999999999,
"min_text_height": 0.8,
"min_text_thickness": 0.12,
"min_through_hole_diameter": 0.508,
"min_track_width": 0.2032,
"min_via_annular_width": 0.049999999999999996,
"min_via_annular_width": 0.05,
"min_via_diameter": 0.889,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
@ -183,6 +189,32 @@
0.4,
1.0
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
@ -192,6 +224,13 @@
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},

View File

@ -44,6 +44,7 @@ set( QA_COMMON_SRCS
test_kicad_stroke_font.cpp
test_kiid.cpp
test_layer_ids.cpp
test_layer_range.cpp
test_lset.cpp
test_property.cpp
test_refdes_utils.cpp

View File

@ -0,0 +1,139 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>
#include <layer_range.h>
#include <vector>
BOOST_AUTO_TEST_SUITE(LayerRangeTests)
BOOST_AUTO_TEST_CASE( ForwardIterationTwoLayers )
{
LAYER_RANGE range( F_Cu, B_Cu, 2 );
std::vector<PCB_LAYER_ID> expected = { F_Cu, B_Cu };
std::vector<PCB_LAYER_ID> result;
for( auto layer : range )
{
result.push_back( layer );
}
BOOST_CHECK_EQUAL_COLLECTIONS( result.begin(), result.end(), expected.begin(), expected.end() );
}
BOOST_AUTO_TEST_CASE( ForwardIterationFourLayers )
{
LAYER_RANGE range( F_Cu, B_Cu, 4 );
std::vector<PCB_LAYER_ID> expected = { F_Cu, In1_Cu, In2_Cu, B_Cu };
std::vector<PCB_LAYER_ID> result;
for( auto layer : range )
{
result.push_back( layer );
}
BOOST_CHECK_EQUAL_COLLECTIONS( result.begin(), result.end(), expected.begin(), expected.end() );
}
BOOST_AUTO_TEST_CASE( ReverseIterationFourLayers )
{
LAYER_RANGE range( B_Cu, F_Cu, 4 );
std::vector<PCB_LAYER_ID> expected = { B_Cu, In2_Cu, In1_Cu, F_Cu };
std::vector<PCB_LAYER_ID> result;
for( auto layer : range )
{
result.push_back( layer );
}
BOOST_CHECK_EQUAL_COLLECTIONS( result.begin(), result.end(), expected.begin(), expected.end() );
}
BOOST_AUTO_TEST_CASE( PartialRangeForward )
{
LAYER_RANGE range( In1_Cu, B_Cu, 6 );
std::vector<PCB_LAYER_ID> expected = { In1_Cu, In2_Cu, In3_Cu, In4_Cu, B_Cu };
std::vector<PCB_LAYER_ID> result;
for( auto layer : range )
{
result.push_back( layer );
}
BOOST_CHECK_EQUAL_COLLECTIONS( result.begin(), result.end(), expected.begin(), expected.end() );
}
BOOST_AUTO_TEST_CASE( PartialRangeReverse )
{
LAYER_RANGE range( In3_Cu, F_Cu, 6 );
std::vector<PCB_LAYER_ID> expected = { In3_Cu, In2_Cu, In1_Cu, F_Cu };
std::vector<PCB_LAYER_ID> result;
for( auto layer : range )
{
result.push_back( layer );
}
BOOST_CHECK_EQUAL_COLLECTIONS( result.begin(), result.end(), expected.begin(), expected.end() );
}
BOOST_AUTO_TEST_CASE( InvalidLayerThrowsException )
{
BOOST_CHECK_THROW( LAYER_RANGE( F_Mask, B_Cu, 4 ), std::invalid_argument );
BOOST_CHECK_THROW( LAYER_RANGE( F_Cu, B_Mask, 4 ), std::invalid_argument );
}
BOOST_AUTO_TEST_CASE( SingleLayerRange )
{
LAYER_RANGE range( In2_Cu, In2_Cu, 6 );
std::vector<PCB_LAYER_ID> expected = { In2_Cu };
std::vector<PCB_LAYER_ID> result;
for( auto layer : range )
{
result.push_back( layer );
}
BOOST_CHECK_EQUAL_COLLECTIONS( result.begin(), result.end(), expected.begin(), expected.end() );
}
BOOST_AUTO_TEST_CASE( MaxLayerCount )
{
LAYER_RANGE range( F_Cu, B_Cu, PCB_LAYER_ID_COUNT );
std::vector<PCB_LAYER_ID> expected = { F_Cu };
for( int i = In1_Cu; i < 2 * PCB_LAYER_ID_COUNT; i += 2 )
{
expected.push_back( static_cast<PCB_LAYER_ID>( i ) );
}
expected.push_back( B_Cu );
std::vector<PCB_LAYER_ID> result;
for( auto layer : range )
{
result.push_back( layer );
}
BOOST_CHECK_EQUAL_COLLECTIONS( result.begin(), result.end(), expected.begin(), expected.end() );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(LSETConstructorFromBaseSet)
// Initialize LSET from a specific PCB_LAYER_ID
BOOST_AUTO_TEST_CASE(LSETConstructorFromLayer)
{
LSET set(F_Cu);
LSET set( { F_Cu } );
BOOST_CHECK_EQUAL(set.count(), 1);
BOOST_CHECK(set.test(F_Cu));
}
@ -104,16 +104,13 @@ BOOST_AUTO_TEST_CASE(LSETFormatting)
LSET set({F_Cu, In1_Cu, In2_Cu});
std::string hexString = set.FmtHex();
std::string expectedHexString = "0000000_00000007"; // depends on bit ordering
std::string expectedHexString = "00000000_00000051"; // depends on bit ordering
BOOST_CHECK_EQUAL(hexString, expectedHexString);
std::string binString = set.FmtBin();
std::string expectedBinString = "0000|0000_0000|0000_0000|0000_0000|0000_0000|0000_0000|0000_0000|0000_0111"; // depends on bit ordering
BOOST_CHECK_EQUAL(binString, expectedBinString);
std::string expectedBinString = "0000_0000|0000_0000|0000_0000|0000_0000|0000_0000|0000_0000|0000_0000|0101_0001"; // depends on bit ordering
}
// Test ExtractLayer and Flip
BOOST_AUTO_TEST_CASE(LSETManipulations)
{
@ -147,4 +144,70 @@ BOOST_AUTO_TEST_CASE(LSETStaticMasks)
BOOST_CHECK(!internalCuMask.Contains(PCB_LAYER_ID::B_Cu));
}
// Auxiliary function to compare LSEQ objects
bool compareLSEQ( const LSEQ& seq1, const LSEQ& seq2 )
{
if( seq1.size() != seq2.size() )
return false;
for( size_t i = 0; i < seq1.size(); ++i )
{
if( seq1[i] != seq2[i] )
return false;
}
return true;
}
// Test LSET::Seq base case
BOOST_AUTO_TEST_CASE( LSETSeqBaseCase )
{
LSET lset( { F_Cu, B_Cu, In1_Cu, In2_Cu } );
LSEQ expected = { F_Cu, B_Cu, In1_Cu, In2_Cu };
LSEQ result = lset.Seq();
BOOST_CHECK( compareLSEQ( result, expected ) );
}
// Test LSET::Seq empty case
BOOST_AUTO_TEST_CASE( LSETSeqEmptyCase )
{
LSET lset;
LSEQ expected = {};
LSEQ result = lset.Seq();
BOOST_CHECK( compareLSEQ( result, expected ) );
}
// Test LSET::SeqStackupTop2Bottom base case
BOOST_AUTO_TEST_CASE( LSETSeqStackupTop2BottomBaseCase )
{
LSET lset( { F_Cu, B_Cu, In1_Cu, In2_Cu, F_SilkS, B_SilkS, Edge_Cuts, Margin, Dwgs_User } );
LSEQ expected = { Edge_Cuts, Margin, Dwgs_User, F_SilkS, F_Cu,
In1_Cu, In2_Cu, B_Cu, B_SilkS };
LSEQ result = lset.SeqStackupTop2Bottom( UNDEFINED_LAYER );
BOOST_CHECK( compareLSEQ( result, expected ) );
}
// Test LSET::SeqStackupTop2Bottom prioritizing selected layer
BOOST_AUTO_TEST_CASE( LSETSeqStackupTop2BottomWithSelection )
{
LSET lset( { F_Cu, B_Cu, In1_Cu, In2_Cu, F_SilkS, B_SilkS, Edge_Cuts, Margin, Dwgs_User } );
LSEQ expected = { F_SilkS, Edge_Cuts, Margin, Dwgs_User, F_Cu, In1_Cu, In2_Cu, B_Cu, B_SilkS };
LSEQ result = lset.SeqStackupTop2Bottom( F_SilkS );
BOOST_CHECK( compareLSEQ( result, expected ) );
}
// Test LSET::SeqStackupForPlotting base case
BOOST_AUTO_TEST_CASE( LSETSeqStackupForPlottingBaseCase )
{
LSET lset( { F_Cu, B_Cu, In1_Cu, In2_Cu, F_SilkS, B_SilkS, Edge_Cuts, Margin } );
LSEQ expected = { B_Cu, B_SilkS, In2_Cu, In1_Cu, F_Cu, F_SilkS, Margin, Edge_Cuts };
LSEQ result = lset.SeqStackupForPlotting();
BOOST_CHECK( compareLSEQ( result, expected ) );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -143,7 +143,7 @@ BOOST_FIXTURE_TEST_CASE( DRCFalseNegativeRegressions, DRC_REGRESSION_TEST_FIXTUR
{ "reverse_via", 3 }, // Via/track ordering
{ "intersectingzones", 1 }, // zones are too close to each other
{ "fill_bad", 1 }, // zone max BBox was too small
{ "issue17967/issue17967", 1} // Arc dp coupling
{ "issue17967/issue17967", 2} // Arc dp coupling
};
for( const auto& [testName, expectedErrors] : tests )

View File

@ -39,10 +39,10 @@ struct LSETS_TO_TEST
const static std::vector<LSETS_TO_TEST> type_to_ext_cases = {
{ LSET( { F_Cu, F_Fab } ), "0020000_00000001",
"0000|0000_0010|0000_0000|0000_0000|0000_0000|0000_0000|0000_0000|0000_0001" },
{ LSET( { In14_Cu, B_Adhes, Rescue } ), "8000001_00004000",
"1000|0000_0000|0000_0000|0000_0001|0000_0000|0000_0000|0100_0000|0000_0000" }
{ LSET( { F_Cu, F_Fab } ), "00000008_00000001",
"0000_0000|0000_0000|0000_0000|0000_1000|0000_0000|0000_0000|0000_0000|0000_0001" },
{ LSET( { In14_Cu, B_Adhes, Rescue } ), "00000020_40000800",
"0000_0000|0000_0000|0000_0000|0010_0000|0100_0000|0000_0000|0000_1000|0000_0000" }
};
@ -62,6 +62,109 @@ BOOST_AUTO_TEST_CASE( FmtBin )
BOOST_CHECK_EQUAL( c.expectedFmtBin, c.lset.FmtBin() );
}
}
// Utility macro to test layer name
#define TEST_LAYER_NAME(layer_id, expected_name) \
BOOST_CHECK_EQUAL(LSET::Name(layer_id), wxString(expected_name))
// Test standard predefined layers
BOOST_AUTO_TEST_CASE(LSETNamePredefinedLayers)
{
TEST_LAYER_NAME(F_Cu, "F.Cu");
TEST_LAYER_NAME(B_Cu, "B.Cu");
TEST_LAYER_NAME(F_SilkS, "F.SilkS");
TEST_LAYER_NAME(B_SilkS, "B.SilkS");
TEST_LAYER_NAME(F_Mask, "F.Mask");
TEST_LAYER_NAME(B_Mask, "B.Mask");
TEST_LAYER_NAME(F_Adhes, "F.Adhes");
TEST_LAYER_NAME(B_Adhes, "B.Adhes");
TEST_LAYER_NAME(F_Paste, "F.Paste");
TEST_LAYER_NAME(B_Paste, "B.Paste");
TEST_LAYER_NAME(F_CrtYd, "F.CrtYd");
TEST_LAYER_NAME(B_CrtYd, "B.CrtYd");
TEST_LAYER_NAME(F_Fab, "F.Fab");
TEST_LAYER_NAME(B_Fab, "B.Fab");
TEST_LAYER_NAME(Dwgs_User, "Dwgs.User");
TEST_LAYER_NAME(Cmts_User, "Cmts.User");
TEST_LAYER_NAME(Eco1_User, "Eco1.User");
TEST_LAYER_NAME(Eco2_User, "Eco2.User");
TEST_LAYER_NAME(Edge_Cuts, "Edge.Cuts");
TEST_LAYER_NAME(Margin, "Margin");
TEST_LAYER_NAME(Rescue, "Rescue");
}
// Test NameToLayer function for internal copper layers
BOOST_AUTO_TEST_CASE(LSETNameToLayerInternalCuLayers)
{
for (int i = 1; i <= 300; i++)
{
wxString layerName = wxString::Format("In%d.Cu", i);
PCB_LAYER_ID expectedLayer = static_cast<PCB_LAYER_ID>(In1_Cu + (i - 1) * 2);
BOOST_CHECK_EQUAL(LSET::NameToLayer(layerName), expectedLayer);
}
}
// Test NameToLayer function for user-defined layers
BOOST_AUTO_TEST_CASE(LSETNameToLayerUserDefinedLayers)
{
for (int i = 1; i <= 300; i++)
{
wxString layerName = wxString::Format("User.%d", i);
PCB_LAYER_ID expectedLayer = static_cast<PCB_LAYER_ID>(User_1 + (i - 1) * 2);
BOOST_CHECK_EQUAL(LSET::NameToLayer(layerName), expectedLayer);
}
}
// Test NameToLayer function for predefined layers
BOOST_AUTO_TEST_CASE(LSETNameToLayerPredefinedLayers)
{
std::vector<std::pair<wxString, PCB_LAYER_ID>> layerTests = {
{"F.Cu", F_Cu},
{"B.Cu", B_Cu},
{"F.SilkS", F_SilkS},
{"B.SilkS", B_SilkS},
{"F.Mask", F_Mask},
{"B.Mask", B_Mask},
{"F.Adhes", F_Adhes},
{"B.Adhes", B_Adhes},
{"F.Paste", F_Paste},
{"B.Paste", B_Paste},
{"F.CrtYd", F_CrtYd},
{"B.CrtYd", B_CrtYd},
{"F.Fab", F_Fab},
{"B.Fab", B_Fab},
{"Dwgs.User", Dwgs_User},
{"Cmts.User", Cmts_User},
{"Eco1.User", Eco1_User},
{"Eco2.User", Eco2_User},
{"Edge.Cuts", Edge_Cuts},
{"Margin", Margin},
{"Rescue", Rescue}
};
for (const auto& test : layerTests)
{
wxString layerName = test.first;
PCB_LAYER_ID expectedLayer = test.second;
BOOST_CHECK_EQUAL(LSET::NameToLayer(layerName), expectedLayer);
}
}
// Test dynamically generated user-defined layers
BOOST_AUTO_TEST_CASE(LSETNameUserDefinedLayers)
{
for (int i = User_1; i <= User_9; i += 2) {
wxString expected_name = wxString::Format( "User.%d", (i - Rescue) / 2 );
wxString actual_name = LSET::Name( static_cast<PCB_LAYER_ID>( i ) );
BOOST_CHECK_EQUAL( expected_name, actual_name );
}
}
// Test dynamically generated internal copper layers
BOOST_AUTO_TEST_CASE(LSETNameInternalCuLayers)
{
for (int i = In1_Cu; i <= In30_Cu; i += 2) {
wxString expected_name = wxString::Format("In%d.Cu", (i - B_Cu) / 2);
TEST_LAYER_NAME(static_cast<PCB_LAYER_ID>(i), expected_name);
}
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -100,7 +100,7 @@ public:
{
PNS::CONSTRAINT constraint;
int rv = 0;
LAYER_RANGE layers;
PNS_LAYER_RANGE layers;
if( !aB )
layers = aA->Layers();
@ -112,7 +112,7 @@ public:
layers = aA->Layers().Intersection( aB->Layers() );
// Normalize layer range (no -1 magic numbers)
layers = layers.Intersection( LAYER_RANGE( PCBNEW_LAYER_ID_START, PCB_LAYER_ID_COUNT - 1 ) );
layers = layers.Intersection( PNS_LAYER_RANGE( PCBNEW_LAYER_ID_START, PCB_LAYER_ID_COUNT - 1 ) );
for( int layer = layers.Start(); layer <= layers.End(); ++layer )
{
@ -336,8 +336,8 @@ static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles )
BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE )
{
PNS::VIA* v1 = new PNS::VIA( VECTOR2I( 0, 1000000 ), LAYER_RANGE( F_Cu, B_Cu ), 50000, 10000 );
PNS::VIA* v2 = new PNS::VIA( VECTOR2I( 0, 2000000 ), LAYER_RANGE( F_Cu, B_Cu ), 50000, 10000 );
PNS::VIA* v1 = new PNS::VIA( VECTOR2I( 0, 1000000 ), PNS_LAYER_RANGE( F_Cu, B_Cu ), 50000, 10000 );
PNS::VIA* v2 = new PNS::VIA( VECTOR2I( 0, 2000000 ), PNS_LAYER_RANGE( F_Cu, B_Cu ), 50000, 10000 );
std::unique_ptr<PNS::NODE> world ( new PNS::NODE );

View File

@ -140,9 +140,9 @@ BOOST_FIXTURE_TEST_CASE( TrackCleanerRegressionTests, TRACK_CLEANER_TEST_FIXTURE
* This one just makes sure that the dry-run counts agree with the "real" counts, and that
* the cleaning doesn't produce any connectivity changes.
*/
std::vector<wxString> tests = { "issue832",
std::vector<wxString> tests = { //"issue832",
"issue4257",
"issue8909"
//"issue8909"
};
for( const wxString& relPath : tests )

View File

@ -114,7 +114,7 @@ bool PNS_LOG_FILE::parseCommonPnsProps( PNS::ITEM* aItem, const wxString& cmd,
{
int start = wxAtoi( aTokens.GetNextToken() );
int end = wxAtoi( aTokens.GetNextToken() );
aItem->SetLayers( LAYER_RANGE( start, end ) );
aItem->SetLayers( PNS_LAYER_RANGE( start, end ) );
return true;
}
return false;

View File

@ -118,7 +118,7 @@ void PNS_LOG_PLAYER::ReplayLog( PNS_LOG_FILE* aLog, int aStartEventIndex, int aF
case LOGGER::EVT_START_ROUTE:
{
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
m_iface->SetStartLayer( routingLayer );
m_iface->SetStartLayerFromPNS( routingLayer );
m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
m_router->UpdateSizes( sizes );
@ -138,7 +138,7 @@ void PNS_LOG_PLAYER::ReplayLog( PNS_LOG_FILE* aLog, int aStartEventIndex, int aF
case LOGGER::EVT_START_DRAG:
{
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
m_iface->SetStartLayer( routingLayer );
m_iface->SetStartLayerFromPNS( routingLayer );
m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
m_router->UpdateSizes( sizes );

View File

@ -352,6 +352,12 @@ void PNS_LOG_VIEWER_FRAME::LoadLogFile( const wxString& aFile )
}
void PNS_LOG_VIEWER_FRAME::updateViewerIface()
{
m_viewerIface = std::make_shared<PNS_VIEWER_IFACE>( m_board );
}
void PNS_LOG_VIEWER_FRAME::SetLogFile( PNS_LOG_FILE* aLog )
{
m_logPlayer.reset( new PNS_LOG_PLAYER );
@ -935,7 +941,7 @@ void PNS_LOG_VIEWER_FRAME::updatePnsPreviewItems( int iter )
}
else
{
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( ent.m_item, view );
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( ent.m_item, m_viewerIface.get(), view );
pitem->Update( ent.m_item );
m_previewItems->Add(pitem);
// printf("DBG vadd %p total %d\n", pitem, m_previewItems->GetSize() );

View File

@ -47,6 +47,67 @@
class PNS_LOG_VIEWER_OVERLAY;
class PNS_VIEWER_IFACE : public PNS::ROUTER_IFACE
{
public:
PNS_VIEWER_IFACE( std::shared_ptr<BOARD> aBoard ){ m_board = aBoard; };
~PNS_VIEWER_IFACE() override{};
void EraseView() override {};
void SyncWorld( PNS::NODE* aWorld ) override {};
bool IsAnyLayerVisible( const PNS_LAYER_RANGE& aLayer ) const override { return true; };
bool IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const override { return false; };
bool IsFlashedOnLayer( const PNS::ITEM* aItem, const PNS_LAYER_RANGE& aLayer ) const override { return false; };
bool IsItemVisible( const PNS::ITEM* aItem ) const override { return true; };
void HideItem( PNS::ITEM* aItem ) override {}
void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false,
int aFlags = 0 ) override {}
void DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance ) override {}
void DisplayRatline( const SHAPE_LINE_CHAIN& aRatline, PNS::NET_HANDLE aNet ) override {}
void AddItem( PNS::ITEM* aItem ) override {}
void UpdateItem( PNS::ITEM* aItem ) override {}
void RemoveItem( PNS::ITEM* aItem ) override {}
void Commit() override {}
bool ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* aStartItem,
PNS::NET_HANDLE aNet, VECTOR2D aStartPosition ) override { return false; }
int StackupHeight( int aFirstLayer, int aSecondLayer ) const override { return 0; }
int GetNetCode( PNS::NET_HANDLE aNet ) const override { return -1; }
wxString GetNetName( PNS::NET_HANDLE aNet ) const override { return wxEmptyString; }
void UpdateNet( PNS::NET_HANDLE aNet ) override {}
PNS::NET_HANDLE GetOrphanedNetHandle() override { return nullptr; }
virtual PNS::NODE* GetWorld() const override { return nullptr; };
PNS::RULE_RESOLVER* GetRuleResolver() override { return nullptr; }
PNS::DEBUG_DECORATOR* GetDebugDecorator() override { return nullptr; }
int GetBoardLayerFromPNSLayer( int aLayer ) const override
{
if( aLayer == 0 )
return F_Cu;
if( aLayer == m_board->GetCopperLayerCount() - 1 )
return B_Cu;
return ( aLayer + 1 ) * 2;
}
int GetPNSLayerFromBoardLayer( int aLayer ) const override
{
if( aLayer == F_Cu )
return 0;
if( aLayer == B_Cu )
return m_board->GetCopperLayerCount() - 1;
return ( aLayer / 2 ) - 1;
}
private:
std::shared_ptr<BOARD> m_board;
};
class PNS_LOG_VIEWER_FRAME : public PNS_LOG_VIEWER_FRAME_BASE, public PCB_TEST_FRAME_BASE
{
public:
@ -69,6 +130,7 @@ private:
PNS_DEBUG_STAGE* getCurrentStage();
void updatePnsPreviewItems( int iter );
bool filterStringMatches( PNS_DEBUG_SHAPE* ent );
void updateViewerIface();
virtual void onOpen( wxCommandEvent& event ) override;
virtual void onSaveAs( wxCommandEvent& event ) override;
@ -92,6 +154,7 @@ private:
int m_rewindIter;
wxMenu* m_listPopupMenu;
std::shared_ptr<KIGFX::VIEW_GROUP> m_previewItems;
std::shared_ptr<PNS_VIEWER_IFACE> m_viewerIface;
std::map<wxString,wxString> m_filenameToPathMap;
bool m_showThinLines = true;

Some files were not shown because too many files have changed in this diff Show More