KiCad PCB EDA Suite
pns_meander.cpp
Go to the documentation of this file.
1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2014 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 #include <base_units.h> // God forgive me doing this...
23 
24 #include "pns_node.h"
25 #include "pns_itemset.h"
26 #include "pns_topology.h"
27 #include "pns_meander.h"
29 #include "pns_router.h"
30 #include "pns_debug_decorator.h"
31 
32 namespace PNS {
33 
35 {
36  return m_placer->MeanderSettings();
37 }
38 
39 
41 {
42  return m_placer->MeanderSettings();
43 }
44 
45 
46 void MEANDERED_LINE::MeanderSegment( const SEG& aBase, int aBaseIndex )
47 {
48  double base_len = aBase.Length();
49 
51 
52  bool side = true;
53  VECTOR2D dir( aBase.B - aBase.A );
54 
55  if( !m_dual )
56  AddCorner( aBase.A );
57 
58  bool turning = false;
59  bool started = false;
60 
61  m_last = aBase.A;
62 
63  do
64  {
66 
68  m.SetBaseIndex( aBaseIndex );
69 
70  double thr = (double) m.spacing();
71 
72  bool fail = false;
73  double remaining = base_len - ( m_last - aBase.A ).EuclideanNorm();
74 
75  if( remaining < Settings( ).m_step )
76  break;
77 
78  if( remaining > 3.0 * thr )
79  {
80  if( !turning )
81  {
82  for( int i = 0; i < 2; i++ )
83  {
84  if( m.Fit( MT_CHECK_START, aBase, m_last, i ) )
85  {
86  turning = true;
87  AddMeander( new MEANDER_SHAPE( m ) );
88  side = !i;
89  started = true;
90  break;
91  }
92  }
93 
94  if( !turning )
95  {
96  fail = true;
97 
98  for( int i = 0; i < 2; i++ )
99  {
100  if( m.Fit( MT_SINGLE, aBase, m_last, i ) )
101  {
102  AddMeander( new MEANDER_SHAPE( m ) );
103  fail = false;
104  started = false;
105  side = !i;
106  break;
107  }
108  }
109  }
110  } else {
111  bool rv = m.Fit( MT_CHECK_FINISH, aBase, m_last, side );
112 
113  if( rv )
114  {
115  m.Fit( MT_TURN, aBase, m_last, side );
116  AddMeander( new MEANDER_SHAPE( m ) );
117  started = true;
118  } else {
119  m.Fit( MT_FINISH, aBase, m_last, side );
120  started = false;
121  AddMeander( new MEANDER_SHAPE( m ) );
122  turning = false;
123  }
124 
125  side = !side;
126  }
127  } else if( started )
128  {
129  bool rv = m.Fit( MT_FINISH, aBase, m_last, side );
130  if( rv )
131  AddMeander( new MEANDER_SHAPE( m ) );
132 
133  break;
134 
135  } else {
136  fail = true;
137  }
138 
139  remaining = base_len - ( m_last - aBase.A ).EuclideanNorm( );
140 
141  if( remaining < Settings( ).m_step )
142  break;
143 
144  if( fail )
145  {
148  tmp.SetBaseIndex( aBaseIndex );
149 
150  int nextP = tmp.spacing() - 2 * tmp.cornerRadius() + Settings().m_step;
151  VECTOR2I pn = m_last + dir.Resize( nextP );
152 
153  if( aBase.Contains( pn ) && !m_dual )
154  {
155  AddCorner( pn );
156  } else
157  break;
158  }
159 
160 
161  } while( true );
162 
163  if( !m_dual )
164  AddCorner( aBase.B );
165 }
166 
167 
169 {
170  // TODO: fix diff-pair meandering so we can use non-100% radii
171  int rPercent = m_dual ? 100 : Settings().m_cornerRadiusPercentage;
172 
173  return (int64_t) spacing() * rPercent / 200;
174 }
175 
176 
178 {
179  if( !m_dual )
180  return std::max( 2 * m_width, Settings().m_spacing );
181  else
182  {
183  int sp = 2 * ( m_width + std::abs( m_baselineOffset ) );
184  return std::max( sp, Settings().m_spacing );
185  }
186 }
187 
188 
190 {
191  SHAPE_LINE_CHAIN lc;
192 
193  if( aDir.EuclideanNorm( ) == 0.0f )
194  {
195  lc.Append( aP );
196  return lc;
197  }
198 
199  VECTOR2D dir_u( aDir );
200  VECTOR2D dir_v( aDir.Perpendicular( ) );
201  VECTOR2D p = aP;
202  lc.Append( ( int ) p.x, ( int ) p.y );
203 
204 
205  // fixme: refactor
207  {
208  case MEANDER_STYLE_ROUND:
209  {
210  const int ArcSegments = Settings().m_cornerArcSegments;
211 
212  double radius = (double) aDir.EuclideanNorm();
213  double angleStep = M_PI / 2.0 / (double) ArcSegments;
214 
215  double correction = 12.0 * radius * ( 1.0 - cos( angleStep / 2.0 ) );
216 
217  if( !m_dual )
218  correction = 0.0;
219  else if( radius < m_meanCornerRadius )
220  correction = 0.0;
221 
222  VECTOR2D dir_uu = dir_u.Resize( radius - correction );
223  VECTOR2D dir_vv = dir_v.Resize( radius - correction );
224 
225  VECTOR2D shift = dir_u.Resize( correction );
226 
227  for( int i = ArcSegments - 1; i >= 0; i-- )
228  {
229  double alpha = (double) i / (double) ( ArcSegments - 1 ) * M_PI / 2.0;
230  p = aP + shift + dir_uu * cos( alpha ) + dir_vv * ( aSide ? -1.0 : 1.0 ) * ( 1.0 - sin( alpha ) );
231  lc.Append( ( int ) p.x, ( int ) p.y );
232  }
233  }
234  break;
236  {
237  double radius = (double) aDir.EuclideanNorm();
238  double correction = 0;
239  if( m_dual && radius > m_meanCornerRadius )
240  correction = (double)(-2 * abs(m_baselineOffset)) * tan( 22.5 * M_PI / 180.0 );
241 
242  VECTOR2D dir_cu = dir_u.Resize( correction );
243  VECTOR2D dir_cv = dir_v.Resize( correction );
244 
245  p = aP - dir_cu;
246  lc.Append( ( int ) p.x, ( int ) p.y );
247  p = aP + dir_u + (dir_v + dir_cv) * ( aSide ? -1.0 : 1.0 );
248  lc.Append( ( int ) p.x, ( int ) p.y );
249  break;
250  }
251  }
252 
253  p = aP + dir_u + dir_v * ( aSide ? -1.0 : 1.0 );
254  lc.Append( ( int ) p.x, ( int ) p.y );
255 
256  return lc;
257 }
258 
259 
261 {
262  typedef int64_t ecoord;
263  VECTOR2I d = line.B - line.A;
264  ecoord l_squared = d.Dot( d );
265  ecoord t = d.Dot( p - line.A );
266  VECTOR2I c, rv;
267 
268  if( !l_squared )
269  c = p;
270  else {
271  c.x = line.A.x + rescale( t, (ecoord) d.x, l_squared );
272  c.y = line.A.y + rescale( t, (ecoord) d.y, l_squared );
273  }
274 
275  return 2 * c - p;
276 }
277 
278 
279 void MEANDER_SHAPE::start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir )
280 {
281  m_currentTarget = aTarget;
283  m_currentTarget->Append( aWhere );
284  m_currentDir = aDir;
285  m_currentPos = aWhere;
286 }
287 
288 
289 void MEANDER_SHAPE::forward( int aLength )
290 {
291  m_currentPos += m_currentDir.Resize( aLength );
293 }
294 
295 
296 void MEANDER_SHAPE::turn( int aAngle )
297 {
298  m_currentDir = m_currentDir.Rotate( (double) aAngle * M_PI / 180.0 );
299 }
300 
301 
302 void MEANDER_SHAPE::miter( int aRadius, bool aSide )
303 {
304  if( aRadius <= 0 )
305  {
306  turn( aSide ? -90 : 90 );
307  return;
308  }
309 
310  VECTOR2D dir = m_currentDir.Resize( (double) aRadius );
311  SHAPE_LINE_CHAIN lc = makeMiterShape( m_currentPos, dir, aSide );
312 
313  m_currentPos = lc.CPoint( -1 );
314  m_currentDir = dir.Rotate( aSide ? -M_PI / 2.0 : M_PI / 2.0 );
315 
316  m_currentTarget->Append( lc );
317 }
318 
319 
320 void MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop )
321 {
322  forward( aSides );
323  miter( aCorner, true );
324  forward( aTop );
325  miter( aCorner, true );
326  forward( aSides );
327 }
328 
329 
331  bool aSide, MEANDER_TYPE aType, int aAmpl, int aBaselineOffset )
332 {
333  const MEANDER_SETTINGS& st = Settings();
334  int cr = cornerRadius();
335  int offset = aBaselineOffset;
336  int spc = spacing();
337 
338  if( aSide )
339  offset *= -1;
340 
341  VECTOR2D dir_u_b( aDir.Resize( offset ) );
342  VECTOR2D dir_v_b( dir_u_b.Perpendicular() );
343 
344  if( 2 * cr > aAmpl )
345  {
346  cr = aAmpl / 2;
347  }
348 
349  if( 2 * cr > spc )
350  {
351  cr = spc / 2;
352  }
353 
354  m_meanCornerRadius = cr;
355 
356  SHAPE_LINE_CHAIN lc;
357 
358  start( &lc, aP + dir_v_b, aDir );
359 
360  switch( aType )
361  {
362  case MT_EMPTY:
363  {
364  lc.Append( aP + dir_v_b + aDir );
365  break;
366  }
367  case MT_START:
368  {
369  miter( cr - offset, false );
370  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
371  forward( std::min( cr - offset, cr + offset ) );
372  forward( std::abs( offset ) );
373 
374  break;
375  }
376 
377  case MT_FINISH:
378  {
379  start( &lc, aP - dir_u_b, aDir );
380  turn( 90 );
381  forward( std::min( cr - offset, cr + offset ) );
382  forward( std::abs( offset ) );
383  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
384  miter( cr - offset, false );
385  break;
386  }
387 
388  case MT_TURN:
389  {
390  start( &lc, aP - dir_u_b, aDir );
391  turn( 90 );
392  forward( std::abs( offset ) );
393  uShape( aAmpl - cr, cr + offset, spc - 2 * cr );
394  forward( std::abs( offset ) );
395  break;
396  }
397 
398  case MT_SINGLE:
399  {
400  miter( cr - offset, false );
401  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
402  miter( cr - offset, false );
403  lc.Append( aP + dir_v_b + aDir.Resize( 2 * st.m_spacing ) );
404  break;
405  }
406 
407  default:
408  break;
409  }
410 
411  if( aSide )
412  {
413  SEG axis( aP, aP + aDir );
414 
415  for( int i = 0; i < lc.PointCount(); i++ )
416  lc.Point( i ) = reflect( lc.CPoint( i ), axis );
417  }
418 
419  return lc;
420 }
421 
422 
424 {
425  for( int i = m_meanders.size() - 1; i >= 0; i-- )
426  {
427  MEANDER_SHAPE* m = m_meanders[i];
428 
429  if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
430  continue;
431 
432  const SEG& b1 = aShape->BaseSegment();
433  const SEG& b2 = m->BaseSegment();
434 
435  if( b1.ApproxParallel( b2 ) )
436  continue;
437 
438  int n = m->CLine( 0 ).SegmentCount();
439 
440  for( int j = n - 1; j >= 0; j-- )
441  if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
442  return false;
443  }
444 
445  return true;
446 }
447 
448 
449 bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
450 {
451  const MEANDER_SETTINGS& st = Settings();
452 
453  bool checkMode = false;
454  MEANDER_TYPE prim1, prim2;
455 
456  if( aType == MT_CHECK_START )
457  {
458  prim1 = MT_START;
459  prim2 = MT_TURN;
460  checkMode = true;
461  }
462  else if( aType == MT_CHECK_FINISH )
463  {
464  prim1 = MT_TURN;
465  prim2 = MT_FINISH;
466  checkMode = true;
467  }
468 
469  if( checkMode )
470  {
473 
476 
477  bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
478  bool c2 = false;
479 
480  if( c1 )
481  c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
482 
483  if( c1 && c2 )
484  {
485  m_type = prim1;
486  m_shapes[0] = m1.m_shapes[0];
487  m_shapes[1] = m1.m_shapes[1];
488  m_baseSeg =aSeg;
489  m_p0 = aP;
490  m_side = aSide;
491  m_amplitude = m1.Amplitude();
492  m_dual = m1.m_dual;
493  m_baseSeg = m1.m_baseSeg;
497  return true;
498  } else
499  return false;
500  }
501 
502  int minAmpl = st.m_minAmplitude;
503  int maxAmpl = st.m_maxAmplitude;
504 
505  if( m_dual )
506  {
507  minAmpl = std::max( minAmpl, 2 * std::abs( m_baselineOffset ) );
508  maxAmpl = std::max( maxAmpl, 2 * std::abs( m_baselineOffset ) );
509  }
510 
511  for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
512  {
513  if( m_dual )
514  {
515  m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, m_baselineOffset );
516  m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, -m_baselineOffset );
517  }
518  else
519  {
520  m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, 0 );
521  }
522 
523  m_type = aType;
524  m_baseSeg = aSeg;
525  m_p0 = aP;
526  m_side = aSide;
527  m_amplitude = ampl;
528 
530 
531  if( m_placer->CheckFit( this ) )
532  return true;
533  }
534 
535  return false;
536 }
537 
538 
540 {
542 
543  if( m_dual )
544  m_shapes[1] = genMeanderShape( m_p0, m_baseSeg.B - m_baseSeg.A, m_side, m_type, m_amplitude, -m_baselineOffset );
545 
547 }
548 
549 
550 void MEANDER_SHAPE::Resize( int aAmpl )
551 {
552  if( aAmpl < 0 )
553  return;
554 
555  m_amplitude = aAmpl;
556 
557  Recalculate();
558 }
559 
560 
562 {
564 
566 
567  m_type = MT_EMPTY;
568 
570 
571  if( m_dual )
572  m_shapes[1] = genMeanderShape( m_p0, dir, m_side, m_type, 0, -m_baselineOffset );
573 }
574 
575 
576 void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
577 {
579 
580  m->MakeCorner( aA, aB );
581  m_last = aA;
582 
583  m_meanders.push_back( m );
584 }
585 
586 
588 {
589  SetType( MT_CORNER );
590  m_shapes[0].Clear();
591  m_shapes[1].Clear();
592  m_shapes[0].Append( aP1 );
593  m_shapes[1].Append( aP2 );
594  m_clippedBaseSeg.A = aP1;
595  m_clippedBaseSeg.B = aP1;
596 }
597 
598 
600 {
601  m_last = aShape->BaseSegment().B;
602  m_meanders.push_back( aShape );
603 }
604 
605 
607 {
608  for( MEANDER_SHAPE* m : m_meanders )
609  {
610  delete m;
611  }
612 
613  m_meanders.clear( );
614 }
615 
616 
618 {
619  return m_clippedBaseSeg.Length();
620 }
621 
622 
624 {
625  return CLine( 0 ).Length();
626 }
627 
628 
630 {
631  if( m_dual )
632  {
633  VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
634  VECTOR2I midpB = ( CLine( 0 ).CPoint( -1 ) + CLine( 1 ).CPoint( -1 ) ) / 2;
635 
638  }
639  else
640  {
641  m_clippedBaseSeg.A = m_baseSeg.LineProject( CLine( 0 ).CPoint( 0 ) );
642  m_clippedBaseSeg.B = m_baseSeg.LineProject( CLine( 0 ).CPoint( -1 ) );
643  }
644 }
645 
646 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
int spacing() const
returns sanitized spacing value
SHAPE_LINE_CHAIN genMeanderShape(VECTOR2D aP, VECTOR2D aDir, bool aSide, MEANDER_TYPE aType, int aAmpl, int aBaselineOffset=0)
produces a meander shape of given type
int m_minAmplitude
minimum meandering amplitude
Definition: pns_meander.h:76
void uShape(int aSides, int aCorner, int aTop)
tells the turtle to draw an U-like shape
void SetBaselineOffset(int aOffset)
Function SetBaselineOffset()
Definition: pns_meander.h:317
bool CheckSelfIntersections(MEANDER_SHAPE *aShape, int aClearance)
Function CheckSelfIntersections()
extended_type Dot(const VECTOR2< T > &aVector) const
Function Dot() computes dot product of self with aVector.
Definition: vector2d.h:485
bool m_side
side (true = right)
Definition: pns_meander.h:376
Class MEANDER_SETTINGS.
Definition: pns_meander.h:104
Implementation of conversion functions that require both schematic and board internal units...
VECTOR2< T > Resize(T aNewLength) const
Function Resize returns a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:385
int PointCount() const
Function PointCount()
int Length() const
Function Length()
Definition: seg.h:292
MEANDER_TYPE
Shapes of available meanders.
Definition: pns_meander.h:35
VECTOR2I m_p0
first point of the meandered line
Definition: pns_meander.h:370
void AddCorner(const VECTOR2I &aA, const VECTOR2I &aB=VECTOR2I(0, 0))
Function AddCorner()
VECTOR2I LineProject(const VECTOR2I &aP) const
Function LineProject()
Definition: seg.h:337
void MeanderSegment(const SEG &aSeg, int aBaseIndex=0)
Function MeanderSegment()
Definition: pns_meander.cpp:46
const SEG & BaseSegment() const
Function BaseSegment()
Definition: pns_meander.h:273
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:370
SHAPE_LINE_CHAIN * m_currentTarget
the line the turtle is drawing on
Definition: pns_meander.h:386
void Clear()
Function Clear()
int m_baseIndex
index of the meandered segment in the base line
Definition: pns_meander.h:380
Class MEANDER_SETTINGS.
Definition: pns_meander.h:57
VECTOR2I End() const
Function End()
Definition: pns_meander.h:231
void Recalculate()
Function Recalculate()
int BaselineLength() const
Function BaselineLength()
virtual bool CheckFit(MEANDER_SHAPE *aShape)
Function CheckFit()
MEANDER_STYLE m_cornerStyle
type of corners for the meandered line
Definition: pns_meander.h:86
#define abs(a)
Definition: auxiliary.h:84
bool Collide(const VECTOR2I &aP, int aClearance=0) const override
Function Collide()
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void Resize(int aAmpl)
Function Resize()
void miter(int aRadius, bool aSide)
tells the turtle to draw a mitered corner of given radius and turn direction
const SEG CSegment(int aIndex) const
Function CSegment()
void MakeCorner(VECTOR2I aP1, VECTOR2I aP2=VECTOR2I(0, 0))
Function MakeCorner()
int m_step
amplitude/spacing adjustment step
Definition: pns_meander.h:82
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:292
void start(SHAPE_LINE_CHAIN *aTarget, const VECTOR2D &aWhere, const VECTOR2D &aDir)
starts turtle drawing
MEANDER_TYPE Type() const
Function Type()
Definition: pns_meander.h:145
void AddMeander(MEANDER_SHAPE *aShape)
Function AddMeander()
VECTOR2I::extended_type ecoord
MEANDER_TYPE m_type
the type
Definition: pns_meander.h:356
SHAPE_LINE_CHAIN makeMiterShape(VECTOR2D aP, VECTOR2D aDir, bool aSide)
generates a 90-degree circular arc
int m_cornerRadiusPercentage
rounding percentage (0 - 100)
Definition: pns_meander.h:88
int m_meanCornerRadius
average radius of meander corners (for correction of DP meanders)
Definition: pns_meander.h:368
void turn(int aAngle)
turns the turtle by aAngle
int cornerRadius() const
returns sanitized corner radius value
MEANDER_PLACER_BASE * m_placer
the placer that placed this meander
Definition: pns_meander.h:358
int m_width
width of the line
Definition: pns_meander.h:362
SHAPE_LINE_CHAIN m_shapes[2]
the actual shapes (0 used for single, both for dual)
Definition: pns_meander.h:378
void forward(int aLength)
moves turtle forward by aLength
int rescale(int aNumerator, int aValue, int aDenominator)
Definition: math_util.cpp:32
int m_baselineOffset
offset wrs the base segment (dual only)
Definition: pns_meander.h:366
int m_amplitude
amplitude of the meander
Definition: pns_meander.h:364
bool Fit(MEANDER_TYPE aType, const SEG &aSeg, const VECTOR2I &aP, bool aSide)
Function Fit()
Definition: seg.h:36
int m_cornerArcSegments
number of line segments for arc approximation
Definition: pns_meander.h:92
void MakeEmpty()
Function MakeEmpty()
void SetBaseIndex(int aIndex)
Function SetBaseIndex()
Definition: pns_meander.h:155
#define max(a, b)
Definition: auxiliary.h:86
const MEANDER_SETTINGS & Settings() const
Function Settings()
Definition: pns_meander.cpp:40
Class SHAPE_LINE_CHAIN.
size_t i
Definition: json11.cpp:597
VECTOR2I A
Definition: seg.h:46
SEG m_baseSeg
base segment (unclipped)
Definition: pns_meander.h:372
VECTOR2< T > Perpendicular() const
Function Perpendicular computes the perpendicular vector.
Definition: vector2d.h:313
virtual const MEANDER_SETTINGS & MeanderSettings() const
Function MeanderSettings()
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I reflect(VECTOR2I aP, const SEG &aLine)
reflects a point onto other side of a given segment
void updateBaseSegment()
recalculates the clipped baseline after the parameters of the meander have been changed.
VECTOR2I & Point(int aIndex)
Function Point()
bool m_dual
dual or single line
Definition: pns_meander.h:360
int m_spacing
meandering period/spacing (see dialog picture for explanation)
Definition: pns_meander.h:80
int Amplitude() const
Function Amplitude()
Definition: pns_meander.h:175
const MEANDER_SETTINGS & Settings() const
Function Settings()
Definition: pns_meander.cpp:34
bool ApproxParallel(const SEG &aSeg) const
Definition: seg.h:253
bool Contains(const VECTOR2I &aP) const
Definition: seg.cpp:155
MEANDER_SHAPE(MEANDER_PLACER_BASE *aPlacer, int aWidth, bool aIsDual=false)
Constructor.
Definition: pns_meander.h:115
Push and Shove diff pair dimensions (gap) settings dialog.
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
VECTOR2D m_currentPos
current turtle position
Definition: pns_meander.h:384
void SetType(MEANDER_TYPE aType)
Function SetType()
Definition: pns_meander.h:135
int SegmentCount() const
Function SegmentCount()
SEG m_clippedBaseSeg
base segment (clipped)
Definition: pns_meander.h:374
int MaxTunableLength() const
Function MaxTunableLength()
VECTOR2D m_currentDir
current turtle direction
Definition: pns_meander.h:382
const SHAPE_LINE_CHAIN & CLine(int aShape) const
Function CLine()
Definition: pns_meander.h:241
int Length() const
Function Length()
int m_maxAmplitude
maximum meandering amplitude
Definition: pns_meander.h:78
#define min(a, b)
Definition: auxiliary.h:85
VECTOR2I B
Definition: seg.h:47