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 507a25f150)
This commit is contained in:
Jeff Young 2023-04-10 22:21:20 +01:00
parent 349dbb98a6
commit c31c14e46b
1 changed files with 62 additions and 73 deletions

View File

@ -78,6 +78,7 @@ DP_PRIMITIVE_PAIR& DP_PRIMITIVE_PAIR::operator=( const DP_PRIMITIVE_PAIR& aOther
{ {
if( aOther.m_primP ) if( aOther.m_primP )
m_primP = aOther.m_primP->Clone(); m_primP = aOther.m_primP->Clone();
if( aOther.m_primN ) if( aOther.m_primN )
m_primN = aOther.m_primN->Clone(); 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 ) 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; return false;
} }
} }
@ -270,7 +271,9 @@ bool DIFF_PAIR::CheckConnectionAngle( const DIFF_PAIR& aOther, int aAllowedAngle
bool checkP, checkN; bool checkP, checkN;
if( m_p.SegmentCount() == 0 || aOther.m_p.SegmentCount() == 0 ) if( m_p.SegmentCount() == 0 || aOther.m_p.SegmentCount() == 0 )
{
checkP = true; checkP = true;
}
else else
{ {
DIRECTION_45 p0( m_p.CSegment( -1 ) ); 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; DP_CANDIDATE best;
int n = 0;
int bestScore = -1000; int bestScore = -1000;
bool found = false; bool found = false;
@ -348,21 +350,18 @@ bool DP_GATEWAYS::FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool a
{ {
for( const DP_GATEWAY& g_target : aTarget.Gateways() ) for( const DP_GATEWAY& g_target : aTarget.Gateways() )
{ {
n++; for( bool preferred : { false, true } )
for( int attempt = 0; attempt < 2; attempt++ )
{ {
int score = ( attempt == 1 ? -3 : 0 ); int score = preferred ? 0 : -3;
score += g_entry.Priority(); score += g_entry.Priority();
score += g_target.Priority(); score += g_target.Priority();
if( score < bestScore ) if( score >= bestScore )
continue; {
DIFF_PAIR l( m_gap ); DIFF_PAIR l( m_gap );
if( l.BuildInitial( g_entry, g_target, if( l.BuildInitial( g_entry, g_target, preferred ? aPrefDiagonal
aPrefDiagonal ^ ( attempt ? true : false ) ) ) : !aPrefDiagonal ) )
{ {
best.p = l.CP(); best.p = l.CP();
best.n = l.CN(); best.n = l.CN();
@ -372,6 +371,7 @@ bool DP_GATEWAYS::FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool a
} }
} }
} }
}
if( found ) if( found )
@ -552,13 +552,13 @@ void DP_GATEWAYS::BuildForCursor( const VECTOR2I& aCursorPos )
{ {
int gap = m_fitVias ? m_viaGap + m_viaDiameter : m_gap; 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++ ) for( int i = 0; i < 4; i++ )
{ {
VECTOR2I dir; VECTOR2I dir;
if( !attempt ) if( !diagonal )
{ {
dir = makeGapVector( VECTOR2I( gap, gap ), gap ); dir = makeGapVector( VECTOR2I( gap, gap ), gap );
@ -579,9 +579,7 @@ void DP_GATEWAYS::BuildForCursor( const VECTOR2I& aCursorPos )
if( m_fitVias ) if( m_fitVias )
BuildGeneric( aCursorPos + dir, aCursorPos - dir, true, true ); BuildGeneric( aCursorPos + dir, aCursorPos - dir, true, true );
else else
m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir, m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir, diagonal );
attempt ? true : false );
} }
} }
} }
@ -612,45 +610,34 @@ void DP_GATEWAYS::buildDpContinuation( const DP_PRIMITIVE_PAIR& aPair, bool aIsD
if( !aPair.Directional() ) if( !aPair.Directional() )
return; return;
DIRECTION_45 dP = aPair.DirP(); // Add gateways that angle the anchor points by 22.5 degrees for connection to tracks which
DIRECTION_45 dN = aPair.DirN(); // are at +/- 45 degrees from the existing direction.
int gap = ( aPair.AnchorP() - aPair.AnchorN() ).EuclideanNorm(); auto addAngledGateways =
[&]( int length, int priority )
VECTOR2I vdP = aPair.AnchorP() + dP.Left().ToVector();
VECTOR2I vdN = aPair.AnchorN() + dN.Left().ToVector();
SEGMENT* sP = static_cast<SEGMENT*>( aPair.PrimP() );
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; SHAPE_LINE_CHAIN entryLineP;
t2 = aPair.AnchorN() + vR; entryLineP.Append( aPair.AnchorP() );
} entryLineP.Append( aPair.AnchorP() + aPair.DirP().ToVector().Resize( length ) );
else DP_GATEWAY gwExtendP( entryLineP.CLastPoint(), aPair.AnchorN(), aIsDiagonal );
{ gwExtendP.SetPriority( priority );
t1 = aPair.AnchorP() + vR; gwExtendP.SetEntryLines( entryLineP, SHAPE_LINE_CHAIN() );
t2 = aPair.AnchorN() + vL; m_gateways.push_back( gwExtendP );
}
DP_GATEWAY gwL( t2, aPair.AnchorN(), !aIsDiagonal ); SHAPE_LINE_CHAIN entryLineN;
SHAPE_LINE_CHAIN ep = dP.BuildInitialTrace( aPair.AnchorP(), t2, !aIsDiagonal ); entryLineN.Append( aPair.AnchorN() );
gwL.SetPriority( 10 ); entryLineN.Append( aPair.AnchorN() + aPair.DirN().ToVector().Resize( length ) );
gwL.SetEntryLines( ep , SHAPE_LINE_CHAIN() ); DP_GATEWAY gwExtendN( aPair.AnchorP(), entryLineN.CLastPoint(), aIsDiagonal );
gwExtendN.SetPriority( priority );
gwExtendN.SetEntryLines( SHAPE_LINE_CHAIN(), entryLineN );
m_gateways.push_back( gwExtendN );
};
m_gateways.push_back( gwL ); addAngledGateways( KiROUND( (double) m_gap * 0.38268 ), 20 );
DP_GATEWAY gwR( aPair.AnchorP(), t1, !aIsDiagonal ); // fixme; sin(22.5) doesn't always work, so we also add some lower priority ones with a bit
SHAPE_LINE_CHAIN en = dP.BuildInitialTrace( aPair.AnchorN(), t1, !aIsDiagonal ); // of wiggle room. See https://gitlab.com/kicad/code/kicad/-/issues/12459.
gwR.SetPriority( 10) ; addAngledGateways( KiROUND( (double) m_gap * 0.4 ), 5 );
gwR.SetEntryLines( SHAPE_LINE_CHAIN(), en );
m_gateways.push_back( gwR );
} }
@ -902,8 +889,8 @@ double DIFF_PAIR::CoupledLength() const
double l = 0.0; double l = 0.0;
for( unsigned int i = 0; i < pairs.size(); i++ ) for( const COUPLED_SEGMENTS& pair : pairs )
l += pairs[i].coupledP.Length(); l += pair.coupledP.Length();
return l; return l;
} }
@ -934,9 +921,11 @@ int DIFF_PAIR::CoupledLength ( const SEG& aP, const SEG& aN ) const
SEG p_clip, n_clip; SEG p_clip, n_clip;
int64_t dist = std::abs( aP.Distance( aN ) - m_width ); int64_t dist = std::abs( aP.Distance( aN ) - m_width );
if( aP.ApproxParallel( aN ) && m_gapConstraint.Matches( dist ) && if( aP.ApproxParallel( aN ) && m_gapConstraint.Matches( dist )
commonParallelProjection ( aP, aN, p_clip, n_clip ) ) && commonParallelProjection ( aP, aN, p_clip, n_clip ) )
{
return p_clip.Length(); return p_clip.Length();
}
return 0; return 0;
} }