From f41af10007dd651292c1568c536ab536c10a1288 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 22 Jul 2022 23:05:25 +0100 Subject: [PATCH] Clean up hole shapes for safety (smart pointer) and consistency. --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 26 +++--- gerbview/gerber_draw_item.cpp | 6 +- include/board_item.h | 7 +- pcbnew/board_item.cpp | 14 ++- pcbnew/connectivity/connectivity_data.cpp | 8 +- pcbnew/dialogs/dialog_pad_properties.cpp | 11 ++- pcbnew/drc/drc_rtree.h | 52 +++++++---- .../drc_test_provider_copper_clearance.cpp | 74 ++++++---------- .../drc_test_provider_courtyard_clearance.cpp | 33 +++---- .../drc/drc_test_provider_edge_clearance.cpp | 9 +- .../drc_test_provider_physical_clearance.cpp | 54 ++++-------- .../drc/drc_test_provider_silk_clearance.cpp | 23 +---- pcbnew/footprint.cpp | 14 ++- pcbnew/pad.cpp | 24 ++--- pcbnew/pad.h | 4 +- pcbnew/pcb_expr_evaluator.cpp | 13 +-- pcbnew/pcb_painter.cpp | 24 ++--- pcbnew/pcb_track.cpp | 6 ++ pcbnew/pcb_track.h | 5 +- pcbnew/plot_board_layers.cpp | 31 ++++--- pcbnew/router/pns_kicad_iface.cpp | 2 +- pcbnew/tools/drawing_tool.cpp | 24 ++--- pcbnew/tools/edit_tool_move_fct.cpp | 24 ++--- pcbnew/tools/pcb_control.cpp | 87 +++++++++++-------- pcbnew/zone.cpp | 17 +--- 25 files changed, 269 insertions(+), 323 deletions(-) diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index 214a80889e..a6a71e3fd5 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -429,28 +429,26 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo OBJECT_2D* BOARD_ADAPTER::createPadWithDrill( const PAD* aPad, int aInflateValue ) { - VECTOR2I drillSize = aPad->GetDrillSize(); - - if( !drillSize.x || !drillSize.y ) + if( !aPad->HasHole() ) { wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::createPadWithDrill - found an invalid pad" ) ); return nullptr; } - if( drillSize.x == drillSize.y ) // usual round hole + std::shared_ptr slot = aPad->GetEffectiveHoleShape(); + + if( slot->GetSeg().A == slot->GetSeg().B ) { - const int radius = ( drillSize.x / 2 ) + aInflateValue; - - return new FILLED_CIRCLE_2D( TO_SFVEC2F( aPad->GetPosition() ), TO_3DU( radius ), *aPad ); - + return new FILLED_CIRCLE_2D( TO_SFVEC2F( slot->GetSeg().A ), + TO_3DU( slot->GetWidth() / 2 + aInflateValue ), + *aPad ); } - else // Oblong hole + else { - const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape(); - float width = seg->GetWidth() + aInflateValue * 2; - - return new ROUND_SEGMENT_2D( TO_SFVEC2F( seg->GetSeg().A ), TO_SFVEC2F( seg->GetSeg().B ), - TO_3DU( width ), *aPad ); + return new ROUND_SEGMENT_2D( TO_SFVEC2F( slot->GetSeg().A ), + TO_SFVEC2F( slot->GetSeg().B ), + TO_3DU( slot->GetWidth() + aInflateValue * 2 ), + *aPad ); } } diff --git a/gerbview/gerber_draw_item.cpp b/gerbview/gerber_draw_item.cpp index e8aef49a47..12cf3d71cd 100644 --- a/gerbview/gerber_draw_item.cpp +++ b/gerbview/gerber_draw_item.cpp @@ -687,15 +687,15 @@ void GERBER_DRAW_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER, - FLASHING aFlash = FLASHING::DEFAULT ) const; + FLASHING aFlash = FLASHING::DEFAULT ) const; + + virtual std::shared_ptr GetEffectiveHoleShape() const; BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_parent; } diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp index ae6da69ce0..1f4b6fc284 100644 --- a/pcbnew/board_item.cpp +++ b/pcbnew/board_item.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -196,7 +196,7 @@ bool BOARD_ITEM::ptr_cmp::operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b std::shared_ptr BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const { - std::shared_ptr shape; + static std::shared_ptr shape; UNIMPLEMENTED_FOR( GetClass() ); @@ -204,6 +204,16 @@ std::shared_ptr BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASH } +std::shared_ptr BOARD_ITEM::GetEffectiveHoleShape() const +{ + static std::shared_ptr slot; + + UNIMPLEMENTED_FOR( GetClass() ); + + return slot; +} + + BOARD_ITEM_CONTAINER* BOARD_ITEM::GetParentFootprint() const { BOARD_ITEM_CONTAINER* ancestor = GetParent(); diff --git a/pcbnew/connectivity/connectivity_data.cpp b/pcbnew/connectivity/connectivity_data.cpp index 04cfc3f73e..46d25ad31d 100644 --- a/pcbnew/connectivity/connectivity_data.cpp +++ b/pcbnew/connectivity/connectivity_data.cpp @@ -398,14 +398,12 @@ bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, i if( aItem->Type() == PCB_PAD_T && zoneLayer ) { const PAD* pad = static_cast( aItem ); - SHAPE_SEGMENT hole( *pad->GetEffectiveHoleShape() ); - PCB_LAYER_ID layer = ToLAYER_ID( aLayer ); ZONE* zone = static_cast( zoneLayer->Parent() ); int islandIdx = zoneLayer->SubpolyIndex(); if( zone->IsFilled() ) { - const SHAPE_POLY_SET* zoneFill = zone->GetFill( layer ); + const SHAPE_POLY_SET* zoneFill = zone->GetFill( ToLAYER_ID( aLayer ) ); const SHAPE_LINE_CHAIN& padHull = pad->GetEffectivePolygon()->Outline( 0 ); for( const VECTOR2I& pt : zoneFill->COutline( islandIdx ).CPoints() ) @@ -424,14 +422,12 @@ bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, i else if( aItem->Type() == PCB_VIA_T && zoneLayer ) { const PCB_VIA* via = static_cast( aItem ); - SHAPE_CIRCLE hole( via->GetCenter(), via->GetDrillValue() / 2 ); - PCB_LAYER_ID layer = ToLAYER_ID( aLayer ); ZONE* zone = static_cast( zoneLayer->Parent() ); int islandIdx = zoneLayer->SubpolyIndex(); if( zone->IsFilled() ) { - const SHAPE_POLY_SET* zoneFill = zone->GetFill( layer ); + const SHAPE_POLY_SET* zoneFill = zone->GetFill( ToLAYER_ID( aLayer ) ); SHAPE_CIRCLE viaHull( via->GetCenter(), via->GetWidth() / 2 ); for( const VECTOR2I& pt : zoneFill->COutline( islandIdx ).CPoints() ) diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index b269e7f0a3..1c2d91ca04 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -1281,14 +1281,13 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK() } else if( m_dummyPad->GetAttribute() == PAD_ATTRIB::PTH ) { - const SHAPE_SEGMENT* drillShape = m_dummyPad->GetEffectiveHoleShape(); - const SEG drillSeg = drillShape->GetSeg(); - SHAPE_POLY_SET drillOutline; + std::shared_ptr slot = m_dummyPad->GetEffectiveHoleShape(); + SHAPE_POLY_SET slotOutline; - TransformOvalToPolygon( drillOutline, drillSeg.A, drillSeg.B, - drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE ); + TransformOvalToPolygon( slotOutline, slot->GetSeg().A, slot->GetSeg().B, + slot->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE ); - padOutline.BooleanSubtract( drillOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST ); + padOutline.BooleanSubtract( slotOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST ); if( padOutline.IsEmpty() ) warning_msgs.Add( _( "Warning: Pad hole will leave no copper." ) ); diff --git a/pcbnew/drc/drc_rtree.h b/pcbnew/drc/drc_rtree.h index 4aea5c6464..1fdd977619 100644 --- a/pcbnew/drc/drc_rtree.h +++ b/pcbnew/drc/drc_rtree.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020 CERN * * This program is free software; you can redistribute it and/or @@ -53,13 +53,23 @@ public: { ITEM_WITH_SHAPE( BOARD_ITEM *aParent, const SHAPE* aShape, std::shared_ptr aParentShape = nullptr ) : - parent ( aParent ), - shape ( aShape ), + parent( aParent ), + shape( aShape ), + shapeStorage( nullptr ), parentShape( aParentShape ) {}; - BOARD_ITEM* parent; - const SHAPE* shape; + ITEM_WITH_SHAPE( BOARD_ITEM *aParent, std::shared_ptr aShape, + std::shared_ptr aParentShape = nullptr ) : + parent( aParent ), + shape( aShape.get() ), + shapeStorage( aShape ), + parentShape( aParentShape ) + {}; + + BOARD_ITEM* parent; + const SHAPE* shape; + std::shared_ptr shapeStorage; std::shared_ptr parentShape; }; @@ -79,9 +89,9 @@ public: ~DRC_RTREE() { - for( auto tree : m_tree ) + for( drc_rtree* tree : m_tree ) { - for( auto el : *tree ) + for( DRC_RTREE::ITEM_WITH_SHAPE* el : *tree ) delete el; delete tree; @@ -110,24 +120,12 @@ public: std::vector subshapes; std::shared_ptr shape = aItem->GetEffectiveShape( aRefLayer ); - subshapes.clear(); if( shape->HasIndexableSubshapes() ) shape->GetIndexableSubshapes( subshapes ); else subshapes.push_back( shape.get() ); - if( aItem->Type() == PCB_PAD_T ) - { - PAD* pad = static_cast( aItem ); - - if( pad->HasHole() ) - { - const SHAPE* hole = pad->GetEffectiveHoleShape(); - subshapes.push_back( const_cast( hole ) ); - } - } - for( const SHAPE* subshape : subshapes ) { if( dynamic_cast( subshape ) ) @@ -144,6 +142,22 @@ public: m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape ); m_count++; } + + if( aItem->Type() == PCB_PAD_T && aItem->HasHole() ) + { + std::shared_ptr hole = aItem->GetEffectiveHoleShape(); + BOX2I bbox = hole->BBox(); + + bbox.Inflate( aWorstClearance ); + + const int mmin[2] = { bbox.GetX(), bbox.GetY() }; + const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() }; + ITEM_WITH_SHAPE* itemShape = new ITEM_WITH_SHAPE( aItem, hole, shape ); + + m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape ); + m_count++; + + } } /** diff --git a/pcbnew/drc/drc_test_provider_copper_clearance.cpp b/pcbnew/drc/drc_test_provider_copper_clearance.cpp index b641b0c689..c673ad3483 100644 --- a/pcbnew/drc/drc_test_provider_copper_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_copper_clearance.cpp @@ -229,24 +229,18 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track, } } - if( testHoles && ( other->Type() == PCB_VIA_T || other->Type() == PCB_PAD_T ) ) + if( testHoles && other->HasHole() ) { - std::unique_ptr holeShape; + std::shared_ptr holeShape; if( other->Type() == PCB_VIA_T ) { - PCB_VIA* via = static_cast( other ); - pos = via->GetPosition(); - - if( via->GetLayerSet().Contains( layer ) ) - holeShape.reset( new SHAPE_SEGMENT( pos, pos, via->GetDrill() ) ); + if( other->GetLayerSet().Contains( layer ) ) + holeShape = other->GetEffectiveHoleShape(); } - else if( other->Type() == PCB_PAD_T ) + else { - PAD* pad = static_cast( other ); - - if( pad->GetDrillSize().x ) - holeShape.reset( new SHAPE_SEGMENT( *pad->GetEffectiveHoleShape() ) ); + holeShape = other->GetEffectiveHoleShape(); } if( holeShape ) @@ -285,7 +279,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track, void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone( BOARD_ITEM* aItem, ZONE* aZone, - PCB_LAYER_ID aLayer ) + PCB_LAYER_ID aLayer ) { if( !aZone->GetLayerSet().test( aLayer ) ) return; @@ -312,31 +306,22 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone( BOARD_ITEM* aItem, int clearance = -1; int actual; VECTOR2I pos; - PCB_VIA* via = nullptr; - PAD* pad = nullptr; - bool flashed = false; - bool hasHole = false; + bool unflashedPad = false; bool platedHole = false; - if( aItem->Type() == PCB_VIA_T ) + if( aItem->Type() == PCB_PAD_T ) { - via = static_cast( aItem ); - } - else if( aItem->Type() == PCB_PAD_T ) - { - pad = static_cast( aItem ); - flashed = pad->FlashLayer( aLayer ); - hasHole = pad->GetDrillSize().x > 0 || pad->GetDrillSize().y > 0; + unflashedPad = !static_cast( aItem )->FlashLayer( aLayer ); - if( !flashed && !hasHole ) + if( unflashedPad && !aItem->HasHole() ) return; - platedHole = hasHole && pad->GetAttribute() == PAD_ATTRIB::PTH; + platedHole = static_cast( aItem )->GetAttribute() == PAD_ATTRIB::PTH; } if( zoneTree && testClearance ) { - if( pad && !flashed && hasHole && !platedHole ) + if( unflashedPad && !platedHole ) constraintType = HOLE_CLEARANCE_CONSTRAINT; constraint = m_drcEngine->EvalRules( constraintType, aItem, aZone, aLayer ); @@ -347,10 +332,10 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone( BOARD_ITEM* aItem, { std::shared_ptr itemShape = aItem->GetEffectiveShape( aLayer ); - if( pad && !flashed && hasHole ) + if( unflashedPad ) { - const SHAPE_SEGMENT* hole = pad->GetEffectiveHoleShape(); - int size = hole->GetWidth(); + std::shared_ptr hole = aItem->GetEffectiveHoleShape(); + int size = hole->GetWidth(); // Note: drill size represents finish size, which means the actual hole size is // 2x the plating thickness larger. @@ -380,18 +365,18 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone( BOARD_ITEM* aItem, } } - if( zoneTree && testHoles && ( pad || via ) ) + if( zoneTree && testHoles && aItem->HasHole() ) { - std::unique_ptr holeShape; + std::shared_ptr holeShape; - if( via && via->GetLayerSet().Contains( aLayer ) ) + if( aItem->Type() == PCB_VIA_T ) { - holeShape.reset( new SHAPE_SEGMENT( via->GetPosition(), via->GetPosition(), - via->GetDrill() ) ); + if( aItem->GetLayerSet().Contains( aLayer ) ) + holeShape = aItem->GetEffectiveHoleShape(); } - else if( pad && pad->GetDrillSize().x ) + else { - holeShape.reset( new SHAPE_SEGMENT( *pad->GetEffectiveHoleShape() ) ); + holeShape = aItem->GetEffectiveHoleShape(); } if( holeShape ) @@ -628,9 +613,9 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa testHoles = false; } - if( testHoles && otherPad && pad->FlashLayer( aLayer ) && otherPad->GetDrillSize().x ) + if( testHoles && otherPad && pad->FlashLayer( aLayer ) && otherPad->HasHole() ) { - if( clearance > 0 && padShape->Collide( otherPad->GetEffectiveHoleShape(), + if( clearance > 0 && padShape->Collide( otherPad->GetEffectiveHoleShape().get(), std::max( 0, clearance - m_drcEpsilon ), &actual, &pos ) ) { @@ -651,9 +636,9 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa } } - if( testHoles && otherPad && otherPad->FlashLayer( aLayer ) && pad->GetDrillSize().x ) + if( testHoles && otherPad && otherPad->FlashLayer( aLayer ) && pad->HasHole() ) { - if( clearance > 0 && otherShape->Collide( pad->GetEffectiveHoleShape(), + if( clearance > 0 && otherShape->Collide( pad->GetEffectiveHoleShape().get(), std::max( 0, clearance - m_drcEpsilon ), &actual, &pos ) ) { @@ -676,10 +661,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa if( testHoles && otherVia && otherVia->IsOnLayer( aLayer ) ) { - pos = otherVia->GetPosition(); - otherShape.reset( new SHAPE_SEGMENT( pos, pos, otherVia->GetDrill() ) ); - - if( clearance > 0 && padShape->Collide( otherShape.get(), + if( clearance > 0 && padShape->Collide( otherVia->GetEffectiveHoleShape().get(), std::max( 0, clearance - m_drcEpsilon ), &actual, &pos ) ) { diff --git a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp index 77583cca55..8fbfc021c3 100644 --- a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp @@ -259,7 +259,7 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances() } auto testPadAgainstCourtyards = - [&]( const PAD* pad, const FOOTPRINT* footprint ) + [&]( const PAD* pad, const FOOTPRINT* fp ) { int errorCode = 0; @@ -273,21 +273,24 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances() if( m_drcEngine->IsErrorLimitExceeded( errorCode ) ) return; - const SHAPE_SEGMENT* hole = pad->GetEffectiveHoleShape(); - const SHAPE_POLY_SET& front = footprint->GetPolyCourtyard( F_CrtYd ); - const SHAPE_POLY_SET& back = footprint->GetPolyCourtyard( B_CrtYd ); + if( pad->HasHole() ) + { + std::shared_ptr hole = pad->GetEffectiveHoleShape(); + const SHAPE_POLY_SET& front = fp->GetPolyCourtyard( F_CrtYd ); + const SHAPE_POLY_SET& back = fp->GetPolyCourtyard( B_CrtYd ); - if( front.OutlineCount() > 0 && front.Collide( hole, 0 ) ) - { - std::shared_ptr drce = DRC_ITEM::Create( errorCode ); - drce->SetItems( pad, footprint ); - reportViolation( drce, pad->GetPosition(), F_CrtYd ); - } - else if( back.OutlineCount() > 0 && back.Collide( hole, 0 ) ) - { - std::shared_ptr drce = DRC_ITEM::Create( errorCode ); - drce->SetItems( pad, footprint ); - reportViolation( drce, pad->GetPosition(), B_CrtYd ); + if( front.OutlineCount() > 0 && front.Collide( hole.get(), 0 ) ) + { + std::shared_ptr drce = DRC_ITEM::Create( errorCode ); + drce->SetItems( pad, fp ); + reportViolation( drce, pad->GetPosition(), F_CrtYd ); + } + else if( back.OutlineCount() > 0 && back.Collide( hole.get(), 0 ) ) + { + std::shared_ptr drce = DRC_ITEM::Create( errorCode ); + drce->SetItems( pad, fp ); + reportViolation( drce, pad->GetPosition(), B_CrtYd ); + } } }; diff --git a/pcbnew/drc/drc_test_provider_edge_clearance.cpp b/pcbnew/drc/drc_test_provider_edge_clearance.cpp index 98e718722d..cf57bc13be 100644 --- a/pcbnew/drc/drc_test_provider_edge_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_edge_clearance.cpp @@ -86,11 +86,12 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::testAgainstEdge( BOARD_ITEM* item, SHAPE* DRC_CONSTRAINT_T aConstraintType, PCB_DRC_CODE aErrorCode ) { - const std::shared_ptr& shape = edge->GetEffectiveShape( Edge_Cuts ); - const SHAPE* edgeShape = shape.get(); + std::shared_ptr shape; if( edge->Type() == PCB_PAD_T ) - edgeShape = static_cast( edge )->GetEffectiveHoleShape(); + shape = edge->GetEffectiveHoleShape(); + else + shape = edge->GetEffectiveShape( Edge_Cuts ); auto constraint = m_drcEngine->EvalRules( aConstraintType, edge, item, UNDEFINED_LAYER ); int minClearance = constraint.GetValue().Min(); @@ -99,7 +100,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::testAgainstEdge( BOARD_ITEM* item, SHAPE* if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && minClearance >= 0 ) { - if( itemShape->Collide( edgeShape, minClearance, &actual, &pos ) ) + if( itemShape->Collide( shape.get(), minClearance, &actual, &pos ) ) { if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T ) { diff --git a/pcbnew/drc/drc_test_provider_physical_clearance.cpp b/pcbnew/drc/drc_test_provider_physical_clearance.cpp index 95de339fc9..962e0afb76 100644 --- a/pcbnew/drc/drc_test_provider_physical_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_physical_clearance.cpp @@ -593,40 +593,28 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstItem( BOARD_ITEM* item if( testHoles ) { - std::unique_ptr itemHoleShape; - std::unique_ptr otherHoleShape; + std::shared_ptr itemHoleShape; + std::shared_ptr otherHoleShape; clearance = 0; if( item->Type() == PCB_VIA_T ) { - PCB_VIA* via = static_cast( item ); - pos = via->GetPosition(); - - if( via->GetLayerSet().Contains( layer ) ) - itemHoleShape.reset( new SHAPE_SEGMENT( pos, pos, via->GetDrill() ) ); + if( item->GetLayerSet().Contains( layer ) ) + itemHoleShape = item->GetEffectiveHoleShape(); } - else if( item->Type() == PCB_PAD_T ) + else if( item->HasHole() ) { - PAD* pad = static_cast( item ); - - if( pad->GetDrillSize().x ) - itemHoleShape.reset( new SHAPE_SEGMENT( *pad->GetEffectiveHoleShape() ) ); + itemHoleShape = item->GetEffectiveHoleShape(); } if( other->Type() == PCB_VIA_T ) { - PCB_VIA* via = static_cast( other ); - pos = via->GetPosition(); - - if( via->GetLayerSet().Contains( layer ) ) - otherHoleShape.reset( new SHAPE_SEGMENT( pos, pos, via->GetDrill() ) ); + if( other->GetLayerSet().Contains( layer ) ) + otherHoleShape = other->GetEffectiveHoleShape(); } - else if( other->Type() == PCB_PAD_T ) + else if( other->HasHole() ) { - PAD* pad = static_cast( other ); - - if( pad->GetDrillSize().x ) - otherHoleShape.reset( new SHAPE_SEGMENT( *pad->GetEffectiveHoleShape() ) ); + otherHoleShape = other->GetEffectiveHoleShape(); } if( itemHoleShape || otherHoleShape ) @@ -722,8 +710,8 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aIt if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 ) continue; - const SHAPE_SEGMENT* hole = pad->GetEffectiveHoleShape(); - int size = hole->GetWidth(); + std::shared_ptr hole = pad->GetEffectiveHoleShape(); + int size = hole->GetWidth(); // Note: drill size represents finish size, which means the actual hole // size is the plating thickness larger. @@ -763,24 +751,18 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aIt } } - if( testHoles && ( aItem->Type() == PCB_VIA_T || aItem->Type() == PCB_PAD_T ) ) + if( testHoles ) { - std::unique_ptr holeShape; + std::shared_ptr holeShape; if( aItem->Type() == PCB_VIA_T ) { - PCB_VIA* via = static_cast( aItem ); - pos = via->GetPosition(); - - if( via->GetLayerSet().Contains( aLayer ) ) - holeShape.reset( new SHAPE_SEGMENT( pos, pos, via->GetDrill() ) ); + if( aItem->GetLayerSet().Contains( aLayer ) ) + holeShape = aItem->GetEffectiveHoleShape(); } - else if( aItem->Type() == PCB_PAD_T ) + else if( aItem->HasHole() ) { - PAD* pad = static_cast( aItem ); - - if( pad->GetDrillSize().x ) - holeShape.reset( new SHAPE_SEGMENT( *pad->GetEffectiveHoleShape() ) ); + holeShape = aItem->GetEffectiveHoleShape(); } if( holeShape ) diff --git a/pcbnew/drc/drc_test_provider_silk_clearance.cpp b/pcbnew/drc/drc_test_provider_silk_clearance.cpp index 6cc24f4f5d..4a29e20ee2 100644 --- a/pcbnew/drc/drc_test_provider_silk_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_silk_clearance.cpp @@ -184,7 +184,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run() BOARD_ITEM* testItem = aTestItemShape->parent; const SHAPE* testShape = aTestItemShape->shape; - std::unique_ptr hole; + std::shared_ptr hole; if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) ) return false; @@ -194,28 +194,13 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run() if( testItem->IsTented() ) { - switch( testItem->Type() ) + if( testItem->HasHole() ) { - case PCB_VIA_T: - { - PCB_VIA* via = static_cast( testItem ); - hole.reset( via->GetEffectiveShape( UNDEFINED_LAYER, - FLASHING::NEVER_FLASHED )->Clone() ); + hole = testItem->GetEffectiveHoleShape(); testShape = hole.get(); - break; } - case PCB_PAD_T: + else { - PAD* pad = static_cast( testItem ); - - if( pad->GetDrillSize().x || pad->GetDrillSize().y ) - return true; - - hole.reset( pad->GetEffectiveHoleShape()->Clone() ); - testShape = hole.get(); - break; - } - default: return true; } } diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index aefebe85c1..d45e8ed06e 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -2322,20 +2322,16 @@ void FOOTPRINT::CheckPads( const std::functionTransformShapeWithClearanceToPolygon( padOutline, layer, 0, ARC_HIGH_DEF, ERROR_LOC::ERROR_INSIDE ); - const SHAPE_SEGMENT* drillShape = pad->GetEffectiveHoleShape(); - const SEG drillSeg = drillShape->GetSeg(); - SHAPE_POLY_SET drillOutline; + std::shared_ptr hole = pad->GetEffectiveHoleShape(); + SHAPE_POLY_SET holeOutline; - TransformOvalToPolygon( drillOutline, drillSeg.A, drillSeg.B, - drillShape->GetWidth(), ARC_HIGH_DEF, - ERROR_LOC::ERROR_INSIDE ); + TransformOvalToPolygon( holeOutline, hole->GetSeg().A, hole->GetSeg().B, + hole->GetWidth(), ARC_HIGH_DEF, ERROR_LOC::ERROR_INSIDE ); - padOutline.BooleanSubtract( drillOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST ); + padOutline.BooleanSubtract( holeOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST ); if( padOutline.IsEmpty() ) - { (aErrorHandler)( pad, DRCE_PADSTACK, _( "(PTH pad's hole leaves no copper)" ) ); - } } } } diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index d5f675287b..305421178e 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -329,17 +329,9 @@ std::shared_ptr PAD::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFl || ( aLayer != UNDEFINED_LAYER && !FlashLayer( aLayer ) ) ) { if( GetAttribute() == PAD_ATTRIB::PTH ) - { - BOARD_DESIGN_SETTINGS& bds = GetBoard()->GetDesignSettings(); - - // Note: drill size represents finish size, which means the actual holes size is the - // plating thickness larger. - auto hole = static_cast( GetEffectiveHoleShape()->Clone() ); - hole->SetWidth( hole->GetWidth() + bds.GetHolePlatingThickness() ); - return std::make_shared( *hole ); - } - - return std::make_shared(); + return GetEffectiveHoleShape(); + else + return std::make_shared(); } if( m_shapesDirty ) @@ -349,12 +341,12 @@ std::shared_ptr PAD::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFl } -const SHAPE_SEGMENT* PAD::GetEffectiveHoleShape() const +std::shared_ptr PAD::GetEffectiveHoleShape() const { if( m_shapesDirty ) BuildEffectiveShapes( UNDEFINED_LAYER ); - return m_effectiveHoleShape.get(); + return m_effectiveHoleShape; } @@ -1537,10 +1529,10 @@ bool PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, in if( !drillsize.x || !drillsize.y ) return false; - const SHAPE_SEGMENT* seg = GetEffectiveHoleShape(); + std::shared_ptr slot = GetEffectiveHoleShape(); - TransformOvalToPolygon( aCornerBuffer, seg->GetSeg().A, seg->GetSeg().B, - seg->GetWidth() + aInflateValue * 2, aError, aErrorLoc ); + TransformOvalToPolygon( aCornerBuffer, slot->GetSeg().A, slot->GetSeg().B, + slot->GetWidth() + aInflateValue * 2, aError, aErrorLoc ); return true; } diff --git a/pcbnew/pad.h b/pcbnew/pad.h index 621376188a..b7f2ba1f9f 100644 --- a/pcbnew/pad.h +++ b/pcbnew/pad.h @@ -437,9 +437,9 @@ public: const std::shared_ptr& GetEffectivePolygon() const; /** - * Return a SHAPE object representing the pad's hole. + * Return a SHAPE_SEGMENT object representing the pad's hole. */ - const SHAPE_SEGMENT* GetEffectiveHoleShape() const; + std::shared_ptr GetEffectiveHoleShape() const override; /** * Return the radius of a minimum sized circle which fully encloses this pad. diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp index f8ef48014a..f53b8508a2 100644 --- a/pcbnew/pcb_expr_evaluator.cpp +++ b/pcbnew/pcb_expr_evaluator.cpp @@ -467,22 +467,17 @@ bool calcIsInsideArea( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox, PCB_EXPR_CO { if( aItem->Type() == PCB_PAD_T ) { - PAD* pad = static_cast( aItem ); - const SHAPE_SEGMENT* holeShape = pad->GetEffectiveHoleShape(); - - return areaOutline.Collide( holeShape ); + return areaOutline.Collide( aItem->GetEffectiveHoleShape().get() ); } else if( aItem->Type() == PCB_VIA_T ) { - PCB_VIA* via = static_cast( aItem ); - const SHAPE_CIRCLE holeShape( via->GetPosition(), via->GetDrillValue() ); - LSET overlap = via->GetLayerSet() & aArea->GetLayerSet(); + LSET overlap = aItem->GetLayerSet() & aArea->GetLayerSet(); /// Avoid buried vias that don't overlap the zone's layers - if( overlap.count() > 0 ) + if( overlap.any() ) { if( aCtx->GetLayer() == UNDEFINED_LAYER || overlap.Contains( aCtx->GetLayer() ) ) - return areaOutline.Collide( &holeShape ); + return areaOutline.Collide( aItem->GetEffectiveHoleShape().get() ); } } diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 9e71011d77..ad4c62a30f 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -1086,13 +1086,13 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer ) m_gal->SetLineWidth( m_holePlatingThickness ); m_gal->SetStrokeColor( color ); - const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape(); - int holeSize = seg->GetWidth() + m_holePlatingThickness; + std::shared_ptr slot = aPad->GetEffectiveHoleShape(); + int holeSize = slot->GetWidth() + m_holePlatingThickness; - if( seg->GetSeg().A == seg->GetSeg().B ) // Circular hole - m_gal->DrawCircle( seg->GetSeg().A, holeSize / 2 ); + if( slot->GetSeg().A == slot->GetSeg().B ) // Circular hole + m_gal->DrawCircle( slot->GetSeg().A, KiROUND( holeSize / 2.0 ) ); else - m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, holeSize ); + m_gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B, holeSize ); return; } @@ -1122,12 +1122,12 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer ) if( aLayer == LAYER_PAD_PLATEDHOLES || aLayer == LAYER_NON_PLATEDHOLES ) { - const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape(); + std::shared_ptr slot = aPad->GetEffectiveHoleShape(); - if( seg->GetSeg().A == seg->GetSeg().B ) // Circular hole - m_gal->DrawCircle( seg->GetSeg().A, getDrillSize( aPad ).x / 2 ); + if( slot->GetSeg().A == slot->GetSeg().B ) // Circular hole + m_gal->DrawCircle( slot->GetSeg().A, slot->GetWidth() / 2 ); else - m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() ); + m_gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B, slot->GetWidth() ); } else { @@ -1400,9 +1400,9 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer ) { clearance += m_holePlatingThickness; - const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape(); - m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, - seg->GetWidth() + 2 * clearance ); + std::shared_ptr slot = aPad->GetEffectiveHoleShape(); + m_gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B, + slot->GetWidth() + 2 * clearance ); } } } diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp index 80178402bf..760313cfda 100644 --- a/pcbnew/pcb_track.cpp +++ b/pcbnew/pcb_track.cpp @@ -366,6 +366,12 @@ SEARCH_RESULT PCB_TRACK::Visit( INSPECTOR inspector, void* testData, const KICAD } +std::shared_ptr PCB_VIA::GetEffectiveHoleShape() const +{ + return std::make_shared( SEG( m_Start, m_Start ), KiROUND( m_drill / 2.0 ) ); +} + + bool PCB_VIA::IsTented() const { const BOARD* board = GetBoard(); diff --git a/pcbnew/pcb_track.h b/pcbnew/pcb_track.h index 7d176adfec..4957ab74cd 100644 --- a/pcbnew/pcb_track.h +++ b/pcbnew/pcb_track.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,6 +38,7 @@ #include #include +#include class PCB_TRACK; @@ -358,6 +359,8 @@ public: return true; } + std::shared_ptr GetEffectiveHoleShape() const override; + bool IsTented() const override; int GetSolderMaskExpansion() const; diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 4904be1d57..db4e8aaa8e 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -702,23 +702,22 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask, { for( PAD* pad : footprint->Pads() ) { - VECTOR2I hole = pad->GetDrillSize(); - - if( hole.x == 0 || hole.y == 0 ) - continue; - - if( hole.x == hole.y ) + if( pad->HasHole() ) { - hole.x = std::min( smallDrill, hole.x ); - aPlotter->Circle( pad->GetPosition(), hole.x, FILL_T::NO_FILL ); - } - else - { - // Note: small drill marks have no significance when applied to slots - const SHAPE_SEGMENT* seg = pad->GetEffectiveHoleShape(); - aPlotter->ThickSegment( seg->GetSeg().A, - seg->GetSeg().B, - seg->GetWidth(), SKETCH, nullptr ); + std::shared_ptr slot = pad->GetEffectiveHoleShape(); + + if( slot->GetSeg().A == slot->GetSeg().B ) // circular hole + { + int drill = std::min( smallDrill, slot->GetWidth() ); + aPlotter->Circle( pad->GetPosition(), drill, FILL_T::NO_FILL ); + } + else + { + // Note: small drill marks have no significance when applied to slots + aPlotter->ThickSegment( slot->GetSeg().A, + slot->GetSeg().B, + slot->GetWidth(), SKETCH, nullptr ); + } } } } diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index c8d0e36fe1..8fff1c142e 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -1297,7 +1297,7 @@ void PNS_KICAD_IFACE_BASE::SyncWorld( PNS::NODE *aWorld ) if( pad->GetProperty() == PAD_PROP::CASTELLATED ) { std::unique_ptr hole; - hole.reset( new SHAPE_SEGMENT( *pad->GetEffectiveHoleShape() ) ); + hole.reset( pad->GetEffectiveHoleShape()->Clone() ); aWorld->AddEdgeExclusion( std::move( hole ) ); } } diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 9b4fc06584..e2fe108b87 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -2816,24 +2816,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) } } - std::unique_ptr holeShape; - - if( aOther->Type() == PCB_VIA_T ) - { - PCB_VIA* via = static_cast( aOther ); - VECTOR2I pos = via->GetPosition(); - - holeShape.reset( new SHAPE_SEGMENT( pos, pos, via->GetDrill() ) ); - } - else if( aOther->Type() == PCB_PAD_T ) - { - PAD* pad = static_cast( aOther ); - - if( pad->GetDrillSize().x ) - holeShape.reset( new SHAPE_SEGMENT( *pad->GetEffectiveHoleShape() ) ); - } - - if( holeShape ) + if( aOther->HasHole() ) { constraint = m_drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, aVia, aOther, UNDEFINED_LAYER ); @@ -2843,8 +2826,11 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) { std::shared_ptr viaShape = aVia->GetEffectiveShape( UNDEFINED_LAYER ); - if( viaShape->Collide( holeShape.get(), clearance - m_drcEpsilon ) ) + if( viaShape->Collide( aOther->GetEffectiveHoleShape().get(), + clearance - m_drcEpsilon ) ) + { return true; + } } } diff --git a/pcbnew/tools/edit_tool_move_fct.cpp b/pcbnew/tools/edit_tool_move_fct.cpp index f83eea0eec..e576471a35 100644 --- a/pcbnew/tools/edit_tool_move_fct.cpp +++ b/pcbnew/tools/edit_tool_move_fct.cpp @@ -187,22 +187,16 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances() auto testPadAgainstCourtyards = [&]( const PAD* pad, FOOTPRINT* footprint ) -> bool { - // Skip pads with no hole - if( pad->GetAttribute() != PAD_ATTRIB::PTH - && pad->GetAttribute() != PAD_ATTRIB::NPTH ) - return false; - - const SHAPE_SEGMENT* hole = pad->GetEffectiveHoleShape(); - const SHAPE_POLY_SET& front = footprint->GetPolyCourtyard( F_CrtYd ); - const SHAPE_POLY_SET& back = footprint->GetPolyCourtyard( B_CrtYd ); - - if( front.OutlineCount() > 0 && front.Collide( hole, 0 ) ) + if( pad->HasHole() ) { - return true; - } - else if( back.OutlineCount() > 0 && back.Collide( hole, 0 ) ) - { - return true; + std::shared_ptr hole = pad->GetEffectiveHoleShape(); + const SHAPE_POLY_SET& front = footprint->GetPolyCourtyard( F_CrtYd ); + const SHAPE_POLY_SET& back = footprint->GetPolyCourtyard( B_CrtYd ); + + if( front.OutlineCount() > 0 && front.Collide( hole.get(), 0 ) ) + return true; + else if( back.OutlineCount() > 0 && back.Collide( hole.get(), 0 ) ) + return true; } return false; diff --git a/pcbnew/tools/pcb_control.cpp b/pcbnew/tools/pcb_control.cpp index 4888e4e802..8ca43c2fe2 100644 --- a/pcbnew/tools/pcb_control.cpp +++ b/pcbnew/tools/pcb_control.cpp @@ -1208,35 +1208,28 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent ) return 0; } + if( fpFrame && !fpFrame->GetModel() ) + return 0; + if( selection.Empty() ) { if( fpFrame ) { - FOOTPRINT* footprint = static_cast( fpFrame->GetModel() ); + FOOTPRINT* fp = static_cast( fpFrame->GetModel() ); + size_t padCount = fp->GetPadCount( DO_NOT_INCLUDE_NPTH ); - if( !footprint ) - return 0; + msgItems.emplace_back( _( "Library" ), fp->GetFPID().GetLibNickname().wx_str() ); - wxString msg; + msgItems.emplace_back( _( "Footprint Name" ), fp->GetFPID().GetLibItemName().wx_str() ); - msg = footprint->GetFPID().GetLibNickname().wx_str(); - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Library" ), msg ) ); + msgItems.emplace_back( _( "Pads" ), wxString::Format( wxT( "%zu" ), padCount ) ); - msg = footprint->GetFPID().GetLibItemName().wx_str(); - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Footprint Name" ), msg ) ); - - msg.Printf( wxT( "%zu" ), (size_t) footprint->GetPadCount( DO_NOT_INCLUDE_NPTH ) ); - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Pads" ), msg ) ); - - wxString doc, keyword; - doc.Printf( _( "Doc: %s" ), footprint->GetDescription() ); - keyword.Printf( _( "Keywords: %s" ), footprint->GetKeywords() ); - msgItems.emplace_back( MSG_PANEL_ITEM( doc, keyword ) ); + msgItems.emplace_back( wxString::Format( _( "Doc: %s" ), fp->GetDescription() ), + wxString::Format( _( "Keywords: %s" ), fp->GetKeywords() ) ); } else { m_frame->SetMsgPanel( m_frame->GetBoard() ); - return 0; } } else if( selection.GetSize() == 1 ) @@ -1245,15 +1238,10 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent ) item->GetMsgPanelInfo( m_frame, msgItems ); } - - // Pair selection broken into multiple, optional data, starting with the selection item names - if( pcbFrame && selection.GetSize() == 2 ) + else if( pcbFrame && selection.GetSize() == 2 ) { - auto clearanceString = - [&]( const DRC_CONSTRAINT& curr_constraint ) - { - return StringFromValue( units, curr_constraint.m_Value.Min(), true ); - }; + // Pair selection broken into multiple, optional data, starting with the selected item + // names BOARD_ITEM* a = static_cast( selection[0] ); BOARD_ITEM* b = static_cast( selection[1] ); @@ -1281,14 +1269,13 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent ) int actual_clearance = a_shape->GetClearance( b_shape.get() ); - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved clearance" ), - clearanceString( constraint ) ) ); + msgItems.emplace_back( _( "Resolved clearance" ), + MessageTextFromValue( units, constraint.m_Value.Min() ) ); if( actual_clearance > -1 && actual_clearance < std::numeric_limits::max() ) { - msgItems.emplace_back( - MSG_PANEL_ITEM( _( "Actual clearance" ), - StringFromValue( units, actual_clearance, true ) ) ); + msgItems.emplace_back( _( "Actual clearance" ), + MessageTextFromValue( units, actual_clearance ) ); } } } @@ -1309,9 +1296,33 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent ) if( layer >= 0 ) { + int actual = std::numeric_limits::max(); + + if( a->HasHole() ) + { + std::shared_ptr hole = a->GetEffectiveHoleShape(); + std::shared_ptr other( b->GetEffectiveShape( layer ) ); + + actual = std::min( actual, hole->GetClearance( other.get() ) ); + } + + if( b->HasHole() ) + { + std::shared_ptr hole = b->GetEffectiveHoleShape(); + std::shared_ptr other( a->GetEffectiveShape( layer ) ); + + actual = std::min( actual, hole->GetClearance( other.get() ) ); + } + constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer ); - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved hole clearance" ), - clearanceString( constraint ) ) ); + msgItems.emplace_back( _( "Resolved hole clearance" ), + MessageTextFromValue( units, constraint.m_Value.Min() ) ); + + if( actual > -1 && actual < std::numeric_limits::max() ) + { + msgItems.emplace_back( _( "Actual hole clearance" ), + MessageTextFromValue( units, actual ) ); + } } } @@ -1341,13 +1352,13 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent ) if( edgeLayer == Edge_Cuts ) { - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved edge clearance" ), - clearanceString( constraint ) ) ); + msgItems.emplace_back( _( "Resolved edge clearance" ), + MessageTextFromValue( units, constraint.m_Value.Min() ) ); } else { - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved margin clearance" ), - clearanceString( constraint ) ) ); + msgItems.emplace_back( _( "Resolved margin clearance" ), + MessageTextFromValue( units, constraint.m_Value.Min() ) ); } } } @@ -1355,8 +1366,8 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent ) if( msgItems.empty() ) { - wxString msg = wxString::Format( wxT( "%d" ), selection.GetSize() ); - msgItems.emplace_back( MSG_PANEL_ITEM( _( "Selected Items" ), msg ) ); + msgItems.emplace_back( _( "Selected Items" ), + wxString::Format( wxT( "%d" ), selection.GetSize() ) ); } m_frame->SetMsgPanel( msgItems ); diff --git a/pcbnew/zone.cpp b/pcbnew/zone.cpp index d4b85030db..939bbc8d3c 100644 --- a/pcbnew/zone.cpp +++ b/pcbnew/zone.cpp @@ -522,7 +522,7 @@ void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& AccumulateDescription( msg, _( "No footprints" ) ); if( !msg.IsEmpty() ) - aList.emplace_back( MSG_PANEL_ITEM( _( "Restrictions" ), msg ) ); + aList.emplace_back( _( "Restrictions" ), msg ); } else if( IsOnCopperLayer() ) { @@ -586,23 +586,14 @@ void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& source ) ); } - // Useful for statistics, especially when zones are complex the number of hatches - // and filled polygons can explain the display and DRC calculation time: - msg.Printf( wxT( "%d" ), (int) m_borderHatchLines.size() ); - aList.emplace_back( MSG_PANEL_ITEM( _( "HatchBorder Lines" ), msg ) ); - if( !m_FilledPolysList.empty() ) { count = 0; - for( auto item: m_FilledPolysList ) - { - const std::shared_ptr& polyset = item.second; - count += polyset->TotalVertices(); - } + for( std::pair>& ii: m_FilledPolysList ) + count += ii.second->TotalVertices(); - msg.Printf( wxT( "%d" ), count ); - aList.emplace_back( MSG_PANEL_ITEM( _( "Corner Count" ), msg ) ); + aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) ); } }