KiCad PCB EDA Suite
drc_test_provider_diff_pair_coupling.cpp File Reference
#include <common.h>
#include <board.h>
#include <pcb_track.h>
#include <drc/drc_engine.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <drc/drc_test_provider.h>
#include <drc/drc_length_report.h>
#include <drc/drc_rtree.h>
#include <geometry/shape_segment.h>
#include <connectivity/connectivity_data.h>
#include <connectivity/from_to_cache.h>
#include <view/view_overlay.h>

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

 test
 
 detail
 

Functions

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

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 92 of file drc_test_provider_diff_pair_coupling.cpp.

93 {
94  SEG n_proj_p( p.LineProject( n.A ), p.LineProject( n.B ) );
95 
96  int64_t t_a = 0;
97  int64_t t_b = p.TCoef( p.B );
98 
99  int64_t tproj_a = p.TCoef( n_proj_p.A );
100  int64_t tproj_b = p.TCoef( n_proj_p.B );
101 
102  if( t_b < t_a )
103  std::swap( t_b, t_a );
104 
105  if( tproj_b < tproj_a )
106  std::swap( tproj_b, tproj_a );
107 
108  if( t_b <= tproj_a )
109  return false;
110 
111  if( t_a >= tproj_b )
112  return false;
113 
114  int64_t t[4] = { 0, p.TCoef( p.B ), p.TCoef( n_proj_p.A ), p.TCoef( n_proj_p.B ) };
115  std::vector<int64_t> tv( t, t + 4 );
116  std::sort( tv.begin(), tv.end() ); // fixme: awful and disgusting way of finding 2 midpoints
117 
118  int64_t pLenSq = p.SquaredLength();
119 
120  VECTOR2I dp = p.B - p.A;
121  pClip.A.x = p.A.x + rescale( (int64_t)dp.x, tv[1], pLenSq );
122  pClip.A.y = p.A.y + rescale( (int64_t)dp.y, tv[1], pLenSq );
123 
124  pClip.B.x = p.A.x + rescale( (int64_t)dp.x, tv[2], pLenSq );
125  pClip.B.y = p.A.y + rescale( (int64_t)dp.y, tv[2], pLenSq );
126 
127  nClip.A = n.LineProject( pClip.A );
128  nClip.B = n.LineProject( pClip.B );
129 
130  return true;
131 }
ecoord SquaredLength() const
Definition: seg.h:355
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:268
ecoord TCoef(const VECTOR2I &aP) const
Definition: seg.h:402
Definition: seg.h:40
VECTOR2I A
Definition: seg.h:48
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
Definition: util.h:98
VECTOR2I B
Definition: seg.h:49

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,
DRC_RTREE aTree 
)
static

Definition at line 189 of file drc_test_provider_diff_pair_coupling.cpp.

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

References SEG::A, 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, and PCB_VIA_T.

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