mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-19 18:51:40 +00:00
ADDED: STL and PLY (since OCCT 7.7.0) 3D model export.
This commit is contained in:
parent
dbf68a80b8
commit
3b987776c7
cmake
common
include
kicad
pcbnew
@ -87,6 +87,7 @@ set( OCC_LIBS_POST_78
|
||||
TKDESTEP
|
||||
TKDESTL
|
||||
TKDEVRML
|
||||
TKDEPLY
|
||||
)
|
||||
|
||||
set(OCC_TYPE "OpenCASCADE Standard Edition")
|
||||
|
@ -30,6 +30,8 @@ NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_3D::FORMAT,
|
||||
{ JOB_EXPORT_PCB_3D::FORMAT::GLB, "step" },
|
||||
{ JOB_EXPORT_PCB_3D::FORMAT::VRML, "vrml" },
|
||||
{ JOB_EXPORT_PCB_3D::FORMAT::XAO, "xao" },
|
||||
{ JOB_EXPORT_PCB_3D::FORMAT::PLY, "ply" },
|
||||
{ JOB_EXPORT_PCB_3D::FORMAT::STL, "stl" },
|
||||
} )
|
||||
|
||||
|
||||
@ -49,6 +51,8 @@ wxString EXPORTER_STEP_PARAMS::GetDefaultExportExtension() const
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::BREP: return wxS( "brep" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::XAO: return wxS( "xao" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::GLB: return wxS( "glb" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::PLY: return wxS( "ply" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::STL: return wxS( "stl" );
|
||||
default: return wxEmptyString; // shouldn't happen
|
||||
}
|
||||
}
|
||||
@ -63,6 +67,8 @@ wxString EXPORTER_STEP_PARAMS::GetFormatName() const
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::BREP: return wxS( "BREP" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::XAO: return wxS( "XAO" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::GLB: return wxS( "Binary GLTF" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::PLY: return wxS( "PLY" );
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::STL: return wxS( "STL" );
|
||||
default: return wxEmptyString; // shouldn't happen
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,9 @@ public:
|
||||
STEP,
|
||||
BREP,
|
||||
XAO,
|
||||
GLB
|
||||
GLB,
|
||||
PLY,
|
||||
STL
|
||||
};
|
||||
|
||||
wxString m_NetFilter;
|
||||
@ -109,7 +111,9 @@ public:
|
||||
BREP,
|
||||
XAO,
|
||||
GLB,
|
||||
VRML
|
||||
VRML,
|
||||
PLY,
|
||||
STL
|
||||
};
|
||||
|
||||
enum class VRML_UNITS
|
||||
|
@ -203,6 +203,8 @@ const std::string FILEEXT::StepFileAbrvExtension( "stp" );
|
||||
const std::string FILEEXT::GltfBinaryFileExtension( "glb" );
|
||||
const std::string FILEEXT::BrepFileExtension( "brep" );
|
||||
const std::string FILEEXT::XaoFileExtension( "xao" );
|
||||
const std::string FILEEXT::PlyFileExtension( "ply" );
|
||||
const std::string FILEEXT::StlFileExtension( "stl" );
|
||||
|
||||
const wxString FILEEXT::GerberFileExtensionsRegex( "(gbr|gko|pho|(g[tb][alops])|(gm?\\d\\d*)|(gp[tb]))" );
|
||||
|
||||
|
@ -192,6 +192,8 @@ public:
|
||||
static const std::string GltfBinaryFileExtension;
|
||||
static const std::string BrepFileExtension;
|
||||
static const std::string XaoFileExtension;
|
||||
static const std::string PlyFileExtension;
|
||||
static const std::string StlFileExtension;
|
||||
|
||||
static const std::string KiCadJobSetFileExtension;
|
||||
|
||||
|
@ -74,7 +74,7 @@ CLI::PCB_EXPORT_3D_COMMAND::PCB_EXPORT_3D_COMMAND( const std::string& aNa
|
||||
m_argParser.add_argument( ARG_FORMAT )
|
||||
.default_value( std::string( "step" ) )
|
||||
.help( UTF8STDSTR(
|
||||
_( "Output file format, options: step, brep, xao, glb (binary glTF)" ) ) );
|
||||
_( "Output file format, options: step, brep, xao, glb (binary glTF), ply, stl" ) ) );
|
||||
}
|
||||
|
||||
m_argParser.add_argument( ARG_FORCE, "-f" )
|
||||
@ -92,9 +92,8 @@ CLI::PCB_EXPORT_3D_COMMAND::PCB_EXPORT_3D_COMMAND( const std::string& aNa
|
||||
_( "Exclude 3D models for components with 'Do not populate' attribute" ) ) )
|
||||
.flag();
|
||||
|
||||
if( m_format == JOB_EXPORT_PCB_3D::FORMAT::STEP || m_format == JOB_EXPORT_PCB_3D::FORMAT::BREP
|
||||
|| m_format == JOB_EXPORT_PCB_3D::FORMAT::XAO
|
||||
|| m_format == JOB_EXPORT_PCB_3D::FORMAT::GLB )
|
||||
if( m_format != JOB_EXPORT_PCB_3D::FORMAT::UNKNOWN
|
||||
&& m_format != JOB_EXPORT_PCB_3D::FORMAT::VRML )
|
||||
{
|
||||
m_argParser.add_argument( ARG_GRID_ORIGIN )
|
||||
.help( UTF8STDSTR( _( "Use Grid Origin for output origin" ) ) )
|
||||
@ -205,9 +204,8 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
|
||||
std::unique_ptr<JOB_EXPORT_PCB_3D> step( new JOB_EXPORT_PCB_3D( true ) );
|
||||
EXPORTER_STEP_PARAMS& params = step->m_3dparams;
|
||||
|
||||
if( m_format == JOB_EXPORT_PCB_3D::FORMAT::STEP || m_format == JOB_EXPORT_PCB_3D::FORMAT::BREP
|
||||
|| m_format == JOB_EXPORT_PCB_3D::FORMAT::XAO
|
||||
|| m_format == JOB_EXPORT_PCB_3D::FORMAT::GLB )
|
||||
if( m_format != JOB_EXPORT_PCB_3D::FORMAT::UNKNOWN
|
||||
&& m_format != JOB_EXPORT_PCB_3D::FORMAT::VRML )
|
||||
{
|
||||
params.m_UseDrillOrigin = m_argParser.get<bool>( ARG_DRILL_ORIGIN );
|
||||
params.m_UseGridOrigin = m_argParser.get<bool>( ARG_GRID_ORIGIN );
|
||||
@ -254,6 +252,10 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
|
||||
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::XAO;
|
||||
else if( format == wxS( "glb" ) )
|
||||
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::GLB;
|
||||
else if( format == wxS( "ply" ) )
|
||||
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::PLY;
|
||||
else if( format == wxS( "stl" ) )
|
||||
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::STL;
|
||||
else
|
||||
{
|
||||
wxFprintf( stderr, _( "Invalid format specified\n" ) );
|
||||
@ -329,9 +331,8 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
|
||||
step->m_hasUserOrigin = true;
|
||||
}
|
||||
|
||||
if( m_format == JOB_EXPORT_PCB_3D::FORMAT::STEP || m_format == JOB_EXPORT_PCB_3D::FORMAT::BREP
|
||||
|| m_format == JOB_EXPORT_PCB_3D::FORMAT::XAO
|
||||
|| m_format == JOB_EXPORT_PCB_3D::FORMAT::GLB )
|
||||
if( m_format != JOB_EXPORT_PCB_3D::FORMAT::UNKNOWN
|
||||
&& m_format != JOB_EXPORT_PCB_3D::FORMAT::VRML )
|
||||
{
|
||||
wxString minDistance =
|
||||
From_UTF8( m_argParser.get<std::string>( ARG_MIN_DISTANCE ).c_str() );
|
||||
|
@ -120,6 +120,8 @@ static CLI::PCB_EXPORT_3D_COMMAND exportPcbStepCmd{ "step", UTF8STDSTR( _
|
||||
static CLI::PCB_EXPORT_3D_COMMAND exportPcbBrepCmd{ "brep", UTF8STDSTR( _( "Export BREP" ) ), JOB_EXPORT_PCB_3D::FORMAT::BREP };
|
||||
static CLI::PCB_EXPORT_3D_COMMAND exportPcbXaoCmd{ "xao", UTF8STDSTR( _( "Export XAO" ) ), JOB_EXPORT_PCB_3D::FORMAT::XAO };
|
||||
static CLI::PCB_EXPORT_3D_COMMAND exportPcbVrmlCmd{ "vrml", UTF8STDSTR( _( "Export VRML" ) ), JOB_EXPORT_PCB_3D::FORMAT::VRML };
|
||||
static CLI::PCB_EXPORT_3D_COMMAND exportPcbPlyCmd{ "ply", UTF8STDSTR( _( "Export PLY" ) ), JOB_EXPORT_PCB_3D::FORMAT::PLY };
|
||||
static CLI::PCB_EXPORT_3D_COMMAND exportPcbStlCmd{ "stl", UTF8STDSTR( _( "Export STL" ) ), JOB_EXPORT_PCB_3D::FORMAT::STL };
|
||||
static CLI::PCB_EXPORT_SVG_COMMAND exportPcbSvgCmd{};
|
||||
static CLI::PCB_EXPORT_PDF_COMMAND exportPcbPdfCmd{};
|
||||
static CLI::PCB_EXPORT_POS_COMMAND exportPcbPosCmd{};
|
||||
@ -198,7 +200,9 @@ static std::vector<COMMAND_ENTRY> commandStack = {
|
||||
&exportPcbStepCmd,
|
||||
&exportPcbSvgCmd,
|
||||
&exportPcbVrmlCmd,
|
||||
&exportPcbXaoCmd
|
||||
&exportPcbXaoCmd,
|
||||
&exportPcbPlyCmd,
|
||||
&exportPcbStlCmd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,14 +56,18 @@
|
||||
static const std::vector<wxString> c_formatCommand = { FILEEXT::StepFileExtension,
|
||||
FILEEXT::GltfBinaryFileExtension,
|
||||
FILEEXT::XaoFileExtension,
|
||||
FILEEXT::BrepFileExtension };
|
||||
FILEEXT::BrepFileExtension,
|
||||
FILEEXT::PlyFileExtension,
|
||||
FILEEXT::StlFileExtension};
|
||||
|
||||
// Maps file extensions to m_choiceFormat selection
|
||||
static const std::map<wxString, int> c_formatExtToChoice = { { FILEEXT::StepFileExtension, 0 },
|
||||
{ FILEEXT::StepFileAbrvExtension, 0 },
|
||||
{ FILEEXT::GltfBinaryFileExtension, 1 },
|
||||
{ FILEEXT::XaoFileExtension, 2 },
|
||||
{ FILEEXT::BrepFileExtension, 3 } };
|
||||
{ FILEEXT::BrepFileExtension, 3 },
|
||||
{ FILEEXT::PlyFileExtension, 4 },
|
||||
{ FILEEXT::StlFileExtension, 5 }};
|
||||
|
||||
|
||||
|
||||
@ -380,7 +384,11 @@ void DIALOG_EXPORT_STEP::onBrowseClicked( wxCommandEvent& aEvent )
|
||||
+ _( "XAO files" )
|
||||
+ AddFileExtListToFilter( { FILEEXT::XaoFileExtension} ) + "|"
|
||||
+ _( "BREP (OCCT) files" )
|
||||
+ AddFileExtListToFilter( { FILEEXT::BrepFileExtension } );
|
||||
+ AddFileExtListToFilter( { FILEEXT::BrepFileExtension } ) + "|"
|
||||
+ _( "PLY files" )
|
||||
+ AddFileExtListToFilter( { FILEEXT::PlyFileExtension} ) + "|"
|
||||
+ _( "STL files" )
|
||||
+ AddFileExtListToFilter( { FILEEXT::StlFileExtension} );
|
||||
// clang-format on
|
||||
|
||||
// Build the absolute path of current output directory to preselect it in the file browser.
|
||||
|
@ -24,7 +24,7 @@ DIALOG_EXPORT_STEP_BASE::DIALOG_EXPORT_STEP_BASE( wxWindow* parent, wxWindowID i
|
||||
m_txtFormat->Wrap( -1 );
|
||||
bSizerTop->Add( m_txtFormat, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
wxString m_choiceFormatChoices[] = { _("STEP"), _("GLB (Binary glTF)"), _("XAO"), _("BREP (OCCT)") };
|
||||
wxString m_choiceFormatChoices[] = { _("STEP"), _("GLB (Binary glTF)"), _("XAO"), _("BREP (OCCT)"), _("PLY (ASCII)"), _("STL") };
|
||||
int m_choiceFormatNChoices = sizeof( m_choiceFormatChoices ) / sizeof( wxString );
|
||||
m_choiceFormat = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceFormatNChoices, m_choiceFormatChoices, 0 );
|
||||
m_choiceFormat->SetSelection( 0 );
|
||||
|
@ -153,7 +153,7 @@
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="choices">"STEP" "GLB (Binary glTF)" "XAO" "BREP (OCCT)"</property>
|
||||
<property name="choices">"STEP" "GLB (Binary glTF)" "XAO" "BREP (OCCT)" "PLY (ASCII)" "STL"</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
|
@ -537,6 +537,14 @@ void EXPORTER_STEP::initOutputVariant()
|
||||
m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_GLTF );
|
||||
break;
|
||||
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::PLY:
|
||||
m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_PLY );
|
||||
break;
|
||||
|
||||
case EXPORTER_STEP_PARAMS::FORMAT::STL:
|
||||
m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_STL );
|
||||
break;
|
||||
|
||||
default:
|
||||
m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_UNKNOWN );
|
||||
break;
|
||||
@ -723,6 +731,10 @@ bool EXPORTER_STEP::Export()
|
||||
success = m_pcbModel->WriteXAO( m_outputFile );
|
||||
else if( m_params.m_Format == EXPORTER_STEP_PARAMS::FORMAT::GLB )
|
||||
success = m_pcbModel->WriteGLTF( m_outputFile );
|
||||
else if( m_params.m_Format == EXPORTER_STEP_PARAMS::FORMAT::PLY )
|
||||
success = m_pcbModel->WritePLY( m_outputFile );
|
||||
else if( m_params.m_Format == EXPORTER_STEP_PARAMS::FORMAT::STL )
|
||||
success = m_pcbModel->WriteSTL( m_outputFile );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
|
@ -115,9 +115,11 @@
|
||||
#include <GC_MakeCircle.hxx>
|
||||
|
||||
#include <RWGltf_CafWriter.hxx>
|
||||
#include <StlAPI_Writer.hxx>
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070700
|
||||
#include <VrmlAPI_CafReader.hxx>
|
||||
#include <RWPly_CafWriter.hxx>
|
||||
#endif
|
||||
|
||||
#include <macros.h>
|
||||
@ -2894,6 +2896,34 @@ TDF_Label STEP_PCB_MODEL::transferModel( Handle( TDocStd_Document ) & source,
|
||||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::performMeshing( Handle( XCAFDoc_ShapeTool ) & aShapeTool )
|
||||
{
|
||||
TDF_LabelSequence freeShapes;
|
||||
aShapeTool->GetFreeShapes( freeShapes );
|
||||
|
||||
ReportMessage( wxT( "Meshing model\n" ) );
|
||||
|
||||
// GLTF is a mesh format, we have to trigger opencascade to mesh the shapes we composited into the asesmbly
|
||||
// To mesh models, lets just grab the free shape root and execute on them
|
||||
for( Standard_Integer i = 1; i <= freeShapes.Length(); ++i )
|
||||
{
|
||||
TDF_Label label = freeShapes.Value( i );
|
||||
TopoDS_Shape shape;
|
||||
aShapeTool->GetShape( label, shape );
|
||||
|
||||
// These deflection values basically affect the accuracy of the mesh generated, a tighter
|
||||
// deflection will result in larger meshes
|
||||
// We could make this a tunable parameter, but for now fix it
|
||||
const Standard_Real linearDeflection = 0.14;
|
||||
const Standard_Real angularDeflection = DEG2RAD( 30.0 );
|
||||
BRepMesh_IncrementalMesh mesh( shape, linearDeflection, Standard_False, angularDeflection,
|
||||
Standard_True );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::WriteGLTF( const wxString& aFileName )
|
||||
{
|
||||
if( !isBoardOutlineValid() )
|
||||
@ -2906,27 +2936,7 @@ bool STEP_PCB_MODEL::WriteGLTF( const wxString& aFileName )
|
||||
|
||||
m_outFmt = OUTPUT_FORMAT::FMT_OUT_GLTF;
|
||||
|
||||
TDF_LabelSequence freeShapes;
|
||||
m_assy->GetFreeShapes( freeShapes );
|
||||
|
||||
ReportMessage( wxT( "Meshing model\n" ) );
|
||||
|
||||
// GLTF is a mesh format, we have to trigger opencascade to mesh the shapes we composited into the asesmbly
|
||||
// To mesh models, lets just grab the free shape root and execute on them
|
||||
for( Standard_Integer i = 1; i <= freeShapes.Length(); ++i )
|
||||
{
|
||||
TDF_Label label = freeShapes.Value( i );
|
||||
TopoDS_Shape shape;
|
||||
m_assy->GetShape( label, shape );
|
||||
|
||||
// These deflection values basically affect the accuracy of the mesh generated, a tighter
|
||||
// deflection will result in larger meshes
|
||||
// We could make this a tunable parameter, but for now fix it
|
||||
const Standard_Real linearDeflection = 0.14;
|
||||
const Standard_Real angularDeflection = DEG2RAD( 30.0 );
|
||||
BRepMesh_IncrementalMesh mesh( shape, linearDeflection, Standard_False, angularDeflection,
|
||||
Standard_True );
|
||||
}
|
||||
performMeshing( m_assy );
|
||||
|
||||
wxFileName fn( aFileName );
|
||||
|
||||
@ -2979,3 +2989,123 @@ bool STEP_PCB_MODEL::WriteGLTF( const wxString& aFileName )
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::WritePLY( const wxString& aFileName )
|
||||
{
|
||||
#if OCC_VERSION_HEX < 0x070700
|
||||
#warning "PLY export is not supported before OCCT 7.7.0"
|
||||
|
||||
ReportMessage( wxT( "PLY export is not supported before OCCT 7.7.0\n" ) );
|
||||
return false;
|
||||
#else
|
||||
|
||||
if( !isBoardOutlineValid() )
|
||||
{
|
||||
ReportMessage( wxString::Format( wxT( "No valid PCB assembly; cannot create output file "
|
||||
"'%s'.\n" ),
|
||||
aFileName ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_outFmt = OUTPUT_FORMAT::FMT_OUT_PLY;
|
||||
|
||||
performMeshing( m_assy );
|
||||
|
||||
wxFileName fn( aFileName );
|
||||
|
||||
const char* tmpFname = "$tempfile$.ply";
|
||||
RWPly_CafWriter cafWriter( tmpFname );
|
||||
|
||||
cafWriter.SetFaceId( true ); // TODO: configurable SetPartId/SetFaceId
|
||||
cafWriter.ChangeCoordinateSystemConverter().SetInputLengthUnit( 0.001 );
|
||||
cafWriter.ChangeCoordinateSystemConverter().SetInputCoordinateSystem(
|
||||
RWMesh_CoordinateSystem_Zup );
|
||||
|
||||
TColStd_IndexedDataMapOfStringString metadata;
|
||||
|
||||
metadata.Add( TCollection_AsciiString( "pcb_name" ),
|
||||
TCollection_ExtendedString( fn.GetName().wc_str() ) );
|
||||
metadata.Add( TCollection_AsciiString( "source_pcb_file" ),
|
||||
TCollection_ExtendedString( fn.GetFullName().wc_str() ) );
|
||||
metadata.Add( TCollection_AsciiString( "generator" ),
|
||||
TCollection_AsciiString(
|
||||
wxString::Format( wxS( "KiCad %s" ), GetSemanticVersion() ).ToAscii() ) );
|
||||
metadata.Add( TCollection_AsciiString( "generated_at" ),
|
||||
TCollection_AsciiString( GetISO8601CurrentDateTime().ToAscii() ) );
|
||||
|
||||
bool success = true;
|
||||
|
||||
// Creates a temporary file with a ascii7 name, because writer does not know unicode filenames.
|
||||
wxString currCWD = wxGetCwd();
|
||||
wxString workCWD = fn.GetPath();
|
||||
|
||||
if( !workCWD.IsEmpty() )
|
||||
wxSetWorkingDirectory( workCWD );
|
||||
|
||||
success = cafWriter.Perform( m_doc, metadata, Message_ProgressRange() );
|
||||
|
||||
if( success )
|
||||
{
|
||||
// Preserve the permissions of the current file
|
||||
KIPLATFORM::IO::DuplicatePermissions( fn.GetFullPath(), tmpFname );
|
||||
|
||||
if( !wxRenameFile( tmpFname, fn.GetFullName(), true ) )
|
||||
{
|
||||
ReportMessage( wxString::Format( wxT( "Cannot rename temporary file '%s' to '%s'.\n" ),
|
||||
tmpFname, fn.GetFullName() ) );
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
wxSetWorkingDirectory( currCWD );
|
||||
|
||||
return success;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool STEP_PCB_MODEL::WriteSTL( const wxString& aFileName )
|
||||
{
|
||||
if( !isBoardOutlineValid() )
|
||||
{
|
||||
ReportMessage( wxString::Format( wxT( "No valid PCB assembly; cannot create output file "
|
||||
"'%s'.\n" ),
|
||||
aFileName ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_outFmt = OUTPUT_FORMAT::FMT_OUT_STL;
|
||||
|
||||
performMeshing( m_assy );
|
||||
|
||||
wxFileName fn( aFileName );
|
||||
|
||||
const char* tmpFname = "$tempfile$.stl";
|
||||
|
||||
// Creates a temporary file with a ascii7 name, because writer does not know unicode filenames.
|
||||
wxString currCWD = wxGetCwd();
|
||||
wxString workCWD = fn.GetPath();
|
||||
|
||||
if( !workCWD.IsEmpty() )
|
||||
wxSetWorkingDirectory( workCWD );
|
||||
|
||||
bool success = StlAPI_Writer().Write( getOneShape( m_assy ), tmpFname );
|
||||
|
||||
if( success )
|
||||
{
|
||||
// Preserve the permissions of the current file
|
||||
KIPLATFORM::IO::DuplicatePermissions( fn.GetFullPath(), tmpFname );
|
||||
|
||||
if( !wxRenameFile( tmpFname, fn.GetFullName(), true ) )
|
||||
{
|
||||
ReportMessage( wxString::Format( wxT( "Cannot rename temporary file '%s' to '%s'.\n" ),
|
||||
tmpFname, fn.GetFullName() ) );
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
wxSetWorkingDirectory( currCWD );
|
||||
|
||||
return success;
|
||||
}
|
@ -82,7 +82,9 @@ enum class OUTPUT_FORMAT
|
||||
FMT_OUT_IGES,
|
||||
FMT_OUT_BREP,
|
||||
FMT_OUT_XAO,
|
||||
FMT_OUT_GLTF
|
||||
FMT_OUT_GLTF,
|
||||
FMT_OUT_PLY,
|
||||
FMT_OUT_STL
|
||||
};
|
||||
|
||||
class STEP_PCB_MODEL
|
||||
@ -192,6 +194,12 @@ public:
|
||||
*/
|
||||
bool WriteGLTF( const wxString& aFileName );
|
||||
|
||||
// write the assembly in PLY format (mesh)
|
||||
bool WritePLY( const wxString& aFileName );
|
||||
|
||||
// write the assembly in STL format (mesh)
|
||||
bool WriteSTL( const wxString& aFileName );
|
||||
|
||||
private:
|
||||
/**
|
||||
* @return true if the board(s) outline is valid. False otherwise
|
||||
@ -226,6 +234,8 @@ private:
|
||||
bool readSTEP( Handle( TDocStd_Document ) & aDoc, const char* aFname );
|
||||
bool readVRML( Handle( TDocStd_Document ) & aDoc, const char* aFname );
|
||||
|
||||
bool performMeshing( Handle( XCAFDoc_ShapeTool ) & aShapeTool );
|
||||
|
||||
TDF_Label transferModel( Handle( TDocStd_Document )& source, Handle( TDocStd_Document ) & dest,
|
||||
VECTOR3D aScale );
|
||||
|
||||
|
@ -315,6 +315,10 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
|
||||
break;
|
||||
case JOB_EXPORT_PCB_3D::FORMAT::GLB: fn.SetExt( FILEEXT::GltfBinaryFileExtension );
|
||||
break;
|
||||
case JOB_EXPORT_PCB_3D::FORMAT::PLY: fn.SetExt( FILEEXT::PlyFileExtension );
|
||||
break;
|
||||
case JOB_EXPORT_PCB_3D::FORMAT::STL: fn.SetExt( FILEEXT::StlFileExtension );
|
||||
break;
|
||||
default:
|
||||
return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
|
||||
}
|
||||
@ -383,6 +387,12 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
|
||||
case JOB_EXPORT_PCB_3D::FORMAT::GLB:
|
||||
params.m_Format = EXPORTER_STEP_PARAMS::FORMAT::GLB;
|
||||
break;
|
||||
case JOB_EXPORT_PCB_3D::FORMAT::PLY:
|
||||
params.m_Format = EXPORTER_STEP_PARAMS::FORMAT::PLY;
|
||||
break;
|
||||
case JOB_EXPORT_PCB_3D::FORMAT::STL:
|
||||
params.m_Format = EXPORTER_STEP_PARAMS::FORMAT::STL;
|
||||
break;
|
||||
default:
|
||||
return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user