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
61
62
63void MEANDER_SETTINGS::SetTargetLength( long long int aOpt )
64{
65 m_targetLength.SetOpt( aOpt );
66
68 {
69 m_targetLength.SetMin( 0 );
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{
94 m_targetLengthDelay.SetOpt( aOpt );
95
97 {
98 m_targetLengthDelay.SetMin( 0 );
99 m_targetLengthDelay.SetMax( aOpt );
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 {
132 m_targetSkew.SetMin( aOpt - DEFAULT_LENGTH_TOLERANCE );
133 m_targetSkew.SetMax( aOpt + DEFAULT_LENGTH_TOLERANCE );
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{
152 m_targetSkewDelay.SetOpt( aOpt );
153
155 {
156 m_targetSkewDelay.SetMin( 0 );
157 m_targetSkewDelay.SetMax( aOpt );
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 {
224 MEANDER_SETTINGS settings = m_placer->MeanderSettings();
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
354 if( m_placer->MeanderSettings().m_cornerStyle == MEANDER_STYLE_ROUND )
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
375 if( m_placer->MeanderSettings().m_cornerStyle == MEANDER_STYLE_ROUND )
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
428 switch( m_placer->MeanderSettings().m_cornerStyle )
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;
472 m_currentTarget->Clear();
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 );
486 m_currentTarget->Append( m_currentPos );
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
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 = MT_EMPTY;
674 MEANDER_TYPE prim2 = MT_EMPTY;
675
676 if( aType == MT_CHECK_START )
677 {
678 prim1 = MT_START;
679 prim2 = MT_TURN;
680 checkMode = true;
681 }
682 else if( aType == MT_CHECK_FINISH )
683 {
684 prim1 = MT_TURN;
685 prim2 = MT_FINISH;
686 checkMode = true;
687 }
688
689 if( checkMode )
690 {
693
695 m2.SetBaselineOffset( m_baselineOffset );
696
697 bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
698 bool c2 = false;
699
700 if( c1 )
701 c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
702
703 if( c1 && c2 )
704 {
705 m_type = prim1;
706 m_shapes[0] = m1.m_shapes[0];
707 m_shapes[1] = m1.m_shapes[1];
708 m_baseSeg =aSeg;
709 m_p0 = aP;
710 m_side = aSide;
711 m_amplitude = m1.Amplitude();
712 m_dual = m1.m_dual;
713 m_baseSeg = m1.m_baseSeg;
717 return true;
718 }
719 else
720 {
721 return false;
722 }
723 }
724
725 int minAmpl = MinAmplitude();
726 int maxAmpl = std::max( st.m_maxAmplitude, minAmpl );
727
728 for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
729 {
730 m_amplitude = ampl;
731
732 if( m_dual )
733 {
734 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, m_baselineOffset );
735 m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, -m_baselineOffset );
736 }
737 else
738 {
739 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, 0 );
740 }
741
742 m_type = aType;
743 m_baseSeg = aSeg;
744 m_p0 = aP;
745 m_side = aSide;
746
748
749 if( m_placer->CheckFit( this ) )
750 return true;
751 }
752
753 return false;
754}
755
756
768
769
770void MEANDER_SHAPE::Resize( int aAmpl )
771{
772 if( aAmpl < 0 )
773 return;
774
775 m_amplitude = aAmpl;
776
777 Recalculate();
778}
779
780
795
796
797void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
798{
800
801 m->MakeCorner( aA, aB );
802 m_last = aA;
803
804 m_meanders.push_back( m );
805}
806
807
808void MEANDERED_LINE::AddArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
809{
811
812 m->MakeArc( aArc1, aArc2 );
813 m_last = aArc1.GetP1();
814
815 m_meanders.push_back( m );
816}
817
818
819void MEANDERED_LINE::AddArcAndPt( const SHAPE_ARC& aArc1, const VECTOR2I& aPt2 )
820{
821 SHAPE_ARC arc2( aPt2, aPt2, aPt2, 0 );
822
823 AddArc( aArc1, arc2 );
824}
825
826
827void MEANDERED_LINE::AddPtAndArc( const VECTOR2I& aPt1, const SHAPE_ARC& aArc2 )
828{
829 SHAPE_ARC arc1( aPt1, aPt1, aPt1, 0 );
830
831 AddArc( arc1, aArc2 );
832}
833
834
835void MEANDER_SHAPE::MakeCorner( const VECTOR2I& aP1, const VECTOR2I& aP2 )
836{
838 m_shapes[0].Clear();
839 m_shapes[1].Clear();
840 m_shapes[0].Append( aP1 );
841 m_shapes[1].Append( aP2 );
842 m_clippedBaseSeg.A = aP1;
843 m_clippedBaseSeg.B = aP1;
844}
845
846
847void MEANDER_SHAPE::MakeArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
848{
850 m_shapes[0].Clear();
851 m_shapes[1].Clear();
852 m_shapes[0].Append( aArc1 );
853 m_shapes[1].Append( aArc2 );
854 m_clippedBaseSeg.A = aArc1.GetP1();
855 m_clippedBaseSeg.B = aArc1.GetP1();
856}
857
858
860{
861 m_last = aShape->BaseSegment().B;
862 m_meanders.push_back( aShape );
863}
864
865
867{
868 for( MEANDER_SHAPE* m : m_meanders )
869 delete m;
870
871 m_meanders.clear( );
872}
873
874
876{
877 return m_clippedBaseSeg.Length();
878}
879
880
881long long int MEANDER_SHAPE::CurrentLength() const
882{
883 return CLine( 0 ).Length();
884}
885
886
888{
889 MEANDER_SHAPE copy = *this;
890
891 copy.SetTargetBaselineLength( BaselineLength() );
892 copy.Resize( copy.MinAmplitude() );
893
894 return copy.CurrentLength();
895}
896
897
899{
900 if( m_dual )
901 {
902 VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
903 VECTOR2I midpB = ( CLine( 0 ).CLastPoint() + CLine( 1 ).CLastPoint() ) / 2;
904
905 m_clippedBaseSeg.A = m_baseSeg.LineProject( midpA );
906 m_clippedBaseSeg.B = m_baseSeg.LineProject( midpB );
907 }
908 else
909 {
910 m_clippedBaseSeg.A = m_baseSeg.LineProject( CLine( 0 ).CPoint( 0 ) );
911 m_clippedBaseSeg.B = m_baseSeg.LineProject( CLine( 0 ).CLastPoint() );
912 }
913}
914
915}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
T Min() const
Definition minoptmax.h:33
bool HasMax() const
Definition minoptmax.h:38
bool HasMin() const
Definition minoptmax.h:37
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
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
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.
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)
bool m_isTimeDomain
The net class this meander pattern belongs to.
static const long long int LENGTH_UNCONSTRAINED
Definition pns_meander.h:71
int m_cornerRadiusPercentage
Place meanders on one side.
MEANDER_SIDE m_initialSide
Allowable tuning error.
bool m_singleSided
Initial side when placing meanders at segment.
void SetTargetLengthDelay(long long int aOpt)
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.
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.
int m_step
Length PadToDie.
MINOPTMAX< int > m_targetSkew
Target skew value for diff pair de-skewing.
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
bool m_keepEndpoints
Calculate tuning in the time domain.
MINOPTMAX< int > m_targetSkewDelay
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.
MINOPTMAX< long long int > m_targetLengthDelay
Target skew value for diff pair de-skewing.
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).
int m_spacing
Amplitude/spacing adjustment step.
Definition pns_meander.h:99
The geometry of a single meander.
MEANDER_TYPE m_type
The placer that placed this meander.
int MinAmplitude() const
MEANDER_PLACER_BASE * m_placer
Dual or single line.
SEG m_baseSeg
Base segment (clipped).
MEANDER_SHAPE(MEANDER_PLACER_BASE *aPlacer, int aWidth, bool aIsDual=false)
SEG m_clippedBaseSeg
Side (true = right).
int Amplitude() const
void SetType(MEANDER_TYPE aType)
Set the type of the meander.
int m_targetBaseLen
First point of the meandered line.
VECTOR2I End() const
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.
int m_baselineOffset
Average radius of meander corners (for correction of DP meanders).
VECTOR2D m_currentDir
The current turtle position.
int m_width
Amplitude of the meander.
VECTOR2D m_currentPos
The line the turtle is drawing on.
SHAPE_LINE_CHAIN m_shapes[2]
Index of the meandered segment in the base line.
long long int CurrentLength() const
bool m_side
The actual shapes (0 used for single, both for dual).
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.
SHAPE_LINE_CHAIN * m_currentTarget
bool m_dual
Width of the line.
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.
int spacing() const
The type of meander.
int m_amplitude
Offset wrs the base segment (dual only).
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.
void forward(int aLength)
Turn the turtle by aAngle.
MEANDER_TYPE Type() const
VECTOR2I m_p0
Base segment (unclipped).
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
int BaselineLength() const
const SEG & BaseSegment() const
Return the base segment the meander was fitted to.
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:343
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
Definition seg.cpp:778
bool Contains(const SEG &aSeg) const
Definition seg.h:324
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.
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 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 VECTOR2I & CLastPoint() const
Return the last point in the 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:413
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:400
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:92
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
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694