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 )
454 majorDirection = ( p0_p - p0_n ).Perpendicular();
459 switch( shP->
Type() )
467 int w =
static_cast<const SHAPE_RECT*
>( shP )->GetWidth();
468 int h =
static_cast<const SHAPE_RECT*
>( shP )->GetHeight();
473 orthoFanDistance = ( w + 1 )* 3 / 2;
474 diagFanDistance = ( w - h );
480 int w =
static_cast<const SHAPE_SEGMENT*
>( shP )->GetWidth();
483 orthoFanDistance = w + ( s.
B - s.
A ).EuclideanNorm();
484 diagFanDistance = ( s.
B - s.
A ).EuclideanNorm();
498 orthoFanDistance = ( w + 1 )* 3 / 2;
499 diagFanDistance = ( w - h );
504 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported starting primitive: %d (%s)." ),
512 int padDist = ( p0_p - p0_n ).EuclideanNorm();
514 for(
int k = 0; k < 2; k++ )
523 int d = std::max( 0, padDist -
m_gap );
527 for(
int i = 0; i < 2; i++ )
529 int sign = i ? -1 : 1;
539 gw.SetEntryLines( entryP, entryN );
540 gw.SetPriority( 100 - k );
554 for(
bool diagonal : {
false,
true } )
556 for(
int i = 0; i < 4; i++ )
573 dir =
VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
575 dir =
VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ) );
579 BuildGeneric( aCursorPos + dir, aCursorPos - dir,
true,
true );
581 m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir, diagonal );
591 if( !g.HasEntryLines() )
597 g.SetEntryLines( lead_p, lead_n );
617 double SIN_22_5 = 0.38268;
618 double SIN_23_5 = 0.39875;
620 auto addAngledGateways =
621 [&](
int length,
int priority )
644 addAngledGateways(
KiROUND( (
double)
m_gap * SIN_22_5 ), 20 );
648 addAngledGateways(
KiROUND( (
double)
m_gap * SIN_23_5 ), 5 );
656 SEG st_p[2], st_n[2];
659 const int padToGapThreshold = 3;
660 int padDist = ( p0_n - p0_p ).EuclideanNorm();
672 for(
int i = 0; i < 2; i++ )
674 bool straightColl = st_p[i].
Collinear( st_n[i] );
675 bool diagColl = d_p[i].
Collinear( d_n[i] );
677 if( straightColl || diagColl )
681 int prio = ( padDist > padToGapThreshold *
m_gap ) ? 2 : 1;
697 for(
int i = 0; i < 2; i++ )
699 for(
int j = 0; j < 2; j++ )
706 if( d_n[i].Collinear( d_p[j] ) )
709 if( st_p[i].Collinear( st_p[j] ) )
714 for(
int k = 0; k < 2; k++ )
720 if( m != p0_p && m != p0_n )
722 int prio = ( padDist > padToGapThreshold *
m_gap ? 10 : 20 );
723 VECTOR2I g_p( ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
724 VECTOR2I g_n( ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
726 m_gateways.emplace_back( m + g_p, m + g_n, k == 0 ?
true :
false,
736 for(
int k = 0; k < 2; k++ )
742 if( !aViaMode && m != p0_p && m != p0_n )
746 g_p = ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
747 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap ) );
750 m_gateways.emplace_back( m + g_p, m + g_n,
true );
752 g_p = ( p0_p - m ).Resize(
m_gap );
753 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
756 m_gateways.emplace_back( m + g_p, m + g_n,
true );
795 int64_t t_b = p.
TCoef( p.
B );
797 int64_t tproj_a = p.
TCoef( n_proj_p.
A );
798 int64_t tproj_b = p.
TCoef( n_proj_p.
B );
801 std::swap( t_b, t_a );
803 if( tproj_b < tproj_a )
804 std::swap( tproj_b, tproj_a );
813 std::vector<int64_t> tv( t, t + 4 );
814 std::sort( tv.begin(), tv.end() );
819 pClip.
A.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[1], pLenSq );
820 pClip.
A.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[1], pLenSq );
822 pClip.
B.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[2], pLenSq );
823 pClip.
B.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[2], pLenSq );
861 aPairs.push_back( spair );
902 l += pair.coupledP.Length();
924 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 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
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