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 lc.Append( aP + dir_v_b + aDir );
565 break;
566
567 case MT_START:
568 if( targetBaseLen )
569 top = std::max( top, targetBaseLen - sCorner - uCorner * 2 + offset );
570
571 miter( sCorner, false );
572 uShape( startSide, uCorner, top );
573 forward( std::min( sCorner, uCorner ) );
574 forward( std::abs( offset ) );
575 break;
576
577 case MT_FINISH:
578 if( targetBaseLen )
579 top = std::max( top, targetBaseLen - cr - spc );
580
581 start( &lc, aP - dir_u_b, aDir );
582 turn( -ANGLE_90 );
583 forward( std::min( sCorner, uCorner ) );
584 forward( std::abs( offset ) );
585 uShape( startSide, uCorner, top );
586 miter( sCorner, false );
587
588 if( targetBaseLen >= spc + cr )
589 lc.Append( aP + dir_v_b + aDir.Resize( targetBaseLen ) );
590 else
591 lc.Append( aP + dir_v_b + aDir.Resize( 2 * spc - cr ) );
592
593 break;
594
595 case MT_TURN:
596 if( targetBaseLen )
597 top = std::max( top, targetBaseLen - uCorner * 2 + offset * 2 );
598
599 start( &lc, aP - dir_u_b, aDir );
600 turn( -ANGLE_90 );
601 forward( std::abs( offset ) );
602 uShape( turnSide, uCorner, top );
603 forward( std::abs( offset ) );
604 break;
605
606 case MT_SINGLE:
607 if( targetBaseLen )
608 top = std::max( top, ( targetBaseLen - sCorner * 2 - uCorner * 2 ) / 2 );
609
610 miter( sCorner, false );
611 uShape( startSide, uCorner, top );
612 miter( sCorner, false );
613 lc.Append( aP + dir_v_b + aDir.Resize( 2 * spc ) );
614 break;
615
616 default:
617 break;
618 }
619
620 if( aSide )
621 {
622 SEG axis( aP, aP + aDir );
623
624 lc.Mirror( axis );
625 }
626
627 // Clear the current target pointer to avoid dangling pointer after lc goes out of scope
628 m_currentTarget = nullptr;
629
630 return lc;
631}
632
633
635{
636 for( int i = m_meanders.size() - 1; i >= 0; i-- )
637 {
639
640 if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
641 continue;
642
643 const SEG& b1 = aShape->BaseSegment();
644 const SEG& b2 = m->BaseSegment();
645
646 if( b1.ApproxParallel( b2 ) )
647 continue;
648
649 int n = m->CLine( 0 ).SegmentCount();
650
651 for( int j = n - 1; j >= 0; j-- )
652 {
653 if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
654 return false;
655 }
656 }
657
658 return true;
659}
660
661
662bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
663{
664 const MEANDER_SETTINGS& st = Settings();
665
666 bool checkMode = false;
667 MEANDER_TYPE prim1 = MT_EMPTY;
668 MEANDER_TYPE prim2 = MT_EMPTY;
669
670 if( aType == MT_CHECK_START )
671 {
672 prim1 = MT_START;
673 prim2 = MT_TURN;
674 checkMode = true;
675 }
676 else if( aType == MT_CHECK_FINISH )
677 {
678 prim1 = MT_TURN;
679 prim2 = MT_FINISH;
680 checkMode = true;
681 }
682
683 if( checkMode )
684 {
687
689 m2.SetBaselineOffset( m_baselineOffset );
690
691 bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
692 bool c2 = false;
693
694 if( c1 )
695 c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
696
697 if( c1 && c2 )
698 {
699 m_type = prim1;
700 m_shapes[0] = m1.m_shapes[0];
701 m_shapes[1] = m1.m_shapes[1];
702 m_baseSeg =aSeg;
703 m_p0 = aP;
704 m_side = aSide;
705 m_amplitude = m1.Amplitude();
706 m_dual = m1.m_dual;
707 m_baseSeg = m1.m_baseSeg;
711 return true;
712 }
713 else
714 {
715 return false;
716 }
717 }
718
719 int minAmpl = MinAmplitude();
720 int maxAmpl = std::max( st.m_maxAmplitude, minAmpl );
721
722 for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
723 {
724 m_amplitude = ampl;
725
726 if( m_dual )
727 {
728 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, m_baselineOffset );
729 m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, -m_baselineOffset );
730 }
731 else
732 {
733 m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, 0 );
734 }
735
736 m_type = aType;
737 m_baseSeg = aSeg;
738 m_p0 = aP;
739 m_side = aSide;
740
742
743 if( m_placer->CheckFit( this ) )
744 return true;
745 }
746
747 return false;
748}
749
750
762
763
764void MEANDER_SHAPE::Resize( int aAmpl )
765{
766 if( aAmpl < 0 )
767 return;
768
769 m_amplitude = aAmpl;
770
771 Recalculate();
772}
773
774
789
790
791void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
792{
794
795 m->MakeCorner( aA, aB );
796 m_last = aA;
797
798 m_meanders.push_back( m );
799}
800
801
802void MEANDERED_LINE::AddArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
803{
805
806 m->MakeArc( aArc1, aArc2 );
807 m_last = aArc1.GetP1();
808
809 m_meanders.push_back( m );
810}
811
812
813void MEANDERED_LINE::AddArcAndPt( const SHAPE_ARC& aArc1, const VECTOR2I& aPt2 )
814{
815 SHAPE_ARC arc2( aPt2, aPt2, aPt2, 0 );
816
817 AddArc( aArc1, arc2 );
818}
819
820
821void MEANDERED_LINE::AddPtAndArc( const VECTOR2I& aPt1, const SHAPE_ARC& aArc2 )
822{
823 SHAPE_ARC arc1( aPt1, aPt1, aPt1, 0 );
824
825 AddArc( arc1, aArc2 );
826}
827
828
829void MEANDER_SHAPE::MakeCorner( const VECTOR2I& aP1, const VECTOR2I& aP2 )
830{
832 m_shapes[0].Clear();
833 m_shapes[1].Clear();
834 m_shapes[0].Append( aP1 );
835 m_shapes[1].Append( aP2 );
836 m_clippedBaseSeg.A = aP1;
837 m_clippedBaseSeg.B = aP1;
838}
839
840
841void MEANDER_SHAPE::MakeArc( const SHAPE_ARC& aArc1, const SHAPE_ARC& aArc2 )
842{
844 m_shapes[0].Clear();
845 m_shapes[1].Clear();
846 m_shapes[0].Append( aArc1 );
847 m_shapes[1].Append( aArc2 );
848 m_clippedBaseSeg.A = aArc1.GetP1();
849 m_clippedBaseSeg.B = aArc1.GetP1();
850}
851
852
854{
855 m_last = aShape->BaseSegment().B;
856 m_meanders.push_back( aShape );
857}
858
859
861{
862 for( MEANDER_SHAPE* m : m_meanders )
863 delete m;
864
865 m_meanders.clear( );
866}
867
868
870{
871 return m_clippedBaseSeg.Length();
872}
873
874
875long long int MEANDER_SHAPE::CurrentLength() const
876{
877 return CLine( 0 ).Length();
878}
879
880
882{
883 MEANDER_SHAPE copy = *this;
884
885 copy.SetTargetBaselineLength( BaselineLength() );
886 copy.Resize( copy.MinAmplitude() );
887
888 return copy.CurrentLength();
889}
890
891
893{
894 if( m_dual )
895 {
896 VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
897 VECTOR2I midpB = ( CLine( 0 ).CLastPoint() + CLine( 1 ).CLastPoint() ) / 2;
898
899 m_clippedBaseSeg.A = m_baseSeg.LineProject( midpA );
900 m_clippedBaseSeg.B = m_baseSeg.LineProject( midpB );
901 }
902 else
903 {
904 m_clippedBaseSeg.A = m_baseSeg.LineProject( CLine( 0 ).CPoint( 0 ) );
905 m_clippedBaseSeg.B = m_baseSeg.LineProject( CLine( 0 ).CLastPoint() );
906 }
907}
908
909}
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:775
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:119
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
KIBIS top(path, &reporter)
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