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 ) );
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 );
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();
498 orthoFanDistance = ( w + 1 )* 3 / 2;
499 diagFanDistance = ( w - h );
504 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported starting primitive: %d (%s)." ),
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;
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;
coord_type GetHeight() const
coord_type GetWidth() 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.
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 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.
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
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).
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)
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)
double EuclideanNorm(const VECTOR2I &vector)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).