3D model export: Improve 3D layer placement calculation algorithm.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/18035
This commit is contained in:
Alex Shvartzkop 2024-05-17 18:19:44 +03:00
parent 4c42f5dae0
commit 0772739cf1
2 changed files with 57 additions and 3 deletions

View File

@ -916,6 +916,46 @@ bool STEP_PCB_MODEL::AddTrackSegment( const PCB_TRACK* aTrack, const VECTOR2D& a
void STEP_PCB_MODEL::getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos, void STEP_PCB_MODEL::getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos,
double& aThickness ) double& aThickness )
{
// Offsets above copper in mm
static const double c_silkscreenAboveCopper = 0.04;
static const double c_soldermaskAboveCopper = 0.015;
if( IsCopperLayer( aLayer ) )
{
getCopperLayerZPlacement( aLayer, aZPos, aThickness );
}
else if( IsFrontLayer( aLayer ) )
{
double f_pos, f_thickness;
getCopperLayerZPlacement( F_Cu, f_pos, f_thickness );
double top = std::max( f_pos, f_pos + f_thickness );
if( aLayer == F_SilkS )
aZPos = top + c_silkscreenAboveCopper;
else
aZPos = top + c_soldermaskAboveCopper;
aThickness = 0.0; // Normal points up
}
else if( IsBackLayer( aLayer ) )
{
double b_pos, b_thickness;
getCopperLayerZPlacement( B_Cu, b_pos, b_thickness );
double bottom = std::min( b_pos, b_pos + b_thickness );
if( aLayer == B_SilkS )
aZPos = bottom - c_silkscreenAboveCopper;
else
aZPos = bottom - c_soldermaskAboveCopper;
aThickness = -0.0; // Normal points down
}
}
void STEP_PCB_MODEL::getCopperLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos,
double& aThickness )
{ {
int z = 0; int z = 0;
int thickness = 0; int thickness = 0;
@ -923,14 +963,22 @@ void STEP_PCB_MODEL::getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPo
const std::vector<BOARD_STACKUP_ITEM*>& materials = m_stackup.GetList(); const std::vector<BOARD_STACKUP_ITEM*>& materials = m_stackup.GetList();
// Iterate from bottom to top
for( auto it = materials.rbegin(); it != materials.rend(); ++it ) for( auto it = materials.rbegin(); it != materials.rend(); ++it )
{ {
const BOARD_STACKUP_ITEM* item = *it; const BOARD_STACKUP_ITEM* item = *it;
if( item->GetType() == BS_ITEM_TYPE_COPPER ) if( item->GetType() == BS_ITEM_TYPE_COPPER )
{ {
if( aLayer == B_Cu )
{
// This is the first encountered layer
thickness = -item->GetThickness();
break;
}
// Inner copper position is usually inside prepreg // Inner copper position is usually inside prepreg
if( ( wasPrepreg || aLayer == B_Cu ) && aLayer != F_Cu ) if( wasPrepreg && item->GetBrdLayerId() != F_Cu )
thickness = -item->GetThickness(); thickness = -item->GetThickness();
else else
thickness = item->GetThickness(); thickness = item->GetThickness();
@ -938,7 +986,8 @@ void STEP_PCB_MODEL::getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPo
if( item->GetBrdLayerId() == aLayer ) if( item->GetBrdLayerId() == aLayer )
break; break;
z += thickness; if( item->GetBrdLayerId() != B_Cu )
z += item->GetThickness();
} }
else if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC ) else if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
{ {
@ -946,8 +995,11 @@ void STEP_PCB_MODEL::getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPo
// Dielectric can have sub-layers. Layer 0 is the main layer // Dielectric can have sub-layers. Layer 0 is the main layer
// Not frequent, but possible // Not frequent, but possible
thickness = 0;
for( int idx = 0; idx < item->GetSublayersCount(); idx++ ) for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
z += item->GetThickness( idx ); thickness += item->GetThickness( idx );
z += thickness;
} }
} }

View File

@ -203,6 +203,8 @@ private:
void getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos, double& aThickness ); void getLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos, double& aThickness );
void getCopperLayerZPlacement( const PCB_LAYER_ID aLayer, double& aZPos, double& aThickness );
void getBoardBodyZPlacement( double& aZPos, double& aThickness ); void getBoardBodyZPlacement( double& aZPos, double& aThickness );
/** /**