From d78f6857c1d7c1306658a50fe7963d7fbaaa452c Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 1 Nov 2025 19:47:46 +0000 Subject: [PATCH] Export Gerber slots as single-pad-footprints. (We export round holes as vias, but they don't allow slots.) Fixes https://gitlab.com/kicad/code/kicad/-/issues/22057 --- gerbview/export_to_pcbnew.cpp | 37 ++++++++++++++++++++++++++++++++--- gerbview/export_to_pcbnew.h | 27 ++++++++++++++++++++----- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/gerbview/export_to_pcbnew.cpp b/gerbview/export_to_pcbnew.cpp index a2bb4b3ca8..f79477dc5a 100644 --- a/gerbview/export_to_pcbnew.cpp +++ b/gerbview/export_to_pcbnew.cpp @@ -38,6 +38,7 @@ #include #include "excellon_image.h" #include +#include GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME* aFrame, const wxString& aFileName ) @@ -135,6 +136,9 @@ bool GBR_TO_PCB_EXPORTER::ExportPcb( const int* aLayerLookUpTable, int aCopperLa for( const EXPORT_VIA& via : m_vias ) export_via( via ); + for( const EXPORT_SLOT& slot : m_slots ) + export_slot( slot ); + fprintf( m_fp, ")\n" ); fclose( m_fp ); @@ -295,8 +299,10 @@ void GBR_TO_PCB_EXPORTER::export_non_copper_arc( const GERBER_DRAW_ITEM* aGbrIte void GBR_TO_PCB_EXPORTER::collect_hole( const GERBER_DRAW_ITEM* aGbrItem ) { - int size = std::min( aGbrItem->m_Size.x, aGbrItem->m_Size.y ); - m_vias.emplace_back( aGbrItem->m_Start, size + 1, size ); + if( aGbrItem->m_ShapeType == GBR_SPOT_CIRCLE ) + m_vias.emplace_back( aGbrItem->m_Start, aGbrItem->m_Size.x + 1, aGbrItem->m_Size.x ); + else if( aGbrItem->m_ShapeType == GBR_SEGMENT ) + m_slots.emplace_back( aGbrItem->m_Start, aGbrItem->m_End, aGbrItem->m_Size.x ); } @@ -308,7 +314,7 @@ void GBR_TO_PCB_EXPORTER::export_via( const EXPORT_VIA& aVia ) via_pos.y = -via_pos.y; // Layers are Front to Back - fprintf( m_fp, " (via (at %s %s) (size %s) (drill %s)", + fprintf( m_fp, "\t(via (at %s %s) (size %s) (drill %s)", FormatDouble2Str( MapToPcbUnits( via_pos.x ) ).c_str(), FormatDouble2Str( MapToPcbUnits( via_pos.y ) ).c_str(), FormatDouble2Str( MapToPcbUnits( aVia.m_Size ) ).c_str(), @@ -320,6 +326,31 @@ void GBR_TO_PCB_EXPORTER::export_via( const EXPORT_VIA& aVia ) } +void GBR_TO_PCB_EXPORTER::export_slot( const EXPORT_SLOT& aSlot ) +{ + VECTOR2I start = aSlot.m_Start; + VECTOR2I end = aSlot.m_End; + + // Reverse Y axis: + start.y = -start.y; + end.y = -end.y; + + VECTOR2I dir = end - start; + int minorAxis = aSlot.m_Width; + int majorAxis = aSlot.m_Width + dir.EuclideanNorm(); + VECTOR2I center = ( start + end ) / 2; + + fprintf( m_fp, "\t(footprint \"slot\" (pad 1 thru_hole oval (at %s %s %s) (size %s %s) (drill oval %s %s)))\n", + FormatDouble2Str( MapToPcbUnits( center.x ) ).c_str(), + FormatDouble2Str( MapToPcbUnits( center.y ) ).c_str(), + FormatDouble2Str( EDA_ANGLE( dir ).AsDegrees() ).c_str(), + FormatDouble2Str( MapToPcbUnits( majorAxis + 1 ) ).c_str(), + FormatDouble2Str( MapToPcbUnits( minorAxis + 1 ) ).c_str(), + FormatDouble2Str( MapToPcbUnits( majorAxis ) ).c_str(), + FormatDouble2Str( MapToPcbUnits( minorAxis ) ).c_str() ); +} + + void GBR_TO_PCB_EXPORTER::export_copper_item( const GERBER_DRAW_ITEM* aGbrItem, int aLayer ) { if( aGbrItem->GetLayerPolarity() ) diff --git a/gerbview/export_to_pcbnew.h b/gerbview/export_to_pcbnew.h index 9323ad88ee..d9f2260216 100644 --- a/gerbview/export_to_pcbnew.h +++ b/gerbview/export_to_pcbnew.h @@ -26,6 +26,20 @@ #include +struct EXPORT_SLOT +{ + EXPORT_SLOT( const VECTOR2I& aStart, const VECTOR2I& aEnd, int aWidth ) : + m_Start( aStart ), + m_End( aEnd ), + m_Width( aWidth ) + { } + + VECTOR2I m_Start; + VECTOR2I m_End; + int m_Width; +}; + + struct EXPORT_VIA { EXPORT_VIA( const VECTOR2I& aPos, int aSize, int aDrill ) : @@ -80,6 +94,8 @@ private: */ void export_via( const EXPORT_VIA& aVia ); + void export_slot( const EXPORT_SLOT& aSlot ); + /** * Write a non copper line or arc to the board file. * @@ -188,9 +204,10 @@ private: } private: - GERBVIEW_FRAME* m_gerbview_frame; // the main gerber frame - wxString m_pcb_file_name; // BOARD file to write to - FILE* m_fp; // the board file - int m_pcbCopperLayersCount; - std::vector m_vias; + GERBVIEW_FRAME* m_gerbview_frame; // the main gerber frame + wxString m_pcb_file_name; // BOARD file to write to + FILE* m_fp; // the board file + int m_pcbCopperLayersCount; + std::vector m_vias; + std::vector m_slots; };