KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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 "pns_node.h"
23#include "pns_itemset.h"
24#include "pns_meander.h"
26#include "pns_router.h"
27#include "pns_debug_decorator.h"
28
29namespace PNS {
30
32const long long int MEANDER_SETTINGS::LENGTH_UNCONSTRAINED( 1000000 * pcbIUScale.IU_PER_MM );
33
35const long long int MEANDER_SETTINGS::DELAY_UNCONSTRAINED( 1000000 * pcbIUScale.IU_PER_PS );
36
37const int MEANDER_SETTINGS::SKEW_UNCONSTRAINED( std::numeric_limits<int>::max() );
38
39
41{
42 m_minAmplitude = 200000;
43 m_maxAmplitude = 1000000;
44 m_step = 50000;
45 m_lenPadToDie = 0;
46 m_spacing = 600000;
49 SetTargetSkew( 0 );
54 m_singleSided = false;
57 m_keepEndpoints = false;
58 m_isTimeDomain = false;
59 m_netClass = nullptr;
60}
61
62
63void MEANDER_SETTINGS::SetTargetLength( long long int aOpt )
64{
65 m_targetLength.SetOpt( aOpt );
66
68 {
70 m_targetLength.SetMax( aOpt );
71 }
72 else
73 {
76 }
77}
78
79
81{
82 SetTargetLength( aConstraint.Opt() );
83
84 if( aConstraint.HasMin() )
85 m_targetLength.SetMin( aConstraint.Min() );
86
87 if( aConstraint.HasMax() )
88 m_targetLength.SetMax( aConstraint.Max() );
89}
90
91
93{
95
97 {
100 }
101 else
102 {
105 }
106}
107
108
110{
111 SetTargetLengthDelay( aConstraint.Opt() );
112
113 if( aConstraint.HasMin() )
114 m_targetLengthDelay.SetMin( aConstraint.Min() );
115
116 if( aConstraint.HasMax() )
117 m_targetLengthDelay.SetMax( aConstraint.Max() );
118}
119
120
122{
123 m_targetSkew.SetOpt( aOpt );
124
126 {
127 m_targetSkew.SetMin( 0 );
128 m_targetSkew.SetMax( aOpt );
129 }
130 else
131 {
134 }
135}
136
137
139{
140 SetTargetSkew( aConstraint.Opt() );
141
142 if( aConstraint.HasMin() )
143 m_targetSkew.SetMin( aConstraint.Min() );
144
145 if( aConstraint.HasMax() )
146 m_targetSkew.SetMax( aConstraint.Max() );
147}
148
149
151{
153
155 {
158 }
159 else
160 {
163 }
164}
165
166
168{
169 SetTargetSkewDelay( aConstraint.Opt() );
170
171 if( aConstraint.HasMin() )
172 m_targetSkewDelay.SetMin( aConstraint.Min() );
173
174 if( aConstraint.HasMax() )
175 m_targetSkewDelay.SetMax( aConstraint.Max() );
176}
177
178
180{
181 return m_placer->MeanderSettings();
182}
183
184
186{
187 return m_placer->MeanderSettings();
188}
189
190
191void MEANDERED_LINE::MeanderSegment( const SEG& aBase, bool aSide, int aBaseIndex )
192{
193 double base_len = aBase.Length();
194
196
197 bool singleSided = Settings().m_singleSided;
198 bool side = aSide;
199 VECTOR2D dir( aBase.B - aBase.A );
200
201 if( !m_dual )
202 AddCorner( aBase.A );
203
204 bool turning = false;
205 bool started = false;
206
207 m_last = aBase.A;
208
209 do
210 {
212
214 m.SetBaseIndex( aBaseIndex );
215
216 double thr = (double) m.spacing();
217
218 bool fail = false;
219 double remaining = base_len - ( m_last - aBase.A ).EuclideanNorm();
220
221 auto flipInitialSide =
222 [&]()
223 {
225 settings.m_initialSide = (PNS::MEANDER_SIDE) -settings.m_initialSide;
226 m_placer->UpdateSettings( settings );
227 };
228
229 auto addSingleIfFits =
230 [&]()
231 {
232 fail = true;
233
234 if( m.Fit( MT_SINGLE, aBase, m_last, side ) )
235 {
236 AddMeander( new MEANDER_SHAPE( m ) );
237 fail = false;
238 started = false;
239 }
240
241 if( fail && !singleSided )
242 {
243 if( m.Fit( MT_SINGLE, aBase, m_last, !side ) )
244 {
245 if( !started )
246 flipInitialSide();
247
248 AddMeander( new MEANDER_SHAPE( m ) );
249 fail = false;
250 started = false;
251 side = !side;
252 }
253 }
254 };
255
256 if( remaining < Settings( ).m_step )
257 break;
258
259 if( !singleSided && remaining > 3.0 * thr )
260 {
261 if( !turning )
262 {
263 for( int i = 0; i < 2; i++ )
264 {
265 bool checkSide = ( i == 0 ) ? side : !side;
266
267 if( m.Fit( MT_CHECK_START, aBase, m_last, checkSide ) )
268 {
269 if( !started && checkSide != side )
270 flipInitialSide();
271
272 turning = true;
273 AddMeander( new MEANDER_SHAPE( m ) );
274 side = !checkSide;
275 started = true;
276 break;
277 }
278 }
279
280 if( !turning )
281 addSingleIfFits();
282 }
283 else
284 {
285 bool rv = m.Fit( MT_CHECK_FINISH, aBase, m_last, side );
286
287 if( rv )
288 {
289 m.Fit( MT_TURN, aBase, m_last, side );
290 AddMeander( new MEANDER_SHAPE( m ) );
291 side = !side;
292 started = true;
293 }
294 else
295 {
296 m.Fit( MT_FINISH, aBase, m_last, side );
297 started = false;
298 AddMeander( new MEANDER_SHAPE( m ) );
299 turning = false;
300 }
301 }
302 }
303 else if( !singleSided && started )
304 {
305 bool rv = m.Fit( MT_FINISH, aBase, m_last, side );
306
307 if( rv )
308 AddMeander( new MEANDER_SHAPE( m ) );
309
310 break;
311
312 }
313 else if( !turning && remaining > thr * 2.0 )
314 {
315 addSingleIfFits();
316 }
317 else
318 {
319 fail = true;
320 }
321
322 remaining = base_len - ( m_last - aBase.A ).EuclideanNorm( );
323
324 if( remaining < Settings( ).m_step )
325 break;
326
327 if( fail )
328 {
331 tmp.SetBaseIndex( aBaseIndex );
332
333 int nextP = tmp.spacing() - 2 * tmp.cornerRadius() + Settings().m_step;
334 VECTOR2I pn = m_last + dir.Resize( nextP );
335
336 if( aBase.Contains( pn ) && !m_dual )
337 AddCorner( pn );
338 else
339 break;
340 }
341
342
343 } while( true );
344
345 if( !m_dual )
346 AddCorner( aBase.B );
347}
348
349
351{
352 int minAmplitude = Settings().m_minAmplitude;
353
355 {
356 minAmplitude = std::max( minAmplitude, std::abs( m_baselineOffset ) + m_width );
357 }
358 else
359 {
360 int correction = m_width * tan( 1 - tan( DEG2RAD( 22.5 ) ) );
361 minAmplitude = std::max( minAmplitude, std::abs( m_baselineOffset ) + correction );
362 }
363
364 return minAmplitude;
365}
366
367
369{
370 if( m_amplitude == 0 )
371 return 0;
372
373 int minCr = 0;
374
376 minCr = std::abs( m_baselineOffset ) + m_width / 2;
377 else
378 minCr = std::abs( m_baselineOffset ) + m_width / 2 * ( 1 - tan( DEG2RAD( 22.5 ) ) );
379
380 int maxCr1 = ( m_amplitude + std::abs( m_baselineOffset ) ) / 2;
381 int maxCr2 = spacing() / 2;
382 int maxCr = std::min( maxCr1, maxCr2 );
383
384 wxCHECK2_MSG( maxCr >= minCr, return maxCr,
385 wxString::Format( "cornerRadius %d < %d amp %d spc %d w %d off %d", maxCr, minCr,
387
388 int rPercent = Settings().m_cornerRadiusPercentage;
389 int optCr = static_cast<int>( static_cast<SEG::ecoord>( spacing() ) * rPercent / 200 );
390
391 return std::clamp( optCr, minCr, maxCr );
392}
393
394
396{
397 if( !m_dual )
398 {
399 return std::max( m_width + m_placer->Clearance(), Settings().m_spacing );
400 }
401 else
402 {
403 int sp = m_width + m_placer->Clearance() + ( 2 * std::abs( m_baselineOffset ) );
404 return std::max( sp, Settings().m_spacing );
405 }
406}
407
408
410 bool aSide )
411{
413
414 if( aDir.EuclideanNorm( ) == 0.0f )
415 {
416 lc.Append( aP );
417 return lc;
418 }
419
420 VECTOR2D dir_u( aDir );
421 VECTOR2D dir_v( aDir.Perpendicular() );
422
423 VECTOR2D endPoint = aP + dir_u + dir_v * ( aSide ? -1.0 : 1.0 );
424 VECTOR2D p = aP;
425 lc.Append( ( int ) p.x, ( int ) p.y );
426
427 // fixme: refactor
429 {
431 {
432 VECTOR2I arcEnd( (int) endPoint.x, (int) endPoint.y );
433
434 SHAPE_ARC arc;
435 arc.ConstructFromStartEndAngle( aP, arcEnd, ( aSide ? -ANGLE_90 : ANGLE_90 ) );
436 lc.Append( arc );
437 break;
438 }
439
441 {
442 double radius = (double) aDir.EuclideanNorm();
443 double correction = 0;
444
446 correction = (double) ( -2 * abs( m_baselineOffset ) ) * tan( DEG2RAD( 22.5 ) );
447
448 VECTOR2D dir_cu = dir_u.Resize( correction );
449 VECTOR2D dir_cv = dir_v.Resize( correction );
450
451 p = aP - dir_cu;
452 lc.Append( ( int ) p.x, ( int ) p.y );
453 p = aP + dir_u + (dir_v + dir_cv) * ( aSide ? -1.0 : 1.0 );
454 lc.Append( ( int ) p.x, ( int ) p.y );
455
456 p = endPoint;
457 lc.Append( (int) p.x, (int) p.y );
458 break;
459 }
460
461 default:
462 break;
463 }
464
465 return lc;
466}
467
468
469void MEANDER_SHAPE::start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir )
470{
471 m_currentTarget = aTarget;
473 m_currentTarget->Append( aWhere );
474 m_currentDir = aDir;
475 m_currentPos = aWhere;
476}
477
478
479void MEANDER_SHAPE::forward( int aLength )
480{
481 // Very small segments cause problems.
482 if( aLength < 5 )
483 return;
484
485 m_currentPos += m_currentDir.Resize( aLength );
487}
488
489
490void MEANDER_SHAPE::turn( const EDA_ANGLE& aAngle )
491{
492 RotatePoint( m_currentDir, aAngle );
493}
494
495
496void MEANDER_SHAPE::miter( int aRadius, bool aSide )
497{
498 if( aRadius <= 0 )
499 {
500 turn( aSide ? ANGLE_90 : -ANGLE_90 );
501 return;
502 }
503
504 VECTOR2D dir = m_currentDir.Resize( (double) aRadius );
505 SHAPE_LINE_CHAIN lc = makeMiterShape( m_currentPos, dir, aSide );
506
507 m_currentPos = lc.CPoint( -1 );
508 turn( aSide ? ANGLE_90 : -ANGLE_90 );
509
510 m_currentTarget->Append( lc );
511}
512
513
514void MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop )
515{
516 forward( aSides );
517 miter( aCorner, true );
518 forward( aTop );
519 miter( aCorner, true );
520 forward( aSides );
521}
522
523
525 bool aSide, MEANDER_TYPE aType,
526 int aBaselineOffset )
527{
528 int cr = cornerRadius();
529 int offset = aBaselineOffset;
530 int spc = spacing();
531 int amplitude = m_amplitude;
532 int targetBaseLen = m_targetBaseLen;
533
534 if( aSide )
535 offset *= -1;
536
537 VECTOR2D dir_u_b( aDir.Resize( offset ) );
538 VECTOR2D dir_v_b( dir_u_b.Perpendicular() );
539
540 if( 2 * cr > amplitude + std::abs( offset ) )
541 cr = ( amplitude + std::abs( offset ) ) / 2;
542
543 if( 2 * cr > spc )
544 cr = spc / 2;
545
546 if( cr - offset < 0 )
547 cr = offset;
548
550
551 int sCorner = cr - offset;
552 int uCorner = cr + offset;
553 int startSide = amplitude - 2 * cr + std::abs( offset );
554 int turnSide = amplitude - cr;
555 int top = spc - 2 * cr;
556
558
559 start( &lc, aP + dir_v_b, aDir );
560
561 switch( aType )
562 {
563 case MT_EMPTY:
564 {
565 lc.Append( aP + dir_v_b + aDir );
566 break;
567 }
568 case MT_START:
569 {
570 if( targetBaseLen )
571 top = std::max( top, targetBaseLen - sCorner - uCorner * 2 + offset );
572
573 miter( sCorner, false );
574 uShape( startSide, uCorner, top );
575 forward( std::min( sCorner, uCorner ) );
576 forward( std::abs( offset ) );
577 break;
578 }
579
580 case MT_FINISH:
581 {
582 if( targetBaseLen )
583 top = std::max( top, targetBaseLen - cr - spc );
584
585 start( &lc, aP - dir_u_b, aDir );
586 turn( -ANGLE_90 );
587 forward( std::min( sCorner, uCorner ) );
588 forward( std::abs( offset ) );
589 uShape( startSide, uCorner, top );
590 miter( sCorner, false );
591
592 if( targetBaseLen >= spc + cr )
593 lc.Append( aP + dir_v_b + aDir.Resize( targetBaseLen ) );
594 else
595 lc.Append( aP + dir_v_b + aDir.Resize( 2 * spc - cr ) );
596
597 break;
598 }
599
600 case MT_TURN:
601 {
602 if( targetBaseLen )
603 top = std::max( top, targetBaseLen - uCorner * 2 + offset * 2 );
604
605 start( &lc, aP - dir_u_b, aDir );
606 turn( -ANGLE_90 );
607 forward( std::abs( offset ) );
608 uShape( turnSide, uCorner, top );
609 forward( std::abs( offset ) );
610 break;
611 }
612
613 case MT_SINGLE:
614 {
615 if( targetBaseLen )
616 top = std::max( top, ( targetBaseLen - sCorner * 2 - uCorner * 2 ) / 2 );
617
618 miter( sCorner, false );
619 uShape( startSide, uCorner, top );
620 miter( sCorner, false );
621 lc.Append( aP + dir_v_b + aDir.Resize( 2 * spc ) );
622 break;
623 }
624
625 default:
626 break;
627 }
628
629 if( aSide )
630 {
631 SEG axis( aP, aP + aDir );
632
633 lc.Mirror( axis );
634 }
635
636 return lc;
637}
638
639
641{
642 for( int i = m_meanders.size() - 1; i >= 0; i-- )
643 {
645
646 if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
647 continue;
648
649 const SEG& b1 = aShape->BaseSegment();
650 const SEG& b2 = m->BaseSegment();
651
652 if( b1.ApproxParallel( b2 ) )
653 continue;
654
655 int n = m->CLine( 0 ).SegmentCount();
656
657 for( int j = n - 1; j >= 0; j-- )
658 {
659 if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
660 return false;
661 }
662 }
663
664 return true;
665}
666
667
668bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
669{
670 const MEANDER_SETTINGS& st = Settings();
671
672 bool checkMode = false;
673 MEANDER_TYPE prim1, prim2;
674
675 if( aType == MT_CHECK_START )
676 {
677 prim1 = MT_START;
678 prim2 = MT_TURN;
679 checkMode = true;
680 }
681 else if( aType == MT_CHECK_FINISH )
682 {
683 prim1 = MT_TURN;
684 prim2 = MT_FINISH;
685 checkMode = true;
686 }
687
688 if( checkMode )
689 {
692
694 m2.SetBaselineOffset( m_baselineOffset );
695
696 bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
697 bool c2 = false;
698
699 if( c1 )
700 c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
701
702 if( c1 && c2 )
703 {
704 m_type = prim1;
705 m_shapes[0] = m1.m_shapes[0];
706 m_shapes[1] = m1.m_shapes[1];
707 m_baseSeg =aSeg;
708 m_p0 = aP;
709 m_side = aSide;
710 m_amplitude = m1.Amplitude();
711 m_dual = m1.m_dual;
712 m_baseSeg = m1.m_baseSeg;
716 return true;
717 }
718 else
719 {
720 return false;
721 }
722 }
723
724 int minAmpl = MinAmplitude();
725 int maxAmpl = std::max( st.m_maxAmplitude, minAmpl );
726
727 for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
728 {
729 m_amplitude = ampl;
730
731 if( m_dual )
732 {
733 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, m_baselineOffset );
734 m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, -m_baselineOffset );
735 }
736 else
737 {
738 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, 0 );
739 }
740
741 m_type = aType;
742 m_baseSeg = aSeg;
743 m_p0 = aP;
744 m_side = aSide;
745
747
748 if( m_placer->CheckFit( this ) )
749 return true;
750 }
751
752 return false;
753}
754
755
757{
759 m_dual ? m_baselineOffset : 0 );
760
761 if( m_dual )
764
766}
767
768
769void MEANDER_SHAPE::Resize( int aAmpl )
770{
771 if( aAmpl < 0 )
772 return;
773
774 m_amplitude = aAmpl;
775
776 Recalculate();
777}
778
779
781{
783
785
787 m_amplitude = 0;
788
790
791 if( m_dual )
793}
794
795
796void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
797{
799
800 m->MakeCorner( aA, aB );
801 m_last = aA;
802
803 m_meanders.push_back( m );
804}
805
806
807void MEANDERED_LINE::AddArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
808{
810
811 m->MakeArc( aArc1, aArc2 );
812 m_last = aArc1.GetP1();
813
814 m_meanders.push_back( m );
815}
816
817
818void MEANDERED_LINE::AddArcAndPt( const SHAPE_ARC& aArc1, const VECTOR2I& aPt2 )
819{
820 SHAPE_ARC arc2( aPt2, aPt2, aPt2, 0 );
821
822 AddArc( aArc1, arc2 );
823}
824
825
826void MEANDERED_LINE::AddPtAndArc( const VECTOR2I& aPt1, const SHAPE_ARC& aArc2 )
827{
828 SHAPE_ARC arc1( aPt1, aPt1, aPt1, 0 );
829
830 AddArc( arc1, aArc2 );
831}
832
833
834void MEANDER_SHAPE::MakeCorner( const VECTOR2I& aP1, const VECTOR2I& aP2 )
835{
837 m_shapes[0].Clear();
838 m_shapes[1].Clear();
839 m_shapes[0].Append( aP1 );
840 m_shapes[1].Append( aP2 );
841 m_clippedBaseSeg.A = aP1;
842 m_clippedBaseSeg.B = aP1;
843}
844
845
846void MEANDER_SHAPE::MakeArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
847{
849 m_shapes[0].Clear();
850 m_shapes[1].Clear();
851 m_shapes[0].Append( aArc1 );
852 m_shapes[1].Append( aArc2 );
853 m_clippedBaseSeg.A = aArc1.GetP1();
854 m_clippedBaseSeg.B = aArc1.GetP1();
855}
856
857
859{
860 m_last = aShape->BaseSegment().B;
861 m_meanders.push_back( aShape );
862}
863
864
866{
867 for( MEANDER_SHAPE* m : m_meanders )
868 delete m;
869
870 m_meanders.clear( );
871}
872
873
875{
876 return m_clippedBaseSeg.Length();
877}
878
879
880long long int MEANDER_SHAPE::CurrentLength() const
881{
882 return CLine( 0 ).Length();
883}
884
885
887{
888 MEANDER_SHAPE copy = *this;
889
890 copy.SetTargetBaselineLength( BaselineLength() );
891 copy.Resize( copy.MinAmplitude() );
892
893 return copy.CurrentLength();
894}
895
896
898{
899 if( m_dual )
900 {
901 VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
902 VECTOR2I midpB = ( CLine( 0 ).CPoint( -1 ) + CLine( 1 ).CPoint( -1 ) ) / 2;
903
906 }
907 else
908 {
911 }
912}
913
914}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:110
T Min() const
Definition: minoptmax.h:33
void SetMin(T v)
Definition: minoptmax.h:41
bool HasMax() const
Definition: minoptmax.h:38
void SetOpt(T v)
Definition: minoptmax.h:43
bool HasMin() const
Definition: minoptmax.h:37
void SetMax(T v)
Definition: minoptmax.h:42
T Max() const
Definition: minoptmax.h:34
T Opt() const
Definition: minoptmax.h:35
void AddMeander(MEANDER_SHAPE *aShape)
Add a new meander shape to the meandered line.
MEANDER_PLACER_BASE * m_placer
Definition: pns_meander.h:572
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:573
void MeanderSegment(const SEG &aSeg, bool aSide, int aBaseIndex=0)
Fit maximum amplitude meanders on a given segment and adds to the current line.
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
void AddPtAndArc(const VECTOR2I &aPt1, const SHAPE_ARC &aArc2)
Create a dummy meander shape representing an arc corner.
virtual void UpdateSettings(const MEANDER_SETTINGS &aSettings)
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:68
int m_minAmplitude
Maximum meandering amplitude.
Definition: pns_meander.h:93
void SetTargetLength(long long int aOpt)
Definition: pns_meander.cpp:63
bool m_isTimeDomain
The net class this meander pattern belongs to.
Definition: pns_meander.h:140
static const long long int LENGTH_UNCONSTRAINED
Definition: pns_meander.h:71
int m_cornerRadiusPercentage
Place meanders on one side.
Definition: pns_meander.h:125
MEANDER_SIDE m_initialSide
Allowable tuning error.
Definition: pns_meander.h:131
bool m_singleSided
Initial side when placing meanders at segment.
Definition: pns_meander.h:128
void SetTargetLengthDelay(long long int aOpt)
Definition: pns_meander.cpp:92
static const int SKEW_UNCONSTRAINED
Definition: pns_meander.h:76
static const long long int DEFAULT_DELAY_TOLERANCE
Definition: pns_meander.h:73
MINOPTMAX< long long int > m_targetLength
Desired propagation delay of the tuned line.
Definition: pns_meander.h:108
void SetTargetSkew(int aOpt)
static const long long int DEFAULT_LENGTH_TOLERANCE
Definition: pns_meander.h:70
int m_lengthTolerance
Keep vertices between pre, tuned and post parts of the line.
Definition: pns_meander.h:134
int m_step
Length PadToDie.
Definition: pns_meander.h:102
MINOPTMAX< int > m_targetSkew
Target skew value for diff pair de-skewing.
Definition: pns_meander.h:114
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
Definition: pns_meander.h:122
bool m_keepEndpoints
Calculate tuning in the time domain.
Definition: pns_meander.h:137
MINOPTMAX< int > m_targetSkewDelay
Definition: pns_meander.h:117
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
Definition: pns_meander.h:96
bool m_overrideCustomRules
Type of corners for the meandered line.
Definition: pns_meander.h:119
MINOPTMAX< long long int > m_targetLengthDelay
Target skew value for diff pair de-skewing.
Definition: pns_meander.h:111
void SetTargetSkewDelay(int aOpt)
static const long long int DELAY_UNCONSTRAINED
Definition: pns_meander.h:74
int m_lenPadToDie
Desired length of the tuned line/diff pair (this is in nm, so allow more than board width).
Definition: pns_meander.h:105
int m_spacing
Amplitude/spacing adjustment step.
Definition: pns_meander.h:99
The geometry of a single meander.
Definition: pns_meander.h:150
MEANDER_TYPE m_type
The placer that placed this meander.
Definition: pns_meander.h:391
int MinAmplitude() const
MEANDER_PLACER_BASE * m_placer
Dual or single line.
Definition: pns_meander.h:394
SEG m_baseSeg
Base segment (clipped).
Definition: pns_meander.h:418
SEG m_clippedBaseSeg
Side (true = right).
Definition: pns_meander.h:421
int Amplitude() const
Definition: pns_meander.h:209
void SetType(MEANDER_TYPE aType)
Set the type of the meander.
Definition: pns_meander.h:177
int m_targetBaseLen
First point of the meandered line.
Definition: pns_meander.h:412
VECTOR2I End() const
Definition: pns_meander.h:264
SHAPE_LINE_CHAIN genMeanderShape(const VECTOR2D &aP, const VECTOR2D &aDir, bool aSide, MEANDER_TYPE aType, int aBaselineOffset=0)
Recalculate the clipped baseline after the parameters of the meander have been changed.
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:193
int m_baselineOffset
Average radius of meander corners (for correction of DP meanders).
Definition: pns_meander.h:406
VECTOR2D m_currentDir
The current turtle position.
Definition: pns_meander.h:433
int m_width
Amplitude of the meander.
Definition: pns_meander.h:400
VECTOR2D m_currentPos
The line the turtle is drawing on.
Definition: pns_meander.h:436
SHAPE_LINE_CHAIN m_shapes[2]
Index of the meandered segment in the base line.
Definition: pns_meander.h:427
long long int CurrentLength() const
bool m_side
The actual shapes (0 used for single, both for dual).
Definition: pns_meander.h:424
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.
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:430
SHAPE_LINE_CHAIN * m_currentTarget
Definition: pns_meander.h:439
bool m_dual
Width of the line.
Definition: pns_meander.h:397
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.
long long int MinTunableLength() const
void Resize(int aAmpl)
Change the amplitude of the meander shape to aAmpl and recalculates the resulting line chain.
int m_meanCornerRadius
Minimum length of the base segment to target when resizing.
Definition: pns_meander.h:409
int spacing() const
The type of meander.
int m_amplitude
Offset wrs the base segment (dual only).
Definition: pns_meander.h:403
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:343
void forward(int aLength)
Turn the turtle by aAngle.
MEANDER_TYPE Type() const
Definition: pns_meander.h:185
VECTOR2I m_p0
Base segment (unclipped).
Definition: pns_meander.h:415
const MEANDER_SETTINGS & Settings() const
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...
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:272
int BaselineLength() const
const SEG & BaseSegment() const
Return the base segment the meander was fitted to.
Definition: pns_meander.h:299
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::extended_type ecoord
Definition: seg.h:44
VECTOR2I B
Definition: seg.h:50
int Length() const
Return the length (this).
Definition: seg.h:333
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
Definition: seg.cpp:545
bool Contains(const SEG &aSeg) const
Definition: seg.h:314
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:417
SHAPE_ARC & ConstructFromStartEndAngle(const VECTOR2I &aStart, const VECTOR2I &aEnd, const EDA_ANGLE &aAngle, double aWidth=0)
Construct this arc from the given start, end and angle.
Definition: shape_arc.cpp:195
const VECTOR2I & GetP1() const
Definition: shape_arc.h:117
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 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.
void Mirror(const VECTOR2I &aRef, FLIP_DIRECTION aFlipDirection)
Mirror the line points about y or x (or both).
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:283
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
Definition: vector2d.h:314
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:385
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:406
Push and Shove diff pair dimensions (gap) settings dialog.
MEANDER_TYPE
Shapes of available meanders.
Definition: pns_meander.h:38
@ MT_TURN
Definition: pns_meander.h:42
@ MT_CHECK_START
Definition: pns_meander.h:43
@ MT_CHECK_FINISH
Definition: pns_meander.h:44
@ MT_START
Definition: pns_meander.h:40
@ MT_FINISH
Definition: pns_meander.h:41
@ MT_EMPTY
Definition: pns_meander.h:47
@ MT_CORNER
Definition: pns_meander.h:45
@ MT_SINGLE
Definition: pns_meander.h:39
MEANDER_SIDE
Definition: pns_meander.h:58
@ MEANDER_SIDE_LEFT
Definition: pns_meander.h:59
@ MEANDER_STYLE_ROUND
Definition: pns_meander.h:52
@ MEANDER_STYLE_CHAMFER
Definition: pns_meander.h:53
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:393
constexpr double correction
const double IU_PER_PS
Internal time units are attoseconds.
Definition: base_units.h:78
const double IU_PER_MM
Definition: base_units.h:76
constexpr int mmToIU(double mm) const
Definition: base_units.h:90
MATRIX3x3D m2(VECTOR3I{ 6, 6, 6 }, { 1, 1, 1 }, { 3, 3, 3 })
Test suite for KiCad math code.
SHAPE_ARC arc2(c.m_arc2.GenerateArc())
int radius
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
double DEG2RAD(double deg)
Definition: trigo.h:166