Handle plated vs non-plated copper for copper other than pads.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/5569
This commit is contained in:
Jeff Young 2023-09-22 18:31:04 +01:00
parent cce366bc1d
commit c1a988e3ff
9 changed files with 406 additions and 354 deletions

View File

@ -143,6 +143,8 @@ BOARD_ADAPTER::BOARD_ADAPTER() :
m_frontPlatedPadPolys = nullptr; m_frontPlatedPadPolys = nullptr;
m_backPlatedPadPolys = nullptr; m_backPlatedPadPolys = nullptr;
m_frontPlatedCopperPolys = nullptr;
m_backPlatedCopperPolys = nullptr;
if( !g_ColorsLoaded ) if( !g_ColorsLoaded )
{ {

View File

@ -434,6 +434,8 @@ private:
SHAPE_POLY_SET* m_frontPlatedPadPolys; SHAPE_POLY_SET* m_frontPlatedPadPolys;
SHAPE_POLY_SET* m_backPlatedPadPolys; SHAPE_POLY_SET* m_backPlatedPadPolys;
SHAPE_POLY_SET* m_frontPlatedCopperPolys;
SHAPE_POLY_SET* m_backPlatedCopperPolys;
MAP_POLY m_layerHoleOdPolys; ///< Hole outer diameters (per layer) MAP_POLY m_layerHoleOdPolys; ///< Hole outer diameters (per layer)
MAP_POLY m_layerHoleIdPolys; ///< Hole inner diameters (per layer) MAP_POLY m_layerHoleIdPolys; ///< Hole inner diameters (per layer)

View File

@ -34,6 +34,7 @@
#include "board_adapter.h" #include "board_adapter.h"
#include "../3d_rendering/raytracing/shapes2D/filled_circle_2d.h" #include "../3d_rendering/raytracing/shapes2D/filled_circle_2d.h"
#include "raytracing/shapes2D/triangle_2d.h"
#include <board_design_settings.h> #include <board_design_settings.h>
#include <footprint.h> #include <footprint.h>
#include <pad.h> #include <pad.h>
@ -118,6 +119,8 @@ void BOARD_ADAPTER::destroyLayers()
DELETE_AND_FREE( m_frontPlatedPadPolys ) DELETE_AND_FREE( m_frontPlatedPadPolys )
DELETE_AND_FREE( m_backPlatedPadPolys ) DELETE_AND_FREE( m_backPlatedPadPolys )
DELETE_AND_FREE( m_frontPlatedCopperPolys )
DELETE_AND_FREE( m_backPlatedCopperPolys )
DELETE_AND_FREE_MAP( m_layerHoleOdPolys ) DELETE_AND_FREE_MAP( m_layerHoleOdPolys )
DELETE_AND_FREE_MAP( m_layerHoleIdPolys ) DELETE_AND_FREE_MAP( m_layerHoleIdPolys )
@ -234,10 +237,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
} }
} }
if( cfg.renderPlatedPadsAsPlated ) if( cfg.differentiate_plated_copper )
{ {
m_frontPlatedPadPolys = new SHAPE_POLY_SET; m_frontPlatedPadPolys = new SHAPE_POLY_SET;
m_backPlatedPadPolys = new SHAPE_POLY_SET; m_backPlatedPadPolys = new SHAPE_POLY_SET;
m_frontPlatedCopperPolys = new SHAPE_POLY_SET;
m_backPlatedCopperPolys = new SHAPE_POLY_SET;
m_platedPadsFront = new BVH_CONTAINER_2D; m_platedPadsFront = new BVH_CONTAINER_2D;
m_platedPadsBack = new BVH_CONTAINER_2D; m_platedPadsBack = new BVH_CONTAINER_2D;
@ -339,6 +344,17 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
m_TH_IDs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius, *track ) ); m_TH_IDs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius, *track ) );
} }
} }
if( cfg.differentiate_plated_copper && layer == F_Cu )
{
track->TransformShapeToPolygon( *m_frontPlatedCopperPolys, F_Cu, 0, maxError,
ERROR_INSIDE );
}
else if( cfg.differentiate_plated_copper && layer == B_Cu )
{
track->TransformShapeToPolygon( *m_backPlatedCopperPolys, B_Cu, 0, maxError,
ERROR_INSIDE );
}
} }
} }
@ -529,26 +545,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PADS // ADD PADS
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
{ {
addPads( footprint, layerContainer, layer, cfg.renderPlatedPadsAsPlated, false ); addPads( footprint, layerContainer, layer, cfg.differentiate_plated_copper, false );
// Micro-wave footprints may have items on copper layers // Micro-wave footprints may have items on copper layers
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags ); addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
} }
} }
if( cfg.renderPlatedPadsAsPlated )
{
// ADD PLATED PADS
for( FOOTPRINT* footprint : m_board->Footprints() )
{
addPads( footprint, m_platedPadsFront, F_Cu, false, true );
addPads( footprint, m_platedPadsBack, B_Cu, false, true );
}
m_platedPadsFront->BuildBVH();
m_platedPadsBack->BuildBVH();
}
// Add footprints PADs poly contours (vertical outlines) // Add footprints PADs poly contours (vertical outlines)
if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL ) if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
{ {
@ -564,13 +567,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// Note: NPTH pads are not drawn on copper layers when the pad has same shape as // Note: NPTH pads are not drawn on copper layers when the pad has same shape as
// its hole // its hole
footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE, footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE,
true, cfg.renderPlatedPadsAsPlated, false ); true, cfg.differentiate_plated_copper, false );
transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE ); transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
} }
} }
if( cfg.renderPlatedPadsAsPlated ) if( cfg.differentiate_plated_copper )
{ {
// ADD PLATED PADS contours // ADD PLATED PADS contours
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
@ -688,6 +691,17 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{ {
zones.emplace_back( std::make_pair( zone, layer ) ); zones.emplace_back( std::make_pair( zone, layer ) );
layer_lock.emplace( layer, std::make_unique<std::mutex>() ); layer_lock.emplace( layer, std::make_unique<std::mutex>() );
if( cfg.differentiate_plated_copper && layer == F_Cu )
{
zone->TransformShapeToPolygon( *m_frontPlatedCopperPolys, F_Cu, 0, maxError,
ERROR_INSIDE );
}
else if( cfg.differentiate_plated_copper && layer == B_Cu )
{
zone->TransformShapeToPolygon( *m_backPlatedCopperPolys, B_Cu, 0, maxError,
ERROR_INSIDE );
}
} }
} }
@ -737,45 +751,339 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
while( threadsFinished < parallelThreadCount ) while( threadsFinished < parallelThreadCount )
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
} }
// End Build Copper layers
// This will make a union of all added contours
m_TH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_NPTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_viaTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_viaAnnuliPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
// Build Tech layers
// Based on:
// https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L1059
if( aStatusReporter )
aStatusReporter->Report( _( "Build Tech layers" ) );
// draw graphic items, on technical layers
static const PCB_LAYER_ID techLayerList[] = {
B_Adhes,
F_Adhes,
B_Paste,
F_Paste,
B_SilkS,
F_SilkS,
B_Mask,
F_Mask,
// Aux Layers
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User
};
std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
if( cfg.subtract_mask_from_silk || cfg.differentiate_plated_copper )
{
enabledFlags.set( LAYER_3D_SOLDERMASK_TOP );
enabledFlags.set( LAYER_3D_SOLDERMASK_BOTTOM );
}
for( PCB_LAYER_ID layer : LSET::AllNonCuMask().Seq( techLayerList, arrayDim( techLayerList ) ) )
{
if( aStatusReporter )
aStatusReporter->Report( wxString::Format( _( "Build Tech layer %d" ), (int) layer ) );
if( !Is3dLayerEnabled( layer, enabledFlags ) )
continue;
BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
m_layerMap[layer] = layerContainer;
SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
m_layers_poly[layer] = layerPoly;
if( Is3dLayerEnabled( layer, visibilityFlags ) )
{
// Add drawing objects
for( BOARD_ITEM* item : m_board->Drawings() )
{
if( !item->IsOnLayer( layer ) )
continue;
switch( item->Type() )
{
case PCB_SHAPE_T:
addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item );
break;
case PCB_TEXT_T:
addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
break;
case PCB_TEXTBOX_T:
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
break;
case PCB_DIM_ALIGNED_T:
case PCB_DIM_CENTER_T:
case PCB_DIM_RADIAL_T:
case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T:
addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
break;
default:
break;
}
}
// Add via tech layers
if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
{
int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
{
createViaWithMargin( track, layerContainer, maskExpansion );
}
}
}
// Add footprints tech layers - objects
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( layer == F_SilkS || layer == B_SilkS )
{
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
for( PAD* pad : footprint->Pads() )
{
if( !pad->IsOnLayer( layer ) )
continue;
buildPadOutlineAsSegments( pad, layerContainer, linewidth );
}
}
else
{
addPads( footprint, layerContainer, layer, false, false );
}
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
}
// Draw non copper zones
if( cfg.show_zones )
{
for( ZONE* zone : m_board->Zones() )
{
if( zone->IsOnLayer( layer ) )
addSolidAreasShapes( zone, layerContainer, layer );
}
}
}
// Add item contours. We need these if we're building vertical walls or if this is a
// mask layer and we're differentiating copper from plated copper.
if( ( cfg.engine == RENDER_ENGINE::OPENGL && cfg.opengl_copper_thickness )
|| ( cfg.differentiate_plated_copper && ( layer == F_Mask || layer == B_Mask ) ) )
{
// DRAWINGS
for( BOARD_ITEM* item : m_board->Drawings() )
{
if( !item->IsOnLayer( layer ) )
continue;
switch( item->Type() )
{
case PCB_SHAPE_T:
item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
break;
case PCB_TEXT_T:
{
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
break;
}
case PCB_TEXTBOX_T:
{
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
break;
}
default:
break;
}
}
// NON-TENTED VIAS
if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
{
int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
{
track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, maxError,
ERROR_INSIDE );
}
}
}
// FOOTPRINT CHILDREN
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( layer == F_SilkS || layer == B_SilkS )
{
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
for( PAD* pad : footprint->Pads() )
{
if( pad->IsOnLayer( layer ) )
{
buildPadOutlineAsPolygon( pad, *layerPoly, linewidth, maxError,
ERROR_INSIDE );
}
}
}
else
{
footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
}
// On tech layers, use a poor circle approximation, only for texts (stroke font)
footprint->TransformFPTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
// Add the remaining things with dynamic seg count for circles
transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
}
if( cfg.show_zones || layer == F_Mask || layer == B_Mask )
{
for( ZONE* zone : m_board->Zones() )
{
if( zone->IsOnLayer( layer ) )
zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
}
}
// This will make a union of all added contours
layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
}
}
// End Build Tech layers
#if 1
// A somewhat experimental feature: if we're rendering off-board silk, turn any pads of
// footprints which are entirely outside the board outline into silk. This makes off-board
// footprints more visually recognizable.
if( cfg.show_off_board_silk )
{
BOX2I boardBBox = m_board_poly.BBox();
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
{
if( footprint->IsFlipped() )
{
BVH_CONTAINER_2D *layerContainer = m_layerMap[ B_SilkS ];
addPads( footprint, layerContainer, B_Cu, false, false );
}
else
{
BVH_CONTAINER_2D *layerContainer = m_layerMap[ F_SilkS ];
addPads( footprint, layerContainer, F_Cu, false, false );
}
}
}
}
#endif
// Simplify layer polygons // Simplify layer polygons
if( aStatusReporter ) if( aStatusReporter )
aStatusReporter->Report( _( "Simplifying copper layers polygons" ) ); aStatusReporter->Report( _( "Simplifying copper layer polygons" ) );
if( cfg.differentiate_plated_copper )
{
if( aStatusReporter )
aStatusReporter->Report( _( "Calculating plated copper" ) );
// TRIM PLATED COPPER TO SOLDERMASK
if( m_layers_poly.find( F_Mask ) != m_layers_poly.end() )
{
m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ),
SHAPE_POLY_SET::PM_FAST );
}
if( m_layers_poly.find( B_Mask ) != m_layers_poly.end() )
{
m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ),
SHAPE_POLY_SET::PM_FAST );
}
// SUBTRACT PLATED COPPER FROM (UNPLATED) COPPER
if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
{
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
}
if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
{
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
}
m_frontPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_backPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
// ADD PLATED PADS
for( FOOTPRINT* footprint : m_board->Footprints() )
{
addPads( footprint, m_platedPadsFront, F_Cu, false, true );
addPads( footprint, m_platedPadsBack, B_Cu, false, true );
}
// ADD PLATED COPPER
ConvertPolygonToTriangles( *m_frontPlatedCopperPolys, *m_platedPadsFront, m_biuTo3Dunits,
*m_board->GetItem( niluuid ) );
ConvertPolygonToTriangles( *m_backPlatedCopperPolys, *m_platedPadsBack, m_biuTo3Dunits,
*m_board->GetItem( niluuid ) );
m_platedPadsFront->BuildBVH();
m_platedPadsBack->BuildBVH();
}
if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL ) if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
{ {
if( cfg.renderPlatedPadsAsPlated )
{
if( m_frontPlatedPadPolys && ( m_layers_poly.find( F_Cu ) != m_layers_poly.end() ) )
{
if( aStatusReporter )
aStatusReporter->Report( _( "Simplifying polygons on F_Cu" ) );
SHAPE_POLY_SET *layerPoly_F_Cu = m_layers_poly[F_Cu];
layerPoly_F_Cu->BooleanSubtract( *m_frontPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
m_frontPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
}
if( m_backPlatedPadPolys && ( m_layers_poly.find( B_Cu ) != m_layers_poly.end() ) )
{
if( aStatusReporter )
aStatusReporter->Report( _( "Simplifying polygons on B_Cu" ) );
SHAPE_POLY_SET *layerPoly_B_Cu = m_layers_poly[B_Cu];
layerPoly_B_Cu->BooleanSubtract( *m_backPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
m_backPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
}
}
std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids; std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
std::vector<PCB_LAYER_ID> layer_id_without_F_and_B; std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
if( cfg.renderPlatedPadsAsPlated ) if( cfg.differentiate_plated_copper )
{ {
layer_id_without_F_and_B.clear(); layer_id_without_F_and_B.clear();
layer_id_without_F_and_B.reserve( layer_ids.size() ); layer_id_without_F_and_B.reserve( layer_ids.size() );
@ -816,8 +1124,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
auto layerPoly = m_layers_poly.find( selected_layer_id[i] ); auto layerPoly = m_layers_poly.find( selected_layer_id[i] );
if( layerPoly != m_layers_poly.end() ) if( layerPoly != m_layers_poly.end() )
{
// This will make a union of all added contours // This will make a union of all added contours
layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST ); layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
}
} }
threadsFinished++; threadsFinished++;
@ -850,268 +1160,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
} }
} }
// End Build Copper layers
// This will make a union of all added contours
m_TH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_NPTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_viaTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_viaAnnuliPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
// Build Tech layers
// Based on:
// https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L1059
if( aStatusReporter )
aStatusReporter->Report( _( "Build Tech layers" ) );
// draw graphic items, on technical layers
// Vertical walls (layer thickness) around shapes is really time consumming
// They are built on request
bool buildVerticalWallsForTechLayers = cfg.opengl_copper_thickness
&& cfg.engine == RENDER_ENGINE::OPENGL;
static const PCB_LAYER_ID techLayerList[] = {
B_Adhes,
F_Adhes,
B_Paste,
F_Paste,
B_SilkS,
F_SilkS,
B_Mask,
F_Mask,
// Aux Layers
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User
};
for( LSEQ seq = LSET::AllNonCuMask().Seq( techLayerList, arrayDim( techLayerList ) );
seq;
++seq )
{
const PCB_LAYER_ID layer = *seq;
if( !Is3dLayerEnabled( layer, visibilityFlags ) )
continue;
if( aStatusReporter )
aStatusReporter->Report( wxString::Format( _( "Build Tech layer %d" ), (int) layer ) );
BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
m_layerMap[layer] = layerContainer;
SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
m_layers_poly[layer] = layerPoly;
// Add drawing objects
for( BOARD_ITEM* item : m_board->Drawings() )
{
if( !item->IsOnLayer( layer ) )
continue;
switch( item->Type() )
{
case PCB_SHAPE_T:
addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item );
break;
case PCB_TEXT_T:
addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
break;
case PCB_TEXTBOX_T:
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
break;
case PCB_DIM_ALIGNED_T:
case PCB_DIM_CENTER_T:
case PCB_DIM_RADIAL_T:
case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T:
addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
break;
default:
break;
}
}
// Add drawing contours (vertical walls)
if( buildVerticalWallsForTechLayers )
{
for( BOARD_ITEM* item : m_board->Drawings() )
{
if( !item->IsOnLayer( layer ) )
continue;
switch( item->Type() )
{
case PCB_SHAPE_T:
item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
break;
case PCB_TEXT_T:
{
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
break;
}
case PCB_TEXTBOX_T:
{
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
break;
}
default:
break;
}
}
}
// Add via tech layers
if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
{
int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
{
createViaWithMargin( track, layerContainer, maskExpansion );
}
}
// Add via tech layers - contours (vertical walls)
if( buildVerticalWallsForTechLayers )
{
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
{
track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, maxError,
ERROR_INSIDE );
}
}
}
}
// Add footprints tech layers - objects
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( layer == F_SilkS || layer == B_SilkS )
{
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
for( PAD* pad : footprint->Pads() )
{
if( !pad->IsOnLayer( layer ) )
continue;
buildPadOutlineAsSegments( pad, layerContainer, linewidth );
}
}
else
{
addPads( footprint, layerContainer, layer, false, false );
}
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
}
// Add footprints tech layers - contours (vertical walls)
if( buildVerticalWallsForTechLayers )
{
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( layer == F_SilkS || layer == B_SilkS )
{
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
for( PAD* pad : footprint->Pads() )
{
if( pad->IsOnLayer( layer ) )
{
buildPadOutlineAsPolygon( pad, *layerPoly, linewidth, maxError,
ERROR_INSIDE );
}
}
}
else
{
footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
}
// On tech layers, use a poor circle approximation, only for texts (stroke font)
footprint->TransformFPTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
// Add the remaining things with dynamic seg count for circles
transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
}
}
// Draw non copper zones
if( cfg.show_zones )
{
for( ZONE* zone : m_board->Zones() )
{
if( zone->IsOnLayer( layer ) )
addSolidAreasShapes( zone, layerContainer, layer );
}
if( buildVerticalWallsForTechLayers )
{
for( ZONE* zone : m_board->Zones() )
{
if( zone->IsOnLayer( layer ) )
zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
}
}
}
// This will make a union of all added contours
layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
}
// End Build Tech layers
#if 1
// A somewhat experimental feature: if we're rendering off-board silk, turn any pads of
// footprints which are entirely outside the board outline into silk. This makes off-board
// footprints more visually recognizable.
if( cfg.show_off_board_silk )
{
BOX2I boardBBox = m_board_poly.BBox();
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
{
if( footprint->IsFlipped() )
{
BVH_CONTAINER_2D *layerContainer = m_layerMap[ B_SilkS ];
addPads( footprint, layerContainer, B_Cu, false, false );
}
else
{
BVH_CONTAINER_2D *layerContainer = m_layerMap[ F_SilkS ];
addPads( footprint, layerContainer, F_Cu, false, false );
}
}
}
}
#endif
// Build BVH (Bounding volume hierarchy) for holes and vias // Build BVH (Bounding volume hierarchy) for holes and vias
if( aStatusReporter ) if( aStatusReporter )

