113 if( aItem->
Anchor( 0 ) == aP )
139 aMidpoint = ( aP + aN ) / 2;
140 aDirection = segP.
B - segP.
A;
141 aDirection = aDirection.
Resize( ( aP - aN ).EuclideanNorm() );
151 aMidpoint = ( aP + aN ) / 2;
152 aDirection = ( aP - aN ).Perpendicular();
154 if( aDirection.
Dot( aCursorPos - aMidpoint ) < 0 )
155 aDirection = -aDirection;
176 return dir_a.
Angle( dir_b );
190 if( dist_sq < gap_sq )
282 checkP = ( p0.
Angle( p1 ) & aAllowedAngles ) != 0;
294 checkN = ( n0.
Angle( n1 ) & aAllowedAngles ) != 0;
297 return checkP && checkN;
312 VECTOR2I midpoint( ( g.AnchorP() + g.AnchorN() ) / 2 );
313 SEG guide_s( midpoint, midpoint +
VECTOR2I( 1, 0 ) );
314 SEG guide_d( midpoint, midpoint +
VECTOR2I( 1, 1 ) );
319 int dist_s = ( proj_s - aCursorPos ).EuclideanNorm();
320 int dist_d = ( proj_d - aCursorPos ).EuclideanNorm();
322 VECTOR2I proj = ( dist_s < dist_d ? proj_s : proj_d );
334 t.SetPriority( aOrthoScore );
346 int bestScore = -1000;
353 for(
bool preferred : {
false,
true } )
355 int score = preferred ? 0 : -3;
356 score += g_entry.Priority();
357 score += g_target.Priority();
359 if( score >= bestScore )
363 if( l.
BuildInitial( g_entry, g_target, preferred ? aPrefDiagonal
392 return (dir.
x == 0 && dir.
y != 0) || (dir.
x == dir.
y) || (dir.
y == 0 && dir.
x != 0);
399 [aAngleMask, aRefOrientation](
const DP_GATEWAY& dp )
402 return ( orient.
Angle( aRefOrientation ) & aAngleMask );
418 }
while( ( rv * 2 ).EuclideanNorm() < length );
427 int orthoFanDistance = 0;
428 int diagFanDistance = 0;
429 const SHAPE* shP =
nullptr;
431 if( aPair.
PrimP() ==
nullptr )
455 majorDirection = ( p0_p - p0_n ).Perpendicular();
460 switch( shP->
Type() )
468 int w =
static_cast<const SHAPE_RECT*
>( shP )->GetWidth();
469 int h =
static_cast<const SHAPE_RECT*
>( shP )->GetHeight();
474 orthoFanDistance = ( w + 1 )* 3 / 2;
475 diagFanDistance = ( w - h );
481 int w =
static_cast<const SHAPE_SEGMENT*
>( shP )->GetWidth();
484 orthoFanDistance = w + ( s.
B - s.
A ).EuclideanNorm();
485 diagFanDistance = ( s.
B - s.
A ).EuclideanNorm();
499 orthoFanDistance = ( w + 1 )* 3 / 2;
500 diagFanDistance = ( w - h );
505 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported starting primitive: %d (%s)." ),
513 int padDist = ( p0_p - p0_n ).EuclideanNorm();
515 for(
int k = 0; k < 2; k++ )
524 int d = std::max( 0, padDist -
m_gap );
528 for(
int i = 0; i < 2; i++ )
530 int sign = i ? -1 : 1;
540 gw.SetEntryLines( entryP, entryN );
541 gw.SetPriority( 100 - k );
555 for(
bool diagonal : {
false,
true } )
557 for(
int i = 0; i < 4; i++ )
574 dir =
VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
576 dir =
VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ) );
580 BuildGeneric( aCursorPos + dir, aCursorPos - dir,
true,
true );
582 m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir, diagonal );
592 if( !g.HasEntryLines() )
598 g.SetEntryLines( lead_p, lead_n );
618 double SIN_22_5 = 0.38268;
619 double SIN_23_5 = 0.39875;
621 auto addAngledGateways =
622 [&](
int length,
int priority )
645 addAngledGateways(
KiROUND( (
double)
m_gap * SIN_22_5 ), 20 );
649 addAngledGateways(
KiROUND( (
double)
m_gap * SIN_23_5 ), 5 );
657 SEG st_p[2], st_n[2];
660 const int padToGapThreshold = 3;
661 int padDist = ( p0_n - p0_p ).EuclideanNorm();
673 for(
int i = 0; i < 2; i++ )
675 bool straightColl = st_p[i].
Collinear( st_n[i] );
676 bool diagColl = d_p[i].
Collinear( d_n[i] );
678 if( straightColl || diagColl )
682 int prio = ( padDist > padToGapThreshold *
m_gap ) ? 2 : 1;
698 for(
int i = 0; i < 2; i++ )
700 for(
int j = 0; j < 2; j++ )
707 if( d_n[i].Collinear( d_p[j] ) )
710 if( st_p[i].Collinear( st_p[j] ) )
715 for(
int k = 0; k < 2; k++ )
721 if( m != p0_p && m != p0_n )
723 int prio = ( padDist > padToGapThreshold *
m_gap ? 10 : 20 );
724 VECTOR2I g_p( ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
725 VECTOR2I g_n( ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
727 m_gateways.emplace_back( m + g_p, m + g_n, k == 0 ?
true :
false,
737 for(
int k = 0; k < 2; k++ )
743 if( !aViaMode && m != p0_p && m != p0_n )
747 g_p = ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
748 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap ) );
751 m_gateways.emplace_back( m + g_p, m + g_n,
true );
753 g_p = ( p0_p - m ).Resize(
m_gap );
754 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
757 m_gateways.emplace_back( m + g_p, m + g_n,
true );
796 int64_t t_b = p.
TCoef( p.
B );
798 int64_t tproj_a = p.
TCoef( n_proj_p.
A );
799 int64_t tproj_b = p.
TCoef( n_proj_p.
B );
802 std::swap( t_b, t_a );
804 if( tproj_b < tproj_a )
805 std::swap( tproj_b, tproj_a );
814 std::vector<int64_t> tv( t, t + 4 );
815 std::sort( tv.begin(), tv.end() );
820 pClip.
A.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[1], pLenSq );
821 pClip.
A.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[1], pLenSq );
823 pClip.
B.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[2], pLenSq );
824 pClip.
B.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[2], pLenSq );
862 aPairs.push_back( spair );
903 l += pair.coupledP.Length();
925 return (lenN + lenP ) / 2.0;
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
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 VECTOR2I ToVector() const
AngleType
Represent kind of angle formed by vectors heading in two DIRECTION_45s.
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 const SHAPE * Shape(int aLayer) const
Return the geometrical shape of the item.
virtual ITEM * Clone() const =0
Return a deep copy of the item.
bool OfKind(int aKindMask) const
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
ecoord SquaredDistance(const SEG &aSeg) const
VECTOR2I::extended_type ecoord
int Length() const
Return the length (this).
static SEG::ecoord Square(int a)
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.
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.
bool Intersects(const SHAPE_LINE_CHAIN &aChain) const
void Simplify(int aMaxError=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
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 VECTOR2I & CLastPoint() const
Return the last point in the 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.
An abstract shape on 2D plane.
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
constexpr 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)
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
std::optional< VECTOR2I > OPT_VECTOR2I
@ SH_RECT
axis-aligned rectangle
@ SH_SIMPLE
simple polygon
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
constexpr int sign(T val)
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
VECTOR2< int32_t > VECTOR2I