Consider a bus entry hitting a wire corner or tee to be dot-worthy

This doesn't change the connectivity, it just makes putting the
dot more closely match what the connectivity already does.

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/18046
This commit is contained in:
John Beard 2024-05-17 21:04:59 +08:00
parent 6313b58ad6
commit 6992afeb38
4 changed files with 62 additions and 6 deletions

View File

@ -13,10 +13,11 @@ POINT_INFO JUNCTION_HELPERS::AnalyzePoint( const EE_RTREE& aItems, const VECTOR2
BUSES
};
POINT_INFO info {};
POINT_INFO info{};
info.hasBusEntry = false;
info.hasExplicitJunctionDot = false;
info.isJunction = false;
info.hasBusEntryToMultipleWires = false;
bool breakLines[2] = { false };
std::unordered_set<int> exitAngles[2];
@ -106,6 +107,17 @@ POINT_INFO JUNCTION_HELPERS::AnalyzePoint( const EE_RTREE& aItems, const VECTOR2
}
}
if( info.hasBusEntry )
{
// The bus entry and one wire is 2 wires, and the one entry is exactly one bus
// Any more wires must be multiple wires, but any more buses means a wire
// crossing at the bus entry root.
info.hasBusEntryToMultipleWires =
exitAngles[WIRES].size() > 2 && exitAngles[BUSES].size() == 1;
}
// Any three things of the same type is a junction of some sort
info.isJunction = exitAngles[WIRES].size() >= 3 || exitAngles[BUSES].size() >= 3;
return info;
}

View File

@ -10,9 +10,14 @@ namespace JUNCTION_HELPERS
*/
struct POINT_INFO
{
///< True if the point has 3+ wires and/or 3+ buses meeting there
bool isJunction;
///< True if there is already junction dot at the point
bool hasExplicitJunctionDot;
///< True if there is a bus entry at the point (either end)
bool hasBusEntry;
///< True if there is a bus entry at the point and it connects to more than one wire
bool hasBusEntryToMultipleWires;
};
/**

View File

@ -488,7 +488,7 @@ bool SCH_SCREEN::IsExplicitJunction( const VECTOR2I& aPosition ) const
const JUNCTION_HELPERS::POINT_INFO info =
JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
return info.isJunction && !info.hasBusEntry;
return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires );
}
@ -497,7 +497,8 @@ bool SCH_SCREEN::IsExplicitJunctionNeeded( const VECTOR2I& aPosition ) const
const JUNCTION_HELPERS::POINT_INFO info =
JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
return info.isJunction && !info.hasBusEntry && !info.hasExplicitJunctionDot;
return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires )
&& !info.hasExplicitJunctionDot;
}
@ -506,7 +507,7 @@ bool SCH_SCREEN::IsExplicitJunctionAllowed( const VECTOR2I& aPosition ) const
const JUNCTION_HELPERS::POINT_INFO info =
JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, true );
return info.isJunction && !info.hasBusEntry;
return info.isJunction && (!info.hasBusEntry || info.hasBusEntryToMultipleWires );
}

View File

@ -109,6 +109,8 @@ BOOST_AUTO_TEST_CASE( WireTee )
const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
BOOST_CHECK( info.isJunction );
BOOST_CHECK( !info.hasBusEntry );
BOOST_CHECK( !info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( BusEntryOnBus )
@ -139,6 +141,8 @@ BOOST_AUTO_TEST_CASE( BusEntryOnBus )
const POINT_INFO info_end = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
BOOST_CHECK( !info_end.isJunction );
BOOST_CHECK( info_end.hasBusEntry );
// There is no wire here
BOOST_CHECK( !info_end.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( BusEntryToWire )
@ -155,6 +159,8 @@ BOOST_AUTO_TEST_CASE( BusEntryToWire )
const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
BOOST_CHECK( !info.isJunction );
BOOST_CHECK( info.hasBusEntry );
// This is a single wire to a bus entry, not multiple
BOOST_CHECK( !info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( WireDirectToBus )
@ -169,6 +175,8 @@ BOOST_AUTO_TEST_CASE( WireDirectToBus )
const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
BOOST_CHECK( !info.isJunction );
BOOST_CHECK( !info.hasBusEntry );
// It's a single wire, and not a bus entry
BOOST_CHECK( !info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( WireCrossingBus )
@ -188,13 +196,14 @@ BOOST_AUTO_TEST_CASE( WireCrossingBus )
// Two wires and two buses meet, which isn't a junction
BOOST_CHECK( !info.isJunction );
BOOST_CHECK( !info.hasBusEntry );
BOOST_CHECK( !info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( WireToBusEntryRoot )
{
/*
* /--- <-- not a junction (also an ERC error!)
* ______________
* /--- <-- not a junction
* _____________
* ||\
* || \
* || \
@ -206,6 +215,8 @@ BOOST_AUTO_TEST_CASE( WireToBusEntryRoot )
const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
BOOST_CHECK( !info.isJunction );
BOOST_CHECK( info.hasBusEntry );
// The bus/bus-entry point isn't valid
BOOST_CHECK( !info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( WireCrossingBusEntryRoot )
@ -228,6 +239,8 @@ BOOST_AUTO_TEST_CASE( WireCrossingBusEntryRoot )
// Three buses meet here, so this is a junction
BOOST_CHECK( info.isJunction );
BOOST_CHECK( info.hasBusEntry );
// There are multiple wires but they don't count here
BOOST_CHECK( !info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( WireCornerToBusEntry )
@ -250,6 +263,31 @@ BOOST_AUTO_TEST_CASE( WireCornerToBusEntry )
const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
BOOST_CHECK( info.isJunction );
BOOST_CHECK( info.hasBusEntry );
BOOST_CHECK( info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( WireTeeToBusEntry )
{
/*
* ||
* ||
* || |
* \ | /--- junction here
* \| /
* O-------------
* |
* |
*/
items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
items.insert( make_wire( { BE_SIZE, BE_SIZE }, { 2 * BE_SIZE, BE_SIZE } ) ); // right
items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 0 } ) ); //up
items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 2 * BE_SIZE } ) ); // down
items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
BOOST_CHECK( info.isJunction );
BOOST_CHECK( info.hasBusEntry );
BOOST_CHECK( info.hasBusEntryToMultipleWires );
}
BOOST_AUTO_TEST_CASE( SheetPinToOneWire )