KiCad PCB EDA Suite
pns_diff_pair.h
Go to the documentation of this file.
1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2015 CERN
5  * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 
23 #ifndef __PNS_DIFF_PAIR_H
24 #define __PNS_DIFF_PAIR_H
25 
26 #include <vector>
27 
28 #include "pns_line.h"
29 #include "pns_via.h"
30 #include "pns_link_holder.h"
31 
32 #include "ranged_num.h"
33 
34 namespace PNS {
35 
36 class DIFF_PAIR;
37 
45 class DP_GATEWAY {
46 public:
47  DP_GATEWAY( const VECTOR2I& aAnchorP,
48  const VECTOR2I& aAnchorN,
49  bool aIsDiagonal,
50  int aAllowedEntryAngles = DIRECTION_45::ANG_OBTUSE,
51  int aPriority = 0 )
52  : m_anchorP( aAnchorP ),
53  m_anchorN( aAnchorN ),
54  m_isDiagonal( aIsDiagonal ),
55  m_allowedEntryAngles( aAllowedEntryAngles ),
56  m_priority( aPriority )
57  {
58  m_hasEntryLines = false;
59  }
60 
62  {
63  }
64 
70  bool IsDiagonal() const
71  {
72  return m_isDiagonal;
73  }
74 
75  const VECTOR2I& AnchorP() const { return m_anchorP; }
76 
77  const VECTOR2I& AnchorN() const { return m_anchorN; }
78 
85  int AllowedAngles () const { return m_allowedEntryAngles; }
86 
92  int Priority() const
93  {
94  return m_priority;
95  }
96 
97  void SetPriority(int aPriority)
98  {
99  m_priority = aPriority;
100  }
101 
102  void SetEntryLines( const SHAPE_LINE_CHAIN& aEntryP, const SHAPE_LINE_CHAIN& aEntryN )
103  {
104  m_entryP = aEntryP;
105  m_entryN = aEntryN;
106  m_hasEntryLines = true;
107  }
108 
109  const SHAPE_LINE_CHAIN& EntryP() const { return m_entryP; }
110  const SHAPE_LINE_CHAIN& EntryN() const { return m_entryN; }
111  const DIFF_PAIR Entry() const ;
112 
113  void Reverse();
114 
115  bool HasEntryLines () const
116  {
117  return m_hasEntryLines;
118  }
119 
120 private:
127 };
128 
135 {
136 public:
138  m_primP( NULL ), m_primN( NULL ) {};
139 
140  DP_PRIMITIVE_PAIR( const DP_PRIMITIVE_PAIR& aOther );
141  DP_PRIMITIVE_PAIR( ITEM* aPrimP, ITEM* aPrimN );
142  DP_PRIMITIVE_PAIR( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
143 
145 
146  void SetAnchors( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
147 
148  const VECTOR2I& AnchorP() const { return m_anchorP; }
149  const VECTOR2I& AnchorN() const { return m_anchorN; }
150 
152 
153  ITEM* PrimP() const { return m_primP; }
154  ITEM* PrimN() const { return m_primN; }
155 
156  bool Directional() const;
157 
158  DIRECTION_45 DirP() const;
159  DIRECTION_45 DirN() const;
160 
161 
162  void CursorOrientation( const VECTOR2I& aCursorPos, VECTOR2I& aMidpoint, VECTOR2I& aDirection ) const;
163 
164  void dump()
165  {
166  printf( "-- Prim-P %p anchor [%d, %d]\n", m_primP, m_anchorP.x, m_anchorP.y );
167  printf( "-- Prim-N %p anchor [%d, %d]\n", m_primN, m_anchorN.x, m_anchorN.y );
168  }
169 
170 private:
171  DIRECTION_45 anchorDirection( const ITEM* aItem, const VECTOR2I& aP ) const;
172 
176 };
177 
185 {
186  public:
187  DP_GATEWAYS( int aGap ):
188  m_gap( aGap ),
189  m_viaGap( aGap )
190  {
191  // Do not leave unitialized members, and keep static analyser quiet:
192  m_viaDiameter = 0;
193  m_fitVias = true;
194  }
195 
196  void Clear()
197  {
198  m_gateways.clear();
199  }
200 
201  void SetFitVias( bool aEnable, int aDiameter = 0, int aViaGap = -1 )
202  {
203  m_fitVias = aEnable;
204  m_viaDiameter = aDiameter;
205 
206  if( aViaGap < 0 )
207  m_viaGap = m_gap;
208  else
209  m_viaGap = aViaGap;
210  }
211 
212 
213  void BuildForCursor( const VECTOR2I& aCursorPos );
214  void BuildOrthoProjections( DP_GATEWAYS &aEntries, const VECTOR2I& aCursorPos, int aOrthoScore );
215  void BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool aBuildEntries = false, bool aViaMode = false );
216  void BuildFromPrimitivePair( const DP_PRIMITIVE_PAIR& aPair, bool aPreferDiagonal );
217 
218  bool FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool aPrefDiagonal, DIFF_PAIR& aDp );
219 
220  std::vector<DP_GATEWAY>& Gateways()
221  {
222  return m_gateways;
223  }
224 
225  const std::vector<DP_GATEWAY>& CGateways() const
226  {
227  return m_gateways;
228  }
229 
230  void FilterByOrientation( int aAngleMask, DIRECTION_45 aRefOrientation );
231 
232  private:
234  {
237  int score;
238  };
239 
240  bool checkDiagonalAlignment( const VECTOR2I& a, const VECTOR2I& b ) const;
241  void buildDpContinuation( const DP_PRIMITIVE_PAIR& aPair, bool aIsDiagonal );
242  void buildEntries( const VECTOR2I& p0_p, const VECTOR2I& p0_n );
243 
244  int m_gap;
245  int m_viaGap;
247  bool m_fitVias;
248 
249  std::vector<DP_GATEWAY> m_gateways;
250 };
251 
252 
259 class DIFF_PAIR : public LINK_HOLDER
260 {
261 public:
263  {
264  COUPLED_SEGMENTS ( const SEG& aCoupledP, const SEG& aParentP, int aIndexP,
265  const SEG& aCoupledN, const SEG& aParentN, int aIndexN ) :
266  coupledP( aCoupledP ),
267  coupledN( aCoupledN ),
268  parentP( aParentP ),
269  parentN( aParentN ),
270  indexP( aIndexP ),
271  indexN( aIndexN )
272  {}
273 
278  int indexP;
279  int indexN;
280  };
281 
282  typedef std::vector<COUPLED_SEGMENTS> COUPLED_SEGMENTS_VEC;
283 
286  m_hasVias( false )
287  {
288  // Initialize some members, to avoid uninitialized variables.
289  m_net_p = 0;
290  m_net_n = 0;;
291  m_width = 0;
292  m_gap = 0;
293  m_viaGap = 0;
295  m_chamferLimit = 0;
296  }
297 
298  DIFF_PAIR( int aGap ) :
300  m_hasVias( false )
301  {
302  m_gapConstraint = aGap;
303 
304  // Initialize other members, to avoid uninitialized variables.
305  m_net_p = 0;
306  m_net_n = 0;;
307  m_width = 0;
308  m_gap = 0;
309  m_viaGap = 0;
311  m_chamferLimit = 0;
312  }
313 
314  DIFF_PAIR( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, int aGap = 0 ) :
316  m_n( aN ),
317  m_p( aP ),
318  m_hasVias( false )
319  {
320  m_gapConstraint = aGap;
321 
322  // Initialize other members, to avoid uninitialized variables.
323  m_net_p = 0;
324  m_net_n = 0;;
325  m_width = 0;
326  m_gap = 0;
327  m_viaGap = 0;
329  m_chamferLimit = 0;
330  }
331 
332  DIFF_PAIR( const LINE &aLineP, const LINE &aLineN, int aGap = 0 ) :
334  m_line_p( aLineP ),
335  m_line_n( aLineN ),
336  m_hasVias( false )
337  {
338  m_gapConstraint = aGap;
339  m_net_p = aLineP.Net();
340  m_net_n = aLineN.Net();
341  m_p = aLineP.CLine();
342  m_n = aLineN.CLine();
343 
344  // Do not leave unitialized members, and keep static analyser quiet:
345  m_width = 0;
346  m_gap = 0;
347  m_viaGap = 0;
349  m_chamferLimit = 0;
350  }
351 
352  static inline bool ClassOf( const ITEM* aItem )
353  {
354  return aItem && ITEM::DIFF_PAIR_T == aItem->Kind();
355  }
356 
357  DIFF_PAIR* Clone() const override { assert( false ); return NULL; }
358 
359  virtual void ClearLinks() override
360  {
361  m_links.clear();
364  }
365 
366  static DIFF_PAIR* AssembleDp( LINE *aLine );
367 
368  void SetShape( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, bool aSwapLanes = false )
369  {
370  if( aSwapLanes )
371  {
372  m_p = aN;
373  m_n = aP;
374  }
375  else
376  {
377  m_p = aP;
378  m_n = aN;
379  }
380  }
381 
382  void SetShape( const DIFF_PAIR& aPair )
383  {
384  m_p = aPair.m_p;
385  m_n = aPair.m_n;
386  }
387 
388  void SetNets( int aP, int aN )
389  {
390  m_net_p = aP;
391  m_net_n = aN;
392  }
393 
394  void SetWidth( int aWidth )
395  {
396  m_width = aWidth;
397  m_n.SetWidth( aWidth );
398  m_p.SetWidth( aWidth );
399  }
400 
401  int Width() const { return m_width; }
402 
403  void SetGap( int aGap )
404  {
405  m_gap = aGap;
406  m_gapConstraint = RANGED_NUM<int>( m_gap, 10000, 10000 );
407  }
408 
409  int Gap() const
410  {
411  return m_gap;
412  }
413 
414  void AppendVias( const VIA &aViaP, const VIA& aViaN )
415  {
416  m_hasVias = true;
417  m_via_p = aViaP;
418  m_via_n = aViaN;
419  }
420 
421  void RemoveVias()
422  {
423  m_hasVias = false;
424  }
425 
426  bool EndsWithVias() const
427  {
428  return m_hasVias;
429  }
430 
431  void SetViaDiameter( int aDiameter )
432  {
433  m_via_p.SetDiameter( aDiameter );
434  m_via_n.SetDiameter( aDiameter );
435  }
436 
437  void SetViaDrill( int aDrill )
438  {
439  m_via_p.SetDrill( aDrill );
440  m_via_n.SetDrill( aDrill );
441  }
442 
443  int NetP() const
444  {
445  return m_net_p;
446  }
447 
448  int NetN() const
449  {
450  return m_net_n;
451  }
452 
454  {
455  if( !m_line_p.IsLinked() )
457 
458  return m_line_p;
459  }
460 
462  {
463  if( !m_line_n.IsLinked() )
465 
466  return m_line_n;
467  }
468 
470 
471  double CoupledLength() const;
472  double TotalLength() const;
473  double CoupledLengthFactor() const;
474  double Skew() const;
475 
476  void CoupledSegmentPairs( COUPLED_SEGMENTS_VEC& aPairs ) const;
477 
478  void Clear()
479  {
480  m_n.Clear();
481  m_p.Clear();
482  }
483 
484  void Append( const DIFF_PAIR& aOther )
485  {
486  m_n.Append( aOther.m_n );
487  m_p.Append( aOther.m_p );
488  }
489 
490  bool Empty() const
491  {
492  return ( m_n.SegmentCount() == 0 ) || ( m_p.SegmentCount() == 0 );
493  }
494 
495  const SHAPE_LINE_CHAIN& CP() const { return m_p; }
496  const SHAPE_LINE_CHAIN& CN() const { return m_n; }
497 
498  bool BuildInitial( const DP_GATEWAY& aEntry, const DP_GATEWAY& aTarget, bool aPrefDiagonal );
499  bool CheckConnectionAngle( const DIFF_PAIR &aOther, int allowedAngles ) const;
500  int CoupledLength( const SEG& aP, const SEG& aN ) const;
501 
502  int64_t CoupledLength( const SHAPE_LINE_CHAIN& aP, const SHAPE_LINE_CHAIN& aN ) const;
503 
505  {
506  return m_gapConstraint;
507  }
508 
509 private:
510  void updateLine( LINE &aLine, const SHAPE_LINE_CHAIN& aShape, int aNet, const VIA& aVia )
511  {
512  aLine.SetShape( aShape );
513  aLine.SetWidth( m_width );
514  aLine.SetNet( aNet );
515  aLine.SetLayer( Layers().Start() );
516 
517  if( m_hasVias )
518  aLine.AppendVia( aVia );
519  }
520 
524 
525  bool m_hasVias;
527  int m_width;
528  int m_gap;
529  int m_viaGap;
533 };
534 
535 }
536 
537 #endif
DIFF_PAIR(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, int aGap=0)
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:137
Base class for PNS router board items.
Definition: pns_item.h:55
const SHAPE_LINE_CHAIN & EntryN() const
void buildEntries(const VECTOR2I &p0_p, const VECTOR2I &p0_n)
DP_PRIMITIVE_PAIR & operator=(const DP_PRIMITIVE_PAIR &aOther)
const std::vector< DP_GATEWAY > & CGateways() const
bool FitGateways(DP_GATEWAYS &aEntry, DP_GATEWAYS &aTarget, bool aPrefDiagonal, DIFF_PAIR &aDp)
void BuildForCursor(const VECTOR2I &aCursorPos)
bool Empty() const
void CoupledSegmentPairs(COUPLED_SEGMENTS_VEC &aPairs) const
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
void SetPriority(int aPriority)
Definition: pns_diff_pair.h:97
const VECTOR2I & AnchorN() const
VECTOR2I m_anchorN
int Gap() const
void SetLayer(int aLayer)
Definition: pns_item.h:153
void AppendVias(const VIA &aViaP, const VIA &aViaN)
bool EndsWithVias() const
const VECTOR2I & AnchorP() const
bool HasEntryLines() const
RANGED_NUM< int > m_gapConstraint
int Width() const
std::vector< DP_GATEWAY > m_gateways
DIRECTION_45 DirP() const
const SHAPE_LINE_CHAIN & CN() const
SHAPE_LINE_CHAIN m_entryN
void FilterByOrientation(int aAngleMask, DIRECTION_45 aRefOrientation)
std::vector< DP_GATEWAY > & Gateways()
void Append(const DIFF_PAIR &aOther)
void buildDpContinuation(const DP_PRIMITIVE_PAIR &aPair, bool aIsDiagonal)
double CoupledLength() const
void AppendVia(const VIA &aVia)
Definition: pns_line.cpp:915
DIFF_PAIR(int aGap)
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:60
bool BuildInitial(const DP_GATEWAY &aEntry, const DP_GATEWAY &aTarget, bool aPrefDiagonal)
const VECTOR2I & AnchorN() const
Definition: pns_diff_pair.h:77
void SetEntryLines(const SHAPE_LINE_CHAIN &aEntryP, const SHAPE_LINE_CHAIN &aEntryN)
VECTOR2I m_anchorP
const RANGED_NUM< int > GapConstraint() const
ITEM * PrimP() const
static bool ClassOf(const ITEM *aItem)
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void SetWidth(int aWidth)
Return line width.
Definition: pns_line.h:149
void SetNet(int aNet)
Definition: pns_item.h:147
int NetP() const
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
Definition: pns_line.h:126
void SetDiameter(int aDiameter)
Definition: pns_via.h:110
DIRECTION_45 anchorDirection(const ITEM *aItem, const VECTOR2I &aP) const
void SetWidth(int aWidth)
Sets the width of all segments in the chain.
void BuildFromPrimitivePair(const DP_PRIMITIVE_PAIR &aPair, bool aPreferDiagonal)
void SetGap(int aGap)
std::vector< COUPLED_SEGMENTS > COUPLED_SEGMENTS_VEC
#define NULL
void SetFitVias(bool aEnable, int aDiameter=0, int aViaGap=-1)
SHAPE_LINE_CHAIN m_p
int Net() const
Definition: pns_item.h:148
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:36
void updateLine(LINE &aLine, const SHAPE_LINE_CHAIN &aShape, int aNet, const VIA &aVia)
int AllowedAngles() const
Function AllowedAngles()
Definition: pns_diff_pair.h:85
SHAPE_LINE_CHAIN m_entryP
bool IsDiagonal() const
Function IsDiagonal()
Definition: pns_diff_pair.h:70
static DIFF_PAIR * AssembleDp(LINE *aLine)
void SetViaDiameter(int aDiameter)
DIRECTION_45 DirN() const
void SetWidth(int aWidth)
const SHAPE_LINE_CHAIN & EntryP() const
double Skew() const
DP_GATEWAYS(int aGap)
int SegmentCount() const
Function SegmentCount()
SHAPE_LINE_CHAIN m_n
DIFF_PAIR * Clone() const override
Return a deep copy of the item.
Definition: seg.h:41
const VECTOR2I & AnchorP() const
Definition: pns_diff_pair.h:75
DIFF_PAIR.
bool CheckConnectionAngle(const DIFF_PAIR &aOther, int allowedAngles) const
const SHAPE_LINE_CHAIN & CP() const
void BuildOrthoProjections(DP_GATEWAYS &aEntries, const VECTOR2I &aCursorPos, int aOrthoScore)
ITEM * PrimN() const
DP_PRIMITIVE_PAIR.
SHAPE_LINE_CHAIN.
double TotalLength() const
DIFF_PAIR(const LINE &aLineP, const LINE &aLineN, int aGap=0)
DP_GATEWAY(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN, bool aIsDiagonal, int aAllowedEntryAngles=DIRECTION_45::ANG_OBTUSE, int aPriority=0)
Definition: pns_diff_pair.h:47
void SetDrill(int aDrill)
Definition: pns_via.h:117
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:126
void Clear()
Function Clear() Removes all points from the line chain.
double CoupledLengthFactor() const
void CursorOrientation(const VECTOR2I &aCursorPos, VECTOR2I &aMidpoint, VECTOR2I &aDirection) const
const DIFF_PAIR Entry() const
void BuildGeneric(const VECTOR2I &p0_p, const VECTOR2I &p0_n, bool aBuildEntries=false, bool aViaMode=false)
int Priority() const
Function Priority()
Definition: pns_diff_pair.h:92
int NetN() const
DP_GATEWAYS.
void SetViaDrill(int aDrill)
Push and Shove diff pair dimensions (gap) settings dialog.
COUPLED_SEGMENTS(const SEG &aCoupledP, const SEG &aParentP, int aIndexP, const SEG &aCoupledN, const SEG &aParentN, int aIndexN)
bool checkDiagonalAlignment(const VECTOR2I &a, const VECTOR2I &b) const
void SetShape(const DIFF_PAIR &aPair)
const LAYER_RANGE & Layers() const
Definition: pns_item.h:150
DP_GATEWAY.
Definition: pns_diff_pair.h:45
DP_PRIMITIVE_PAIR EndingPrimitives()
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
virtual void ClearLinks() override
Return the number of segments that were assembled together to form this line.
void SetNets(int aP, int aN)