115 if( aItem->
Anchor( 0 ) == aP )
141 aMidpoint = ( aP + aN ) / 2;
142 aDirection = segP.
B - segP.
A;
143 aDirection = aDirection.
Resize( ( aP - aN ).EuclideanNorm() );
153 aMidpoint = ( aP + aN ) / 2;
154 aDirection = ( aP - aN ).Perpendicular();
156 if( aDirection.
Dot( aCursorPos - aMidpoint ) < 0 )
157 aDirection = -aDirection;
178 return dir_a.
Angle( dir_b );
192 if( dist_sq < gap_sq )
277 checkP = ( p0.
Angle( p1 ) & aAllowedAngles ) != 0;
289 checkN = ( n0.
Angle( n1 ) & aAllowedAngles ) != 0;
292 return checkP && checkN;
307 VECTOR2I midpoint( ( g.AnchorP() + g.AnchorN() ) / 2 );
308 SEG guide_s( midpoint, midpoint +
VECTOR2I( 1, 0 ) );
309 SEG guide_d( midpoint, midpoint +
VECTOR2I( 1, 1 ) );
314 int dist_s = ( proj_s - aCursorPos ).EuclideanNorm();
315 int dist_d = ( proj_d - aCursorPos ).EuclideanNorm();
317 VECTOR2I proj = ( dist_s < dist_d ? proj_s : proj_d );
329 t.SetPriority( aOrthoScore );
341 int bestScore = -1000;
348 for(
bool preferred : {
false,
true } )
350 int score = preferred ? 0 : -3;
351 score += g_entry.Priority();
352 score += g_target.Priority();
354 if( score >= bestScore )
358 if( l.
BuildInitial( g_entry, g_target, preferred ? aPrefDiagonal
387 return (dir.
x == 0 && dir.
y != 0) || (dir.
x == dir.
y) || (dir.
y == 0 && dir.
x != 0);
394 [aAngleMask, aRefOrientation](
const DP_GATEWAY& dp )
397 return ( orient.
Angle( aRefOrientation ) & aAngleMask );
413 }
while( ( rv * 2 ).EuclideanNorm() < length );
422 int orthoFanDistance = 0;
423 int diagFanDistance = 0;
424 const SHAPE* shP =
nullptr;
426 if( aPair.
PrimP() ==
nullptr )
450 majorDirection = ( p0_p - p0_n ).Perpendicular();
455 switch( shP->
Type() )
463 int w =
static_cast<const SHAPE_RECT*
>( shP )->GetWidth();
464 int h =
static_cast<const SHAPE_RECT*
>( shP )->GetHeight();
469 orthoFanDistance = ( w + 1 )* 3 / 2;
470 diagFanDistance = ( w - h );
476 int w =
static_cast<const SHAPE_SEGMENT*
>( shP )->GetWidth();
479 orthoFanDistance = w + ( s.
B - s.
A ).EuclideanNorm();
480 diagFanDistance = ( s.
B - s.
A ).EuclideanNorm();
494 orthoFanDistance = ( w + 1 )* 3 / 2;
495 diagFanDistance = ( w - h );
500 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported starting primitive: %d (%s)." ),
508 int padDist = ( p0_p - p0_n ).EuclideanNorm();
510 for(
int k = 0; k < 2; k++ )
519 int d = std::max( 0, padDist -
m_gap );
523 for(
int i = 0; i < 2; i++ )
525 int sign = i ? -1 : 1;
535 gw.SetEntryLines( entryP, entryN );
536 gw.SetPriority( 100 - k );
550 for(
bool diagonal : {
false,
true } )
552 for(
int i = 0; i < 4; i++ )
569 dir =
VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
571 dir =
VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ) );
575 BuildGeneric( aCursorPos + dir, aCursorPos - dir,
true,
true );
577 m_gateways.emplace_back( aCursorPos + dir, aCursorPos - dir, diagonal );
587 if( !g.HasEntryLines() )
593 g.SetEntryLines( lead_p, lead_n );
613 double SIN_22_5 = 0.38268;
614 double SIN_23_5 = 0.39875;
616 auto addAngledGateways =
617 [&](
int length,
int priority )
640 addAngledGateways(
KiROUND( (
double)
m_gap * SIN_22_5 ), 20 );
644 addAngledGateways(
KiROUND( (
double)
m_gap * SIN_23_5 ), 5 );
652 SEG st_p[2], st_n[2];
655 const int padToGapThreshold = 3;
656 int padDist = ( p0_n - p0_p ).EuclideanNorm();
668 for(
int i = 0; i < 2; i++ )
670 bool straightColl = st_p[i].
Collinear( st_n[i] );
671 bool diagColl = d_p[i].
Collinear( d_n[i] );
673 if( straightColl || diagColl )
677 int prio = ( padDist > padToGapThreshold *
m_gap ) ? 2 : 1;
693 for(
int i = 0; i < 2; i++ )
695 for(
int j = 0; j < 2; j++ )
702 if( d_n[i].Collinear( d_p[j] ) )
705 if( st_p[i].Collinear( st_p[j] ) )
710 for(
int k = 0; k < 2; k++ )
716 if( m != p0_p && m != p0_n )
718 int prio = ( padDist > padToGapThreshold *
m_gap ? 10 : 20 );
719 VECTOR2I g_p( ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
720 VECTOR2I g_n( ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT1_2 ) ) );
722 m_gateways.emplace_back( m + g_p, m + g_n, k == 0 ?
true :
false,
732 for(
int k = 0; k < 2; k++ )
738 if( !aViaMode && m != p0_p && m != p0_n )
742 g_p = ( p0_p - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
743 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap ) );
746 m_gateways.emplace_back( m + g_p, m + g_n,
true );
748 g_p = ( p0_p - m ).Resize(
m_gap );
749 g_n = ( p0_n - m ).Resize( ceil( (
double)
m_gap * M_SQRT2 ) );
752 m_gateways.emplace_back( m + g_p, m + g_n,
true );
791 int64_t t_b = p.
TCoef( p.
B );
793 int64_t tproj_a = p.
TCoef( n_proj_p.
A );
794 int64_t tproj_b = p.
TCoef( n_proj_p.
B );
797 std::swap( t_b, t_a );
799 if( tproj_b < tproj_a )
800 std::swap( tproj_b, tproj_a );
809 std::vector<int64_t> tv( t, t + 4 );
810 std::sort( tv.begin(), tv.end() );
815 pClip.
A.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[1], pLenSq );
816 pClip.
A.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[1], pLenSq );
818 pClip.
B.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[2], pLenSq );
819 pClip.
B.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[2], pLenSq );
857 aPairs.push_back( spair );
898 l += pair.coupledP.Length();
920 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.
void Simplify(int aTolerance=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.
bool Intersects(const SEG &aSeg) 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 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)
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