Eeschema: Consider buses for junctions

Allows buses to acquire junctions based on their connections.  Buses
can only have junctions with other buses.  Also allows buses to be
draggable junctions for collections
This commit is contained in:
Seth Hillbrand 2017-12-12 21:12:06 -08:00 committed by Wayne Stambaugh
parent 23d71cfa93
commit 1396ab0941
3 changed files with 72 additions and 80 deletions

View File

@ -483,7 +483,7 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( bool aAppend )
PICKED_ITEMS_LIST itemList;
SCH_SCREEN* screen = GetScreen();
auto remove_item = [ &itemList, screen ]( SCH_ITEM* aItem ) -> void
auto remove_item = [ &itemList ]( SCH_ITEM* aItem ) -> void
{
aItem->SetFlags( STRUCT_DELETED );
itemList.PushItem( ITEM_PICKER( aItem, UR_DELETED ) );
@ -493,9 +493,9 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( bool aAppend )
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 ))
if( ( item->Type() != SCH_LINE_T )
&& ( item->Type() != SCH_JUNCTION_T )
&& ( item->Type() != SCH_NO_CONNECT_T ) )
continue;
if( item->GetFlags() & STRUCT_DELETED )
@ -503,14 +503,15 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( bool aAppend )
// Remove unneeded junctions
if( ( item->Type() == SCH_JUNCTION_T )
&& ( !screen->IsJunctionNeeded( item->GetPosition() ) ) )
&& ( !screen->IsJunctionNeeded( item->GetPosition() ) ) )
{
remove_item( item );
continue;
}
// Remove zero-length lines
if( item->Type() == SCH_LINE_T
&& ( (SCH_LINE*) item )->IsNull() )
&& ( (SCH_LINE*) item )->IsNull() )
{
remove_item( item );
continue;
@ -524,24 +525,26 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( bool aAppend )
// Merge overlapping lines
if( item->Type() == SCH_LINE_T )
{
SCH_LINE* firstLine = (SCH_LINE*) item;
SCH_LINE* secondLine = (SCH_LINE*) secondItem;
SCH_LINE* line = NULL;
SCH_LINE* firstLine = (SCH_LINE*) item;
SCH_LINE* secondLine = (SCH_LINE*) secondItem;
SCH_LINE* line = NULL;
bool needed = false;
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() ) )
// Remove identical lines
if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
&& firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
{
remove_item( secondItem );
continue;
}
// If the end points overlap, check if we still need the junction
if( secondLine->IsEndPoint( firstLine->GetStartPoint() ) )
needed = screen->IsJunctionNeeded( firstLine->GetStartPoint() );
else if( secondLine->IsEndPoint( firstLine->GetEndPoint() )
&& !secondLine->IsSameQuadrant( firstLine, firstLine->GetEndPoint() ) )
else if( secondLine->IsEndPoint( firstLine->GetEndPoint() ) )
needed = screen->IsJunctionNeeded( firstLine->GetEndPoint() );
if( !needed && ( line = (SCH_LINE*) secondLine->MergeOverlap( firstLine ) ) )
@ -558,12 +561,15 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( bool aAppend )
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 );
return !!( itemList.GetCount() );

View File

@ -325,42 +325,11 @@ bool SCH_COLLECTOR::IsNode( bool aIncludePins ) const
bool SCH_COLLECTOR::IsDraggableJunction() const
{
int wireEndCount = 0;
int wireMidPoint = 0;
int junctionCount = 0;
for( size_t i = 0; i < m_List.size(); i++ )
{
SCH_ITEM* item = (SCH_ITEM*) m_List[ i ];
KICAD_T type = item->Type();
if( ( (SCH_ITEM*) m_List[ i ] )->Type() == SCH_JUNCTION_T )
return true;
if( type == SCH_JUNCTION_T )
{
junctionCount++;
continue;
}
if( type == SCH_LINE_T )
{
if( item->GetLayer() != LAYER_WIRE )
return false;
SCH_LINE* line = (SCH_LINE*) item;
if( line->IsEndPoint( m_RefPos ) )
wireEndCount++;
else
wireMidPoint++;
continue;
}
// Any other item types indicate that this collection is not a draggable junction.
return false;
}
return (wireEndCount >= 3) || ((wireEndCount >= 1) && (wireMidPoint == 1))
|| ((wireMidPoint >= 2) && (junctionCount == 1));
return false;
}

View File

@ -55,8 +55,6 @@
#include <lib_pin.h>
#include <symbol_lib_table.h>
#include <boost/foreach.hpp>
#define EESCHEMA_FILE_STAMP "EESchema"
/* Default zoom values. Limited to these values to keep a decent size
@ -349,11 +347,11 @@ void SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
{
bool has_line = false;
bool has_nonparallel = false;
int end_count = 0;
int pin_count = 0;
std::vector< SCH_LINE* > lines;
bool has_nonparallel[2] = { false };
int end_count[2] = { 0 };
int pin_count = 0;
std::vector<SCH_LINE*> lines[2];
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
{
@ -364,44 +362,63 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
return false;
if( ( item->Type() == SCH_LINE_T )
&& ( item->GetLayer() == LAYER_WIRE )
&& ( item->HitTest( aPosition, 0 ) ) )
lines.push_back( (SCH_LINE*) item );
&& ( item->HitTest( aPosition, 0 ) ) )
{
if( item->GetLayer() == LAYER_WIRE )
lines[0].push_back( (SCH_LINE*) item );
else if( item->GetLayer() == LAYER_BUS )
lines[1].push_back( (SCH_LINE*) item );
}
if( ( item->Type() == SCH_COMPONENT_T )
&& ( item->IsConnected( aPosition ) ) )
pin_count++;
}
BOOST_FOREACH( SCH_LINE* line, lines)
for( int i = 0; i < 2; i++ )
{
if( !line->IsEndPoint( aPosition ) )
has_line = true;
else
end_count++;
BOOST_REVERSE_FOREACH( SCH_LINE* second_line, lines )
bool removed_overlapping = false;
end_count[i] = lines[i].size();
for( auto line = lines[i].begin(); line < lines[i].end(); line++ )
{
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;
// Consider ending on a line to be equivalent to two endpoints because
// we will want to split the line if anything else connects
if( !(*line)->IsEndPoint( aPosition ) )
end_count[i]++;
for( auto second_line = lines[i].end() - 1; second_line > line; second_line-- )
{
if( !(*line)->IsParallel( *second_line ) )
has_nonparallel[i] = true;
else if( !removed_overlapping
&& (*line)->IsSameQuadrant( *second_line, aPosition ) )
{
/**
* Overlapping lines that point in the same direction should not be counted
* as extra end_points. We remove the overlapping lines, being careful to only
* remove them once.
*/
removed_overlapping = true;
end_count[i]--;
}
}
}
}
// If there is line intersecting a pin
if( pin_count && has_line )
return true;
//
// If there are three or more endpoints
if( pin_count + end_count > 2 )
if( pin_count + end_count[0] > 2 )
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 ) )
if( has_nonparallel[0] && end_count[0] > 2 )
return true;
// Check for bus - bus junction requirements
if( has_nonparallel[1] && end_count[1] > 2 )
return true;
return false;