From ff3bd7e72a0274f1513a4fa10ffc2156505c7995 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 20 Nov 2020 21:22:27 +0000 Subject: [PATCH] Fix a crash bug in DRC, and equate Margin to Edge.Cuts. --- pcbnew/drc/drc_rule_condition.cpp | 2 +- .../drc/drc_test_provider_edge_clearance.cpp | 2 +- .../drc/drc_test_provider_silk_clearance.cpp | 12 ++++-- pcbnew/router/pns_kicad_iface.cpp | 42 ++++++++++--------- pcbnew/tools/pcb_inspection_tool.cpp | 7 ++-- pcbnew/zone_filler.cpp | 32 ++++++++------ 6 files changed, 58 insertions(+), 39 deletions(-) diff --git a/pcbnew/drc/drc_rule_condition.cpp b/pcbnew/drc/drc_rule_condition.cpp index 56cbb42a35..6218953df2 100644 --- a/pcbnew/drc/drc_rule_condition.cpp +++ b/pcbnew/drc/drc_rule_condition.cpp @@ -63,7 +63,7 @@ bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM } ); BOARD_ITEM* a = const_cast( aItemA ); - BOARD_ITEM* b = aItemB ? const_cast( aItemB ) : DELETED_BOARD_ITEM::GetInstance(); + BOARD_ITEM* b = const_cast( aItemB ); ctx.SetItems( a, b ); diff --git a/pcbnew/drc/drc_test_provider_edge_clearance.cpp b/pcbnew/drc/drc_test_provider_edge_clearance.cpp index 7b17da1908..86531404f1 100644 --- a/pcbnew/drc/drc_test_provider_edge_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_edge_clearance.cpp @@ -188,7 +188,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() return true; }; - forEachGeometryItem( { PCB_SHAPE_T }, LSET( Edge_Cuts ), queryBoardOutlineItems ); + forEachGeometryItem( { PCB_SHAPE_T }, LSET( 2, Edge_Cuts, Margin ), queryBoardOutlineItems ); forEachGeometryItem( s_allBasicItemsButZones, LSET::AllCuMask(), queryBoardGeometryItems ); for( const std::unique_ptr& edge : edges ) diff --git a/pcbnew/drc/drc_test_provider_silk_clearance.cpp b/pcbnew/drc/drc_test_provider_silk_clearance.cpp index b42068c11f..b70bd57ad2 100644 --- a/pcbnew/drc/drc_test_provider_silk_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_silk_clearance.cpp @@ -199,11 +199,15 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run() }; forEachGeometryItem( s_allBasicItems, LSET( 2, F_SilkS, B_SilkS ), addToSilkTree ); - forEachGeometryItem( s_allBasicItems, LSET::FrontMask() | LSET::BackMask(), countTargets ); + forEachGeometryItem( s_allBasicItems, + LSET::FrontMask() | LSET::BackMask() | LSET( 2, Edge_Cuts, Margin ), + countTargets ); targets *= 2; // One for adding to RTree; one for testing - forEachGeometryItem( s_allBasicItems, LSET::FrontMask() | LSET::BackMask(), addToTargetTree ); + forEachGeometryItem( s_allBasicItems, + LSET::FrontMask() | LSET::BackMask() | LSET( 2, Edge_Cuts, Margin ), + addToTargetTree ); reportAux( _("Testing %d silkscreen features against %d board items."), silkTree.size(), @@ -219,6 +223,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run() DRC_RTREE::LAYER_PAIR( F_SilkS, F_Fab ), DRC_RTREE::LAYER_PAIR( F_SilkS, F_Cu ), DRC_RTREE::LAYER_PAIR( F_SilkS, Edge_Cuts ), + DRC_RTREE::LAYER_PAIR( F_SilkS, Margin ), DRC_RTREE::LAYER_PAIR( B_SilkS, B_SilkS ), DRC_RTREE::LAYER_PAIR( B_SilkS, B_Mask ), DRC_RTREE::LAYER_PAIR( B_SilkS, B_Adhes ), @@ -226,7 +231,8 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run() DRC_RTREE::LAYER_PAIR( B_SilkS, B_CrtYd ), DRC_RTREE::LAYER_PAIR( B_SilkS, B_Fab ), DRC_RTREE::LAYER_PAIR( B_SilkS, B_Cu ), - DRC_RTREE::LAYER_PAIR( B_SilkS, Edge_Cuts ) + DRC_RTREE::LAYER_PAIR( B_SilkS, Edge_Cuts ), + DRC_RTREE::LAYER_PAIR( B_SilkS, Margin ) }; targetTree.QueryCollidingPairs( &silkTree, layerPairs, checkClearance, m_largestClearance, diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 97a87b400c..4fa0f159b0 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -1039,31 +1039,35 @@ bool PNS_KICAD_IFACE_BASE::syncTextItem( PNS::NODE* aWorld, EDA_TEXT* aText, PCB bool PNS_KICAD_IFACE_BASE::syncGraphicalItem( PNS::NODE* aWorld, PCB_SHAPE* aItem ) { - if( aItem->GetLayer() != Edge_Cuts && !IsCopperLayer( aItem->GetLayer() ) ) - return false; - - // TODO: where do we handle filled polygons on copper layers? - if( aItem->GetShape() == S_POLYGON && aItem->IsFilled() ) - return false; - - for( SHAPE* shape : aItem->MakeEffectiveShapes() ) + if( aItem->GetLayer() == Edge_Cuts + || aItem->GetLayer() == Margin + || IsCopperLayer( aItem->GetLayer() ) ) { - std::unique_ptr solid = std::make_unique(); + // TODO: where do we handle filled polygons on copper layers? + if( aItem->GetShape() == S_POLYGON && aItem->IsFilled() ) + return false; - if( aItem->GetLayer() == Edge_Cuts ) - solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) ); - else - solid->SetLayer( aItem->GetLayer() ); + for( SHAPE* shape : aItem->MakeEffectiveShapes() ) + { + std::unique_ptr solid = std::make_unique(); - solid->SetNet( -1 ); - solid->SetParent( aItem ); - solid->SetShape( shape ); - solid->SetRoutable( false ); + if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin ) + solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) ); + else + solid->SetLayer( aItem->GetLayer() ); - aWorld->Add( std::move( solid ) ); + solid->SetNet( -1 ); + solid->SetParent( aItem ); + solid->SetShape( shape ); + solid->SetRoutable( false ); + + aWorld->Add( std::move( solid ) ); + } + + return true; } - return true; + return false; } diff --git a/pcbnew/tools/pcb_inspection_tool.cpp b/pcbnew/tools/pcb_inspection_tool.cpp index a9c6841c9c..945cd495d0 100644 --- a/pcbnew/tools/pcb_inspection_tool.cpp +++ b/pcbnew/tools/pcb_inspection_tool.cpp @@ -216,7 +216,8 @@ void PCB_INSPECTION_TOOL::reportClearance( DRC_CONSTRAINT_TYPE_T aClearanceType, if( aClearanceType == CLEARANCE_CONSTRAINT ) { - if( ( aA && aA->GetLayer() == Edge_Cuts ) || ( aB && aB->GetLayer() == Edge_Cuts ) ) + if( ( aA && ( aA->GetLayerSet() & LSET( 2, Edge_Cuts, Margin ) ).any() ) + || ( aB && ( aB->GetLayerSet() & LSET( 2, Edge_Cuts, Margin ) ).any() ) ) { auto edgeConstraint = drcEngine.EvalRulesForItems( EDGE_CLEARANCE_CONSTRAINT, aA, aB, aLayer, r ); @@ -321,13 +322,13 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) reportClearance( SILK_CLEARANCE_CONSTRAINT, layer, a, b, r ); } - else if( !( a->GetLayerSet() & LSET( 2, layer, Edge_Cuts ) ).any() ) + else if( !( a->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() ) { r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ), a->GetSelectMenuText( r->GetUnits() ), m_frame->GetBoard()->GetLayerName( layer ) ) ); } - else if( !( b->GetLayerSet() & LSET( 2, layer, Edge_Cuts ) ).any() ) + else if( !( b->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() ) { r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ), b->GetSelectMenuText( r->GetUnits() ), diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 8a1dbea2fc..0efd0dbbf4 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -796,21 +796,29 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa auto knockoutGraphicClearance = [&]( BOARD_ITEM* aItem ) { - // A item on the Edge_Cuts is always seen as on any layer: - if( !aItem->IsOnLayer( aLayer ) && !aItem->IsOnLayer( Edge_Cuts ) ) - return; - - if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) ) + // A item on the Edge_Cuts or Margin is always seen as on any layer: + if( aItem->IsOnLayer( aLayer ) + || aItem->IsOnLayer( Edge_Cuts ) + || aItem->IsOnLayer( Margin ) ) { - int gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aItem, aLayer ); - - if( aItem->IsOnLayer( Edge_Cuts ) ) + if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) ) { - gap = std::max( gap, evalRulesForItems( EDGE_CLEARANCE_CONSTRAINT, aZone, - aItem, Edge_Cuts ) ); - } + int gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aItem, aLayer ); - addKnockout( aItem, aLayer, gap, aItem->IsOnLayer( Edge_Cuts ), aHoles ); + if( aItem->IsOnLayer( Edge_Cuts ) ) + { + gap = std::max( gap, evalRulesForItems( EDGE_CLEARANCE_CONSTRAINT, + aZone, aItem, Edge_Cuts ) ); + } + + if( aItem->IsOnLayer( Margin ) ) + { + gap = std::max( gap, evalRulesForItems( EDGE_CLEARANCE_CONSTRAINT, + aZone, aItem, Margin ) ); + } + + addKnockout( aItem, aLayer, gap, aItem->IsOnLayer( Edge_Cuts ), aHoles ); + } } };