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;
235 
237  {
238  double radius = (double) aDir.EuclideanNorm();
239  double correction = 0;
240  if( m_dual && radius > m_meanCornerRadius )
241  correction = (double)( -2 * abs(m_baselineOffset) ) * tan( 22.5 * M_PI / 180.0 );
242 
243  VECTOR2D dir_cu = dir_u.Resize( correction );
244  VECTOR2D dir_cv = dir_v.Resize( correction );
245 
246  p = aP - dir_cu;
247  lc.Append( ( int ) p.x, ( int ) p.y );
248  p = aP + dir_u + (dir_v + dir_cv) * ( aSide ? -1.0 : 1.0 );
249  lc.Append( ( int ) p.x, ( int ) p.y );
250  }
251  break;
252  }
253 
254  p = aP + dir_u + dir_v * ( aSide ? -1.0 : 1.0 );
255  lc.Append( ( int ) p.x, ( int ) p.y );
256 
257  return lc;
258 }
259 
260 
262 {
263  typedef int64_t ecoord;
264  VECTOR2I d = line.B - line.A;
265  ecoord l_squared = d.Dot( d );
266  ecoord t = d.Dot( p - line.A );
267  VECTOR2I c, rv;
268 
269  if( !l_squared )
270  c = p;
271  else {
272  c.x = line.A.x + rescale( t, (ecoord) d.x, l_squared );
273  c.y = line.A.y + rescale( t, (ecoord) d.y, l_squared );
274  }
275 
276  return 2 * c - p;
277 }
278 
279 
280 void MEANDER_SHAPE::start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir )
281 {
282  m_currentTarget = aTarget;
284  m_currentTarget->Append( aWhere );
285  m_currentDir = aDir;
286  m_currentPos = aWhere;
287 }
288 
289 
290 void MEANDER_SHAPE::forward( int aLength )
291 {
292  m_currentPos += m_currentDir.Resize( aLength );
294 }
295 
296 
297 void MEANDER_SHAPE::turn( int aAngle )
298 {
299  m_currentDir = m_currentDir.Rotate( (double) aAngle * M_PI / 180.0 );
300 }
301 
302 
303 void MEANDER_SHAPE::miter( int aRadius, bool aSide )
304 {
305  if( aRadius <= 0 )
306  {
307  turn( aSide ? -90 : 90 );
308  return;
309  }
310 
311  VECTOR2D dir = m_currentDir.Resize( (double) aRadius );
312  SHAPE_LINE_CHAIN lc = makeMiterShape( m_currentPos, dir, aSide );
313 
314  m_currentPos = lc.CPoint( -1 );
315  m_currentDir = dir.Rotate( aSide ? -M_PI / 2.0 : M_PI / 2.0 );
316 
317  m_currentTarget->Append( lc );
318 }
319 
320 
321 void MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop )
322 {
323  forward( aSides );
324  miter( aCorner, true );
325  forward( aTop );
326  miter( aCorner, true );
327  forward( aSides );
328 }
329 
330 
332  bool aSide, MEANDER_TYPE aType, int aAmpl, int aBaselineOffset )
333 {
334  const MEANDER_SETTINGS& st = Settings();
335  int cr = cornerRadius();
336  int offset = aBaselineOffset;
337  int spc = spacing();
338 
339  if( aSide )
340  offset *= -1;
341 
342  VECTOR2D dir_u_b( aDir.Resize( offset ) );
343  VECTOR2D dir_v_b( dir_u_b.Perpendicular() );
344 
345  if( 2 * cr > aAmpl )
346  {
347  cr = aAmpl / 2;
348  }
349 
350  if( 2 * cr > spc )
351  {
352  cr = spc / 2;
353  }
354 
355  m_meanCornerRadius = cr;
356 
357  SHAPE_LINE_CHAIN lc;
358 
359  start( &lc, aP + dir_v_b, aDir );
360 
361  switch( aType )
362  {
363  case MT_EMPTY:
364  {
365  lc.Append( aP + dir_v_b + aDir );
366  break;
367  }
368  case MT_START:
369  {
370  miter( cr - offset, false );
371  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
372  forward( std::min( cr - offset, cr + offset ) );
373  forward( std::abs( offset ) );
374 
375  break;
376  }
377 
378  case MT_FINISH:
379  {
380  start( &lc, aP - dir_u_b, aDir );
381  turn( 90 );
382  forward( std::min( cr - offset, cr + offset ) );
383  forward( std::abs( offset ) );
384  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
385  miter( cr - offset, false );
386  break;
387  }
388 
389  case MT_TURN:
390  {
391  start( &lc, aP - dir_u_b, aDir );
392  turn( 90 );
393  forward( std::abs( offset ) );
394  uShape( aAmpl - cr, cr + offset, spc - 2 * cr );
395  forward( std::abs( offset ) );
396  break;
397  }
398 
399  case MT_SINGLE:
400  {
401  miter( cr - offset, false );
402  uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
403  miter( cr - offset, false );
404  lc.Append( aP + dir_v_b + aDir.Resize( 2 * st.m_spacing ) );
405  break;
406  }
407 
408  default:
409  break;
410  }
411 
412  if( aSide )
413  {
414  SEG axis( aP, aP + aDir );
415 
416  for( int i = 0; i < lc.PointCount(); i++ )
417  lc.SetPoint( i, reflect( lc.CPoint( i ), axis ) );
418  }
419 
420  return lc;
421 }
422 
423 
425 {
426  for( int i = m_meanders.size() - 1; i >= 0; i-- )
427  {
428  MEANDER_SHAPE* m = m_meanders[i];
429 
430  if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
431  continue;
432 
433  const SEG& b1 = aShape->BaseSegment();
434  const SEG& b2 = m->BaseSegment();
435 
436  if( b1.ApproxParallel( b2 ) )
437  continue;
438 
439  int n = m->CLine( 0 ).SegmentCount();
440 
441  for( int j = n - 1; j >= 0; j-- )
442  if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
443  return false;
444  }
445 
446  return true;
447 }
448 
449 
450 bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
451 {
452  const MEANDER_SETTINGS& st = Settings();
453 
454  bool checkMode = false;
455  MEANDER_TYPE prim1, prim2;
456 
457  if( aType == MT_CHECK_START )
458  {
459  prim1 = MT_START;
460  prim2 = MT_TURN;
461  checkMode = true;
462  }
463  else if( aType == MT_CHECK_FINISH )
464  {
465  prim1 = MT_TURN;
466  prim2 = MT_FINISH;
467  checkMode = true;
468  }
469 
470  if( checkMode )
471  {
474 
477 
478  bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
479  bool c2 = false;
480 
481  if( c1 )
482  c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
483 
484  if( c1 && c2 )
485  {
486  m_type = prim1;
487  m_shapes[0] = m1.m_shapes[0];
488  m_shapes[1] = m1.m_shapes[1];
489  m_baseSeg =aSeg;
490  m_p0 = aP;
491  m_side = aSide;
492  m_amplitude = m1.Amplitude();
493  m_dual = m1.m_dual;
494  m_baseSeg = m1.m_baseSeg;
498  return true;
499  } else
500  return false;
501  }
502 
503  int minAmpl = st.m_minAmplitude;
504  int maxAmpl = st.m_maxAmplitude;
505 
506  if( m_dual )
507  {
508  minAmpl = std::max( minAmpl, 2 * std::abs( m_baselineOffset ) );
509  maxAmpl = std::max( maxAmpl, 2 * std::abs( m_baselineOffset ) );
510  }
511 
512  for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
513  {
514  if( m_dual )
515  {
516  m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, m_baselineOffset );
517  m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, -m_baselineOffset );
518  }
519  else
520  {
521  m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, 0 );
522  }
523 
524  m_type = aType;
525  m_baseSeg = aSeg;
526  m_p0 = aP;
527  m_side = aSide;
528  m_amplitude = ampl;
529 
531 
532  if( m_placer->CheckFit( this ) )
533  return true;
534  }
535 
536  return false;
537 }
538 
539 
541 {
543 
544  if( m_dual )
546 
548 }
549 
550 
551 void MEANDER_SHAPE::Resize( int aAmpl )
552 {
553  if( aAmpl < 0 )
554  return;
555 
556  m_amplitude = aAmpl;
557 
558  Recalculate();
559 }
560 
561 
563 {
565 
567 
568  m_type = MT_EMPTY;
569 
571 
572  if( m_dual )
574 }
575 
576 
577 void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
578 {
580 
581  m->MakeCorner( aA, aB );
582  m_last = aA;
583 
584  m_meanders.push_back( m );
585 }
586 
587 
589 {
590  SetType( MT_CORNER );
591  m_shapes[0].Clear();
592  m_shapes[1].Clear();
593  m_shapes[0].Append( aP1 );
594  m_shapes[1].Append( aP2 );
595  m_clippedBaseSeg.A = aP1;
596  m_clippedBaseSeg.B = aP1;
597 }
598 
599 
601 {
602  m_last = aShape->BaseSegment().B;
603  m_meanders.push_back( aShape );
604 }
605 
606 
608 {
609  for( MEANDER_SHAPE* m : m_meanders )
610  {
611  delete m;
612  }
613 
614  m_meanders.clear( );
615 }
616 
617 
619 {
620  return m_clippedBaseSeg.Length();
621 }
622 
623 
625 {
626  return CLine( 0 ).Length();
627 }
628 
629 
631 {
632  if( m_dual )
633  {
634  VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
635  VECTOR2I midpB = ( CLine( 0 ).CPoint( -1 ) + CLine( 1 ).CPoint( -1 ) ) / 2;
636 
639  }
640  else
641  {
642  m_clippedBaseSeg.A = m_baseSeg.LineProject( CLine( 0 ).CPoint( 0 ) );
643  m_clippedBaseSeg.B = m_baseSeg.LineProject( CLine( 0 ).CPoint( -1 ) );
644  }
645 }
646 
647 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:148
int Length() const
Return the length (this).
Definition: seg.h:340
SHAPE_LINE_CHAIN genMeanderShape(VECTOR2D aP, VECTOR2D aDir, bool aSide, MEANDER_TYPE aType, int aAmpl, int aBaselineOffset=0)
Recalculate the clipped baseline after the parameters of the meander have been changed.
long long int Length() const
Function Length()
int m_minAmplitude
Maximum meandering amplitude.
Definition: pns_meander.h:77
void uShape(int aSides, int aCorner, int aTop)
Generate a 90-degree circular arc.
void SetBaselineOffset(int aOffset)
Set the parallel offset between the base segment and the meandered line.
Definition: pns_meander.h:277
bool CheckSelfIntersections(MEANDER_SHAPE *aShape, int aClearance)
Check if the given shape is intersecting with any other meander in the current line.
int BaselineLength() const
bool m_side
The actual shapes (0 used for single, both for dual).
Definition: pns_meander.h:350
The geometry of a single meander.
Definition: pns_meander.h:103
VECTOR2I End() const
Definition: pns_meander.h:208
Implementation of conversion functions that require both schematic and board internal units.
void SetPoint(int aIndex, const VECTOR2I &aPos)
Accessor Function to move a point to a specific location.
MEANDER_PLACER_BASE * m_placer
Definition: pns_meander.h:470
VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
Definition: vector2d.h:314
MEANDER_TYPE
Shapes of available meanders.
Definition: pns_meander.h:37
VECTOR2I m_p0
Base segment (unclipped).
Definition: pns_meander.h:341
void AddCorner(const VECTOR2I &aA, const VECTOR2I &aB=VECTOR2I(0, 0))
Create a dummy meander shape representing a line corner.
void MeanderSegment(const SEG &aSeg, int aBaseIndex=0)
Fit maximum amplitude meanders on a given segment and adds to the current line.
Definition: pns_meander.cpp:46
SHAPE_LINE_CHAIN * m_currentTarget
Definition: pns_meander.h:365
std::vector< MEANDER_SHAPE * > m_meanders
Definition: pns_meander.h:471
void Clear()
Clear the line geometry, removing all corners and meanders.
int m_baseIndex
The current turtle direction.
Definition: pns_meander.h:356
MEANDER_TYPE Type() const
Definition: pns_meander.h:138
Dimensions for the meandering algorithm.
Definition: pns_meander.h:57
void Recalculate()
Recalculate the line chain representing the meander's shape.
virtual bool CheckFit(MEANDER_SHAPE *aShape)
Checks if it's OK to place the shape aShape (i.e.
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
Definition: pns_meander.h:89
int PointCount() const
Function PointCount()
const MEANDER_SETTINGS & Settings() const
Definition: pns_meander.cpp:40
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
void Resize(int aAmpl)
Change the amplitude of the meander shape to aAmpl and recalculates the resulting line chain.
void miter(int aRadius, bool aSide)
Tell the turtle to draw an U-like shape.
const VECTOR2I & CPoint(int aIndex) const
Function Point()
void MakeCorner(VECTOR2I aP1, VECTOR2I aP2=VECTOR2I(0, 0))
Create a dummy meander shape representing a line corner.
int m_step
Length PadToDie.
Definition: pns_meander.h:83
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.h:389
bool ApproxParallel(const SEG &aSeg) const
Definition: seg.h:280
void start(SHAPE_LINE_CHAIN *aTarget, const VECTOR2D &aWhere, const VECTOR2D &aDir)
Move turtle forward by aLength.
void AddMeander(MEANDER_SHAPE *aShape)
Add a new meander shape the the meandered line.
VECTOR2I::extended_type ecoord
MEANDER_TYPE m_type
The placer that placed this meander.
Definition: pns_meander.h:320
SHAPE_LINE_CHAIN makeMiterShape(VECTOR2D aP, VECTOR2D aDir, bool aSide)
Reflect a point onto other side of a given segment.
const SHAPE_LINE_CHAIN & CLine(int aShape) const
Definition: pns_meander.h:216
int m_cornerRadiusPercentage
Allowable tuning error.
Definition: pns_meander.h:91
int m_meanCornerRadius
First point of the meandered line.
Definition: pns_meander.h:338
const SEG & BaseSegment() const
Return the base segment the meander was fitted to.
Definition: pns_meander.h:243
void turn(int aAngle)
Tell the turtle to draw a mitered corner of given radius and turn direction.
MEANDER_PLACER_BASE * m_placer
Dual or single line.
Definition: pns_meander.h:323
int m_width
Amplitude of the meander.
Definition: pns_meander.h:329
SHAPE_LINE_CHAIN m_shapes[2]
Index of the meandered segment in the base line.
Definition: pns_meander.h:353
int MaxTunableLength() const
int SegmentCount() const
Function SegmentCount()
void forward(int aLength)
Turn the turtle by aAngle.
int m_baselineOffset
Average radius of meander corners (for correction of DP meanders).
Definition: pns_meander.h:335
const MEANDER_SETTINGS & Settings() const
Definition: pns_meander.cpp:34
int m_amplitude
Offset wrs the base segment (dual only).
Definition: pns_meander.h:332
bool Fit(MEANDER_TYPE aType, const SEG &aSeg, const VECTOR2I &aP, bool aSide)
Attempt to fit a meander of a given type onto a segment, avoiding collisions with other board feature...
Definition: seg.h:41
int m_cornerArcSegments
Target skew value for diff pair de-skewing.
Definition: pns_meander.h:95
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:404
void MakeEmpty()
Replace the meander with straight bypass line(s), effectively clearing it.
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371
void SetBaseIndex(int aIndex)
Set an auxiliary index of the segment being meandered in its original LINE.
Definition: pns_meander.h:146
const SEG CSegment(int aIndex) const
Function CSegment()
extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
Definition: vector2d.h:521
SHAPE_LINE_CHAIN.
int cornerRadius() const
Return sanitized spacing value.
VECTOR2I A
Definition: seg.h:49
SEG m_baseSeg
Base segment (clipped).
Definition: pns_meander.h:344
T rescale(T aNumerator, T aValue, T aDenominator)
Function rescale()
Definition: util.h:95
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I reflect(VECTOR2I aP, const SEG &aLine)
Produce a meander shape of given type.
void updateBaseSegment()
Return sanitized corner radius value.
bool m_dual
Width of the line.
Definition: pns_meander.h:326
int m_spacing
Amplitude/spacing adjustment step.
Definition: pns_meander.h:81
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
int spacing() const
The type of meander.
Push and Shove diff pair dimensions (gap) settings dialog.
VECTOR2D m_currentPos
The line the turtle is drawing on.
Definition: pns_meander.h:362
virtual const MEANDER_SETTINGS & MeanderSettings() const
Return the current meandering configuration.
void SetType(MEANDER_TYPE aType)
Set the type of the meander.
Definition: pns_meander.h:130
int Amplitude() const
Definition: pns_meander.h:162
SEG m_clippedBaseSeg
Side (true = right).
Definition: pns_meander.h:347
VECTOR2D m_currentDir
The current turtle position.
Definition: pns_meander.h:359
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
Definition: pns_meander.h:79
bool Contains(const SEG &aSeg) const
Definition: seg.h:321
VECTOR2I B
Definition: seg.h:50