diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 0a0b80345c..92b6fa3d03 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -2084,6 +2085,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) std::shared_ptr m_drcEngine; int m_drcEpsilon; int m_worstClearance; + bool m_allowDRCViolations; bool m_flaggedDRC; VIA_PLACER( PCB_BASE_EDIT_FRAME* aFrame ) : @@ -2094,6 +2096,11 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) m_worstClearance( 0 ), m_flaggedDRC( false ) { + ROUTER_TOOL* router = m_frame->GetToolManager()->GetTool(); + PNS::ROUTING_SETTINGS& cfg = router->Router()->Settings(); + + m_allowDRCViolations = cfg.Mode() == PNS::RM_MarkObstacles && cfg.CanViolateDRC(); + try { m_drcEngine->InitEngine( aFrame->GetDesignRulesPath() ); @@ -2178,11 +2185,16 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) if( cItem && cItem->GetNetCode() == aVia->GetNetCode() ) return false; + DRC_CONSTRAINT constraint; + int clearance; + for( PCB_LAYER_ID layer : aOther->GetLayerSet().Seq() ) { - DRC_CONSTRAINT constraint = m_drcEngine->EvalRules( CLEARANCE_CONSTRAINT, aVia, - aOther, layer ); - int clearance = constraint.GetValue().Min(); + if( !IsCopperLayer( layer ) ) + continue; + + constraint = m_drcEngine->EvalRules( CLEARANCE_CONSTRAINT, aVia, aOther, layer ); + clearance = constraint.GetValue().Min(); if( clearance >= 0 ) { @@ -2194,13 +2206,45 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) } } + std::unique_ptr holeShape; + + if( aOther->Type() == PCB_VIA_T ) + { + VIA* via = static_cast( aOther ); + wxPoint 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 ) + { + constraint = m_drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, aVia, aOther, + UNDEFINED_LAYER ); + clearance = constraint.GetValue().Min(); + + if( clearance >= 0 ) + { + std::shared_ptr viaShape = DRC_ENGINE::GetShape( aVia, UNDEFINED_LAYER ); + + if( viaShape->Collide( holeShape.get(), clearance - m_drcEpsilon ) ) + return true; + } + } + return false; } bool hasDRCViolation( VIA* aVia ) { std::vector items; - std::set handled; + std::set checkedItems; BOX2I bbox = aVia->GetBoundingBox(); bbox.Inflate( m_worstClearance ); @@ -2210,16 +2254,22 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) { BOARD_ITEM* item = dynamic_cast( it.first ); - if( !item || item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T ) + if( !item ) continue; - if( handled.count( item ) ) + if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T ) + continue; + + if( item->Type() == PCB_FP_TEXT_T && !static_cast( item )->IsVisible() ) + continue; + + if( checkedItems.count( item ) ) continue; if( hasDRCViolation( aVia, item ) ) return true; - handled.insert( item ); + checkedItems.insert( item ); } return false; @@ -2293,7 +2343,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) int newNet; TRACK* track = findTrack( via ); - if( hasDRCViolation( via ) ) + if( !m_allowDRCViolations && hasDRCViolation( via ) ) { m_frame->ShowInfoBarError( _( "Via location violates DRC." ) ); m_flaggedDRC = true;