7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-07 18:45:32 +00:00

Simplify (and fix) plated copper differentiation.

Also a few fixes for 3D rendering textboxes and
tables.
This commit is contained in:
Jeff Young 2025-03-17 20:08:05 +00:00
parent 683444733a
commit 142f8265c5
8 changed files with 108 additions and 145 deletions

View File

@ -146,8 +146,6 @@ BOARD_ADAPTER::BOARD_ADAPTER() :
m_offboardPadsFront = nullptr;
m_offboardPadsBack = nullptr;
m_frontPlatedPadAndGraphicPolys = nullptr;
m_backPlatedPadAndGraphicPolys = nullptr;
m_frontPlatedCopperPolys = nullptr;
m_backPlatedCopperPolys = nullptr;

View File

@ -341,14 +341,14 @@ public:
*/
const MAP_POLY& GetPolyMap() const noexcept { return m_layers_poly; }
const SHAPE_POLY_SET* GetFrontPlatedPadAndGraphicPolys()
const SHAPE_POLY_SET* GetFrontPlatedCopperPolys()
{
return m_frontPlatedPadAndGraphicPolys;
return m_frontPlatedCopperPolys;
}
const SHAPE_POLY_SET* GetBackPlatedPadAndGraphicPolys()
const SHAPE_POLY_SET* GetBackPlatedCopperPolys()
{
return m_backPlatedPadAndGraphicPolys;
return m_backPlatedCopperPolys;
}
const MAP_POLY& GetHoleIdPolysMap() const noexcept { return m_layerHoleIdPolys; }
@ -375,7 +375,7 @@ private:
int aInflateValue );
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads );
PCB_LAYER_ID aLayerId );
void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId,
@ -461,8 +461,6 @@ private:
MAP_POLY m_layers_poly; ///< Amalgamated polygon contours for various types
///< of items
SHAPE_POLY_SET* m_frontPlatedPadAndGraphicPolys;
SHAPE_POLY_SET* m_backPlatedPadAndGraphicPolys;
SHAPE_POLY_SET* m_frontPlatedCopperPolys;
SHAPE_POLY_SET* m_backPlatedCopperPolys;

View File

