KiCad PCB EDA Suite
drc_test_provider_diff_pair_coupling.cpp File Reference

Go to the source code of this file.

Classes

class  test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING
 
struct  DIFF_PAIR_KEY
 
struct  DIFF_PAIR_COUPLED_SEGMENTS
 
struct  DIFF_PAIR_ITEMS
 

Namespaces

namespace  test
 
namespace  detail
 

Functions

static bool commonParallelProjection (SEG p, SEG n, SEG &pClip, SEG &nClip)
 
static void extractDiffPairCoupledItems (DIFF_PAIR_ITEMS &aDp)
 

Variables

static DRC_REGISTER_TEST_PROVIDER< test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLINGdetail::dummy
 

Function Documentation

◆ commonParallelProjection()

static bool commonParallelProjection ( SEG  p,
SEG  n,
SEG pClip,
SEG nClip 
)
static

Definition at line 83 of file drc_test_provider_diff_pair_coupling.cpp.

84{
85 SEG n_proj_p( p.LineProject( n.A ), p.LineProject( n.B ) );
86
87 int64_t t_a = 0;
88 int64_t t_b = p.TCoef( p.B );
89
90 int64_t tproj_a = p.TCoef( n_proj_p.A );
91 int64_t tproj_b = p.TCoef( n_proj_p.B );
92
93 if( t_b < t_a )
94 std::swap( t_b, t_a );
95
96 if( tproj_b < tproj_a )
97 std::swap( tproj_b, tproj_a );
98
99 if( t_b <= tproj_a )
100 return false;
101
102 if( t_a >= tproj_b )
103 return false;
104
105 int64_t t[4] = { 0, p.TCoef( p.B ), p.TCoef( n_proj_p.A ), p.TCoef( n_proj_p.B ) };
106 std::vector<int64_t> tv( t, t + 4 );
107 std::sort( tv.begin(), tv.end() ); // fixme: awful and disgusting way of finding 2 midpoints
108
109 int64_t pLenSq = p.SquaredLength();
110
111 VECTOR2I dp = p.B - p.A;
112 pClip.A.x = p.A.x + rescale( (int64_t)dp.x, tv[1], pLenSq );
113 pClip.A.y = p.A.y + rescale( (int64_t)dp.y, tv[1], pLenSq );
114
115 pClip.B.x = p.A.x + rescale( (int64_t)dp.x, tv[2], pLenSq );
116 pClip.B.y = p.A.y + rescale( (int64_t)dp.y, tv[2], pLenSq );
117
118 nClip.A = n.LineProject( pClip.A );
119 nClip.B = n.LineProject( pClip.B );
120
121 return true;
122}
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
ecoord TCoef(const VECTOR2I &aP) const
Definition: seg.h:380
ecoord SquaredLength() const
Definition: seg.h:331
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.cpp:302
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
Definition: util.h:118

