Force overlapping wires to share labels

Crossing wires with pathological label in the center are actually
connected for the netlist.  This is an ERC error but we should keep
things consistent.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21494
This commit is contained in:
Seth Hillbrand
2025-08-19 13:19:00 -07:00
parent 811745ff96
commit c995d47c87
3 changed files with 82 additions and 0 deletions
+25
View File
@@ -1325,6 +1325,31 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
else
{
updateGenericItemConnectivity( aSheet, item, connection_map );
/// Special case for labels that overlap wires
/// While this is an ERC error as there is not an explicit junction,
/// we want to enforce connectivity for all items under the label position.
if( dynamic_cast<SCH_LABEL_BASE*>( item ) )
{
VECTOR2I point = item->GetPosition();
SCH_SCREEN* screen = aSheet.LastScreen();
auto items = screen->Items().Overlapping( point );
std::vector<SCH_ITEM*> overlapping_items;
std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
[&]( SCH_ITEM* test_item )
{
return test_item->Type() == SCH_LINE_T
&& test_item->HitTest( point, -1 );
} );
// We need at least two connnectable lines that are not the label here
// Otherwise, the label will be normally assigned to one or the other
if( overlapping_items.size() < 2 ) continue;
for( SCH_ITEM* test_item : overlapping_items )
connection_map[point].push_back( test_item );
}
}
}
+1
View File
@@ -68,6 +68,7 @@ set( QA_EESCHEMA_SRCS
test_annotation_units_conflicts.cpp
test_annotation_units_integration.cpp
test_connectivity_algo.cpp
test_crossing_label.cpp
test_eagle_plugin.cpp
test_junction_helpers.cpp
test_bus_entry_concurrency.cpp
+56
View File
@@ -0,0 +1,56 @@
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <connection_graph.h>
#include <sch_line.h>
#include <sch_label.h>
#include <sch_sheet.h>
#include <sch_sheet_path.h>
#include <sch_screen.h>
#include <schematic.h>
#include <settings/settings_manager.h>
#include <project.h>
BOOST_AUTO_TEST_CASE( LabelDrivesCrossingWires )
{
SETTINGS_MANAGER manager;
manager.LoadProject( "" );
SCHEMATIC schematic( &manager.Prj() );
SCH_SCREEN* screen = new SCH_SCREEN( nullptr );
SCH_SHEET* sheet = new SCH_SHEET( nullptr, VECTOR2I( 0, 0 ), VECTOR2I( 1000, 1000 ) );
sheet->SetScreen( screen );
schematic.SetRoot( sheet );
CONNECTION_GRAPH graph;
graph.SetSchematic( &schematic );
SCH_SHEET_PATH sheetPath;
sheetPath.push_back( sheet );
SCH_LINE* h = new SCH_LINE( VECTOR2I( -1000, 0 ), LAYER_WIRE );
h->SetEndPoint( VECTOR2I( 1000, 0 ) );
SCH_LINE* v = new SCH_LINE( VECTOR2I( 0, -1000 ), LAYER_WIRE );
v->SetEndPoint( VECTOR2I( 0, 1000 ) );
SCH_LABEL* label = new SCH_LABEL( VECTOR2I( 0, 0 ), wxS( "N" ) );
screen->Append( h, false );
screen->Append( v, false );
screen->Append( label, false );
std::vector<SCH_ITEM*> items = { h, v, label };
label->GetOrInitConnection( sheetPath, &graph )->ConfigureFromLabel(wxS("N"));
SCH_SHEET_LIST sheets = schematic.BuildSheetListSortedByPageNumbers();
graph.Recalculate( sheets, true );
CONNECTION_SUBGRAPH* sg1 = graph.GetSubgraphForItem( h );
CONNECTION_SUBGRAPH* sg2 = graph.GetSubgraphForItem( v );
BOOST_REQUIRE( sg1 );
BOOST_REQUIRE( sg2 );
BOOST_CHECK( sg1 == sg2 );
BOOST_CHECK( sg1->GetDriver() == label );
BOOST_CHECK( sg2->GetDriver() == label );
}