From 2c280e83c346abc71ab4c5ecc511bb5d84652a72 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 15 Jun 2022 16:27:54 +0100 Subject: [PATCH] Handle junctions in MarkConnections. Fixes https://gitlab.com/kicad/code/kicad/issues/8579 --- eeschema/sch_screen.cpp | 59 ++++++++++++++++++++++++++++------------- eeschema/sch_screen.h | 4 +-- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp index 6f12d7c973..04048f0729 100644 --- a/eeschema/sch_screen.cpp +++ b/eeschema/sch_screen.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2008 Wayne Stambaugh - * 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 @@ -355,8 +355,10 @@ SCH_ITEM* SCH_SCREEN::GetItem( const VECTOR2I& aPosition, int aAccuracy, KICAD_T } -std::set SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aIgnorePins ) +std::set SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aSecondPass ) { +#define PROCESSED CANDIDATE // Don't use SKIP_STRUCT; IsConnected() returns false if it's set. + std::set retval; std::stack to_search; @@ -366,36 +368,55 @@ std::set SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aIgnor while( !to_search.empty() ) { - SCH_LINE* test_item = to_search.top(); + SCH_ITEM* item = to_search.top(); to_search.pop(); - for( SCH_ITEM* item : Items().Overlapping( SCH_JUNCTION_T, test_item->GetBoundingBox() ) ) - { - if( test_item->IsEndPoint( item->GetPosition() ) ) - retval.insert( item ); - } + if( item->HasFlag( PROCESSED ) ) + continue; - for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, test_item->GetBoundingBox() ) ) + item->SetFlags( PROCESSED ); + + for( SCH_ITEM* candidate : Items().Overlapping( SCH_LINE_T, item->GetBoundingBox() ) ) { - // Skip connecting lines on different layers (e.g. buses) - if( test_item->GetLayer() != item->GetLayer() ) + SCH_LINE* line = static_cast( candidate ); + + if( line->HasFlag( PROCESSED ) ) continue; - SCH_LINE* line = static_cast( item ); + // Skip connecting lines on different layers (e.g. buses) + if( item->GetLayer() != line->GetLayer() ) + break; - if( ( test_item->IsEndPoint( line->GetStartPoint() ) - && ( aIgnorePins || !GetPin( line->GetStartPoint(), nullptr, true ) ) ) - || ( test_item->IsEndPoint( line->GetEndPoint() ) - && ( aIgnorePins || !GetPin( line->GetEndPoint(), nullptr, true ) ) ) ) + for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } ) { - auto result = retval.insert( line ); + if( item->IsConnected( pt ) ) + { + SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T ); + SCH_ITEM* pin = GetItem( pt, 0, SCH_PIN_T ); - if( result.second ) - to_search.push( line ); + if( item->IsSelected() && aSecondPass ) + { + if( junction ) + retval.insert( junction ); + + retval.insert( line ); + to_search.push( line ); + } + else if( !junction && !pin ) + { + retval.insert( line ); + to_search.push( line ); + } + + break; + } } } } + for( SCH_ITEM* item : Items() ) + item->ClearTempFlags(); + return retval; } diff --git a/eeschema/sch_screen.h b/eeschema/sch_screen.h index 4703597fba..139d30466e 100644 --- a/eeschema/sch_screen.h +++ b/eeschema/sch_screen.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2009 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 @@ -298,7 +298,7 @@ public: * * @param aSegment The segment to test for connections. */ - std::set MarkConnections( SCH_LINE* aSegment, bool aIgnorePins ); + std::set MarkConnections( SCH_LINE* aSegment, bool aSecondPass ); /** * Clear the state flags of all the items in the screen.