Eeschema: Automatically manage junctions

CHANGE: eeschema automatically adds and removes junctions
when required by the schematic

Fixes: lp:593888
* https://bugs.launchpad.net/kicad/+bug/593888

Fixes: lp:1482111
* https://bugs.launchpad.net/kicad/+bug/1482111

Fixes: lp:1563153
* https://bugs.launchpad.net/kicad/+bug/1563153

Fixes: lp:1730219
* https://bugs.launchpad.net/kicad/+bug/1730219

Fixes: lp:1491052
* https://bugs.launchpad.net/kicad/+bug/1491052
This commit is contained in:
Seth Hillbrand 2017-11-27 11:27:24 -08:00 committed by Wayne Stambaugh
parent b5ec5f9a73
commit 069448f20e
13 changed files with 302 additions and 162 deletions

View File

@ -127,9 +127,8 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
if( m_canvas->IsMouseCaptured() )
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
SaveCopyInUndoList( block->GetItems(), UR_MOVED, false, block->GetMoveVector() );
SaveCopyInUndoList( block->GetItems(), UR_CHANGED, false, block->GetMoveVector() );
MoveItemsInList( block->GetItems(), block->GetMoveVector() );
block->ClearItemsList();
break;
case BLOCK_DUPLICATE: /* Duplicate */
@ -141,8 +140,6 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
SaveCopyInUndoList( block->GetItems(),
( block->GetCommand() == BLOCK_PRESELECT_MOVE ) ? UR_CHANGED : UR_NEW );
block->ClearItemsList();
break;
case BLOCK_PASTE:
@ -150,13 +147,15 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
PasteListOfItems( DC );
block->ClearItemsList();
break;
default: // others are handled by HandleBlockEnd()
break;
}
CheckJunctionsInList( block->GetItems(), true );
block->ClearItemsList();
SchematicCleanUp( true );
OnModify();
// clear dome flags and pointers
@ -218,6 +217,8 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
SetCrossHairPosition( rotationPoint );
SaveCopyInUndoList( block->GetItems(), UR_ROTATED, false, rotationPoint );
RotateListOfItems( block->GetItems(), rotationPoint );
CheckJunctionsInList( block->GetItems(), true );
SchematicCleanUp( true );
OnModify();
}
@ -270,6 +271,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
if( block->GetCount() )
{
DeleteItemsInList( block->GetItems() );
SchematicCleanUp( true );
OnModify();
}
block->ClearItemsList();
@ -301,6 +303,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
copyBlockItems( block->GetItems() );
MoveItemsInList( m_blockItems.GetItems(), move_vector );
DeleteItemsInList( block->GetItems() );
SchematicCleanUp( true );
OnModify();
}
@ -329,6 +332,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
SetCrossHairPosition( mirrorPoint );
SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_X, false, mirrorPoint );
MirrorX( block->GetItems(), mirrorPoint );
SchematicCleanUp( true );
OnModify();
}
@ -348,6 +352,7 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
SetCrossHairPosition( mirrorPoint );
SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_Y, false, mirrorPoint );
MirrorY( block->GetItems(), mirrorPoint );
SchematicCleanUp( true );
OnModify();
}

View File

