KiCad2Step code cleaning.
This commit is contained in:
parent
934b6e4cdc
commit
d36fbb864f
|
@ -32,6 +32,11 @@
|
|||
#include "pluginldr.h"
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable plugin loader trace output.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* const tracePluginLoader = wxT( "KICAD_PLUGIN_LOADER" );
|
||||
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ class KICAD2MCAD_APP : public wxApp
|
|||
public:
|
||||
KICAD2MCAD_APP() :
|
||||
wxApp(),
|
||||
m_frame( nullptr ),
|
||||
m_Panel( nullptr )
|
||||
m_Panel( nullptr ),
|
||||
m_frame( nullptr )
|
||||
{}
|
||||
|
||||
virtual bool OnInit() override;
|
||||
|
@ -53,24 +53,24 @@ public:
|
|||
virtual void OnInitCmdLine(wxCmdLineParser& parser) override;
|
||||
virtual bool OnCmdLineParsed(wxCmdLineParser& parser) override;
|
||||
|
||||
private:
|
||||
KICAD2STEP_FRAME * m_frame;
|
||||
KICAD2MCAD_PRMS m_params;
|
||||
|
||||
public:
|
||||
PANEL_KICAD2STEP* m_Panel;
|
||||
|
||||
private:
|
||||
KICAD2STEP_FRAME* m_frame;
|
||||
KICAD2MCAD_PRMS m_params;
|
||||
};
|
||||
|
||||
wxIMPLEMENT_APP(KICAD2MCAD_APP);
|
||||
|
||||
wxIMPLEMENT_APP( KICAD2MCAD_APP );
|
||||
|
||||
|
||||
class KICAD2STEP_FRAME : public KICAD2STEP_FRAME_BASE
|
||||
{
|
||||
public:
|
||||
KICAD2STEP_FRAME(const wxString& title);
|
||||
|
||||
private:
|
||||
KICAD2STEP_FRAME( const wxString& title );
|
||||
};
|
||||
|
||||
|
||||
KICAD2MCAD_PRMS::KICAD2MCAD_PRMS()
|
||||
{
|
||||
#ifdef SUPPORTS_IGES
|
||||
|
@ -95,38 +95,40 @@ void ReportMessage( const wxString& aMessage )
|
|||
}
|
||||
|
||||
|
||||
static const wxCmdLineEntryDesc cmdLineDesc[] =
|
||||
{
|
||||
{ wxCMD_LINE_PARAM, NULL, NULL, _( "pcb_filename" ).mb_str(),
|
||||
wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
|
||||
{ wxCMD_LINE_OPTION, "o", "output-filename", _( "output filename" ).mb_str(),
|
||||
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
static const wxCmdLineEntryDesc cmdLineDesc[] = {
|
||||
{ wxCMD_LINE_PARAM, NULL, NULL, _( "pcb_filename" ).mb_str(), wxCMD_LINE_VAL_STRING,
|
||||
wxCMD_LINE_OPTION_MANDATORY },
|
||||
{ wxCMD_LINE_OPTION, "o", "output-filename", _( "output filename" ).mb_str(),
|
||||
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
|
||||
#ifdef SUPPORTS_IGES
|
||||
{ wxCMD_LINE_SWITCH, "fmt-iges", NULL, _("IGES output (default STEP)").mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, "fmt-iges", NULL, _( "IGES output (default STEP)" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
#endif
|
||||
{ wxCMD_LINE_SWITCH, "f", "force", _( "overwrite output file" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "drill-origin", _( "Use Drill Origin for output origin" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "grid-origin", _( "Use Grid Origin for output origin" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_OPTION, NULL, "user-origin",
|
||||
_( "User-specified output origin ex. 1x1in, 1x1inch, 25.4x25.4mm (default mm)" ).mb_str(),
|
||||
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "no-virtual",
|
||||
_( "Exclude 3D models for components with 'virtual' attribute" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "subst-models",
|
||||
_( "Substitute STEP or IGS models with the same name in place of VRML models" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_OPTION, NULL, "min-distance",
|
||||
_( "Minimum distance between points to treat them as separate ones (default 0.01 mm)" ).mb_str(),
|
||||
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, "h", NULL, _( "display this message" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
|
||||
{ wxCMD_LINE_NONE, nullptr, nullptr, nullptr, wxCMD_LINE_VAL_NONE, 0 }
|
||||
};
|
||||
|
||||
{ wxCMD_LINE_SWITCH, "f", "force", _( "overwrite output file" ).mb_str(), wxCMD_LINE_VAL_NONE,
|
||||
wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "drill-origin", _( "Use Drill Origin for output origin" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "grid-origin", _( "Use Grid Origin for output origin" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_OPTION, NULL, "user-origin",
|
||||
_( "User-specified output origin ex. 1x1in, 1x1inch, 25.4x25.4mm (default mm)" ).mb_str(),
|
||||
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "no-virtual",
|
||||
_( "Exclude 3D models for components with 'virtual' attribute" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, NULL, "subst-models",
|
||||
_( "Substitute STEP or IGS models with the same name in place of VRML models" ).mb_str(),
|
||||
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_OPTION, NULL, "min-distance",
|
||||
_( "Minimum distance between points to treat them as separate ones (default 0.01 mm)" )
|
||||
.mb_str(),
|
||||
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||
{ wxCMD_LINE_SWITCH, "h", NULL, _( "display this message" ).mb_str(), wxCMD_LINE_VAL_NONE,
|
||||
wxCMD_LINE_OPTION_HELP },
|
||||
{ wxCMD_LINE_NONE, nullptr, nullptr, nullptr, wxCMD_LINE_VAL_NONE, 0 }
|
||||
};
|
||||
|
||||
|
||||
bool KICAD2MCAD_APP::OnInit()
|
||||
|
@ -157,8 +159,8 @@ int KICAD2MCAD_APP::OnRun()
|
|||
}
|
||||
|
||||
|
||||
KICAD2STEP_FRAME::KICAD2STEP_FRAME(const wxString& title)
|
||||
: KICAD2STEP_FRAME_BASE(NULL, wxID_ANY, title)
|
||||
KICAD2STEP_FRAME::KICAD2STEP_FRAME( const wxString& title ) :
|
||||
KICAD2STEP_FRAME_BASE( NULL, wxID_ANY, title )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -167,7 +169,6 @@ void KICAD2MCAD_APP::OnInitCmdLine( wxCmdLineParser& parser )
|
|||
{
|
||||
parser.SetDesc( cmdLineDesc );
|
||||
parser.SetSwitchChars( "-" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -178,8 +179,8 @@ PANEL_KICAD2STEP::PANEL_KICAD2STEP( wxWindow* parent, wxWindowID id, const wxPoi
|
|||
wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_tcMessages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_MULTILINE|wxTE_READONLY );
|
||||
bSizer->Add( m_tcMessages, 1, wxALL|wxEXPAND, 5 );
|
||||
wxTE_MULTILINE | wxTE_READONLY );
|
||||
bSizer->Add( m_tcMessages, 1, wxALL | wxEXPAND, 5 );
|
||||
|
||||
SetSizer( bSizer );
|
||||
Layout();
|
||||
|
@ -196,10 +197,10 @@ void PANEL_KICAD2STEP::AppendMessage( const wxString& aMessage )
|
|||
|
||||
bool KICAD2MCAD_APP::OnCmdLineParsed( wxCmdLineParser& parser )
|
||||
{
|
||||
#ifdef SUPPORTS_IGES
|
||||
#ifdef SUPPORTS_IGES
|
||||
if( parser.Found( "fmt-iges" ) )
|
||||
m_fmtIGES = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if( parser.Found( "f" ) )
|
||||
m_params.m_overwrite = true;
|
||||
|
@ -265,7 +266,6 @@ bool KICAD2MCAD_APP::OnCmdLineParsed( wxCmdLineParser& parser )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if( parser.Found( "min-distance", &tstr ) )
|
||||
{
|
||||
std::istringstream istr;
|
||||
|
@ -319,20 +319,21 @@ bool KICAD2MCAD_APP::OnCmdLineParsed( wxCmdLineParser& parser )
|
|||
class STREAMBUF_SWAPPER
|
||||
{
|
||||
public:
|
||||
STREAMBUF_SWAPPER( std::ostream & orig, std::ostream & replacement )
|
||||
: m_buf( orig.rdbuf() ), m_str( orig )
|
||||
STREAMBUF_SWAPPER( std::ostream& orig, std::ostream& replacement ) :
|
||||
m_buf( orig.rdbuf() ),
|
||||
m_str( orig )
|
||||
{
|
||||
orig.rdbuf( replacement.rdbuf() );
|
||||
}
|
||||
|
||||
~STREAMBUF_SWAPPER()
|
||||
{
|
||||
m_str.rdbuf( m_buf);
|
||||
m_str.rdbuf( m_buf );
|
||||
}
|
||||
|
||||
private:
|
||||
std::streambuf * m_buf;
|
||||
std::ostream & m_str;
|
||||
std::streambuf* m_buf;
|
||||
std::ostream& m_str;
|
||||
};
|
||||
|
||||
|
||||
|
@ -342,7 +343,7 @@ int PANEL_KICAD2STEP::RunConverter()
|
|||
|
||||
if( !fname.FileExists() )
|
||||
{
|
||||
wxMessageBox( wxString::Format( "No such file: %s", m_params.m_filename ) );
|
||||
wxMessageBox( wxString::Format( _( "No such file: %s" ), m_params.m_filename ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -365,8 +366,8 @@ int PANEL_KICAD2STEP::RunConverter()
|
|||
|
||||
if( out_fname.FileExists() && !m_params.m_overwrite )
|
||||
{
|
||||
ReportMessage( "** Output already exists.\n"
|
||||
"Enable the force overwrite flag to overwrite it." );
|
||||
ReportMessage( _( "** Output already exists.\n"
|
||||
"Enable the force overwrite flag to overwrite it." ) );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -376,14 +377,14 @@ int PANEL_KICAD2STEP::RunConverter()
|
|||
|
||||
pcb.SetOrigin( m_params.m_xOrigin, m_params.m_yOrigin );
|
||||
pcb.SetMinDistance( m_params.m_minDistance );
|
||||
ReportMessage( wxString::Format( "Read: %s\n", m_params.m_filename ) );
|
||||
ReportMessage( wxString::Format( _( "Read file: '%s'\n" ), m_params.m_filename ) );
|
||||
|
||||
// create the new streams to "redirect" cout and cerr output to
|
||||
// msgs_from_opencascade and errors_from_opencascade
|
||||
std::ostringstream msgs_from_opencascade;
|
||||
std::ostringstream errors_from_opencascade;
|
||||
STREAMBUF_SWAPPER swapper_cout(std::cout, msgs_from_opencascade);
|
||||
STREAMBUF_SWAPPER swapper_cerr(std::cerr, errors_from_opencascade);
|
||||
STREAMBUF_SWAPPER swapper_cout( std::cout, msgs_from_opencascade );
|
||||
STREAMBUF_SWAPPER swapper_cerr( std::cerr, errors_from_opencascade );
|
||||
|
||||
if( pcb.ReadFile( m_params.m_filename ) )
|
||||
{
|
||||
|
@ -397,44 +398,44 @@ int PANEL_KICAD2STEP::RunConverter()
|
|||
|
||||
try
|
||||
{
|
||||
ReportMessage( "Build STEP data\n" );
|
||||
ReportMessage( _( "Build STEP data\n" ) );
|
||||
|
||||
res = pcb.ComposePCB( m_params.m_includeVirtual, m_params.m_substModels );
|
||||
|
||||
if( !res )
|
||||
{
|
||||
ReportMessage( "\n**Error building STEP board model. Abort export **\n" );
|
||||
ReportMessage( _( "\n**Error building STEP board model. Abort export **\n" ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
ReportMessage( "Write STEP file\n" );
|
||||
ReportMessage( _( "Write STEP file\n" ) );
|
||||
|
||||
#ifdef SUPPORTS_IGES
|
||||
#ifdef SUPPORTS_IGES
|
||||
if( m_fmtIGES )
|
||||
res = pcb.WriteIGES( outfile );
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
res = pcb.WriteSTEP( outfile );
|
||||
|
||||
if( !res )
|
||||
{
|
||||
ReportMessage( "\nError Write STEP file\n" );
|
||||
ReportMessage( _( "\nError Write STEP file\n" ) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch( const Standard_Failure& e )
|
||||
{
|
||||
wxString err = e.GetMessageString();
|
||||
wxMessageBox( err, "Export Error" );
|
||||
wxMessageBox( err, _( "Export Error" ) );
|
||||
|
||||
ReportMessage( wxString::Format( "\nExport Error: %s\n", err ) );
|
||||
ReportMessage( "\n*** Abort export ***\n" );
|
||||
ReportMessage( wxString::Format( _( "\nExport Error: %s\n" ), err ) );
|
||||
ReportMessage( _( "\n*** Abort export ***\n" ) );
|
||||
return -1;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
wxMessageBox( "(no exception information)", "Unknown error" );
|
||||
ReportMessage( "\nUnknown error\n*** Abort export ***\n" );
|
||||
wxMessageBox( _( "(no exception information)" ), _( "Unknown error" ) );
|
||||
ReportMessage( _( "\nUnknown error\n*** Abort export ***\n" ) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -443,7 +444,7 @@ int PANEL_KICAD2STEP::RunConverter()
|
|||
msgs << msgs_from_opencascade.str();
|
||||
ReportMessage( msgs );
|
||||
|
||||
ReportMessage( wxString::Format( "\nStep file %s created\n\n", outfile ) );
|
||||
ReportMessage( wxString::Format( _( "\nStep file '%s' created\n\n" ), outfile ) );
|
||||
|
||||
errs << errors_from_opencascade.str();
|
||||
ReportMessage( errs );
|
||||
|
@ -456,17 +457,17 @@ int PANEL_KICAD2STEP::RunConverter()
|
|||
{
|
||||
if( !success )
|
||||
{
|
||||
msg = "Unable to create STEP file.\n"
|
||||
"Check that the board has a valid outline and models.";
|
||||
msg = _( "Unable to create STEP file.\n"
|
||||
"Check that the board has a valid outline and models." );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "STEP file has been created, but there are warnings.";
|
||||
msg = _( "STEP file has been created, but there are warnings." );
|
||||
}
|
||||
}
|
||||
else // No error messages: the file is expected OK
|
||||
{
|
||||
msg.Printf( "STEP file:\n%s\nhas been created successfully.", outfile );
|
||||
msg.Printf( _( "STEP file:\n%s\nhas been created successfully." ), outfile );
|
||||
}
|
||||
|
||||
ReportMessage( msg );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part kicad2mcad
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2021 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
|
||||
|
@ -49,12 +49,21 @@
|
|||
#define ERRFLG_RELPATH (2)
|
||||
#define ERRFLG_ENVPATH (4)
|
||||
|
||||
#define MASK_3D_RESOLVER "3D_RESOLVER"
|
||||
|
||||
/**
|
||||
* Flag to enable plugin loader trace output.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* const trace3dResolver = wxT( "KICAD_3D_RESOLVER" );
|
||||
|
||||
|
||||
static std::mutex mutex3D_resolver;
|
||||
|
||||
|
||||
static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult );
|
||||
|
||||
|
||||
S3D_RESOLVER::S3D_RESOLVER()
|
||||
{
|
||||
m_errflags = 0;
|
||||
|
@ -116,15 +125,9 @@ bool S3D_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChanged )
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] changed project dir to ";
|
||||
ostr << m_Paths.front().m_Pathexp.ToUTF8();
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * [INFO] changed project dir to '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, m_Paths.front().m_Pathexp );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -244,15 +247,10 @@ bool S3D_RESOLVER::createPathList( void )
|
|||
return false;
|
||||
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_RESOLVER, " * [3D model] search paths:\n" );
|
||||
std::list< SEARCH_PATH >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< SEARCH_PATH >::const_iterator ePL = m_Paths.end();
|
||||
wxLogTrace( trace3dResolver, " * [3D model] search paths:\n" );
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
wxLogTrace( MASK_3D_RESOLVER, " + '%s'\n", (*sPL).m_Pathexp.ToUTF8() );
|
||||
++sPL;
|
||||
}
|
||||
for( const auto searchPath : m_Paths )
|
||||
wxLogTrace( trace3dResolver, " + '%s'\n", searchPath.m_Pathexp );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -409,7 +407,7 @@ wxString S3D_RESOLVER::ResolvePath( const wxString& aFileName )
|
|||
wxString errmsg = "[3D File Resolver] No such path";
|
||||
errmsg.append( "\n" );
|
||||
errmsg.append( tname );
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", errmsg.ToUTF8() );
|
||||
wxLogTrace( trace3dResolver, "%s\n", errmsg.ToUTF8() );
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
|
@ -443,10 +441,9 @@ wxString S3D_RESOLVER::ResolvePath( const wxString& aFileName )
|
|||
if( !( m_errflags & ERRFLG_ALIAS ) )
|
||||
{
|
||||
m_errflags |= ERRFLG_ALIAS;
|
||||
wxString errmsg = "[3D File Resolver] No such path; ensure the path alias is defined";
|
||||
errmsg.append( "\n" );
|
||||
errmsg.append( tname.substr( 1 ) );
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", errmsg.ToUTF8() );
|
||||
wxLogTrace( trace3dResolver,
|
||||
wxT( "[3D File Resolver] No such path; ensure the path alias is defined %s" ),
|
||||
tname.substr( 1 ) );
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
|
@ -476,7 +473,8 @@ bool S3D_RESOLVER::addPath( const SEARCH_PATH& aPath )
|
|||
if( !path.DirExists() )
|
||||
{
|
||||
// suppress the message if the missing pathvar is the legacy KICAD6_3DMODEL_DIR variable
|
||||
if( aPath.m_Pathvar != "${KICAD6_3DMODEL_DIR}" && aPath.m_Pathvar != "$(KICAD6_3DMODEL_DIR)" )
|
||||
if( aPath.m_Pathvar != "${KICAD6_3DMODEL_DIR}" &&
|
||||
aPath.m_Pathvar != "$(KICAD6_3DMODEL_DIR)" )
|
||||
{
|
||||
wxString msg = _( "The given path does not exist" );
|
||||
msg.append( "\n" );
|
||||
|
@ -541,12 +539,10 @@ bool S3D_RESOLVER::readPathList( void )
|
|||
|
||||
if( !wxFileName::Exists( cfgname ) )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "no 3D configuration file";
|
||||
ostr << " * " << errmsg.ToUTF8() << " '";
|
||||
ostr << cfgname.ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:d\n"
|
||||
" * no 3D configuration file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgname );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -554,11 +550,10 @@ bool S3D_RESOLVER::readPathList( void )
|
|||
|
||||
if( !cfgFile.is_open() )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "Could not open configuration file";
|
||||
ostr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * Could not open configuration file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgname );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -729,8 +724,7 @@ wxString S3D_RESOLVER::ShortenPath( const wxString& aFullPathName )
|
|||
|
||||
while( sL != eL )
|
||||
{
|
||||
// undefined paths do not participate in the
|
||||
// file name shortening procedure
|
||||
// undefined paths do not participate in the file name shortening procedure.
|
||||
if( sL->m_Pathexp.empty() )
|
||||
{
|
||||
++sL;
|
||||
|
@ -793,8 +787,7 @@ const std::list< SEARCH_PATH >* S3D_RESOLVER::GetPaths( void )
|
|||
}
|
||||
|
||||
|
||||
bool S3D_RESOLVER::SplitAlias( const wxString& aFileName,
|
||||
wxString& anAlias, wxString& aRelPath )
|
||||
bool S3D_RESOLVER::SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath )
|
||||
{
|
||||
anAlias.clear();
|
||||
aRelPath.clear();
|
||||
|
@ -823,11 +816,9 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
|||
|
||||
if( aIndex >= aString.size() )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "bad Hollerith string on line";
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * Bad Hollerith string in line \"%s\"" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aString );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -836,11 +827,9 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
|||
|
||||
if( std::string::npos == i2 )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "missing opening quote mark in config file";
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * missing opening quote mark in line \"%s\"" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aString );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -849,11 +838,9 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
|||
|
||||
if( i2 >= aString.size() )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "invalid entry (unexpected end of line)";
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * unexpected end of line in line \"%s\"" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aString );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -865,11 +852,9 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
|||
|
||||
if( tnum.empty() || aString[i2++] != ':' )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "bad Hollerith string on line";
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * Bad Hollerith string in line \"%s\"" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aString );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -881,11 +866,9 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
|||
|
||||
if( (i2 + nchars) >= aString.size() )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "invalid entry (unexpected end of line)";
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * unexpected end of line in line \"%s\"\n" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aString );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -898,11 +881,9 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
|||
|
||||
if( i2 >= aString.size() || aString[i2] != '"' )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "missing closing quote mark in config file";
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
|
||||
wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n"
|
||||
" * missing closing quote mark in line \"%s\"" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aString );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2021 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
|
||||
|
@ -38,53 +39,52 @@
|
|||
|
||||
namespace S3D
|
||||
{
|
||||
|
||||
struct rsort_wxString
|
||||
struct rsort_wxString
|
||||
{
|
||||
bool operator() (const wxString& strA, const wxString& strB ) const
|
||||
{
|
||||
bool operator() (const wxString& strA, const wxString& strB ) const
|
||||
// sort a wxString using the reverse character order; for 3d model
|
||||
// filenames this will typically be a much faster operation than
|
||||
// a normal alphabetic sort
|
||||
wxString::const_reverse_iterator sA = strA.rbegin();
|
||||
wxString::const_reverse_iterator eA = strA.rend();
|
||||
|
||||
wxString::const_reverse_iterator sB = strB.rbegin();
|
||||
wxString::const_reverse_iterator eB = strB.rend();
|
||||
|
||||
if( strA.empty() )
|
||||
{
|
||||
// sort a wxString using the reverse character order; for 3d model
|
||||
// filenames this will typically be a much faster operation than
|
||||
// a normal alphabetic sort
|
||||
wxString::const_reverse_iterator sA = strA.rbegin();
|
||||
wxString::const_reverse_iterator eA = strA.rend();
|
||||
|
||||
wxString::const_reverse_iterator sB = strB.rbegin();
|
||||
wxString::const_reverse_iterator eB = strB.rend();
|
||||
|
||||
if( strA.empty() )
|
||||
{
|
||||
if( strB.empty() )
|
||||
return false;
|
||||
|
||||
// note: this rule implies that a null string is first in the sort order
|
||||
return true;
|
||||
}
|
||||
|
||||
if( strB.empty() )
|
||||
return false;
|
||||
|
||||
while( sA != eA && sB != eB )
|
||||
{
|
||||
if( (*sA) == (*sB) )
|
||||
{
|
||||
++sA;
|
||||
++sB;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (*sA) < (*sB) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sB == eB )
|
||||
return false;
|
||||
|
||||
// note: this rule implies that a null string is first in the sort order
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if( strB.empty() )
|
||||
return false;
|
||||
|
||||
while( sA != eA && sB != eB )
|
||||
{
|
||||
if( (*sA) == (*sB) )
|
||||
{
|
||||
++sA;
|
||||
++sB;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (*sA) < (*sB) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sB == eB )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}; // end NAMESPACE
|
||||
|
||||
|
@ -99,128 +99,114 @@ struct SEARCH_PATH
|
|||
wxString m_Description; // description of the aliased path
|
||||
};
|
||||
|
||||
|
||||
class S3D_RESOLVER
|
||||
{
|
||||
private:
|
||||
wxString m_ConfigDir; // 3D configuration directory
|
||||
std::list< SEARCH_PATH > m_Paths; // list of base paths to search from
|
||||
// mapping of (short) file names to resolved names
|
||||
std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap;
|
||||
int m_errflags;
|
||||
wxString m_curProjDir;
|
||||
// environment variables
|
||||
std::map< wxString, wxString > m_EnvVars;
|
||||
public:
|
||||
S3D_RESOLVER();
|
||||
|
||||
/**
|
||||
* Function createPathList
|
||||
* builds the path list using available information such as
|
||||
* KICAD6_3DMODEL_DIR and the 3d_path_list configuration file. Invalid
|
||||
* paths are silently discarded and removed from the configuration
|
||||
* file.
|
||||
* Set the user's configuration directory for 3D models.
|
||||
*
|
||||
* @param aConfigDir
|
||||
* @return true if the call succeeds (directory exists).
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Set the current KiCad project directory as the first entry in the model path list.
|
||||
*
|
||||
* @param aProjDir is the current project directory.
|
||||
* @param flgChanged, if specified, is set to true if the directory actually changed.
|
||||
* @return true if the call succeeds.
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL );
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Determine the full path of the given file name.
|
||||
*
|
||||
* In the future remote files may be supported, in which case it is best to require a full
|
||||
* URI in which case #ResolvePath should check that the URI conforms to RFC-2396 and related
|
||||
* documents and copies \a aFileName into the resolved name if the URI is valid.
|
||||
*/
|
||||
wxString ResolvePath( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* Produce a relative path based on the existing search directories or returns the same path
|
||||
* if the path is not a superset of an existing search path.
|
||||
*
|
||||
* @param aFullPathName is an absolute path to shorten.
|
||||
* @return the shortened path or aFullPathName.
|
||||
*/
|
||||
wxString ShortenPath( const wxString& aFullPathName );
|
||||
|
||||
/**
|
||||
* Return a pointer to the internal path list.
|
||||
*
|
||||
* The list can be used to set up the list of search paths available to a 3D file browser.
|
||||
*
|
||||
* @return the search path list.
|
||||
*/
|
||||
const std::list< SEARCH_PATH >* GetPaths( void );
|
||||
|
||||
/**
|
||||
* Return true if the given name contains an alias and populates the string with the alias
|
||||
* and the relative path.
|
||||
*/
|
||||
bool SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath );
|
||||
|
||||
/**
|
||||
* If the path contains an alias then \a hasAlias is set true.
|
||||
*
|
||||
* @return true if the given path is a valid aliased relative path.
|
||||
*/
|
||||
bool ValidateFileName( const wxString& aFileName, bool& hasAlias );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Build the path list using available information such as KICAD6_3DMODEL_DIR and the
|
||||
* 3d_path_list configuration file.
|
||||
*
|
||||
* Invalid paths are silently discarded and removed from the configuration file.
|
||||
*
|
||||
* @return true if at least one valid path was found
|
||||
*/
|
||||
bool createPathList( void );
|
||||
|
||||
/**
|
||||
* Function addPath
|
||||
* checks that a path is valid and adds it to the search list
|
||||
* Check that \a aPath is valid and adds it to the search list.
|
||||
*
|
||||
* @param aPath is the alias set to be checked and added
|
||||
* @return true if aPath is valid
|
||||
* @param aPath is the alias set to be checked and added.
|
||||
* @return true if \a aPath is valid.
|
||||
*/
|
||||
bool addPath( const SEARCH_PATH& aPath );
|
||||
|
||||
/**
|
||||
* Function readPathList
|
||||
* reads a list of path names from a configuration file
|
||||
* Read a list of path names from a configuration file.
|
||||
*
|
||||
* @return true if a file was found and contained at least
|
||||
* one valid path
|
||||
* @return true if a file was found and contained at least one valid path.
|
||||
*/
|
||||
bool readPathList( void );
|
||||
|
||||
/**
|
||||
* Function checkEnvVarPath
|
||||
* checks the ${ENV_VAR} component of a path and adds
|
||||
* it to the resolver's path list if it is not yet in
|
||||
* the list
|
||||
* Check the ${ENV_VAR} component of a path and adds it to the resolver's path list if it
|
||||
* is not yet in the list.
|
||||
*/
|
||||
void checkEnvVarPath( const wxString& aPath );
|
||||
|
||||
wxString expandVars( const wxString& aPath );
|
||||
|
||||
public:
|
||||
S3D_RESOLVER();
|
||||
wxString m_ConfigDir; ///< 3D configuration directory.
|
||||
std::list< SEARCH_PATH > m_Paths; ///< List of base search paths.
|
||||
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* sets the user's configuration directory
|
||||
* for 3D models.
|
||||
*
|
||||
* @param aConfigDir
|
||||
* @return true if the call succeeds (directory exists)
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
///< Mapping of (short) file names to resolved names.
|
||||
std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap;
|
||||
int m_errflags;
|
||||
wxString m_curProjDir;
|
||||
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current KiCad project directory as the first
|
||||
* entry in the model path list
|
||||
*
|
||||
* @param aProjDir is the current project directory
|
||||
* @param flgChanged, if specified, is set to true if the directory actually changed
|
||||
* @return true if the call succeeds
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL );
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function ResolvePath
|
||||
* determines the full path of the given file name. In the future
|
||||
* remote files may be supported, in which case it is best to
|
||||
* require a full URI in which case ResolvePath should check that
|
||||
* the URI conforms to RFC-2396 and related documents and copies
|
||||
* aFileName into aResolvedName if the URI is valid.
|
||||
*/
|
||||
wxString ResolvePath( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* Function ShortenPath
|
||||
* produces a relative path based on the existing
|
||||
* search directories or returns the same path if
|
||||
* the path is not a superset of an existing search path.
|
||||
*
|
||||
* @param aFullPathName is an absolute path to shorten
|
||||
* @return the shortened path or aFullPathName
|
||||
*/
|
||||
wxString ShortenPath( const wxString& aFullPathName );
|
||||
|
||||
/**
|
||||
* Function GetPaths
|
||||
* returns a pointer to the internal path list; the items in:load
|
||||
*
|
||||
* the list can be used to set up the list of search paths
|
||||
* available to a 3D file browser.
|
||||
*
|
||||
* @return pointer to the internal path list
|
||||
*/
|
||||
const std::list< SEARCH_PATH >* GetPaths( void );
|
||||
|
||||
/**
|
||||
* Function SplitAlias
|
||||
* returns true if the given name contains an alias and
|
||||
* populates the string anAlias with the alias and aRelPath
|
||||
* with the relative path.
|
||||
*/
|
||||
bool SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath );
|
||||
|
||||
/**
|
||||
* Function ValidateName
|
||||
* returns true if the given path is a valid aliased relative path.
|
||||
* If the path contains an alias then hasAlias is set true.
|
||||
*/
|
||||
bool ValidateFileName( const wxString& aFileName, bool& hasAlias );
|
||||
///< Environment variables.
|
||||
std::map< wxString, wxString > m_EnvVars;
|
||||
};
|
||||
|
||||
#endif // RESOLVER_3D_H
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2021 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
|
||||
|
@ -43,6 +44,15 @@ class S3D_RESOLVER;
|
|||
|
||||
class KICADFOOTPRINT
|
||||
{
|
||||
public:
|
||||
KICADFOOTPRINT( KICADPCB* aParent );
|
||||
virtual ~KICADFOOTPRINT();
|
||||
|
||||
bool Read( SEXPR::SEXPR* aEntry );
|
||||
|
||||
bool ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
|
||||
DOUBLET aOrigin, bool aComposeVirtual = true, bool aSubstituteModels = true );
|
||||
|
||||
private:
|
||||
bool parseModel( SEXPR::SEXPR* data );
|
||||
bool parseCurve( SEXPR::SEXPR* data, CURVE_TYPE aCurveType );
|
||||
|
@ -64,15 +74,6 @@ private:
|
|||
std::vector< KICADPAD* > m_pads;
|
||||
std::vector< KICADCURVE* > m_curves;
|
||||
std::vector< KICADMODEL* > m_models;
|
||||
|
||||
public:
|
||||
KICADFOOTPRINT( KICADPCB* aParent );
|
||||
virtual ~KICADFOOTPRINT();
|
||||
|
||||
bool Read( SEXPR::SEXPR* aEntry );
|
||||
|
||||
bool ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
|
||||
DOUBLET aOrigin, bool aComposeVirtual = true, bool aSubstituteModels = true );
|
||||
};
|
||||
|
||||
#endif // KICADFOOTPRINT_H
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2021 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
|
||||
|
@ -23,7 +24,7 @@
|
|||
|
||||
/**
|
||||
* @file kicadpad.h
|
||||
* declares the PAD description object.
|
||||
* Declare the PAD description object.
|
||||
*/
|
||||
|
||||
#ifndef KICADPAD_H
|
||||
|
@ -43,10 +44,6 @@ struct KICADDRILL
|
|||
|
||||
class KICADPAD
|
||||
{
|
||||
private:
|
||||
bool m_thruhole;
|
||||
bool parseDrill( const SEXPR::SEXPR* aDrill );
|
||||
|
||||
public:
|
||||
KICADPAD();
|
||||
virtual ~KICADPAD();
|
||||
|
@ -58,9 +55,16 @@ public:
|
|||
return m_thruhole;
|
||||
}
|
||||
|
||||
private:
|
||||
bool parseDrill( const SEXPR::SEXPR* aDrill );
|
||||
|
||||
public:
|
||||
DOUBLET m_position;
|
||||
double m_rotation; // rotation (radians)
|
||||
KICADDRILL m_drill;
|
||||
|
||||
private:
|
||||
bool m_thruhole;
|
||||
};
|
||||
|
||||
#endif // KICADPAD_H
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2021 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
|
||||
|
@ -52,38 +53,6 @@ class PCBMODEL;
|
|||
|
||||
class KICADPCB
|
||||
{
|
||||
private:
|
||||
S3D_RESOLVER m_resolver;
|
||||
wxString m_filename;
|
||||
PCBMODEL* m_pcb_model;
|
||||
DOUBLET m_origin;
|
||||
DOUBLET m_gridOrigin;
|
||||
DOUBLET m_drillOrigin;
|
||||
bool m_useGridOrigin;
|
||||
bool m_useDrillOrigin;
|
||||
// set to TRUE if the origin was actually parsed
|
||||
bool m_hasGridOrigin;
|
||||
bool m_hasDrillOrigin;
|
||||
// minimum distance between points to treat them as separate entities (mm)
|
||||
double m_minDistance;
|
||||
// the names of layers in use, and the internal layer ID
|
||||
std::map<std::string, int> m_layersNames;
|
||||
|
||||
// PCB parameters/entities
|
||||
double m_thickness;
|
||||
std::vector<KICADFOOTPRINT*> m_footprints;
|
||||
std::vector<KICADCURVE*> m_curves;
|
||||
|
||||
bool parsePCB( SEXPR::SEXPR* data );
|
||||
bool parseGeneral( SEXPR::SEXPR* data );
|
||||
bool parseSetup( SEXPR::SEXPR* data );
|
||||
bool parseLayers( SEXPR::SEXPR* data );
|
||||
bool parseModule( SEXPR::SEXPR* data );
|
||||
bool parseCurve( SEXPR::SEXPR* data, CURVE_TYPE aCurveType );
|
||||
bool parseRect( SEXPR::SEXPR* data );
|
||||
bool parsePolygon( SEXPR::SEXPR* data );
|
||||
|
||||
|
||||
public:
|
||||
KICADPCB();
|
||||
virtual ~KICADPCB();
|
||||
|
@ -114,9 +83,44 @@ public:
|
|||
bool ReadFile( const wxString& aFileName );
|
||||
bool ComposePCB( bool aComposeVirtual = true, bool aSubstituteModels = true );
|
||||
bool WriteSTEP( const wxString& aFileName );
|
||||
#ifdef SUPPORTS_IGES
|
||||
|
||||
#ifdef SUPPORTS_IGES
|
||||
bool WriteIGES( const wxString& aFileName );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool parsePCB( SEXPR::SEXPR* data );
|
||||
bool parseGeneral( SEXPR::SEXPR* data );
|
||||
bool parseSetup( SEXPR::SEXPR* data );
|
||||
bool parseLayers( SEXPR::SEXPR* data );
|
||||
bool parseModule( SEXPR::SEXPR* data );
|
||||
bool parseCurve( SEXPR::SEXPR* data, CURVE_TYPE aCurveType );
|
||||
bool parseRect( SEXPR::SEXPR* data );
|
||||
bool parsePolygon( SEXPR::SEXPR* data );
|
||||
|
||||
S3D_RESOLVER m_resolver;
|
||||
wxString m_filename;
|
||||
PCBMODEL* m_pcb_model;
|
||||
DOUBLET m_origin;
|
||||
DOUBLET m_gridOrigin;
|
||||
DOUBLET m_drillOrigin;
|
||||
bool m_useGridOrigin;
|
||||
bool m_useDrillOrigin;
|
||||
|
||||
// set to TRUE if the origin was actually parsed
|
||||
bool m_hasGridOrigin;
|
||||
bool m_hasDrillOrigin;
|
||||
|
||||
// minimum distance between points to treat them as separate entities (mm)
|
||||
double m_minDistance;
|
||||
|
||||
// the names of layers in use, and the internal layer ID
|
||||
std::map<std::string, int> m_layersNames;
|
||||
|
||||
// PCB parameters/entities
|
||||
double m_thickness;
|
||||
std::vector<KICADFOOTPRINT*> m_footprints;
|
||||
std::vector<KICADCURVE*> m_curves;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -85,17 +85,21 @@
|
|||
|
||||
static constexpr double USER_PREC = 1e-4;
|
||||
static constexpr double USER_ANGLE_PREC = 1e-6;
|
||||
|
||||
// minimum PCB thickness in mm (2 microns assumes a very thin polyimide film)
|
||||
static constexpr double THICKNESS_MIN = 0.002;
|
||||
|
||||
// default PCB thickness in mm
|
||||
static constexpr double THICKNESS_DEFAULT = 1.6;
|
||||
|
||||
// nominal offset from the board
|
||||
static constexpr double BOARD_OFFSET = 0.05;
|
||||
|
||||
// min. length**2 below which 2 points are considered coincident
|
||||
static constexpr double MIN_LENGTH2 = MIN_DISTANCE * MIN_DISTANCE;
|
||||
|
||||
static void getEndPoints( const KICADCURVE& aCurve, double& spx0, double& spy0,
|
||||
double& epx0, double& epy0 )
|
||||
double& epx0, double& epy0 )
|
||||
{
|
||||
if( CURVE_ARC == aCurve.m_form )
|
||||
{
|
||||
|
@ -111,9 +115,9 @@ static void getEndPoints( const KICADCURVE& aCurve, double& spx0, double& spy0,
|
|||
spy0 = aCurve.m_start.y;
|
||||
epx0 = aCurve.m_end.x;
|
||||
epy0 = aCurve.m_end.y;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void getCurveEndPoint( const KICADCURVE& aCurve, DOUBLET& aEndPoint )
|
||||
{
|
||||
if( CURVE_CIRCLE == aCurve.m_form )
|
||||
|
@ -129,7 +133,6 @@ static void getCurveEndPoint( const KICADCURVE& aCurve, DOUBLET& aEndPoint )
|
|||
// assume a line
|
||||
aEndPoint.x = aCurve.m_end.x;
|
||||
aEndPoint.y = aCurve.m_end.y;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -154,8 +157,6 @@ static void reverseCurve( KICADCURVE& aCurve )
|
|||
std::swap( aCurve.m_end, aCurve.m_ep );
|
||||
std::swap( aCurve.m_endangle, aCurve.m_startangle );
|
||||
aCurve.m_angle = -aCurve.m_angle;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -252,17 +253,15 @@ PCBMODEL::PCBMODEL()
|
|||
m_minx = 1.0e10; // absurdly large number; any valid PCB X value will be smaller
|
||||
m_mincurve = m_curves.end();
|
||||
BRepBuilderAPI::Precision( MIN_DISTANCE );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PCBMODEL::~PCBMODEL()
|
||||
{
|
||||
m_doc->Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// add an outline segment
|
||||
|
||||
bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve )
|
||||
{
|
||||
if( NULL == aCurve || LAYER_EDGE != aCurve->m_layer || CURVE_NONE == aCurve->m_form )
|
||||
|
@ -330,7 +329,8 @@ bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve )
|
|||
if( rad < m_minDistance2 )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( " * AddOutlineSegment() rejected an arc with equivalent end points, %s\n",
|
||||
msg.Printf( " * AddOutlineSegment() rejected an arc with equivalent end "
|
||||
"points, %s\n",
|
||||
aCurve->Describe() );
|
||||
ReportMessage( msg );
|
||||
return false;
|
||||
|
@ -343,124 +343,122 @@ bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve )
|
|||
// check if this curve has the current leftmost feature
|
||||
switch( aCurve->m_form )
|
||||
{
|
||||
case CURVE_LINE:
|
||||
if( aCurve->m_start.x < m_minx )
|
||||
case CURVE_LINE:
|
||||
if( aCurve->m_start.x < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_start.x;
|
||||
m_mincurve = --( m_curves.end() );
|
||||
}
|
||||
|
||||
if( aCurve->m_end.x < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_end.x;
|
||||
m_mincurve = --( m_curves.end() );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CURVE_CIRCLE:
|
||||
do
|
||||
{
|
||||
double dx = aCurve->m_start.x - aCurve->m_radius;
|
||||
|
||||
if( dx < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_start.x;
|
||||
m_mincurve = --(m_curves.end());
|
||||
m_minx = dx;
|
||||
m_mincurve = --( m_curves.end() );
|
||||
}
|
||||
} while( 0 );
|
||||
|
||||
break;
|
||||
|
||||
case CURVE_ARC:
|
||||
do
|
||||
{
|
||||
double dx0 = aCurve->m_end.x - aCurve->m_start.x;
|
||||
double dy0 = aCurve->m_end.y - aCurve->m_start.y;
|
||||
int q0; // quadrant of start point
|
||||
|
||||
if( dx0 > 0.0 && dy0 >= 0.0 )
|
||||
q0 = 1;
|
||||
else if( dx0 <= 0.0 && dy0 > 0.0 )
|
||||
q0 = 2;
|
||||
else if( dx0 < 0.0 && dy0 <= 0.0 )
|
||||
q0 = 3;
|
||||
else
|
||||
q0 = 4;
|
||||
|
||||
double dx1 = aCurve->m_ep.x - aCurve->m_start.x;
|
||||
double dy1 = aCurve->m_ep.y - aCurve->m_start.y;
|
||||
int q1; // quadrant of end point
|
||||
|
||||
if( dx1 > 0.0 && dy1 >= 0.0 )
|
||||
q1 = 1;
|
||||
else if( dx1 <= 0.0 && dy1 > 0.0 )
|
||||
q1 = 2;
|
||||
else if( dx1 < 0.0 && dy1 <= 0.0 )
|
||||
q1 = 3;
|
||||
else
|
||||
q1 = 4;
|
||||
|
||||
// calculate x0, y0 for the start point on a CCW arc
|
||||
double x0 = aCurve->m_end.x;
|
||||
double x1 = aCurve->m_ep.x;
|
||||
|
||||
if( aCurve->m_angle < 0.0 )
|
||||
{
|
||||
std::swap( q0, q1 );
|
||||
std::swap( x0, x1 );
|
||||
}
|
||||
|
||||
if( aCurve->m_end.x < m_minx )
|
||||
double minx;
|
||||
|
||||
if( ( q0 <= 2 && q1 >= 3 ) || ( q0 >= 3 && x0 > x1 ) )
|
||||
minx = aCurve->m_start.x - aCurve->m_radius;
|
||||
else
|
||||
minx = std::min( x0, x1 );
|
||||
|
||||
if( minx < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_end.x;
|
||||
m_mincurve = --(m_curves.end());
|
||||
m_minx = minx;
|
||||
m_mincurve = --( m_curves.end() );
|
||||
}
|
||||
|
||||
break;
|
||||
} while( 0 );
|
||||
|
||||
case CURVE_CIRCLE:
|
||||
do
|
||||
{
|
||||
double dx = aCurve->m_start.x - aCurve->m_radius;
|
||||
break;
|
||||
|
||||
if( dx < m_minx )
|
||||
{
|
||||
m_minx = dx;
|
||||
m_mincurve = --(m_curves.end());
|
||||
}
|
||||
} while( 0 );
|
||||
case CURVE_BEZIER:
|
||||
if( aCurve->m_start.x < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_start.x;
|
||||
m_mincurve = --( m_curves.end() );
|
||||
}
|
||||
|
||||
break;
|
||||
if( aCurve->m_end.x < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_end.x;
|
||||
m_mincurve = --( m_curves.end() );
|
||||
}
|
||||
|
||||
case CURVE_ARC:
|
||||
do
|
||||
{
|
||||
double dx0 = aCurve->m_end.x - aCurve->m_start.x;
|
||||
double dy0 = aCurve->m_end.y - aCurve->m_start.y;
|
||||
int q0; // quadrant of start point
|
||||
break;
|
||||
|
||||
if( dx0 > 0.0 && dy0 >= 0.0 )
|
||||
q0 = 1;
|
||||
else if( dx0 <= 0.0 && dy0 > 0.0 )
|
||||
q0 = 2;
|
||||
else if( dx0 < 0.0 && dy0 <= 0.0 )
|
||||
q0 = 3;
|
||||
else
|
||||
q0 = 4;
|
||||
default:
|
||||
// unexpected curve type
|
||||
do
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( " * AddOutlineSegment() unsupported curve type: %d\n", aCurve->m_form );
|
||||
ReportMessage( msg );
|
||||
} while( 0 );
|
||||
|
||||
double dx1 = aCurve->m_ep.x - aCurve->m_start.x;
|
||||
double dy1 = aCurve->m_ep.y - aCurve->m_start.y;
|
||||
int q1; // quadrant of end point
|
||||
|
||||
if( dx1 > 0.0 && dy1 >= 0.0 )
|
||||
q1 = 1;
|
||||
else if( dx1 <= 0.0 && dy1 > 0.0 )
|
||||
q1 = 2;
|
||||
else if( dx1 < 0.0 && dy1 <= 0.0 )
|
||||
q1 = 3;
|
||||
else
|
||||
q1 = 4;
|
||||
|
||||
// calculate x0, y0 for the start point on a CCW arc
|
||||
double x0 = aCurve->m_end.x;
|
||||
double x1 = aCurve->m_ep.x;
|
||||
|
||||
if( aCurve->m_angle < 0.0 )
|
||||
{
|
||||
std::swap( q0, q1 );
|
||||
std::swap( x0, x1 );
|
||||
}
|
||||
|
||||
double minx;
|
||||
|
||||
if( ( q0 <= 2 && q1 >= 3 ) || ( q0 >= 3 && x0 > x1 ) )
|
||||
minx = aCurve->m_start.x - aCurve->m_radius;
|
||||
else
|
||||
minx = std::min( x0, x1 );
|
||||
|
||||
if( minx < m_minx )
|
||||
{
|
||||
m_minx = minx;
|
||||
m_mincurve = --(m_curves.end());
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
break;
|
||||
|
||||
case CURVE_BEZIER:
|
||||
if( aCurve->m_start.x < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_start.x;
|
||||
m_mincurve = --(m_curves.end());
|
||||
}
|
||||
|
||||
if( aCurve->m_end.x < m_minx )
|
||||
{
|
||||
m_minx = aCurve->m_end.x;
|
||||
m_mincurve = --(m_curves.end());
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// unexpected curve type
|
||||
do
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( " * AddOutlineSegment() unsupported curve type: %d\n",
|
||||
aCurve->m_form );
|
||||
ReportMessage( msg );
|
||||
} while( 0 );
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// add a pad hole or slot
|
||||
bool PCBMODEL::AddPadHole( const KICADPAD* aPad )
|
||||
{
|
||||
if( NULL == aPad || !aPad->IsThruHole() )
|
||||
|
@ -469,9 +467,10 @@ bool PCBMODEL::AddPadHole( const KICADPAD* aPad )
|
|||
if( !aPad->m_drill.oval )
|
||||
{
|
||||
TopoDS_Shape s = BRepPrimAPI_MakeCylinder( aPad->m_drill.size.x * 0.5,
|
||||
m_thickness * 2.0 ).Shape();
|
||||
m_thickness * 2.0 ).Shape();
|
||||
gp_Trsf shift;
|
||||
shift.SetTranslation( gp_Vec( aPad->m_position.x, aPad->m_position.y, -m_thickness * 0.5 ) );
|
||||
shift.SetTranslation( gp_Vec( aPad->m_position.x, aPad->m_position.y,
|
||||
-m_thickness * 0.5 ) );
|
||||
BRepBuilderAPI_Transform hole( s, shift );
|
||||
m_cutouts.push_back( hole.Shape() );
|
||||
return true;
|
||||
|
@ -601,7 +600,6 @@ bool PCBMODEL::AddPadHole( const KICADPAD* aPad )
|
|||
}
|
||||
|
||||
|
||||
// add a component at the given position and orientation
|
||||
bool PCBMODEL::AddComponent( const std::string& aFileName, const std::string& aRefDes,
|
||||
bool aBottom, DOUBLET aPosition, double aRotation,
|
||||
TRIPLET aOffset, TRIPLET aOrientation, TRIPLET aScale,
|
||||
|
@ -664,8 +662,6 @@ void PCBMODEL::SetPCBThickness( double aThickness )
|
|||
m_thickness = THICKNESS_MIN;
|
||||
else
|
||||
m_thickness = aThickness;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -677,7 +673,6 @@ void PCBMODEL::SetMinDistance( double aDistance )
|
|||
}
|
||||
|
||||
|
||||
// create the PCB (board only) model using the current outlines and drill holes
|
||||
bool PCBMODEL::CreatePCB()
|
||||
{
|
||||
if( m_hasPCB )
|
||||
|
@ -814,7 +809,8 @@ bool PCBMODEL::CreatePCB()
|
|||
(int)m_cutouts.size() ) );
|
||||
}
|
||||
|
||||
#if 0 // First version for holes removing: very slow when having many (> 300) holes
|
||||
#if 0
|
||||
// First version for holes removing: very slow when having many (> 300) holes
|
||||
// Substract holes (cutouts) can be time consuming, so display activity
|
||||
// state to be sure there is no hang:
|
||||
int char_count = 0;
|
||||
|
@ -863,8 +859,7 @@ bool PCBMODEL::CreatePCB()
|
|||
return false;
|
||||
|
||||
// color the PCB
|
||||
Handle(XCAFDoc_ColorTool) color =
|
||||
XCAFDoc_DocumentTool::ColorTool( m_doc->Main () );
|
||||
Handle( XCAFDoc_ColorTool ) color = XCAFDoc_DocumentTool::ColorTool( m_doc->Main () );
|
||||
Quantity_Color pcb_green( 0.06, 0.4, 0.06, Quantity_TOC_RGB );
|
||||
color->SetColor( m_pcb_label, pcb_green, XCAFDoc_ColorSurf );
|
||||
|
||||
|
@ -915,7 +910,6 @@ bool PCBMODEL::WriteIGES( const wxString& aFileName )
|
|||
#endif
|
||||
|
||||
|
||||
// write the assembly model in STEP format
|
||||
bool PCBMODEL::WriteSTEP( const wxString& aFileName )
|
||||
{
|
||||
if( m_pcb_label.IsNull() )
|
||||
|
@ -942,9 +936,11 @@ bool PCBMODEL::WriteSTEP( const wxString& aFileName )
|
|||
return false;
|
||||
|
||||
APIHeaderSection_MakeHeader hdr( writer.ChangeWriter().Model() );
|
||||
|
||||
// Note: use only Ascii7 chars, non Ascii7 chars (therefore UFT8 chars)
|
||||
// are creating issues in the step file
|
||||
hdr.SetName( new TCollection_HAsciiString( fn.GetFullName().ToAscii() ) );
|
||||
|
||||
// TODO: how to control and ensure consistency with IGES?
|
||||
hdr.SetAuthorValue( 1, new TCollection_HAsciiString( "Pcbnew" ) );
|
||||
hdr.SetOrganizationValue( 1, new TCollection_HAsciiString( "Kicad" ) );
|
||||
|
@ -952,10 +948,10 @@ bool PCBMODEL::WriteSTEP( const wxString& aFileName )
|
|||
hdr.SetDescriptionValue( 1, new TCollection_HAsciiString( "KiCad electronic assembly" ) );
|
||||
|
||||
bool success = true;
|
||||
// Creates a temporary file with a ascii7 name, because writer does not know
|
||||
// unicode filenames
|
||||
|
||||
// Creates a temporary file with a ascii7 name, because writer does not know unicode filenames.
|
||||
wxString currCWD = wxGetCwd();
|
||||
wxString workCWD =fn.GetPath();
|
||||
wxString workCWD = fn.GetPath();
|
||||
|
||||
if( !workCWD.IsEmpty() )
|
||||
wxSetWorkingDirectory( workCWD );
|
||||
|
@ -1005,171 +1001,166 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
|||
|
||||
switch( modelFmt )
|
||||
{
|
||||
case FMT_IGES:
|
||||
if( !readIGES( doc, aFileName.c_str() ) )
|
||||
{
|
||||
ReportMessage( wxString::Format( "readIGES() failed on filename '%s'.\n",
|
||||
aFileName ) );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case FMT_STEP:
|
||||
if( !readSTEP( doc, aFileName.c_str() ) )
|
||||
{
|
||||
ReportMessage( wxString::Format( "readSTEP() failed on filename '%s'.\n",
|
||||
aFileName ) );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case FMT_STEPZ:
|
||||
case FMT_IGES:
|
||||
if( !readIGES( doc, aFileName.c_str() ) )
|
||||
{
|
||||
wxFFileInputStream ifile( aFileName );
|
||||
wxFileName outFile( aFileName );
|
||||
ReportMessage( wxString::Format( "readIGES() failed on filename '%s'.\n", aFileName ) );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
outFile.SetPath( wxStandardPaths::Get().GetTempDir() );
|
||||
outFile.SetExt( "STEP" );
|
||||
case FMT_STEP:
|
||||
if( !readSTEP( doc, aFileName.c_str() ) )
|
||||
{
|
||||
ReportMessage( wxString::Format( "readSTEP() failed on filename '%s'.\n", aFileName ) );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
wxFileOffset size = ifile.GetLength();
|
||||
case FMT_STEPZ:
|
||||
{
|
||||
wxFFileInputStream ifile( aFileName );
|
||||
wxFileName outFile( aFileName );
|
||||
|
||||
if( size == wxInvalidOffset )
|
||||
{
|
||||
ReportMessage( wxString::Format( "readSTEP() failed on filename '%s'.\n",
|
||||
aFileName ) );
|
||||
return false;
|
||||
}
|
||||
outFile.SetPath( wxStandardPaths::Get().GetTempDir() );
|
||||
outFile.SetExt( "STEP" );
|
||||
|
||||
{
|
||||
bool success = false;
|
||||
wxFFileOutputStream ofile( outFile.GetFullPath() );
|
||||
wxFileOffset size = ifile.GetLength();
|
||||
|
||||
if( !ofile.IsOk() )
|
||||
return false;
|
||||
|
||||
char *buffer = new char[size];
|
||||
|
||||
ifile.Read( buffer, size);
|
||||
std::string expanded;
|
||||
|
||||
try
|
||||
{
|
||||
expanded = gzip::decompress( buffer, size );
|
||||
success = true;
|
||||
}
|
||||
catch(...)
|
||||
{}
|
||||
|
||||
if( expanded.empty() )
|
||||
{
|
||||
ifile.Reset();
|
||||
ifile.SeekI( 0 );
|
||||
wxZipInputStream izipfile( ifile );
|
||||
std::unique_ptr<wxZipEntry> zip_file( izipfile.GetNextEntry() );
|
||||
|
||||
if( zip_file && !zip_file->IsDir() && izipfile.CanRead() )
|
||||
{
|
||||
izipfile.Read( ofile );
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ofile.Write( expanded.data(), expanded.size() );
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
ofile.Close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
break;
|
||||
if( size == wxInvalidOffset )
|
||||
{
|
||||
ReportMessage( wxString::Format( "readSTEP() failed on filename '%s'.\n", aFileName ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
case FMT_WRL:
|
||||
case FMT_WRZ:
|
||||
/* WRL files are preferred for internal rendering,
|
||||
* due to superior material properties, etc.
|
||||
* However they are not suitable for MCAD export.
|
||||
*
|
||||
* If a .wrl file is specified, attempt to locate
|
||||
* a replacement file for it.
|
||||
*
|
||||
* If a valid replacement file is found, the label
|
||||
* for THAT file will be associated with the .wrl file
|
||||
*
|
||||
*/
|
||||
if( aSubstituteModels )
|
||||
{
|
||||
bool success = false;
|
||||
wxFFileOutputStream ofile( outFile.GetFullPath() );
|
||||
|
||||
if( !ofile.IsOk() )
|
||||
return false;
|
||||
|
||||
char* buffer = new char[size];
|
||||
|
||||
ifile.Read( buffer, size );
|
||||
std::string expanded;
|
||||
|
||||
try
|
||||
{
|
||||
wxFileName wrlName( aFileName );
|
||||
expanded = gzip::decompress( buffer, size );
|
||||
success = true;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
|
||||
wxString basePath = wrlName.GetPath();
|
||||
wxString baseName = wrlName.GetName();
|
||||
if( expanded.empty() )
|
||||
{
|
||||
ifile.Reset();
|
||||
ifile.SeekI( 0 );
|
||||
wxZipInputStream izipfile( ifile );
|
||||
std::unique_ptr<wxZipEntry> zip_file( izipfile.GetNextEntry() );
|
||||
|
||||
// List of alternate files to look for
|
||||
// Given in order of preference
|
||||
// (Break if match is found)
|
||||
wxArrayString alts;
|
||||
|
||||
// Step files
|
||||
alts.Add( "stp" );
|
||||
alts.Add( "step" );
|
||||
alts.Add( "STP" );
|
||||
alts.Add( "STEP" );
|
||||
alts.Add( "Stp" );
|
||||
alts.Add( "Step" );
|
||||
alts.Add( "stpz" );
|
||||
alts.Add( "stpZ" );
|
||||
alts.Add( "STPZ" );
|
||||
alts.Add( "step.gz" );
|
||||
|
||||
// IGES files
|
||||
alts.Add( "iges" );
|
||||
alts.Add( "IGES" );
|
||||
alts.Add( "igs" );
|
||||
alts.Add( "IGS" );
|
||||
|
||||
//TODO - Other alternative formats?
|
||||
|
||||
for( const auto& alt : alts )
|
||||
if( zip_file && !zip_file->IsDir() && izipfile.CanRead() )
|
||||
{
|
||||
wxFileName altFile( basePath, baseName + "." + alt );
|
||||
izipfile.Read( ofile );
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ofile.Write( expanded.data(), expanded.size() );
|
||||
}
|
||||
|
||||
if( altFile.IsOk() && altFile.FileExists() )
|
||||
delete[] buffer;
|
||||
ofile.Close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case FMT_WRL:
|
||||
case FMT_WRZ:
|
||||
/* WRL files are preferred for internal rendering, due to superior material properties, etc.
|
||||
* However they are not suitable for MCAD export.
|
||||
*
|
||||
* If a .wrl file is specified, attempt to locate a replacement file for it.
|
||||
*
|
||||
* If a valid replacement file is found, the label for THAT file will be associated with
|
||||
* the .wrl file
|
||||
*/
|
||||
if( aSubstituteModels )
|
||||
{
|
||||
wxFileName wrlName( aFileName );
|
||||
|
||||
wxString basePath = wrlName.GetPath();
|
||||
wxString baseName = wrlName.GetName();
|
||||
|
||||
// List of alternate files to look for
|
||||
// Given in order of preference
|
||||
// (Break if match is found)
|
||||
wxArrayString alts;
|
||||
|
||||
// Step files
|
||||
alts.Add( "stp" );
|
||||
alts.Add( "step" );
|
||||
alts.Add( "STP" );
|
||||
alts.Add( "STEP" );
|
||||
alts.Add( "Stp" );
|
||||
alts.Add( "Step" );
|
||||
alts.Add( "stpz" );
|
||||
alts.Add( "stpZ" );
|
||||
alts.Add( "STPZ" );
|
||||
alts.Add( "step.gz" );
|
||||
|
||||
// IGES files
|
||||
alts.Add( "iges" );
|
||||
alts.Add( "IGES" );
|
||||
alts.Add( "igs" );
|
||||
alts.Add( "IGS" );
|
||||
|
||||
//TODO - Other alternative formats?
|
||||
|
||||
for( const auto& alt : alts )
|
||||
{
|
||||
wxFileName altFile( basePath, baseName + "." + alt );
|
||||
|
||||
if( altFile.IsOk() && altFile.FileExists() )
|
||||
{
|
||||
std::string altFileName = altFile.GetFullPath().ToStdString();
|
||||
|
||||
// When substituting a STEP/IGS file for VRML, do not apply the VRML scaling
|
||||
// to the new STEP model. This process of auto-substitution is janky as all
|
||||
// heck so let's not mix up un-displayed scale factors with potentially
|
||||
// mis-matched files. And hope that the user doesn't have multiples files
|
||||
// named "model.wrl" and "model.stp" referring to different parts.
|
||||
// TODO: Fix model handling in v7. Default models should only be STP.
|
||||
// Have option to override this in DISPLAY.
|
||||
if( getModelLabel( altFileName, TRIPLET( 1.0, 1.0, 1.0 ), aLabel, false ) )
|
||||
{
|
||||
std::string altFileName = altFile.GetFullPath().ToStdString();
|
||||
|
||||
// When substituting a STEP/IGS file for VRML, do not apply the VRML scaling
|
||||
// to the new STEP model. This process of auto-substitution is janky as all
|
||||
// heck so let's not mix up un-displayed scale factors with potentially
|
||||
// mis-matched files. And hope that the user doesn't have multiples files
|
||||
// named "model.wrl" and "model.stp" referring to different parts.
|
||||
// TODO: Fix model handling in v7. Default models should only be STP.
|
||||
// Have option to override this in DISPLAY.
|
||||
if( getModelLabel( altFileName, TRIPLET( 1.0, 1.0, 1.0 ), aLabel, false ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // No replacement model found
|
||||
}
|
||||
else // Substitution is not allowed
|
||||
{
|
||||
if( aErrorMessage )
|
||||
aErrorMessage->Printf( "Cannot add a VRML model data to a Step file.\n",
|
||||
aFileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
return false; // No replacement model found
|
||||
}
|
||||
else // Substitution is not allowed
|
||||
{
|
||||
if( aErrorMessage )
|
||||
aErrorMessage->Printf( "Cannot add a VRML model data to a Step file.\n",
|
||||
aFileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// TODO: implement IDF and EMN converters
|
||||
|
||||
default:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
aLabel = transferModel( doc, m_doc, aScale );
|
||||
|
@ -1338,7 +1329,6 @@ TDF_Label PCBMODEL::transferModel( Handle( TDocStd_Document )& source,
|
|||
0, 0, aScale.z ) );
|
||||
BRepBuilderAPI_GTransform brep( scale_transform );
|
||||
|
||||
|
||||
// s_assy = shape tool for the source
|
||||
Handle(XCAFDoc_ShapeTool) s_assy = XCAFDoc_DocumentTool::ShapeTool ( source->Main() );
|
||||
|
||||
|
@ -1456,13 +1446,11 @@ OUTLINE::OUTLINE()
|
|||
{
|
||||
m_closed = false;
|
||||
m_minDistance2 = MIN_LENGTH2;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OUTLINE::~OUTLINE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1470,7 +1458,6 @@ void OUTLINE::Clear()
|
|||
{
|
||||
m_closed = false;
|
||||
m_curves.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1618,53 +1605,52 @@ bool OUTLINE::addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBL
|
|||
|
||||
switch( aCurve.m_form )
|
||||
{
|
||||
case CURVE_LINE:
|
||||
edge = BRepBuilderAPI_MakeEdge( gp_Pnt( aLastPoint.x, aLastPoint.y, 0.0 ),
|
||||
gp_Pnt( endPoint.x, endPoint.y, 0.0 ) );
|
||||
break;
|
||||
case CURVE_LINE:
|
||||
edge = BRepBuilderAPI_MakeEdge( gp_Pnt( aLastPoint.x, aLastPoint.y, 0.0 ),
|
||||
gp_Pnt( endPoint.x, endPoint.y, 0.0 ) );
|
||||
break;
|
||||
|
||||
case CURVE_ARC:
|
||||
{
|
||||
gp_Circ arc( gp_Ax2( gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 ),
|
||||
gp_Dir( 0.0, 0.0, 1.0 ) ), aCurve.m_radius );
|
||||
case CURVE_ARC:
|
||||
{
|
||||
gp_Circ arc( gp_Ax2( gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 ),
|
||||
gp_Dir( 0.0, 0.0, 1.0 ) ), aCurve.m_radius );
|
||||
|
||||
gp_Pnt sa( aLastPoint.x, aLastPoint.y, 0.0 );
|
||||
gp_Pnt ea( endPoint.x, endPoint.y, 0.0 );
|
||||
gp_Pnt sa( aLastPoint.x, aLastPoint.y, 0.0 );
|
||||
gp_Pnt ea( endPoint.x, endPoint.y, 0.0 );
|
||||
|
||||
if( aCurve.m_angle < 0.0 )
|
||||
edge = BRepBuilderAPI_MakeEdge( arc, ea, sa );
|
||||
else
|
||||
edge = BRepBuilderAPI_MakeEdge( arc, sa, ea );
|
||||
}
|
||||
break;
|
||||
if( aCurve.m_angle < 0.0 )
|
||||
edge = BRepBuilderAPI_MakeEdge( arc, ea, sa );
|
||||
else
|
||||
edge = BRepBuilderAPI_MakeEdge( arc, sa, ea );
|
||||
}
|
||||
break;
|
||||
|
||||
case CURVE_CIRCLE:
|
||||
edge = BRepBuilderAPI_MakeEdge( gp_Circ( gp_Ax2( gp_Pnt( aCurve.m_start.x,
|
||||
aCurve.m_start.y, 0.0 ),
|
||||
gp_Dir( 0.0, 0.0, 1.0 ) ),
|
||||
aCurve.m_radius ) );
|
||||
break;
|
||||
case CURVE_CIRCLE:
|
||||
edge = BRepBuilderAPI_MakeEdge(
|
||||
gp_Circ( gp_Ax2( gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 ),
|
||||
gp_Dir( 0.0, 0.0, 1.0 ) ), aCurve.m_radius ) );
|
||||
break;
|
||||
|
||||
case CURVE_BEZIER:
|
||||
{
|
||||
TColgp_Array1OfPnt poles(0, 3);
|
||||
gp_Pnt pt = gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 );
|
||||
poles(0) = pt;
|
||||
pt = gp_Pnt( aCurve.m_bezierctrl1.x, aCurve.m_bezierctrl1.y, 0.0 );
|
||||
poles(1) = pt;
|
||||
pt = gp_Pnt( aCurve.m_bezierctrl2.x, aCurve.m_bezierctrl2.y, 0.0 );
|
||||
poles(2) = pt;
|
||||
pt = gp_Pnt( endPoint.x, endPoint.y, 0.0 );
|
||||
poles(3) = pt;
|
||||
case CURVE_BEZIER:
|
||||
{
|
||||
TColgp_Array1OfPnt poles( 0, 3 );
|
||||
gp_Pnt pt = gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 );
|
||||
poles( 0 ) = pt;
|
||||
pt = gp_Pnt( aCurve.m_bezierctrl1.x, aCurve.m_bezierctrl1.y, 0.0 );
|
||||
poles( 1 ) = pt;
|
||||
pt = gp_Pnt( aCurve.m_bezierctrl2.x, aCurve.m_bezierctrl2.y, 0.0 );
|
||||
poles( 2 ) = pt;
|
||||
pt = gp_Pnt( endPoint.x, endPoint.y, 0.0 );
|
||||
poles( 3 ) = pt;
|
||||
|
||||
Geom_BezierCurve* bezier_curve = new Geom_BezierCurve( poles );
|
||||
edge = BRepBuilderAPI_MakeEdge( bezier_curve );
|
||||
}
|
||||
break;
|
||||
Geom_BezierCurve* bezier_curve = new Geom_BezierCurve( poles );
|
||||
edge = BRepBuilderAPI_MakeEdge( bezier_curve );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ReportMessage( wxString::Format( "unsupported curve type: %d\n", aCurve.m_form ) );
|
||||
return false;
|
||||
default:
|
||||
ReportMessage( wxString::Format( "unsupported curve type: %d\n", aCurve.m_form ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( edge.IsNull() )
|
||||
|
|
|
@ -49,15 +49,7 @@ class KICADPAD;
|
|||
|
||||
class OUTLINE
|
||||
{
|
||||
private:
|
||||
bool m_closed; // set true if the loop is closed
|
||||
double m_minDistance2; // min squared distance to treat points as separate entities (mm)
|
||||
|
||||
bool addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBLET& aLastPoint );
|
||||
bool testClosed( const KICADCURVE& aFrontCurve, const KICADCURVE& aBackCurve );
|
||||
|
||||
public:
|
||||
std::list< KICADCURVE > m_curves; // list of contiguous segments
|
||||
OUTLINE();
|
||||
virtual ~OUTLINE();
|
||||
|
||||
|
@ -77,51 +69,22 @@ public:
|
|||
}
|
||||
|
||||
bool MakeShape( TopoDS_Shape& aShape, double aThickness );
|
||||
|
||||
private:
|
||||
bool addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBLET& aLastPoint );
|
||||
bool testClosed( const KICADCURVE& aFrontCurve, const KICADCURVE& aBackCurve );
|
||||
|
||||
public:
|
||||
std::list< KICADCURVE > m_curves; // list of contiguous segments
|
||||
|
||||
private:
|
||||
bool m_closed; // set true if the loop is closed
|
||||
double m_minDistance2; // min squared distance to treat points as separate entities (mm)
|
||||
};
|
||||
|
||||
|
||||
class PCBMODEL
|
||||
{
|
||||
Handle( XCAFApp_Application ) m_app;
|
||||
Handle( TDocStd_Document ) m_doc;
|
||||
Handle( XCAFDoc_ShapeTool ) m_assy;
|
||||
TDF_Label m_assy_label;
|
||||
bool m_hasPCB; // set true if CreatePCB() has been invoked
|
||||
TDF_Label m_pcb_label; // label for the PCB model
|
||||
MODEL_MAP m_models; // map of file names to model labels
|
||||
int m_components; // number of successfully loaded components;
|
||||
double m_precision; // model (length unit) numeric precision
|
||||
double m_angleprec; // angle numeric precision
|
||||
double m_thickness; // PCB thickness, mm
|
||||
double m_minx; // minimum X value in curves (leftmost curve feature)
|
||||
double m_minDistance2; // minimum squared distance between items (mm)
|
||||
std::list<KICADCURVE>::iterator m_mincurve; // iterator to the leftmost curve
|
||||
|
||||
std::list<KICADCURVE> m_curves;
|
||||
std::vector<TopoDS_Shape> m_cutouts;
|
||||
|
||||
/**
|
||||
* Load a 3D model data
|
||||
* aFileName is the filename (different formats allowed) but for WRML files a model
|
||||
* data can be loaded instead of the vrml data, not suitable in a step file
|
||||
* @param aScale is the X,Y,Z scaling factors
|
||||
* @param aLabel is the TDF_Label to store the data
|
||||
* @param aSubstituteModels = true to allows data substitution, false to disallow.
|
||||
* @param aErrorMessage (can be nullptr) is an error message to be displayed on error.
|
||||
* @return true if successfully loaded, false on error
|
||||
*/
|
||||
bool getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel,
|
||||
bool aSubstituteModels, wxString* aErrorMessage = nullptr );
|
||||
|
||||
bool getModelLocation( bool aBottom, DOUBLET aPosition, double aRotation,
|
||||
TRIPLET aOffset, TRIPLET aOrientation, TopLoc_Location& aLocation );
|
||||
|
||||
bool readIGES( Handle( TDocStd_Document )& m_doc, const char* fname );
|
||||
bool readSTEP( Handle( TDocStd_Document )& m_doc, const char* fname );
|
||||
|
||||
TDF_Label transferModel( Handle( TDocStd_Document )& source,
|
||||
Handle( TDocStd_Document )& dest, TRIPLET aScale );
|
||||
|
||||
public:
|
||||
PCBMODEL();
|
||||
virtual ~PCBMODEL();
|
||||
|
@ -157,6 +120,50 @@ public:
|
|||
|
||||
// write the assembly model in STEP format
|
||||
bool WriteSTEP( const wxString& aFileName );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Load a 3D model data.
|
||||
*
|
||||
* @param aFileName is the filename (different formats allowed) but for WRML files a model
|
||||
* data can be loaded instead of the vrml data, not suitable in a step file.
|
||||
* @param aScale is the X,Y,Z scaling factors.
|
||||
* @param aLabel is the TDF_Label to store the data.
|
||||
* @param aSubstituteModels = true to allows data substitution, false to disallow.
|
||||
* @param aErrorMessage (can be nullptr) is an error message to be displayed on error.
|
||||
* @return true if successfully loaded, false on error.
|
||||
*/
|
||||
bool getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel,
|
||||
bool aSubstituteModels, wxString* aErrorMessage = nullptr );
|
||||
|
||||
bool getModelLocation( bool aBottom, DOUBLET aPosition, double aRotation, TRIPLET aOffset,
|
||||
TRIPLET aOrientation, TopLoc_Location& aLocation );
|
||||
|
||||
bool readIGES( Handle( TDocStd_Document )& m_doc, const char* fname );
|
||||
bool readSTEP( Handle( TDocStd_Document )& m_doc, const char* fname );
|
||||
|
||||
TDF_Label transferModel( Handle( TDocStd_Document )& source,
|
||||
Handle( TDocStd_Document )& dest, TRIPLET aScale );
|
||||
|
||||
Handle( XCAFApp_Application ) m_app;
|
||||
Handle( TDocStd_Document ) m_doc;
|
||||
Handle( XCAFDoc_ShapeTool ) m_assy;
|
||||
TDF_Label m_assy_label;
|
||||
bool m_hasPCB; // set true if CreatePCB() has been invoked
|
||||
TDF_Label m_pcb_label; // label for the PCB model
|
||||
MODEL_MAP m_models; // map of file names to model labels
|
||||
int m_components; // number of successfully loaded components;
|
||||
double m_precision; // model (length unit) numeric precision
|
||||
double m_angleprec; // angle numeric precision
|
||||
double m_thickness; // PCB thickness, mm
|
||||
|
||||
// minimum X value in curves (leftmost curve feature).
|
||||
double m_minx;
|
||||
double m_minDistance2; // minimum squared distance between items (mm)
|
||||
std::list<KICADCURVE>::iterator m_mincurve; // iterator to the leftmost curve
|
||||
|
||||
std::list<KICADCURVE> m_curves;
|
||||
std::vector<TopoDS_Shape> m_cutouts;
|
||||
};
|
||||
|
||||
#endif // OCE_VIS_OCE_UTILS_H
|
||||
|
|
Loading…
Reference in New Issue