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 <geometry/shape.h>
30 
31 #include "pns_line.h"
32 #include "pns_via.h"
33 #include "pns_link_holder.h"
34 
35 #include "ranged_num.h"
36 
37 namespace PNS {
38 
39 class DIFF_PAIR;
40 
48 class DP_GATEWAY {
49 public:
50  DP_GATEWAY( const VECTOR2I& aAnchorP,
51  const VECTOR2I& aAnchorN,
52  bool aIsDiagonal,
53  int aAllowedEntryAngles = DIRECTION_45::ANG_OBTUSE,
54  int aPriority = 0 )
55  : m_anchorP( aAnchorP ),
56  m_anchorN( aAnchorN ),
57  m_isDiagonal( aIsDiagonal ),
58  m_allowedEntryAngles( aAllowedEntryAngles ),
59  m_priority( aPriority )
60  {
61  m_hasEntryLines = false;
62  }
63 
65  {
66  }
67 
73  bool IsDiagonal() const
74  {
75  return m_isDiagonal;
76  }
77 
78  const VECTOR2I& AnchorP() const { return m_anchorP; }
79 
80  const VECTOR2I& AnchorN() const { return m_anchorN; }
81 
88  int AllowedAngles () const { return m_allowedEntryAngles; }
89 
95  int Priority() const
96  {
97  return m_priority;
98  }
99 
100  void SetPriority(int aPriority)
101  {
102  m_priority = aPriority;
103  }
104 
105  void SetEntryLines( const SHAPE_LINE_CHAIN& aEntryP, const SHAPE_LINE_CHAIN& aEntryN )
106  {
107  m_entryP = aEntryP;
108  m_entryN = aEntryN;
109  m_hasEntryLines = true;
110  }
111 
112  const SHAPE_LINE_CHAIN& EntryP() const { return m_entryP; }
113  const SHAPE_LINE_CHAIN& EntryN() const { return m_entryN; }
114  const DIFF_PAIR Entry() const ;
115 
116  void Reverse();
117 
118  bool HasEntryLines () const
119  {
120  return m_hasEntryLines;
121  }
122 
123 private:
130 };
131 
138 {
139 public:
141  m_primP( NULL ), m_primN( NULL ) {};
142 
143  DP_PRIMITIVE_PAIR( const DP_PRIMITIVE_PAIR& aOther );
144  DP_PRIMITIVE_PAIR( ITEM* aPrimP, ITEM* aPrimN );
145  DP_PRIMITIVE_PAIR( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
146 
148 
149  void SetAnchors( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
150 
151  const VECTOR2I& AnchorP() const { return m_anchorP; }
152  const VECTOR2I& AnchorN() const { return m_anchorN; }
153 
155 
156  ITEM* PrimP() const { return m_primP; }
157  ITEM* PrimN() const { return m_primN; }
158 
159  bool Directional() const;
160 
161  DIRECTION_45 DirP() const;
162  DIRECTION_45 DirN() const;
163 
164 
165  void CursorOrientation( const VECTOR2I& aCursorPos, VECTOR2I& aMidpoint, VECTOR2I& aDirection ) const;
166 
167  void dump()
168  {
169  printf( "-- Prim-P %p anchor [%d, %d]\n", m_primP, m_anchorP.x, m_anchorP.y );
170  printf( "-- Prim-N %p anchor [%d, %d]\n", m_primN, m_anchorN.x, m_anchorN.y );
171  }
172 
173 private:
174  DIRECTION_45 anchorDirection( const ITEM* aItem, const VECTOR2I& aP ) const;
175 
179 };
180 
188 {
189  public:
190  DP_GATEWAYS( int aGap ):
191  m_gap( aGap ),
192  m_viaGap( aGap )
193  {
194  // Do not leave unitialized members, and keep static analyser quiet:
195  m_viaDiameter = 0;
196  m_fitVias = true;
197  }
198 
199  void Clear()
200  {
201  m_gateways.clear();
202  }
203 
204  void SetFitVias( bool aEnable, int aDiameter = 0, int aViaGap = -1 )
205  {
206  m_fitVias = aEnable;
207  m_viaDiameter = aDiameter;
208 
209  if( aViaGap < 0 )
210  m_viaGap = m_gap;
211  else
212  m_viaGap = aViaGap;
213  }
214 
215 
216  void BuildForCursor( const VECTOR2I& aCursorPos );
217  void BuildOrthoProjections( DP_GATEWAYS &aEntries, const VECTOR2I& aCursorPos, int aOrthoScore );
218  void BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool aBuildEntries = false, bool aViaMode = false );
219  void BuildFromPrimitivePair( const DP_PRIMITIVE_PAIR& aPair, bool aPreferDiagonal );
220 
221  bool FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool aPrefDiagonal, DIFF_PAIR& aDp );
222 
223  std::vector<DP_GATEWAY>& Gateways()
224  {
225  return m_gateways;
226  }
227 
228  const std::vector<DP_GATEWAY>& CGateways() const
229  {
230  return m_gateways;
231  }
232 
233  void FilterByOrientation( int aAngleMask, DIRECTION_45 aRefOrientation );
234 
235  private:
237  {
240  int score;
241  };
242 
243  bool checkDiagonalAlignment( const VECTOR2I& a, const VECTOR2I& b ) const;
244  void buildDpContinuation( const DP_PRIMITIVE_PAIR& aPair, bool aIsDiagonal );
245  void buildEntries( const VECTOR2I& p0_p, const VECTOR2I& p0_n );
246 
247  int m_gap;
248  int m_viaGap;
250  bool m_fitVias;
251 
252  std::vector<DP_GATEWAY> m_gateways;
253 };
254 
255 
262 class DIFF_PAIR : public LINK_HOLDER
263 {
264 public:
266  {
267  COUPLED_SEGMENTS ( const SEG& aCoupledP, const SEG& aParentP, int aIndexP,
268  const SEG& aCoupledN, const SEG& aParentN, int aIndexN ) :
269  coupledP( aCoupledP ),
270  coupledN( aCoupledN ),
271  parentP( aParentP ),
272  parentN( aParentN ),
273  indexP( aIndexP ),
274  indexN( aIndexN )
275  {}
276 
281  int indexP;
282  int indexN;
283  };
284 
285  typedef std::vector<COUPLED_SEGMENTS> COUPLED_SEGMENTS_VEC;
286 
289  m_hasVias( false )
290  {
291  // Initialize some members, to avoid uninitialized variables.
292  m_net_p = 0;
293  m_net_n = 0;;
294  m_width = 0;
295  m_gap = 0;
296  m_viaGap = 0;
298  m_chamferLimit = 0;
299  }
300 
301  DIFF_PAIR( int aGap ) :
303  m_hasVias( false )
304  {
305  m_gapConstraint = aGap;
306 
307  // Initialize other members, to avoid uninitialized variables.
308  m_net_p = 0;
309  m_net_n = 0;;
310  m_width = 0;
311  m_gap = 0;
312  m_viaGap = 0;
314  m_chamferLimit = 0;
315  }
316 
317  DIFF_PAIR( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, int aGap = 0 ) :
319  m_n( aN ),
320  m_p( aP ),
321  m_hasVias( false )
322  {
323  m_gapConstraint = aGap;
324 
325  // Initialize other members, to avoid uninitialized variables.
326  m_net_p = 0;
327  m_net_n = 0;;
328  m_width = 0;
329  m_gap = 0;
330  m_viaGap = 0;
332  m_chamferLimit = 0;
333  }
334 
335  DIFF_PAIR( const LINE &aLineP, const LINE &aLineN, int aGap = 0 ) :
337  m_line_p( aLineP ),
338  m_line_n( aLineN ),
339  m_hasVias( false )
340  {
341  m_gapConstraint = aGap;
342  m_net_p = aLineP.Net();
343  m_net_n = aLineN.Net();
344  m_p = aLineP.CLine();
345  m_n = aLineN.CLine();
346 
347  // Do not leave unitialized members, and keep static analyser quiet:
348  m_width = 0;
349  m_gap = 0;
350  m_viaGap = 0;
352  m_chamferLimit = 0;
353  }
354 
355  static inline bool ClassOf( const ITEM* aItem )
356  {
357  return aItem && ITEM::DIFF_PAIR_T == aItem->Kind();
358  }
359 
360  DIFF_PAIR* Clone() const override { assert( false ); return NULL; }
361 
362  virtual void ClearLinks() override
363  {
364  m_links.clear();
367  }
368 
369  static DIFF_PAIR* AssembleDp( LINE *aLine );
370 
371  void SetShape( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, bool aSwapLanes = false )
372  {
373  if( aSwapLanes )
374  {
375  m_p = aN;
376  m_n = aP;
377  }
378  else
379  {
380  m_p = aP;
381  m_n = aN;
382  }
383  }
384 
385  void SetShape( const DIFF_PAIR& aPair )
386  {
387  m_p = aPair.m_p;
388  m_n = aPair.m_n;
389  }
390 
391  void SetNets( int aP, int aN )
392  {
393  m_net_p = aP;
394  m_net_n = aN;
395  }
396 
397  void SetWidth( int aWidth )
398  {
399  m_width = aWidth;
400  m_n.SetWidth( aWidth );
401  m_p.SetWidth( aWidth );
402  }
403 
404  int Width() const { return m_width; }
405 
406  void SetGap( int aGap )
407  {
408  m_gap = aGap;
409  m_gapConstraint = RANGED_NUM<int>( m_gap, 10000, 10000 );
410  }
411 
412  int Gap() const
413  {
414  return m_gap;
415  }
416 
417  void AppendVias( const VIA &aViaP, const VIA& aViaN )
418  {
419  m_hasVias = true;
420  m_via_p = aViaP;
421  m_via_n = aViaN;
422  }
423 
424  void RemoveVias()
425  {
426  m_hasVias = false;
427  }
428 
429  bool EndsWithVias() const
430  {
431  return m_hasVias;
432  }
433 
434  void SetViaDiameter( int aDiameter )
435  {
436  m_via_p.SetDiameter( aDiameter );
437  m_via_n.SetDiameter( aDiameter );
438  }
439 
440  void SetViaDrill( int aDrill )
441  {
442  m_via_p.SetDrill( aDrill );
443  m_via_n.SetDrill( aDrill );
444  }
445 
446  int NetP() const
447  {
448  return m_net_p;
449  }
450 
451  int NetN() const
452  {
453  return m_net_n;
454  }
455 
457  {
458  if( !m_line_p.IsLinked() )
460 
461  return m_line_p;
462  }
463 
465  {
466  if( !m_line_n.IsLinked() )
468 
469  return m_line_n;
470  }
471 
473 
474  double CoupledLength() const;
475  double TotalLength() const;
476  double CoupledLengthFactor() const;
477  double Skew() const;
478 
479  void CoupledSegmentPairs( COUPLED_SEGMENTS_VEC& aPairs ) const;
480 
481  void Clear()
482  {
483  m_n.Clear();
484  m_p.Clear();
485  }
486 
487  void Append( const DIFF_PAIR& aOther )
488  {
489  m_n.Append( aOther.m_n );
490  m_p.Append( aOther.m_p );
491  }
492 
493  bool Empty() const
494  {
495  return ( m_n.SegmentCount() == 0 ) || ( m_p.SegmentCount() == 0 );
496  }
497 
498  const SHAPE_LINE_CHAIN& CP() const { return m_p; }
499  const SHAPE_LINE_CHAIN& CN() const { return m_n; }
500 
501  bool BuildInitial( const DP_GATEWAY& aEntry, const DP_GATEWAY& aTarget, bool aPrefDiagonal );
502  bool CheckConnectionAngle( const DIFF_PAIR &aOther, int allowedAngles ) const;
503  int CoupledLength( const SEG& aP, const SEG& aN ) const;
504 
505  int64_t CoupledLength( const SHAPE_LINE_CHAIN& aP, const SHAPE_LINE_CHAIN& aN ) const;
506 
508  {
509  return m_gapConstraint;
510  }
511 
512 private:
513  void updateLine( LINE &aLine, const SHAPE_LINE_CHAIN& aShape, int aNet, const VIA& aVia )
514  {
515  aLine.SetShape( aShape );
516  aLine.SetWidth( m_width );
517  aLine.SetNet( aNet );
518  aLine.SetLayer( Layers().Start() );
519 
520  if( m_hasVias )
521  aLine.AppendVia( aVia );
522  }
523 
527 
528  bool m_hasVias;
530  int m_width;
531  int m_gap;
532  int m_viaGap;
536 };
537 
538 }
539 
540 #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)
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:870
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:80
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:109
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:88
SHAPE_LINE_CHAIN m_entryP
bool IsDiagonal() const
Function IsDiagonal()
Definition: pns_diff_pair.h:73
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:78
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:50
void SetDrill(int aDrill)
Definition: pns_via.h:116
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:95
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:48
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)