@ -503,7 +503,7 @@ void BOARD_ADAPTER::createPadWithHole( const PAD* aPad, CONTAINER_2D_BASE* aDstC
void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aContainer,
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads )
PCB_LAYER_ID aLayerId )
{
for( PAD* pad : aFootprint->Pads() )
{
@ -527,24 +527,6 @@ void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aCo
switch( aLayerId )
{
case F_Cu:
if( aSkipPlatedPads && pad->FlashLayer( F_Mask ) )
continue;
if( aSkipNonPlatedPads && !pad->FlashLayer( F_Mask ) )
continue;
break;
case B_Cu:
if( aSkipPlatedPads && pad->FlashLayer( B_Mask ) )
continue;
if( aSkipNonPlatedPads && !pad->FlashLayer( B_Mask ) )
continue;
break;
case F_Mask:
case B_Mask:
margin.x += pad->GetSolderMaskExpansion( aLayerId );

View File

@ -183,8 +183,6 @@ void BOARD_ADAPTER::destroyLayers()
DELETE_AND_FREE_MAP( m_layers_poly );
DELETE_AND_FREE( m_frontPlatedPadAndGraphicPolys )
DELETE_AND_FREE( m_backPlatedPadAndGraphicPolys )
DELETE_AND_FREE( m_frontPlatedCopperPolys )
DELETE_AND_FREE( m_backPlatedCopperPolys )
@ -302,8 +300,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( cfg.DifferentiatePlatedCopper() )
{
m_frontPlatedPadAndGraphicPolys = new SHAPE_POLY_SET;
m_backPlatedPadAndGraphicPolys = new SHAPE_POLY_SET;
m_frontPlatedCopperPolys = new SHAPE_POLY_SET;
m_backPlatedCopperPolys = new SHAPE_POLY_SET;
@ -614,10 +610,19 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PADS
for( FOOTPRINT* footprint : m_board->Footprints() )
{
addPads( footprint, layerContainer, layer, cfg.DifferentiatePlatedCopper(), false );
// Micro-wave footprints may have items on copper layers
addPads( footprint, layerContainer, layer );
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
if( cfg.DifferentiatePlatedCopper() && layer == F_Cu )
{
footprint->TransformPadsToPolySet( *m_frontPlatedCopperPolys, F_Cu, 0, maxError,
ERROR_INSIDE, true );
}
else if( cfg.DifferentiatePlatedCopper() && layer == B_Cu )
{
footprint->TransformPadsToPolySet( *m_backPlatedCopperPolys, B_Cu, 0, maxError,
ERROR_INSIDE, true );
}
}
}
@ -636,24 +641,11 @@ 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.DifferentiatePlatedCopper(), false );
true );
transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
}
}
if( cfg.DifferentiatePlatedCopper() )
{
// ADD PLATED PADS contours
for( FOOTPRINT* footprint : m_board->Footprints() )
{
footprint->TransformPadsToPolySet( *m_frontPlatedPadAndGraphicPolys, F_Cu, 0,
maxError, ERROR_INSIDE, true, false, true );
footprint->TransformPadsToPolySet( *m_backPlatedPadAndGraphicPolys, B_Cu, 0,
maxError, ERROR_INSIDE, true, false, true );
}
}
}
// Add graphic item on copper layers to object containers
@ -702,36 +694,29 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
}
// add also this shape to the plated copper polygon list if required
if( cfg.DifferentiatePlatedCopper() )
if( cfg.DifferentiatePlatedCopper() && ( layer == F_Cu || layer == B_Cu ) )
{
// Note: for TEXT and TEXTBOX, TransformShapeToPolygon returns the bounding
// box shape, not the exact text shape. So it is not used for these items
if( layer == F_Cu || layer == B_Cu )
{
SHAPE_POLY_SET* platedCopperPolys = layer == F_Cu
? m_frontPlatedCopperPolys
SHAPE_POLY_SET* copperPolys = layer == F_Cu ? m_frontPlatedCopperPolys
: m_backPlatedCopperPolys;
if( item->Type() == PCB_TEXTBOX_T )
{
PCB_TEXTBOX* text_box = static_cast<PCB_TEXTBOX*>( item );
text_box->TransformTextToPolySet( *platedCopperPolys,
0, maxError, ERROR_INSIDE );
// Add box outlines
text_box->PCB_SHAPE::TransformShapeToPolygon( *platedCopperPolys, layer,
0, maxError, ERROR_INSIDE );
}
else if( item->Type() == PCB_TEXT_T )
{
static_cast<PCB_TEXT*>( item )->TransformTextToPolySet( *platedCopperPolys,
0, maxError,
ERROR_INSIDE );
}
else
{
item->TransformShapeToPolySet( *platedCopperPolys, layer, 0, maxError,
ERROR_INSIDE );
}
// Note: for TEXT and TEXTBOX, TransformShapeToPolygon returns the bounding
// box shape, not the exact text shape. So it is not used for these items
if( item->Type() == PCB_TEXTBOX_T )
{
PCB_TEXTBOX* text_box = static_cast<PCB_TEXTBOX*>( item );
text_box->TransformTextToPolySet( *copperPolys, 0, maxError, ERROR_INSIDE );
// Add box outlines
text_box->PCB_SHAPE::TransformShapeToPolygon( *copperPolys, layer, 0, maxError,
ERROR_INSIDE );
}
else if( item->Type() == PCB_TEXT_T )
{
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
text->TransformTextToPolySet( *copperPolys, 0, maxError, ERROR_INSIDE );
}
else
{
item->TransformShapeToPolySet( *copperPolys, layer, 0, maxError, ERROR_INSIDE );
}
}
}
@ -770,13 +755,32 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
if( textbox->IsBorderEnabled() )
{
textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0,
maxError, ERROR_INSIDE );
}
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
break;
}
case PCB_TABLE_T:
// JEY TODO: tables
{
PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
for( PCB_TABLECELL* cell : table->GetCells() )
cell->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
table->DrawBorders(
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB,
const STROKE_PARAMS& stroke )
{
SHAPE_SEGMENT seg( ptA, ptB, stroke.GetWidth() );
seg.TransformToPolygon( *layerPoly, maxError, ERROR_INSIDE );
} );
break;
}
default:
wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ),
@ -1042,7 +1046,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
}
else
{
addPads( footprint, layerContainer, layer, false, false );
addPads( footprint, layerContainer, layer );
}
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
@ -1088,13 +1092,33 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
if( textbox->IsBorderEnabled() )
{
textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0,
maxError, ERROR_INSIDE );
}
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
break;
}
case PCB_TABLE_T:
// JEY TODO: tables
{
PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
for( PCB_TABLECELL* cell : table->GetCells() )
cell->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
table->DrawBorders(
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB,
const STROKE_PARAMS& stroke )
{
SHAPE_SEGMENT seg( ptA, ptB, stroke.GetWidth() );
seg.TransformToPolygon( *layerPoly, maxError, ERROR_INSIDE );
} );
break;
}
default:
break;
@ -1172,9 +1196,9 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
{
if( footprint->IsFlipped() )
addPads( footprint, m_offboardPadsBack, B_Cu, false, false );
addPads( footprint, m_offboardPadsBack, B_Cu );
else
addPads( footprint, m_offboardPadsFront, F_Cu, false, false );
addPads( footprint, m_offboardPadsFront, F_Cu );
}
}
@ -1200,41 +1224,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ) );
// Subtract plated copper from unplated copper
bool hasF_Cu = false;
bool hasB_Cu = false;
if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
{
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys );
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys );
hasF_Cu = true;
}
if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
{
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys );
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys );
hasB_Cu = true;
}
// Add plated graphic items to build vertical walls
if( hasF_Cu && m_frontPlatedCopperPolys->OutlineCount() )
m_frontPlatedPadAndGraphicPolys->Append( *m_frontPlatedCopperPolys );
if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
m_frontPlatedPadAndGraphicPolys->Simplify();
m_backPlatedPadAndGraphicPolys->Simplify();
m_frontPlatedCopperPolys->Simplify();
m_backPlatedCopperPolys->Simplify();
// 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,

