ADDED: XAO export for SALOME / Gmsh workflows.

Pad surfaces are assigned as face groups.
This commit is contained in:
Alex Shvartzkop 2024-04-26 01:53:39 +03:00
parent 22c4fa29f1
commit 1ae9e9b676
14 changed files with 269 additions and 26 deletions

View File

@ -35,6 +35,7 @@ public:
UNKNOWN, // defefer to arg UNKNOWN, // defefer to arg
STEP, STEP,
BREP, BREP,
XAO,
GLB, GLB,
VRML VRML
}; };

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2008 Wayne Stambaugh <stambaughw@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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -198,6 +198,7 @@ const std::string FILEEXT::StepFileExtension( "step" );
const std::string FILEEXT::StepFileAbrvExtension( "stp" ); const std::string FILEEXT::StepFileAbrvExtension( "stp" );
const std::string FILEEXT::GltfBinaryFileExtension( "glb" ); const std::string FILEEXT::GltfBinaryFileExtension( "glb" );
const std::string FILEEXT::BrepFileExtension( "brep" ); const std::string FILEEXT::BrepFileExtension( "brep" );
const std::string FILEEXT::XaoFileExtension( "xao" );
const wxString FILEEXT::GerberFileExtensionsRegex( "(gbr|gko|pho|(g[tb][alops])|(gm?\\d\\d*)|(gp[tb]))" ); const wxString FILEEXT::GerberFileExtensionsRegex( "(gbr|gko|pho|(g[tb][alops])|(gm?\\d\\d*)|(gp[tb]))" );

View File

@ -4,7 +4,7 @@
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2007-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2007-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2008 Wayne Stambaugh <stambaughw@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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -188,6 +188,7 @@ public:
static const std::string StepFileAbrvExtension; static const std::string StepFileAbrvExtension;
static const std::string GltfBinaryFileExtension; static const std::string GltfBinaryFileExtension;
static const std::string BrepFileExtension; static const std::string BrepFileExtension;
static const std::string XaoFileExtension;
static const wxString GerberFileExtensionsRegex; static const wxString GerberFileExtensionsRegex;

View File

