From f5fe1d5462001776bc9ebce8ea85836647d29519 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Thu, 9 Jun 2022 20:51:14 +0200 Subject: [PATCH] router: another attempt at improving 'kink' robustness of the hull generator --- pcbnew/router/pns_utils.cpp | 74 +++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/pcbnew/router/pns_utils.cpp b/pcbnew/router/pns_utils.cpp index 9391f21c49..dcdfeed9f2 100644 --- a/pcbnew/router/pns_utils.cpp +++ b/pcbnew/router/pns_utils.cpp @@ -23,6 +23,7 @@ #include "pns_line.h" #include "pns_via.h" #include "pns_router.h" +#include "pns_debug_decorator.h" #include #include @@ -143,18 +144,20 @@ const SHAPE_LINE_CHAIN ArcHull( const SHAPE_ARC& aSeg, int aClearance, int aWalk static bool IsSegment45Degree( const SEG& aS ) { - double angle = 180.0 / M_PI - * atan2( (double) aS.B.y - (double) aS.A.y, (double) aS.B.x - (double) aS.A.x ); + VECTOR2I dir( aS.B - aS.A ); - if( angle < 0 ) - angle += 360.0; + if( std::abs( dir.x ) <= 1 ) + return true; + + if( std::abs( dir.y ) <= 1 ) + return true; + + int delta = std::abs(dir.x) - std::abs(dir.y); - double angle_a = fabs( fmod( angle, 45.0 ) ); + if( delta >= -1 && delta <= 1) + return true; - if( angle_a > 1.0 && angle_a < 44.0 ) - return false; - - return true; + return false; } @@ -166,7 +169,7 @@ template int sgn(T val) { const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance, int aWalkaroundThickness ) { - const int kinkThreshold = 10; + const int kinkThreshold = aClearance / 10; int cl = aClearance + aWalkaroundThickness / 2; double d = (double)aSeg.GetWidth() / 2.0 + cl; @@ -178,15 +181,56 @@ const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance, const VECTOR2I a = aSeg.GetSeg().A; VECTOR2I b = aSeg.GetSeg().B; int len = aSeg.GetSeg().Length(); + int w = b.x - a.x; + int h = b.y - a.y; - if ( !IsSegment45Degree( aSeg.GetSeg() ) && len <= kinkThreshold && len > 0 ) + /* + auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator(); + + if( len < kinkThreshold ) { + PNS_DBG( dbg, AddShape, &aSeg, CYAN, 10000, wxString::Format( "kinky-seg 45 %d l %d dx %d dy %d", !!IsSegment45Degree( aSeg.GetSeg() ), len, w, h ) ); + } + */ - int w = b.x - a.x; - int h = b.y - a.y; - int ll = std::max( std::abs( w ), std::abs( h ) ); + if ( !IsSegment45Degree( aSeg.GetSeg() ) ) + { + if ( len <= kinkThreshold && len > 0 ) + { + int ll = std::max( std::abs( w ), std::abs( h ) ); - b = a + VECTOR2I( sgn( w ) * ll, sgn( h ) * ll ); + b = a + VECTOR2I( sgn( w ) * ll, sgn( h ) * ll ); + } + } + else + { + if( len <= kinkThreshold ) + { + int delta45 = std::abs( std::abs(w) - std::abs(h) ); + if( std::abs(w) <= 1 ) // almost vertical + { + w = 0; + cl ++; + } + else if ( std::abs(h) <= 1 ) // almost horizontal + { + h = 0; + cl ++; + } + else if ( delta45 <= 2 ) // almost 45 degree + { + int newW = sgn( w ) * std::max( std::abs(w), std::abs( h ) ); + int newH = sgn( h ) * std::max( std::abs(w), std::abs( h ) ); + w = newW; + h = newH; + cl += 2; + //PNS_DBG( dbg, AddShape, &aSeg, CYAN, 10000, wxString::Format( "almostkinky45 45 %d l %d dx %d dy %d", !!IsSegment45Degree( aSeg.GetSeg() ), len, w, h ) ); + + } + + b.x = a.x + w; + b.y = a.y + h; + } } if( a == b )