View File

@ -607,14 +607,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
if( m_boardAdapter.m_Cfg->m_Render.DifferentiatePlatedCopper() )
{
const SHAPE_POLY_SET* frontPlatedPadAndGraphicPolys =
m_boardAdapter.GetFrontPlatedPadAndGraphicPolys();
const SHAPE_POLY_SET* backPlatedPadAndGraphicPolys =
m_boardAdapter.GetBackPlatedPadAndGraphicPolys();
const SHAPE_POLY_SET* frontPlatedCopperPolys = m_boardAdapter.GetFrontPlatedCopperPolys();
const SHAPE_POLY_SET* backPlatedCopperPolys = m_boardAdapter.GetBackPlatedCopperPolys();
if( frontPlatedPadAndGraphicPolys )
if( frontPlatedCopperPolys )
{
SHAPE_POLY_SET poly = frontPlatedPadAndGraphicPolys->CloneDropTriangulation();
SHAPE_POLY_SET poly = frontPlatedCopperPolys->CloneDropTriangulation();
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
@ -627,9 +625,9 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
m_layers[F_Cu] = generateEmptyLayerList( F_Cu );
}
if( backPlatedPadAndGraphicPolys )
if( backPlatedCopperPolys )
{
SHAPE_POLY_SET poly = backPlatedPadAndGraphicPolys->CloneDropTriangulation();
SHAPE_POLY_SET poly = backPlatedCopperPolys->CloneDropTriangulation();
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );

View File

@ -29,6 +29,8 @@
#include <board_design_settings.h>
#include <footprint.h>
#include <pcb_textbox.h>
#include <pcb_table.h>
#include <pcb_tablecell.h>
#include <pcb_track.h>
#include <pcb_shape.h>
#include <pad.h>
@ -545,8 +547,22 @@ bool EXPORTER_STEP::buildGraphic3DShape( BOARD_ITEM* aItem, VECTOR2D aOrigin )
}
case PCB_TABLE_T:
// JEY TODO: tables
{
PCB_TABLE* table = static_cast<PCB_TABLE*>( aItem );
for( PCB_TABLECELL* cell : table->GetCells() )
cell->TransformTextToPolySet( m_poly_shapes[pcblayer], 0, maxError, ERROR_INSIDE );
table->DrawBorders(
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB,
const STROKE_PARAMS& stroke )
{
SHAPE_SEGMENT seg( ptA, ptB, stroke.GetWidth() );
seg.TransformToPolygon( m_poly_shapes[pcblayer], maxError, ERROR_INSIDE );
} );
break;
}
default: wxFAIL_MSG( "buildGraphic3DShape: unhandled item type" );
}

View File

@ -3852,8 +3852,7 @@ bool FOOTPRINT::cmp_zones::operator()( const ZONE* aFirst, const ZONE* aSecond )
void FOOTPRINT::TransformPadsToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aMaxError, ERROR_LOC aErrorLoc,
bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
bool aSkipNonPlatedPads ) const
bool aSkipNPTHPadsWihNoCopper ) const
{
auto processPad =
[&]( const PAD* pad, PCB_LAYER_ID padLayer )
@ -3862,24 +3861,6 @@ void FOOTPRINT::TransformPadsToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aL
switch( aLayer )
{
case F_Cu:
if( aSkipPlatedPads && pad->FlashLayer( F_Mask ) )
return;
if( aSkipNonPlatedPads && !pad->FlashLayer( F_Mask ) )
return;
break;
case B_Cu:
if( aSkipPlatedPads && pad->FlashLayer( B_Mask ) )
return;
if( aSkipNonPlatedPads && !pad->FlashLayer( B_Mask ) )
return;
break;
case F_Mask:
case B_Mask:
clearance.x += pad->GetSolderMaskExpansion( padLayer );

View File

@ -539,14 +539,10 @@ public:
* Due to diff between layers and holes, these pads must be skipped to be sure
* there is no copper left on the board (for instance when creating Gerber Files or
* 3D shapes). Defaults to false.
* @param aSkipPlatedPads is used on 3D-Viewer to extract plated and non-plated pads.
* @param aSkipNonPlatedPads is used on 3D-Viewer to extract plated and plated pads.
*/
void TransformPadsToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
int aMaxError, ERROR_LOC aErrorLoc,
bool aSkipNPTHPadsWihNoCopper = false,
bool aSkipPlatedPads = false,
bool aSkipNonPlatedPads = false ) const;
bool aSkipNPTHPadsWihNoCopper = false ) const;
/**
* Generate shapes of graphic items (outlines) on layer \a aLayer as polygons and adds these