@ -69,7 +69,7 @@ CLI::PCB_EXPORT_3D_COMMAND::PCB_EXPORT_3D_COMMAND( const std::string& aNa
m_argParser.add_argument( ARG_FORMAT ) m_argParser.add_argument( ARG_FORMAT )
.default_value( std::string( "step" ) ) .default_value( std::string( "step" ) )
.help( UTF8STDSTR( .help( UTF8STDSTR(
_( "Output file format, options: step, brep, glb (binary glTF)" ) ) ); _( "Output file format, options: step, brep, xao, glb (binary glTF)" ) ) );
} }
m_argParser.add_argument( ARG_FORCE, "-f" ) m_argParser.add_argument( ARG_FORCE, "-f" )
@ -88,6 +88,7 @@ CLI::PCB_EXPORT_3D_COMMAND::PCB_EXPORT_3D_COMMAND( const std::string& aNa
.flag(); .flag();
if( m_format == JOB_EXPORT_PCB_3D::FORMAT::STEP || m_format == JOB_EXPORT_PCB_3D::FORMAT::BREP 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 ) || m_format == JOB_EXPORT_PCB_3D::FORMAT::GLB )
{ {
m_argParser.add_argument( ARG_GRID_ORIGIN ) m_argParser.add_argument( ARG_GRID_ORIGIN )
@ -181,6 +182,7 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
std::unique_ptr<JOB_EXPORT_PCB_3D> step( new JOB_EXPORT_PCB_3D( true ) ); std::unique_ptr<JOB_EXPORT_PCB_3D> step( new JOB_EXPORT_PCB_3D( true ) );
if( m_format == JOB_EXPORT_PCB_3D::FORMAT::STEP || m_format == JOB_EXPORT_PCB_3D::FORMAT::BREP 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 ) || m_format == JOB_EXPORT_PCB_3D::FORMAT::GLB )
{ {
step->m_useDrillOrigin = m_argParser.get<bool>( ARG_DRILL_ORIGIN ); step->m_useDrillOrigin = m_argParser.get<bool>( ARG_DRILL_ORIGIN );
@ -217,6 +219,8 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::STEP; step->m_format = JOB_EXPORT_PCB_3D::FORMAT::STEP;
else if( format == wxS( "brep" ) ) else if( format == wxS( "brep" ) )
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::BREP; step->m_format = JOB_EXPORT_PCB_3D::FORMAT::BREP;
else if( format == wxS( "xao" ) )
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::XAO;
else if( format == wxS( "glb" ) ) else if( format == wxS( "glb" ) )
step->m_format = JOB_EXPORT_PCB_3D::FORMAT::GLB; step->m_format = JOB_EXPORT_PCB_3D::FORMAT::GLB;
else else
@ -296,6 +300,7 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
} }
if( m_format == JOB_EXPORT_PCB_3D::FORMAT::STEP || m_format == JOB_EXPORT_PCB_3D::FORMAT::BREP 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 ) || m_format == JOB_EXPORT_PCB_3D::FORMAT::GLB )
{ {
wxString minDistance = wxString minDistance =

View File

@ -113,6 +113,7 @@ static CLI::PCB_EXPORT_DXF_COMMAND exportPcbDxfCmd{};
static CLI::PCB_EXPORT_3D_COMMAND exportPcbGlbCmd{ "glb", UTF8STDSTR( _( "Export GLB (binary GLTF)" ) ), JOB_EXPORT_PCB_3D::FORMAT::GLB }; static CLI::PCB_EXPORT_3D_COMMAND exportPcbGlbCmd{ "glb", UTF8STDSTR( _( "Export GLB (binary GLTF)" ) ), JOB_EXPORT_PCB_3D::FORMAT::GLB };
static CLI::PCB_EXPORT_3D_COMMAND exportPcbStepCmd{ "step", UTF8STDSTR( _( "Export STEP" ) ), JOB_EXPORT_PCB_3D::FORMAT::STEP }; static CLI::PCB_EXPORT_3D_COMMAND exportPcbStepCmd{ "step", UTF8STDSTR( _( "Export STEP" ) ), JOB_EXPORT_PCB_3D::FORMAT::STEP };
static CLI::PCB_EXPORT_3D_COMMAND exportPcbBrepCmd{ "brep", UTF8STDSTR( _( "Export BREP" ) ), JOB_EXPORT_PCB_3D::FORMAT::BREP }; 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 exportPcbVrmlCmd{ "vrml", UTF8STDSTR( _( "Export VRML" ) ), JOB_EXPORT_PCB_3D::FORMAT::VRML };
static CLI::PCB_EXPORT_SVG_COMMAND exportPcbSvgCmd{}; static CLI::PCB_EXPORT_SVG_COMMAND exportPcbSvgCmd{};
static CLI::PCB_EXPORT_PDF_COMMAND exportPcbPdfCmd{}; static CLI::PCB_EXPORT_PDF_COMMAND exportPcbPdfCmd{};
@ -181,7 +182,8 @@ static std::vector<COMMAND_ENTRY> commandStack = {
&exportPcbPosCmd, &exportPcbPosCmd,
&exportPcbStepCmd, &exportPcbStepCmd,
&exportPcbSvgCmd, &exportPcbSvgCmd,
&exportPcbVrmlCmd &exportPcbVrmlCmd,
&exportPcbXaoCmd
} }
} }
} }

View File

@ -480,6 +480,8 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
cmdK2S.Append( wxT( " glb" ) ); cmdK2S.Append( wxT( " glb" ) );
else if( fn.GetExt() == FILEEXT::BrepFileExtension ) else if( fn.GetExt() == FILEEXT::BrepFileExtension )
cmdK2S.Append( wxT( " brep" ) ); cmdK2S.Append( wxT( " brep" ) );
else if( fn.GetExt() == FILEEXT::XaoFileExtension )
cmdK2S.Append( wxT( " xao" ) );
else else
cmdK2S.Append( wxT( " step" ) ); cmdK2S.Append( wxT( " step" ) );

