2016-09-02 10:08:40 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of kicad2mcad
|
|
|
|
*
|
|
|
|
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
2021-07-06 20:22:06 +00:00
|
|
|
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
2016-09-02 10:08:40 +00:00
|
|
|
*
|
|
|
|
* 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 2
|
|
|
|
* 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, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
2021-06-08 00:23:17 +00:00
|
|
|
|
2016-09-02 10:08:40 +00:00
|
|
|
#include <wx/app.h>
|
|
|
|
#include <wx/cmdline.h>
|
|
|
|
#include <wx/log.h>
|
2021-06-08 00:23:17 +00:00
|
|
|
#include <wx/msgdlg.h>
|
2016-09-02 10:08:40 +00:00
|
|
|
#include <wx/string.h>
|
|
|
|
#include <wx/filename.h>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iostream>
|
2016-09-18 02:24:04 +00:00
|
|
|
#include <sstream>
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2021-09-11 16:40:20 +00:00
|
|
|
#include "kicad2step.h"
|
2019-04-15 17:09:27 +00:00
|
|
|
#include "pcb/kicadpcb.h"
|
2018-09-20 09:05:52 +00:00
|
|
|
#include "kicad2step_frame_base.h"
|
|
|
|
#include "panel_kicad2step.h"
|
2020-02-15 09:58:44 +00:00
|
|
|
#include <Standard_Failure.hxx> // In open cascade
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
class KICAD2STEP_FRAME : public KICAD2STEP_FRAME_BASE
|
|
|
|
{
|
|
|
|
public:
|
2021-07-29 11:10:58 +00:00
|
|
|
KICAD2STEP_FRAME( const wxString& title );
|
2021-09-20 03:11:11 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void OnOKButtonClick( wxCommandEvent& aEvent ) override;
|
2018-09-20 09:05:52 +00:00
|
|
|
};
|
2018-09-11 07:22:10 +00:00
|
|
|
|
2021-09-11 16:40:20 +00:00
|
|
|
// Horrible hack until we decouple things more
|
|
|
|
static PANEL_KICAD2STEP* openPanel = nullptr;
|
|
|
|
void ReportMessage( const wxString& aMessage )
|
|
|
|
{
|
|
|
|
if( openPanel != nullptr )
|
|
|
|
openPanel->AppendMessage( aMessage );
|
|
|
|
}
|
|
|
|
|
2021-07-29 11:10:58 +00:00
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
KICAD2MCAD_PRMS::KICAD2MCAD_PRMS()
|
|
|
|
{
|
2016-09-02 10:08:40 +00:00
|
|
|
#ifdef SUPPORTS_IGES
|
2018-09-20 09:05:52 +00:00
|
|
|
m_fmtIGES = false;
|
2016-09-02 10:08:40 +00:00
|
|
|
#endif
|
2018-09-20 09:05:52 +00:00
|
|
|
m_overwrite = false;
|
|
|
|
m_useGridOrigin = false;
|
|
|
|
m_useDrillOrigin = false;
|
|
|
|
m_includeVirtual = true;
|
2021-06-08 22:46:37 +00:00
|
|
|
m_substModels = false;
|
2018-09-20 09:05:52 +00:00
|
|
|
m_xOrigin = 0.0;
|
|
|
|
m_yOrigin = 0.0;
|
|
|
|
m_minDistance = MIN_DISTANCE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-02 06:34:07 +00:00
|
|
|
|
2021-07-29 11:10:58 +00:00
|
|
|
KICAD2STEP_FRAME::KICAD2STEP_FRAME( const wxString& title ) :
|
|
|
|
KICAD2STEP_FRAME_BASE( NULL, wxID_ANY, title )
|
2018-09-20 09:05:52 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-09-20 03:11:11 +00:00
|
|
|
|
|
|
|
void KICAD2STEP_FRAME::OnOKButtonClick( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-06 20:22:06 +00:00
|
|
|
PANEL_KICAD2STEP::PANEL_KICAD2STEP( wxWindow* parent, wxWindowID id, const wxPoint& pos,
|
|
|
|
const wxSize& size, long style ) :
|
|
|
|
wxPanel( parent, id, pos, size, style )
|
2018-09-20 09:05:52 +00:00
|
|
|
{
|
|
|
|
wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
|
2021-07-06 20:22:06 +00:00
|
|
|
m_tcMessages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
2021-07-29 11:10:58 +00:00
|
|
|
wxTE_MULTILINE | wxTE_READONLY );
|
|
|
|
bSizer->Add( m_tcMessages, 1, wxALL | wxEXPAND, 5 );
|
2018-09-20 09:05:52 +00:00
|
|
|
|
|
|
|
SetSizer( bSizer );
|
|
|
|
Layout();
|
|
|
|
bSizer->Fit( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_KICAD2STEP::AppendMessage( const wxString& aMessage )
|
|
|
|
{
|
2018-10-02 06:34:07 +00:00
|
|
|
m_tcMessages->AppendText( aMessage );
|
|
|
|
wxSafeYield();
|
2018-09-20 09:05:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Smart class that will swap streambufs and replace them when object goes out of scope.
|
|
|
|
// ( ensure the initial stream buffer is restored )
|
|
|
|
// see:
|
|
|
|
// https://groups.google.com/forum/#!topic/borland.public.cppbuilder.language/Uua6t3VhELA
|
|
|
|
// It is useful here to redirect for instance cout or cerr to a string stream
|
|
|
|
class STREAMBUF_SWAPPER
|
2016-09-02 10:08:40 +00:00
|
|
|
{
|
2018-09-20 09:05:52 +00:00
|
|
|
public:
|
2021-07-29 11:10:58 +00:00
|
|
|
STREAMBUF_SWAPPER( std::ostream& orig, std::ostream& replacement ) :
|
|
|
|
m_buf( orig.rdbuf() ),
|
|
|
|
m_str( orig )
|
2018-09-20 09:05:52 +00:00
|
|
|
{
|
|
|
|
orig.rdbuf( replacement.rdbuf() );
|
|
|
|
}
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
~STREAMBUF_SWAPPER()
|
2016-09-02 10:08:40 +00:00
|
|
|
{
|
2021-07-29 11:10:58 +00:00
|
|
|
m_str.rdbuf( m_buf );
|
2018-09-20 09:05:52 +00:00
|
|
|
}
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
private:
|
2021-07-29 11:10:58 +00:00
|
|
|
std::streambuf* m_buf;
|
|
|
|
std::ostream& m_str;
|
2018-09-20 09:05:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int PANEL_KICAD2STEP::RunConverter()
|
|
|
|
{
|
|
|
|
wxFileName fname( m_params.m_filename );
|
|
|
|
|
|
|
|
if( !fname.FileExists() )
|
|
|
|
{
|
2021-07-29 11:10:58 +00:00
|
|
|
wxMessageBox( wxString::Format( _( "No such file: %s" ), m_params.m_filename ) );
|
2016-09-02 10:08:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-10-02 06:34:07 +00:00
|
|
|
wxFileName out_fname;
|
2016-09-18 02:24:04 +00:00
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
if( m_params.m_outputFile.empty() )
|
2018-09-11 07:22:10 +00:00
|
|
|
{
|
2018-10-02 06:34:07 +00:00
|
|
|
out_fname.Assign( fname.GetFullPath() );
|
|
|
|
out_fname.SetExt( m_params.getOutputExt() );
|
2018-09-11 07:22:10 +00:00
|
|
|
}
|
2016-09-18 02:24:04 +00:00
|
|
|
else
|
2018-09-11 07:22:10 +00:00
|
|
|
{
|
2018-10-02 06:34:07 +00:00
|
|
|
out_fname.Assign( m_params.m_outputFile );
|
2016-09-18 02:24:04 +00:00
|
|
|
|
2018-09-11 07:22:10 +00:00
|
|
|
// Set the file extension if the user's requested
|
|
|
|
// file name does not have an extension.
|
2018-10-02 06:34:07 +00:00
|
|
|
if( !out_fname.HasExt() )
|
|
|
|
out_fname.SetExt( m_params.getOutputExt() );
|
2017-08-09 17:17:26 +00:00
|
|
|
}
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2018-10-02 06:34:07 +00:00
|
|
|
if( out_fname.FileExists() && !m_params.m_overwrite )
|
2018-09-11 07:23:11 +00:00
|
|
|
{
|
2021-08-14 10:07:58 +00:00
|
|
|
ReportMessage( _( "** Output already exists. Export aborted. **\n"
|
2021-07-29 11:10:58 +00:00
|
|
|
"Enable the force overwrite flag to overwrite it." ) );
|
2018-09-11 07:23:11 +00:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-10-02 06:34:07 +00:00
|
|
|
wxString outfile = out_fname.GetFullPath();
|
2021-09-12 21:41:18 +00:00
|
|
|
KICADPCB pcb( fname.GetName() );
|
2016-09-18 02:24:04 +00:00
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
pcb.SetOrigin( m_params.m_xOrigin, m_params.m_yOrigin );
|
|
|
|
pcb.SetMinDistance( m_params.m_minDistance );
|
2021-07-29 11:10:58 +00:00
|
|
|
ReportMessage( wxString::Format( _( "Read file: '%s'\n" ), m_params.m_filename ) );
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2018-10-02 06:34:07 +00:00
|
|
|
// create the new streams to "redirect" cout and cerr output to
|
|
|
|
// msgs_from_opencascade and errors_from_opencascade
|
2018-09-20 09:05:52 +00:00
|
|
|
std::ostringstream msgs_from_opencascade;
|
2018-10-02 06:34:07 +00:00
|
|
|
std::ostringstream errors_from_opencascade;
|
2021-07-29 11:10:58 +00:00
|
|
|
STREAMBUF_SWAPPER swapper_cout( std::cout, msgs_from_opencascade );
|
|
|
|
STREAMBUF_SWAPPER swapper_cerr( std::cerr, errors_from_opencascade );
|
2018-09-20 09:05:52 +00:00
|
|
|
|
|
|
|
if( pcb.ReadFile( m_params.m_filename ) )
|
2016-09-02 10:08:40 +00:00
|
|
|
{
|
2018-09-20 09:05:52 +00:00
|
|
|
if( m_params.m_useDrillOrigin )
|
2016-09-04 07:08:56 +00:00
|
|
|
pcb.UseDrillOrigin( true );
|
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
if( m_params.m_useGridOrigin )
|
2016-09-04 07:08:56 +00:00
|
|
|
pcb.UseGridOrigin( true );
|
|
|
|
|
2016-09-02 10:08:40 +00:00
|
|
|
bool res;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2021-07-29 11:10:58 +00:00
|
|
|
ReportMessage( _( "Build STEP data\n" ) );
|
2018-10-02 06:34:07 +00:00
|
|
|
|
2021-06-08 22:46:37 +00:00
|
|
|
res = pcb.ComposePCB( m_params.m_includeVirtual, m_params.m_substModels );
|
2020-10-06 14:03:08 +00:00
|
|
|
|
|
|
|
if( !res )
|
|
|
|
{
|
2021-08-14 10:07:58 +00:00
|
|
|
ReportMessage( _( "\n** Error building STEP board model. Export aborted. **\n" ) );
|
2020-10-06 14:03:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-29 11:10:58 +00:00
|
|
|
ReportMessage( _( "Write STEP file\n" ) );
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2021-07-29 11:10:58 +00:00
|
|
|
#ifdef SUPPORTS_IGES
|
2016-09-02 10:08:40 +00:00
|
|
|
if( m_fmtIGES )
|
2018-09-11 07:23:11 +00:00
|
|
|
res = pcb.WriteIGES( outfile );
|
2016-09-02 10:08:40 +00:00
|
|
|
else
|
2021-07-29 11:10:58 +00:00
|
|
|
#endif
|
2018-09-11 07:23:11 +00:00
|
|
|
res = pcb.WriteSTEP( outfile );
|
2016-09-02 10:08:40 +00:00
|
|
|
|
|
|
|
if( !res )
|
2018-09-20 09:05:52 +00:00
|
|
|
{
|
2021-08-14 10:07:58 +00:00
|
|
|
ReportMessage( _( "\n** Error writing STEP file. **\n" ) );
|
2016-09-02 10:08:40 +00:00
|
|
|
return -1;
|
2018-09-20 09:05:52 +00:00
|
|
|
}
|
2021-09-20 00:54:33 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ReportMessage( wxString::Format( _( "\nSTEP file '%s' created.\n" ), outfile ) );
|
|
|
|
}
|
2016-09-02 10:08:40 +00:00
|
|
|
}
|
2018-07-26 12:37:44 +00:00
|
|
|
catch( const Standard_Failure& e )
|
2016-09-02 10:08:40 +00:00
|
|
|
{
|
2021-08-14 10:07:58 +00:00
|
|
|
ReportMessage( e.GetMessageString() );
|
|
|
|
ReportMessage( _( "\n** Error exporting STEP file. Export aborted. **\n" ) );
|
2016-09-02 10:08:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
catch( ... )
|
|
|
|
{
|
2021-08-14 10:07:58 +00:00
|
|
|
ReportMessage( _( "\n** Error exporting STEP file. Export aborted. **\n" ) );
|
2016-09-02 10:08:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2021-09-20 00:54:33 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ReportMessage( _( "\n** Error reading kicad_pcb file. **\n" ) );
|
|
|
|
return -1;
|
|
|
|
}
|
2016-09-02 10:08:40 +00:00
|
|
|
|
2018-10-02 06:34:07 +00:00
|
|
|
wxString msgs, errs;
|
|
|
|
msgs << msgs_from_opencascade.str();
|
|
|
|
ReportMessage( msgs );
|
|
|
|
|
|
|
|
errs << errors_from_opencascade.str();
|
|
|
|
ReportMessage( errs );
|
|
|
|
|
|
|
|
// Check the output log for an indication of success
|
|
|
|
bool success = msgs.Contains( "Done" );
|
2018-09-20 09:05:52 +00:00
|
|
|
wxString msg;
|
|
|
|
|
2018-10-02 06:34:07 +00:00
|
|
|
if( !errs.IsEmpty() ) // Any troubles?
|
|
|
|
{
|
|
|
|
if( !success )
|
2021-07-06 20:22:06 +00:00
|
|
|
{
|
2021-07-29 11:10:58 +00:00
|
|
|
msg = _( "Unable to create STEP file.\n"
|
|
|
|
"Check that the board has a valid outline and models." );
|
2021-07-06 20:22:06 +00:00
|
|
|
}
|
2018-10-02 06:34:07 +00:00
|
|
|
else
|
|
|
|
{
|
2021-07-29 11:10:58 +00:00
|
|
|
msg = _( "STEP file has been created, but there are warnings." );
|
2018-10-02 06:34:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReportMessage( msg );
|
2018-09-20 09:05:52 +00:00
|
|
|
|
2016-09-02 10:08:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-09-11 07:22:10 +00:00
|
|
|
|
|
|
|
|
2018-09-20 09:05:52 +00:00
|
|
|
wxString KICAD2MCAD_PRMS::getOutputExt() const
|
2018-09-11 07:22:10 +00:00
|
|
|
{
|
|
|
|
#ifdef SUPPORTS_IGES
|
|
|
|
if( m_fmtIGES )
|
|
|
|
return wxString( "igs" );
|
|
|
|
else
|
|
|
|
#endif
|
2018-10-02 06:34:07 +00:00
|
|
|
return wxString( "step" );
|
2018-09-11 07:22:10 +00:00
|
|
|
}
|
2021-09-11 16:40:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
KICAD2STEP::KICAD2STEP( KICAD2MCAD_PRMS aParams ) : m_params( aParams ), m_panel( nullptr )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int KICAD2STEP::Run()
|
|
|
|
{
|
|
|
|
// create the main application window
|
|
|
|
KICAD2STEP_FRAME* frame = new KICAD2STEP_FRAME( "Kicad2step" );
|
|
|
|
|
|
|
|
m_panel = frame->m_panelKicad2Step;
|
|
|
|
m_panel->m_params = m_params;
|
|
|
|
|
|
|
|
// and show it (a wxFrame is not shown when created initially)
|
|
|
|
frame->Show( true );
|
|
|
|
frame->Iconize( false );
|
|
|
|
|
|
|
|
openPanel = m_panel;
|
|
|
|
|
|
|
|
int diag = m_panel->RunConverter();
|
|
|
|
|
|
|
|
openPanel = nullptr;
|
|
|
|
|
|
|
|
return diag;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KICAD2STEP::ReportMessage( const wxString& aMessage )
|
|
|
|
{
|
|
|
|
m_panel->AppendMessage( aMessage );
|
|
|
|
}
|