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-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#include <base_units.h> // God forgive me doing this...
23
24#include "pns_node.h"
25#include "pns_itemset.h"
26#include "pns_meander.h"
28#include "pns_router.h"
29#include "pns_debug_decorator.h"
30
31namespace PNS {
32
34{
35 return m_placer->MeanderSettings();
36}
37
38
40{
41 return m_placer->MeanderSettings();
42}
43
44
45void MEANDERED_LINE::MeanderSegment( const SEG& aBase, bool aSide, int aBaseIndex )
46{
47 double base_len = aBase.Length();
48
50
51 bool side = aSide;
52 VECTOR2D dir( aBase.B - aBase.A );
53
54 if( !m_dual )
55 AddCorner( aBase.A );
56
57 bool turning = false;
58 bool started = false;
59
60 m_last = aBase.A;
61
62 do
63 {
65
67 m.SetBaseIndex( aBaseIndex );
68
69 double thr = (double) m.spacing();
70
71 bool fail = false;
72 double remaining = base_len - ( m_last - aBase.A ).EuclideanNorm();
73
74 auto addSingleIfFits = [&]()
75 {
76 fail = true;
77
78 for( int i = 0; i < 2; i++ )
79 {
80 bool checkSide = ( i == 0 ) ? side : !side;
81
82 if( m.Fit( MT_SINGLE, aBase, m_last, checkSide ) )
83 {
84 AddMeander( new MEANDER_SHAPE( m ) );
85 fail = false;
86 started = false;
87 side = !checkSide;
88 break;
89 }
90 }
91 };
92
93 if( remaining < Settings( ).m_step )
94 break;
95
96 if( remaining > 3.0 * thr )
97 {
98 if( !turning )
99 {
100 for( int i = 0; i < 2; i++ )
101 {
102 bool checkSide = ( i == 0 ) ? side : !side;
103
104 if( m.Fit( MT_CHECK_START, aBase, m_last, checkSide ) )
105 {
106 turning = true;
107 AddMeander( new MEANDER_SHAPE( m ) );
108 side = !checkSide;
109 started = true;
110 break;
111 }
112 }
113
114 if( !turning )
115 addSingleIfFits();
116 }
117 else
118 {
119 bool rv = m.Fit( MT_CHECK_FINISH, aBase, m_last, side );
120
121 if( rv )
122 {
123 m.Fit( MT_TURN, aBase, m_last, side );
124 AddMeander( new MEANDER_SHAPE( m ) );
125 started = true;
126 }
127 else
128 {
129 m.Fit( MT_FINISH, aBase, m_last, side );
130 started = false;
131 AddMeander( new MEANDER_SHAPE( m ) );
132 turning = false;
133 }
134
135 side = !side;
136 }
137 }
138 else if( started )
139 {
140 bool rv = m.Fit( MT_FINISH, aBase, m_last, side );
141
142 if( rv )
143 AddMeander( new MEANDER_SHAPE( m ) );
144
145 break;
146
147 }
148 else if( !turning && remaining > thr * 2.0 )
149 {
150 addSingleIfFits();
151 }
152 else
153 {
154 fail = true;
155 }
156
157 remaining = base_len - ( m_last - aBase.A ).EuclideanNorm( );
158
159 if( remaining < Settings( ).m_step )
160 break;
161
162 if( fail )
163 {
166 tmp.SetBaseIndex( aBaseIndex );
167
168 int nextP = tmp.spacing() - 2 * tmp.cornerRadius() + Settings().m_step;
169 VECTOR2I pn = m_last + dir.Resize( nextP );
170
171 if( aBase.Contains( pn ) && !m_dual )
172 {
173 AddCorner( pn );
174 } else
175 break;
176 }
177
178
179 } while( true );
180
181 if( !m_dual )
182 AddCorner( aBase.B );
183}
184
185
187{
188 // TODO: fix diff-pair meandering so we can use non-100% radii
189 int rPercent = m_dual ? 100 : Settings().m_cornerRadiusPercentage;
190
191 return (int64_t) spacing() * rPercent / 200;
192}
193
194
196{
197 if( !m_dual )
198 {
199 return std::max( m_width + m_placer->Clearance(), Settings().m_spacing );
200 }
201 else
202 {
203 int sp = m_width + m_placer->Clearance() + ( 2 * std::abs( m_baselineOffset ) );
204 return std::max( sp, Settings().m_spacing );
205 }
206}
207
208
210 bool aSide )
211{
213
214 if( aDir.EuclideanNorm( ) == 0.0f )
215 {
216 lc.Append( aP );
217 return lc;
218 }
219
220 VECTOR2D dir_u( aDir );
221 VECTOR2D dir_v( aDir.Perpendicular( ) );
222 VECTOR2D p = aP;
223 lc.Append( ( int ) p.x, ( int ) p.y );
224
225 // fixme: refactor
227 {
229 {
230 VECTOR2D center = aP + dir_v * ( aSide ? -1.0 : 1.0 );
231
232 lc.Append( SHAPE_ARC( center, aP, ( aSide ? -ANGLE_90 : ANGLE_90 ) ) );
233 }
234 break;
235
237 {
238 double radius = (double) aDir.EuclideanNorm();
239 double correction = 0;
240
241 if( m_dual && radius > m_meanCornerRadius )
242 correction = (double)( -2 * abs(m_baselineOffset) ) * tan( 22.5 * M_PI / 180.0 );
243
244 VECTOR2D dir_cu = dir_u.Resize( correction );
245 VECTOR2D dir_cv = dir_v.Resize( correction );
246
247 p = aP - dir_cu;
248 lc.Append( ( int ) p.x, ( int ) p.y );
249 p = aP + dir_u + (dir_v + dir_cv) * ( aSide ? -1.0 : 1.0 );
250 lc.Append( ( int ) p.x, ( int ) p.y );
251 }
252 break;
253 }
254
255 p = aP + dir_u + dir_v * ( aSide ? -1.0 : 1.0 );
256 lc.Append( ( int ) p.x, ( int ) p.y );
257
258 return lc;
259}
260
261
262void MEANDER_SHAPE::start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir )
263{
264 m_currentTarget = aTarget;
266 m_currentTarget->Append( aWhere );
267 m_currentDir = aDir;
268 m_currentPos = aWhere;
269}
270
271
272void MEANDER_SHAPE::forward( int aLength )
273{
274 m_currentPos += m_currentDir.Resize( aLength );
276}
277
278
279void MEANDER_SHAPE::turn( const EDA_ANGLE& aAngle )
280{
281 RotatePoint( m_currentDir, aAngle );
282}
283
284
285void MEANDER_SHAPE::miter( int aRadius, bool aSide )
286{
287 if( aRadius <= 0 )
288 {
289 turn( aSide ? ANGLE_90 : -ANGLE_90 );
290 return;
291 }
292
293 VECTOR2D dir = m_currentDir.Resize( (double) aRadius );
294 SHAPE_LINE_CHAIN lc = makeMiterShape( m_currentPos, dir, aSide );
295
296 m_currentPos = lc.CPoint( -1 );
297 turn( aSide ? ANGLE_90 : -ANGLE_90 );
298
299 m_currentTarget->Append( lc );
300}
301
302
303void MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop )
304{
305 forward( aSides );
306 miter( aCorner, true );
307 forward( aTop );
308 miter( aCorner, true );
309 forward( aSides );
310}
311
312
314 bool aSide, MEANDER_TYPE aType, int aAmpl,
315 int aBaselineOffset )
316{
317 int cr = cornerRadius();
318 int offset = aBaselineOffset;
319 int spc = spacing();
320
321 if( aSide )
322 offset *= -1;
323
324 VECTOR2D dir_u_b( aDir.Resize( offset ) );
325 VECTOR2D dir_v_b( dir_u_b.Perpendicular() );
326
327 if( 2 * cr > aAmpl )
328 {
329 cr = aAmpl / 2;
330 }
331
332 if( 2 * cr > spc )
333 {
334 cr = spc / 2;
335 }
336
338
340
341 start( &lc, aP + dir_v_b, aDir );
342
343 switch( aType )
344 {
345 case MT_EMPTY:
346 {
347 lc.Append( aP + dir_v_b + aDir );
348 break;
349 }
350 case MT_START:
351 {
352 miter( cr - offset, false );
353 uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
354 forward( std::min( cr - offset, cr + offset ) );
355 forward( std::abs( offset ) );
356 break;
357 }
358
359 case MT_FINISH:
360 {
361 start( &lc, aP - dir_u_b, aDir );
362 turn( -ANGLE_90 );
363 forward( std::min( cr - offset, cr + offset ) );
364 forward( std::abs( offset ) );
365 uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
366 miter( cr - offset, false );
367 break;
368 }
369
370 case MT_TURN:
371 {
372 start( &lc, aP - dir_u_b, aDir );
373 turn( -ANGLE_90 );
374 forward( std::abs( offset ) );
375 uShape( aAmpl - cr, cr + offset, spc - 2 * cr );
376 forward( std::abs( offset ) );
377 break;
378 }
379
380 case MT_SINGLE:
381 {
382 miter( cr - offset, false );
383 uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
384 miter( cr - offset, false );
385 lc.Append( aP + dir_v_b + aDir.Resize( 2 * spc ) );
386 break;
387 }
388
389 default:
390 break;
391 }
392
393 if( aSide )
394 {
395 SEG axis( aP, aP + aDir );
396
397 lc.Mirror( axis );
398 }
399
400 return lc;
401}
402
403
405{
406 for( int i = m_meanders.size() - 1; i >= 0; i-- )
407 {
409
410 if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
411 continue;
412
413 const SEG& b1 = aShape->BaseSegment();
414 const SEG& b2 = m->BaseSegment();
415
416 if( b1.ApproxParallel( b2 ) )
417 continue;
418
419 int n = m->CLine( 0 ).SegmentCount();
420
421 for( int j = n - 1; j >= 0; j-- )
422 {
423 if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
424 return false;
425 }
426 }
427
428 return true;
429}
430
431
432bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
433{
434 const MEANDER_SETTINGS& st = Settings();
435
436 bool checkMode = false;
437 MEANDER_TYPE prim1, prim2;
438
439 if( aType == MT_CHECK_START )
440 {
441 prim1 = MT_START;
442 prim2 = MT_TURN;
443 checkMode = true;
444 }
445 else if( aType == MT_CHECK_FINISH )
446 {
447 prim1 = MT_TURN;
448 prim2 = MT_FINISH;
449 checkMode = true;
450 }
451
452 if( checkMode )
453 {
456
459
460 bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
461 bool c2 = false;
462
463 if( c1 )
464 c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
465
466 if( c1 && c2 )
467 {
468 m_type = prim1;
469 m_shapes[0] = m1.m_shapes[0];
470 m_shapes[1] = m1.m_shapes[1];
471 m_baseSeg =aSeg;
472 m_p0 = aP;
473 m_side = aSide;
474 m_amplitude = m1.Amplitude();
475 m_dual = m1.m_dual;
476 m_baseSeg = m1.m_baseSeg;
480 return true;
481 }
482 else
483 {
484 return false;
485 }
486 }
487
488 int minAmpl = st.m_minAmplitude;
489 int maxAmpl = st.m_maxAmplitude;
490
491 if( m_dual )
492 {
493 minAmpl = std::max( minAmpl, 2 * std::abs( m_baselineOffset ) );
494 maxAmpl = std::max( maxAmpl, 2 * std::abs( m_baselineOffset ) );
495 }
496
497 for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
498 {
499 if( m_dual )
500 {
501 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl,
503 m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl,
505 }
506 else
507 {
508 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, 0 );
509 }
510
511 m_type = aType;
512 m_baseSeg = aSeg;
513 m_p0 = aP;
514 m_side = aSide;
515 m_amplitude = ampl;
516
518
519 if( m_placer->CheckFit( this ) )
520 return true;
521 }
522
523 return false;
524}
525
526
528{
530 m_dual ? m_baselineOffset : 0 );
531
532 if( m_dual )
535
537}
538
539
540void MEANDER_SHAPE::Resize( int aAmpl )
541{
542 if( aAmpl < 0 )
543 return;
544
545 m_amplitude = aAmpl;
546
547 Recalculate();
548}
549
550
552{
554
556
558
560
561 if( m_dual )
563}
564
565
566void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
567{
569
570 m->MakeCorner( aA, aB );
571 m_last = aA;
572
573 m_meanders.push_back( m );
574}
575
576
577void MEANDERED_LINE::AddArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
578{
580
581 m->MakeArc( aArc1, aArc2 );
582 m_last = aArc1.GetP1();
583
584 m_meanders.push_back( m );
585}
586
587
588void MEANDERED_LINE::AddArcAndPt( const SHAPE_ARC& aArc1, const VECTOR2I& aPt2 )
589{
590 SHAPE_ARC arc2( aPt2, aPt2, aPt2, 0 );
591
592 AddArc( aArc1, arc2 );
593}
594
595
596void MEANDERED_LINE::AddPtAndArc( const VECTOR2I& aPt1, const SHAPE_ARC& aArc2 )
597{
598 SHAPE_ARC arc1( aPt1, aPt1, aPt1, 0 );
599
600 AddArc( arc1, aArc2 );
601}
602
603
604void MEANDER_SHAPE::MakeCorner( const VECTOR2I& aP1, const VECTOR2I& aP2 )
605{
607 m_shapes[0].Clear();
608 m_shapes[1].Clear();
609 m_shapes[0].Append( aP1 );
610 m_shapes[1].Append( aP2 );
611 m_clippedBaseSeg.A = aP1;
612 m_clippedBaseSeg.B = aP1;
613}
614
615
616void MEANDER_SHAPE::MakeArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
617{
619 m_shapes[0].Clear();
620 m_shapes[1].Clear();
621 m_shapes[0].Append( aArc1 );
622 m_shapes[1].Append( aArc2 );
623 m_clippedBaseSeg.A = aArc1.GetP1();
624 m_clippedBaseSeg.B = aArc1.GetP1();
625}
626
627
629{
630 m_last = aShape->BaseSegment().B;
631 m_meanders.push_back( aShape );
632}
633
634
636{
637 for( MEANDER_SHAPE* m : m_meanders )
638 {
639 delete m;
640 }
641
642 m_meanders.clear( );
643}
644
645
647{
648 return m_clippedBaseSeg.Length();
649}
650
651
653{
654 return CLine( 0 ).Length();
655}
656
657
659{
660 if( m_dual )
661 {
662 VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
663 VECTOR2I midpB = ( CLine( 0 ).CPoint( -1 ) + CLine( 1 ).CPoint( -1 ) ) / 2;
664
667 }
668 else
669 {
672 }
673}
674
675}
Implementation of conversion functions that require both schematic and board internal units.
void AddMeander(MEANDER_SHAPE *aShape)
Add a new meander shape to the meandered line.
MEANDER_PLACER_BASE * m_placer
Definition: pns_meander.h:511
void AddCorner(const VECTOR2I &aA, const VECTOR2I &aB=VECTOR2I(0, 0))
Create a dummy meander shape representing a line corner.
void Clear()
Clear the line geometry, removing all corners and meanders.
std::vector< MEANDER_SHAPE * > m_meanders
Definition: pns_meander.h:512
void MeanderSegment(const SEG &aSeg, bool aSide, int aBaseIndex=0)
Fit maximum amplitude meanders on a given segment and adds to the current line.
Definition: pns_meander.cpp:45
void AddArc(const SHAPE_ARC &aArc1, const SHAPE_ARC &aArc2=SHAPE_ARC())
Create a dummy meander shape representing an arc corner.
void AddArcAndPt(const SHAPE_ARC &aArc1, const VECTOR2I &aPt2)
Create a dummy meander shape representing an arc corner.
bool CheckSelfIntersections(MEANDER_SHAPE *aShape, int aClearance)
Check if the given shape is intersecting with any other meander in the current line.
const MEANDER_SETTINGS & Settings() const
Definition: pns_meander.cpp:39
void AddPtAndArc(const VECTOR2I &aPt1, const SHAPE_ARC &aArc2)
Create a dummy meander shape representing an arc corner.
virtual bool CheckFit(MEANDER_SHAPE *aShape)
Checks if it's OK to place the shape aShape (i.e.
virtual int Clearance()
Return the clearance of the track(s) being length tuned.
virtual const MEANDER_SETTINGS & MeanderSettings() const
Return the current meandering configuration.
Dimensions for the meandering algorithm.
Definition: pns_meander.h:59
int m_minAmplitude
Maximum meandering amplitude.
Definition: pns_meander.h:77
int m_cornerRadiusPercentage
Allowable tuning error.
Definition: pns_meander.h:98
int m_step
Length PadToDie.
Definition: pns_meander.h:86
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
Definition: pns_meander.h:95
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
Definition: pns_meander.h:80
The geometry of a single meander.
Definition: pns_meander.h:111
MEANDER_TYPE m_type
The placer that placed this meander.
Definition: pns_meander.h:333
MEANDER_PLACER_BASE * m_placer
Dual or single line.
Definition: pns_meander.h:336
SEG m_baseSeg
Base segment (clipped).
Definition: pns_meander.h:357
SEG m_clippedBaseSeg
Side (true = right).
Definition: pns_meander.h:360
int Amplitude() const
Definition: pns_meander.h:169
void SetType(MEANDER_TYPE aType)
Set the type of the meander.
Definition: pns_meander.h:137
VECTOR2I End() const
Definition: pns_meander.h:224
void start(SHAPE_LINE_CHAIN *aTarget, const VECTOR2D &aWhere, const VECTOR2D &aDir)
Move turtle forward by aLength.
void SetBaseIndex(int aIndex)
Set an auxiliary index of the segment being meandered in its original LINE.
Definition: pns_meander.h:153
int m_baselineOffset
Average radius of meander corners (for correction of DP meanders).
Definition: pns_meander.h:348
VECTOR2D m_currentDir
The current turtle position.
Definition: pns_meander.h:372
int m_width
Amplitude of the meander.
Definition: pns_meander.h:342
VECTOR2D m_currentPos
The line the turtle is drawing on.
Definition: pns_meander.h:375
SHAPE_LINE_CHAIN m_shapes[2]
Index of the meandered segment in the base line.
Definition: pns_meander.h:366
bool m_side
The actual shapes (0 used for single, both for dual).
Definition: pns_meander.h:363
void updateBaseSegment()
Return sanitized corner radius value.
SHAPE_LINE_CHAIN makeMiterShape(const VECTOR2D &aP, const VECTOR2D &aDir, bool aSide)
Produce a meander shape of given type.
SHAPE_LINE_CHAIN genMeanderShape(const VECTOR2D &aP, const 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.
void MakeArc(const SHAPE_ARC &aArc1, const SHAPE_ARC &aArc2=SHAPE_ARC())
Create a dummy meander shape representing an arc corner.
int m_baseIndex
The current turtle direction.
Definition: pns_meander.h:369
SHAPE_LINE_CHAIN * m_currentTarget
Definition: pns_meander.h:378
bool m_dual
Width of the line.
Definition: pns_meander.h:339
void Recalculate()
Recalculate the line chain representing the meander's shape.
void miter(int aRadius, bool aSide)
Tell the turtle to draw an U-like shape.
void Resize(int aAmpl)
Change the amplitude of the meander shape to aAmpl and recalculates the resulting line chain.
int m_meanCornerRadius
First point of the meandered line.
Definition: pns_meander.h:351
int spacing() const
The type of meander.
int m_amplitude
Offset wrs the base segment (dual only).
Definition: pns_meander.h:345
int cornerRadius() const
Return sanitized spacing value.
void turn(const EDA_ANGLE &aAngle)
Tell the turtle to draw a mitered corner of given radius and turn direction.
void SetBaselineOffset(int aOffset)
Set the parallel offset between the base segment and the meandered line.
Definition: pns_meander.h:293
void forward(int aLength)
Turn the turtle by aAngle.
MEANDER_TYPE Type() const
Definition: pns_meander.h:145
VECTOR2I m_p0
Base segment (unclipped).
Definition: pns_meander.h:354
const MEANDER_SETTINGS & Settings() const
Definition: pns_meander.cpp:33
void MakeEmpty()
Replace the meander with straight bypass line(s), effectively clearing it.
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...
int MaxTunableLength() const
void uShape(int aSides, int aCorner, int aTop)
Generate a 90-degree circular arc.
const SHAPE_LINE_CHAIN & CLine(int aShape) const
Definition: pns_meander.h:232
int BaselineLength() const
const SEG & BaseSegment() const
Return the base segment the meander was fitted to.
Definition: pns_meander.h:259
void MakeCorner(const VECTOR2I &aP1, const VECTOR2I &aP2=VECTOR2I(0, 0))
Create a dummy meander shape representing a line corner.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int Length() const
Return the length (this).
Definition: seg.h:351
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
Definition: seg.h:291
bool Contains(const SEG &aSeg) const
Definition: seg.h:332
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.cpp:302
const VECTOR2I & GetP1() const
Definition: shape_arc.h:113
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
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 Clear()
Remove all points from the line chain.
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both).
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
long long int Length() const
Return length of the line chain in Euclidean metric.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:291
VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
Definition: vector2d.h:305
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:367
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:425
Push and Shove diff pair dimensions (gap) settings dialog.
MEANDER_TYPE
Shapes of available meanders.
Definition: pns_meander.h:37
@ MT_TURN
Definition: pns_meander.h:41
@ MT_CHECK_START
Definition: pns_meander.h:42
@ MT_CHECK_FINISH
Definition: pns_meander.h:43
@ MT_START
Definition: pns_meander.h:39
@ MT_FINISH
Definition: pns_meander.h:40
@ MT_EMPTY
Definition: pns_meander.h:46
@ MT_CORNER
Definition: pns_meander.h:44
@ MT_SINGLE
Definition: pns_meander.h:38
@ MEANDER_STYLE_ROUND
Definition: pns_meander.h:51
@ MEANDER_STYLE_CHAMFER
Definition: pns_meander.h:52
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:412
constexpr double correction
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129