@ -267,81 +267,77 @@ void SCH_EDIT_FRAME::BeginSegment( wxDC* DC, int type )
}
void SCH_EDIT_FRAME::GetSchematicConnections( std::vector< wxPoint >& aConnections )
{
for( SCH_ITEM* item = GetScreen()->GetDrawItems(); item; item = item->Next() )
item->GetConnectionPoints( aConnections );
// We always have some overlapping connection points. Drop duplicates here
std::sort( aConnections.begin(), aConnections.end(),
[]( wxPoint& a, wxPoint& b ) -> bool
{ return a.x < b.x || (a.x == b.x && a.y < b.y); } );
aConnections.erase( unique( aConnections.begin(), aConnections.end() ), aConnections.end() );
}
void SCH_EDIT_FRAME::EndSegment()
{
SCH_SCREEN* screen = GetScreen();
SCH_LINE* segment = (SCH_LINE*) screen->GetCurItem();
PICKED_ITEMS_LIST itemList;
if( segment == NULL || segment->Type() != SCH_LINE_T || !segment->IsNew() )
return;
// Delete zero length segments and clear item flags.
SCH_ITEM* item = s_wires.begin();
while( item )
{
item->ClearFlags();
wxCHECK_RET( item->Type() == SCH_LINE_T, wxT( "Unexpected object type in wire list." ) );
segment = (SCH_LINE*) item;
item = item->Next();
if( segment->IsNull() )
delete s_wires.Remove( segment );
}
// Remove segments backtracking over others
RemoveBacktracks( s_wires );
if( s_wires.GetCount() == 0 )
return;
// Collect the possible connection points for the new lines
std::vector< wxPoint > connections;
std::vector< wxPoint > new_ends;
GetSchematicConnections( connections );
// Check each new segment for possible junctions and add/split if needed
for( SCH_ITEM* wire = s_wires.GetFirst(); wire; wire=wire->Next() )
{
SCH_LINE* test_line = (SCH_LINE*) wire;
if( wire->GetFlags() & SKIP_STRUCT )
continue;
wire->GetConnectionPoints( new_ends );
for( auto i : connections )
{
if( IsPointOnSegment( test_line->GetStartPoint(), test_line->GetEndPoint(), i ) )
{
new_ends.push_back( i );
}
}
itemList.PushItem( ITEM_PICKER( wire, UR_NEW ) );
}
// Get the last non-null wire (this is the last created segment).
SetRepeatItem( segment = (SCH_LINE*) s_wires.GetLast() );
screen->SetCurItem( NULL );
m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false );
// store the terminal point of this last segment: a junction could be needed
// (the last wire could be merged/deleted/modified, and lost)
wxPoint endpoint = segment->GetEndPoint();
// store the starting point of this first segment: a junction could be needed
SCH_LINE* firstsegment = (SCH_LINE*) s_wires.GetFirst();
wxPoint startPoint = firstsegment->GetStartPoint();
// Save the old wires for the undo command
DLIST< SCH_ITEM > oldWires; // stores here the old wires
GetScreen()->ExtractWires( oldWires, true ); // Save them in oldWires list
// Put the snap shot of the previous wire, buses, and junctions in the undo/redo list.
PICKED_ITEMS_LIST oldItems;
oldItems.m_Status = UR_WIRE_IMAGE;
while( oldWires.GetCount() != 0 )
{
ITEM_PICKER picker = ITEM_PICKER( oldWires.PopFront(), UR_WIRE_IMAGE );
oldItems.PushItem( picker );
}
SaveCopyInUndoList( oldItems, UR_WIRE_IMAGE );
// Remove segments backtracking over others
RemoveBacktracks( s_wires );
// Add the new wires
screen->Append( s_wires );
SaveCopyInUndoList(itemList, UR_NEW);
// Correct and remove segments that need to be merged.
SchematicCleanUp();
// A junction could be needed to connect the end point of the last created segment.
if( screen->IsJunctionNeeded( endpoint ) )
screen->Append( AddJunction( endpoint ) );
// A junction could be needed to connect the start point of the set of new created wires
if( screen->IsJunctionNeeded( startPoint ) )
screen->Append( AddJunction( startPoint ) );
m_canvas->Refresh();
SchematicCleanUp( true );
for( auto i : new_ends )
{
if( screen->IsJunctionNeeded( i, true ) )
AddJunction( i, true );
}
screen->TestDanglingEnds();
screen->ClearDrawingState();
screen->SetCurItem( NULL );
m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false );
OnModify();
}
@ -441,54 +437,100 @@ void SCH_EDIT_FRAME::SaveWireImage()
}
bool SCH_EDIT_FRAME::SchematicCleanUp()
bool SCH_EDIT_FRAME::SchematicCleanUp( bool aAppend )
{
bool modified = false;
SCH_ITEM* item = NULL;
SCH_ITEM* secondItem = NULL;
PICKED_ITEMS_LIST itemList;
SCH_SCREEN* screen = GetScreen();
for( SCH_ITEM* item = GetScreen()->GetDrawItems() ; item; item = item->Next() )
auto remove_item = [ &itemList, screen ]( SCH_ITEM* aItem ) -> void
{
if( ( item->Type() != SCH_LINE_T ) && ( item->Type() != SCH_JUNCTION_T ) )
aItem->SetFlags( STRUCT_DELETED );
itemList.PushItem( ITEM_PICKER( aItem, UR_DELETED ) );
};
BreakSegmentsOnJunctions( true );
for( item = screen->GetDrawItems(); item; item = item->Next() )
{
if( ( item->Type() != SCH_LINE_T ) &&
( item->Type() != SCH_JUNCTION_T ) &&
( item->Type() != SCH_NO_CONNECT_T ))
continue;
bool restart;
if( item->GetFlags() & STRUCT_DELETED )
continue;
for( SCH_ITEM* testItem = item->Next(); testItem; testItem = restart ? GetScreen()->GetDrawItems() : testItem->Next() )
// Remove unneeded junctions
if( ( item->Type() == SCH_JUNCTION_T )
&& ( !screen->IsJunctionNeeded( item->GetPosition() ) ) )
{
restart = false;
remove_item( item );
continue;
}
// Remove zero-length lines
if( item->Type() == SCH_LINE_T
&& ( (SCH_LINE*) item )->IsNull() )
{
remove_item( item );
continue;
}
if( ( item->Type() == SCH_LINE_T ) && ( testItem->Type() == SCH_LINE_T ) )
for( secondItem = item->Next(); secondItem; secondItem = secondItem->Next() )
{
if( item->Type() != secondItem->Type() || ( secondItem->GetFlags() & STRUCT_DELETED ) )
continue;
// Merge overlapping lines
if( item->Type() == SCH_LINE_T )
{
SCH_LINE* line = (SCH_LINE*) item;
SCH_LINE* firstLine = (SCH_LINE*) item;
SCH_LINE* secondLine = (SCH_LINE*) secondItem;
SCH_LINE* line = NULL;
bool needed = false;
if( line->MergeOverlap( (SCH_LINE*) testItem ) )
if( !secondLine->IsParallel( firstLine ) )
continue;
// Check if a junction needs to be kept
// This can only happen if:
// 1) the endpoints overlap,
// 2) the lines are not pointing in the same direction AND
// 3) IsJunction Needed is false
if( secondLine->IsEndPoint( firstLine->GetStartPoint() )
&& !secondLine->IsSameQuadrant( firstLine, firstLine->GetStartPoint() ) )
needed = screen->IsJunctionNeeded( firstLine->GetStartPoint() );
else if( secondLine->IsEndPoint( firstLine->GetEndPoint() )
&& !secondLine->IsSameQuadrant( firstLine, firstLine->GetEndPoint() ) )
needed = screen->IsJunctionNeeded( firstLine->GetEndPoint() );
if( !needed && ( line = (SCH_LINE*) secondLine->MergeOverlap( firstLine ) ) )
{
// Keep the current flags, because the deleted segment can be flagged.
item->SetFlags( testItem->GetFlags() );
DeleteItem( testItem );
restart = true;
modified = true;
}
}
else if ( ( ( item->Type() == SCH_JUNCTION_T )
&& ( testItem->Type() == SCH_JUNCTION_T ) ) && ( testItem != item ) )
{
if ( testItem->HitTest( item->GetPosition() ) )
{
// Keep the current flags, because the deleted segment can be flagged.
item->SetFlags( testItem->GetFlags() );
DeleteItem( testItem );
restart = true;
modified = true;
remove_item( item );
remove_item( secondItem );
itemList.PushItem( ITEM_PICKER( line, UR_NEW ) );
screen->Append( (SCH_ITEM*) line );
break;
}
}
// Remove duplicate junctions and no-connects
else if( secondItem->GetPosition() == item->GetPosition() )
remove_item( secondItem );
}
}
for( item = screen->GetDrawItems(); item; item = secondItem )
{
secondItem = item->Next();
if( item->GetFlags() & STRUCT_DELETED )
screen->Remove( item );
}
SaveCopyInUndoList( itemList, UR_CHANGED, aAppend );
GetScreen()->TestDanglingEnds();
return modified;
return !!( itemList.GetCount() );
}
bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE *aSegment, const wxPoint& aPoint, bool aAppend )
{
if( !IsPointOnSegment( aSegment->GetStartPoint(), aSegment->GetEndPoint(), aPoint )
@ -552,20 +594,17 @@ bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( bool aAppend )
}
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPosition,
bool aPutInUndoList )
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPosition, bool aAppend )
{
SCH_JUNCTION* junction = new SCH_JUNCTION( aPosition );
SCH_SCREEN* screen = GetScreen();
bool broken_segments = false;
SetRepeatItem( junction );
if( aPutInUndoList )
{
GetScreen()->Append( junction );
SaveCopyInUndoList( junction, UR_NEW );
OnModify();
}
screen->Append( junction );
broken_segments = BreakSegments( aPosition, aAppend );
screen->TestDanglingEnds();
OnModify();
SaveCopyInUndoList( junction, UR_NEW, broken_segments || aAppend );
return junction;
}

