Step exporter: code cleaning and merge connected tracks in polygons

This commit is contained in:
jean-pierre charras 2023-03-06 11:47:29 +01:00
parent d96598c87c
commit eeee3adb94
4 changed files with 84 additions and 32 deletions

View File

@ -121,6 +121,7 @@ EXPORTER_STEP::EXPORTER_STEP( BOARD* aBoard, const EXPORTER_STEP_PARAMS& aParams
m_boardThickness( DEFAULT_BOARD_THICKNESS_MM )
{
m_solderMaskColor = COLOR4D( 0.08, 0.20, 0.14, 0.83 );
m_copperColor = COLOR4D( 0.7, 0.61, 0.0, 1.0 );
m_resolver = std::make_unique<FILENAME_RESOLVER>();
m_resolver->Set3DConfigDir( wxT( "" ) );
@ -135,7 +136,7 @@ EXPORTER_STEP::~EXPORTER_STEP()
}
bool EXPORTER_STEP::composePCB( FOOTPRINT* aFootprint, VECTOR2D aOrigin )
bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin )
{
bool hasdata = false;
@ -152,6 +153,20 @@ bool EXPORTER_STEP::composePCB( FOOTPRINT* aFootprint, VECTOR2D aOrigin )
}
}
// Build 3D shapes of the footprint graphic items on external layers:
if( ExportTracksAndVias() )
{
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 */ );
}
if( ( aFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) && !m_params.m_includeExcludedBom )
{
return hasdata;
@ -241,7 +256,7 @@ bool EXPORTER_STEP::composePCB( FOOTPRINT* aFootprint, VECTOR2D aOrigin )
}
bool EXPORTER_STEP::composePCB( PCB_TRACK* aTrack, VECTOR2D aOrigin )
bool EXPORTER_STEP::buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin )
{
if( aTrack->Type() == PCB_VIA_T )
{
@ -268,15 +283,18 @@ bool EXPORTER_STEP::composePCB( PCB_TRACK* aTrack, VECTOR2D aOrigin )
SHAPE_POLY_SET copper_shapes;
int maxError = m_board->GetDesignSettings().m_MaxError;
aTrack->TransformShapeToPolygon( copper_shapes, pcblayer, 0, maxError, ERROR_INSIDE );
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 );
m_pcbModel->AddCopperPolygonShapes( &copper_shapes, pcblayer == F_Cu, aOrigin );
//m_pcbModel->AddCopperPolygonShapes( &copper_shapes, pcblayer == F_Cu, aOrigin );
return true;
}
bool EXPORTER_STEP::composePCB()
bool EXPORTER_STEP::buildBoard3DShapes()
{
if( m_pcbModel )
return true;
@ -303,6 +321,7 @@ bool EXPORTER_STEP::composePCB()
// TODO: Handle when top & bottom soldermask colours are different...
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 );
@ -320,14 +339,20 @@ bool EXPORTER_STEP::composePCB()
// For copper layers, only pads and tracks are added, because adding everything on copper
// generate unreasonable file sizes and take a unreasonable calculation time.
for( FOOTPRINT* fp : m_board->Footprints() )
composePCB( fp, origin );
buildFootprint3DShapes( fp, origin );
if( ExportTracksAndVias() )
{
for( PCB_TRACK* track : m_board->Tracks() )
composePCB( track, origin );
buildTrack3DShape( track, origin );
}
m_top_copper_shapes.Fracture( SHAPE_POLY_SET::PM_FAST );
m_bottom_copper_shapes.Fracture( SHAPE_POLY_SET::PM_FAST );
m_pcbModel->AddCopperPolygonShapes( &m_top_copper_shapes, true, origin );
m_pcbModel->AddCopperPolygonShapes( &m_bottom_copper_shapes, false, origin );
ReportMessage( wxT( "Create PCB solid model\n" ) );
wxString msg;
@ -344,7 +369,7 @@ bool EXPORTER_STEP::composePCB()
}
void EXPORTER_STEP::determinePcbThickness()
void EXPORTER_STEP::calculatePcbThickness()
{
m_boardThickness = DEFAULT_BOARD_THICKNESS_MM;
@ -389,7 +414,7 @@ bool EXPORTER_STEP::Export()
Message::DefaultMessenger()->AddPrinter( new KiCadPrinter( this ) );
ReportMessage( _( "Determining PCB data\n" ) );
determinePcbThickness();
calculatePcbThickness();
wxString msg;
msg.Printf( _( "Board Thickness from stackup: %.3f mm\n" ), m_boardThickness );
ReportMessage( msg );
@ -398,7 +423,7 @@ bool EXPORTER_STEP::Export()
{
ReportMessage( _( "Build STEP data\n" ) );
if( !composePCB() )
if( !buildBoard3DShapes() )
{
ReportMessage( _( "\n** Error building STEP board model. Export aborted. **\n" ) );
return false;

View File

@ -87,10 +87,10 @@ public:
bool ExportTracksAndVias() { return m_params.m_exportTracks; }
private:
bool composePCB();
bool composePCB( FOOTPRINT* aFootprint, VECTOR2D aOrigin );
bool composePCB( PCB_TRACK* aTrack, VECTOR2D aOrigin );
void determinePcbThickness();
bool buildBoard3DShapes();
bool buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin );
bool buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin );
void calculatePcbThickness();
EXPORTER_STEP_PARAMS m_params;
std::unique_ptr<FILENAME_RESOLVER> m_resolver;
@ -107,7 +107,11 @@ private:
double m_boardThickness;
SHAPE_POLY_SET m_top_copper_shapes;
SHAPE_POLY_SET m_bottom_copper_shapes;
KIGFX::COLOR4D m_solderMaskColor;
KIGFX::COLOR4D m_copperColor;
};
#endif

