← Back to team overview

kicad-developers team mailing list archive

[PATCH] SCH_LINE: Split mergeability test and actual merge

 

---
 eeschema/sch_line.cpp   | 58 ++++++++++++++++++++++++++-----------------------
 eeschema/sch_line.h     | 16 ++++++++++----
 eeschema/sch_screen.cpp |  3 ++-
 3 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp
index 72efb5c..372885b 100644
--- a/eeschema/sch_line.cpp
+++ b/eeschema/sch_line.cpp
@@ -284,7 +284,7 @@ bool sort_by_ends_position(const wxPoint * ref, const wxPoint * tst )
  * MergeOverlap try to merge 2 lines that are colinear.
  * this function expects these 2 lines have at least a common end
  */
-bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
+bool SCH_LINE::CanMerge( const SCH_LINE* aLine ) const
 {
     wxCHECK_MSG( aLine != NULL && aLine->Type() == SCH_LINE_T, false,
                  wxT( "Cannot test line segment for overlap." ) );
@@ -292,22 +292,25 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
     if( this == aLine || GetLayer() != aLine->GetLayer() )
         return false;
 
+    auto rhs_start = aLine->m_start;
+    auto rhs_end = aLine->m_end;
+
     // Search for a common end:
-    if( m_start == aLine->m_start )
+    if( m_start == rhs_start )
     {
-        if( m_end == aLine->m_end )     // Trivial case
+        if( m_end == rhs_end )     // Trivial case
             return true;
     }
-    else if( m_start == aLine->m_end )
+    else if( m_start == rhs_end )
     {
-        if( m_end == aLine->m_start )     // Trivial case
+        if( m_end == rhs_start )     // Trivial case
             return true;
     }
-    else if( m_end == aLine->m_end )
+    else if( m_end == rhs_end )
     {
-        std::swap( aLine->m_start, aLine->m_end );
+        std::swap( rhs_start, rhs_end );
     }
-    else if( m_end != aLine->m_start )
+    else if( m_end != rhs_start )
     {
         // No common end point, segments cannot be merged.
         return false;
@@ -318,14 +321,14 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
     /* Test alignment: */
     if( m_start.y == m_end.y )       // Horizontal segment
     {
-        if( aLine->m_start.y == aLine->m_end.y )
+        if( rhs_start.y == rhs_end.y )
         {
             colinear = true;
         }
     }
     else if( m_start.x == m_end.x )  // Vertical segment
     {
-        if( aLine->m_start.x == aLine->m_end.x )
+        if( rhs_start.x == rhs_end.x )
         {
             colinear = true;
         }
@@ -333,32 +336,33 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine )
     else
     {
         if( atan2( (double) ( m_start.x - m_end.x ), (double) ( m_start.y - m_end.y ) )
-            == atan2( (double) ( aLine->m_start.x - aLine->m_end.x ),
-                      (double) ( aLine->m_start.y - aLine->m_end.y ) ) )
+            == atan2( (double) ( rhs_start.x - rhs_end.x ),
+                      (double) ( rhs_start.y - rhs_end.y ) ) )
         {
             colinear = true;
         }
     }
 
+    return colinear;
+}
+
+
+void SCH_LINE::MergeOverlap( SCH_LINE* aLine )
+{
     // Make a segment which merge the 2 segments
     // we must find the extremums
     // i.e. the more to the left and to the right points, or
     // for horizontal segments the uppermost and the lowest point
-    if( colinear )
-    {
-        static std::vector <wxPoint*> candidates;
-        candidates.clear();
-        candidates.push_back( &m_start );
-        candidates.push_back( &m_end );
-        candidates.push_back( &aLine->m_start );
-        candidates.push_back( &aLine->m_end );
-        sort( candidates.begin(), candidates.end(), sort_by_ends_position );
-        wxPoint tmp = *candidates[3];
-        m_start = *candidates[0];
-        m_end = tmp;
-        return true;
-    }
-    return false;
+    std::vector <wxPoint*> candidates;
+    candidates.reserve(4);
+    candidates.push_back( &m_start );
+    candidates.push_back( &m_end );
+    candidates.push_back( &aLine->m_start );
+    candidates.push_back( &aLine->m_end );
+    sort( candidates.begin(), candidates.end(), sort_by_ends_position );
+    wxPoint tmp = *candidates[3];
+    m_start = *candidates[0];
+    m_end = tmp;
 }
 
 
diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h
index e52280c..a35d899 100644
--- a/eeschema/sch_line.h
+++ b/eeschema/sch_line.h
@@ -102,16 +102,24 @@ public:
     virtual void Rotate( wxPoint aPosition ) override;
 
     /**
-     * Check line against \a aLine to see if it overlaps and merge if it does.
+     * Check line against \a aLine to see if it overlaps.
+     * @param[in]   aLine   Line to be compared
+     * @return  whether lines can be merged
+     */
+    bool CanMerge( const SCH_LINE* aLine ) const;
+
+    /**
+     * Merge line with \a aLine
      *
      * This method will change the line to be equivalent of the 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.
+     * This function will only work if CanMerge returned true.
+     *
+     * @param[in]   aLine   Line to merge
      */
-    bool MergeOverlap( SCH_LINE* aLine );
+    void MergeOverlap( SCH_LINE* aLine );
 
     virtual void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList ) override;
 
diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp
index a2655a7..93cd9d6 100644
--- a/eeschema/sch_screen.cpp
+++ b/eeschema/sch_screen.cpp
@@ -461,8 +461,9 @@ bool SCH_SCREEN::SchematicCleanUp()
             {
                 SCH_LINE* line = (SCH_LINE*) item;
 
-                if( line->MergeOverlap( (SCH_LINE*) testItem ) )
+                if( line->CanMerge( (SCH_LINE*) testItem ) )
                 {
+                    line->MergeOverlap( (SCH_LINE*) testItem );
                     // Keep the current flags, because the deleted segment can be flagged.
                     item->SetFlags( testItem->GetFlags() );
                     DeleteItem( testItem );