kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #34779
[PATCH] - File format shim for clearance data
I have a patch for treating track clearance the same as track width. The
user can already specify a track width that is an exception to the
netclass width, and now do the same for clearance. (
https://youtu.be/05vfAvYwDio )
This is not that patch.
This is a small shim for the file format that will allow reading and
writing clearance data from the kicad_pcb file without causing a file
parse error. This will allow us to transparently load and save files
with clearance data using version 5 stable.
There are 2 patch files. The first deals with the clearance data. It
adds a (clearance ) field to vias and segments that is only populated if
the item has a non-netclass clearance. The second patch preserves user
clearances. It adds a (user_clearance ) field to setup to compliment the
(user_width ) already there. As stated in the patch title, the 1st patch
is enough to make a significant difference for my team.
Issues:
TRACK gains an int sized member. There are hints in the source
comments that this was a planned improvement all along. Meanwhile some
may be concerned about impact on memory usage. If anyone is, I'm happy
to do a memory impact analysis.
I reduced the patch to the smallest one that would make a
meaningful impact on the work we do here. Easy to review and most likely
to be acceptable given the point in the release cycle we are. The wider
impact of this patch is therefore limited and as a result it might be
just our team that benefits.
If it's not clear, some of our work computers are locked to the stable
kicad version, while others are not. We gain benefit from being able to
do flexible clearance layout on the non-locked computers and still edit
those files on a stable version of kicad. If you would prefer to look at
the minimum patch which allows flexible clearance layout, I am happy to
submit that.
-hauptmech
>From 08165106624d2940ae4507b8981298d58f4ae1a2 Mon Sep 17 00:00:00 2001
From: hauptmech <hauptmech@xxxxxxxxx>
Date: Wed, 7 Mar 2018 13:12:20 +1300
Subject: [PATCH 1/2] Minimum viable shim for kicad file format to handle track
clearances
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.16.2"
This is a multi-part message in MIME format.
--------------2.16.2
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
common/pcb.keywords | 1 +
pcbnew/class_track.cpp | 1 +
pcbnew/class_track.h | 22 ++++++++++++++++++++++
pcbnew/kicad_plugin.cpp | 6 ++++++
pcbnew/pcb_parser.cpp | 14 ++++++++++++++
5 files changed, 44 insertions(+)
--------------2.16.2
Content-Type: text/x-patch; name="0001-Minimum-viable-shim-for-kicad-file-format-to-handle-.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0001-Minimum-viable-shim-for-kicad-file-format-to-handle-.patch"
diff --git a/common/pcb.keywords b/common/pcb.keywords
index 1998f9ab5..c36971085 100644
--- a/common/pcb.keywords
+++ b/common/pcb.keywords
@@ -187,6 +187,7 @@ thru_hole_only
tstamp
unlocked
user
+user_clearance
user_trace_width
user_via
uvia_dia
diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp
index 1c5f69be7..9fd08dae0 100644
--- a/pcbnew/class_track.cpp
+++ b/pcbnew/class_track.cpp
@@ -99,6 +99,7 @@ TRACK::TRACK( BOARD_ITEM* aParent, KICAD_T idtype ) :
m_Width = Millimeter2iu( 0.2 );
start = end = NULL;
m_Param = 0;
+ m_Clearance = NETCLASS_HAS_CLEARANCE; // Netlist drives clearance by default
}
diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h
index 1da81e6ff..0de9014b4 100644
--- a/pcbnew/class_track.h
+++ b/pcbnew/class_track.h
@@ -60,6 +60,8 @@ enum VIATYPE_T
#define MIN_VIA_DRAW_SIZE 4 /// Minimum size in pixel for full drawing
+#define NETCLASS_HAS_CLEARANCE -1
+
/**
* Function GetTrack
* is a helper function to locate a trace segment having an end point at \a aPosition
@@ -280,6 +282,25 @@ public:
return wxT( "TRACK" );
}
+ /**
+ * Function HasClearance
+ * Return false if clearance is provided by the netclass, otherwise true.
+ */
+ bool HasClearance() const
+ {
+ return m_Clearance != NETCLASS_HAS_CLEARANCE;
+ }
+
+ void SetClearance( int aClearance )
+ {
+ m_Clearance = aClearance;
+ }
+
+ int GetInternalClearance() const
+ {
+ return m_Clearance;
+ }
+
/**
* Function GetClearance
* returns the clearance in internal units. If \a aItem is not NULL then the
@@ -333,6 +354,7 @@ protected:
void DrawShortNetname( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
COLOR4D aBgColor );
+ int m_Clearance; ///< Clearance between this and other elements
int m_Width; ///< Thickness of track, or via diameter
wxPoint m_Start; ///< Line start point
wxPoint m_End; ///< Line end point
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index eef47d7a5..6b0c39897 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -1602,6 +1602,9 @@ void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const
FMT_IU( aTrack->GetStart() ).c_str(),
FMT_IU( aTrack->GetWidth() ).c_str() );
+ if( via->HasClearance() )
+ m_out->Print( 0, " (clearance %s)", FMT_IU( via->GetInternalClearance() ).c_str() );
+
if( via->GetDrill() != UNDEFINED_DRILL_DIAMETER )
m_out->Print( 0, " (drill %s)", FMT_IU( via->GetDrill() ).c_str() );
@@ -1615,6 +1618,9 @@ void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const
FMT_IU( aTrack->GetStart() ).c_str(), FMT_IU( aTrack->GetEnd() ).c_str(),
FMT_IU( aTrack->GetWidth() ).c_str() );
+ if( aTrack->HasClearance() )
+ m_out->Print( 0, " (clearance %s)", FMT_IU( aTrack->GetInternalClearance() ).c_str() );
+
m_out->Print( 0, " (layer %s)", m_out->Quotew( aTrack->GetLayerName() ).c_str() );
}
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index f6049dd52..a514e043e 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -1057,6 +1057,12 @@ void PCB_PARSER::parseSetup()
NeedRIGHT();
break;
+ case T_user_clearance:
+ // Absorb this token if it exists
+ parseBoardUnits( T_user_clearance );
+ NeedRIGHT();
+ break;
+
case T_trace_clearance:
defaultNetClass->SetClearance( parseBoardUnits( T_trace_clearance ) );
NeedRIGHT();
@@ -2703,6 +2709,10 @@ TRACK* PCB_PARSER::parseTRACK()
track->SetWidth( parseBoardUnits( "width" ) );
break;
+ case T_clearance:
+ track->SetClearance( parseBoardUnits( "clearance" ) );
+ break;
+
case T_layer:
track->SetLayer( parseBoardItemLayer() );
break;
@@ -2767,6 +2777,10 @@ VIA* PCB_PARSER::parseVIA()
NeedRIGHT();
break;
+ case T_clearance:
+ via->SetClearance( parseBoardUnits( "clearance" ) );
+ break;
+
case T_size:
via->SetWidth( parseBoardUnits( "via width" ) );
NeedRIGHT();
--------------2.16.2--
>From dfe8b56d1c8bc76eaf55812ab0a5da2a28c3f9c6 Mon Sep 17 00:00:00 2001
From: hauptmech <hauptmech@xxxxxxxxx>
Date: Wed, 7 Mar 2018 13:19:08 +1300
Subject: [PATCH 2/2] Better shim for kicad file format to handle track
clearances. User clearance values are preserved instead of discarded.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.16.2"
This is a multi-part message in MIME format.
--------------2.16.2
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
include/board_design_settings.h | 44 ++++++++++++++++++++++++++++++++++++++++
pcbnew/board_design_settings.cpp | 27 ++++++++++++++++++++++++
pcbnew/class_track.cpp | 18 +++++++++++++---
pcbnew/class_track.h | 5 -----
pcbnew/kicad_plugin.cpp | 9 ++++++--
pcbnew/pcb_parser.cpp | 3 +--
6 files changed, 94 insertions(+), 12 deletions(-)
--------------2.16.2
Content-Type: text/x-patch; name="0002-Better-shim-for-kicad-file-format-to-handle-track-cl.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0002-Better-shim-for-kicad-file-format-to-handle-track-cl.patch"
diff --git a/include/board_design_settings.h b/include/board_design_settings.h
index 2d7cc9ec9..236d334d0 100644
--- a/include/board_design_settings.h
+++ b/include/board_design_settings.h
@@ -47,6 +47,7 @@
#define DEFAULT_SOLDERMASK_MIN_WIDTH Millimeter2iu( 0.0 )
#define DEFAULT_CUSTOMTRACKWIDTH 0.2
+#define DEFAULT_CUSTOMCLEARANCE 0.2
#define DEFAULT_TRACKMINWIDTH 0.2 // track width min value
#define DEFAULT_VIASMINSIZE 0.4 // vias (not micro vias) min diameter
#define DEFAULT_VIASMINDRILL 0.3 // vias (not micro vias) min drill diameter
@@ -105,6 +106,10 @@ public:
/// Track width list
std::vector<int> m_TrackWidthList;
+ // The first value is the current netclass clearance
+ /// Clearance list
+ std::vector<int> m_ClearanceList;
+
/// List of current netclasses. There is always the default netclass.
NETCLASSES m_NetClasses;
@@ -169,6 +174,10 @@ private:
/// 0 is the index selection of the default value Netclass
unsigned m_trackWidthIndex;
+ // Index for m_ClearanceList to select the value.
+ /// 0 is the index selection of the default value Netclass
+ unsigned m_clearanceIndex;
+
///> Use custom values for track/via sizes (not specified in net class nor in the size lists).
bool m_useCustomTrackVia;
@@ -220,6 +229,16 @@ public:
return ( m_trackWidthIndex == 0 && !m_useCustomTrackVia );
}
+
+ /**
+ * Function UseNetClassClearance
+ * returns true if netclass values should be used to obtain appropriate clearance.
+ */
+ inline bool UseNetClassClearance() const
+ {
+ return ( m_clearanceIndex == 0 && !m_useCustomTrackVia );
+ }
+
/**
* Function UseNetClassVia
* returns true if netclass values should be used to obtain appropriate via size.
@@ -265,6 +284,31 @@ public:
*/
int GetCurrentMicroViaDrill();
+ /**
+ * Function GetClearanceIndex
+ * @return the current clearance list index.
+ */
+ inline unsigned GetClearanceIndex() const { return m_clearanceIndex; }
+
+ /**
+ * Function SetClearanceIndex
+ * sets the current track clearance index to \a aIndex.
+ *
+ * @param aIndex is the clearance list index.
+ */
+ void SetClearanceIndex( unsigned aIndex );
+
+ /**
+ * Function GetCurrentClearance
+ * @return the current clearance, according to the selected options
+ * ( using the default netclass value or a preset/custom value )
+ * the default netclass is always in m_ClearanceList[0]
+ */
+ inline int GetCurrentClearance() const
+ {
+ return m_ClearanceList[m_clearanceIndex];
+ }
+
/**
* Function GetTrackWidthIndex
* @return the current track width list index.
diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp
index fd91a9c4a..598c0e0f8 100644
--- a/pcbnew/board_design_settings.cpp
+++ b/pcbnew/board_design_settings.cpp
@@ -92,6 +92,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() :
m_viaSizeIndex = 0;
m_trackWidthIndex = 0;
+ m_clearanceIndex = 0;
// Default values for the footprint editor and fp creation
// (also covers footprints created on the fly by micor-waves tools)
@@ -203,6 +204,12 @@ bool BOARD_DESIGN_SETTINGS::SetCurrentNetClass( const wxString& aNetClassName )
m_TrackWidthList.push_back( 0 );
}
+ if( m_ClearanceList.size() == 0 )
+ {
+ lists_sizes_modified = true;
+ m_ClearanceList.push_back( 0 );
+ }
+
/* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values
* are always the Netclass values
*/
@@ -224,12 +231,21 @@ bool BOARD_DESIGN_SETTINGS::SetCurrentNetClass( const wxString& aNetClassName )
m_TrackWidthList[0] = netClass->GetTrackWidth();
}
+ if( m_ClearanceList[0] != netClass->GetClearance() )
+ {
+ lists_sizes_modified = true;
+ m_ClearanceList[0] = netClass->GetClearance();
+ }
+
if( GetViaSizeIndex() >= m_ViasDimensionsList.size() )
SetViaSizeIndex( m_ViasDimensionsList.size() );
if( GetTrackWidthIndex() >= m_TrackWidthList.size() )
SetTrackWidthIndex( m_TrackWidthList.size() );
+ if( GetClearanceIndex() >= m_ClearanceList.size() )
+ SetClearanceIndex( m_ClearanceList.size() );
+
return lists_sizes_modified;
}
@@ -314,6 +330,17 @@ void BOARD_DESIGN_SETTINGS::SetTrackWidthIndex( unsigned aIndex )
m_useCustomTrackVia = false;
}
+// Setting the clearance disables the custom TrackVia mode
+void BOARD_DESIGN_SETTINGS::SetClearanceIndex( unsigned aIndex )
+{
+ if( aIndex >= m_ClearanceList.size() )
+ m_clearanceIndex = m_ClearanceList.size();
+ else
+ m_clearanceIndex = aIndex;
+
+ m_useCustomTrackVia = false;
+}
+
void BOARD_DESIGN_SETTINGS::SetVisibleAlls()
{
diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp
index 9fd08dae0..38d9d2f29 100644
--- a/pcbnew/class_track.cpp
+++ b/pcbnew/class_track.cpp
@@ -226,9 +226,21 @@ BITMAP_DEF VIA::GetMenuImage() const
int TRACK::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
{
- // Currently tracks have no specific clearance parameter on a per track or per
- // segment basis. The NETCLASS clearance is used.
- return BOARD_CONNECTED_ITEM::GetClearance( aItem );
+ // Return netclass clearance if no clearance has been specifically set
+ if ( m_Clearance == NETCLASS_HAS_CLEARANCE )
+ {
+ return BOARD_CONNECTED_ITEM::GetClearance( aItem );
+ }
+ else
+ {
+ if( aItem )
+ {
+ int hisClearance = aItem->GetClearance();
+ return std::max( hisClearance, m_Clearance );
+ }
+
+ return m_Clearance;
+ }
}
diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h
index 0de9014b4..a03fc70d8 100644
--- a/pcbnew/class_track.h
+++ b/pcbnew/class_track.h
@@ -296,11 +296,6 @@ public:
m_Clearance = aClearance;
}
- int GetInternalClearance() const
- {
- return m_Clearance;
- }
-
/**
* Function GetClearance
* returns the clearance in internal units. If \a aItem is not NULL then the
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index 6b0c39897..d1c8d7cf2 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -514,6 +514,11 @@ void PCB_IO::formatSetup( BOARD* aBoard, int aNestLevel ) const
m_out->Print( aNestLevel+1, "(user_trace_width %s)\n",
FMT_IU( dsnSettings.m_TrackWidthList[ii] ).c_str() );
+ // Save custom clearance list (the first is not saved here since it is the netclass value)
+ for( unsigned ii = 1; ii < dsnSettings.m_ClearanceList.size(); ii++ )
+ m_out->Print( aNestLevel+1, "(user_clearance %s)\n",
+ FMT_IU( dsnSettings.m_ClearanceList[ii] ).c_str() );
+
m_out->Print( aNestLevel+1, "(trace_clearance %s)\n",
FMT_IU( dsnSettings.GetDefault()->GetClearance() ).c_str() );
@@ -1603,7 +1608,7 @@ void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const
FMT_IU( aTrack->GetWidth() ).c_str() );
if( via->HasClearance() )
- m_out->Print( 0, " (clearance %s)", FMT_IU( via->GetInternalClearance() ).c_str() );
+ m_out->Print( 0, " (clearance %s)", FMT_IU( via->GetClearance() ).c_str() );
if( via->GetDrill() != UNDEFINED_DRILL_DIAMETER )
m_out->Print( 0, " (drill %s)", FMT_IU( via->GetDrill() ).c_str() );
@@ -1619,7 +1624,7 @@ void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const
FMT_IU( aTrack->GetWidth() ).c_str() );
if( aTrack->HasClearance() )
- m_out->Print( 0, " (clearance %s)", FMT_IU( aTrack->GetInternalClearance() ).c_str() );
+ m_out->Print( 0, " (clearance %s)", FMT_IU( aTrack->GetClearance() ).c_str() );
m_out->Print( 0, " (layer %s)", m_out->Quotew( aTrack->GetLayerName() ).c_str() );
}
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index a514e043e..df069ec57 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -1058,8 +1058,7 @@ void PCB_PARSER::parseSetup()
break;
case T_user_clearance:
- // Absorb this token if it exists
- parseBoardUnits( T_user_clearance );
+ designSettings.m_ClearanceList.push_back( parseBoardUnits( T_user_clearance ) );
NeedRIGHT();
break;
--------------2.16.2--
Follow ups