From 2faaa0a042c69d54432356d55507b350c02002b6 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 8 Sep 2022 13:09:05 +0100 Subject: [PATCH] Improve drop-a-knee-selection-to-a-single-segment algorithm. In particular, don't rely on there being only two items in the collector at the start. Fixes https://gitlab.com/kicad/code/kicad/issues/10745 (cherry picked from commit a619ef9d532b361cadace31f77955e388b777db4) --- pcbnew/tools/edit_tool.cpp | 46 +++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index c19e0fb6fc..ef9e5000dd 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -290,20 +290,46 @@ int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent ) sTool->FilterCollectorForFreePads( aCollector ); sTool->FilterCollectorForHierarchy( aCollector, true ); - // drop a knee between two segments to a single segment - if( aCollector.GetCount() == 2 && dynamic_cast( aCollector[0] ) ) + // drop a knee between two segments to a single segment, or a via with two + // segments attached to the via + static KICAD_T trackTypes[] = { PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T, EOT }; + std::vector tracks; + std::vector vias; + + for( EDA_ITEM* item : aCollector ) { - static KICAD_T types[] = { PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T, EOT }; + if( item->IsType( trackTypes ) ) + tracks.push_back( static_cast( item ) ); + else if( item->Type() == PCB_VIA_T ) + vias.push_back( static_cast( item ) ); + } - PCB_TRACK* a = static_cast( aCollector[0] ); - PCB_TRACK* b = static_cast( aCollector[1] ); - const auto& c = aCollector[0]->GetBoard()->GetConnectivity(); + if( tracks.size() == 2 ) + { + const BOARD* board = tracks[0]->GetBoard(); + std::shared_ptr c = board->GetConnectivity(); + std::vector cItems; - int dist = a->GetWidth() / 2; - auto connectedItems = c->GetConnectedItemsAtAnchor( a, aPt, types, dist ); + if( vias.size() == 1 ) + { + cItems = c->GetConnectedItemsAtAnchor( vias[0], aPt, trackTypes, + vias[0]->GetWidth() / 2 ); - if( alg::contains( connectedItems, b ) ) - aCollector.Remove( b ); + if( alg::contains( cItems, tracks[0] ) + && alg::contains( cItems, tracks[1] ) ) + { + aCollector.Remove( tracks[0] ); + aCollector.Remove( tracks[1] ); + } + } + else if( vias.size() == 0 ) + { + cItems = c->GetConnectedItemsAtAnchor( tracks[0], aPt, trackTypes, + tracks[0]->GetWidth() / 2 ); + + if( alg::contains( cItems, tracks[1] ) ) + aCollector.Remove( tracks[1] ); + } } }, true /* prompt user regarding locked items */ );