112 if( aItem->
Anchor( 0 ) == aP )
138 aMidpoint = ( aP + aN ) / 2;
139 aDirection = segP.
B - segP.
A;
140 aDirection = aDirection.
Resize( ( aP - aN ).EuclideanNorm() );
150 aMidpoint = ( aP + aN ) / 2;
151 aDirection = ( aP - aN ).Perpendicular();
153 if( aDirection.
Dot( aCursorPos - aMidpoint ) < 0 )
154 aDirection = -aDirection;
175 return dir_a.
Angle( dir_b );
189 if( dist < gap - 100 )
279 checkP = ( p0.
Angle( p1 ) & aAllowedAngles ) != 0;
291 checkN = ( n0.
Angle( n1 ) & aAllowedAngles ) != 0;
294 return checkP && checkN;
309 VECTOR2I midpoint( ( g.AnchorP() + g.AnchorN() ) / 2 );
310 SEG guide_s( midpoint, midpoint +
VECTOR2I( 1, 0 ) );
311 SEG guide_d( midpoint, midpoint +
VECTOR2I( 1, 1 ) );
319 VECTOR2I proj = ( dist_s < dist_d ? proj_s : proj_d );
331 t.SetPriority( aOrthoScore );
344 int bestScore = -1000;
353 for(
int attempt = 0; attempt < 2; attempt++ )
355 int score = ( attempt == 1 ? -3 : 0 );
356 score += g_entry.Priority();
357 score += g_target.Priority();
359 if( score < bestScore )
365 aPrefDiagonal ^ ( attempt ?
true :
false ) ) )
392 return (dir.
x == 0 && dir.
y != 0) || (dir.
x == dir.
y) || (dir.
y == 0 && dir.
x != 0);
400 [aAngleMask, aRefOrientation](
const DP_GATEWAY& dp)
402 DIRECTION_45 orient( dp.AnchorP() - dp.AnchorN() );
403 return ( orient.Angle( aRefOrientation ) & aAngleMask );
429 int orthoFanDistance;
431 const SHAPE* shP =
nullptr;
433 if( aPair.
PrimP() ==
nullptr )
455 majorDirection = ( p0_p - p0_n ).Perpendicular();
460 switch( shP->
Type() )
464 int w =
static_cast<const SHAPE_RECT*
>( shP )->GetWidth();
465 int h =
static_cast<const SHAPE_RECT*
>( shP )->GetHeight();
470 orthoFanDistance = ( w + 1 )* 3 / 2;
471 diagFanDistance = ( w - h );
477 int w =
static_cast<const SHAPE_SEGMENT*
>( shP )->GetWidth();
494 for(
int k = 0; k < 2; k++ )
503 int d = std::max( 0, padDist -
m_gap );
507 for(
int i = 0; i < 2; i++ )
509 int sign = i ? -1 : 1;
519 gw.SetEntryLines( entryP, entryN );
520 gw.SetPriority( 100 - k );
534 for(
int attempt = 0; attempt < 2; attempt++ )
536 for(
int i = 0; i < 4; i++ )
553 dir =
VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
555 dir =
VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1) );
559 BuildGeneric( aCursorPos + dir, aCursorPos - dir,
true,
true );
561 m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir,
562 attempt ?
true :
false );
573 if( !g.HasEntryLines() )
579 g.SetEntryLines( lead_p, lead_n );
639 SEG st_p[2], st_n[2];
642 const int padToGapThreshold = 3;
655 for(
int i = 0; i < 2; i++ )
657 bool straightColl = st_p[i].
Collinear( st_n[i] );
658 bool diagColl = d_p[i].
Collinear( d_n[i] );
660 if( straightColl || diagColl )
664 int prio = ( padDist > padToGapThreshold *
m_gap ? 2 : 1);
680 for(
int i = 0; i < 2; i++ )
682 for(
int j = 0; j < 2; j++ )
689 if( d_n[i].Collinear( d_p[j] ) )
692 if( st_p[i].Collinear( st_p[j] ) )
697 for(
int k = 0; k < 2; k++ )
703 if( m != p0_p && m != p0_n )
705 int prio = ( padDist > padToGapThreshold *
m_gap ? 10 : 20 );
706 VECTOR2I g_p( ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
707 VECTOR2I g_n( ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
709 m_gateways.emplace_back( m + g_p, m + g_n, k == 0 ?
true :
false,
719 for(
int k = 0; k < 2; k++ )
725 if( !aViaMode && m != p0_p && m != p0_n )
729 g_p = ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
730 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap ) );
733 m_gateways.emplace_back( m + g_p, m + g_n,
true );
735 g_p = ( p0_p - m ).Resize(
m_gap );
736 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
739 m_gateways.emplace_back( m + g_p, m + g_n,
true );
778 int64_t t_b = p.
TCoef( p.
B );
780 int64_t tproj_a = p.
TCoef( n_proj_p.
A );
781 int64_t tproj_b = p.
TCoef( n_proj_p.
B );
784 std::swap( t_b, t_a );
786 if( tproj_b < tproj_a )
787 std::swap( tproj_b, tproj_a );
796 std::vector<int64_t> tv( t, t + 4 );
797 std::sort( tv.begin(), tv.end() );
802 pClip.
A.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[1], pLenSq );
803 pClip.
A.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[1], pLenSq );
805 pClip.
B.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[2], pLenSq );
806 pClip.
B.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[2], pLenSq );
844 aPairs.push_back( spair );
884 for(
unsigned int i = 0; i < pairs.size(); i++ )
885 l += pairs[i].coupledP.Length();
907 return (lenN + lenP ) / 2.0;
Represent route directions & corner angles in a 45-degree metric.
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false, CORNER_MODE aMode=CORNER_MODE::MITERED_45) const
Build a 2-segment line chain between points aP0 and aP1 and following 45-degree routing regime.
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
const DIRECTION_45 Left() const
Return the direction on the left side of this (i.e.
const VECTOR2I ToVector() const
AngleType
Represent kind of angle formed by vectors heading in two DIRECTION_45s.
const DIRECTION_45 Right() const
Return the direction on the right side of this (i.e.
Basic class for a differential pair.
bool CheckConnectionAngle(const DIFF_PAIR &aOther, int allowedAngles) const
const SHAPE_LINE_CHAIN & CN() const
DP_PRIMITIVE_PAIR EndingPrimitives()
std::vector< COUPLED_SEGMENTS > COUPLED_SEGMENTS_VEC
double CoupledLength() const
bool BuildInitial(const DP_GATEWAY &aEntry, const DP_GATEWAY &aTarget, bool aPrefDiagonal)
RANGED_NUM< int > m_gapConstraint
double TotalLength() const
double CoupledLengthFactor() const
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
const SHAPE_LINE_CHAIN & CP() const
void CoupledSegmentPairs(COUPLED_SEGMENTS_VEC &aPairs) const
A set of gateways calculated for the cursor or starting/ending primitive pair.
void BuildFromPrimitivePair(const DP_PRIMITIVE_PAIR &aPair, bool aPreferDiagonal)
bool FitGateways(DP_GATEWAYS &aEntry, DP_GATEWAYS &aTarget, bool aPrefDiagonal, DIFF_PAIR &aDp)
void BuildGeneric(const VECTOR2I &p0_p, const VECTOR2I &p0_n, bool aBuildEntries=false, bool aViaMode=false)
std::vector< DP_GATEWAY > & Gateways()
bool checkDiagonalAlignment(const VECTOR2I &a, const VECTOR2I &b) const
void BuildOrthoProjections(DP_GATEWAYS &aEntries, const VECTOR2I &aCursorPos, int aOrthoScore)
void buildDpContinuation(const DP_PRIMITIVE_PAIR &aPair, bool aIsDiagonal)
std::vector< DP_GATEWAY > m_gateways
void FilterByOrientation(int aAngleMask, DIRECTION_45 aRefOrientation)
void BuildForCursor(const VECTOR2I &aCursorPos)
void buildEntries(const VECTOR2I &p0_p, const VECTOR2I &p0_n)
Define a "gateway" for routing a differential pair - e.g.
SHAPE_LINE_CHAIN m_entryP
bool HasEntryLines() const
int AllowedAngles() const
const VECTOR2I & AnchorN() const
SHAPE_LINE_CHAIN m_entryN
void SetEntryLines(const SHAPE_LINE_CHAIN &aEntryP, const SHAPE_LINE_CHAIN &aEntryN)
const VECTOR2I & AnchorP() const
const DIFF_PAIR Entry() const
void SetPriority(int aPriority)
Store starting/ending primitives (pads, vias or segments) for a differential pair.
DIRECTION_45 DirN() const
const VECTOR2I & AnchorN() const
const VECTOR2I & AnchorP() const
DIRECTION_45 anchorDirection(const ITEM *aItem, const VECTOR2I &aP) const
void CursorOrientation(const VECTOR2I &aCursorPos, VECTOR2I &aMidpoint, VECTOR2I &aDirection) const
DP_PRIMITIVE_PAIR & operator=(const DP_PRIMITIVE_PAIR &aOther)
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
DIRECTION_45 DirP() const
Base class for PNS router board items.
virtual ITEM * Clone() const =0
Return a deep copy of the item.
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
bool OfKind(int aKindMask) const
Return true if the item's type matches the mask aKindMask.
virtual VECTOR2I Anchor(int n) const
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
const SEG CSegment(int aIdx) const
Set line width.
bool Matches(const T &aOther) const
int Length() const
Return the length (this).
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
bool Collinear(const SEG &aSeg) const
Check if segment aSeg lies on the same line as (this).
ecoord TCoef(const VECTOR2I &aP) const
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
ecoord SquaredLength() const
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
SHAPE_TYPE Type() const
Return the type of the shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
const std::optional< INTERSECTION > SelfIntersecting() const
Check if the line chain is self-intersecting.
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
bool Intersects(const SHAPE_LINE_CHAIN &aChain) const
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
long long int Length() const
Return length of the line chain in Euclidean metric.
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
An abstract shape on 2D plane.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Push and Shove diff pair dimensions (gap) settings dialog.
bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
static VECTOR2I makeGapVector(VECTOR2I dir, int length)
static bool checkGap(const SHAPE_LINE_CHAIN &p, const SHAPE_LINE_CHAIN &n, int gap)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
std::optional< VECTOR2I > OPT_VECTOR2I
@ SH_RECT
axis-aligned rectangle
double EuclideanNorm(const VECTOR2I &vector)
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).