Trim wires based on how many pins they intersect

If a wire intersects more than 2 pins from the same symbol, we don't
trim connections.  If the wire intersects exactly two pins from a single
symbol, we remove the wire between the pins.

We avoided doing this before because we didn't have a good metric for
trimming vs. not.  But the per-symbol calculation feels like the least
surprising option.

Fixes https://gitlab.com/kicad/code/kicad/issues/10909

Fixes https://gitlab.com/kicad/code/kicad/issues/1857
This commit is contained in:
Seth Hillbrand 2022-02-19 16:49:26 -08:00
parent f0d7a09af9
commit 75a4036e45
7 changed files with 69 additions and 11 deletions

View File

@ -692,6 +692,11 @@ TOOL_ACTION EE_ACTIONS::addNeededJunctions( "eeschema.InteractiveDrawingLineWire
_( "Add Junctions to Selection where needed" ), "",
BITMAPS::INVALID_BITMAP, AF_ACTIVATE );
TOOL_ACTION EE_ACTIONS::trimOverlappingWires( "eeschema.InteractiveDrawingLineWireBus.trimOverlappingWires",
AS_ACTIVE, 0, "",
"", "",
BITMAPS::INVALID_BITMAP, AF_ACTIVATE );
const DRAW_SEGMENT_EVENT_PARAMS drawWireActionParam = { LAYER_WIRE, false };
TOOL_ACTION EE_ACTIONS::drawWire( "eeschema.InteractiveDrawingLineWireBus.drawWires",

View File

@ -73,6 +73,7 @@ public:
// Schematic Tools
static TOOL_ACTION addNeededJunctions;
static TOOL_ACTION trimOverlappingWires;
static TOOL_ACTION pickerTool;
static TOOL_ACTION placeSymbol;
static TOOL_ACTION placePower;

View File

@ -278,12 +278,14 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
symbol->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
symbol->ClearEditFlags();
m_view->Update( symbol );
m_frame->GetScreen()->Update( symbol );
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true,
&m_selectionTool->GetSelection() );
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true,
&m_selectionTool->GetSelection() );
m_view->Update( symbol );
m_frame->GetScreen()->Update( symbol );
m_frame->OnModify();
SCH_SYMBOL* nextSymbol = nullptr;

View File

@ -893,6 +893,7 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
EE_SELECTION new_sel;
new_sel.Add( newItem );
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &new_sel );
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &new_sel );
m_frame->RecalculateConnections( LOCAL_CLEANUP );

View File

@ -973,6 +973,50 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
}
int SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires( const TOOL_EVENT& aEvent )
{
EE_SELECTION* aSelection = aEvent.Parameter<EE_SELECTION*>();
SCHEMATIC* sch = getModel<SCHEMATIC>();
SCH_SCREEN* screen = sch->CurrentSheet().LastScreen();
std::set<SCH_LINE*> lines;
EDA_RECT bb = aSelection->GetBoundingBox();
for( EDA_ITEM* item : screen->Items().Overlapping( SCH_LINE_T, bb ) )
lines.insert( static_cast<SCH_LINE*>( item ) );
for( unsigned ii = 0; ii < aSelection->GetSize(); ii++ )
{
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( ii ) );
std::vector<wxPoint> pts = item->GetConnectionPoints();
if( !item || !item->IsConnectable() || ( item->Type() == SCH_LINE_T ) )
continue;
/// If the line intersects with an item in the selection at only two points,
/// then we can remove the line between the two points.
for( SCH_LINE* line : lines )
{
std::vector<wxPoint> conn_pts;
for( wxPoint pt : pts )
{
if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
conn_pts.push_back( pt );
if( conn_pts.size() > 2 )
break;
}
if( conn_pts.size() == 2 )
m_frame->TrimWire( conn_pts[0], conn_pts[1] );
}
}
return 0;
}
int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
{
EE_SELECTION* aSelection = aEvent.Parameter<EE_SELECTION*>();
@ -980,6 +1024,12 @@ int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
std::vector<wxPoint> pts;
std::vector<wxPoint> connections = m_frame->GetSchematicConnections();
std::set<SCH_LINE*> lines;
EDA_RECT bb = aSelection->GetBoundingBox();
for( EDA_ITEM* item : m_frame->GetScreen()->Items().Overlapping( SCH_LINE_T, bb ) )
lines.insert( static_cast<SCH_LINE*>( item ) );
for( unsigned ii = 0; ii < aSelection->GetSize(); ii++ )
{
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( ii ) );
@ -1002,15 +1052,6 @@ int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
pts.push_back( pt );
}
}
else
{
// Clean up any wires that short non-wire connections in the list
for( auto pt = new_pts.begin(); pt != new_pts.end(); pt++ )
{
for( auto secondPt = pt + 1; secondPt != new_pts.end(); secondPt++ )
m_frame->TrimWire( *pt, *secondPt );
}
}
}
// We always have some overlapping connection points. Drop duplicates here
@ -1035,6 +1076,7 @@ int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
void SCH_LINE_WIRE_BUS_TOOL::setTransitions()
{
Go( &SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded, EE_ACTIONS::addNeededJunctions.MakeEvent() );
Go( &SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires, EE_ACTIONS::trimOverlappingWires.MakeEvent() );
Go( &SCH_LINE_WIRE_BUS_TOOL::DrawSegments, EE_ACTIONS::drawWire.MakeEvent() );
Go( &SCH_LINE_WIRE_BUS_TOOL::DrawSegments, EE_ACTIONS::drawBus.MakeEvent() );
Go( &SCH_LINE_WIRE_BUS_TOOL::DrawSegments, EE_ACTIONS::drawLines.MakeEvent() );

View File

@ -93,6 +93,11 @@ public:
*/
int AddJunctionsIfNeeded( const TOOL_EVENT& aEvent );
/**
* Logic to remove wires when overlapping correct items
*/
int TrimOverLappingWires( const TOOL_EVENT& aEvent );
private:
int doDrawSegments( const std::string& aTool, int aType, bool aQuitOnDraw );
SCH_LINE* startSegments( int aType, const VECTOR2D& aPos );

View File

@ -505,6 +505,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
m_frame->AddJunction( m_frame->GetScreen(), it.GetPosition(), true, false );
}
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &selectionCopy );
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selectionCopy );
m_frame->RecalculateConnections( LOCAL_CLEANUP );
@ -917,6 +918,7 @@ int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
}
m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved );
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &selection );
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selection );
m_frame->RecalculateConnections( LOCAL_CLEANUP );