ADDED: Export inner PCB copper layers to STEP / BREP / GLTF.
Also adds options to exclude board body and components. Fixes https://gitlab.com/kicad/code/kicad/-/issues/16855
This commit is contained in:
parent
6a73c7ffb3
commit
c68e3ceb44
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2023 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2023-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -38,9 +38,12 @@ JOB_EXPORT_PCB_3D::JOB_EXPORT_PCB_3D( bool aIsCli ) :
|
|||
m_yOrigin( 0.0 ),
|
||||
// max dist to chain 2 items (lines or curves) to build the board outlines
|
||||
m_BoardOutlinesChainingEpsilon( 0.01 ), // 0.01 mm is a good value
|
||||
m_exportTracks( false ), // Time consuming if true
|
||||
m_exportZones( false ), // Time consuming if true
|
||||
m_fuseShapes( false ), // Time consuming if true
|
||||
m_exportBoardBody( true ),
|
||||
m_exportComponents( true ),
|
||||
m_exportTracks( false ),
|
||||
m_exportZones( false ),
|
||||
m_exportInnerCopper( false ),
|
||||
m_fuseShapes( false ),
|
||||
m_format( JOB_EXPORT_PCB_3D::FORMAT::UNKNOWN ),
|
||||
m_vrmlUnits( JOB_EXPORT_PCB_3D::VRML_UNITS::METERS ),
|
||||
m_vrmlModelDir( wxEmptyString ),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -61,8 +61,11 @@ public:
|
|||
double m_xOrigin;
|
||||
double m_yOrigin;
|
||||
double m_BoardOutlinesChainingEpsilon;
|
||||
bool m_exportBoardBody;
|
||||
bool m_exportComponents;
|
||||
bool m_exportTracks;
|
||||
bool m_exportZones;
|
||||
bool m_exportInnerCopper;
|
||||
bool m_fuseShapes;
|
||||
JOB_EXPORT_PCB_3D::FORMAT m_format;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -37,8 +37,11 @@
|
|||
#define ARG_MIN_DISTANCE "--min-distance"
|
||||
#define ARG_USER_ORIGIN "--user-origin"
|
||||
#define ARG_BOARD_ONLY "--board-only"
|
||||
#define ARG_NO_BOARD_BODY "--no-board-body"
|
||||
#define ARG_NO_COMPONENTS "--no-components"
|
||||
#define ARG_INCLUDE_TRACKS "--include-tracks"
|
||||
#define ARG_INCLUDE_ZONES "--include-zones"
|
||||
#define ARG_INCLUDE_INNER_COPPER "--include-inner-copper"
|
||||
#define ARG_FUSE_SHAPES "--fuse-shapes"
|
||||
#define ARG_NO_OPTIMIZE_STEP "--no-optimize-step"
|
||||
#define ARG_FORMAT "--format"
|
||||
|
@ -103,15 +106,26 @@ CLI::PCB_EXPORT_3D_COMMAND::PCB_EXPORT_3D_COMMAND( const std::string& aNa
|
|||
.help( UTF8STDSTR( _( "Only generate a board with no components" ) ) )
|
||||
.flag();
|
||||
|
||||
m_argParser.add_argument( ARG_NO_BOARD_BODY )
|
||||
.help( UTF8STDSTR( _( "Exclude board body" ) ) )
|
||||
.flag();
|
||||
|
||||
m_argParser.add_argument( ARG_NO_COMPONENTS )
|
||||
.help( UTF8STDSTR( _( "Exclude 3D models for components" ) ) )
|
||||
.flag();
|
||||
|
||||
m_argParser.add_argument( ARG_INCLUDE_TRACKS )
|
||||
.help( UTF8STDSTR( _( "Export tracks" ) ) )
|
||||
.implicit_value( true )
|
||||
.default_value( false );
|
||||
.flag();
|
||||
|
||||
m_argParser.add_argument( ARG_INCLUDE_ZONES )
|
||||
.help( UTF8STDSTR( _( "Export zones" ) ) )
|
||||
.flag();
|
||||
|
||||
m_argParser.add_argument( ARG_INCLUDE_INNER_COPPER )
|
||||
.help( UTF8STDSTR( _( "Export elements on inner copper layers" ) ) )
|
||||
.flag();
|
||||
|
||||
m_argParser.add_argument( ARG_FUSE_SHAPES )
|
||||
.help( UTF8STDSTR( _( "Fuse overlapping geometry together" ) ) )
|
||||
.flag();
|
||||
|
@ -166,8 +180,11 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
|
|||
step->m_useDrillOrigin = m_argParser.get<bool>( ARG_DRILL_ORIGIN );
|
||||
step->m_useGridOrigin = m_argParser.get<bool>( ARG_GRID_ORIGIN );
|
||||
step->m_substModels = m_argParser.get<bool>( ARG_SUBST_MODELS );
|
||||
step->m_exportBoardBody = !m_argParser.get<bool>( ARG_NO_BOARD_BODY );
|
||||
step->m_exportComponents = !m_argParser.get<bool>( ARG_NO_COMPONENTS );
|
||||
step->m_exportTracks = m_argParser.get<bool>( ARG_INCLUDE_TRACKS );
|
||||
step->m_exportZones = m_argParser.get<bool>( ARG_INCLUDE_ZONES );
|
||||
step->m_exportInnerCopper = m_argParser.get<bool>( ARG_INCLUDE_INNER_COPPER );
|
||||
step->m_fuseShapes = m_argParser.get<bool>( ARG_FUSE_SHAPES );
|
||||
step->m_boardOnly = m_argParser.get<bool>( ARG_BOARD_ONLY );
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo
|
||||
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -117,9 +117,12 @@ private:
|
|||
bool m_noUnspecified; // remember last preference for No Unspecified Component
|
||||
bool m_noDNP; // remember last preference for No DNP Component
|
||||
static bool m_optimizeStep; // remember last preference for Optimize STEP file (stored only for the session)
|
||||
static bool m_exportBoardBody; // remember last preference to export board body (stored only for the session)
|
||||
static bool m_exportComponents; // remember last preference to export components (stored only for the session)
|
||||
static bool m_exportTracks; // remember last preference to export tracks (stored only for the session)
|
||||
static bool m_exportZones; // remember last preference to export tracks (stored only for the session)
|
||||
static bool m_fuseShapes; // remember last preference to export tracks (stored only for the session)
|
||||
static bool m_exportZones; // remember last preference to export zones (stored only for the session)
|
||||
static bool m_fuseShapes; // remember last preference to fuse shapes (stored only for the session)
|
||||
static bool m_exportInnerCopper; // remember last preference to export inner layers (stored only for the session)
|
||||
wxString m_boardPath; // path to the exported board file
|
||||
static int m_toleranceLastChoice; // Store m_tolerance option during a session
|
||||
};
|
||||
|
@ -127,8 +130,11 @@ private:
|
|||
|
||||
int DIALOG_EXPORT_STEP::m_toleranceLastChoice = -1; // Use default
|
||||
bool DIALOG_EXPORT_STEP::m_optimizeStep = true;
|
||||
bool DIALOG_EXPORT_STEP::m_exportBoardBody = true;
|
||||
bool DIALOG_EXPORT_STEP::m_exportComponents = true;
|
||||
bool DIALOG_EXPORT_STEP::m_exportTracks = false;
|
||||
bool DIALOG_EXPORT_STEP::m_exportZones = false;
|
||||
bool DIALOG_EXPORT_STEP::m_exportInnerCopper = false;
|
||||
bool DIALOG_EXPORT_STEP::m_fuseShapes = false;
|
||||
|
||||
DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aParent, const wxString& aBoardPath ) :
|
||||
|
@ -180,8 +186,11 @@ DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aParent, const wxString&
|
|||
m_noDNP = cfg->m_ExportStep.no_dnp;
|
||||
|
||||
m_cbOptimizeStep->SetValue( m_optimizeStep );
|
||||
m_cbExportBody->SetValue( m_exportBoardBody );
|
||||
m_cbExportComponents->SetValue( m_exportComponents );
|
||||
m_cbExportTracks->SetValue( m_exportTracks );
|
||||
m_cbExportZones->SetValue( m_exportZones );
|
||||
m_cbExportInnerCopper->SetValue( m_exportInnerCopper );
|
||||
m_cbFuseShapes->SetValue( m_fuseShapes );
|
||||
m_cbRemoveUnspecified->SetValue( m_noUnspecified );
|
||||
m_cbRemoveDNP->SetValue( m_noDNP );
|
||||
|
@ -276,8 +285,11 @@ DIALOG_EXPORT_STEP::~DIALOG_EXPORT_STEP()
|
|||
|
||||
m_toleranceLastChoice = m_choiceTolerance->GetSelection();
|
||||
m_optimizeStep = m_cbOptimizeStep->GetValue();
|
||||
m_exportBoardBody = m_cbExportBody->GetValue();
|
||||
m_exportComponents = m_cbExportComponents->GetValue();
|
||||
m_exportTracks = m_cbExportTracks->GetValue();
|
||||
m_exportZones = m_cbExportZones->GetValue();
|
||||
m_exportInnerCopper = m_cbExportInnerCopper->GetValue();
|
||||
m_fuseShapes = m_cbFuseShapes->GetValue();
|
||||
}
|
||||
|
||||
|
@ -385,8 +397,11 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
|
|||
double tolerance; // default value in mm
|
||||
m_toleranceLastChoice = m_choiceTolerance->GetSelection();
|
||||
m_optimizeStep = m_cbOptimizeStep->GetValue();
|
||||
m_exportBoardBody = m_cbExportBody->GetValue();
|
||||
m_exportComponents = m_cbExportComponents->GetValue();
|
||||
m_exportTracks = m_cbExportTracks->GetValue();
|
||||
m_exportZones = m_cbExportZones->GetValue();
|
||||
m_exportInnerCopper = m_cbExportInnerCopper->GetValue();
|
||||
m_fuseShapes = m_cbFuseShapes->GetValue();
|
||||
|
||||
switch( m_choiceTolerance->GetSelection() )
|
||||
|
@ -475,12 +490,21 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
|
|||
if( !m_optimizeStep )
|
||||
cmdK2S.Append( wxT( " --no-optimize-step" ) );
|
||||
|
||||
if( !m_exportBoardBody )
|
||||
cmdK2S.Append( wxT( " --no-board-body" ) );
|
||||
|
||||
if( !m_exportComponents )
|
||||
cmdK2S.Append( wxT( " --no-components" ) );
|
||||
|
||||
if( m_exportTracks )
|
||||
cmdK2S.Append( wxT( " --include-tracks" ) );
|
||||
|
||||
if( m_exportZones )
|
||||
cmdK2S.Append( wxT( " --include-zones" ) );
|
||||
|
||||
if( m_exportInnerCopper )
|
||||
cmdK2S.Append( wxT( " --include-inner-copper" ) );
|
||||
|
||||
if( m_fuseShapes )
|
||||
cmdK2S.Append( wxT( " --fuse-shapes" ) );
|
||||
|
||||
|
|
|
@ -151,16 +151,25 @@ DIALOG_EXPORT_STEP_BASE::DIALOG_EXPORT_STEP_BASE( wxWindow* parent, wxWindowID i
|
|||
m_staticline1 = new wxStaticLine( sbOtherOptions->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
sbOtherOptions->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 );
|
||||
|
||||
m_cbExportBody = new wxCheckBox( sbOtherOptions->GetStaticBox(), wxID_ANY, _("Export board body"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbOtherOptions->Add( m_cbExportBody, 0, wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
m_cbExportComponents = new wxCheckBox( sbOtherOptions->GetStaticBox(), wxID_ANY, _("Export components"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbOtherOptions->Add( m_cbExportComponents, 0, wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
m_cbExportTracks = new wxCheckBox( sbOtherOptions->GetStaticBox(), wxID_ANY, _("Export tracks, pads and vias"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbExportTracks->SetToolTip( _("Export tracks, pads and vias on external copper layers.") );
|
||||
|
||||
sbOtherOptions->Add( m_cbExportTracks, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 );
|
||||
sbOtherOptions->Add( m_cbExportTracks, 0, wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
m_cbExportZones = new wxCheckBox( sbOtherOptions->GetStaticBox(), wxID_ANY, _("Export zones"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbExportZones->SetToolTip( _("Export zones on external copper layers.") );
|
||||
|
||||
sbOtherOptions->Add( m_cbExportZones, 0, wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
m_cbExportInnerCopper = new wxCheckBox( sbOtherOptions->GetStaticBox(), wxID_ANY, _("Export inner copper layers"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbOtherOptions->Add( m_cbExportInnerCopper, 0, wxBOTTOM|wxEXPAND|wxRIGHT, 5 );
|
||||
|
||||
m_cbFuseShapes = new wxCheckBox( sbOtherOptions->GetStaticBox(), wxID_ANY, _("Fuse shapes (time consuming)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbFuseShapes->SetToolTip( _("Combine intersecting geometry into one shape.") );
|
||||
|
||||
|
|
|
@ -1496,7 +1496,137 @@
|
|||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxTOP|wxBOTTOM|wxRIGHT</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<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="drag_accept_files">0</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">Export board body</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_cbExportBody</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">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></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="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<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="drag_accept_files">0</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">Export components</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_cbExportComponents</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">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></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="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -1624,6 +1754,71 @@
|
|||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<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="drag_accept_files">0</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">Export inner copper layers</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_cbExportInnerCopper</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">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></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="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT</property>
|
||||
|
|
|
@ -68,8 +68,11 @@ class DIALOG_EXPORT_STEP_BASE : public DIALOG_SHIM
|
|||
wxCheckBox* m_cbOptimizeStep;
|
||||
wxCheckBox* m_cbExportCompound_hidden;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxCheckBox* m_cbExportBody;
|
||||
wxCheckBox* m_cbExportComponents;
|
||||
wxCheckBox* m_cbExportTracks;
|
||||
wxCheckBox* m_cbExportZones;
|
||||
wxCheckBox* m_cbExportInnerCopper;
|
||||
wxCheckBox* m_cbFuseShapes;
|
||||
wxCheckBox* m_cbExportSilkscreen_hidden;
|
||||
wxCheckBox* m_cbExportSoldermask_hidden;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -143,8 +143,7 @@ EXPORTER_STEP::EXPORTER_STEP( BOARD* aBoard, const EXPORTER_STEP_PARAMS& aParams
|
|||
m_fail( false ),
|
||||
m_warn( false ),
|
||||
m_board( aBoard ),
|
||||
m_pcbModel( nullptr ),
|
||||
m_boardThickness( DEFAULT_BOARD_THICKNESS_MM )
|
||||
m_pcbModel( nullptr )
|
||||
{
|
||||
m_solderMaskColor = COLOR4D( 0.08, 0.20, 0.14, 0.83 );
|
||||
m_copperColor = COLOR4D( 0.7, 0.61, 0.0, 1.0 );
|
||||
|
@ -177,7 +176,7 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
|
|||
if( m_pcbModel->AddPadHole( pad, aOrigin ) )
|
||||
hasdata = true;
|
||||
|
||||
if( ExportTracksAndVias() )
|
||||
if( m_params.m_exportTracksVias )
|
||||
{
|
||||
if( m_pcbModel->AddPadShape( pad, aOrigin ) )
|
||||
hasdata = true;
|
||||
|
@ -185,17 +184,18 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
|
|||
}
|
||||
|
||||
// Build 3D shapes of the footprint graphic items on external layers:
|
||||
if( ExportTracksAndVias() )
|
||||
if( m_params.m_exportTracksVias )
|
||||
{
|
||||
int maxError = m_board->GetDesignSettings().m_MaxError;
|
||||
aFootprint->TransformFPShapesToPolySet( m_top_copper_shapes, F_Cu, 0, maxError, ERROR_INSIDE,
|
||||
false, /* include text */
|
||||
true, /* include shapes */
|
||||
false /* include private items */ );
|
||||
aFootprint->TransformFPShapesToPolySet( m_bottom_copper_shapes, B_Cu, 0, maxError, ERROR_INSIDE,
|
||||
false, /* include text */
|
||||
true, /* include shapes */
|
||||
false /* include private items */ );
|
||||
|
||||
for( PCB_LAYER_ID pcblayer : aFootprint->GetLayerSet().CuStack() )
|
||||
{
|
||||
aFootprint->TransformFPShapesToPolySet( m_poly_copper_shapes[pcblayer], pcblayer, 0,
|
||||
maxError, ERROR_INSIDE,
|
||||
false, /* include text */
|
||||
true, /* include shapes */
|
||||
false /* include private items */ );
|
||||
}
|
||||
}
|
||||
|
||||
if( ( !(aFootprint->GetAttributes() & (FP_THROUGH_HOLE|FP_SMD)) ) && !m_params.m_includeUnspecified )
|
||||
|
@ -234,7 +234,7 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
|
|||
}
|
||||
|
||||
// Exit early if we don't want to include footprint models
|
||||
if( m_params.m_boardOnly )
|
||||
if( m_params.m_boardOnly || !m_params.m_exportComponents )
|
||||
{
|
||||
return hasdata;
|
||||
}
|
||||
|
@ -244,7 +244,6 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
|
|||
for( const FP_3DMODEL& fp_model : aFootprint->Models() )
|
||||
{
|
||||
if( !fp_model.m_Show || fp_model.m_Filename.empty() )
|
||||
|
||||
continue;
|
||||
|
||||
std::vector<wxString> searchedPaths;
|
||||
|
@ -305,17 +304,15 @@ bool EXPORTER_STEP::buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin )
|
|||
|
||||
PCB_LAYER_ID pcblayer = aTrack->GetLayer();
|
||||
|
||||
if( pcblayer != F_Cu && pcblayer != B_Cu )
|
||||
if( !IsCopperLayer( pcblayer ) )
|
||||
return false;
|
||||
|
||||
if( aTrack->Type() == PCB_ARC_T )
|
||||
{
|
||||
int maxError = m_board->GetDesignSettings().m_MaxError;
|
||||
|
||||
if( pcblayer == F_Cu )
|
||||
aTrack->TransformShapeToPolygon( m_top_copper_shapes, pcblayer, 0, maxError, ERROR_INSIDE );
|
||||
else
|
||||
aTrack->TransformShapeToPolygon( m_bottom_copper_shapes, pcblayer, 0, maxError, ERROR_INSIDE );
|
||||
aTrack->TransformShapeToPolygon( m_poly_copper_shapes[pcblayer], pcblayer, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
else
|
||||
m_pcbModel->AddTrackSegment( aTrack, aOrigin );
|
||||
|
@ -328,16 +325,13 @@ void EXPORTER_STEP::buildZones3DShape( VECTOR2D aOrigin )
|
|||
{
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().CuStack() )
|
||||
{
|
||||
if( layer == F_Cu || layer == B_Cu )
|
||||
{
|
||||
SHAPE_POLY_SET copper_shape;
|
||||
zone->TransformSolidAreasShapesToPolygon( layer, copper_shape );
|
||||
copper_shape.Unfracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
SHAPE_POLY_SET copper_shape;
|
||||
zone->TransformSolidAreasShapesToPolygon( layer, copper_shape );
|
||||
copper_shape.Unfracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
m_pcbModel->AddCopperPolygonShapes( &copper_shape, layer == F_Cu, aOrigin, false );
|
||||
}
|
||||
m_pcbModel->AddCopperPolygonShapes( &copper_shape, layer, aOrigin, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -347,24 +341,18 @@ bool EXPORTER_STEP::buildGraphic3DShape( BOARD_ITEM* aItem, VECTOR2D aOrigin )
|
|||
{
|
||||
PCB_SHAPE* graphic = dynamic_cast<PCB_SHAPE*>( aItem );
|
||||
|
||||
if( ! graphic )
|
||||
if( !graphic )
|
||||
return false;
|
||||
|
||||
PCB_LAYER_ID pcblayer = graphic->GetLayer();
|
||||
|
||||
if( pcblayer != F_Cu && pcblayer != B_Cu )
|
||||
if( !IsCopperLayer( pcblayer ) )
|
||||
return false;
|
||||
|
||||
SHAPE_POLY_SET copper_shapes;
|
||||
int maxError = m_board->GetDesignSettings().m_MaxError;
|
||||
|
||||
|
||||
if( pcblayer == F_Cu )
|
||||
graphic->TransformShapeToPolygon( m_top_copper_shapes, pcblayer, 0,
|
||||
maxError, ERROR_INSIDE );
|
||||
else
|
||||
graphic->TransformShapeToPolygon( m_bottom_copper_shapes, pcblayer, 0,
|
||||
maxError, ERROR_INSIDE );
|
||||
graphic->TransformShapeToPolygon( m_poly_copper_shapes[pcblayer], pcblayer, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -384,6 +372,13 @@ bool EXPORTER_STEP::buildBoard3DShapes()
|
|||
wxLogWarning( _( "Board outline is malformed. Run DRC for a full analysis." ) );
|
||||
}
|
||||
|
||||
LSET layersToExport = LSET::ExternalCuMask();
|
||||
|
||||
if( m_params.m_exportInnerCopper )
|
||||
layersToExport |= LSET::InternalCuMask();
|
||||
|
||||
layersToExport &= m_board->GetEnabledLayers();
|
||||
|
||||
VECTOR2D origin;
|
||||
|
||||
// Determine the coordinate system reference:
|
||||
|
@ -401,7 +396,10 @@ bool EXPORTER_STEP::buildBoard3DShapes()
|
|||
m_pcbModel->SetBoardColor( m_solderMaskColor.r, m_solderMaskColor.g, m_solderMaskColor.b );
|
||||
m_pcbModel->SetCopperColor( m_copperColor.r, m_copperColor.g, m_copperColor.b );
|
||||
|
||||
m_pcbModel->SetPCBThickness( m_boardThickness );
|
||||
wxCHECK( m_board->GetDesignSettings().m_HasStackup, false );
|
||||
|
||||
m_pcbModel->SetStackup( m_board->GetDesignSettings().GetStackupDescriptor() );
|
||||
m_pcbModel->SetEnabledLayers( layersToExport );
|
||||
m_pcbModel->SetFuseShapes( m_params.m_fuseShapes );
|
||||
|
||||
// Note: m_params.m_BoardOutlinesChainingEpsilon is used only to build the board outlines,
|
||||
|
@ -420,7 +418,7 @@ bool EXPORTER_STEP::buildBoard3DShapes()
|
|||
for( FOOTPRINT* fp : m_board->Footprints() )
|
||||
buildFootprint3DShapes( fp, origin );
|
||||
|
||||
if( ExportTracksAndVias() )
|
||||
if( m_params.m_exportTracksVias )
|
||||
{
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
buildTrack3DShape( track, origin );
|
||||
|
@ -429,8 +427,11 @@ bool EXPORTER_STEP::buildBoard3DShapes()
|
|||
buildGraphic3DShape( item, origin );
|
||||
}
|
||||
|
||||
m_pcbModel->AddCopperPolygonShapes( &m_top_copper_shapes, true, origin, true );
|
||||
m_pcbModel->AddCopperPolygonShapes( &m_bottom_copper_shapes, false, origin, true );
|
||||
for( PCB_LAYER_ID pcblayer : layersToExport.Seq() )
|
||||
{
|
||||
m_pcbModel->AddCopperPolygonShapes( &m_poly_copper_shapes[pcblayer], pcblayer, origin,
|
||||
true );
|
||||
}
|
||||
|
||||
if( m_params.m_exportZones )
|
||||
{
|
||||
|
@ -443,7 +444,7 @@ bool EXPORTER_STEP::buildBoard3DShapes()
|
|||
msg.Printf( wxT( "Board outline: find %d initial points\n" ), pcbOutlines.FullPointCount() );
|
||||
ReportMessage( msg );
|
||||
|
||||
if( !m_pcbModel->CreatePCB( pcbOutlines, origin ) )
|
||||
if( !m_pcbModel->CreatePCB( pcbOutlines, origin, m_params.m_exportBoardBody ) )
|
||||
{
|
||||
ReportMessage( wxT( "could not create PCB solid model\n" ) );
|
||||
return false;
|
||||
|
@ -453,46 +454,6 @@ bool EXPORTER_STEP::buildBoard3DShapes()
|
|||
}
|
||||
|
||||
|
||||
void EXPORTER_STEP::calculatePcbThickness()
|
||||
{
|
||||
m_boardThickness = DEFAULT_BOARD_THICKNESS_MM;
|
||||
|
||||
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||
|
||||
if( bds.GetStackupDescriptor().GetCount() )
|
||||
{
|
||||
int thickness = 0;
|
||||
|
||||
for( BOARD_STACKUP_ITEM* item : bds.GetStackupDescriptor().GetList() )
|
||||
{
|
||||
switch( item->GetType() )
|
||||
{
|
||||
case BS_ITEM_TYPE_DIELECTRIC:
|
||||
// Dielectric can have sub-layers. Layer 0 is the main layer
|
||||
// Not frequent, but possible
|
||||
for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
|
||||
thickness += item->GetThickness( idx );
|
||||
|
||||
break;
|
||||
|
||||
case BS_ITEM_TYPE_COPPER:
|
||||
case BS_ITEM_TYPE_SOLDERMASK:
|
||||
if( item->IsEnabled() )
|
||||
thickness += item->GetThickness();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( thickness > 0 )
|
||||
m_boardThickness = pcbIUScale.IUTomm( thickness );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool EXPORTER_STEP::Export()
|
||||
{
|
||||
// Display the export time, for statistics
|
||||
|
@ -503,10 +464,6 @@ bool EXPORTER_STEP::Export()
|
|||
Message::DefaultMessenger()->AddPrinter( new KiCadPrinter( this ) );
|
||||
|
||||
ReportMessage( _( "Determining PCB data\n" ) );
|
||||
calculatePcbThickness();
|
||||
wxString msg;
|
||||
msg.Printf( _( "Board Thickness from stackup: %.3f mm\n" ), m_boardThickness );
|
||||
ReportMessage( msg );
|
||||
|
||||
if( m_params.m_outputFile.IsEmpty() )
|
||||
{
|
||||
|
@ -565,9 +522,11 @@ bool EXPORTER_STEP::Export()
|
|||
|
||||
if( m_fail || m_error )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
if( m_fail )
|
||||
{
|
||||
msg = wxString::Format( _( "Unable to create %s file.\n"
|
||||
msg = wxString::Format( _( "Unable to create %s file.\n"
|
||||
"Check that the board has a valid outline and models." ),
|
||||
m_params.GetFormatName() );
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <gal/color4d.h>
|
||||
#include <layer_ids.h>
|
||||
|
||||
// Default value to chain 2 shapes when creating the board outlines
|
||||
// from shapes on Edges.Cut layer
|
||||
|
@ -54,8 +55,11 @@ public:
|
|||
m_substModels( true ),
|
||||
m_BoardOutlinesChainingEpsilon( BOARD_DEFAULT_CHAINING_EPSILON ),
|
||||
m_boardOnly( false ),
|
||||
m_exportTracks( false ),
|
||||
m_exportBoardBody( true ),
|
||||
m_exportComponents( true ),
|
||||
m_exportTracksVias( false ),
|
||||
m_exportZones( false ),
|
||||
m_exportInnerCopper( false ),
|
||||
m_fuseShapes( false ),
|
||||
m_optimizeStep( true ),
|
||||
m_format( FORMAT::STEP )
|
||||
|
@ -80,8 +84,11 @@ public:
|
|||
bool m_substModels;
|
||||
double m_BoardOutlinesChainingEpsilon;
|
||||
bool m_boardOnly;
|
||||
bool m_exportTracks;
|
||||
bool m_exportBoardBody;
|
||||
bool m_exportComponents;
|
||||
bool m_exportTracksVias;
|
||||
bool m_exportZones;
|
||||
bool m_exportInnerCopper;
|
||||
bool m_fuseShapes;
|
||||
bool m_optimizeStep;
|
||||
FORMAT m_format;
|
||||
|
@ -104,16 +111,12 @@ public:
|
|||
void SetFail() { m_fail = true; }
|
||||
void SetWarn() { m_warn = true; }
|
||||
|
||||
/// Return rue to export tracks and vias on top and bottom copper layers
|
||||
bool ExportTracksAndVias() { return m_params.m_exportTracks; }
|
||||
|
||||
private:
|
||||
bool buildBoard3DShapes();
|
||||
bool buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin );
|
||||
bool buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin );
|
||||
void buildZones3DShape( VECTOR2D aOrigin );
|
||||
bool buildGraphic3DShape( BOARD_ITEM* aItem, VECTOR2D aOrigin );
|
||||
void calculatePcbThickness();
|
||||
|
||||
EXPORTER_STEP_PARAMS m_params;
|
||||
std::unique_ptr<FILENAME_RESOLVER> m_resolver;
|
||||
|
@ -130,10 +133,7 @@ private:
|
|||
/// used to identify items in step file
|
||||
wxString m_pcbBaseName;
|
||||
|
||||
double m_boardThickness;
|
||||
|
||||
SHAPE_POLY_SET m_top_copper_shapes;
|
||||
SHAPE_POLY_SET m_bottom_copper_shapes;
|
||||
std::map<PCB_LAYER_ID, SHAPE_POLY_SET> m_poly_copper_shapes;
|
||||
|
||||
KIGFX::COLOR4D m_solderMaskColor;
|
||||
KIGFX::COLOR4D m_copperColor;
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include <build_version.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <geometry/shape_circle.h>
|
||||
#include <board_stackup_manager/board_stackup.h>
|
||||
#include <board_stackup_manager/stackup_predefined_prms.h>
|
||||
|
||||
#include "step_pcb_model.h"
|
||||
#include "streamwrapper.h"
|
||||
|
@ -59,27 +61,33 @@
|
|||
#include <STEPCAFControl_Reader.hxx>
|
||||
#include <STEPCAFControl_Writer.hxx>
|
||||
#include <APIHeaderSection_MakeHeader.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
#include <Standard_Version.hxx>
|
||||
#include <TCollection_ExtendedString.hxx>
|
||||
#include <TDocStd_Document.hxx>
|
||||
#include <TDataStd_Name.hxx>
|
||||
#include <TDataStd_TreeNode.hxx>
|
||||
#include <TDF_LabelSequence.hxx>
|
||||
#include <TDF_ChildIterator.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <XCAFApp_Application.hxx>
|
||||
#include <XCAFDoc.hxx>
|
||||
#include <XCAFDoc_DocumentTool.hxx>
|
||||
#include <XCAFDoc_ColorTool.hxx>
|
||||
#include <XCAFDoc_ShapeTool.hxx>
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <BRepBuilderAPI.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepBuilderAPI_GTransform.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepPrimAPI_MakePrism.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <BRepLib_MakeWire.hxx>
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
#include <BRepAlgoAPI_Fuse.hxx>
|
||||
#include <ShapeUpgrade_UnifySameDomain.hxx>
|
||||
|
@ -87,19 +95,10 @@
|
|||
#include <BRepBndLib.hxx>
|
||||
#include <Bnd_BoundSortBox.hxx>
|
||||
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Builder.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <GC_MakeArcOfCircle.hxx>
|
||||
|
@ -203,8 +202,6 @@ STEP_PCB_MODEL::STEP_PCB_MODEL( const wxString& aPcbName )
|
|||
m_components = 0;
|
||||
m_precision = USER_PREC;
|
||||
m_angleprec = USER_ANGLE_PREC;
|
||||
m_boardThickness = BOARD_THICKNESS_DEFAULT_MM;
|
||||
m_copperThickness = COPPER_THICKNESS_DEFAULT_MM;
|
||||
m_mergeOCCMaxDist = OCC_MAX_DISTANCE_TO_MERGE_POINTS;
|
||||
m_minx = 1.0e10; // absurdly large number; any valid PCB X value will be smaller
|
||||
m_pcbName = aPcbName;
|
||||
|
@ -219,141 +216,149 @@ STEP_PCB_MODEL::~STEP_PCB_MODEL()
|
|||
m_doc->Close();
|
||||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin )
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
for( PCB_LAYER_ID pcb_layer = F_Cu; ; pcb_layer = B_Cu )
|
||||
for( PCB_LAYER_ID pcb_layer : aPad->GetLayerSet().Seq() )
|
||||
{
|
||||
if( !IsCopperLayer( pcb_layer ) )
|
||||
continue;
|
||||
|
||||
if( !m_enabledLayers.Contains( pcb_layer ) )
|
||||
continue;
|
||||
|
||||
TopoDS_Shape curr_shape;
|
||||
double Zpos = pcb_layer == F_Cu ? m_boardThickness : -m_copperThickness;
|
||||
|
||||
if( aPad->IsOnLayer( pcb_layer ) )
|
||||
double Zpos, thickness;
|
||||
getLayerZPlacement( pcb_layer, Zpos, thickness );
|
||||
|
||||
// Make a shape on copper layers
|
||||
std::shared_ptr<SHAPE> effShapePtr = aPad->GetEffectiveShape( pcb_layer );
|
||||
|
||||
wxCHECK( effShapePtr->Type() == SHAPE_TYPE::SH_COMPOUND, false );
|
||||
SHAPE_COMPOUND* compoundShape = static_cast<SHAPE_COMPOUND*>( effShapePtr.get() );
|
||||
|
||||
std::vector<TopoDS_Shape> topodsShapes;
|
||||
|
||||
for( SHAPE* shape : compoundShape->Shapes() )
|
||||
{
|
||||
// Make a shape on top/bottom copper layer
|
||||
std::shared_ptr<SHAPE> effShapePtr = aPad->GetEffectiveShape( pcb_layer );
|
||||
|
||||
wxCHECK( effShapePtr->Type() == SHAPE_TYPE::SH_COMPOUND, false );
|
||||
SHAPE_COMPOUND* compoundShape = static_cast<SHAPE_COMPOUND*>( effShapePtr.get() );
|
||||
|
||||
std::vector<TopoDS_Shape> topodsShapes;
|
||||
|
||||
for( SHAPE* shape : compoundShape->Shapes() )
|
||||
if( shape->Type() == SHAPE_TYPE::SH_SEGMENT || shape->Type() == SHAPE_TYPE::SH_CIRCLE )
|
||||
{
|
||||
if( shape->Type() == SHAPE_TYPE::SH_SEGMENT
|
||||
|| shape->Type() == SHAPE_TYPE::SH_CIRCLE )
|
||||
VECTOR2I start, end;
|
||||
int width = 0;
|
||||
|
||||
if( shape->Type() == SHAPE_TYPE::SH_SEGMENT )
|
||||
{
|
||||
VECTOR2I start, end;
|
||||
int width = 0;
|
||||
SHAPE_SEGMENT* sh_seg = static_cast<SHAPE_SEGMENT*>( shape );
|
||||
|
||||
if( shape->Type() == SHAPE_TYPE::SH_SEGMENT )
|
||||
{
|
||||
SHAPE_SEGMENT* sh_seg = static_cast<SHAPE_SEGMENT*>( shape );
|
||||
start = sh_seg->GetSeg().A;
|
||||
end = sh_seg->GetSeg().B;
|
||||
width = sh_seg->GetWidth();
|
||||
}
|
||||
else if( shape->Type() == SHAPE_TYPE::SH_CIRCLE )
|
||||
{
|
||||
SHAPE_CIRCLE* sh_circ = static_cast<SHAPE_CIRCLE*>( shape );
|
||||
|
||||
start = sh_seg->GetSeg().A;
|
||||
end = sh_seg->GetSeg().B;
|
||||
width = sh_seg->GetWidth();
|
||||
}
|
||||
else if( shape->Type() == SHAPE_TYPE::SH_CIRCLE )
|
||||
{
|
||||
SHAPE_CIRCLE* sh_circ = static_cast<SHAPE_CIRCLE*>( shape );
|
||||
start = end = sh_circ->GetCenter();
|
||||
width = sh_circ->GetRadius() * 2;
|
||||
}
|
||||
|
||||
start = end = sh_circ->GetCenter();
|
||||
width = sh_circ->GetRadius() * 2;
|
||||
}
|
||||
TopoDS_Shape topods_shape;
|
||||
|
||||
TopoDS_Shape topods_shape;
|
||||
|
||||
if( MakeShapeAsThickSegment( topods_shape, start, end, width, m_copperThickness,
|
||||
Zpos, aOrigin ) )
|
||||
{
|
||||
topodsShapes.emplace_back( topods_shape );
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
if( MakeShapeAsThickSegment( topods_shape, start, end, width, thickness, Zpos,
|
||||
aOrigin ) )
|
||||
{
|
||||
topodsShapes.emplace_back( topods_shape );
|
||||
}
|
||||
else
|
||||
{
|
||||
SHAPE_POLY_SET polySet;
|
||||
shape->TransformToPolygon( polySet, ARC_HIGH_DEF, ERROR_INSIDE );
|
||||
|
||||
success &= MakeShapes( topodsShapes, polySet, m_copperThickness, Zpos, aOrigin );
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fuse shapes
|
||||
if( topodsShapes.size() == 1 )
|
||||
{
|
||||
m_board_copper_pads.emplace_back( topodsShapes.front() );
|
||||
}
|
||||
else
|
||||
{
|
||||
BRepAlgoAPI_Fuse mkFuse;
|
||||
TopTools_ListOfShape shapeArguments, shapeTools;
|
||||
SHAPE_POLY_SET polySet;
|
||||
shape->TransformToPolygon( polySet, ARC_HIGH_DEF, ERROR_INSIDE );
|
||||
|
||||
for( TopoDS_Shape& sh : topodsShapes )
|
||||
{
|
||||
if( sh.IsNull() )
|
||||
continue;
|
||||
|
||||
if( shapeArguments.IsEmpty() )
|
||||
shapeArguments.Append( sh );
|
||||
else
|
||||
shapeTools.Append( sh );
|
||||
}
|
||||
|
||||
mkFuse.SetRunParallel( true );
|
||||
mkFuse.SetToFillHistory( false );
|
||||
mkFuse.SetArguments( shapeArguments );
|
||||
mkFuse.SetTools( shapeTools );
|
||||
mkFuse.Build();
|
||||
|
||||
if( mkFuse.IsDone() )
|
||||
{
|
||||
TopoDS_Shape fusedShape = mkFuse.Shape();
|
||||
|
||||
ShapeUpgrade_UnifySameDomain unify( fusedShape, false, true, false );
|
||||
unify.History() = nullptr;
|
||||
unify.Build();
|
||||
|
||||
TopoDS_Shape unifiedShapes = unify.Shape();
|
||||
|
||||
if( !unifiedShapes.IsNull() )
|
||||
{
|
||||
m_board_copper_pads.emplace_back( unifiedShapes );
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportMessage(
|
||||
_( "** ShapeUpgrade_UnifySameDomain produced a null shape **\n" ) );
|
||||
m_board_copper_pads.emplace_back( fusedShape );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( TopoDS_Shape& sh : topodsShapes )
|
||||
m_board_copper_pads.emplace_back( sh );
|
||||
}
|
||||
success &= MakeShapes( topodsShapes, polySet, thickness, Zpos, aOrigin );
|
||||
}
|
||||
}
|
||||
|
||||
if( pcb_layer == B_Cu )
|
||||
break;
|
||||
// Fuse shapes
|
||||
if( topodsShapes.size() == 1 )
|
||||
{
|
||||
m_board_copper_pads.emplace_back( topodsShapes.front() );
|
||||
}
|
||||
else
|
||||
{
|
||||
BRepAlgoAPI_Fuse mkFuse;
|
||||
TopTools_ListOfShape shapeArguments, shapeTools;
|
||||
|
||||
for( TopoDS_Shape& sh : topodsShapes )
|
||||
{
|
||||
if( sh.IsNull() )
|
||||
continue;
|
||||
|
||||
if( shapeArguments.IsEmpty() )
|
||||
shapeArguments.Append( sh );
|
||||
else
|
||||
shapeTools.Append( sh );
|
||||
}
|
||||
|
||||
mkFuse.SetRunParallel( true );
|
||||
mkFuse.SetToFillHistory( false );
|
||||
mkFuse.SetArguments( shapeArguments );
|
||||
mkFuse.SetTools( shapeTools );
|
||||
mkFuse.Build();
|
||||
|
||||
if( mkFuse.IsDone() )
|
||||
{
|
||||
TopoDS_Shape fusedShape = mkFuse.Shape();
|
||||
|
||||
ShapeUpgrade_UnifySameDomain unify( fusedShape, false, true, false );
|
||||
unify.History() = nullptr;
|
||||
unify.Build();
|
||||
|
||||
TopoDS_Shape unifiedShapes = unify.Shape();
|
||||
|
||||
if( !unifiedShapes.IsNull() )
|
||||
{
|
||||
m_board_copper_pads.emplace_back( unifiedShapes );
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportMessage(
|
||||
_( "** ShapeUpgrade_UnifySameDomain produced a null shape **\n" ) );
|
||||
m_board_copper_pads.emplace_back( fusedShape );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( TopoDS_Shape& sh : topodsShapes )
|
||||
m_board_copper_pads.emplace_back( sh );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( aPad->GetAttribute() == PAD_ATTRIB::PTH && aPad->IsOnLayer( F_Cu )
|
||||
&& aPad->IsOnLayer( B_Cu ) )
|
||||
{
|
||||
double f_pos, f_thickness;
|
||||
double b_pos, b_thickness;
|
||||
getLayerZPlacement( F_Cu, f_pos, f_thickness );
|
||||
getLayerZPlacement( B_Cu, b_pos, b_thickness );
|
||||
double top = std::max( f_pos, f_pos + f_thickness );
|
||||
double bottom = std::min( b_pos, b_pos + b_thickness );
|
||||
|
||||
TopoDS_Shape plating;
|
||||
|
||||
std::shared_ptr<SHAPE_SEGMENT> seg_hole = aPad->GetEffectiveHoleShape();
|
||||
double width = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
|
||||
|
||||
if( MakeShapeAsThickSegment( plating, seg_hole->GetSeg().A, seg_hole->GetSeg().B, width,
|
||||
m_boardThickness + m_copperThickness * 2, -m_copperThickness,
|
||||
aOrigin ) )
|
||||
( top - bottom ), bottom, aOrigin ) )
|
||||
{
|
||||
m_board_copper_pads.push_back( plating );
|
||||
}
|
||||
|
@ -394,15 +399,16 @@ bool STEP_PCB_MODEL::AddTrackSegment( const PCB_TRACK* aTrack, const VECTOR2D& a
|
|||
{
|
||||
PCB_LAYER_ID pcblayer = aTrack->GetLayer();
|
||||
|
||||
if( pcblayer != F_Cu && pcblayer != B_Cu )
|
||||
return false;
|
||||
if( !m_enabledLayers.Contains( pcblayer ) )
|
||||
return true;
|
||||
|
||||
TopoDS_Shape shape;
|
||||
double zposition = pcblayer == F_Cu ? m_boardThickness : -m_copperThickness;
|
||||
|
||||
double zposition, thickness;
|
||||
getLayerZPlacement( pcblayer, zposition, thickness );
|
||||
|
||||
bool success = MakeShapeAsThickSegment( shape, aTrack->GetStart(), aTrack->GetEnd(),
|
||||
aTrack->GetWidth(), m_copperThickness,
|
||||
zposition, aOrigin );
|
||||
aTrack->GetWidth(), thickness, zposition, aOrigin );
|
||||
|
||||
if( success )
|
||||
m_board_copper_tracks.push_back( shape );
|
||||
|
@ -411,7 +417,65 @@ bool STEP_PCB_MODEL::AddTrackSegment( const PCB_TRACK* aTrack, const VECTOR2D& a
|
|||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::AddCopperPolygonShapes( const SHAPE_POLY_SET* aPolyShapes, bool aOnTop,
|
||||
void STEP_PCB_MODEL::getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos,
|
||||
double& aThickness )
|
||||
{
|
||||
int z = 0;
|
||||
int thickness = 0;
|
||||
bool wasPrepreg = false;
|
||||
|
||||
const std::vector<BOARD_STACKUP_ITEM*>& materials = m_stackup.GetList();
|
||||
|
||||
for( auto it = materials.rbegin(); it != materials.rend(); ++it )
|
||||
{
|
||||
const BOARD_STACKUP_ITEM* item = *it;
|
||||
|
||||
if( item->GetType() == BS_ITEM_TYPE_COPPER )
|
||||
{
|
||||
// Inner copper position is usually inside prepreg
|
||||
if( ( wasPrepreg || aLayer == B_Cu ) && aLayer != F_Cu )
|
||||
thickness = -item->GetThickness();
|
||||
else
|
||||
thickness = item->GetThickness();
|
||||
|
||||
if( item->GetBrdLayerId() == aLayer )
|
||||
break;
|
||||
|
||||
z += thickness;
|
||||
}
|
||||
else if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
|
||||
{
|
||||
wasPrepreg = ( item->GetTypeName() == KEY_PREPREG );
|
||||
|
||||
// Dielectric can have sub-layers. Layer 0 is the main layer
|
||||
// Not frequent, but possible
|
||||
for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
|
||||
z += item->GetThickness( idx );
|
||||
}
|
||||
}
|
||||
|
||||
aZPos = pcbIUScale.IUTomm( z );
|
||||
aThickness = pcbIUScale.IUTomm( thickness );
|
||||
}
|
||||
|
||||
|
||||
void STEP_PCB_MODEL::getBoardBodyZPlacement( double& aZPos, double& aThickness )
|
||||
{
|
||||
double f_pos, f_thickness;
|
||||
double b_pos, b_thickness;
|
||||
getLayerZPlacement( F_Cu, f_pos, f_thickness );
|
||||
getLayerZPlacement( B_Cu, b_pos, b_thickness );
|
||||
double top = std::min( f_pos, f_pos + f_thickness );
|
||||
double bottom = std::max( b_pos, b_pos + b_thickness );
|
||||
|
||||
aThickness = ( top - bottom );
|
||||
aZPos = bottom;
|
||||
|
||||
wxASSERT( aZPos == 0.0 );
|
||||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::AddCopperPolygonShapes( const SHAPE_POLY_SET* aPolyShapes, PCB_LAYER_ID aLayer,
|
||||
const VECTOR2D& aOrigin, bool aTrack )
|
||||
{
|
||||
bool success = true;
|
||||
|
@ -419,14 +483,18 @@ bool STEP_PCB_MODEL::AddCopperPolygonShapes( const SHAPE_POLY_SET* aPolyShapes,
|
|||
if( aPolyShapes->IsEmpty() )
|
||||
return true;
|
||||
|
||||
double z_pos = aOnTop ? m_boardThickness : -m_copperThickness;
|
||||
if( !m_enabledLayers.Contains( aLayer ) )
|
||||
return true;
|
||||
|
||||
if( !MakeShapes( aTrack ? m_board_copper_tracks : m_board_copper_zones, *aPolyShapes,
|
||||
m_copperThickness, z_pos, aOrigin ) )
|
||||
double z_pos, thickness;
|
||||
getLayerZPlacement( aLayer, z_pos, thickness );
|
||||
|
||||
if( !MakeShapes( aTrack ? m_board_copper_tracks : m_board_copper_zones, *aPolyShapes, thickness,
|
||||
z_pos, aOrigin ) )
|
||||
{
|
||||
ReportMessage( wxString::Format(
|
||||
wxT( "Could not add shape (%d points) to copper layer on %s.\n" ),
|
||||
aPolyShapes->FullPointCount(), aOnTop ? wxT( "top" ) : wxT( "bottom" ) ) );
|
||||
ReportMessage(
|
||||
wxString::Format( wxT( "Could not add shape (%d points) to copper layer on %s.\n" ),
|
||||
aPolyShapes->FullPointCount(), LayerName( aLayer ) ) );
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
@ -446,7 +514,15 @@ bool STEP_PCB_MODEL::AddPadHole( const PAD* aPad, const VECTOR2D& aOrigin )
|
|||
const double margin = 0.01; // a small margin on the Z axix to be sure the hole
|
||||
// is bigger than the board with copper
|
||||
// must be > OCC_MAX_DISTANCE_TO_MERGE_POINTS
|
||||
double holeZsize = m_boardThickness + ( m_copperThickness * 2 ) + ( margin * 2 );
|
||||
|
||||
double f_pos, f_thickness;
|
||||
double b_pos, b_thickness;
|
||||
getLayerZPlacement( F_Cu, f_pos, f_thickness );
|
||||
getLayerZPlacement( B_Cu, b_pos, b_thickness );
|
||||
double top = std::max( f_pos, f_pos + f_thickness );
|
||||
double bottom = std::min( b_pos, b_pos + b_thickness );
|
||||
|
||||
double holeZsize = ( top - bottom ) + ( margin * 2 );
|
||||
|
||||
std::shared_ptr<SHAPE_SEGMENT> seg_hole = aPad->GetEffectiveHoleShape();
|
||||
|
||||
|
@ -456,7 +532,7 @@ bool STEP_PCB_MODEL::AddPadHole( const PAD* aPad, const VECTOR2D& aOrigin )
|
|||
TopoDS_Shape copperHole, boardHole;
|
||||
|
||||
if( MakeShapeAsThickSegment( copperHole, seg_hole->GetSeg().A, seg_hole->GetSeg().B,
|
||||
copperDrill, holeZsize, -m_copperThickness - margin, aOrigin ) )
|
||||
copperDrill, holeZsize, bottom - margin, aOrigin ) )
|
||||
{
|
||||
m_copperCutouts.push_back( copperHole );
|
||||
}
|
||||
|
@ -466,7 +542,7 @@ bool STEP_PCB_MODEL::AddPadHole( const PAD* aPad, const VECTOR2D& aOrigin )
|
|||
}
|
||||
|
||||
if( MakeShapeAsThickSegment( boardHole, seg_hole->GetSeg().A, seg_hole->GetSeg().B, boardDrill,
|
||||
holeZsize, -m_copperThickness - margin, aOrigin ) )
|
||||
holeZsize, bottom - margin, aOrigin ) )
|
||||
{
|
||||
m_boardCutouts.push_back( boardHole );
|
||||
}
|
||||
|
@ -534,14 +610,9 @@ bool STEP_PCB_MODEL::AddComponent( const std::string& aFileNameUTF8, const std::
|
|||
}
|
||||
|
||||
|
||||
void STEP_PCB_MODEL::SetPCBThickness( double aThickness )
|
||||
void STEP_PCB_MODEL::SetEnabledLayers( const LSET& aLayers )
|
||||
{
|
||||
if( aThickness < 0.0 )
|
||||
m_boardThickness = BOARD_THICKNESS_DEFAULT_MM;
|
||||
else if( aThickness < BOARD_THICKNESS_MIN_MM )
|
||||
m_boardThickness = BOARD_THICKNESS_MIN_MM;
|
||||
else
|
||||
m_boardThickness = aThickness;
|
||||
m_enabledLayers = aLayers;
|
||||
}
|
||||
|
||||
|
||||
|
@ -551,6 +622,12 @@ void STEP_PCB_MODEL::SetFuseShapes( bool aValue )
|
|||
}
|
||||
|
||||
|
||||
void STEP_PCB_MODEL::SetStackup( const BOARD_STACKUP& aStackup )
|
||||
{
|
||||
m_stackup = aStackup;
|
||||
}
|
||||
|
||||
|
||||
void STEP_PCB_MODEL::SetBoardColor( double r, double g, double b )
|
||||
{
|
||||
m_boardColor[0] = r;
|
||||
|
@ -1001,7 +1078,7 @@ bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE
|
|||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
|
||||
bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin, bool aPushBoardBody )
|
||||
{
|
||||
if( m_hasPCB )
|
||||
{
|
||||
|
@ -1014,10 +1091,14 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
|
|||
Handle( XCAFDoc_ColorTool ) colorTool = XCAFDoc_DocumentTool::ColorTool( m_doc->Main() );
|
||||
m_hasPCB = true; // whether or not operations fail we note that CreatePCB has been invoked
|
||||
|
||||
|
||||
// Support for more than one main outline (more than one board)
|
||||
ReportMessage( wxString::Format( wxT( "Build board outlines (%d outlines) with %d points.\n" ),
|
||||
aOutline.OutlineCount(), aOutline.FullPointCount() ) );
|
||||
|
||||
double boardThickness;
|
||||
double boardZPos;
|
||||
getBoardBodyZPlacement( boardZPos, boardThickness );
|
||||
|
||||
#if 0
|
||||
// This code should work, and it is working most of time
|
||||
// However there are issues if the main outline is a circle with holes:
|
||||
|
@ -1025,7 +1106,7 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
|
|||
// see bug https://gitlab.com/kicad/code/kicad/-/issues/17446
|
||||
// (Holes are missing from STEP export with circular PCB outline)
|
||||
// Hard to say if the bug is in our code or in OCC 7.7
|
||||
if( !MakeShapes( m_board_outlines, aOutline, m_boardThickness, 0.0, aOrigin ) )
|
||||
if( !MakeShapes( m_board_outlines, aOutline, boardThickness, boardZPos, aOrigin ) )
|
||||
{
|
||||
// Error
|
||||
ReportMessage( wxString::Format(
|
||||
|
@ -1043,18 +1124,19 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
|
|||
|
||||
if( contId == 0 ) // main Outline
|
||||
{
|
||||
if( !MakeShapes( m_board_outlines, polyset, m_boardThickness, 0.0, aOrigin ) )
|
||||
if( !MakeShapes( m_board_outlines, polyset, boardThickness, boardZPos, aOrigin ) )
|
||||
ReportMessage( wxT( "OCC error creating main outline.\n" ) );
|
||||
}
|
||||
else // Hole inside the main outline
|
||||
{
|
||||
if( !MakeShapes( m_boardCutouts, polyset, m_boardThickness, 0.0, aOrigin ) )
|
||||
if( !MakeShapes( m_boardCutouts, polyset, boardThickness, boardZPos, aOrigin ) )
|
||||
ReportMessage( wxT( "OCC error creating hole in main outline.\n" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Even if we've disabled board body export, we still need the shapes for bounding box calculations.
|
||||
Bnd_Box brdBndBox;
|
||||
|
||||
for( const TopoDS_Shape& brdShape : m_board_outlines )
|
||||
|
@ -1312,7 +1394,8 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
|
|||
pushToAssembly( m_board_copper_pads, copper_color, "pad" );
|
||||
pushToAssembly( m_board_copper_fused, copper_color, "copper" );
|
||||
|
||||
pushToAssembly( m_board_outlines, board_color, "PCB" );
|
||||
if( aPushBoardBody )
|
||||
pushToAssembly( m_board_outlines, board_color, "PCB" );
|
||||
|
||||
#if( defined OCC_VERSION_HEX ) && ( OCC_VERSION_HEX > 0x070101 )
|
||||
m_assy->UpdateAssemblies();
|
||||
|
@ -1719,10 +1802,17 @@ bool STEP_PCB_MODEL::getModelLocation( bool aBottom, VECTOR2D aPosition, double
|
|||
// Offset board thickness
|
||||
aOffset.z += BOARD_OFFSET;
|
||||
|
||||
double boardThickness;
|
||||
double boardZPos;
|
||||
getBoardBodyZPlacement( boardZPos, boardThickness );
|
||||
double top = std::max( boardZPos, boardZPos + boardThickness );
|
||||
double bottom = std::min( boardZPos, boardZPos + boardThickness );
|
||||
|
||||
gp_Trsf lRot;
|
||||
|
||||
if( aBottom )
|
||||
{
|
||||
aOffset.z -= bottom;
|
||||
lRot.SetRotation( gp_Ax1( gp_Pnt( 0.0, 0.0, 0.0 ), gp_Dir( 0.0, 0.0, 1.0 ) ), aRotation );
|
||||
lPos.Multiply( lRot );
|
||||
lRot.SetRotation( gp_Ax1( gp_Pnt( 0.0, 0.0, 0.0 ), gp_Dir( 1.0, 0.0, 0.0 ) ), M_PI );
|
||||
|
@ -1730,7 +1820,7 @@ bool STEP_PCB_MODEL::getModelLocation( bool aBottom, VECTOR2D aPosition, double
|
|||
}
|
||||
else
|
||||
{
|
||||
aOffset.z += m_boardThickness;
|
||||
aOffset.z += top;
|
||||
lRot.SetRotation( gp_Ax1( gp_Pnt( 0.0, 0.0, 0.0 ), gp_Dir( 0.0, 0.0, 1.0 ) ), aRotation );
|
||||
lPos.Multiply( lRot );
|
||||
}
|
||||
|
|
|
@ -31,17 +31,14 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <Standard_Version.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <TDocStd_Document.hxx>
|
||||
#include <XCAFApp_Application.hxx>
|
||||
#include <XCAFDoc_ShapeTool.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <TDF_Label.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
|
||||
#include <math/vector2d.h>
|
||||
#include <math/vector3.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <board_stackup_manager/board_stackup.h>
|
||||
|
||||
/**
|
||||
* Default distance between points to treat them as separate ones (mm)
|
||||
|
@ -69,6 +66,10 @@ static constexpr double ARC_TO_SEGMENT_MAX_ERROR_MM = 0.005;
|
|||
|
||||
class PAD;
|
||||
|
||||
class TDocStd_Document;
|
||||
class XCAFApp_Application;
|
||||
class XCAFDoc_ShapeTool;
|
||||
|
||||
typedef std::pair< std::string, TDF_Label > MODEL_DATUM;
|
||||
typedef std::map< std::string, TDF_Label > MODEL_MAP;
|
||||
|
||||
|
@ -93,7 +94,7 @@ public:
|
|||
bool AddTrackSegment( const PCB_TRACK* aTrack, const VECTOR2D& aOrigin );
|
||||
|
||||
// add a set of polygons (must be in final position) on top or bottom of the board as copper
|
||||
bool AddCopperPolygonShapes( const SHAPE_POLY_SET* aPolyShapes, bool aOnTop,
|
||||
bool AddCopperPolygonShapes( const SHAPE_POLY_SET* aPolyShapes, PCB_LAYER_ID aLayer,
|
||||
const VECTOR2D& aOrigin, bool aTrack );
|
||||
|
||||
// add a component at the given position and orientation
|
||||
|
@ -104,15 +105,12 @@ public:
|
|||
void SetBoardColor( double r, double g, double b );
|
||||
void SetCopperColor( double r, double g, double b );
|
||||
|
||||
// set the thickness of the PCB (mm); the top of the PCB shall be at Z = aThickness
|
||||
// aThickness < 0.0 == use default thickness
|
||||
// aThickness <= THICKNESS_MIN == use THICKNESS_MIN
|
||||
// aThickness > THICKNESS_MIN == use aThickness
|
||||
void SetPCBThickness( double aThickness );
|
||||
void SetEnabledLayers( const LSET& aLayers );
|
||||
|
||||
// enable fusing the geometry
|
||||
void SetFuseShapes( bool aValue );
|
||||
|
||||
void SetStackup( const BOARD_STACKUP& aStackup );
|
||||
|
||||
// Set the max distance (in mm) to consider 2 points have the same coordinates
|
||||
// and can be merged
|
||||
void OCCSetMergeMaxDistance( double aDistance = OCC_MAX_DISTANCE_TO_MERGE_POINTS );
|
||||
|
@ -120,7 +118,7 @@ public:
|
|||
void SetMaxError( int aMaxError ) { m_maxError = aMaxError; }
|
||||
|
||||
// create the PCB model using the current outlines and drill holes
|
||||
bool CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin );
|
||||
bool CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin, bool aPushBoardBody );
|
||||
|
||||
/**
|
||||
* Convert a SHAPE_POLY_SET to TopoDS_Shape's (polygonal vertical prisms)
|
||||
|
@ -196,12 +194,9 @@ private:
|
|||
*/
|
||||
bool isBoardOutlineValid();
|
||||
|
||||
/** create one solid board using current outline and drill holes set
|
||||
* @param aIdx is the main outline index
|
||||
* @param aOutline is the set of outlines with holes
|
||||
* @param aOrigin is the coordinate origin for 3 view
|
||||
*/
|
||||
bool createOneBoard( int aIdx, SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin );
|
||||
void getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos, double& aThickness );
|
||||
|
||||
void getBoardBodyZPlacement( double& aZPos, double& aThickness );
|
||||
|
||||
/**
|
||||
* Load a 3D model data.
|
||||
|
@ -240,8 +235,8 @@ private:
|
|||
double m_angleprec; // angle numeric precision
|
||||
double m_boardColor[3]; // board body, RGB values
|
||||
double m_copperColor[3]; // copper, RGB values
|
||||
double m_boardThickness; // PCB thickness, mm
|
||||
double m_copperThickness; // copper thickness, mm
|
||||
BOARD_STACKUP m_stackup; // board stackup
|
||||
LSET m_enabledLayers; // a set of layers enabled for export
|
||||
|
||||
double m_minx; // leftmost curve point
|
||||
double m_mergeOCCMaxDist; // minimum distance (mm) below which two
|
||||
|
|
|
@ -190,8 +190,11 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
|
|||
else
|
||||
{
|
||||
EXPORTER_STEP_PARAMS params;
|
||||
params.m_exportTracks = aStepJob->m_exportTracks;
|
||||
params.m_exportBoardBody = aStepJob->m_exportBoardBody;
|
||||
params.m_exportComponents = aStepJob->m_exportComponents;
|
||||
params.m_exportTracksVias = aStepJob->m_exportTracks;
|
||||
params.m_exportZones = aStepJob->m_exportZones;
|
||||
params.m_exportInnerCopper = aStepJob->m_exportInnerCopper;
|
||||
params.m_fuseShapes = aStepJob->m_fuseShapes;
|
||||
params.m_includeUnspecified = aStepJob->m_includeUnspecified;
|
||||
params.m_includeDNP = aStepJob->m_includeDNP;
|
||||
|
|
Loading…
Reference in New Issue