From c31c14e46be06c640d8ffef4a4d2e6732b5fbc29 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 10 Apr 2023 22:21:20 +0100 Subject: [PATCH] Don't call BuildInitialTrace() for entry gateways. We're going to call it to connect the entry and target gateways anyway, so all we need are gateways at 22.5 degrees to setup entry at +/- 45 degrees from the current direction. Fixes https://gitlab.com/kicad/code/kicad/issues/14324 Fixes https://gitlab.com/kicad/code/kicad/issues/12459 (cherry picked from commit 507a25f1505e103309f2a5141d1ed311019f0fe2) --- pcbnew/router/pns_diff_pair.cpp | 135 +++++++++++++++----------------- 1 file changed, 62 insertions(+), 73 deletions(-) diff --git a/pcbnew/router/pns_diff_pair.cpp b/pcbnew/router/pns_diff_pair.cpp index 4a0307ee0d..88a1044975 100644 --- a/pcbnew/router/pns_diff_pair.cpp +++ b/pcbnew/router/pns_diff_pair.cpp @@ -78,6 +78,7 @@ DP_PRIMITIVE_PAIR& DP_PRIMITIVE_PAIR::operator=( const DP_PRIMITIVE_PAIR& aOther { if( aOther.m_primP ) m_primP = aOther.m_primP->Clone(); + if( aOther.m_primN ) m_primN = aOther.m_primN->Clone(); @@ -178,15 +179,15 @@ static DIRECTION_45::AngleType angle( const VECTOR2I &a, const VECTOR2I &b ) static bool checkGap( const SHAPE_LINE_CHAIN &p, const SHAPE_LINE_CHAIN &n, int gap ) { - int i, j; + SEG::ecoord gap_sq = SEG::Square( gap - 100 ); - for( i = 0; i < p.SegmentCount(); i++ ) + for( int i = 0; i < p.SegmentCount(); i++ ) { - for( j = 0; j < n.SegmentCount() ; j++ ) + for( int j = 0; j < n.SegmentCount() ; j++ ) { - int dist = p.CSegment( i ).Distance( n.CSegment( j ) ); + SEG::ecoord dist_sq = p.CSegment( i ).SquaredDistance( n.CSegment( j ) ); - if( dist < gap - 100 ) + if( dist_sq < gap_sq ) return false; } } @@ -205,10 +206,10 @@ void DP_GATEWAY::Reverse() bool DIFF_PAIR::BuildInitial( const DP_GATEWAY& aEntry, const DP_GATEWAY &aTarget, bool aPrefDiagonal ) { - SHAPE_LINE_CHAIN p = DIRECTION_45().BuildInitialTrace ( aEntry.AnchorP(), aTarget.AnchorP(), - aPrefDiagonal ); - SHAPE_LINE_CHAIN n = DIRECTION_45().BuildInitialTrace ( aEntry.AnchorN(), aTarget.AnchorN(), - aPrefDiagonal ); + SHAPE_LINE_CHAIN p = DIRECTION_45().BuildInitialTrace( aEntry.AnchorP(), aTarget.AnchorP(), + aPrefDiagonal ); + SHAPE_LINE_CHAIN n = DIRECTION_45().BuildInitialTrace( aEntry.AnchorN(), aTarget.AnchorN(), + aPrefDiagonal ); int mask = aEntry.AllowedAngles() | DIRECTION_45::ANG_STRAIGHT | DIRECTION_45::ANG_OBTUSE; @@ -239,7 +240,7 @@ bool DIFF_PAIR::BuildInitial( const DP_GATEWAY& aEntry, const DP_GATEWAY &aTarge if( aTarget.HasEntryLines() ) { - DP_GATEWAY t(aTarget) ; + DP_GATEWAY t( aTarget ); t.Reverse(); if( !CheckConnectionAngle( t.Entry(), mask ) ) @@ -252,7 +253,7 @@ bool DIFF_PAIR::BuildInitial( const DP_GATEWAY& aEntry, const DP_GATEWAY &aTarge m_p = sum_p; m_n = sum_n; - if( !checkGap ( p, n, m_gapConstraint ) ) + if( !checkGap( p, n, m_gapConstraint ) ) return false; if( p.SelfIntersecting() || n.SelfIntersecting() ) @@ -270,7 +271,9 @@ bool DIFF_PAIR::CheckConnectionAngle( const DIFF_PAIR& aOther, int aAllowedAngle bool checkP, checkN; if( m_p.SegmentCount() == 0 || aOther.m_p.SegmentCount() == 0 ) + { checkP = true; + } else { DIRECTION_45 p0( m_p.CSegment( -1 ) ); @@ -340,7 +343,6 @@ bool DP_GATEWAYS::FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool a { DP_CANDIDATE best; - int n = 0; int bestScore = -1000; bool found = false; @@ -348,26 +350,24 @@ bool DP_GATEWAYS::FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool a { for( const DP_GATEWAY& g_target : aTarget.Gateways() ) { - n++; - - for( int attempt = 0; attempt < 2; attempt++ ) + for( bool preferred : { false, true } ) { - int score = ( attempt == 1 ? -3 : 0 ); + int score = preferred ? 0 : -3; score += g_entry.Priority(); score += g_target.Priority(); - if( score < bestScore ) - continue; - - DIFF_PAIR l( m_gap ); - - if( l.BuildInitial( g_entry, g_target, - aPrefDiagonal ^ ( attempt ? true : false ) ) ) + if( score >= bestScore ) { - best.p = l.CP(); - best.n = l.CN(); - bestScore = score; - found = true; + DIFF_PAIR l( m_gap ); + + if( l.BuildInitial( g_entry, g_target, preferred ? aPrefDiagonal + : !aPrefDiagonal ) ) + { + best.p = l.CP(); + best.n = l.CN(); + bestScore = score; + found = true; + } } } } @@ -552,13 +552,13 @@ void DP_GATEWAYS::BuildForCursor( const VECTOR2I& aCursorPos ) { int gap = m_fitVias ? m_viaGap + m_viaDiameter : m_gap; - for( int attempt = 0; attempt < 2; attempt++ ) + for( bool diagonal : { false, true } ) { for( int i = 0; i < 4; i++ ) { VECTOR2I dir; - if( !attempt ) + if( !diagonal ) { dir = makeGapVector( VECTOR2I( gap, gap ), gap ); @@ -573,15 +573,13 @@ void DP_GATEWAYS::BuildForCursor( const VECTOR2I& aCursorPos ) if( i /2 == 0 ) dir = VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 ); else - dir = VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1) ); + dir = VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ) ); } if( m_fitVias ) BuildGeneric( aCursorPos + dir, aCursorPos - dir, true, true ); else - m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir, - attempt ? true : false ); - + m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir, diagonal ); } } } @@ -612,45 +610,34 @@ void DP_GATEWAYS::buildDpContinuation( const DP_PRIMITIVE_PAIR& aPair, bool aIsD if( !aPair.Directional() ) return; - DIRECTION_45 dP = aPair.DirP(); - DIRECTION_45 dN = aPair.DirN(); + // Add gateways that angle the anchor points by 22.5 degrees for connection to tracks which + // are at +/- 45 degrees from the existing direction. - int gap = ( aPair.AnchorP() - aPair.AnchorN() ).EuclideanNorm(); + auto addAngledGateways = + [&]( int length, int priority ) + { + SHAPE_LINE_CHAIN entryLineP; + entryLineP.Append( aPair.AnchorP() ); + entryLineP.Append( aPair.AnchorP() + aPair.DirP().ToVector().Resize( length ) ); + DP_GATEWAY gwExtendP( entryLineP.CLastPoint(), aPair.AnchorN(), aIsDiagonal ); + gwExtendP.SetPriority( priority ); + gwExtendP.SetEntryLines( entryLineP, SHAPE_LINE_CHAIN() ); + m_gateways.push_back( gwExtendP ); - VECTOR2I vdP = aPair.AnchorP() + dP.Left().ToVector(); - VECTOR2I vdN = aPair.AnchorN() + dN.Left().ToVector(); + SHAPE_LINE_CHAIN entryLineN; + entryLineN.Append( aPair.AnchorN() ); + entryLineN.Append( aPair.AnchorN() + aPair.DirN().ToVector().Resize( length ) ); + DP_GATEWAY gwExtendN( aPair.AnchorP(), entryLineN.CLastPoint(), aIsDiagonal ); + gwExtendN.SetPriority( priority ); + gwExtendN.SetEntryLines( SHAPE_LINE_CHAIN(), entryLineN ); + m_gateways.push_back( gwExtendN ); + }; - SEGMENT* sP = static_cast( aPair.PrimP() ); + addAngledGateways( KiROUND( (double) m_gap * 0.38268 ), 20 ); - VECTOR2I t1, t2; - - auto vL = makeGapVector( dP.Left().ToVector(), ( gap + 1 ) / 2 ); - auto vR = makeGapVector( dP.Right().ToVector(), ( gap + 1 ) / 2 ); - - if( sP->Seg().Side( vdP ) == sP->Seg().Side( vdN ) ) - { - t1 = aPair.AnchorP() + vL; - t2 = aPair.AnchorN() + vR; - } - else - { - t1 = aPair.AnchorP() + vR; - t2 = aPair.AnchorN() + vL; - } - - DP_GATEWAY gwL( t2, aPair.AnchorN(), !aIsDiagonal ); - SHAPE_LINE_CHAIN ep = dP.BuildInitialTrace( aPair.AnchorP(), t2, !aIsDiagonal ); - gwL.SetPriority( 10 ); - gwL.SetEntryLines( ep , SHAPE_LINE_CHAIN() ); - - m_gateways.push_back( gwL ); - - DP_GATEWAY gwR( aPair.AnchorP(), t1, !aIsDiagonal ); - SHAPE_LINE_CHAIN en = dP.BuildInitialTrace( aPair.AnchorN(), t1, !aIsDiagonal ); - gwR.SetPriority( 10) ; - gwR.SetEntryLines( SHAPE_LINE_CHAIN(), en ); - - m_gateways.push_back( gwR ); + // fixme; sin(22.5) doesn't always work, so we also add some lower priority ones with a bit + // of wiggle room. See https://gitlab.com/kicad/code/kicad/-/issues/12459. + addAngledGateways( KiROUND( (double) m_gap * 0.4 ), 5 ); } @@ -736,7 +723,7 @@ void DP_GATEWAYS::BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool ips[0] = st_n[i].IntersectLines( d_p[j] ); ips[1] = st_p[i].IntersectLines( d_n[j] ); -// diagonal-straight cases: 8 possibilities of "weirder" exists + // diagonal-straight cases: 8 possibilities of "weirder" exists for( int k = 0; k < 2; k++ ) { if( ips[k] ) @@ -902,8 +889,8 @@ double DIFF_PAIR::CoupledLength() const double l = 0.0; - for( unsigned int i = 0; i < pairs.size(); i++ ) - l += pairs[i].coupledP.Length(); + for( const COUPLED_SEGMENTS& pair : pairs ) + l += pair.coupledP.Length(); return l; } @@ -934,9 +921,11 @@ int DIFF_PAIR::CoupledLength ( const SEG& aP, const SEG& aN ) const SEG p_clip, n_clip; int64_t dist = std::abs( aP.Distance( aN ) - m_width ); - if( aP.ApproxParallel( aN ) && m_gapConstraint.Matches( dist ) && - commonParallelProjection ( aP, aN, p_clip, n_clip ) ) + if( aP.ApproxParallel( aN ) && m_gapConstraint.Matches( dist ) + && commonParallelProjection ( aP, aN, p_clip, n_clip ) ) + { return p_clip.Length(); + } return 0; }