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
This commit is contained in:
Jeff Young
2025-11-01 19:47:46 +00:00
parent 732ef17b97
commit d78f6857c1
2 changed files with 56 additions and 8 deletions
+34 -3
View File
@@ -38,6 +38,7 @@
#include <wildcards_and_files_ext.h>
#include "excellon_image.h"
#include <wx/log.h>
#include <convert_basic_shapes_to_polygon.h>
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() )
+22 -5
View File
@@ -26,6 +26,20 @@
#include <layer_ids.h>
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<EXPORT_VIA> 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<EXPORT_VIA> m_vias;
std::vector<EXPORT_SLOT> m_slots;
};