View File

@ -51,7 +51,7 @@
<property name="size">-1,-1</property> <property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property> <property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Export STEP / BREP / GLTF</property> <property name="title">Export STEP / BREP / XAO / GLTF</property>
<property name="tooltip"></property> <property name="tooltip"></property>
<property name="two_step_creation">0</property> <property name="two_step_creation">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>

View File

@ -95,7 +95,7 @@ class DIALOG_EXPORT_STEP_BASE : public DIALOG_SHIM
public: public:
DIALOG_EXPORT_STEP_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export STEP / BREP / GLTF"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); DIALOG_EXPORT_STEP_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export STEP / BREP / XAO / GLTF"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_EXPORT_STEP_BASE(); ~DIALOG_EXPORT_STEP_BASE();

View File

@ -121,6 +121,7 @@ wxString EXPORTER_STEP_PARAMS::GetDefaultExportExtension()
{ {
case EXPORTER_STEP_PARAMS::FORMAT::STEP: return wxS( "step" ); case EXPORTER_STEP_PARAMS::FORMAT::STEP: return wxS( "step" );
case EXPORTER_STEP_PARAMS::FORMAT::BREP: return wxS( "brep" ); 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::GLB: return wxS( "glb" );
default: return wxEmptyString; // shouldn't happen default: return wxEmptyString; // shouldn't happen
} }
@ -133,6 +134,7 @@ wxString EXPORTER_STEP_PARAMS::GetFormatName()
// honestly these names shouldn't be translated since they are mostly industry standard acronyms // honestly these names shouldn't be translated since they are mostly industry standard acronyms
case EXPORTER_STEP_PARAMS::FORMAT::STEP: return wxS( "STEP" ); case EXPORTER_STEP_PARAMS::FORMAT::STEP: return wxS( "STEP" );
case EXPORTER_STEP_PARAMS::FORMAT::BREP: return wxS( "BREP" ); 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::GLB: return wxS( "Binary GLTF" );
default: return wxEmptyString; // shouldn't happen default: return wxEmptyString; // shouldn't happen
} }
@ -542,6 +544,8 @@ bool EXPORTER_STEP::Export()
success = m_pcbModel->WriteSTEP( m_outputFile, m_params.m_optimizeStep ); success = m_pcbModel->WriteSTEP( m_outputFile, m_params.m_optimizeStep );
else if( m_params.m_format == EXPORTER_STEP_PARAMS::FORMAT::BREP ) else if( m_params.m_format == EXPORTER_STEP_PARAMS::FORMAT::BREP )
success = m_pcbModel->WriteBREP( m_outputFile ); success = m_pcbModel->WriteBREP( m_outputFile );
else if( m_params.m_format == EXPORTER_STEP_PARAMS::FORMAT::XAO )
success = m_pcbModel->WriteXAO( m_outputFile );
else if( m_params.m_format == EXPORTER_STEP_PARAMS::FORMAT::GLB ) else if( m_params.m_format == EXPORTER_STEP_PARAMS::FORMAT::GLB )
success = m_pcbModel->WriteGLTF( m_outputFile ); success = m_pcbModel->WriteGLTF( m_outputFile );

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com> * Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -69,6 +69,7 @@ public:
{ {
STEP, STEP,
BREP, BREP,
XAO,
GLB GLB
}; };

View File