View File

@ -336,19 +336,19 @@ public:
/**
* Test if a junction is required for the items at \a aPosition on the screen.
* <p>
* A junction is required at \a aPosition if the following criteria are satisfied:
* A junction is required at \a aPosition if one of the following criteria is satisfied:
* <ul>
* <li>one wire midpoint, one or more wire endpoints and no junction.</li>
* <li>three or more wire endpoints and no junction.</li>
* <li>two wire midpoints and no junction</li>
* <li>one wire midpoint, a component pin, and no junction.</li>
* <li>three wire endpoints, a component pin, and no junction.</li>
* <li>one wire midpoint and one or more wire endpoints;</li>
* <li>three or more wire endpoints;</li>
* <li>one wire midpoint and a component pin;</li>
* <li>two or more wire endpoints and a component pin.</li>
* </ul>
* </p>
* @param aPosition The position to test.
* @param aNew Checks if a _new_ junction is needed, i.e. there isn't one already
* @return True if a junction is required at \a aPosition.
*/
bool IsJunctionNeeded( const wxPoint& aPosition );
bool IsJunctionNeeded( const wxPoint& aPosition, bool aNew = false );
/**
* Test if \a aPosition is a connection point on \a aLayer.

View File

@ -356,6 +356,11 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
}
schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
// Ensure the schematic is fully segmented on first display
BreakSegmentsOnJunctions();
SchematicCleanUp( true );
GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
}
@ -768,6 +773,11 @@ bool SCH_EDIT_FRAME::ImportFile( const wxString& aFileName, int aFileType )
UpdateFileHistory( fullFileName );
schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
// Ensure the schematic is fully segmented on first display
BreakSegmentsOnJunctions();
SchematicCleanUp( true );
GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );

View File

@ -299,7 +299,13 @@ void SCH_EDIT_FRAME::DisplayCurrentSheet()
screen->m_FirstRedraw = false;
SetCrossHairPosition( GetScrollCenterPosition() );
m_canvas->MoveCursorToCrossHair();
SchematicCleanUp();
// Ensure the schematic is fully segmented on first display
BreakSegmentsOnJunctions();
SchematicCleanUp( true );
screen->ClearUndoORRedoList( screen->m_UndoList, 1 );
screen->TestDanglingEnds();
}
else
{

View File

@ -115,6 +115,42 @@ void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector
}
void SCH_EDIT_FRAME::CheckJunctionsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend )
{
std::vector< wxPoint > pts;
std::vector< wxPoint > connections;
GetSchematicConnections( connections );
for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
{
SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
item->GetConnectionPoints( pts );
if( item->Type() == SCH_LINE_T )
{
SCH_LINE* line = (SCH_LINE*) item;
for( auto i : connections )
if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), i ) )
pts.push_back( i );
}
}
// We always have some overlapping connection points. Drop duplicates here
std::sort( pts.begin(), pts.end(),
[]( wxPoint& a, wxPoint& b ) -> bool
{ return a.x < b.x || (a.x == b.x && a.y < b.y); } );
pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
for( auto point : pts )
{
if( GetScreen()->IsJunctionNeeded( point, true ) )
{
AddJunction( point, aAppend );
aAppend = true;
}
}
}
void SCH_EDIT_FRAME::DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend )
{
PICKED_ITEMS_LIST itemsList;

View File

@ -557,6 +557,7 @@ bool SCH_EDIT_FRAME::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
// Clean up wire ends
SchematicCleanUp();
GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
m_canvas->Refresh( true );
OnModify();

View File

@ -388,7 +388,8 @@ bool SCH_LINE::IsParallel( SCH_LINE* aLine )
return !( (long long) firstSeg.x * secondSeg.y - (long long) firstSeg.y * secondSeg.x );
}
bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
EDA_ITEM* SCH_LINE::MergeOverlap( SCH_LINE* aLine )
{
auto less = []( const wxPoint& lhs, const wxPoint& rhs ) -> bool
{
@ -396,12 +397,11 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
return lhs.y < rhs.y;
return lhs.x < rhs.x;
};
wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, false,
wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, NULL,
wxT( "Cannot test line segment for overlap." ) );
if( this == aLine || GetLayer() != aLine->GetLayer() )
return false;
return NULL;
SCH_LINE leftmost = SCH_LINE( *aLine );
SCH_LINE rightmost = SCH_LINE( *this );
@ -428,16 +428,14 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
// If we end one before the beginning of the other, no overlap is possible
if( less( leftmost.m_end, other.m_start ) )
{
return false;
return NULL;
}
// Search for a common end:
if( ( leftmost.m_start == other.m_start )
&& ( leftmost.m_end == other.m_end ) ) // Trivial case
{
m_start = leftmost.m_start;
m_end = leftmost.m_end;
return true;
return new SCH_LINE( leftmost );
}
bool colinear = false;
@ -471,12 +469,11 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
// Make a new segment that merges the 2 segments
if( colinear )
{
m_start = leftmost.m_start;
m_end = rightmost.m_end;
return true;
leftmost.m_end = rightmost.m_end;
return new SCH_LINE( leftmost );
}
return false;
return NULL;
}
@ -696,6 +693,7 @@ bool SCH_LINE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
return rect.Intersects( m_start, m_end );
}
void SCH_LINE::SwapData( SCH_ITEM* aItem )
{
SCH_LINE* item = (SCH_LINE*) aItem;
@ -711,6 +709,7 @@ void SCH_LINE::SwapData( SCH_ITEM* aItem )
std::swap( m_color, item->m_color );
}
bool SCH_LINE::doIsConnected( const wxPoint& aPosition ) const
{
if( m_Layer != LAYER_WIRE && m_Layer != LAYER_BUS )

View File

@ -133,14 +133,14 @@ public:
/**
* Check line against \a aLine to see if it overlaps and merge if it does.
*
* This method will change the line to be equivalent of the line and \a aLine if the
* This method will return an equivalent of the union of line and \a aLine if the
* two lines overlap. This method is used to merge multiple line segments into a single
* line.
*
* @param aLine - Line to compare.
* @return True if lines overlap and the line was merged with \a aLine.
* @return New line that combines the two or NULL on non-overlapping segments.
*/
bool MergeOverlap( SCH_LINE* aLine );
EDA_ITEM* MergeOverlap( SCH_LINE* aLine );
/**
* Check if two lines are in the same quadrant as each other, using a reference point as

View File

@ -55,6 +55,7 @@
#include <lib_pin.h>
#include <symbol_lib_table.h>
#include <boost/foreach.hpp>
#define EESCHEMA_FILE_STAMP "EESchema"
@ -346,20 +347,60 @@ void SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
}
bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition )
bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
{
if( GetItem( aPosition, 0, SCH_JUNCTION_T ) )
return false;
bool has_line = false;
bool has_nonparallel = false;
int end_count = 0;
if( GetWire( aPosition, 0, EXCLUDE_END_POINTS_T ) )
std::vector< SCH_LINE* > lines;
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
{
if( GetWire( aPosition, 0, END_POINTS_ONLY_T ) )
return true;
if( item->GetFlags() & STRUCT_DELETED )
continue;
if( aNew && ( item->Type() == SCH_JUNCTION_T ) && ( item->HitTest( aPosition ) ) )
return false;
if( GetPin( aPosition, NULL, true ) )
return true;
if( item->Type() != SCH_LINE_T )
continue;
if( item->GetLayer() != LAYER_WIRE )
continue;
if( item->HitTest( aPosition, 0 ) )
lines.push_back( (SCH_LINE*) item );
}
BOOST_FOREACH( SCH_LINE* line, lines)
{
if( !line->IsEndPoint( aPosition ) )
has_line = true;
else
end_count++;
BOOST_REVERSE_FOREACH( SCH_LINE* second_line, lines )
{
if( line == second_line )
break;
if( line->IsEndPoint( second_line->GetStartPoint() )
&& line->IsEndPoint( second_line->GetEndPoint() ) )
end_count--;
if( !line->IsParallel( second_line ) )
has_nonparallel = true;
}
}
int has_pin = !!( GetPin( aPosition, NULL, true ) );
// If there is line intersecting a pin or non-parallel end
if( has_pin && ( has_line || end_count > 1 ) )
return true;
// If there is at least one segment that ends on a non-parallel line or
// junction of two other lines
if( has_nonparallel && (has_line || end_count > 2 ) )
return true;
return false;
}
@ -1098,30 +1139,6 @@ int SCH_SCREEN::GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aLis
}
}
// Get redundant junctions (junctions which connect < 3 end wires
// and no pin)
for( item = m_drawList.begin(); item; item = item->Next() )
{
if( item->GetFlags() & STRUCT_DELETED )
continue;
if( !(item->GetFlags() & CANDIDATE) )
continue;
if( item->Type() != SCH_JUNCTION_T )
continue;
SCH_JUNCTION* junction = (SCH_JUNCTION*) item;
if( CountConnectedItems( junction->GetPosition(), false ) <= 2 )
{
item->SetFlags( STRUCT_DELETED );
ITEM_PICKER picker( item, UR_DELETED );
aList.PushItem( picker );
}
}
for( item = m_drawList.begin(); item; item = item->Next() )
{
if( item->GetFlags() & STRUCT_DELETED )
@ -1132,7 +1149,7 @@ int SCH_SCREEN::GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aLis
tmp = GetWireOrBus( ( (SCH_TEXT*) item )->GetPosition() );
if( tmp && tmp->GetFlags() & STRUCT_DELETED )
if( tmp && ( tmp->GetFlags() & STRUCT_DELETED ) )
{
item->SetFlags( STRUCT_DELETED );

View File

@ -190,6 +190,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_SCH_DELETE_CONNECTION:
m_canvas->MoveCursorToCrossHair();
DeleteConnection( id == ID_POPUP_SCH_DELETE_CONNECTION );
SchematicCleanUp( true );
screen->SetCurItem( NULL );
SetRepeatItem( NULL );
@ -214,6 +215,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break;
DeleteItem( item );
SchematicCleanUp( true );
screen->SetCurItem( NULL );
SetRepeatItem( NULL );
screen->TestDanglingEnds();
@ -630,6 +632,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool aFullConnection )
if( screen->GetConnection( pos, pickList, aFullConnection ) != 0 )
{
DeleteItemsInList( pickList );
SchematicCleanUp( true );
OnModify();
}
}

View File

@ -1443,7 +1443,16 @@ void SCH_EDIT_FRAME::addCurrentItemToList( bool aRedraw )
m_canvas->EndMouseCapture();
if( item->IsConnectable() )
{
std::vector< wxPoint > pts;
item->GetConnectionPoints( pts );
for( auto i : pts )
{
if( screen->IsJunctionNeeded( i, true ) )
AddJunction( i, true );
}
screen->TestDanglingEnds();
}
if( aRedraw )
GetCanvas()->Refresh();

View File

@ -937,19 +937,25 @@ private:
SCH_JUNCTION* AddJunction( const wxPoint& aPosition, bool aPutInUndoList = false );
/**
* Function SaveWireImage
* saves a copy of the current wire image in the undo list
* Save a copy of the current wire image in the undo list.
*/
void SaveWireImage();
/**
* Function SchematicCleanUp
* performs routine schematic cleaning including breaking wire and buses and
* Collects a unique list of all possible connection points in the schematic.
*
* @param aConnections vector of connections
*/
void GetSchematicConnections( std::vector< wxPoint >& aConnections );
/**
* Performs routine schematic cleaning including breaking wire and buses and
* deleting identical objects superimposed on top of each other.
*
* @param aAppend The changes to the schematic should be appended to the previous undo
* @return True if any schematic clean up was performed.
*/
bool SchematicCleanUp();
bool SchematicCleanUp( bool aAppend = false );
/**
* Start moving \a aItem using the mouse.
@ -1128,6 +1134,15 @@ public:
*/
void DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend = false );
/**
* Adds junctions if needed to each item in the list after they have been
* moved.
*
* @param aItemsList The list of items to check
* @param aAppend True if we are updating a previous commit
*/
void CheckJunctionsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend = false );
int GetLabelIncrement() const { return m_repeatLabelDelta; }
private: