Browse Source

Added GenCad export within kicad-cli

Available options:

 "--flip-bottom-pads"
 "--unique-pins"
 "--unique-footprints"
 "--use-drill-origin"
 "--store-origin-coord"
jobs
Julie Vairai 1 year ago
committed by Seth Hillbrand
parent
commit
06eb7fa588
  1. 1
      common/CMakeLists.txt
  2. 34
      common/jobs/job_export_pcb_gencad.cpp
  3. 45
      common/jobs/job_export_pcb_gencad.h
  4. 1
      kicad/CMakeLists.txt
  5. 6
      kicad/cli/command_pcb_export_base.h
  6. 100
      kicad/cli/command_pcb_export_gencad.cpp
  7. 38
      kicad/cli/command_pcb_export_gencad.h
  8. 3
      kicad/kicad_cli.cpp
  9. 117
      pcbnew/pcbnew_jobs_handler.cpp
  10. 1
      pcbnew/pcbnew_jobs_handler.h

1
common/CMakeLists.txt

@ -69,6 +69,7 @@ set( KICOMMON_SRCS
jobs/job_export_pcb_pdf.cpp
jobs/job_export_pcb_pos.cpp
jobs/job_export_pcb_svg.cpp
jobs/job_export_pcb_gencad.cpp
jobs/job_export_pcb_3d.cpp
jobs/job_export_sch_bom.cpp
jobs/job_export_sch_netlist.cpp

34
common/jobs/job_export_pcb_gencad.cpp

@ -0,0 +1,34 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Julie Vairai <j.vairai@hexa-h.com>
* 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 <jobs/job_export_pcb_gencad.h>
JOB_EXPORT_PCB_GENCAD::JOB_EXPORT_PCB_GENCAD( bool aIsCli ) :
JOB( "gencad", aIsCli ),
m_filename(),
m_outputFile(),
m_flipBottomPads(),
m_useUniquePins(),
m_useIndividualShapes(),
m_storeOriginCoords(),
m_useDrillOrigin()
{
}

45
common/jobs/job_export_pcb_gencad.h

@ -0,0 +1,45 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Julie Vairai <j.vairai@hexa-h.com>
* Copyright (C) 1992-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/>.
*/
#ifndef JOB_EXPORT_PCB_GENCAD_H
#define JOB_EXPORT_PCB_GENCAD_H
#include <kicommon.h>
#include <kicommon.h>
#include <layer_ids.h>
#include <wx/string.h>
#include "job.h"
class KICOMMON_API JOB_EXPORT_PCB_GENCAD : public JOB
{
public:
JOB_EXPORT_PCB_GENCAD( bool aIsCli );
wxString m_outputFile;
wxString m_filename;
bool m_flipBottomPads;
bool m_useIndividualShapes;
bool m_storeOriginCoords;
bool m_useDrillOrigin;
bool m_useUniquePins;
};
#endif

1
kicad/CMakeLists.txt

@ -49,6 +49,7 @@ set( KICAD_CLI_SRCS
cli/command_pcb_export_dxf.cpp
cli/command_pcb_export_gerber.cpp
cli/command_pcb_export_gerbers.cpp
cli/command_pcb_export_gencad.cpp
cli/command_pcb_export_ipc2581.cpp
cli/command_pcb_export_pdf.cpp
cli/command_pcb_export_pos.cpp

6
kicad/cli/command_pcb_export_base.h

@ -55,6 +55,12 @@ namespace CLI
#define ARG_INCLUDE_BORDER_TITLE "--include-border-title"
#define ARG_MIRROR "--mirror"
#define ARG_FLIP_BOTTOM_PADS "--flip-bottom-pads"
#define ARG_UNIQUE_PINS "--unique-pins"
#define ARG_UNIQUE_FOOTPRINTS "--unique-footprints"
#define ARG_USE_DRILL_ORIGIN "--use-drill-origin"
#define ARG_STORE_ORIGIN_COORD "--store-origin-coord"
struct PCB_EXPORT_BASE_COMMAND : public COMMAND
{
PCB_EXPORT_BASE_COMMAND( const std::string& aName, bool aInputIsDir = false,

100
kicad/cli/command_pcb_export_gencad.cpp

@ -0,0 +1,100 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Julie Vairai <j.vairai@hexa-h.com>
* Copyright (C) 1992-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 "command_pcb_export_gencad.h"
#include <cli/exit_codes.h>
#include "jobs/job_export_pcb_gencad.h"
#include <kiface_base.h>
#include <layer_ids.h>
#include <string_utils.h>
#include <wx/crt.h>
#include <macros.h>
#include <wx/tokenzr.h>
#include <locale_io.h>
CLI::PCB_EXPORT_GENCAD_COMMAND::PCB_EXPORT_GENCAD_COMMAND() : PCB_EXPORT_BASE_COMMAND( "gencad" )
{
m_argParser.add_description( UTF8STDSTR( _( "Generate Gencad from a list of layers" ) ) );
addLayerArg( true );
addDrawingSheetArg();
addDefineArg();
m_argParser.add_argument( "-f", ARG_FLIP_BOTTOM_PADS )
.default_value( false )
.help( UTF8STDSTR( _( "Flip bottom footprint padstacks" ) ) )
.flag();
m_argParser.add_argument( "", ARG_UNIQUE_PINS )
.default_value( false )
.help( UTF8STDSTR( _( "Generate unique pin names" ) ) )
.flag();
m_argParser.add_argument( "", ARG_UNIQUE_FOOTPRINTS )
.default_value( false )
.help( UTF8STDSTR( _(
"Generate a new shape for each footprint instance (do not reuse shapes)" ) ) )
.flag();
m_argParser.add_argument( "", ARG_USE_DRILL_ORIGIN )
.default_value( false )
.help( UTF8STDSTR( _( "Use drill/place file origin as origin" ) ) )
.flag();
m_argParser.add_argument( "", ARG_STORE_ORIGIN_COORD )
.default_value( false )
.help( UTF8STDSTR( _( "Save the origin coordinates in the file" ) ) )
.flag();
}
int CLI::PCB_EXPORT_GENCAD_COMMAND::doPerform( KIWAY& aKiway )
{
int baseExit = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway );
if( baseExit != EXIT_CODES::OK )
return baseExit;
std::unique_ptr<JOB_EXPORT_PCB_GENCAD> gencadJob( new JOB_EXPORT_PCB_GENCAD( true ) );
gencadJob->m_filename = m_argInput;
gencadJob->m_outputFile = m_argOutput;
gencadJob->SetVarOverrides( m_argDefineVars );
gencadJob->m_flipBottomPads = m_argParser.get<bool>( ARG_FLIP_BOTTOM_PADS );
gencadJob->m_useUniquePins = m_argParser.get<bool>( ARG_UNIQUE_PINS );
gencadJob->m_useIndividualShapes = m_argParser.get<bool>( ARG_UNIQUE_FOOTPRINTS );
gencadJob->m_useDrillOrigin = m_argParser.get<bool>( ARG_USE_DRILL_ORIGIN );
gencadJob->m_storeOriginCoords = m_argParser.get<bool>( ARG_STORE_ORIGIN_COORD );
if( !wxFile::Exists( gencadJob->m_filename ) )
{
wxFprintf( stderr, _( "Board file does not exist or is not accessible\n" ) );
return EXIT_CODES::ERR_INVALID_INPUT_FILE;
}
LOCALE_IO dummy; // Switch to "C" locale
int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, gencadJob.get() );
return exitCode;
}

38
kicad/cli/command_pcb_export_gencad.h

@ -0,0 +1,38 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Julie Vairai <j.vairai@hexa-h.com>
* Copyright (C) 1992-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/>.
*/
#ifndef COMMAND_EXPORT_PCB_GENCAD_H
#define COMMAND_EXPORT_PCB_GENCAD_H
#include "command_pcb_export_base.h"
namespace CLI
{
class PCB_EXPORT_GENCAD_COMMAND : public PCB_EXPORT_BASE_COMMAND
{
public:
PCB_EXPORT_GENCAD_COMMAND();
protected:
int doPerform( KIWAY& aKiway ) override;
};
} // namespace CLI
#endif

3
kicad/kicad_cli.cpp

@ -55,6 +55,7 @@
#include "cli/command_pcb_export_dxf.h"
#include "cli/command_pcb_export_gerber.h"
#include "cli/command_pcb_export_gerbers.h"
#include "cli/command_pcb_export_gencad.h"
#include "cli/command_pcb_export_ipc2581.h"
#include "cli/command_pcb_export_pdf.h"
#include "cli/command_pcb_export_pos.h"
@ -120,6 +121,7 @@ static CLI::PCB_EXPORT_PDF_COMMAND exportPcbPdfCmd{};
static CLI::PCB_EXPORT_POS_COMMAND exportPcbPosCmd{};
static CLI::PCB_EXPORT_GERBER_COMMAND exportPcbGerberCmd{};
static CLI::PCB_EXPORT_GERBERS_COMMAND exportPcbGerbersCmd{};
static CLI::PCB_EXPORT_GENCAD_COMMAND exportPcbGencadCmd{};
static CLI::PCB_EXPORT_IPC2581_COMMAND exportPcbIpc2581Cmd{};
static CLI::PCB_EXPORT_COMMAND exportPcbCmd{};
static CLI::SCH_EXPORT_COMMAND exportSchCmd{};
@ -176,6 +178,7 @@ static std::vector<COMMAND_ENTRY> commandStack = {
&exportPcbDxfCmd,
&exportPcbGerberCmd,
&exportPcbGerbersCmd,
&exportPcbGencadCmd,
&exportPcbGlbCmd,
&exportPcbIpc2581Cmd,
&exportPcbPdfCmd,

117
pcbnew/pcbnew_jobs_handler.cpp

@ -33,6 +33,7 @@
#include <jobs/job_export_pcb_gerbers.h>
#include <jobs/job_export_pcb_drill.h>
#include <jobs/job_export_pcb_dxf.h>
#include <jobs/job_export_pcb_gencad.h>
#include <jobs/job_export_pcb_pdf.h>
#include <jobs/job_export_pcb_pos.h>
#include <jobs/job_export_pcb_svg.h>
@ -59,6 +60,7 @@
#include <pcb_marker.h>
#include <project/project_file.h>
#include <exporters/export_svg.h>
#include <exporters/export_gencad_writer.h>
#include <kiface_ids.h>
#include <netlist_reader/pcb_netlist.h>
#include <netlist_reader/netlist_reader.h>
@ -91,6 +93,8 @@ PCBNEW_JOBS_HANDLER::PCBNEW_JOBS_HANDLER( KIWAY* aKiway ) :
Register( "3d", std::bind( &PCBNEW_JOBS_HANDLER::JobExportStep, this, std::placeholders::_1 ) );
Register( "render", std::bind( &PCBNEW_JOBS_HANDLER::JobExportRender, this, std::placeholders::_1 ) );
Register( "svg", std::bind( &PCBNEW_JOBS_HANDLER::JobExportSvg, this, std::placeholders::_1 ) );
Register( "gencad",
std::bind( &PCBNEW_JOBS_HANDLER::JobExportGencad, this, std::placeholders::_1 ) );
Register( "dxf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDxf, this, std::placeholders::_1 ) );
Register( "pdf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPdf, this, std::placeholders::_1 ) );
Register( "gerber",
@ -574,9 +578,9 @@ int PCBNEW_JOBS_HANDLER::JobExportPdf( JOB* aJob )
switch( aPdfJob->m_drillShapeOption )
{
default:
default:
case 0: plotOpts.SetDrillMarksType( DRILL_MARKS::NO_DRILL_SHAPE ); break;
case 1: plotOpts.SetDrillMarksType( DRILL_MARKS::SMALL_DRILL_SHAPE ); break;
case 1: plotOpts.SetDrillMarksType( DRILL_MARKS::SMALL_DRILL_SHAPE ); break;
case 2: plotOpts.SetDrillMarksType( DRILL_MARKS::FULL_DRILL_SHAPE ); break;
}
@ -724,7 +728,7 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob )
{
m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
fn.GetFullPath() ),
RPT_SEVERITY_ERROR );
RPT_SEVERITY_ERROR );
exitCode = CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
}
@ -741,6 +745,61 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob )
return exitCode;
}
int PCBNEW_JOBS_HANDLER::JobExportGencad( JOB* aJob )
{
JOB_EXPORT_PCB_GENCAD* aGencadJob = dynamic_cast<JOB_EXPORT_PCB_GENCAD*>( aJob );
if( aGencadJob == nullptr )
return CLI::EXIT_CODES::ERR_UNKNOWN;
BOARD* aBoard = LoadBoard( aGencadJob->m_filename, true ); // Ensure m_board is of type BOARD*
if( aBoard == nullptr )
return CLI::EXIT_CODES::ERR_UNKNOWN;
GENCAD_EXPORTER exporter( aBoard );
VECTOR2I GencadOffset;
VECTOR2I auxOrigin = aBoard->GetDesignSettings().GetAuxOrigin();
GencadOffset.x = aGencadJob->m_useDrillOrigin ? auxOrigin.x : 0;
GencadOffset.y = aGencadJob->m_useDrillOrigin ? auxOrigin.y : 0;
exporter.FlipBottomPads( aGencadJob->m_flipBottomPads );
exporter.UsePinNamesUnique( aGencadJob->m_useUniquePins );
exporter.UseIndividualShapes( aGencadJob->m_useIndividualShapes );
exporter.SetPlotOffet( GencadOffset );
exporter.StoreOriginCoordsInFile( aGencadJob->m_storeOriginCoords );
m_reporter->Report( aGencadJob->m_outputFile, RPT_SEVERITY_ERROR );
wxString outputFile = aGencadJob->m_outputFile;
if( outputFile.IsEmpty() )
{
wxFileName fn = aBoard->GetFileName();
fn.SetName( fn.GetName() );
fn.SetExt( wxS( "cad" ) );
outputFile = fn.GetFullName();
}
if( !exporter.WriteFile( outputFile ) )
{
wxString msg;
msg.Printf( _( "Failed to create file '%s'.\n" ), outputFile );
if( aJob->IsCli() )
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_UNKNOWN;
}
if( aJob->IsCli() )
m_reporter->Report( _( "Successfully created genCAD file\n" ), RPT_SEVERITY_INFO );
return CLI::EXIT_CODES::OK;
}
void PCBNEW_JOBS_HANDLER::populateGerberPlotOptionsFromJob( PCB_PLOT_PARAMS& aPlotOpts,
JOB_EXPORT_PCB_GERBER* aJob )
@ -827,7 +886,7 @@ int PCBNEW_JOBS_HANDLER::JobExportGerber( JOB* aJob )
{
m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
aGerberJob->m_outputFile ),
RPT_SEVERITY_ERROR );
RPT_SEVERITY_ERROR );
exitCode = CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
}
@ -920,7 +979,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDrill( JOB* aJob )
return CLI::EXIT_CODES::ERR_UNKNOWN;
excellonWriter->SetFormat( aDrillJob->m_drillUnits
== JOB_EXPORT_PCB_DRILL::DRILL_UNITS::MILLIMETERS,
== JOB_EXPORT_PCB_DRILL::DRILL_UNITS::MILLIMETERS,
zeroFmt, precision.m_Lhs, precision.m_Rhs );
excellonWriter->SetOptions( aDrillJob->m_excellonMirrorY,
aDrillJob->m_excellonMinimalHeader,
@ -987,7 +1046,7 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
}
if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::ASCII
|| aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV )
|| aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV )
{
FILE* file = nullptr;
file = wxFopen( aPosJob->m_outputFile, wxS( "wt" ) );
@ -1001,14 +1060,14 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
|| aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH;
bool backSide = aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BACK
|| aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH;
|| aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH;
PLACE_FILE_EXPORTER exporter( brd,
aPosJob->m_units == JOB_EXPORT_PCB_POS::UNITS::MILLIMETERS,
aPosJob->m_smdOnly, aPosJob->m_excludeFootprintsWithTh,
aPosJob->m_excludeDNP,
frontSide, backSide,
aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV,
aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV,
aPosJob->m_useDrillPlaceFileOrigin,
aPosJob->m_negateBottomX );
data = exporter.GenPositionData();
@ -1057,7 +1116,7 @@ int PCBNEW_JOBS_HANDLER::JobExportFpUpgrade( JOB* aJob )
else if( fileType != PCB_IO_MGR::KICAD_SEXP )
{
m_reporter->Report( _( "Output path must be specified to convert legacy and non-KiCad libraries\n" ),
RPT_SEVERITY_ERROR );
RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
}
@ -1385,10 +1444,10 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
m_reporter->Report( wxString::Format( _( "Found %d violations\n" ),
markersProvider->GetCount() ),
RPT_SEVERITY_INFO );
RPT_SEVERITY_INFO );
m_reporter->Report( wxString::Format( _( "Found %d unconnected items\n" ),
ratsnestProvider->GetCount() ),
RPT_SEVERITY_INFO );
RPT_SEVERITY_INFO );
if( drcJob->m_parity )
{
@ -1410,7 +1469,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
{
m_reporter->Report( wxString::Format( _( "Unable to save DRC report to %s\n" ),
drcJob->m_outputFile ),
RPT_SEVERITY_INFO );
RPT_SEVERITY_INFO );
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
}
@ -1541,28 +1600,28 @@ void PCBNEW_JOBS_HANDLER::loadOverrideDrawingSheet( BOARD* aBrd, const wxString&
auto loadSheet =
[&]( const wxString& path ) -> bool
{
BASE_SCREEN::m_DrawingSheetFileName = path;
FILENAME_RESOLVER resolver;
resolver.SetProject( aBrd->GetProject() );
resolver.SetProgramBase( &Pgm() );
{
BASE_SCREEN::m_DrawingSheetFileName = path;
FILENAME_RESOLVER resolver;
resolver.SetProject( aBrd->GetProject() );
resolver.SetProgramBase( &Pgm() );
wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
aBrd->GetProject()->GetProjectPath(),
aBrd->GetEmbeddedFiles() );
wxString msg;
wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
aBrd->GetProject()->GetProjectPath(),
aBrd->GetEmbeddedFiles() );
wxString msg;
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )
{
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )
{
m_reporter->Report( wxString::Format( _( "Error loading drawing sheet '%s'." ),
path )
+ wxS( "\n" ) + msg + wxS( "\n" ),
RPT_SEVERITY_ERROR );
return false;
}
+ wxS( "\n" ) + msg + wxS( "\n" ),
RPT_SEVERITY_ERROR );
return false;
}
return true;
};
return true;
};
if( loadSheet( aSheetPath ) )
return;

1
pcbnew/pcbnew_jobs_handler.h

@ -42,6 +42,7 @@ public:
int JobExportPdf( JOB* aJob );
int JobExportGerber( JOB* aJob );
int JobExportGerbers( JOB* aJob );
int JobExportGencad( JOB* aJob );
int JobExportDrill( JOB* aJob );
int JobExportPos( JOB* aJob );
int JobExportFpUpgrade( JOB* aJob );

Loading…
Cancel
Save