← Back to team overview

kicad-developers team mailing list archive

[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