References SEG::A, SEG::B, SEG::LineProject(), rescale(), SEG::SquaredLength(), SEG::TCoef(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by extractDiffPairCoupledItems().

◆ extractDiffPairCoupledItems()

static void extractDiffPairCoupledItems ( DIFF_PAIR_ITEMS aDp)
static

Definition at line 191 of file drc_test_provider_diff_pair_coupling.cpp.

192{
193 for( BOARD_CONNECTED_ITEM* itemP : aDp.itemsP )
194 {
195 PCB_TRACK* sp = dyn_cast<PCB_TRACK*>( itemP );
196 std::optional<DIFF_PAIR_COUPLED_SEGMENTS> bestCoupled;
197 int bestGap = std::numeric_limits<int>::max();
198
199 if( !sp )
200 continue;
201
202 for ( BOARD_CONNECTED_ITEM* itemN : aDp.itemsN )
203 {
204 PCB_TRACK* sn = dyn_cast<PCB_TRACK*> ( itemN );
205
206 if( !sn )
207 continue;
208
209 if( ( sn->GetLayerSet() & sp->GetLayerSet() ).none() )
210 continue;
211
212 SEG ssp ( sp->GetStart(), sp->GetEnd() );
213 SEG ssn ( sn->GetStart(), sn->GetEnd() );
214
215 // Segments that are ~ 1 IU in length per side are approximately parallel (tolerance is 1 IU)
216 // with everything and their parallel projection is < 1 IU, leading to bad distance calculations
217 if( ssp.SquaredLength() > 2 && ssn.SquaredLength() > 2 && ssp.ApproxParallel(ssn) )
218 {
220 bool coupled = commonParallelProjection( ssp, ssn, cpair.coupledP, cpair.coupledN );
221
222 if( coupled )
223 {
224 cpair.parentP = sp;
225 cpair.parentN = sn;
226 cpair.layer = sp->GetLayer();
227
228 int gap = (cpair.coupledP.A - cpair.coupledN.A).EuclideanNorm();
229 if( gap < bestGap )
230 {
231 bestGap = gap;
232 bestCoupled = cpair;
233 }
234 }
235
236 }
237 }
238
239 if( bestCoupled )
240 {
241 auto excludeSelf =
242 [&] ( BOARD_ITEM *aItem )
243 {
244 if( aItem == bestCoupled->parentN || aItem == bestCoupled->parentP )
245 {
246 return false;
247 }
248
249 if( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_VIA_T )
250 {
251 auto bci = static_cast<BOARD_CONNECTED_ITEM*>( aItem );
252
253 if( bci->GetNetCode() == bestCoupled->parentN->GetNetCode()
254 || bci->GetNetCode() == bestCoupled->parentP->GetNetCode() )
255 return false;
256 }
257
258 return true;
259 };
260
261 SHAPE_SEGMENT checkSegStart( bestCoupled->coupledP.A, bestCoupled->coupledN.A );
262 SHAPE_SEGMENT checkSegEnd( bestCoupled->coupledP.B, bestCoupled->coupledN.B );
263 DRC_RTREE* tree = bestCoupled->parentP->GetBoard()->m_CopperItemRTreeCache.get();
264
265 // check if there's anything in between the segments suspected to be coupled. If
266 // there's nothing, assume they are really coupled.
267
268 if( !tree->CheckColliding( &checkSegStart, sp->GetLayer(), 0, excludeSelf )
269 && !tree->CheckColliding( &checkSegEnd, sp->GetLayer(), 0, excludeSelf ) )
270 {
271 aDp.coupled.push_back( *bestCoupled );
272 }
273 }
274 }
275}
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:197
Implement an R-tree for fast spatial and layer indexing of connectable items.
Definition: drc_rtree.h:48
bool CheckColliding(SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
Definition: drc_rtree.h:174
const VECTOR2I & GetStart() const
Definition: pcb_track.h:113
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:110
static bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
std::set< BOARD_CONNECTED_ITEM * > itemsN
std::vector< DIFF_PAIR_COUPLED_SEGMENTS > coupled
std::set< BOARD_CONNECTED_ITEM * > itemsP
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101

References SEG::A, SEG::ApproxParallel(), DRC_RTREE::CheckColliding(), commonParallelProjection(), DIFF_PAIR_ITEMS::coupled, DIFF_PAIR_COUPLED_SEGMENTS::coupledN, DIFF_PAIR_COUPLED_SEGMENTS::coupledP, EuclideanNorm(), PCB_TRACK::GetEnd(), BOARD_ITEM::GetLayer(), BOARD_ITEM::GetLayerSet(), PCB_TRACK::GetStart(), DIFF_PAIR_ITEMS::itemsN, DIFF_PAIR_ITEMS::itemsP, DIFF_PAIR_COUPLED_SEGMENTS::layer, DIFF_PAIR_COUPLED_SEGMENTS::parentN, DIFF_PAIR_COUPLED_SEGMENTS::parentP, PCB_TRACE_T, PCB_VIA_T, and SEG::SquaredLength().

Referenced by test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run().