View File

@ -565,39 +565,42 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
// Load the vertical (Z axis) component of shapes // Load the vertical (Z axis) component of shapes
if( map_poly.find( layer ) != map_poly.end() ) if( m_boardAdapter.m_Cfg->m_Render.opengl_copper_thickness )
{ {
polyListSubtracted = *map_poly.at( layer ); if( map_poly.find( layer ) != map_poly.end() )
if( LSET::PhysicalLayersMask().test( layer ) )
{ {
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(), polyListSubtracted = *map_poly.at( layer );
SHAPE_POLY_SET::PM_FAST );
}
if( layer != B_Mask && layer != F_Mask ) if( LSET::PhysicalLayersMask().test( layer ) )
{
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(),
SHAPE_POLY_SET::PM_FAST );
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(),
SHAPE_POLY_SET::PM_FAST );
}
if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
{
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
{ {
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ), polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
SHAPE_POLY_SET::PM_FAST );
}
if( layer != B_Mask && layer != F_Mask )
{
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(),
SHAPE_POLY_SET::PM_FAST );
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(),
SHAPE_POLY_SET::PM_FAST ); SHAPE_POLY_SET::PM_FAST );
} }
else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
{
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ),
SHAPE_POLY_SET::PM_FAST );
}
}
polyList = &polyListSubtracted; if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
{
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
{
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ),
SHAPE_POLY_SET::PM_FAST );
}
else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
{
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ),
SHAPE_POLY_SET::PM_FAST );
}
}
polyList = &polyListSubtracted;
}
} }
OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, polyList, layer, OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, polyList, layer,
@ -607,20 +610,19 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
m_layers[layer] = oglList; m_layers[layer] = oglList;
} }
if( m_boardAdapter.m_Cfg->m_Render.renderPlatedPadsAsPlated ) if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
{ {
const SHAPE_POLY_SET* frontPlatedPadPolys = m_boardAdapter.GetFrontPlatedPadPolys(); const SHAPE_POLY_SET* frontPlatedPadPolys = m_boardAdapter.GetFrontPlatedPadPolys();
const SHAPE_POLY_SET* backPlatedPadPolys = m_boardAdapter.GetBackPlatedPadPolys(); const SHAPE_POLY_SET* backPlatedPadPolys = m_boardAdapter.GetBackPlatedPadPolys();
if( frontPlatedPadPolys ) if( frontPlatedPadPolys )
{ {
SHAPE_POLY_SET polySubtracted = frontPlatedPadPolys->CloneDropTriangulation(); SHAPE_POLY_SET poly = frontPlatedPadPolys->CloneDropTriangulation();
polySubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(), m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(), &poly, F_Cu );
&polySubtracted, F_Cu );
// An entry for F_Cu must exist in m_layers or we'll never look at m_platedPadsFront // An entry for F_Cu must exist in m_layers or we'll never look at m_platedPadsFront
if( m_layers.count( F_Cu ) == 0 ) if( m_layers.count( F_Cu ) == 0 )
@ -629,13 +631,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
if( backPlatedPadPolys ) if( backPlatedPadPolys )
{ {
SHAPE_POLY_SET polySubtracted = backPlatedPadPolys->CloneDropTriangulation(); SHAPE_POLY_SET poly = backPlatedPadPolys->CloneDropTriangulation();
polySubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(), m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(), &poly, B_Cu );
&polySubtracted, B_Cu );
// An entry for B_Cu must exist in m_layers or we'll never look at m_platedPadsBack // An entry for B_Cu must exist in m_layers or we'll never look at m_platedPadsBack
if( m_layers.count( B_Cu ) == 0 ) if( m_layers.count( B_Cu ) == 0 )

View File

@ -584,7 +584,7 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
if( isCopperLayer ) if( isCopperLayer )
{ {
if( cfg.renderPlatedPadsAsPlated ) if( cfg.differentiate_plated_copper )
setCopperMaterial(); setCopperMaterial();
else else
setLayerMaterial( layer_id ); setLayerMaterial( layer_id );

View File

@ -625,7 +625,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
break; break;
default: default:
if( m_boardAdapter.m_Cfg->m_Render.renderPlatedPadsAsPlated ) if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
{ {
layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f ); layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
materialLayer = &m_materials.m_NonPlatedCopper; materialLayer = &m_materials.m_NonPlatedCopper;
@ -643,7 +643,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
} // for each layer on map } // for each layer on map
// Create plated copper // Create plated copper
if( m_boardAdapter.m_Cfg->m_Render.renderPlatedPadsAsPlated ) if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
{ {
createItemsFromContainer( m_boardAdapter.GetPlatedPadsFront(), F_Cu, &m_materials.m_Copper, createItemsFromContainer( m_boardAdapter.GetPlatedPadsFront(), F_Cu, &m_materials.m_Copper,
m_boardAdapter.m_CopperColor, m_boardAdapter.m_CopperColor,

View File

@ -367,7 +367,7 @@ EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() :
m_params.emplace_back( new PARAM<bool>( "render.clip_silk_on_via_annulus", m_params.emplace_back( new PARAM<bool>( "render.clip_silk_on_via_annulus",
&m_Render.clip_silk_on_via_annuli, false ) ); &m_Render.clip_silk_on_via_annuli, false ) );
m_params.emplace_back( new PARAM<bool>( "render.plated_and_bare_copper", m_params.emplace_back( new PARAM<bool>( "render.plated_and_bare_copper",
&m_Render.renderPlatedPadsAsPlated, false ) ); &m_Render.differentiate_plated_copper, false ) );
m_params.emplace_back( new PARAM<bool>( "camera.animation_enabled", m_params.emplace_back( new PARAM<bool>( "camera.animation_enabled",
&m_Camera.animation_enabled, true ) ); &m_Camera.animation_enabled, true ) );
m_params.emplace_back( new PARAM<int>( "camera.moving_speed_multiplier", m_params.emplace_back( new PARAM<int>( "camera.moving_speed_multiplier",

View File

@ -120,7 +120,6 @@ public:
std::vector<int> raytrace_lightElevation; // -90 .. 90 std::vector<int> raytrace_lightElevation; // -90 .. 90
std::vector<int> raytrace_lightAzimuth; // 0 .. 359 std::vector<int> raytrace_lightAzimuth; // 0 .. 359
bool realistic;
bool show_adhesive; bool show_adhesive;
bool show_axis; bool show_axis;
bool show_board_body; bool show_board_body;
@ -146,7 +145,7 @@ public:
bool show_fp_text; bool show_fp_text;
bool subtract_mask_from_silk; bool subtract_mask_from_silk;
bool clip_silk_on_via_annuli; bool clip_silk_on_via_annuli;
bool renderPlatedPadsAsPlated; bool differentiate_plated_copper;
}; };
struct CAMERA_SETTINGS struct CAMERA_SETTINGS

View File

@ -49,7 +49,7 @@ void PANEL_3D_DISPLAY_OPTIONS::loadViewSettings( EDA_3D_VIEWER_SETTINGS* aCfg )
m_checkBoxSubtractMaskFromSilk->SetValue( aCfg->m_Render.subtract_mask_from_silk ); m_checkBoxSubtractMaskFromSilk->SetValue( aCfg->m_Render.subtract_mask_from_silk );
m_checkBoxClipSilkOnViaAnnulus->SetValue( aCfg->m_Render.clip_silk_on_via_annuli ); m_checkBoxClipSilkOnViaAnnulus->SetValue( aCfg->m_Render.clip_silk_on_via_annuli );
m_checkBoxRenderPlatedPadsAsPlated->SetValue( aCfg->m_Render.renderPlatedPadsAsPlated ); m_checkBoxRenderPlatedPadsAsPlated->SetValue( aCfg->m_Render.differentiate_plated_copper );
m_materialProperties->SetSelection( static_cast<int>( aCfg->m_Render.material_mode ) ); m_materialProperties->SetSelection( static_cast<int>( aCfg->m_Render.material_mode ) );
@ -80,7 +80,7 @@ bool PANEL_3D_DISPLAY_OPTIONS::TransferDataFromWindow()
cfg->m_Render.show_zones = m_checkBoxAreas->GetValue(); cfg->m_Render.show_zones = m_checkBoxAreas->GetValue();
cfg->m_Render.subtract_mask_from_silk = m_checkBoxSubtractMaskFromSilk->GetValue(); cfg->m_Render.subtract_mask_from_silk = m_checkBoxSubtractMaskFromSilk->GetValue();
cfg->m_Render.clip_silk_on_via_annuli = m_checkBoxClipSilkOnViaAnnulus->GetValue(); cfg->m_Render.clip_silk_on_via_annuli = m_checkBoxClipSilkOnViaAnnulus->GetValue();
cfg->m_Render.renderPlatedPadsAsPlated = m_checkBoxRenderPlatedPadsAsPlated->GetValue(); cfg->m_Render.differentiate_plated_copper = m_checkBoxRenderPlatedPadsAsPlated->GetValue();
cfg->m_Render.material_mode = static_cast<MATERIAL_MODE>( m_materialProperties->GetSelection() ); cfg->m_Render.material_mode = static_cast<MATERIAL_MODE>( m_materialProperties->GetSelection() );