From 3456b6e3c30539388ebfd04c9b2cdb5df050777b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Tue, 23 Jan 2018 11:55:03 +0100 Subject: [PATCH] pcbnew: fixed incorrect ratsnest computation when all nodes in a net are on a single line --- pcbnew/ratsnest_data.cpp | 76 +++++++++++++++------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/pcbnew/ratsnest_data.cpp b/pcbnew/ratsnest_data.cpp index e172c63a71..c7628a8e24 100644 --- a/pcbnew/ratsnest_data.cpp +++ b/pcbnew/ratsnest_data.cpp @@ -175,57 +175,31 @@ private: } - std::list computeTriangulation( std::vector& aNodes ) + // Checks if all nodes in aNodes lie on a single line. Requires the nodes to + // have unique coordinates! + bool areNodesColinear( const std::vector& aNodes ) const { - #if 0 - bool refresh = false; - // we assume aNodes are sorted - VECTOR2I prevDelta; + if ( aNodes.size() <= 2 ) + return true; - if ( aNodes.size() == m_prevNodes.size() ) + const auto p0 = aNodes[0]->Pos(); + const auto v0 = aNodes[1]->Pos() - p0; + + for( int i = 2; i < aNodes.size(); i++ ) { - for ( int i = 0; i < aNodes.size(); i++ ) + const auto v1 = aNodes[i]->Pos() - p0; + + if( v0.Cross( v1 ) != 0 ) { - const auto& a = aNodes[i]; - const auto& b = m_prevNodes[i]; - - const auto delta = a->Pos() - b; - - if ( i > 0 && delta != prevDelta ) - { - refresh = true; - break; - } - - prevDelta = delta; + return false; } } - if( refresh ) - { - m_prevNodes.resize( aNodes.size() ); + return true; + } - for ( int i = 0; i < aNodes.size(); i++ ) - { - m_prevNodes[i] = aNodes[i]->Pos(); - } - - printf("need triang refresh\n"); - auto edges = hedTriangulation( aNodes ); - - m_prevEdges.resize( edges.size() ); - - int i = 0; - for ( auto e : edges ) - { - m_prevEdges[i].first = e->GetSourceNode()->Id(); - m_prevEdges[i].second = e->GetTargetNode()->Id(); - } - - } - - - #endif + const std::list computeTriangulation( std::vector& aNodes ) + { return hedTriangulation( aNodes ); } @@ -280,6 +254,7 @@ public: if( !prev || prev->Pos() != n->Pos() ) { auto tn = std::make_shared ( n->Pos().x, n->Pos().y ); + tn->SetId( id ); triNodes.push_back( tn ); } @@ -305,17 +280,22 @@ public: { return mstEdges; } - else if( triNodes.size() == 2 ) + else if( areNodesColinear( triNodes ) ) { - auto src = m_allNodes[ triNodes[0]->Id() ]; - auto dst = m_allNodes[ triNodes[1]->Id() ]; - mstEdges.emplace_back( src, dst, getDistance( src, dst ) ); + // special case: all nodes are on the same line - there's no + // triangulation for such set. In this case, we sort along any coordinate + // and chain the nodes together. + for(int i = 0; i < triNodes.size() - 1; i++ ) + { + auto src = m_allNodes[ triNodes[i]->Id() ]; + auto dst = m_allNodes[ triNodes[i + 1]->Id() ]; + mstEdges.emplace_back( src, dst, getDistance( src, dst ) ); + } } else { hed::TRIANGULATION triangulator; triangulator.CreateDelaunay( triNodes.begin(), triNodes.end() ); -// std::list edges; triangulator.GetEdges( triangEdges ); for( auto e : triangEdges )