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-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
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
34namespace PNS {
35
36class DIFF_PAIR;
37
44{
45public:
46 DP_GATEWAY( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN, bool aIsDiagonal,
47 int aAllowedEntryAngles = DIRECTION_45::ANG_OBTUSE, int aPriority = 0 ) :
48 m_anchorP( aAnchorP ),
49 m_anchorN( aAnchorN ), m_isDiagonal( aIsDiagonal ),
50 m_allowedEntryAngles( aAllowedEntryAngles ), m_priority( aPriority )
51 {
52 m_hasEntryLines = false;
53 }
54
56 {
57 }
58
62 bool IsDiagonal() const
63 {
64 return m_isDiagonal;
65 }
66
67 const VECTOR2I& AnchorP() const { return m_anchorP; }
68
69 const VECTOR2I& AnchorN() const { return m_anchorN; }
70
74 int AllowedAngles () const { return m_allowedEntryAngles; }
75
79 int Priority() const
80 {
81 return m_priority;
82 }
83
84 void SetPriority(int aPriority)
85 {
86 m_priority = aPriority;
87 }
88
89 void SetEntryLines( const SHAPE_LINE_CHAIN& aEntryP, const SHAPE_LINE_CHAIN& aEntryN )
90 {
91 m_entryP = aEntryP;
92 m_entryN = aEntryN;
93 m_hasEntryLines = true;
94 }
95
96 const SHAPE_LINE_CHAIN& EntryP() const { return m_entryP; }
97 const SHAPE_LINE_CHAIN& EntryN() const { return m_entryN; }
98 const DIFF_PAIR Entry() const ;
99
100 void Reverse();
101
102 bool HasEntryLines () const
103 {
104 return m_hasEntryLines;
105 }
106
107private:
114};
115
120{
121public:
123 m_primP( nullptr ), m_primN( nullptr ) {};
124
125 DP_PRIMITIVE_PAIR( const DP_PRIMITIVE_PAIR& aOther );
126 DP_PRIMITIVE_PAIR( ITEM* aPrimP, ITEM* aPrimN );
127 DP_PRIMITIVE_PAIR( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
128
130
131 void SetAnchors( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
132
133 const VECTOR2I& AnchorP() const { return m_anchorP; }
134 const VECTOR2I& AnchorN() const { return m_anchorN; }
135
137
138 ITEM* PrimP() const { return m_primP; }
139 ITEM* PrimN() const { return m_primN; }
140
141 bool Directional() const;
142
143 DIRECTION_45 DirP() const;
144 DIRECTION_45 DirN() const;
145
146
147 void CursorOrientation( const VECTOR2I& aCursorPos, VECTOR2I& aMidpoint,
148 VECTOR2I& aDirection ) const;
149
150 void dump()
151 {
152 printf( "-- Prim-P %p anchor [%d, %d]\n", m_primP, m_anchorP.x, m_anchorP.y );
153 printf( "-- Prim-N %p anchor [%d, %d]\n", m_primN, m_anchorN.x, m_anchorN.y );
154 }
155
156private:
157 DIRECTION_45 anchorDirection( const ITEM* aItem, const VECTOR2I& aP ) const;
158
162};
163
168{
169public:
170 DP_GATEWAYS( int aGap ):
171 m_gap( aGap ),
172 m_viaGap( aGap )
173 {
174 // Do not leave uninitialized members, and keep static analyzer quiet:
175 m_viaDiameter = 0;
176 m_fitVias = true;
177 }
178
179 void Clear() { m_gateways.clear(); }
180
181 void SetFitVias( bool aEnable, int aDiameter = 0, int aViaGap = -1 )
182 {
183 m_fitVias = aEnable;
184 m_viaDiameter = aDiameter;
185
186 if( aViaGap < 0 )
187 m_viaGap = m_gap;
188 else
189 m_viaGap = aViaGap;
190 }
191
192
193 void BuildForCursor( const VECTOR2I& aCursorPos );
194 void BuildOrthoProjections( DP_GATEWAYS& aEntries, const VECTOR2I& aCursorPos,
195 int aOrthoScore );
196 void BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool aBuildEntries = false,
197 bool aViaMode = false );
198 void BuildFromPrimitivePair( const DP_PRIMITIVE_PAIR& aPair, bool aPreferDiagonal );
199
200 bool FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool aPrefDiagonal,
201 DIFF_PAIR& aDp );
202
203 std::vector<DP_GATEWAY>& Gateways() { return m_gateways; }
204
205 const std::vector<DP_GATEWAY>& CGateways() const { return m_gateways; }
206
207 void FilterByOrientation( int aAngleMask, DIRECTION_45 aRefOrientation );
208
209private:
211 {
214 int score;
215 };
216
217 bool checkDiagonalAlignment( const VECTOR2I& a, const VECTOR2I& b ) const;
218 void buildDpContinuation( const DP_PRIMITIVE_PAIR& aPair, bool aIsDiagonal );
219 void buildEntries( const VECTOR2I& p0_p, const VECTOR2I& p0_n );
220
221 int m_gap;
225
226 std::vector<DP_GATEWAY> m_gateways;
227};
228
229
234class DIFF_PAIR : public LINK_HOLDER
235{
236public:
238 {
239 COUPLED_SEGMENTS ( const SEG& aCoupledP, const SEG& aParentP, int aIndexP,
240 const SEG& aCoupledN, const SEG& aParentN, int aIndexN ) :
241 coupledP( aCoupledP ),
242 coupledN( aCoupledN ),
243 parentP( aParentP ),
244 parentN( aParentN ),
245 indexP( aIndexP ),
246 indexN( aIndexN )
247 {}
248
255 };
256
257 typedef std::vector<COUPLED_SEGMENTS> COUPLED_SEGMENTS_VEC;
258
261 m_hasVias( false )
262 {
263 // Initialize some members, to avoid uninitialized variables.
264 m_net_p = 0;
265 m_net_n = 0;;
266 m_width = 0;
267 m_gap = 0;
268 m_viaGap = 0;
270 m_chamferLimit = 0;
271 }
272
273 DIFF_PAIR( int aGap ) :
275 m_hasVias( false )
276 {
277 m_gapConstraint = aGap;
278
279 // Initialize other members, to avoid uninitialized variables.
280 m_net_p = 0;
281 m_net_n = 0;;
282 m_width = 0;
283 m_gap = 0;
284 m_viaGap = 0;
286 m_chamferLimit = 0;
287 }
288
289 DIFF_PAIR( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, int aGap = 0 ) :
291 m_n( aN ),
292 m_p( aP ),
293 m_hasVias( false )
294 {
295 m_gapConstraint = aGap;
296
297 // Initialize other members, to avoid uninitialized variables.
298 m_net_p = 0;
299 m_net_n = 0;;
300 m_width = 0;
301 m_gap = 0;
302 m_viaGap = 0;
304 m_chamferLimit = 0;
305 }
306
307 DIFF_PAIR( const LINE &aLineP, const LINE &aLineN, int aGap = 0 ) :
309 m_line_p( aLineP ),
310 m_line_n( aLineN ),
311 m_hasVias( false )
312 {
313 m_gapConstraint = aGap;
314 m_net_p = aLineP.Net();
315 m_net_n = aLineN.Net();
316 m_p = aLineP.CLine();
317 m_n = aLineN.CLine();
318
319 // Do not leave uninitialized members, and keep static analyzer quiet:
320 m_width = 0;
321 m_gap = 0;
322 m_viaGap = 0;
324 m_chamferLimit = 0;
325 }
326
327 static inline bool ClassOf( const ITEM* aItem )
328 {
329 return aItem && ITEM::DIFF_PAIR_T == aItem->Kind();
330 }
331
332 DIFF_PAIR* Clone() const override
333 {
334 assert( false );
335 return nullptr;
336 }
337
338 virtual void ClearLinks() override
339 {
340 m_links.clear();
343 }
344
345 static DIFF_PAIR* AssembleDp( LINE *aLine );
346
347 void SetShape( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, bool aSwapLanes = false )
348 {
349 if( aSwapLanes )
350 {
351 m_p = aN;
352 m_n = aP;
353 }
354 else
355 {
356 m_p = aP;
357 m_n = aN;
358 }
359 }
360
361 void SetShape( const DIFF_PAIR& aPair )
362 {
363 m_p = aPair.m_p;
364 m_n = aPair.m_n;
365 }
366
367 void SetNets( int aP, int aN )
368 {
369 m_net_p = aP;
370 m_net_n = aN;
371 }
372
373 void SetWidth( int aWidth )
374 {
375 m_width = aWidth;
376 m_n.SetWidth( aWidth );
377 m_p.SetWidth( aWidth );
378 }
379
380 int Width() const { return m_width; }
381
382 void SetGap( int aGap )
383 {
384 m_gap = aGap;
385 m_gapConstraint = RANGED_NUM<int>( m_gap, 10000, 10000 );
386 }
387
388 int Gap() const
389 {
390 return m_gap;
391 }
392
393 void AppendVias( const VIA &aViaP, const VIA& aViaN )
394 {
395 m_hasVias = true;
396 m_via_p = aViaP;
397 m_via_n = aViaN;
398 }
399
401 {
402 m_hasVias = false;
405 }
406
407 bool EndsWithVias() const
408 {
409 return m_hasVias;
410 }
411
412 void SetViaDiameter( int aDiameter )
413 {
414 m_via_p.SetDiameter( aDiameter );
415 m_via_n.SetDiameter( aDiameter );
416 }
417
418 void SetViaDrill( int aDrill )
419 {
420 m_via_p.SetDrill( aDrill );
421 m_via_n.SetDrill( aDrill );
422 }
423
424 int NetP() const
425 {
426 return m_net_p;
427 }
428
429 int NetN() const
430 {
431 return m_net_n;
432 }
433
435 {
436 if( !m_line_p.IsLinked() )
438
439 return m_line_p;
440 }
441
443 {
444 if( !m_line_n.IsLinked() )
446
447 return m_line_n;
448 }
449
451
452 double CoupledLength() const;
453 double TotalLength() const;
454 double CoupledLengthFactor() const;
455 double Skew() const;
456
457 void CoupledSegmentPairs( COUPLED_SEGMENTS_VEC& aPairs ) const;
458
459 void Clear()
460 {
461 m_n.Clear();
462 m_p.Clear();
463 }
464
465 void Append( const DIFF_PAIR& aOther )
466 {
467 m_n.Append( aOther.m_n );
468 m_p.Append( aOther.m_p );
469 }
470
471 bool Empty() const
472 {
473 return ( m_n.SegmentCount() == 0 ) || ( m_p.SegmentCount() == 0 );
474 }
475
476 const SHAPE_LINE_CHAIN& CP() const { return m_p; }
477 const SHAPE_LINE_CHAIN& CN() const { return m_n; }
478
479 bool BuildInitial( const DP_GATEWAY& aEntry, const DP_GATEWAY& aTarget, bool aPrefDiagonal );
480 bool CheckConnectionAngle( const DIFF_PAIR &aOther, int allowedAngles ) const;
481 int CoupledLength( const SEG& aP, const SEG& aN ) const;
482
483 int64_t CoupledLength( const SHAPE_LINE_CHAIN& aP, const SHAPE_LINE_CHAIN& aN ) const;
484
486 {
487 return m_gapConstraint;
488 }
489
490private:
491 void updateLine( LINE &aLine, const SHAPE_LINE_CHAIN& aShape, int aNet, const VIA& aVia )
492 {
493 aLine.SetShape( aShape );
494 aLine.SetWidth( m_width );
495 aLine.SetNet( aNet );
496 aLine.SetLayer( Layers().Start() );
497
498 if( m_hasVias )
499 aLine.AppendVia( aVia );
500 }
501
505
509 int m_gap;
514};
515
516}
517
518#endif
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:37
Basic class for a differential pair.
bool CheckConnectionAngle(const DIFF_PAIR &aOther, int allowedAngles) const
void AppendVias(const VIA &aViaP, const VIA &aViaN)
SHAPE_LINE_CHAIN m_p
const SHAPE_LINE_CHAIN & CN() const
static DIFF_PAIR * AssembleDp(LINE *aLine)
DP_PRIMITIVE_PAIR EndingPrimitives()
int Width() const
std::vector< COUPLED_SEGMENTS > COUPLED_SEGMENTS_VEC
const RANGED_NUM< int > GapConstraint() const
double CoupledLength() const
bool BuildInitial(const DP_GATEWAY &aEntry, const DP_GATEWAY &aTarget, bool aPrefDiagonal)
void Append(const DIFF_PAIR &aOther)
int NetN() const
double Skew() const
void SetViaDiameter(int aDiameter)
DIFF_PAIR(int aGap)
RANGED_NUM< int > m_gapConstraint
double TotalLength() const
void SetViaDrill(int aDrill)
virtual void ClearLinks() override
Return the number of segments that were assembled together to form this line.
void SetShape(const DIFF_PAIR &aPair)
double CoupledLengthFactor() const
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
int Gap() const
bool EndsWithVias() const
DIFF_PAIR(const LINE &aLineP, const LINE &aLineN, int aGap=0)
bool Empty() const
DIFF_PAIR * Clone() const override
Return a deep copy of the item.
static bool ClassOf(const ITEM *aItem)
int NetP() const
void SetGap(int aGap)
SHAPE_LINE_CHAIN m_n
const SHAPE_LINE_CHAIN & CP() const
DIFF_PAIR(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, int aGap=0)
void CoupledSegmentPairs(COUPLED_SEGMENTS_VEC &aPairs) const
void updateLine(LINE &aLine, const SHAPE_LINE_CHAIN &aShape, int aNet, const VIA &aVia)
void SetNets(int aP, int aN)
void SetWidth(int aWidth)
A set of gateways calculated for the cursor or starting/ending primitive pair.
void SetFitVias(bool aEnable, int aDiameter=0, int aViaGap=-1)
void BuildFromPrimitivePair(const DP_PRIMITIVE_PAIR &aPair, bool aPreferDiagonal)
DP_GATEWAYS(int aGap)
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
const std::vector< DP_GATEWAY > & CGateways() const
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.
Definition: pns_diff_pair.h:44
SHAPE_LINE_CHAIN m_entryP
bool IsDiagonal() const
Definition: pns_diff_pair.h:62
const SHAPE_LINE_CHAIN & EntryP() const
Definition: pns_diff_pair.h:96
bool HasEntryLines() const
int AllowedAngles() const
Definition: pns_diff_pair.h:74
const VECTOR2I & AnchorN() const
Definition: pns_diff_pair.h:69
VECTOR2I m_anchorP
SHAPE_LINE_CHAIN m_entryN
VECTOR2I m_anchorN
void SetEntryLines(const SHAPE_LINE_CHAIN &aEntryP, const SHAPE_LINE_CHAIN &aEntryN)
Definition: pns_diff_pair.h:89
const VECTOR2I & AnchorP() const
Definition: pns_diff_pair.h:67
const SHAPE_LINE_CHAIN & EntryN() const
Definition: pns_diff_pair.h:97
const DIFF_PAIR Entry() const
DP_GATEWAY(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN, bool aIsDiagonal, int aAllowedEntryAngles=DIRECTION_45::ANG_OBTUSE, int aPriority=0)
Definition: pns_diff_pair.h:46
int Priority() const
Definition: pns_diff_pair.h:79
void SetPriority(int aPriority)
Definition: pns_diff_pair.h:84
Store starting/ending primitives (pads, vias or segments) for a differential pair.
DIRECTION_45 DirN() const
const VECTOR2I & AnchorN() const
ITEM * PrimN() 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)
ITEM * PrimP() const
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
DIRECTION_45 DirP() const
Base class for PNS router board items.
Definition: pns_item.h:56
void SetNet(int aNet)
Definition: pns_item.h:153
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:132
void SetLayer(int aLayer)
Definition: pns_item.h:159
@ DIFF_PAIR_T
Definition: pns_item.h:69
const LAYER_RANGE & Layers() const
Definition: pns_item.h:156
int Net() const
Definition: pns_item.h:154
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
Definition: pns_line.h:126
void RemoveVia()
Definition: pns_line.h:197
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:142
void AppendVia(const VIA &aVia)
Definition: pns_line.cpp:1031
void SetWidth(int aWidth)
Return line width.
Definition: pns_line.h:154
void SetDiameter(int aDiameter)
Definition: pns_via.h:114
void SetDrill(int aDrill)
Definition: pns_via.h:122
Definition: seg.h:42
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Clear()
Remove all points from the line chain.
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.
void SetWidth(int aWidth)
Set the width of all segments in the chain.
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)