Do not blindly substitute model names

Makes model substitution (VRML->STEP in STEP Export) optional.  This can
prevent nasty surprises where the user doesn't see/can't affect the
outcome

Also, when substituting models, do not maintain scale factor.  So a VRML
model with non-unity scaling will not be export as a STEP file (of the
same name) with non-unity scaling.  This is the first step to address
https://gitlab.com/kicad/code/kicad/-/issues/1781
This commit is contained in:
Seth Hillbrand 2021-06-08 15:46:37 -07:00
parent 6e01ce84b9
commit b891b5e1e2
12 changed files with 114 additions and 17 deletions

View File

@ -89,6 +89,11 @@ protected:
return m_cbRemoveVirtual->GetValue();
}
bool GetSubstOption()
{
return m_cbSubstModels->GetValue();
}
bool GetOverwriteFile()
{
return m_cbOverwriteFile->GetValue();
@ -311,6 +316,9 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
if( GetNoVirtOption() )
cmdK2S.Append( " --no-virtual" );
if( GetSubstOption() )
cmdK2S.Append( " --subst-models" );
switch( orgOpt )
{
case DIALOG_EXPORT_STEP::STEP_ORG_0:

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// C++ code generated with wxFormBuilder (version 3.9.0 Apr 22 2021)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -136,6 +136,11 @@ DIALOG_EXPORT_STEP_BASE::DIALOG_EXPORT_STEP_BASE( wxWindow* parent, wxWindowID i
m_cbRemoveVirtual = new wxCheckBox( this, wxID_ANY, _("Ignore virtual components"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer8->Add( m_cbRemoveVirtual, 0, wxALL, 5 );
m_cbSubstModels = new wxCheckBox( this, wxID_ANY, _("Substitute similarly named models"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbSubstModels->SetToolTip( _("Replace VRML models with STEP models of the same name") );
bSizer8->Add( m_cbSubstModels, 0, wxALL, 5 );
m_cbOverwriteFile = new wxCheckBox( this, wxID_ANY, _("Overwrite old file"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer8->Add( m_cbOverwriteFile, 0, wxALL, 5 );

View File

@ -14,6 +14,7 @@
<property name="file">dialog_export_step_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_export_step_base</property>
@ -25,6 +26,7 @@
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
@ -1211,6 +1213,70 @@
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Substitute similarly named models</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbSubstModels</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Replace VRML models with STEP models of the same name</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// C++ code generated with wxFormBuilder (version 3.9.0 Apr 22 2021)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -57,6 +57,7 @@ class DIALOG_EXPORT_STEP_BASE : public DIALOG_SHIM
TEXT_CTRL_EVAL* m_STEP_Yorg;
wxStaticText* m_staticText7;
wxCheckBox* m_cbRemoveVirtual;
wxCheckBox* m_cbSubstModels;
wxCheckBox* m_cbOverwriteFile;
wxStaticLine* m_staticline3;
wxStaticText* m_staticText9;
@ -67,7 +68,7 @@ class DIALOG_EXPORT_STEP_BASE : public DIALOG_SHIM
wxButton* m_sdbSizerOK;
wxButton* m_sdbSizerCancel;
// Virtual event handlers, overide them in your derived class
// Virtual event handlers, override them in your derived class
virtual void onUpdateUnits( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onUpdateXPos( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onUpdateYPos( wxUpdateUIEvent& event ) { event.Skip(); }

View File

@ -76,6 +76,7 @@ KICAD2MCAD_PRMS::KICAD2MCAD_PRMS()
m_useGridOrigin = false;
m_useDrillOrigin = false;
m_includeVirtual = true;
m_substModels = false;
m_xOrigin = 0.0;
m_yOrigin = 0.0;
m_minDistance = MIN_DISTANCE;
@ -110,7 +111,10 @@ static const wxCmdLineEntryDesc cmdLineDesc[] =
_( "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(),
_( "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(),
@ -205,6 +209,9 @@ bool KICAD2MCAD_APP::OnCmdLineParsed( wxCmdLineParser& parser )
if( parser.Found( "no-virtual" ) )
m_params.m_includeVirtual = false;
if( parser.Found( "subst-models" ) )
m_params.m_substModels = true;
wxString tstr;
if( parser.Found( "user-origin", &tstr ) )
@ -388,7 +395,7 @@ int PANEL_KICAD2STEP::RunConverter()
{
ReportMessage( "Build STEP data\n" );
res = pcb.ComposePCB( m_params.m_includeVirtual );
res = pcb.ComposePCB( m_params.m_includeVirtual, m_params.m_substModels );
if( !res )
{

View File

@ -49,6 +49,7 @@ public:
bool m_useGridOrigin;
bool m_useDrillOrigin;
bool m_includeVirtual;
bool m_substModels;
wxString m_filename;
wxString m_outputFile;
double m_xOrigin;

View File

@ -341,7 +341,7 @@ bool KICADFOOTPRINT::parsePad( SEXPR::SEXPR* data )
bool KICADFOOTPRINT::ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
DOUBLET aOrigin, bool aComposeVirtual )
DOUBLET aOrigin, bool aComposeVirtual, bool aSubstituteModels )
{
// translate pads and curves to final position and append to PCB.
double dlim = (double)std::numeric_limits< float >::epsilon();
@ -423,7 +423,7 @@ bool KICADFOOTPRINT::ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
try
{
if( aPCB->AddComponent( fname, m_refdes, LAYER_BOTTOM == m_side ? true : false,
newpos, m_rotation, i->m_offset, i->m_rotation, i->m_scale ) )
newpos, m_rotation, i->m_offset, i->m_rotation, i->m_scale, aSubstituteModels ) )
hasdata = true;
}
catch( const Standard_Failure& e)

View File

@ -72,7 +72,7 @@ public:
bool Read( SEXPR::SEXPR* aEntry );
bool ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
DOUBLET aOrigin, bool aComposeVirtual = true );
DOUBLET aOrigin, bool aComposeVirtual = true, bool aSubstituteModels = true );
};
#endif // KICADFOOTPRINT_H

View File

@ -496,7 +496,7 @@ bool KICADPCB::parseCurve( SEXPR::SEXPR* data, CURVE_TYPE aCurveType )
}
bool KICADPCB::ComposePCB( bool aComposeVirtual )
bool KICADPCB::ComposePCB( bool aComposeVirtual, bool aSubstituteModels )
{
if( m_pcb_model )
return true;
@ -554,7 +554,7 @@ bool KICADPCB::ComposePCB( bool aComposeVirtual )
}
for( auto i : m_footprints )
i->ComposePCB( m_pcb_model, &m_resolver, origin, aComposeVirtual );
i->ComposePCB( m_pcb_model, &m_resolver, origin, aComposeVirtual, aSubstituteModels );
ReportMessage( "Create PCB solid model\n" );

View File

@ -112,7 +112,7 @@ public:
}
bool ReadFile( const wxString& aFileName );
bool ComposePCB( bool aComposeVirtual = true );
bool ComposePCB( bool aComposeVirtual = true, bool aSubstituteModels = true );
bool WriteSTEP( const wxString& aFileName );
#ifdef SUPPORTS_IGES
bool WriteIGES( const wxString& aFileName );

View File

@ -603,7 +603,8 @@ 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 )
TRIPLET aOffset, TRIPLET aOrientation, TRIPLET aScale,
bool aSubstituteModels )
{
if( aFileName.empty() )
{
@ -616,7 +617,7 @@ bool PCBMODEL::AddComponent( const std::string& aFileName, const std::string& aR
// first retrieve a label
TDF_Label lmodel;
if( !getModelLabel( aFileName, aScale, lmodel ) )
if( !getModelLabel( aFileName, aScale, lmodel, aSubstituteModels ) )
{
ReportMessage( wxString::Format( "no model for filename %s\n", aFileName ) );
return false;
@ -972,7 +973,7 @@ bool PCBMODEL::WriteSTEP( const wxString& aFileName )
}
bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel )
bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel, bool aSubstituteModels )
{
std::string model_key = aFileName + "_" + std::to_string( aScale.x )
+ "_" + std::to_string( aScale.y ) + "_" + std::to_string( aScale.z );
@ -1089,6 +1090,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
* for THAT file will be associated with the .wrl file
*
*/
if( aSubstituteModels )
{
wxFileName wrlName( aFileName );
@ -1128,7 +1130,13 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
{
std::string altFileName = altFile.GetFullPath().ToStdString();
if( getModelLabel( altFileName, aScale, aLabel ) )
// 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;
}

View File

@ -99,7 +99,7 @@ class PCBMODEL
std::list< KICADCURVE > m_curves;
std::vector< TopoDS_Shape > m_cutouts;
bool getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel );
bool getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel, bool aSubstituteModels );
bool getModelLocation( bool aBottom, DOUBLET aPosition, double aRotation,
TRIPLET aOffset, TRIPLET aOrientation, TopLoc_Location& aLocation );
@ -123,7 +123,8 @@ public:
// add a component at the given position and orientation
bool AddComponent( const std::string& aFileName, const std::string& aRefDes,
bool aBottom, DOUBLET aPosition, double aRotation,
TRIPLET aOffset, TRIPLET aOrientation, TRIPLET aScale );
TRIPLET aOffset, TRIPLET aOrientation, TRIPLET aScale,
bool aSubstituteModels = true );
// set the thickness of the PCB (mm); the top of the PCB shall be at Z = aThickness
// aThickness < 0.0 == use default thickness