View File

@ -178,7 +178,7 @@ STEP_PCB_MODEL::STEP_PCB_MODEL( const wxString& aPcbName )
{
m_app = XCAFApp_Application::GetApplication();
m_app->NewDocument( "MDTV-XCAF", m_doc );
m_assy = XCAFDoc_DocumentTool::ShapeTool ( m_doc->Main() );
m_assy = XCAFDoc_DocumentTool::ShapeTool( m_doc->Main() );
m_assy_label = m_assy->NewShape();
m_hasPCB = false;
m_components = 0;
@ -277,16 +277,19 @@ bool STEP_PCB_MODEL::AddPadHole( const PAD* aPad, const VECTOR2D& aOrigin )
return false;
VECTOR2I pos = aPad->GetPosition();
double holeZsize = m_boardThickness + ( m_copperThickness * 2 );
const double margin = 0.01; // a small margin on the Z axix to be sure the hole
// is bigget than the board with copper
// must be > OCC_MAX_DISTANCE_TO_MERGE_POINTS
double holeZsize = m_boardThickness + ( m_copperThickness * 2 ) + ( margin * 2 );
if( aPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
{
TopoDS_Shape s =
BRepPrimAPI_MakeCylinder( pcbIUScale.IUTomm( aPad->GetDrillSize().x ) * 0.5, holeZsize * 2.0 ).Shape();
BRepPrimAPI_MakeCylinder( pcbIUScale.IUTomm( aPad->GetDrillSize().x ) * 0.5, holeZsize ).Shape();
gp_Trsf shift;
shift.SetTranslation( gp_Vec( pcbIUScale.IUTomm( pos.x - aOrigin.x ),
-pcbIUScale.IUTomm( pos.y - aOrigin.y ),
-holeZsize * 0.5 ) );
-m_copperThickness - margin ) );
BRepBuilderAPI_Transform hole( s, shift );
m_cutouts.push_back( hole.Shape() );
return true;
@ -304,7 +307,7 @@ bool STEP_PCB_MODEL::AddPadHole( const PAD* aPad, const VECTOR2D& aOrigin )
if( holeOutlines.OutlineCount() > 0 )
{
if( MakeShape( hole, holeOutlines.COutline( 0 ), holeZsize*2, -holeZsize * 0.5, aOrigin ) )
if( MakeShape( hole, holeOutlines.COutline( 0 ), holeZsize, -m_copperThickness - margin, aOrigin ) )
{
m_cutouts.push_back( hole );
}
@ -392,6 +395,14 @@ void STEP_PCB_MODEL::SetBoardColor( double r, double g, double b )
}
void STEP_PCB_MODEL::SetCopperColor( double r, double g, double b )
{
m_copperColor[0] = r;
m_copperColor[1] = g;
m_copperColor[2] = b;
}
void STEP_PCB_MODEL::OCCSetMergeMaxDistance( double aDistance )
{
// Ensure a minimal value (in mm)
@ -562,7 +573,7 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
for( TopoDS_Shape& hole : m_cutouts )
holelist.Append( hole );
// Remove holes for each board (usually there is only one board
// Remove holes for each board (usually there is only one board)
int cnt = 0;
for( TopoDS_Shape& board: m_board_outlines )
{
@ -605,18 +616,18 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
// identically named assemblies. So we want to avoid having the PCB be generally defaulted
// to "Component" or "Assembly".
// color the PCB
// Init colors for the board body and the copper items (if any)
Handle( XCAFDoc_ColorTool ) colorTool = XCAFDoc_DocumentTool::ColorTool( m_doc->Main() );
Quantity_Color board_color( m_boardColor[0], m_boardColor[1], m_boardColor[2], Quantity_TOC_RGB );
Quantity_Color copper_color( 0.7, 0.61, 0.0, Quantity_TOC_RGB );
Quantity_Color board_color( m_boardColor[0], m_boardColor[1], m_boardColor[2],
Quantity_TOC_RGB );
Quantity_Color copper_color( m_copperColor[0], m_copperColor[1], m_copperColor[2],
Quantity_TOC_RGB );
int pcbIdx = 1;
int copper_objects_cnt = 0;
for( TDF_Label& pcb_label : m_pcb_labels )
{
colorTool->SetColor( pcb_label, board_color, XCAFDoc_ColorSurf );
Handle( TDataStd_TreeNode ) node;
if( pcb_label.FindAttribute( XCAFDoc::ShapeRefGUID(), node ) )
@ -628,10 +639,17 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
{
wxString pcbName;
if( m_pcb_labels.size() == 1 )
pcbName = wxT( "PCB" );
if( copper_objects_cnt < copper_item_count )
{
pcbName = wxString::Format( wxT( "Copper_Item%d" ), copper_objects_cnt+1 );
}
else
pcbName = wxString::Format( wxT( "PCB%d" ), pcbIdx++ );
{
if( m_pcb_labels.size() == 1 )
pcbName = wxT( "PCB" );
else
pcbName = wxString::Format( wxT( "PCB%d" ), pcbIdx++ );
}
std::string pcbNameStdString( pcbName.ToUTF8() );
TCollection_ExtendedString partname( pcbNameStdString.c_str() );
@ -641,10 +659,11 @@ bool STEP_PCB_MODEL::CreatePCB( SHAPE_POLY_SET& aOutline, VECTOR2D aOrigin )
// color the PCB
TopExp_Explorer topex;
topex.Init( m_assy->GetShape( pcb_label ), TopAbs_SOLID );
topex.Init( m_assy->GetShape( pcb_label ), TopAbs_COMPOUND /*TopAbs_SOLID*/ );
while( topex.More() )
{
// First objects are copper objects, last(s) is the board body
if( copper_objects_cnt < copper_item_count )
colorTool->SetColor( topex.Current(), copper_color, XCAFDoc_ColorSurf );
else

View File

@ -44,9 +44,9 @@
/**
* Default distance between points to treat them as separate ones (mm)
* 0.001 mm is a reasonable value. A too large value creates issues by
* 0.001 mm or less is a reasonable value. A too large value creates issues by
* merging points that should be different.
* Remember we are a 3D space, so a thin line can be broken if 2 points
* Remember we are a 3D space, so a thin shape can be broken if 2 points
* are merged (in X, Y, Z coords) when they should not.
* round shapes converted to polygon can also be not good with a to large value
*/
@ -56,9 +56,11 @@ static constexpr double OCC_MAX_DISTANCE_TO_MERGE_POINTS = 0.001;
static constexpr double BOARD_THICKNESS_DEFAULT_MM = 1.6;
// minimum PCB thickness in mm (10 microns assumes a very thin polyimide film)
// must be > OCC_MAX_DISTANCE_TO_MERGE_POINTS
static constexpr double BOARD_THICKNESS_MIN_MM = 0.01;
// default copper thickness in mm
// must be > OCC_MAX_DISTANCE_TO_MERGE_POINTS
static constexpr double COPPER_THICKNESS_DEFAULT_MM = 0.035;
// Max error to approximate an arc by segments (in mm)
@ -92,6 +94,7 @@ public:
VECTOR3D aOrientation, VECTOR3D aScale, bool aSubstituteModels = true );
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
@ -166,7 +169,8 @@ private:
int m_components; // number of successfully loaded components;
double m_precision; // model (length unit) numeric precision
double m_angleprec; // angle numeric precision
double m_boardColor[3]; // RGB values
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