diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp index 24b7ff72f2..f947268c78 100644 --- a/eeschema/sch_line.cpp +++ b/eeschema/sch_line.cpp @@ -411,26 +411,29 @@ void SCH_LINE::RotateEnd( wxPoint aPosition ) } -bool SCH_LINE::IsSameQuadrant( const SCH_LINE* aLine, const wxPoint& aPosition ) const +int SCH_LINE::GetAngleFrom( const wxPoint& aPoint ) const { - wxPoint first; - wxPoint second; + wxPoint vec; - if( m_start == aPosition ) - first = m_end - aPosition; - else if( m_end == aPosition ) - first = m_start - aPosition; + if( aPoint == m_start ) + vec = m_end - aPoint; else - return false; + vec = m_start - aPoint; - if( aLine->m_start == aPosition ) - second = aLine->m_end - aPosition; - else if( aLine->m_end == aPosition ) - second = aLine->m_start - aPosition; + return KiROUND( ArcTangente( vec.y, vec.x ) ); +} + + +int SCH_LINE::GetReverseAngleFrom( const wxPoint& aPoint ) const +{ + wxPoint vec; + + if( aPoint == m_end ) + vec = m_start - aPoint; else - return false; + vec = m_end - aPoint; - return ( sign( first.x ) == sign( second.x ) && sign( first.y ) == sign( second.y ) ); + return KiROUND( ArcTangente( vec.y, vec.x ) ); } diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h index d959791c5b..97a131b5bc 100644 --- a/eeschema/sch_line.h +++ b/eeschema/sch_line.h @@ -89,6 +89,9 @@ public: return aPoint == m_start || aPoint == m_end; } + int GetAngleFrom( const wxPoint& aPoint ) const; + int GetReverseAngleFrom( const wxPoint& aPoint ) const; + bool IsNull() const { return m_start == m_end; } wxPoint GetStartPoint() const { return m_start; } @@ -193,16 +196,6 @@ public: */ SCH_LINE* MergeOverlap( SCH_SCREEN* aScreen, SCH_LINE* aLine, bool aCheckJunctions ); - /** - * Check if two lines are in the same quadrant as each other, using a reference point as - * the origin - * - * @param aLine - Line to compare - * @param aPosition - Point to reference against lines - * @return true if lines are mostly in different quadrants of aPosition, false otherwise - */ - bool IsSameQuadrant( const SCH_LINE* aLine, const wxPoint& aPosition ) const; - bool IsParallel( const SCH_LINE* aLine ) const; void GetEndPoints( std::vector& aItemList ) override; diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp index d4ca290172..789b579e81 100644 --- a/eeschema/sch_screen.cpp +++ b/eeschema/sch_screen.cpp @@ -372,14 +372,12 @@ std::set SCH_SCREEN::MarkConnections( SCH_LINE* aSegment ) bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew ) const { - enum { WIRES, BUSES } layers; + bool breakLines = false; + std::unordered_set exitAngles; + std::vector midPointLines; - bool has_nonparallel[ sizeof( layers ) ] = { false }; - int end_count[ sizeof( layers ) ] = { 0 }; - int entry_count = 0; - int pin_count = 0; - - std::vector lines[ sizeof( layers ) ]; + // A pin at 90º still shouldn't match a line at 90º so just give pins unique numbers + int uniqueAngle = 10000; for( const SCH_ITEM* item : Items().Overlapping( aPosition ) ) { @@ -395,26 +393,31 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew ) const break; case SCH_LINE_T: - if( item->HitTest( aPosition, 0 ) ) + { + const SCH_LINE* line = static_cast( item ); + + if( line->IsConnected( aPosition ) ) { - if( item->GetLayer() == LAYER_WIRE ) - lines[WIRES].push_back( (SCH_LINE*) item ); - else if( item->GetLayer() == LAYER_BUS ) - lines[BUSES].push_back( (SCH_LINE*) item ); + breakLines = true; + exitAngles.insert( line->GetAngleFrom( aPosition ) ); } + else if( item->HitTest( aPosition ) ) + { + // Defer any line midpoints until we know whether or not we're breaking them + midPointLines.push_back( line ); + } + } break; case SCH_BUS_WIRE_ENTRY_T: case SCH_BUS_BUS_ENTRY_T: - if( item->IsConnected( aPosition ) ) - entry_count++; - - break; - case SCH_COMPONENT_T: case SCH_SHEET_T: if( item->IsConnected( aPosition ) ) - pin_count++; + { + breakLines = true; + exitAngles.insert( uniqueAngle++ ); + } break; @@ -423,60 +426,16 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew ) const } } - for( int i : { WIRES, BUSES } ) + if( breakLines ) { - bool removed_overlapping = false; - - for( auto line = lines[i].begin(); line < lines[i].end(); ++line ) + for( const SCH_LINE* line : midPointLines ) { - /// A line with a midpoint should be counted as two endpoints for this calculation - /// because the junction will split the line into two if there is another item - /// present at the point. - if( !(*line)->IsEndPoint( aPosition ) ) - end_count[i] += 2; - else - 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 ) ) - { - removed_overlapping = true; - } - } + exitAngles.insert( line->GetAngleFrom( aPosition ) ); + exitAngles.insert( line->GetReverseAngleFrom( aPosition ) ); } - - ///Overlapping lines that point in the same direction should not be counted - /// as extra end_points. - if( removed_overlapping ) - end_count[i]--; } - // If there are three or more endpoints - if( pin_count && pin_count + end_count[WIRES] > 2 ) - return true; - - // If wire segments overlap an entry - if( entry_count && entry_count + end_count[WIRES] > 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[WIRES] && end_count[WIRES] > 2 ) - return true; - - // Check for bus - bus junction requirements - if( has_nonparallel[BUSES] && end_count[BUSES] > 2 ) - return true; - - // Check for bus - bus entry requirements - if( !aNew && entry_count && end_count[BUSES] ) - return true; - - return false; + return exitAngles.size() >= 3; } @@ -495,16 +454,12 @@ bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer ) const SCH_SHEET_PIN* sheetPin = GetSheetPin( aPosition ); if( sheetPin && sheetPin->IsConnected( aPosition ) ) - { return true; - } SCH_TEXT* label = GetLabel( aPosition ); if( label && label->IsConnected( aPosition ) ) - { return true; - } } break; @@ -532,16 +487,12 @@ bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer ) const SCH_TEXT* label = GetLabel( aPosition, 1 ); if( label && label->IsConnected( aPosition ) ) - { return true; - } SCH_SHEET_PIN* sheetPin = GetSheetPin( aPosition ); if( sheetPin && sheetPin->IsConnected( aPosition ) ) - { return true; - } } break;