From 3a8744d0541cf3bcfb06d4d37c9dadc66ed5e556 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Tue, 27 Apr 2021 00:24:37 +0200 Subject: [PATCH] router: introduce concept of a root lines in the OPTIMIZER. By 'root lines' we mean the oldest traceable ancestor of each track moved by the router (i.e. after shoving for a while, the root of each shoved line is it's latest non-shoved version). With this we can teach the OPTIMIZER more tricks, such as the LIMIT_CORNER_COUNT constraint. It ensures the results of the optimization will not be less cornery than the original line, reducing the feeling of the optimizer being too intrusive. --- pcbnew/router/pns_optimizer.cpp | 33 ++++++++++++++++++++++++++++++++- pcbnew/router/pns_optimizer.h | 29 +++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/pcbnew/router/pns_optimizer.cpp b/pcbnew/router/pns_optimizer.cpp index 70e7e7e84b..e1da771d87 100644 --- a/pcbnew/router/pns_optimizer.cpp +++ b/pcbnew/router/pns_optimizer.cpp @@ -272,6 +272,21 @@ bool RESTRICT_VERTEX_RANGE_CONSTRAINT::Check( int aVertex1, int aVertex2, const return true; } + +bool CORNER_COUNT_LIMIT_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, + const SHAPE_LINE_CHAIN& aCurrentPath, + const SHAPE_LINE_CHAIN& aReplacement ) +{ + LINE newPath( *aOriginLine, aCurrentPath ); + newPath.Line().Replace( aVertex1, aVertex2, aReplacement ); + int cc = newPath.CountCorners( m_angleMask ); + if( cc >= m_minCorners && cc <= m_maxCorners ) + return true; + + return false; +} + + /** * Determine if a point is located within a given polygon * @@ -587,8 +602,16 @@ bool OPTIMIZER::mergeColinear( LINE* aLine ) } -bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult ) +bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult, LINE* aRoot ) { + g_dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator(); + + if( aRoot ) + { + g_dbg->AddLine( aRoot->CLine(), 3, 100000 ); + } + + if( !aResult ) { aResult = aLine; @@ -602,6 +625,14 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult ) bool hasArcs = aLine->ArcCount(); bool rv = false; + if( (m_effortLevel & LIMIT_CORNER_COUNT) && aRoot ) + { + const int angleMask = DIRECTION_45::ANG_OBTUSE; + int rootObtuseCorners = aRoot->CountCorners( angleMask ); + auto c = new CORNER_COUNT_LIMIT_CONSTRAINT( m_world, rootObtuseCorners, aLine->SegmentCount(), angleMask ); + AddConstraint( c ); + } + if( m_effortLevel & PRESERVE_VERTEX ) { auto c = new PRESERVE_VERTEX_CONSTRAINT( m_world, m_preservedVertex ); diff --git a/pcbnew/router/pns_optimizer.h b/pcbnew/router/pns_optimizer.h index f63f021527..401ba9c53f 100644 --- a/pcbnew/router/pns_optimizer.h +++ b/pcbnew/router/pns_optimizer.h @@ -104,7 +104,9 @@ public: PRESERVE_VERTEX = 0x20, RESTRICT_VERTEX_RANGE = 0x40, MERGE_COLINEAR = 0x80, ///< Merge co-linear segments - RESTRICT_AREA = 0x100 + RESTRICT_AREA = 0x100, + LIMIT_CORNER_COUNT = 0x200 ///< Do not attempt to optimize if the resulting line's + ///< corner count is outside the predefined range }; OPTIMIZER( NODE* aWorld ); @@ -114,7 +116,7 @@ public: static bool Optimize( LINE* aLine, int aEffortLevel, NODE* aWorld, const VECTOR2I aV = VECTOR2I(0, 0) ); - bool Optimize( LINE* aLine, LINE* aResult = NULL ); + bool Optimize( LINE* aLine, LINE* aResult = nullptr, LINE* aRoot = nullptr ); bool Optimize( DIFF_PAIR* aPair ); @@ -326,6 +328,29 @@ private: }; +class CORNER_COUNT_LIMIT_CONSTRAINT: public OPT_CONSTRAINT +{ +public: + CORNER_COUNT_LIMIT_CONSTRAINT( NODE* aWorld, int aMinCorners, int aMaxCorners, int aAngleMask ) : + OPT_CONSTRAINT( aWorld ), + m_minCorners( aMinCorners ), + m_maxCorners( aMaxCorners ), + m_angleMask( aAngleMask ) + { + }; + + virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine, + const SHAPE_LINE_CHAIN& aCurrentPath, + const SHAPE_LINE_CHAIN& aReplacement ) override; + +private: + int m_minCorners; + int m_maxCorners; + int m_angleMask; +}; + + + }; #endif // __PNS_OPTIMIZER_H