@ -62,6 +62,7 @@
#include <STEPCAFControl_Writer.hxx> #include <STEPCAFControl_Writer.hxx>
#include <APIHeaderSection_MakeHeader.hxx> #include <APIHeaderSection_MakeHeader.hxx>
#include <Standard_Failure.hxx> #include <Standard_Failure.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Version.hxx> #include <Standard_Version.hxx>
#include <TCollection_ExtendedString.hxx> #include <TCollection_ExtendedString.hxx>
#include <TDocStd_Document.hxx> #include <TDocStd_Document.hxx>
@ -70,6 +71,7 @@
#include <TDF_LabelSequence.hxx> #include <TDF_LabelSequence.hxx>
#include <TDF_ChildIterator.hxx> #include <TDF_ChildIterator.hxx>
#include <TopExp_Explorer.hxx> #include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <XCAFApp_Application.hxx> #include <XCAFApp_Application.hxx>
#include <XCAFDoc.hxx> #include <XCAFDoc.hxx>
#include <XCAFDoc_DocumentTool.hxx> #include <XCAFDoc_DocumentTool.hxx>
@ -84,10 +86,13 @@
#include <BRepBuilderAPI_MakeEdge.hxx> #include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx> #include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx> #include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepPrimAPI_MakePrism.hxx> #include <BRepPrimAPI_MakePrism.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx> #include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepTools.hxx> #include <BRepTools.hxx>
#include <BRepLib_MakeWire.hxx> #include <BRepLib_MakeWire.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAlgoAPI_Check.hxx> #include <BRepAlgoAPI_Check.hxx>
#include <BRepAlgoAPI_Cut.hxx> #include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx> #include <BRepAlgoAPI_Fuse.hxx>
@ -438,6 +443,8 @@ bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool
thickness -= 0.01; thickness -= 0.01;
} }
TopoDS_Shape testShape;
// Make a shape on copper layers // Make a shape on copper layers
std::shared_ptr<SHAPE> effShapePtr = aPad->GetEffectiveShape( pcb_layer ); std::shared_ptr<SHAPE> effShapePtr = aPad->GetEffectiveShape( pcb_layer );
@ -475,6 +482,12 @@ bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool
aOrigin ) ) aOrigin ) )
{ {
topodsShapes.emplace_back( topods_shape ); topodsShapes.emplace_back( topods_shape );
if( testShape.IsNull() )
{
MakeShapeAsThickSegment( testShape, start, end, width, 0.0,
Zpos + thickness, aOrigin );
}
} }
else else
{ {
@ -487,6 +500,16 @@ bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool
shape->TransformToPolygon( polySet, ARC_HIGH_DEF, ERROR_INSIDE ); shape->TransformToPolygon( polySet, ARC_HIGH_DEF, ERROR_INSIDE );
success &= MakeShapes( topodsShapes, polySet, false, thickness, Zpos, aOrigin ); success &= MakeShapes( topodsShapes, polySet, false, thickness, Zpos, aOrigin );
if( testShape.IsNull() )
{
std::vector<TopoDS_Shape> testShapes;
MakeShapes( testShapes, polySet, false, 0.0, Zpos + thickness, aOrigin );
if( testShapes.size() > 0 )
testShape = testShapes.front();
}
} }
} }
@ -544,6 +567,29 @@ bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool
m_board_copper_pads.emplace_back( sh ); m_board_copper_pads.emplace_back( sh );
} }
} }
if( !aVia && !testShape.IsNull() )
{
if( pcb_layer == F_Cu || pcb_layer == B_Cu )
{
wxString name;
name << "Pad_";
if( pcb_layer == F_Cu )
name << 'F' << '_';
else if( pcb_layer == B_Cu )
name << 'B' << '_';
name << aPad->GetParentFootprint()->GetReferenceAsString() << '_'
<< aPad->GetNumber() << '_' << aPad->GetShortNetname();
gp_Pnt point( pcbIUScale.IUTomm( aPad->GetX() - aOrigin.x ),
-pcbIUScale.IUTomm( aPad->GetY() - aOrigin.y ), Zpos + thickness );
m_pad_points[name] = { point, testShape };
}
}
} }
if( aPad->GetAttribute() == PAD_ATTRIB::PTH && aPad->IsOnLayer( F_Cu ) if( aPad->GetAttribute() == PAD_ATTRIB::PTH && aPad->IsOnLayer( F_Cu )
@ -1034,12 +1080,13 @@ bool STEP_PCB_MODEL::MakeShapeAsThickSegment( TopoDS_Shape& aShape,
} }
catch( const Standard_Failure& e ) catch( const Standard_Failure& e )
{ {
ReportMessage( ReportMessage( wxString::Format( wxT( "MakeShapeThickSegment: OCC exception: %s\n" ),
wxString::Format( wxT( "MakeShapeThickSegment: OCC exception: %s\n" ),
e.GetMessageString() ) ); e.GetMessageString() ) );
return false; return false;
} }
if( aThickness != 0.0 )
{
aShape = BRepPrimAPI_MakePrism( face, gp_Vec( 0, 0, aThickness ) ); aShape = BRepPrimAPI_MakePrism( face, gp_Vec( 0, 0, aThickness ) );
if( aShape.IsNull() ) if( aShape.IsNull() )
@ -1047,6 +1094,11 @@ bool STEP_PCB_MODEL::MakeShapeAsThickSegment( TopoDS_Shape& aShape,
ReportMessage( wxT( "failed to create a prismatic shape\n" ) ); ReportMessage( wxT( "failed to create a prismatic shape\n" ) );
return false; return false;
} }
}
else
{
aShape = face;
}
return success; return success;
} }
@ -1139,8 +1191,7 @@ bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE
} }
else else
{ {
curve = GC_MakeArcOfCircle( toPoint( aPt0 ), curve = GC_MakeArcOfCircle( toPoint( aPt0 ), toPoint( aArc.GetArcMid() ),
toPoint( aArc.GetArcMid() ),
toPoint( aArc.GetP1() ) ) toPoint( aArc.GetP1() ) )
.Value(); .Value();
} }
@ -1341,6 +1392,8 @@ bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE
} }
if( mkFace.IsDone() ) if( mkFace.IsDone() )
{
if( aThickness != 0.0 )
{ {
TopoDS_Shape prism = BRepPrimAPI_MakePrism( mkFace, gp_Vec( 0, 0, aThickness ) ); TopoDS_Shape prism = BRepPrimAPI_MakePrism( mkFace, gp_Vec( 0, 0, aThickness ) );
aShapes.push_back( prism ); aShapes.push_back( prism );
@ -1352,6 +1405,11 @@ bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE
} }
} }
else else
{
aShapes.push_back( mkFace );
}
}
else
{ {
wxASSERT( false ); wxASSERT( false );
} }
@ -1849,6 +1907,163 @@ bool STEP_PCB_MODEL::WriteBREP( const wxString& aFileName )
} }
bool STEP_PCB_MODEL::WriteXAO( const wxString& aFileName )
{
wxFileName fn( aFileName );
wxFFileOutputStream ffStream( fn.GetFullPath() );
wxStdOutputStream file( ffStream );
if( !ffStream.IsOk() )
{
ReportMessage( wxString::Format( "Could not open file '%s'", fn.GetFullPath() ) );
return false;
}
// s_assy = shape tool for the source
Handle( XCAFDoc_ShapeTool ) s_assy = XCAFDoc_DocumentTool::ShapeTool( m_doc->Main() );
// retrieve the shape from the assembly
const TopoDS_Shape shape = s_assy->GetOneShape();
std::map<wxString, std::vector<int>> groups[4];
TopExp_Explorer exp;
int faceIndex = 0;
for( exp.Init( shape, TopAbs_FACE ); exp.More(); exp.Next() )
{
TopoDS_Shape subShape = exp.Current();
Bnd_Box bbox;
BRepBndLib::Add( subShape, bbox );
for( const auto& [padKey, pair] : m_pad_points )
{
const auto& [point, padTestShape] = pair;
if( bbox.IsOut( point ) )
continue;
BRepAdaptor_Surface surface( TopoDS::Face( subShape ) );
if( surface.GetType() != GeomAbs_Plane )
continue;
BRepExtrema_DistShapeShape dist( padTestShape, subShape );
dist.Perform();
if( !dist.IsDone() )
continue;
std::cout << padKey << " " << dist.Value() << std::endl;
if( dist.Value() < Precision::Approximation() )
{
// Push as a face group
groups[2][padKey].push_back( faceIndex );
}
}
faceIndex++;
}
// Based on Gmsh code
file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
file << "<XAO version=\"1.0\" author=\"KiCad\">" << std::endl;
file << " <geometry name=\"" << fn.GetName() << "\">" << std::endl;
file << " <shape format=\"BREP\"><![CDATA[";
#if OCC_VERSION_HEX < 0x070600
BRepTools::Write( shape, file );
#else
BRepTools::Write( shape, file, Standard_True, Standard_True, TopTools_FormatVersion_VERSION_1 );
#endif
file << "]]></shape>" << std::endl;
file << " <topology>" << std::endl;
TopTools_IndexedMapOfShape mainMap;
TopExp::MapShapes( shape, mainMap );
std::set<int> topo[4];
static const TopAbs_ShapeEnum c_dimShapeTypes[] = { TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE,
TopAbs_SOLID };
static const std::string c_dimLabel[] = { "vertex", "edge", "face", "solid" };
static const std::string c_dimLabels[] = { "vertices", "edges", "faces", "solids" };
for( int dim = 0; dim < 4; dim++ )
{
for( exp.Init( shape, c_dimShapeTypes[dim] ); exp.More(); exp.Next() )
{
TopoDS_Shape subShape = exp.Current();
int idx = mainMap.FindIndex( subShape );
if( idx && !topo[dim].count( idx ) )
topo[dim].insert( idx );
}
}
for( int dim = 0; dim <= 3; dim++ )
{
std::string labels = c_dimLabels[dim];
std::string label = c_dimLabel[dim];
file << " <" << labels << " count=\"" << topo[dim].size() << "\">" << std::endl;
int index = 0;
for( auto p : topo[dim] )
{
std::string name( "" );
file << " <" << label << " index=\"" << index << "\" "
<< "name=\"" << name << "\" "
<< "reference=\"" << p << "\"/>" << std::endl;
index++;
}
file << " </" << labels << ">" << std::endl;
}
file << " </topology>" << std::endl;
file << " </geometry>" << std::endl;
file << " <groups count=\""
<< groups[0].size() + groups[1].size() + groups[2].size() + groups[3].size() << "\">"
<< std::endl;
for( int dim = 0; dim <= 3; dim++ )
{
std::string label = c_dimLabel[dim];
for( auto g : groups[dim] )
{
//std::string name = model->getPhysicalName( dim, g.first );
wxString name = g.first;
if( name.empty() )
{ // create same unique name as for MED export
std::ostringstream gs;
gs << "G_" << dim << "D_" << g.first;
name = gs.str();
}
file << " <group name=\"" << name << "\" dimension=\"" << label;
//#if 1
// // Gmsh XAO extension: also save the physical tag, so that XAO can be used
// // to serialize OCC geometries, ready to be used by GetDP, GmshFEM & co
// file << "\" tag=\"" << g.first;
//#endif
file << "\" count=\"" << g.second.size() << "\">" << std::endl;
for( auto index : g.second )
{
file << " <element index=\"" << index << "\"/>" << std::endl;
}
file << " </group>" << std::endl;
}
}
file << " </groups>" << std::endl;
file << " <fields count=\"0\"/>" << std::endl;
file << "</XAO>" << std::endl;
return true;
}
bool STEP_PCB_MODEL::getModelLabel( const std::string& aFileNameUTF8, VECTOR3D aScale, TDF_Label& aLabel, bool STEP_PCB_MODEL::getModelLabel( const std::string& aFileNameUTF8, VECTOR3D aScale, TDF_Label& aLabel,
bool aSubstituteModels, wxString* aErrorMessage ) bool aSubstituteModels, wxString* aErrorMessage )
{ {

View File

@ -176,6 +176,9 @@ public:
// write the assembly in BREP format // write the assembly in BREP format
bool WriteBREP( const wxString& aFileName ); bool WriteBREP( const wxString& aFileName );
// write the assembly in XAO format with pad faces as groups
bool WriteXAO( const wxString& aFileName );
/** /**
* Write the assembly in binary GLTF Format * Write the assembly in binary GLTF Format
* *
@ -259,6 +262,9 @@ private:
std::vector<TopoDS_Shape> m_board_copper_pads; std::vector<TopoDS_Shape> m_board_copper_pads;
std::vector<TopoDS_Shape> m_board_copper_fused; std::vector<TopoDS_Shape> m_board_copper_fused;
// Data for pads
std::map<wxString, std::pair<gp_Pnt, TopoDS_Shape>> m_pad_points;
/// Name of the PCB, which will most likely be the file name of the path. /// Name of the PCB, which will most likely be the file name of the path.
wxString m_pcbName; wxString m_pcbName;

View File

@ -4,7 +4,7 @@
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2022 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -133,7 +133,7 @@ void PCB_EDIT_FRAME::doReCreateMenuBar()
ID_GEN_EXPORT_FILE_VRML, BITMAPS::export3d ); ID_GEN_EXPORT_FILE_VRML, BITMAPS::export3d );
submenuExport->Add( _( "IDFv3..." ), _( "Export IDF 3D board representation" ), submenuExport->Add( _( "IDFv3..." ), _( "Export IDF 3D board representation" ),
ID_GEN_EXPORT_FILE_IDF3, BITMAPS::export_idf ); ID_GEN_EXPORT_FILE_IDF3, BITMAPS::export_idf );
submenuExport->Add( _( "STEP..." ), _( "Export STEP 3D board representation" ), submenuExport->Add( _( "STEP / BREP / XAO..." ), _( "Export STEP / BREP / XAO 3D board representation" ),
ID_GEN_EXPORT_FILE_STEP, BITMAPS::export_step ); ID_GEN_EXPORT_FILE_STEP, BITMAPS::export_step );
submenuExport->Add( _( "SVG..." ), _( "Export SVG board representation" ), submenuExport->Add( _( "SVG..." ), _( "Export SVG board representation" ),
ID_GEN_PLOT_SVG, BITMAPS::export_svg ); ID_GEN_PLOT_SVG, BITMAPS::export_svg );

View File

@ -135,6 +135,8 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
break; break;
case JOB_EXPORT_PCB_3D::FORMAT::BREP: fn.SetExt( FILEEXT::BrepFileExtension ); case JOB_EXPORT_PCB_3D::FORMAT::BREP: fn.SetExt( FILEEXT::BrepFileExtension );
break; break;
case JOB_EXPORT_PCB_3D::FORMAT::XAO: fn.SetExt( FILEEXT::XaoFileExtension );
break;
case JOB_EXPORT_PCB_3D::FORMAT::GLB: fn.SetExt( FILEEXT::GltfBinaryFileExtension ); case JOB_EXPORT_PCB_3D::FORMAT::GLB: fn.SetExt( FILEEXT::GltfBinaryFileExtension );
break; break;
default: default:
@ -216,6 +218,9 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
case JOB_EXPORT_PCB_3D::FORMAT::BREP: case JOB_EXPORT_PCB_3D::FORMAT::BREP:
params.m_format = EXPORTER_STEP_PARAMS::FORMAT::BREP; params.m_format = EXPORTER_STEP_PARAMS::FORMAT::BREP;
break; break;
case JOB_EXPORT_PCB_3D::FORMAT::XAO:
params.m_format = EXPORTER_STEP_PARAMS::FORMAT::XAO;
break;
case JOB_EXPORT_PCB_3D::FORMAT::GLB: case JOB_EXPORT_PCB_3D::FORMAT::GLB:
params.m_format = EXPORTER_STEP_PARAMS::FORMAT::GLB; params.m_format = EXPORTER_STEP_PARAMS::FORMAT::GLB;
break; break;