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 // Clear the current target pointer to avoid dangling pointer after lc goes out of scope
637 m_currentTarget = nullptr;
638
639 return lc;
640}
641
642
644{
645 for( int i = m_meanders.size() - 1; i >= 0; i-- )
646 {
648
649 if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
650 continue;
651
652 const SEG& b1 = aShape->BaseSegment();
653 const SEG& b2 = m->BaseSegment();
654
655 if( b1.ApproxParallel( b2 ) )
656 continue;
657
658 int n = m->CLine( 0 ).SegmentCount();
659
660 for( int j = n - 1; j >= 0; j-- )
661 {
662 if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
663 return false;
664 }
665 }
666
667 return true;
668}
669
670
671bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
672{
673 const MEANDER_SETTINGS& st = Settings();
674
675 bool checkMode = false;
676 MEANDER_TYPE prim1 = MT_EMPTY;
677 MEANDER_TYPE prim2 = MT_EMPTY;
678
679 if( aType == MT_CHECK_START )
680 {
681 prim1 = MT_START;
682 prim2 = MT_TURN;
683 checkMode = true;
684 }
685 else if( aType == MT_CHECK_FINISH )
686 {
687 prim1 = MT_TURN;
688 prim2 = MT_FINISH;
689 checkMode = true;
690 }
691
692 if( checkMode )
693 {
696
698 m2.SetBaselineOffset( m_baselineOffset );
699
700 bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
701 bool c2 = false;
702
703 if( c1 )
704 c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
705
706 if( c1 && c2 )
707 {
708 m_type = prim1;
709 m_shapes[0] = m1.m_shapes[0];
710 m_shapes[1] = m1.m_shapes[1];
711 m_baseSeg =aSeg;
712 m_p0 = aP;
713 m_side = aSide;
714 m_amplitude = m1.Amplitude();
715 m_dual = m1.m_dual;
716 m_baseSeg = m1.m_baseSeg;
720 return true;
721 }
722 else
723 {
724 return false;
725 }
726 }
727
728 int minAmpl = MinAmplitude();
729 int maxAmpl = std::max( st.m_maxAmplitude, minAmpl );
730
731 for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
732 {
733 m_amplitude = ampl;
734
735 if( m_dual )
736 {
737 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, m_baselineOffset );
738 m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, -m_baselineOffset );
739 }
740 else
741 {
742 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, 0 );
743 }
744
745 m_type = aType;
746 m_baseSeg = aSeg;
747 m_p0 = aP;
748 m_side = aSide;
749
751
752 if( m_placer->CheckFit( this ) )
753 return true;
754 }
755
756 return false;
757}
758
759
771
772
773void MEANDER_SHAPE::Resize( int aAmpl )
774{
775 if( aAmpl < 0 )
776 return;
777
778 m_amplitude = aAmpl;
779
780 Recalculate();
781}
782
783
798
799
800void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
801{
803
804 m->MakeCorner( aA, aB );
805 m_last = aA;
806
807 m_meanders.push_back( m );
808}
809
810
811void MEANDERED_LINE::AddArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
812{
814
815 m->MakeArc( aArc1, aArc2 );
816 m_last = aArc1.GetP1();
817
818 m_meanders.push_back( m );
819}
820
821
822void MEANDERED_LINE::AddArcAndPt( const SHAPE_ARC& aArc1, const VECTOR2I& aPt2 )
823{
824 SHAPE_ARC arc2( aPt2, aPt2, aPt2, 0 );
825
826 AddArc( aArc1, arc2 );
827}
828
829
830void MEANDERED_LINE::AddPtAndArc( const VECTOR2I& aPt1, const SHAPE_ARC& aArc2 )
831{
832 SHAPE_ARC arc1( aPt1, aPt1, aPt1, 0 );
833
834 AddArc( arc1, aArc2 );
835}
836
837
838void MEANDER_SHAPE::MakeCorner( const VECTOR2I& aP1, const VECTOR2I& aP2 )
839{
841 m_shapes[0].Clear();
842 m_shapes[1].Clear();
843 m_shapes[0].Append( aP1 );
844 m_shapes[1].Append( aP2 );
845 m_clippedBaseSeg.A = aP1;
846 m_clippedBaseSeg.B = aP1;
847}
848
849
850void MEANDER_SHAPE::MakeArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
851{
853 m_shapes[0].Clear();
854 m_shapes[1].Clear();
855 m_shapes[0].Append( aArc1 );
856 m_shapes[1].Append( aArc2 );
857 m_clippedBaseSeg.A = aArc1.GetP1();
858 m_clippedBaseSeg.B = aArc1.GetP1();
859}
860
861
863{
864 m_last = aShape->BaseSegment().B;
865 m_meanders.push_back( aShape );
866}
867
868
870{
871 for( MEANDER_SHAPE* m : m_meanders )
872 delete m;
873
874 m_meanders.clear( );
875}
876
877
879{
880 return m_clippedBaseSeg.Length();
881}
882
883
884long long int MEANDER_SHAPE::CurrentLength() const
885{
886 return CLine( 0 ).Length();
887}
888
889
891{
892 MEANDER_SHAPE copy = *this;
893
894 copy.SetTargetBaselineLength( BaselineLength() );
895 copy.Resize( copy.MinAmplitude() );
896
897 return copy.CurrentLength();
898}
899
900
902{
903 if( m_dual )
904 {
905 VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
906 VECTOR2I midpB = ( CLine( 0 ).CLastPoint() + CLine( 1 ).CLastPoint() ) / 2;
907
908 m_clippedBaseSeg.A = m_baseSeg.LineProject( midpA );
909 m_clippedBaseSeg.B = m_baseSeg.LineProject( midpB );
910 }
911 else
912 {
913 m_clippedBaseSeg.A = m_baseSeg.LineProject( CLine( 0 ).CPoint( 0 ) );
914 m_clippedBaseSeg.B = m_baseSeg.LineProject( CLine( 0 ).CLastPoint() );
915 }
916}
917
918}
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