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_backPlatedPadPolys = nullptr;
m_frontPlatedCopperPolys = nullptr;
m_backPlatedCopperPolys = nullptr;
if( !g_ColorsLoaded )
{

View File

@ -434,6 +434,8 @@ private:
SHAPE_POLY_SET* m_frontPlatedPadPolys;
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_layerHoleIdPolys; ///< Hole inner diameters (per layer)

View File

@ -34,6 +34,7 @@
#include "board_adapter.h"
#include "../3d_rendering/raytracing/shapes2D/filled_circle_2d.h"
#include "raytracing/shapes2D/triangle_2d.h"
#include <board_design_settings.h>
#include <footprint.h>
#include <pad.h>
@ -118,6 +119,8 @@ void BOARD_ADAPTER::destroyLayers()
DELETE_AND_FREE( m_frontPlatedPadPolys )
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_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_backPlatedPadPolys = new SHAPE_POLY_SET;
m_frontPlatedCopperPolys = new SHAPE_POLY_SET;
m_backPlatedCopperPolys = new SHAPE_POLY_SET;
m_platedPadsFront = 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 ) );
}
}
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
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
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)
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
// its hole
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 );
}
}
if( cfg.renderPlatedPadsAsPlated )
if( cfg.differentiate_plated_copper )
{
// ADD PLATED PADS contours
for( FOOTPRINT* footprint : m_board->Footprints() )
@ -688,6 +691,17 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{
zones.emplace_back( std::make_pair( zone, layer ) );
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 )
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
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.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> 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.reserve( layer_ids.size() );
@ -816,8 +1124,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
auto layerPoly = m_layers_poly.find( selected_layer_id[i] );
if( layerPoly != m_layers_poly.end() )
{
// This will make a union of all added contours
layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
}
}
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
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
if( map_poly.find( layer ) != map_poly.end() )
if( m_boardAdapter.m_Cfg->m_Render.opengl_copper_thickness )
{
polyListSubtracted = *map_poly.at( layer );
if( LSET::PhysicalLayersMask().test( layer ) )
if( map_poly.find( layer ) != map_poly.end() )
{
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
SHAPE_POLY_SET::PM_FAST );
}
polyListSubtracted = *map_poly.at( layer );
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 );
}
if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
{
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
if( LSET::PhysicalLayersMask().test( layer ) )
{
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 );
}
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,
@ -607,20 +610,19 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
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* backPlatedPadPolys = m_boardAdapter.GetBackPlatedPadPolys();
if( frontPlatedPadPolys )
{
SHAPE_POLY_SET polySubtracted = frontPlatedPadPolys->CloneDropTriangulation();
polySubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
SHAPE_POLY_SET poly = frontPlatedPadPolys->CloneDropTriangulation();
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(),
&polySubtracted, F_Cu );
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(), &poly, F_Cu );
// 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 )
@ -629,13 +631,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
if( backPlatedPadPolys )
{
SHAPE_POLY_SET polySubtracted = backPlatedPadPolys->CloneDropTriangulation();
polySubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
polySubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
SHAPE_POLY_SET poly = backPlatedPadPolys->CloneDropTriangulation();
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(),
&polySubtracted, B_Cu );
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(), &poly, B_Cu );
// 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 )

View File

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

View File

@ -625,7 +625,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
break;
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 );
materialLayer = &m_materials.m_NonPlatedCopper;
@ -643,7 +643,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
} // for each layer on map
// 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,
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_Render.clip_silk_on_via_annuli, false ) );
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_Camera.animation_enabled, true ) );
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_lightAzimuth; // 0 .. 359
bool realistic;
bool show_adhesive;
bool show_axis;
bool show_board_body;
@ -146,7 +145,7 @@ public:
bool show_fp_text;
bool subtract_mask_from_silk;
bool clip_silk_on_via_annuli;
bool renderPlatedPadsAsPlated;
bool differentiate_plated_copper;
};
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_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 ) );
@ -80,7 +80,7 @@ bool PANEL_3D_DISPLAY_OPTIONS::TransferDataFromWindow()
cfg->m_Render.show_zones = m_checkBoxAreas->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.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() );