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  return (int64_t) spacing() * Settings().m_cornerRadiusPercentage / 200;
171 }
172 
173 
175 {
176  if( !m_dual )
177  return std::max( 2 * m_width, Settings().m_spacing );
178  else
179  {
180  int sp = 2 * ( m_width + std::abs( m_baselineOffset ) );
181  return std::max( sp, Settings().m_spacing );
182  }
183 }
184 
185 
187 {
188  SHAPE_LINE_CHAIN lc;
189 
190  if( aDir.EuclideanNorm( ) == 0.0f )
191  {
192  lc.Append( aP );
193  return lc;
194  }
195 
196  VECTOR2D dir_u( aDir );
197  VECTOR2D dir_v( aDir.Perpendicular( ) );
198  VECTOR2D p = aP;
199  lc.Append( ( int ) p.x, ( int ) p.y );
200 
201 
202  // fixme: refactor
204  {
205  case MEANDER_STYLE_ROUND:
206  {
207  const int ArcSegments = Settings().m_cornerArcSegments;
208 
209  double radius = (double) aDir.EuclideanNorm();
210  double angleStep = M_PI / 2.0 / (double) ArcSegments;
211 
212  double correction = 12.0 * radius * ( 1.0 - cos( angleStep / 2.0 ) );
213 
214  if( !m_dual )
215  correction = 0.0;
216  else if( radius < m_meanCornerRadius )
217  correction = 0.0;
218 
219  VECTOR2D dir_uu = dir_u.Resize( radius - correction );
220  VECTOR2D dir_vv = dir_v.Resize( radius - correction );
221 
222  VECTOR2D shift = dir_u.Resize( correction );
223 
224  for( int i = ArcSegments - 1; i >= 0; i-- )
225  {
226  double alpha = (double) i / (double) ( ArcSegments - 1 ) * M_PI / 2.0;
227  p = aP + shift + dir_uu * cos( alpha ) + dir_vv * ( aSide ? -1.0 : 1.0 ) * ( 1.0 - sin( alpha ) );
228  lc.Append( ( int ) p.x, ( int ) p.y );
229  }
230  }
231  break;
233  {
234  double radius = (double) aDir.EuclideanNorm();
235  double correction = 0;
236  if( m_dual && radius > m_meanCornerRadius )
237  correction = (double)(-2 * abs(m_baselineOffset)) * tan( 22.5 * M_PI / 180.0 );
238 
239  VECTOR2D dir_cu = dir_u.Resize( correction );
240  VECTOR2D dir_cv = dir_v.Resize( correction );
241 
242  p = aP - dir_cu;
243  lc.Append( ( int ) p.x, ( int ) p.y );
244  p = aP + dir_u + (dir_v + dir_cv) * ( aSide ? -1.0 : 1.0 );
245  lc.Append( ( int ) p.x, ( int ) p.y );
246  break;
247  }
248  }
249 
250  p = aP + dir_u + dir_v * ( aSide ? -1.0 : 1.0 );
251  lc.Append( ( int ) p.x, ( int ) p.y );
252 
253  return lc;
254 }
255 
256 
258 {
259  typedef int64_t ecoord;
260  VECTOR2I d = line.B - line.A;
261  ecoord l_squared = d.Dot( d );
262  ecoord t = d.Dot( p - line.A );
263  VECTOR2I c, rv;
264 
265  if( !l_squared )
266  c = p;
267  else {
268  c.x = line.A.x + rescale( t, (ecoord) d.x, l_squared );
269  c.y = line.A.y + rescale( t, (ecoord) d.y, l_squared );
270  }
271 
272  return 2 * c - p;
273 }
274 
275 
276 void MEANDER_SHAPE::start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir )
277 {
278  m_currentTarget = aTarget;
280  m_currentTarget->Append( aWhere );
281  m_currentDir = aDir;
282  m_currentPos = aWhere;
283 }
284 
285 
286 void MEANDER_SHAPE::forward( int aLength )
287 {
288  m_currentPos += m_currentDir.Resize( aLength );
290 }
291 
292 
293 void MEANDER_SHAPE::turn( int aAngle )
294 {
295  m_currentDir = m_currentDir.Rotate( (double) aAngle * M_PI / 180.0 );
296 }
297 
298 
299 void MEANDER_SHAPE::miter( int aRadius, bool aSide )
300 {
301  if( aRadius <= 0 )
302  {
303  turn( aSide ? -90 : 90 );
304  return;
305  }
306 
307  VECTOR2D dir = m_currentDir.Resize( (double) aRadius );
308  SHAPE_LINE_CHAIN lc = makeMiterShape( m_currentPos, dir, aSide );
309 
310  m_currentPos = lc.CPoint( -1 );
311  m_currentDir = dir.Rotate( aSide ? -M_PI / 2.0 : M_PI / 2.0 );
312 
313  m_currentTarget->Append( lc );
314 }
315 
316 
317 void MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop )
318 {
319  forward( aSides );
320  miter( aCorner, true );
321  forward( aTop );
322  miter( aCorner, true );
323  forward( aSides );
324 }
325 
326 
328  bool aSide, MEANDER_TYPE aType, int aAmpl, int aBaselineOffset )
329 {
330  const MEANDER_SETTINGS& st = Settings();
331  int cr = cornerRadius();
332  int offset = aBaselineOffset;
333  int spc = spacing();
334 
335  if( aSide )
336  offset *= -1;
337 
338  VECTOR2D dir_u_b( aDir.Resize( offset ) );
339  VECTOR2D dir_v_b( dir_u_b.Perpendicular() );
340 
341  if( 2 * cr > aAmpl )
342  {
343  cr = aAmpl / 2;
344  }
345 
346  if( 2 * cr > spc )
347  {
348  cr = spc / 2;
349  }
350 
351  m_meanCornerRadius = cr;
352 
353  SHAPE_LINE_CHAIN lc;
354 
355  start( &lc, aP + dir_v_b, aDir );
356 
357  switch( aType )
358  {
359  case MT_EMPTY:
360  {
361  lc.Append( aP + dir_v_b + aDir );
362  break;
363  }
364  case MT_START:
365  {
366  miter( cr - offset, false );
367  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
368  forward( std::min( cr - offset, cr + offset ) );
369  forward( std::abs( offset ) );
370 
371  break;
372  }
373 
374  case MT_FINISH:
375  {
376  start( &lc, aP - dir_u_b, aDir );
377  turn( 90 );
378  forward( std::min( cr - offset, cr + offset ) );
379  forward( std::abs( offset ) );
380  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
381  miter( cr - offset, false );
382  break;
383  }
384 
385  case MT_TURN:
386  {
387  start( &lc, aP - dir_u_b, aDir );
388  turn( 90 );
389  forward( std::abs( offset ) );
390  uShape( aAmpl - cr, cr + offset, spc - 2 * cr );
391  forward( std::abs( offset ) );
392  break;
393  }
394 
395  case MT_SINGLE:
396  {
397  miter( cr - offset, false );
398  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
399  miter( cr - offset, false );
400  lc.Append( aP + dir_v_b + aDir.Resize( 2 * st.m_spacing ) );
401  break;
402  }
403 
404  default:
405  break;
406  }
407 
408  if( aSide )
409  {
410  SEG axis( aP, aP + aDir );
411 
412  for( int i = 0; i < lc.PointCount(); i++ )
413  lc.Point( i ) = reflect( lc.CPoint( i ), axis );
414  }
415 
416  return lc;
417 }
418 
419 
421 {
422  for( int i = m_meanders.size() - 1; i >= 0; i-- )
423  {
424  MEANDER_SHAPE* m = m_meanders[i];
425 
426  if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
427  continue;
428 
429  const SEG& b1 = aShape->BaseSegment();
430  const SEG& b2 = m->BaseSegment();
431 
432  if( b1.ApproxParallel( b2 ) )
433  continue;
434 
435  int n = m->CLine( 0 ).SegmentCount();
436 
437  for( int j = n - 1; j >= 0; j-- )
438  if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
439  return false;
440  }
441 
442  return true;
443 }
444 
445 
446 bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
447 {
448  const MEANDER_SETTINGS& st = Settings();
449 
450  bool checkMode = false;
451  MEANDER_TYPE prim1, prim2;
452 
453  if( aType == MT_CHECK_START )
454  {
455  prim1 = MT_START;
456  prim2 = MT_TURN;
457  checkMode = true;
458  }
459  else if( aType == MT_CHECK_FINISH )
460  {
461  prim1 = MT_TURN;
462  prim2 = MT_FINISH;
463  checkMode = true;
464  }
465 
466  if( checkMode )
467  {
470 
473 
474  bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
475  bool c2 = false;
476 
477  if( c1 )
478  c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
479 
480  if( c1 && c2 )
481  {
482  m_type = prim1;
483  m_shapes[0] = m1.m_shapes[0];
484  m_shapes[1] = m1.m_shapes[1];
485  m_baseSeg =aSeg;
486  m_p0 = aP;
487  m_side = aSide;
488  m_amplitude = m1.Amplitude();
489  m_dual = m1.m_dual;
490  m_baseSeg = m1.m_baseSeg;
494  return true;
495  } else
496  return false;
497  }
498 
499  int minAmpl = st.m_minAmplitude;
500  int maxAmpl = st.m_maxAmplitude;
501 
502  if( m_dual )
503  {
504  minAmpl = std::max( minAmpl, 2 * std::abs( m_baselineOffset ) );
505  maxAmpl = std::max( maxAmpl, 2 * std::abs( m_baselineOffset ) );
506  }
507 
508  for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
509  {
510  if( m_dual )
511  {
512  m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, m_baselineOffset );
513  m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, -m_baselineOffset );
514  }
515  else
516  {
517  m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, 0 );
518  }
519 
520  m_type = aType;
521  m_baseSeg = aSeg;
522  m_p0 = aP;
523  m_side = aSide;
524  m_amplitude = ampl;
525 
527 
528  if( m_placer->CheckFit( this ) )
529  return true;
530  }
531 
532  return false;
533 }
534 
535 
537 {
539 
540  if( m_dual )
541  m_shapes[1] = genMeanderShape( m_p0, m_baseSeg.B - m_baseSeg.A, m_side, m_type, m_amplitude, -m_baselineOffset );
542 
544 }
545 
546 
547 void MEANDER_SHAPE::Resize( int aAmpl )
548 {
549  if( aAmpl < 0 )
550  return;
551 
552  m_amplitude = aAmpl;
553 
554  Recalculate();
555 }
556 
557 
559 {
561 
563 
564  m_type = MT_EMPTY;
565 
567 
568  if( m_dual )
569  m_shapes[1] = genMeanderShape( m_p0, dir, m_side, m_type, 0, -m_baselineOffset );
570 }
571 
572 
573 void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
574 {
576 
577  m->MakeCorner( aA, aB );
578  m_last = aA;
579 
580  m_meanders.push_back( m );
581 }
582 
583 
585 {
586  SetType( MT_CORNER );
587  m_shapes[0].Clear();
588  m_shapes[1].Clear();
589  m_shapes[0].Append( aP1 );
590  m_shapes[1].Append( aP2 );
591  m_clippedBaseSeg.A = aP1;
592  m_clippedBaseSeg.B = aP1;
593 }
594 
595 
597 {
598  m_last = aShape->BaseSegment().B;
599  m_meanders.push_back( aShape );
600 }
601 
602 
604 {
605  for( MEANDER_SHAPE* m : m_meanders )
606  {
607  delete m;
608  }
609 
610  m_meanders.clear( );
611 }
612 
613 
615 {
616  return m_clippedBaseSeg.Length();
617 }
618 
619 
621 {
622  return CLine( 0 ).Length();
623 }
624 
625 
627 {
628  if( m_dual )
629  {
630  VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
631  VECTOR2I midpB = ( CLine( 0 ).CPoint( -1 ) + CLine( 1 ).CPoint( -1 ) ) / 2;
632 
635  }
636  else
637  {
638  m_clippedBaseSeg.A = m_baseSeg.LineProject( CLine( 0 ).CPoint( 0 ) );
639  m_clippedBaseSeg.B = m_baseSeg.LineProject( CLine( 0 ).CPoint( -1 ) );
640  }
641 }
642 
643 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:104
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:488
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:388
MEANDER_PLACER_BASE * m_placer
Definition: pns_meander.h:509
int PointCount() const
Function PointCount()
int Length() const
Function Length()
Definition: seg.h:283
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:322
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:373
SHAPE_LINE_CHAIN * m_currentTarget
the line the turtle is drawing on
Definition: pns_meander.h:386
std::vector< MEANDER_SHAPE * > m_meanders
Definition: pns_meander.h:510
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:295
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:37
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.
VECTOR2I A
Definition: seg.h:47
SEG m_baseSeg
base segment (unclipped)
Definition: pns_meander.h:372
VECTOR2< T > Perpendicular() const
Function Perpendicular computes the perpendicular vector.
Definition: vector2d.h:316
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:244
bool Contains(const VECTOR2I &aP) const
Definition: seg.cpp:155
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:48