KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_tuning_pattern.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <pcb_generator.h>
26#include <generators_mgr.h>
27
28#include <optional>
29#include <magic_enum.hpp>
30
31#include <wx/debug.h>
34#include <kiplatform/ui.h>
36#include <collectors.h>
37#include <scoped_set_reset.h>
38#include <core/mirror.h>
39
41#include <drc/drc_engine.h>
42#include <pcb_track.h>
43#include <pcb_shape.h>
44#include <pcb_group.h>
45
46#include <tool/edit_points.h>
47#include <tools/drawing_tool.h>
52
55#include <view/view.h>
56#include <view/view_controls.h>
57
60#include <router/pns_meander.h>
62#include <router/pns_segment.h>
63#include <router/pns_arc.h>
64#include <router/pns_solid.h>
65#include <router/pns_topology.h>
67
69
70
72{
76};
77
78
80{
81public:
83 EDA_ITEM( NOT_USED ), // Never added to anything - just a preview
84 m_frame( aFrame ),
85 m_min( 0.0 ),
86 m_max( 0.0 ),
87 m_current( 0.0 )
88 { }
89
90 wxString GetClass() const override { return wxT( "TUNING_STATUS" ); }
91
92#if defined(DEBUG)
93 void Show( int nestLevel, std::ostream& os ) const override {}
94#endif
95
96 VECTOR2I GetPosition() const override { return m_pos; }
97 void SetPosition( const VECTOR2I& aPos ) override { m_pos = aPos; };
98
99 void SetMinMax( double aMin, double aMax )
100 {
101 m_min = aMin;
103 m_max = aMax;
105 }
106
108 {
109 m_min = 0.0;
110 m_minText = wxT( "---" );
111 m_max = std::numeric_limits<double>::max();
112 m_maxText = wxT( "---" );
113 }
114
115 void SetCurrent( double aCurrent, const wxString& aLabel )
116 {
117 m_current = aCurrent;
119 m_currentLabel = aLabel;
120 }
121
122 const BOX2I ViewBBox() const override
123 {
124 BOX2I tmp;
125
126 // this is an edit-time artefact; no reason to try and be smart with the bounding box
127 // (besides, we can't tell the text extents without a view to know what the scale is)
128 tmp.SetMaximum();
129 return tmp;
130 }
131
132 void ViewGetLayers( int aLayers[], int& aCount ) const override
133 {
134 aLayers[0] = LAYER_UI_START;
135 aLayers[1] = LAYER_UI_START + 1;
136 aCount = 2;
137 }
138
139 void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override
140 {
141 KIGFX::GAL* gal = aView->GetGAL();
142 bool viewFlipped = gal->IsFlippedX();
143 bool drawingDropShadows = ( aLayer == LAYER_UI_START );
144
145 gal->Save();
146 gal->Scale( { 1., 1. } );
147
151 const KIFONT::METRICS& fontMetrics = KIFONT::METRICS::Default();
152 TEXT_ATTRIBUTES textAttrs;
153
154 int glyphWidth = textDims.GlyphSize.x;
155 VECTOR2I margin( KiROUND( glyphWidth * 0.4 ), KiROUND( glyphWidth ) );
156 VECTOR2I size( glyphWidth * 25 + margin.x * 2, headerDims.GlyphSize.y + textDims.GlyphSize.y );
157 VECTOR2I offset( margin.x * 2, -( size.y + margin.y * 2 ) );
158
159 if( drawingDropShadows )
160 {
161 gal->SetIsFill( true );
162 gal->SetIsStroke( true );
163 gal->SetLineWidth( gal->GetScreenWorldMatrix().GetScale().x * 2 );
164 gal->SetStrokeColor( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT ) );
165 KIGFX::COLOR4D bgColor( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
166 gal->SetFillColor( bgColor.WithAlpha( 0.9 ) );
167
168 gal->DrawRectangle( GetPosition() + offset - margin,
169 GetPosition() + offset + size + margin );
170 gal->Restore();
171 return;
172 }
173
174 COLOR4D bg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
175 COLOR4D normal = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT );
176 COLOR4D red;
177
178 // Choose a red with reasonable contrasting with the background
179 double bg_h, bg_s, bg_l;
180 bg.ToHSL( bg_h, bg_s, bg_l );
181 red.FromHSL( 0, 1.0, bg_l < 0.5 ? 0.7 : 0.3 );
182
183 if( viewFlipped )
185 else
186 textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
187
188 gal->SetIsFill( false );
189 gal->SetIsStroke( true );
190 gal->SetStrokeColor( normal );
191 textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
192
193 // Prevent text flipping when view is flipped
194 if( gal->IsFlippedX() )
195 {
196 textAttrs.m_Mirrored = true;
198 }
199
200 textAttrs.m_Size = headerDims.GlyphSize;
201 textAttrs.m_StrokeWidth = headerDims.StrokeWidth;
202
203 VECTOR2I textPos = GetPosition() + offset;
204 font->Draw( gal, m_currentLabel, textPos, textAttrs, KIFONT::METRICS::Default() );
205
206 textPos.x += glyphWidth * 11 + margin.x;
207 font->Draw( gal, _( "min" ), textPos, textAttrs, fontMetrics );
208
209 textPos.x += glyphWidth * 7 + margin.x;
210 font->Draw( gal, _( "max" ), textPos, textAttrs, fontMetrics );
211
212 textAttrs.m_Size = textDims.GlyphSize;
213 textAttrs.m_StrokeWidth = textDims.StrokeWidth;
214
215 textPos = GetPosition() + offset;
216 textPos.y += KiROUND( headerDims.LinePitch * 1.3 );
217 font->Draw( gal, m_currentText, textPos, textAttrs, KIFONT::METRICS::Default() );
218
219 textPos.x += glyphWidth * 11 + margin.x;
221 font->Draw( gal, m_minText, textPos, textAttrs, fontMetrics );
222
223 textPos.x += glyphWidth * 7 + margin.x;
225 font->Draw( gal, m_maxText, textPos, textAttrs, fontMetrics );
226
227 gal->Restore();
228 }
229
230protected:
233 double m_min;
234 double m_max;
235 double m_current;
238 wxString m_minText;
239 wxString m_maxText;
240};
241
242
244{
245public:
246 static const wxString GENERATOR_TYPE;
247 static const wxString DISPLAY_NAME;
248
249 PCB_TUNING_PATTERN( BOARD_ITEM* aParent = nullptr, PCB_LAYER_ID aLayer = F_Cu,
250 LENGTH_TUNING_MODE aMode = LENGTH_TUNING_MODE::SINGLE );
251
252 wxString GetGeneratorType() const override { return wxS( "tuning_pattern" ); }
253
254 wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override
255 {
256 return wxString( _( "Tuning Pattern" ) );
257 }
258
259 wxString GetFriendlyName() const override
260 {
261 return wxString( _( "Tuning Pattern" ) );
262 }
263
264 wxString GetPluralName() const override
265 {
266 return wxString( _( "Tuning Patterns" ) );
267 }
268
270 BOARD_CONNECTED_ITEM* aStartItem,
271 LENGTH_TUNING_MODE aMode );
272
273 void EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
274
275 bool Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
276
277 void EditPush( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit,
278 const wxString& aCommitMsg = wxEmptyString, int aCommitFlags = 0 ) override;
279
280 void EditRevert( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
281
282 void Remove( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
283
284 bool MakeEditPoints( std::shared_ptr<EDIT_POINTS> points ) const override;
285
286 bool UpdateFromEditPoints( std::shared_ptr<EDIT_POINTS> aEditPoints,
287 BOARD_COMMIT* aCommit ) override;
288
289 bool UpdateEditPoints( std::shared_ptr<EDIT_POINTS> aEditPoints ) override;
290
291 void Move( const VECTOR2I& aMoveVector ) override
292 {
293 m_origin += aMoveVector;
294 m_end += aMoveVector;
295
296 if( !this->HasFlag( IN_EDIT ) )
297 {
298 PCB_GROUP::Move( aMoveVector );
299
300 if( m_baseLine )
301 m_baseLine->Move( aMoveVector );
302
304 m_baseLineCoupled->Move( aMoveVector );
305 }
306 }
307
308 void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override
309 {
310 if( !this->HasFlag( IN_EDIT ) )
311 {
312 PCB_GENERATOR::Rotate( aRotCentre, aAngle );
313 RotatePoint( m_end, aRotCentre, aAngle );
314
315 if( m_baseLine )
316 m_baseLine->Rotate( aAngle, aRotCentre );
317
319 m_baseLineCoupled->Rotate( aAngle, aRotCentre );
320 }
321 }
322
323 void Flip( const VECTOR2I& aCentre, bool aFlipLeftRight ) override
324 {
325 if( !this->HasFlag( IN_EDIT ) )
326 {
327 PCB_GENERATOR::Flip( aCentre, aFlipLeftRight );
328
329 if( aFlipLeftRight )
330 MIRROR( m_end.x, aCentre.x );
331 else
332 MIRROR( m_end.y, aCentre.y );
333
334 if( m_baseLine )
335 m_baseLine->Mirror( aFlipLeftRight, !aFlipLeftRight, aCentre );
336
338 m_baseLineCoupled->Mirror( aFlipLeftRight, !aFlipLeftRight, aCentre );
339 }
340 }
341
342 const BOX2I GetBoundingBox() const override
343 {
344 return getOutline().BBox();
345 }
346
347 void ViewGetLayers( int aLayers[], int& aCount ) const override
348 {
349 aCount = 0;
350 aLayers[aCount++] = LAYER_ANCHOR;
351 aLayers[aCount++] = GetLayer();
352 }
353
354 bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override
355 {
356 return getOutline().Collide( aPosition, aAccuracy );
357 }
358
359 bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const override
360 {
361 BOX2I sel = aRect;
362
363 if ( aAccuracy )
364 sel.Inflate( aAccuracy );
365
366 if( aContained )
367 return sel.Contains( GetBoundingBox() );
368
369 return sel.Intersects( GetBoundingBox() );
370 }
371
372 const BOX2I ViewBBox() const override { return GetBoundingBox(); }
373
374 EDA_ITEM* Clone() const override { return new PCB_TUNING_PATTERN( *this ); }
375
376 void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override final;
377
378 const VECTOR2I& GetEnd() const { return m_end; }
379 void SetEnd( const VECTOR2I& aValue ) { m_end = aValue; }
380
381 int GetEndX() const { return m_end.x; }
382 void SetEndX( int aValue ) { m_end.x = aValue; }
383
384 int GetEndY() const { return m_end.y; }
385 void SetEndY( int aValue ) { m_end.y = aValue; }
386
388
390 {
391 switch( m_tuningMode )
392 {
393 case LENGTH_TUNING_MODE::SINGLE: return PNS::PNS_MODE_TUNE_SINGLE;
394 case LENGTH_TUNING_MODE::DIFF_PAIR: return PNS::PNS_MODE_TUNE_DIFF_PAIR;
395 case LENGTH_TUNING_MODE::DIFF_PAIR_SKEW: return PNS::PNS_MODE_TUNE_DIFF_PAIR_SKEW;
396 default: return PNS::PNS_MODE_TUNE_SINGLE;
397 }
398 }
399
401
403 void SetMinAmplitude( int aValue )
404 {
405 aValue = std::max( aValue, 0 );
406
407 m_settings.m_minAmplitude = aValue;
408
411 }
412
414 void SetMaxAmplitude( int aValue )
415 {
416 aValue = std::max( aValue, 0 );
417
418 m_settings.m_maxAmplitude = aValue;
419
422 }
423
426
427 int GetSpacing() const { return m_settings.m_spacing; }
428 void SetSpacing( int aValue ) { m_settings.m_spacing = aValue; }
429
430 std::optional<int> GetTargetLength() const
431 {
433 return std::optional<int>();
434 else
436 }
437
438 void SetTargetLength( std::optional<int> aValue )
439 {
440 if( aValue.has_value() )
441 m_settings.SetTargetLength( aValue.value() );
442 else
444 }
445
446 int GetTargetSkew() const { return m_settings.m_targetSkew.Opt(); }
447 void SetTargetSkew( int aValue ) { m_settings.SetTargetSkew( aValue ); }
448
450 void SetOverrideCustomRules( bool aOverride ) { m_settings.m_overrideCustomRules = aOverride; }
451
454
455 bool IsSingleSided() const { return m_settings.m_singleSided; }
456 void SetSingleSided( bool aValue ) { m_settings.m_singleSided = aValue; }
457
461
462 std::vector<std::pair<wxString, wxVariant>> GetRowData() override
463 {
464 std::vector<std::pair<wxString, wxVariant>> data = PCB_GENERATOR::GetRowData();
465 data.emplace_back( _HKI( "Net" ), m_lastNetName );
466 data.emplace_back( _HKI( "Tuning" ), m_tuningInfo );
467 return data;
468 }
469
470 const STRING_ANY_MAP GetProperties() const override;
471 void SetProperties( const STRING_ANY_MAP& aProps ) override;
472
473 void ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame ) override;
474
475 std::vector<EDA_ITEM*> GetPreviewItems( GENERATOR_TOOL* aTool, PCB_BASE_EDIT_FRAME* aFrame,
476 bool aStatusItemsOnly = false ) override;
477
478 void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
479
480protected:
481 void swapData( BOARD_ITEM* aImage ) override
482 {
483 wxASSERT( aImage->Type() == PCB_GENERATOR_T );
484
485 std::swap( *this, *static_cast<PCB_TUNING_PATTERN*>( aImage ) );
486 }
487
488 bool recoverBaseline( PNS::ROUTER* aRouter );
489
490 bool baselineValid();
491
492 bool initBaseLine( PNS::ROUTER* aRouter, int aLayer, BOARD* aBoard, VECTOR2I& aStart,
493 VECTOR2I& aEnd, NETINFO_ITEM* aNet,
494 std::optional<SHAPE_LINE_CHAIN>& aBaseLine );
495
496 bool initBaseLines( PNS::ROUTER* aRouter, int aLayer, BOARD* aBoard );
497
498 bool removeToBaseline( PNS::ROUTER* aRouter, int aLayer, SHAPE_LINE_CHAIN& aBaseLine );
499
500 bool resetToBaseline( GENERATOR_TOOL* aTool, int aLayer, SHAPE_LINE_CHAIN& aBaseLine,
501 bool aPrimary );
502
504
505protected:
507
509
510 std::optional<SHAPE_LINE_CHAIN> m_baseLine;
511 std::optional<SHAPE_LINE_CHAIN> m_baseLineCoupled;
512
515
517
519 wxString m_tuningInfo;
520
522};
523
524
525static LENGTH_TUNING_MODE tuningFromString( const std::string& aStr )
526{
527 if( aStr == "single" )
529 else if( aStr == "diff_pair" )
531 else if( aStr == "diff_pair_skew" )
533 else
534 {
535 wxFAIL_MSG( wxS( "Unknown length tuning token" ) );
537 }
538}
539
540
541static std::string tuningToString( const LENGTH_TUNING_MODE aTuning )
542{
543 switch( aTuning )
544 {
545 case LENGTH_TUNING_MODE::SINGLE: return "single";
546 case LENGTH_TUNING_MODE::DIFF_PAIR: return "diff_pair";
547 case LENGTH_TUNING_MODE::DIFF_PAIR_SKEW: return "diff_pair_skew";
548 default: wxFAIL; return "";
549 }
550}
551
552
554{
555 switch( aRouterMode )
556 {
560 default: return LENGTH_TUNING_MODE::SINGLE;
561 }
562}
563
564
565static PNS::MEANDER_SIDE sideFromString( const std::string& aStr )
566{
567 if( aStr == "default" )
569 else if( aStr == "left" )
571 else if( aStr == "right" )
573 else
574 {
575 wxFAIL_MSG( wxS( "Unknown length-tuning side token" ) );
577 }
578}
579
580
582{
583 switch( aStatus )
584 {
585 case PNS::MEANDER_PLACER_BASE::TOO_LONG: return "too_long";
586 case PNS::MEANDER_PLACER_BASE::TOO_SHORT: return "too_short";
587 case PNS::MEANDER_PLACER_BASE::TUNED: return "tuned";
588 default: wxFAIL; return "";
589 }
590}
591
592
594{
595 if( aStr == "too_long" )
597 else if( aStr == "too_short" )
599 else if( aStr == "tuned" )
601 else
602 {
603 wxFAIL_MSG( wxS( "Unknown tuning status token" ) );
605 }
606}
607
608
609static std::string sideToString( const PNS::MEANDER_SIDE aValue )
610{
611 switch( aValue )
612 {
613 case PNS::MEANDER_SIDE_DEFAULT: return "default";
614 case PNS::MEANDER_SIDE_LEFT: return "left";
615 case PNS::MEANDER_SIDE_RIGHT: return "right";
616 default: wxFAIL; return "";
617 }
618}
619
620
622 LENGTH_TUNING_MODE aMode ) :
623 PCB_GENERATOR( aParent, aLayer ),
624 m_trackWidth( 0 ),
625 m_diffPairGap( 0 ),
626 m_tuningMode( aMode ),
627 m_tuningStatus( PNS::MEANDER_PLACER_BASE::TUNING_STATUS::TUNED )
628{
631 m_end = VECTOR2I( pcbIUScale.mmToIU( 10 ), 0 );
633}
634
635
636static VECTOR2I snapToNearestTrack( const VECTOR2I& aP, BOARD* aBoard, NETINFO_ITEM* aNet,
637 PCB_TRACK** aNearestTrack )
638{
640 VECTOR2I closestPt = aP;
641
642 for( PCB_TRACK *track : aBoard->Tracks() )
643 {
644 if( aNet && track->GetNet() != aNet )
645 continue;
646
647 VECTOR2I nearest;
648
649 if( track->Type() == PCB_ARC_T )
650 {
651 PCB_ARC* pcbArc = static_cast<PCB_ARC*>( track );
652 SHAPE_ARC arc( pcbArc->GetStart(), pcbArc->GetMid(), pcbArc->GetEnd(),
653 pcbArc->GetWidth() );
654
655 nearest = arc.NearestPoint( aP );
656 }
657 else
658 {
659 SEG seg( track->GetStart(), track->GetEnd() );
660 nearest = seg.NearestPoint( aP );
661 }
662
663 SEG::ecoord dist_sq = ( nearest - aP ).SquaredEuclideanNorm();
664
665 if( dist_sq < minDist_sq )
666 {
667 minDist_sq = dist_sq;
668 closestPt = nearest;
669
670 if( aNearestTrack )
671 *aNearestTrack = track;
672 }
673 }
674
675 return closestPt;
676}
677
678
680{
682 {
683 return( m_baseLine && m_baseLine->PointCount() > 1
684 && m_baseLineCoupled && m_baseLineCoupled->PointCount() > 1 );
685 }
686 else
687 {
688 return( m_baseLine && m_baseLine->PointCount() > 1 );
689 }
690}
691
692
694 PCB_BASE_EDIT_FRAME* aFrame,
695 BOARD_CONNECTED_ITEM* aStartItem,
696 LENGTH_TUNING_MODE aMode )
697{
698 BOARD* board = aStartItem->GetBoard();
700 DRC_CONSTRAINT constraint;
701 PCB_LAYER_ID layer = aStartItem->GetLayer();
702
703 PCB_TUNING_PATTERN* pattern = new PCB_TUNING_PATTERN( board, layer, aMode );
704
705 switch( aMode )
706 {
707 case SINGLE: pattern->m_settings = bds.m_SingleTrackMeanderSettings; break;
708 case DIFF_PAIR: pattern->m_settings = bds.m_DiffPairMeanderSettings; break;
709 case DIFF_PAIR_SKEW: pattern->m_settings = bds.m_SkewMeanderSettings; break;
710 }
711
712 constraint = bds.m_DRCEngine->EvalRules( LENGTH_CONSTRAINT, aStartItem, nullptr, layer );
713
714 if( !constraint.IsNull() )
715 {
716 if( aMode == DIFF_PAIR_SKEW )
717 pattern->m_settings.SetTargetSkew( constraint.GetValue() );
718 else
719 pattern->m_settings.SetTargetLength( constraint.GetValue() );
720 }
721
722 pattern->SetFlags( IS_NEW );
723
724 return pattern;
725}
726
728{
729 if( aCommit )
730 {
731 if( IsNew() )
732 aCommit->Add( this );
733 else
734 aCommit->Modify( this );
735 }
736
737 SetFlags( IN_EDIT );
738
739 int layer = GetLayer();
740 PNS::ROUTER* router = aTool->Router();
741
742 aTool->ClearRouterChanges();
743 router->SyncWorld();
744
746 PNS::CONSTRAINT constraint;
747
748 if( !baselineValid() )
749 initBaseLines( router, layer, aBoard );
750
752 {
753 PCB_TRACK* track = nullptr;
754 PNS::SEGMENT pnsItem;
755
756 m_origin = snapToNearestTrack( m_origin, aBoard, nullptr, &track );
757 wxCHECK( track, /* void */ );
758
759 NETINFO_ITEM* net = track->GetNet();
760
761 pnsItem.SetParent( track );
762 pnsItem.SetNet( net );
763
764 if( m_tuningMode == SINGLE )
765 {
766 if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_LENGTH,
767 &pnsItem, nullptr, layer, &constraint ) )
768 {
769 m_settings.SetTargetLength( constraint.m_Value );
771 }
772 }
773 else
774 {
775 PCB_TRACK* coupledTrack = nullptr;
776 PNS::SEGMENT pnsCoupledItem;
777 NETINFO_ITEM* coupledNet = aBoard->DpCoupledNet( net );
778
779 if( coupledNet )
780 snapToNearestTrack( m_origin, aBoard, coupledNet, &coupledTrack );
781
782 pnsCoupledItem.SetParent( coupledTrack );
783 pnsCoupledItem.SetNet( coupledNet );
784
785 if( m_tuningMode == DIFF_PAIR )
786 {
787 if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_LENGTH,
788 &pnsItem, &pnsCoupledItem, layer, &constraint ) )
789 {
790 m_settings.SetTargetLength( constraint.m_Value );
792 }
793 }
794 else
795 {
797 &pnsItem, &pnsCoupledItem, layer, &constraint ) )
798 {
799 m_settings.m_targetSkew = constraint.m_Value;
801 }
802 }
803 }
804 }
805}
806
807
808static PNS::LINKED_ITEM* pickSegment( PNS::ROUTER* aRouter, const VECTOR2I& aWhere, int aLayer,
809 VECTOR2I& aPointOut,
810 const SHAPE_LINE_CHAIN& aBaseline = SHAPE_LINE_CHAIN() )
811{
812 int maxSlopRadius = aRouter->Sizes().Clearance() + aRouter->Sizes().TrackWidth() / 2;
813
814 static const int candidateCount = 2;
815 PNS::LINKED_ITEM* prioritized[candidateCount];
816 SEG::ecoord dist[candidateCount];
817 SEG::ecoord distBaseline[candidateCount];
818 VECTOR2I point[candidateCount];
819
820 for( int i = 0; i < candidateCount; i++ )
821 {
822 prioritized[i] = nullptr;
823 dist[i] = VECTOR2I::ECOORD_MAX;
824 distBaseline[i] = VECTOR2I::ECOORD_MAX;
825 }
826
827 for( int slopRadius : { 0, maxSlopRadius } )
828 {
829 PNS::ITEM_SET candidates = aRouter->QueryHoverItems( aWhere, slopRadius );
830
831 for( PNS::ITEM* item : candidates.Items() )
832 {
833 if( !item->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T ) )
834 continue;
835
836 if( !item->IsRoutable() )
837 continue;
838
839 if( !item->Layers().Overlaps( aLayer ) )
840 continue;
841
842 PNS::LINKED_ITEM* linked = static_cast<PNS::LINKED_ITEM*>( item );
843
844 if( item->Kind() & PNS::ITEM::ARC_T )
845 {
846 PNS::ARC* pnsArc = static_cast<PNS::ARC*>( item );
847
848 VECTOR2I nearest = pnsArc->Arc().NearestPoint( aWhere );
849 SEG::ecoord d0 = ( nearest - aWhere ).SquaredEuclideanNorm();
850
851 if( d0 > dist[1] )
852 continue;
853
854 if( aBaseline.PointCount() > 0 )
855 {
856 SEG::ecoord dcBaseline;
857 VECTOR2I target = pnsArc->Arc().GetArcMid();
858
859 if( aBaseline.SegmentCount() > 0 )
860 dcBaseline = aBaseline.SquaredDistance( target );
861 else
862 dcBaseline = ( aBaseline.CPoint( 0 ) - target ).SquaredEuclideanNorm();
863
864 if( dcBaseline > distBaseline[1] )
865 continue;
866
867 distBaseline[1] = dcBaseline;
868 }
869
870 prioritized[1] = linked;
871 dist[1] = d0;
872 point[1] = nearest;
873 }
874 else if( item->Kind() & PNS::ITEM::SEGMENT_T )
875 {
876 PNS::SEGMENT* segm = static_cast<PNS::SEGMENT*>( item );
877
878 VECTOR2I nearest = segm->CLine().NearestPoint( aWhere, false );
879 SEG::ecoord dd = ( aWhere - nearest ).SquaredEuclideanNorm();
880
881 if( dd > dist[1] )
882 continue;
883
884 if( aBaseline.PointCount() > 0 )
885 {
886 SEG::ecoord dcBaseline;
887 VECTOR2I target = segm->Shape()->Centre();
888
889 if( aBaseline.SegmentCount() > 0 )
890 dcBaseline = aBaseline.SquaredDistance( target );
891 else
892 dcBaseline = ( aBaseline.CPoint( 0 ) - target ).SquaredEuclideanNorm();
893
894 if( dcBaseline > distBaseline[1] )
895 continue;
896
897 distBaseline[1] = dcBaseline;
898 }
899
900 prioritized[1] = segm;
901 dist[1] = dd;
902 point[1] = nearest;
903 }
904 }
905 }
906
907 PNS::LINKED_ITEM* rv = nullptr;
908
909 for( int i = 0; i < candidateCount; i++ )
910 {
911 PNS::LINKED_ITEM* item = prioritized[i];
912
913 if( item && ( aLayer < 0 || item->Layers().Overlaps( aLayer ) ) )
914 {
915 rv = item;
916 aPointOut = point[i];
917 break;
918 }
919 }
920
921 return rv;
922}
923
924
925static std::optional<PNS::LINE> getPNSLine( const VECTOR2I& aStart, const VECTOR2I& aEnd,
926 PNS::ROUTER* router, int layer, VECTOR2I& aStartOut,
927 VECTOR2I& aEndOut )
928{
929 PNS::NODE* world = router->GetWorld();
930
931 PNS::LINKED_ITEM* startItem = pickSegment( router, aStart, layer, aStartOut );
932 PNS::LINKED_ITEM* endItem = pickSegment( router, aEnd, layer, aEndOut );
933
934 //wxCHECK( startItem && endItem, std::nullopt );
935
936 for( PNS::LINKED_ITEM* testItem : { startItem, endItem } )
937 {
938 if( !testItem )
939 continue;
940
941 PNS::LINE line = world->AssembleLine( testItem, nullptr, false, false );
942 SHAPE_LINE_CHAIN oldChain = line.CLine();
943
944 if( oldChain.PointOnEdge( aStartOut, 1 ) && oldChain.PointOnEdge( aEndOut, 1 ) )
945 return line;
946 }
947
948 return std::nullopt;
949}
950
951
952bool PCB_TUNING_PATTERN::initBaseLine( PNS::ROUTER* aRouter, int aLayer, BOARD* aBoard,
953 VECTOR2I& aStart, VECTOR2I& aEnd, NETINFO_ITEM* aNet,
954 std::optional<SHAPE_LINE_CHAIN>& aBaseLine )
955{
956 PNS::NODE* world = aRouter->GetWorld();
957
958 aStart = snapToNearestTrack( aStart, aBoard, aNet, nullptr );
959 aEnd = snapToNearestTrack( aEnd, aBoard, aNet, nullptr );
960
961 VECTOR2I startSnapPoint, endSnapPoint;
962
963 PNS::LINKED_ITEM* startItem = pickSegment( aRouter, aStart, aLayer, startSnapPoint );
964 PNS::LINKED_ITEM* endItem = pickSegment( aRouter, aEnd, aLayer, endSnapPoint );
965
966 wxASSERT( startItem );
967 wxASSERT( endItem );
968
969 if( !startItem || !endItem )
970 return false;
971
972 PNS::LINE line = world->AssembleLine( startItem );
973 const SHAPE_LINE_CHAIN& chain = line.CLine();
974
975 wxASSERT( line.ContainsLink( endItem ) );
976
977 wxASSERT( chain.PointOnEdge( startSnapPoint, 40000 ) );
978 wxASSERT( chain.PointOnEdge( endSnapPoint, 40000 ) );
979
982 SHAPE_LINE_CHAIN post;
983
984 chain.Split( startSnapPoint, endSnapPoint, pre, mid, post );
985
986 aBaseLine = mid;
987
988 return true;
989}
990
991
992bool PCB_TUNING_PATTERN::initBaseLines( PNS::ROUTER* aRouter, int aLayer, BOARD* aBoard )
993{
994 m_baseLineCoupled.reset();
995
996 PCB_TRACK* track = nullptr;
997
998 m_origin = snapToNearestTrack( m_origin, aBoard, nullptr, &track );
999 wxCHECK( track, false );
1000
1001 NETINFO_ITEM* net = track->GetNet();
1002
1003 if( !initBaseLine( aRouter, aLayer, aBoard, m_origin, m_end, net, m_baseLine ) )
1004 return false;
1005
1006 // Generate both baselines even if we're skewing. We need the coupled baseline to run the
1007 // DRC rules against.
1009 {
1010 if( NETINFO_ITEM* coupledNet = aBoard->DpCoupledNet( net ) )
1011 {
1012 VECTOR2I coupledStart = snapToNearestTrack( m_origin, aBoard, coupledNet, nullptr );
1013 VECTOR2I coupledEnd = snapToNearestTrack( m_end, aBoard, coupledNet, nullptr );
1014
1015 return initBaseLine( aRouter, aLayer, aBoard, coupledStart, coupledEnd, coupledNet,
1017 }
1018
1019 return false;
1020 }
1021
1022 return true;
1023}
1024
1026 SHAPE_LINE_CHAIN& aBaseLine )
1027{
1028 VECTOR2I startSnapPoint, endSnapPoint;
1029
1030 std::optional<PNS::LINE> pnsLine = getPNSLine( aBaseLine.CPoint( 0 ), aBaseLine.CPoint( -1 ),
1031 aRouter, aLayer, startSnapPoint, endSnapPoint );
1032
1033 wxCHECK( pnsLine, false );
1034
1035 SHAPE_LINE_CHAIN pre;
1036 SHAPE_LINE_CHAIN mid;
1037 SHAPE_LINE_CHAIN post;
1038 pnsLine->CLine().Split( startSnapPoint, endSnapPoint, pre, mid, post );
1039
1040 for( PNS::LINKED_ITEM* li : pnsLine->Links() )
1041 aRouter->GetInterface()->RemoveItem( li );
1042
1043 aRouter->GetWorld()->Remove( *pnsLine );
1044
1045 SHAPE_LINE_CHAIN straightChain;
1046 straightChain.Append( pre );
1047 straightChain.Append( aBaseLine );
1048 straightChain.Append( post );
1049 straightChain.Simplify();
1050
1051 PNS::LINE straightLine( *pnsLine, straightChain );
1052
1053 aRouter->GetWorld()->Add( straightLine, false );
1054
1055 for( PNS::LINKED_ITEM* li : straightLine.Links() )
1056 aRouter->GetInterface()->AddItem( li );
1057
1058 return true;
1059}
1060
1061
1063{
1064 SetFlags( IN_EDIT );
1065
1066 aTool->Router()->SyncWorld();
1067
1068 PNS::ROUTER* router = aTool->Router();
1069 int layer = GetLayer();
1070
1071 // Ungroup first so that undo works
1072 if( !GetItems().empty() )
1073 {
1074 PCB_GENERATOR* group = this;
1075
1076 for( BOARD_ITEM* member : group->GetItems() )
1077 aCommit->Stage( member, CHT_UNGROUP );
1078
1079 group->GetItems().clear();
1080 }
1081
1082 aCommit->Remove( this );
1083
1084 aTool->ClearRouterChanges();
1085
1086 if( baselineValid() )
1087 {
1088 bool success = true;
1089
1090 success &= removeToBaseline( router, layer, *m_baseLine );
1091
1092 if( m_tuningMode == DIFF_PAIR )
1093 success &= removeToBaseline( router, layer, *m_baseLineCoupled );
1094
1095 if( !success )
1096 recoverBaseline( router );
1097 }
1098
1099 const std::vector<GENERATOR_PNS_CHANGES>& allPnsChanges = aTool->GetRouterChanges();
1100
1101 for( const GENERATOR_PNS_CHANGES& pnsChanges : allPnsChanges )
1102 {
1103 const std::set<BOARD_ITEM*> routerRemovedItems = pnsChanges.removedItems;
1104 const std::set<BOARD_ITEM*> routerAddedItems = pnsChanges.addedItems;
1105
1106 /*std::cout << "Push commits << " << allPnsChanges.size() << " routerRemovedItems "
1107 << routerRemovedItems.size() << " routerAddedItems " << routerAddedItems.size()
1108 << " m_removedItems " << m_removedItems.size() << std::endl;*/
1109
1110 for( BOARD_ITEM* item : routerRemovedItems )
1111 {
1112 item->ClearSelected();
1113 aCommit->Remove( item );
1114 }
1115
1116 for( BOARD_ITEM* item : routerAddedItems )
1117 aCommit->Add( item );
1118 }
1119
1120 aCommit->Push( "Remove Tuning Pattern" );
1121}
1122
1123
1125{
1126 PNS::SOLID queryItem;
1127
1128 SHAPE_LINE_CHAIN* chain = static_cast<SHAPE_LINE_CHAIN*>( getOutline().Clone() );
1129 queryItem.SetShape( chain ); // PNS::SOLID takes ownership
1130 queryItem.SetLayer( m_layer );
1131
1132 int lineWidth = 0;
1133
1134 PNS::NODE::OBSTACLES obstacles;
1136 opts.m_useClearanceEpsilon = false;
1137
1138 PNS::NODE* world = aRouter->GetWorld();
1139 PNS::NODE* branch = world->Branch();
1140
1141 branch->QueryColliding( &queryItem, obstacles, opts );
1142
1143 for( const PNS::OBSTACLE& obs : obstacles )
1144 {
1145 PNS::ITEM* item = obs.m_item;
1146
1148 continue;
1149
1150 if( PNS::LINKED_ITEM* li = dynamic_cast<PNS::LINKED_ITEM*>( item ) )
1151 {
1152 if( lineWidth == 0 || li->Width() < lineWidth )
1153 lineWidth = li->Width();
1154 }
1155
1156 if( chain->PointInside( item->Anchor( 0 ), 10 )
1157 && chain->PointInside( item->Anchor( 1 ), 10 ) )
1158 {
1159 branch->Remove( item );
1160 }
1161 }
1162
1163 if( lineWidth == 0 )
1164 lineWidth = pcbIUScale.mmToIU( 0.1 ); // Fallback
1165
1166 if( baselineValid() )
1167 {
1168 NETINFO_ITEM* recoverNet = GetBoard()->FindNet( m_lastNetName );
1169 PNS::LINE recoverLine;
1170
1171 recoverLine.SetLayer( m_layer );
1172 recoverLine.SetWidth( lineWidth );
1173 recoverLine.Line() = *m_baseLine;
1174 recoverLine.SetNet( recoverNet );
1175 branch->Add( recoverLine, false );
1176
1178 {
1179 NETINFO_ITEM* recoverCoupledNet = GetBoard()->DpCoupledNet( recoverNet );
1180 PNS::LINE recoverLineCoupled;
1181
1182 recoverLineCoupled.SetLayer( m_layer );
1183 recoverLineCoupled.SetWidth( lineWidth );
1184 recoverLineCoupled.Line() = *m_baseLineCoupled;
1185 recoverLineCoupled.SetNet( recoverCoupledNet );
1186 branch->Add( recoverLineCoupled, false );
1187 }
1188 }
1189
1190 aRouter->CommitRouting( branch );
1191
1192 //wxLogWarning( "PNS baseline recovered" );
1193
1194 return true;
1195}
1196
1197
1199 SHAPE_LINE_CHAIN& aBaseLine, bool aPrimary )
1200{
1201 PNS_KICAD_IFACE* iface = aTool->GetInterface();
1202 PNS::ROUTER* router = aTool->Router();
1203 PNS::NODE* world = router->GetWorld();
1204 VECTOR2I startSnapPoint, endSnapPoint;
1205
1206 std::optional<PNS::LINE> pnsLine = getPNSLine( aBaseLine.CPoint( 0 ), aBaseLine.CPoint( -1 ),
1207 router, aLayer, startSnapPoint, endSnapPoint );
1208
1209 if( !pnsLine )
1210 {
1211 // TODO
1212 //recoverBaseline( aRouter );
1213 return true;
1214 }
1215
1216 PNS::NODE* branch = world->Branch();
1217
1218 SHAPE_LINE_CHAIN straightChain;
1219 {
1220 SHAPE_LINE_CHAIN pre, mid, post;
1221 pnsLine->CLine().Split( startSnapPoint, endSnapPoint, pre, mid, post );
1222
1223 straightChain.Append( pre );
1224 straightChain.Append( aBaseLine );
1225 straightChain.Append( post );
1226 straightChain.Simplify();
1227 }
1228
1229 branch->Remove( *pnsLine );
1230
1231 SHAPE_LINE_CHAIN newLineChain;
1232
1233 if( aPrimary )
1234 {
1235 m_origin = straightChain.NearestPoint( m_origin );
1236 m_end = straightChain.NearestPoint( m_end );
1237
1238 // Don't allow points too close
1239 if( ( m_end - m_origin ).EuclideanNorm() < pcbIUScale.mmToIU( 0.1 ) )
1240 {
1241 m_origin = startSnapPoint;
1242 m_end = endSnapPoint;
1243 }
1244
1245 {
1246 SHAPE_LINE_CHAIN pre, mid, post;
1247 straightChain.Split( m_origin, m_end, pre, mid, post );
1248
1249 newLineChain.Append( pre );
1250 newLineChain.Append( mid );
1251 newLineChain.Append( post );
1252
1253 m_baseLine = mid;
1254 }
1255 }
1256 else
1257 {
1258 VECTOR2I start = straightChain.NearestPoint( m_origin );
1259 VECTOR2I end = straightChain.NearestPoint( m_end );
1260
1261 {
1262 SHAPE_LINE_CHAIN pre, mid, post;
1263 straightChain.Split( start, end, pre, mid, post );
1264
1265 newLineChain.Append( pre );
1266 newLineChain.Append( mid );
1267 newLineChain.Append( post );
1268
1269 m_baseLineCoupled = mid;
1270 }
1271 }
1272
1273 PNS::LINE newLine( *pnsLine, newLineChain );
1274
1275 branch->Add( newLine, false );
1276 router->CommitRouting( branch );
1277
1278 int clearance = router->GetRuleResolver()->Clearance( &newLine, nullptr );
1279
1280 iface->DisplayItem( &newLine, clearance, true, PNS_COLLISION );
1281
1282 return true;
1283}
1284
1285
1287{
1288 if( !( GetFlags() & IN_EDIT ) )
1289 return false;
1290
1291 KIGFX::VIEW* view = aTool->GetManager()->GetView();
1292 PNS::ROUTER* router = aTool->Router();
1293 PNS_KICAD_IFACE* iface = aTool->GetInterface();
1294 int layer = GetLayer();
1295
1296 auto hideRemovedItems = [&]( bool aHide )
1297 {
1298 if( view )
1299 {
1300 for( const GENERATOR_PNS_CHANGES& pnsCommit : aTool->GetRouterChanges() )
1301 {
1302 for( BOARD_ITEM* item : pnsCommit.removedItems )
1303 {
1304 if( view )
1305 view->Hide( item, aHide, aHide );
1306 }
1307 }
1308 }
1309 };
1310
1311 iface->SetStartLayer( layer );
1312
1313 if( router->RoutingInProgress() )
1314 {
1315 router->StopRouting();
1316 }
1317
1318 if( !baselineValid() )
1319 {
1320 initBaseLines( router, layer, aBoard );
1321 }
1322 else
1323 {
1324 if( resetToBaseline( aTool, layer, *m_baseLine, true ) )
1325 {
1326 m_origin = m_baseLine->CPoint( 0 );
1327 m_end = m_baseLine->CPoint( -1 );
1328 }
1329 else
1330 {
1331 //initBaseLines( router, layer, aBoard );
1332 return false;
1333 }
1334
1335 if( m_tuningMode == DIFF_PAIR )
1336 {
1337 if( !resetToBaseline( aTool, layer, *m_baseLineCoupled, false ) )
1338 {
1339 initBaseLines( router, layer, aBoard );
1340 return false;
1341 }
1342 }
1343 }
1344
1345 hideRemovedItems( true );
1346 // Snap points
1347 VECTOR2I startSnapPoint, endSnapPoint;
1348
1349 wxCHECK( m_baseLine, false );
1350
1351 PNS::LINKED_ITEM* startItem = pickSegment( router, m_origin, layer, startSnapPoint, *m_baseLine);
1352 PNS::LINKED_ITEM* endItem = pickSegment( router, m_end, layer, endSnapPoint, *m_baseLine );
1353
1354 wxASSERT( startItem );
1355 wxASSERT( endItem );
1356
1357 if( !startItem || !endItem )
1358 return false;
1359
1360 router->SetMode( GetPNSMode() );
1361
1362 if( !router->StartRouting( startSnapPoint, startItem, layer ) )
1363 {
1364 //recoverBaseline( router );
1365 return false;
1366 }
1367
1368 PNS::MEANDER_PLACER_BASE* placer = static_cast<PNS::MEANDER_PLACER_BASE*>( router->Placer() );
1369
1370 m_settings.m_keepEndpoints = true; // Required for re-grouping
1371 placer->UpdateSettings( m_settings );
1372
1373 router->Move( m_end, nullptr );
1374
1375 if( PNS::DP_MEANDER_PLACER* dpPlacer = dynamic_cast<PNS::DP_MEANDER_PLACER*>( placer ) )
1376 {
1377 m_trackWidth = dpPlacer->GetOriginPair().Width();
1378 m_diffPairGap = dpPlacer->GetOriginPair().Gap();
1379 }
1380 else
1381 {
1382 m_trackWidth = startItem->Width();
1383 m_diffPairGap = router->Sizes().DiffPairGap();
1384 }
1385
1386 m_settings = placer->MeanderSettings();
1387 m_lastNetName = iface->GetNetName( startItem->Net() );
1388 m_tuningStatus = placer->TuningStatus();
1389
1390 wxString statusMessage;
1391
1392 switch ( m_tuningStatus )
1393 {
1394 case PNS::MEANDER_PLACER_BASE::TOO_LONG: statusMessage = _( "too long" ); break;
1395 case PNS::MEANDER_PLACER_BASE::TOO_SHORT: statusMessage = _( "too short" ); break;
1396 case PNS::MEANDER_PLACER_BASE::TUNED: statusMessage = _( "tuned" ); break;
1397 default: statusMessage = _( "unknown" ); break;
1398 }
1399
1400 wxString result;
1401 EDA_UNITS userUnits = EDA_UNITS::MILLIMETRES;
1402
1403 if( aTool->GetManager()->GetSettings() )
1404 userUnits = static_cast<EDA_UNITS>( aTool->GetManager()->GetSettings()->m_System.units );
1405
1407 (double) placer->TuningResult() );
1408
1409 m_tuningInfo.Printf( wxS( "%s (%s)" ), result, statusMessage );
1410
1411 return true;
1412}
1413
1414
1416 const wxString& aCommitMsg, int aCommitFlags )
1417{
1418 if( !( GetFlags() & IN_EDIT ) )
1419 return;
1420
1422
1423 KIGFX::VIEW* view = aTool->GetManager()->GetView();
1424 PNS::ROUTER* router = aTool->Router();
1425 PNS_KICAD_IFACE* iface = aTool->GetInterface();
1426 SHAPE_LINE_CHAIN bounds = getOutline();
1427 int epsilon = aBoard->GetDesignSettings().GetDRCEpsilon();
1428
1429 iface->EraseView();
1430
1431 if( router->RoutingInProgress() )
1432 {
1433 bool forceFinish = true;
1434 bool forceCommit = false;
1435
1436 router->FixRoute( m_end, nullptr, forceFinish, forceCommit );
1437 router->StopRouting();
1438 }
1439
1440 const std::vector<GENERATOR_PNS_CHANGES>& pnsCommits = aTool->GetRouterChanges();
1441
1442 for( const GENERATOR_PNS_CHANGES& pnsCommit : pnsCommits )
1443 {
1444 const std::set<BOARD_ITEM*> routerRemovedItems = pnsCommit.removedItems;
1445 const std::set<BOARD_ITEM*> routerAddedItems = pnsCommit.addedItems;
1446
1447 //std::cout << "Push commits << " << allPnsChanges.size() << " routerRemovedItems "
1448 // << routerRemovedItems.size() << " routerAddedItems " << routerAddedItems.size()
1449 // << " m_removedItems " << m_removedItems.size() << std::endl;
1450
1451 for( BOARD_ITEM* item : routerRemovedItems )
1452 {
1453 if( view )
1454 view->Hide( item, false );
1455
1456 aCommit->Remove( item );
1457 }
1458
1459 for( BOARD_ITEM* item : routerAddedItems )
1460 {
1461 aCommit->Add( item );
1462
1463 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
1464 {
1465 if( bounds.PointInside( track->GetStart(), epsilon )
1466 && bounds.PointInside( track->GetEnd(), epsilon ) )
1467 {
1468 AddItem( item );
1469 aCommit->Stage( item, CHT_GROUP );
1470 }
1471 }
1472 }
1473 }
1474
1475 if( aCommitMsg.IsEmpty() )
1476 aCommit->Push( _( "Edit Tuning Pattern" ), aCommitFlags );
1477 else
1478 aCommit->Push( aCommitMsg, aCommitFlags );
1479}
1480
1481
1483{
1484 if( !( GetFlags() & IN_EDIT ) )
1485 return;
1486
1488
1489 PNS_KICAD_IFACE* iface = aTool->GetInterface();
1490
1491 iface->EraseView();
1492
1493 if( KIGFX::VIEW* view = aTool->GetManager()->GetView() )
1494 {
1495 for( const GENERATOR_PNS_CHANGES& pnsCommit : aTool->GetRouterChanges() )
1496 {
1497 for( BOARD_ITEM* item : pnsCommit.removedItems )
1498 view->Hide( item, false );
1499 }
1500 }
1501
1502 aTool->Router()->StopRouting();
1503
1504 if( aCommit )
1505 aCommit->Revert();
1506}
1507
1508
1509bool PCB_TUNING_PATTERN::MakeEditPoints( std::shared_ptr<EDIT_POINTS> points ) const
1510{
1511 VECTOR2I centerlineOffset;
1512 VECTOR2I centerlineOffsetEnd;
1513
1514 if( m_tuningMode == DIFF_PAIR && m_baseLineCoupled && m_baseLineCoupled->SegmentCount() > 0 )
1515 {
1516 centerlineOffset = ( m_baseLineCoupled->CPoint( 0 ) - m_origin ) / 2;
1517 centerlineOffsetEnd = ( m_baseLineCoupled->CPoint( -1 ) - m_end ) / 2;
1518 }
1519
1520 points->AddPoint( m_origin + centerlineOffset );
1521 points->AddPoint( m_end + centerlineOffsetEnd );
1522
1523 SEG base = m_baseLine && m_baseLine->SegmentCount() > 0 ? m_baseLine->CSegment( 0 )
1524 : SEG( m_origin, m_end );
1525
1526 base.A += centerlineOffset;
1527 base.B += centerlineOffset;
1528
1529 int amplitude = m_settings.m_maxAmplitude + KiROUND( m_trackWidth / 2.0 );
1530
1531 if( m_tuningMode == DIFF_PAIR )
1532 amplitude += m_trackWidth + m_diffPairGap;
1533
1534 if( m_settings.m_initialSide == -1 )
1535 amplitude *= -1;
1536
1537 VECTOR2I widthHandleOffset = ( base.B - base.A ).Perpendicular().Resize( amplitude );
1538
1539 points->AddPoint( base.A + widthHandleOffset );
1540 points->Point( 2 ).SetGridConstraint( IGNORE_GRID );
1541
1542 VECTOR2I spacingHandleOffset =
1543 widthHandleOffset + ( base.B - base.A ).Resize( KiROUND( m_settings.m_spacing * 1.5 ) );
1544
1545 points->AddPoint( base.A + spacingHandleOffset );
1546 points->Point( 3 ).SetGridConstraint( IGNORE_GRID );
1547
1548 return true;
1549}
1550
1551
1552bool PCB_TUNING_PATTERN::UpdateFromEditPoints( std::shared_ptr<EDIT_POINTS> aEditPoints,
1553 BOARD_COMMIT* aCommit )
1554{
1555 VECTOR2I centerlineOffset;
1556 VECTOR2I centerlineOffsetEnd;
1557
1558 if( m_tuningMode == DIFF_PAIR && m_baseLineCoupled && m_baseLineCoupled->SegmentCount() > 0 )
1559 {
1560 centerlineOffset = ( m_baseLineCoupled->CPoint( 0 ) - m_origin ) / 2;
1561 centerlineOffsetEnd = ( m_baseLineCoupled->CPoint( -1 ) - m_end ) / 2;
1562 }
1563
1564 SEG base = m_baseLine && m_baseLine->SegmentCount() > 0 ? m_baseLine->CSegment( 0 )
1565 : SEG( m_origin, m_end );
1566
1567 base.A += centerlineOffset;
1568 base.B += centerlineOffset;
1569
1570 m_origin = aEditPoints->Point( 0 ).GetPosition() - centerlineOffset;
1571 m_end = aEditPoints->Point( 1 ).GetPosition() - centerlineOffsetEnd;
1572
1573 if( aEditPoints->Point( 2 ).IsActive() )
1574 {
1575 VECTOR2I wHandle = aEditPoints->Point( 2 ).GetPosition();
1576
1577 int value = base.LineDistance( wHandle );
1578
1579 value -= KiROUND( m_trackWidth / 2.0 );
1580
1581 if( m_tuningMode == DIFF_PAIR )
1582 value -= m_trackWidth + m_diffPairGap;
1583
1584 SetMaxAmplitude( KiROUND( value / pcbIUScale.mmToIU( 0.01 ) ) * pcbIUScale.mmToIU( 0.01 ) );
1585
1586 int side = base.Side( wHandle );
1587
1588 if( side < 0 )
1590 else
1592 }
1593
1594 if( aEditPoints->Point( 3 ).IsActive() )
1595 {
1596 VECTOR2I wHandle = aEditPoints->Point( 2 ).GetPosition();
1597 VECTOR2I sHandle = aEditPoints->Point( 3 ).GetPosition();
1598
1599 int value = KiROUND( SEG( base.A, wHandle ).LineDistance( sHandle ) / 1.5 );
1600
1601 SetSpacing( KiROUND( value / pcbIUScale.mmToIU( 0.01 ) ) * pcbIUScale.mmToIU( 0.01 ) );
1602 }
1603
1604 return true;
1605}
1606
1607
1608bool PCB_TUNING_PATTERN::UpdateEditPoints( std::shared_ptr<EDIT_POINTS> aEditPoints )
1609{
1610 VECTOR2I centerlineOffset;
1611 VECTOR2I centerlineOffsetEnd;
1612
1613 if( m_tuningMode == DIFF_PAIR && m_baseLineCoupled && m_baseLineCoupled->SegmentCount() > 0 )
1614 {
1615 centerlineOffset = ( m_baseLineCoupled->CPoint( 0 ) - m_origin ) / 2;
1616 centerlineOffsetEnd = ( m_baseLineCoupled->CPoint( -1 ) - m_end ) / 2;
1617 }
1618
1619 SEG base = m_baseLine && m_baseLine->SegmentCount() > 0 ? m_baseLine->CSegment( 0 )
1620 : SEG( m_origin, m_end );
1621
1622 base.A += centerlineOffset;
1623 base.B += centerlineOffset;
1624
1625 int amplitude = m_settings.m_maxAmplitude + KiROUND( m_trackWidth / 2.0 );
1626
1627 if( m_tuningMode == DIFF_PAIR )
1628 amplitude += m_trackWidth + m_diffPairGap;
1629
1630 if( m_settings.m_initialSide == -1 )
1631 amplitude *= -1;
1632
1633 VECTOR2I widthHandleOffset = ( base.B - base.A ).Perpendicular().Resize( amplitude );
1634
1635 aEditPoints->Point( 0 ).SetPosition( m_origin + centerlineOffset );
1636 aEditPoints->Point( 1 ).SetPosition( m_end + centerlineOffsetEnd );
1637
1638 aEditPoints->Point( 2 ).SetPosition( base.A + widthHandleOffset );
1639
1640 VECTOR2I spacingHandleOffset =
1641 widthHandleOffset + ( base.B - base.A ).Resize( KiROUND( m_settings.m_spacing * 1.5 ) );
1642
1643 aEditPoints->Point( 3 ).SetPosition( base.A + spacingHandleOffset );
1644
1645 return true;
1646}
1647
1648
1650{
1651 if( m_baseLine )
1652 {
1653 int clampedMaxAmplitude = m_settings.m_maxAmplitude;
1654 int minAllowedAmplitude = 0;
1655 int baselineOffset = m_tuningMode == DIFF_PAIR ? ( m_diffPairGap + m_trackWidth ) / 2 : 0;
1656
1658 {
1659 minAllowedAmplitude = baselineOffset + m_trackWidth;
1660 }
1661 else
1662 {
1663 int correction = m_trackWidth * tan( 1 - tan( DEG2RAD( 22.5 ) ) );
1664 minAllowedAmplitude = baselineOffset + correction;
1665 }
1666
1667 clampedMaxAmplitude = std::max( clampedMaxAmplitude, minAllowedAmplitude );
1668
1670 {
1671 SHAPE_LINE_CHAIN clBase = *m_baseLine;
1673
1674 if( m_tuningMode != DIFF_PAIR )
1675 {
1676 int amplitude = clampedMaxAmplitude + KiROUND( m_trackWidth / 2.0 );
1677
1678 SHAPE_LINE_CHAIN chain;
1679
1680 if( clBase.OffsetLine( amplitude, CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF,
1681 left, right, true ) )
1682 {
1683 chain.Append( m_settings.m_initialSide >= 0 ? right : left );
1684 chain.Append( clBase.Reverse() );
1685 chain.SetClosed( true );
1686
1687 return chain;
1688 }
1689 }
1691 {
1692 int amplitude = clampedMaxAmplitude + m_trackWidth + KiROUND( m_diffPairGap / 2.0 );
1693
1695 SHAPE_LINE_CHAIN chain1, chain2;
1696
1697 if( clBase.OffsetLine( amplitude, CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF,
1698 left, right, true ) )
1699 {
1700 if( m_settings.m_initialSide >= 0 )
1701 chain1.Append( right );
1702 else
1703 chain1.Append( left );
1704
1705 if( clBase.OffsetLine( KiROUND( m_trackWidth / 2.0 ),
1706 CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF, left,
1707 right, true ) )
1708 {
1709 if( m_settings.m_initialSide >= 0 )
1710 chain1.Append( left.Reverse() );
1711 else
1712 chain1.Append( right.Reverse() );
1713 }
1714
1715 chain1.SetClosed( true );
1716 }
1717
1718 if( clCoupled.OffsetLine( amplitude, CORNER_STRATEGY::ROUND_ALL_CORNERS,
1719 ARC_LOW_DEF, left, right, true ) )
1720 {
1721 if( m_settings.m_initialSide >= 0 )
1722 chain2.Append( right );
1723 else
1724 chain2.Append( left );
1725
1726 if( clCoupled.OffsetLine( KiROUND( m_trackWidth / 2.0 ),
1727 CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF, left,
1728 right, true ) )
1729 {
1730 if( m_settings.m_initialSide >= 0 )
1731 chain2.Append( left.Reverse() );
1732 else
1733 chain2.Append( right.Reverse() );
1734 }
1735
1736 chain2.SetClosed( true );
1737 }
1738
1739 SHAPE_POLY_SET merged;
1740 merged.BooleanAdd( chain1, chain2, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1741
1742 if( merged.OutlineCount() > 0 )
1743 return merged.Outline( 0 );
1744 }
1745 }
1746
1747 // Not single-sided / fallback
1748 SHAPE_POLY_SET poly;
1750
1751 int amplitude = 0;
1752
1753 if( m_tuningMode == DIFF_PAIR )
1754 amplitude = clampedMaxAmplitude + m_diffPairGap / 2 + KiROUND( m_trackWidth );
1755 else
1756 amplitude = clampedMaxAmplitude + KiROUND( m_trackWidth / 2.0 );
1757
1758 poly.OffsetLineChain( *m_baseLine, amplitude, CORNER_STRATEGY::ROUND_ALL_CORNERS,
1759 ARC_LOW_DEF, false );
1760
1762 {
1763 SHAPE_POLY_SET polyCoupled;
1764 polyCoupled.OffsetLineChain( *m_baseLineCoupled, amplitude,
1765 CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF, false );
1766
1767 SHAPE_POLY_SET merged;
1768 merged.BooleanAdd( poly, polyCoupled, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1769
1770 if( merged.OutlineCount() > 0 )
1771 return merged.Outline( 0 );
1772 }
1773
1774 if( poly.OutlineCount() > 0 )
1775 return poly.Outline( 0 );
1776 }
1777
1778 return SHAPE_LINE_CHAIN();
1779}
1780
1781
1782void PCB_TUNING_PATTERN::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
1783{
1784 if( !IsSelected() && !IsNew() )
1785 return;
1786
1787 KIGFX::PREVIEW::DRAW_CONTEXT ctx( *aView );
1788
1789 int size = KiROUND( aView->ToWorld( EDIT_POINT::POINT_SIZE ) * 0.8 );
1790 size = std::max( size, pcbIUScale.mmToIU( 0.05 ) );
1791
1792 if( !HasFlag( IN_EDIT ) )
1793 {
1794 if( m_baseLine )
1795 {
1796 for( int i = 0; i < m_baseLine->SegmentCount(); i++ )
1797 {
1798 SEG seg = m_baseLine->CSegment( i );
1799 ctx.DrawLineDashed( seg.A, seg.B, size, size / 6, true );
1800 }
1801 }
1802 else
1803 {
1804 ctx.DrawLineDashed( m_origin, m_end, size, size / 6, false );
1805 }
1806
1808 {
1809 for( int i = 0; i < m_baseLineCoupled->SegmentCount(); i++ )
1810 {
1811 SEG seg = m_baseLineCoupled->CSegment( i );
1812 ctx.DrawLineDashed( seg.A, seg.B, size, size / 6, true );
1813 }
1814 }
1815 }
1816
1817 SHAPE_LINE_CHAIN chain = getOutline();
1818
1819 for( int i = 0; i < chain.SegmentCount(); i++ )
1820 {
1821 SEG seg = chain.Segment( i );
1822 ctx.DrawLineDashed( seg.A, seg.B, size, size / 2, false );
1823 }
1824}
1825
1826
1828{
1830
1831 props.set( "tuning_mode", tuningToString( m_tuningMode ) );
1832 props.set( "initial_side", sideToString( m_settings.m_initialSide ) );
1833 props.set( "last_status", statusToString( m_tuningStatus ) );
1834
1835 props.set( "end", m_end );
1836 props.set( "corner_radius_percent", m_settings.m_cornerRadiusPercentage );
1837 props.set( "single_sided", m_settings.m_singleSided );
1839
1840 props.set_iu( "max_amplitude", m_settings.m_maxAmplitude );
1841 props.set_iu( "min_amplitude", m_settings.m_minAmplitude );
1842 props.set_iu( "min_spacing", m_settings.m_spacing );
1843 props.set_iu( "target_length_min", m_settings.m_targetLength.Min() );
1844 props.set_iu( "target_length", m_settings.m_targetLength.Opt() );
1845 props.set_iu( "target_length_max", m_settings.m_targetLength.Max() );
1846 props.set_iu( "target_skew_min", m_settings.m_targetSkew.Min() );
1847 props.set_iu( "target_skew", m_settings.m_targetSkew.Opt() );
1848 props.set_iu( "target_skew_max", m_settings.m_targetSkew.Max() );
1849 props.set_iu( "last_track_width", m_trackWidth );
1850 props.set_iu( "last_diff_pair_gap", m_diffPairGap );
1851
1852 props.set( "last_netname", m_lastNetName );
1853 props.set( "last_tuning", m_tuningInfo );
1854 props.set( "override_custom_rules", m_settings.m_overrideCustomRules );
1855
1856 if( m_baseLine )
1857 props.set( "base_line", wxAny( *m_baseLine ) );
1858
1859 if( m_baseLineCoupled )
1860 props.set( "base_line_coupled", wxAny( *m_baseLineCoupled ) );
1861
1862 return props;
1863}
1864
1865
1867{
1869
1870 wxString tuningMode;
1871 aProps.get_to( "tuning_mode", tuningMode );
1872 m_tuningMode = tuningFromString( tuningMode.utf8_string() );
1873
1874 wxString side;
1875 aProps.get_to( "initial_side", side );
1876 m_settings.m_initialSide = sideFromString( side.utf8_string() );
1877
1878 wxString status;
1879 aProps.get_to( "last_status", status );
1880 m_tuningStatus = statusFromString( status.utf8_string() );
1881
1882 aProps.get_to( "end", m_end );
1883 aProps.get_to( "corner_radius_percent", m_settings.m_cornerRadiusPercentage );
1884 aProps.get_to( "single_sided", m_settings.m_singleSided );
1885 aProps.get_to( "side", m_settings.m_initialSide );
1886
1887 bool rounded = false;
1888 aProps.get_to( "rounded", rounded );
1890
1891 long long int val;
1892
1893 aProps.get_to_iu( "target_length", val );
1895
1896 if( aProps.get_to_iu( "target_length_min", val ) )
1898
1899 if( aProps.get_to_iu( "target_length_max", val ) )
1901
1902 int int_val;
1903
1904 aProps.get_to_iu( "target_skew", int_val );
1905 m_settings.SetTargetSkew( int_val );
1906
1907 if( aProps.get_to_iu( "target_skew_min", int_val ) )
1908 m_settings.m_targetSkew.SetMin( int_val );
1909
1910 if( aProps.get_to_iu( "target_skew_max", int_val ) )
1911 m_settings.m_targetSkew.SetMax( int_val );
1912
1913 aProps.get_to_iu( "max_amplitude", m_settings.m_maxAmplitude );
1914 aProps.get_to_iu( "min_amplitude", m_settings.m_minAmplitude );
1915 aProps.get_to_iu( "min_spacing", m_settings.m_spacing );
1916 aProps.get_to_iu( "last_track_width", m_trackWidth );
1917 aProps.get_to_iu( "last_diff_pair_gap", m_diffPairGap );
1918 aProps.get_to( "override_custom_rules", m_settings.m_overrideCustomRules );
1919
1920 aProps.get_to( "last_netname", m_lastNetName );
1921 aProps.get_to( "last_tuning", m_tuningInfo );
1922
1923 if( auto baseLine = aProps.get_opt<SHAPE_LINE_CHAIN>( "base_line" ) )
1924 m_baseLine = *baseLine;
1925
1926 if( auto baseLineCoupled = aProps.get_opt<SHAPE_LINE_CHAIN>( "base_line_coupled" ) )
1927 m_baseLineCoupled = *baseLineCoupled;
1928}
1929
1930
1932{
1934 DRC_CONSTRAINT constraint;
1935
1936 if( !m_items.empty() )
1937 {
1938 BOARD_ITEM* startItem = *m_items.begin();
1939 std::shared_ptr<DRC_ENGINE>& drcEngine = GetBoard()->GetDesignSettings().m_DRCEngine;
1940
1941 constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr, GetLayer() );
1942
1943 if( !constraint.IsNull() && !settings.m_overrideCustomRules )
1944 settings.SetTargetLength( constraint.GetValue() );
1945 }
1946
1947 DIALOG_TUNING_PATTERN_PROPERTIES dlg( aEditFrame, settings, GetPNSMode(), constraint );
1948
1949 if( dlg.ShowModal() == wxID_OK )
1950 {
1951 BOARD_COMMIT commit( aEditFrame );
1952 commit.Modify( this );
1953 m_settings = settings;
1954
1955 GENERATOR_TOOL* generatorTool = aEditFrame->GetToolManager()->GetTool<GENERATOR_TOOL>();
1956 EditStart( generatorTool, GetBoard(), &commit );
1957 Update( generatorTool, GetBoard(), &commit );
1958 EditPush( generatorTool, GetBoard(), &commit );
1959 }
1960}
1961
1962
1964 PCB_BASE_EDIT_FRAME* aFrame,
1965 bool aStatusItemsOnly )
1966{
1967 std::vector<EDA_ITEM*> previewItems;
1968 KIGFX::VIEW* view = aFrame->GetCanvas()->GetView();
1969
1970 if( auto* placer = dynamic_cast<PNS::MEANDER_PLACER_BASE*>( aTool->Router()->Placer() ) )
1971 {
1972 if( !aStatusItemsOnly )
1973 {
1974 PNS::ITEM_SET items = placer->TunedPath();
1975
1976 for( PNS::ITEM* item : items )
1977 previewItems.push_back( new ROUTER_PREVIEW_ITEM( item, view, PNS_HOVER_ITEM ) );
1978 }
1979
1980 TUNING_STATUS_VIEW_ITEM* statusItem = new TUNING_STATUS_VIEW_ITEM( aFrame );
1981
1983 {
1985 }
1986 else
1987 {
1989 {
1990 statusItem->ClearMinMax();
1991 }
1992 else
1993 {
1994 statusItem->SetMinMax( (double) m_settings.m_targetLength.Min(),
1995 (double) m_settings.m_targetLength.Max() );
1996 }
1997 }
1998
2000 statusItem->SetCurrent( (double) placer->TuningResult(), _( "current skew" ) );
2001 else
2002 statusItem->SetCurrent( (double) placer->TuningResult(), _( "current length" ) );
2003
2004 statusItem->SetPosition( aFrame->GetToolManager()->GetMousePosition() );
2005 previewItems.push_back( statusItem );
2006 }
2007
2008 return previewItems;
2009}
2010
2011
2013 std::vector<MSG_PANEL_ITEM>& aList )
2014{
2015 wxString msg;
2016 NETINFO_ITEM* primaryNet = nullptr;
2017 NETINFO_ITEM* coupledNet = nullptr;
2018 PCB_TRACK* primaryItem = nullptr;
2019 PCB_TRACK* coupledItem = nullptr;
2020 NETCLASS* netclass = nullptr;
2021 int width = 0;
2022 bool mixedWidth = false;
2023
2024 aList.emplace_back( _( "Type" ), GetFriendlyName() );
2025
2026 for( BOARD_ITEM* member : GetItems() )
2027 {
2028 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( member ) )
2029 {
2030 if( !primaryNet )
2031 {
2032 primaryItem = track;
2033 primaryNet = track->GetNet();
2034 }
2035 else if( !coupledNet && track->GetNet() != primaryNet )
2036 {
2037 coupledItem = track;
2038 coupledNet = track->GetNet();
2039 }
2040
2041 if( !netclass )
2042 netclass = track->GetEffectiveNetClass();
2043
2044 if( !width )
2045 width = track->GetWidth();
2046 else if( width != track->GetWidth() )
2047 mixedWidth = true;
2048 }
2049 }
2050
2051 if( coupledNet )
2052 {
2053 aList.emplace_back( _( "Nets" ), UnescapeString( primaryNet->GetNetname() )
2054 + wxS( ", " )
2055 + UnescapeString( coupledNet->GetNetname() ) );
2056 }
2057 else if( primaryNet )
2058 {
2059 aList.emplace_back( _( "Net" ), UnescapeString( primaryNet->GetNetname() ) );
2060 }
2061
2062 if( netclass )
2063 aList.emplace_back( _( "Resolved Netclass" ), UnescapeString( netclass->GetName() ) );
2064
2065 aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
2066
2067 if( width && !mixedWidth )
2068 aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( width ) );
2069
2070 BOARD* board = GetBoard();
2071 std::shared_ptr<DRC_ENGINE>& drcEngine = board->GetDesignSettings().m_DRCEngine;
2072 DRC_CONSTRAINT constraint;
2073
2074 // Display full track length (in Pcbnew)
2075 if( board && primaryItem && primaryItem->GetNetCode() > 0 )
2076 {
2077 int count;
2078 double trackLen;
2079 double lenPadToDie;
2080
2081 std::tie( count, trackLen, lenPadToDie ) = board->GetTrackLength( *primaryItem );
2082
2083 if( coupledItem && coupledItem->GetNetCode() > 0 )
2084 {
2085 double coupledLen;
2086 std::tie( count, coupledLen, lenPadToDie ) = board->GetTrackLength( *coupledItem );
2087
2088 aList.emplace_back( _( "Routed Lengths" ), aFrame->MessageTextFromValue( trackLen )
2089 + wxS( ", " )
2090 + aFrame->MessageTextFromValue( coupledLen ) );
2091 }
2092 else
2093 {
2094 aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
2095 }
2096
2097 if( lenPadToDie != 0 )
2098 {
2099 msg = aFrame->MessageTextFromValue( lenPadToDie );
2100 aList.emplace_back( _( "Pad To Die Length" ), msg );
2101
2102 msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
2103 aList.emplace_back( _( "Full Length" ), msg );
2104 }
2105 }
2106
2108 {
2109 constraint = drcEngine->EvalRules( SKEW_CONSTRAINT, primaryItem, coupledItem, m_layer );
2110
2111 if( constraint.IsNull() || m_settings.m_overrideCustomRules )
2112 {
2114
2115 aList.emplace_back( wxString::Format( _( "Target Skew: %s" ), msg ),
2116 wxString::Format( _( "(from tuning pattern properties)" ) ) );
2117 }
2118 else
2119 {
2120 msg = aFrame->MessageTextFromMinOptMax( constraint.GetValue() );
2121
2122 if( !msg.IsEmpty() )
2123 {
2124 aList.emplace_back( wxString::Format( _( "Skew Constraints: %s" ), msg ),
2125 wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
2126 }
2127 }
2128 }
2129 else
2130 {
2131 constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, primaryItem, coupledItem, m_layer );
2132
2133 if( constraint.IsNull() || m_settings.m_overrideCustomRules )
2134 {
2135 msg = aFrame->MessageTextFromValue( (double) m_settings.m_targetLength.Opt() );
2136
2137 aList.emplace_back( wxString::Format( _( "Target Length: %s" ), msg ),
2138 wxString::Format( _( "(from tuning pattern properties)" ) ) );
2139 }
2140 else
2141 {
2142 msg = aFrame->MessageTextFromMinOptMax( constraint.GetValue() );
2143
2144 if( !msg.IsEmpty() )
2145 {
2146 aList.emplace_back( wxString::Format( _( "Length Constraints: %s" ), msg ),
2147 wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
2148 }
2149 }
2150 }
2151}
2152
2153
2154const wxString PCB_TUNING_PATTERN::DISPLAY_NAME = _HKI( "Tuning Pattern" );
2155const wxString PCB_TUNING_PATTERN::GENERATOR_TYPE = wxS( "tuning_pattern" );
2156
2157
2159
2160
2161#define HITTEST_THRESHOLD_PIXELS 5
2162
2163
2165{
2167 return 0;
2168
2169 if( m_inDrawingTool )
2170 return 0;
2171
2173
2175
2176 m_frame->PushTool( aEvent );
2177 Activate();
2178
2180 std::shared_ptr<DRC_ENGINE>& drcEngine = board->GetDesignSettings().m_DRCEngine;
2181 GENERATOR_TOOL* generatorTool = m_toolMgr->GetTool<GENERATOR_TOOL>();
2182 PNS::ROUTER* router = generatorTool->Router();
2184
2188 SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TUNING );
2189
2190 m_pickerItem = nullptr;
2191 m_tuningPattern = nullptr;
2192
2193 // Add a VIEW_GROUP that serves as a preview for the new item
2194 m_preview.Clear();
2195 m_view->Add( &m_preview );
2196
2197 auto setCursor =
2198 [&]()
2199 {
2200 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::BULLSEYE );
2201 controls->ShowCursor( true );
2202 };
2203
2204 auto updateHoverStatus =
2205 [&]()
2206 {
2207 std::unique_ptr<PCB_TUNING_PATTERN> dummyPattern;
2208
2209 if( m_pickerItem )
2210 {
2211 dummyPattern.reset( PCB_TUNING_PATTERN::CreateNew( generatorTool, m_frame,
2212 m_pickerItem, mode ) );
2213 dummyPattern->SetPosition( m_pickerItem->GetFocusPosition() );
2214 dummyPattern->SetEnd( m_pickerItem->GetFocusPosition() );
2215 }
2216
2217 if( dummyPattern )
2218 {
2219 dummyPattern->EditStart( generatorTool, m_board, nullptr );
2220 dummyPattern->Update( generatorTool, m_board, nullptr );
2221
2223
2224 for( EDA_ITEM* item : dummyPattern->GetPreviewItems( generatorTool, m_frame ) )
2225 m_preview.Add( item );
2226
2227 generatorTool->Router()->StopRouting();
2228
2229 m_view->Update( &m_preview );
2230 }
2231 else
2232 {
2234 m_view->Update( &m_preview );
2235 }
2236 };
2237
2238 auto updateTuningPattern =
2239 [&]()
2240 {
2242 {
2243 m_tuningPattern->EditStart( generatorTool, m_board, nullptr );
2244 m_tuningPattern->Update( generatorTool, m_board, nullptr );
2245
2247
2248 for( EDA_ITEM* item : m_tuningPattern->GetPreviewItems( generatorTool, m_frame,
2249 true ) )
2250 {
2251 m_preview.Add( item );
2252 }
2253
2254 m_view->Update( &m_preview );
2255 }
2256 };
2257
2258 // Set initial cursor
2259 setCursor();
2260
2261 while( TOOL_EVENT* evt = Wait() )
2262 {
2263 setCursor();
2264 VECTOR2D cursorPos = controls->GetMousePosition();
2265
2266 if( evt->IsCancelInteractive() || evt->IsActivate()
2267 || ( m_tuningPattern && evt->IsAction( &ACTIONS::undo ) ) )
2268 {
2269 if( m_tuningPattern )
2270 {
2271 // First click already made; clean up tuning pattern preview
2272 m_tuningPattern->EditRevert( generatorTool, m_board, nullptr );
2273
2274 delete m_tuningPattern;
2275 m_tuningPattern = nullptr;
2276 }
2277
2278 break;
2279 }
2280 else if( evt->IsMotion() )
2281 {
2282 if( !m_tuningPattern )
2283 {
2284 // First click not yet made; we're in highlight-net-under-cursor mode
2285
2286 GENERAL_COLLECTOR collector;
2287 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
2288
2289 if( m_frame->GetDisplayOptions().m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL )
2290 guide.SetIncludeSecondary( false );
2291 else
2292 guide.SetIncludeSecondary( true );
2293
2294 collector.Collect( board, { PCB_TRACE_T, PCB_ARC_T }, cursorPos, guide );
2295
2296 if( collector.GetCount() > 1 )
2297 selectionTool->GuessSelectionCandidates( collector, cursorPos );
2298
2299 m_pickerItem = nullptr;
2300
2301 if( collector.GetCount() > 0 )
2302 {
2303 double min_dist_sq = std::numeric_limits<double>::max();
2304
2305 for( EDA_ITEM* candidate : collector )
2306 {
2307 VECTOR2I candidatePos;
2308
2309 if( candidate->Type() == PCB_TRACE_T )
2310 {
2311 candidatePos = static_cast<PCB_TRACK*>( candidate )->GetCenter();
2312 }
2313 else if( candidate->Type() == PCB_ARC_T )
2314 {
2315 candidatePos = static_cast<PCB_ARC*>( candidate )->GetMid();
2316 }
2317
2318 double dist_sq = ( cursorPos - candidatePos ).SquaredEuclideanNorm();
2319
2320 if( dist_sq < min_dist_sq )
2321 {
2322 min_dist_sq = dist_sq;
2323 m_pickerItem = static_cast<BOARD_CONNECTED_ITEM*>( candidate );
2324 }
2325 }
2326 }
2327
2328 updateHoverStatus();
2329 }
2330 else
2331 {
2332 // First click already made; we're in preview-tuning-pattern mode
2333
2334 m_tuningPattern->SetEnd( cursorPos );
2335 updateTuningPattern();
2336 }
2337 }
2338 else if( evt->IsClick( BUT_LEFT ) )
2339 {
2341 {
2342 // First click; create a tuning pattern
2343
2344 if( dynamic_cast<PCB_TUNING_PATTERN*>( m_pickerItem->GetParentGroup() ) )
2345 {
2346 m_frame->ShowInfoBarWarning( _( "Unable to tune segments inside other "
2347 "tuning patterns." ) );
2348 }
2349 else
2350 {
2352
2355 m_pickerItem, mode );
2356
2357 int dummyDist;
2358 int dummyClearance = std::numeric_limits<int>::max() / 2;
2359 VECTOR2I closestPt;
2360
2361 // With an artificially-large clearance this can't *not* collide, but the
2362 // if stmt keeps Coverity happy....
2363 if( m_pickerItem->GetEffectiveShape()->Collide( cursorPos, dummyClearance,
2364 &dummyDist, &closestPt ) )
2365 {
2366 m_tuningPattern->SetPosition( closestPt );
2367 m_tuningPattern->SetEnd( closestPt );
2368 }
2369
2371 }
2372 }
2373 else if( m_pickerItem && m_tuningPattern )
2374 {
2375 // Second click; we're done
2376 BOARD_COMMIT commit( m_frame );
2377
2378 m_tuningPattern->EditStart( generatorTool, m_board, &commit );
2379 m_tuningPattern->Update( generatorTool, m_board, &commit );
2380 m_tuningPattern->EditPush( generatorTool, m_board, &commit, _( "Tune" ) );
2381
2382 for( BOARD_ITEM* item : m_tuningPattern->GetItems() )
2383 item->SetSelected();
2384
2385 break;
2386 }
2387 }
2388 else if( evt->IsClick( BUT_RIGHT ) )
2389 {
2392 }
2393 else if( evt->IsAction( &PCB_ACTIONS::spacingIncrease )
2394 || evt->IsAction( &PCB_ACTIONS::spacingDecrease ) )
2395 {
2396 if( m_tuningPattern )
2397 {
2398 auto* placer = static_cast<PNS::MEANDER_PLACER_BASE*>( router->Placer() );
2399
2400 placer->SpacingStep( evt->IsAction( &PCB_ACTIONS::spacingIncrease ) ? 1 : -1 );
2401 m_tuningPattern->SetSpacing( placer->MeanderSettings().m_spacing );
2402 updateTuningPattern();
2403 }
2404 else
2405 {
2406 m_frame->ShowInfoBarWarning( _( "Select a track to tune first." ) );
2407 }
2408 }
2409 else if( evt->IsAction( &PCB_ACTIONS::amplIncrease )
2410 || evt->IsAction( &PCB_ACTIONS::amplDecrease ) )
2411 {
2412 if( m_tuningPattern )
2413 {
2414 auto* placer = static_cast<PNS::MEANDER_PLACER_BASE*>( router->Placer() );
2415
2416 placer->AmplitudeStep( evt->IsAction( &PCB_ACTIONS::amplIncrease ) ? 1 : -1 );
2417 m_tuningPattern->SetMaxAmplitude( placer->MeanderSettings().m_maxAmplitude );
2418 updateTuningPattern();
2419 }
2420 else
2421 {
2422 m_frame->ShowInfoBarWarning( _( "Select a track to tune first." ) );
2423 }
2424 }
2425 else if( evt->IsAction( &PCB_ACTIONS::properties )
2426 || evt->IsAction( &PCB_ACTIONS::lengthTunerSettings ) )
2427 {
2428 if( m_tuningPattern )
2429 {
2430 DRC_CONSTRAINT constraint;
2431
2432 if( !m_tuningPattern->GetItems().empty() )
2433 {
2434 BOARD_ITEM* startItem = *m_tuningPattern->GetItems().begin();
2435
2436 constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr,
2437 startItem->GetLayer() );
2438 }
2439
2441 m_tuningPattern->GetPNSMode(), constraint );
2442
2443 if( dlg.ShowModal() == wxID_OK )
2444 updateTuningPattern();
2445 }
2446 else
2447 {
2448 m_frame->ShowInfoBarWarning( _( "Select a track to tune first." ) );
2449 }
2450 }
2451 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
2452 // but we don't at present have that, so we just knock out some of the egregious ones.
2453 else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
2454 {
2455 wxBell();
2456 }
2457 else
2458 {
2459 evt->SetPassEvent();
2460 }
2461
2462 controls->CaptureCursor( m_tuningPattern != nullptr );
2463 controls->SetAutoPan( m_tuningPattern != nullptr );
2464 }
2465
2466 controls->CaptureCursor( false );
2467 controls->SetAutoPan( false );
2468 controls->ForceCursorPosition( false );
2469 controls->ShowCursor( false );
2470 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2471
2473 m_view->Remove( &m_preview );
2474
2476
2477 if( m_tuningPattern )
2478 selectionTool->AddItemToSel( m_tuningPattern );
2479
2480 m_frame->PopTool( aEvent );
2481 return 0;
2482}
2483
2484
2486{
2488 {
2490 .Map( LENGTH_TUNING_MODE::SINGLE, _HKI( "Single track" ) )
2491 .Map( LENGTH_TUNING_MODE::DIFF_PAIR, _HKI( "Differential pair" ) )
2492 .Map( LENGTH_TUNING_MODE::DIFF_PAIR_SKEW, _HKI( "Diff pair skew" ) );
2493
2495 .Map( PNS::MEANDER_SIDE_LEFT, _HKI( "Left" ) )
2496 .Map( PNS::MEANDER_SIDE_RIGHT, _HKI( "Right" ) )
2497 .Map( PNS::MEANDER_SIDE_DEFAULT, _HKI( "Default" ) );
2498
2505
2506 const wxString groupTab = _HKI( "Pattern Properties" );
2507
2509 _HKI( "End X" ), &PCB_TUNING_PATTERN::SetEndX,
2510 &PCB_TUNING_PATTERN::GetEndX, PROPERTY_DISPLAY::PT_SIZE,
2512 groupTab );
2513
2515 _HKI( "End Y" ), &PCB_TUNING_PATTERN::SetEndY,
2516 &PCB_TUNING_PATTERN::GetEndY, PROPERTY_DISPLAY::PT_SIZE,
2518 groupTab );
2519
2521 _HKI( "Tuning Mode" ),
2524 groupTab );
2525
2527 _HKI( "Min Amplitude" ),
2530 PROPERTY_DISPLAY::PT_SIZE, ORIGIN_TRANSFORMS::ABS_X_COORD ),
2531 groupTab );
2532
2534 _HKI( "Max Amplitude" ),
2537 PROPERTY_DISPLAY::PT_SIZE, ORIGIN_TRANSFORMS::ABS_X_COORD ),
2538 groupTab );
2539
2541 _HKI( "Initial Side" ),
2544 groupTab );
2545
2547 _HKI( "Min Spacing" ), &PCB_TUNING_PATTERN::SetSpacing,
2548 &PCB_TUNING_PATTERN::GetSpacing, PROPERTY_DISPLAY::PT_SIZE,
2550 groupTab );
2551
2553 _HKI( "Corner Radius %" ),
2556 PROPERTY_DISPLAY::PT_DEFAULT, ORIGIN_TRANSFORMS::NOT_A_COORD ),
2557 groupTab );
2558
2559 auto isSkew =
2560 []( INSPECTABLE* aItem ) -> bool
2561 {
2562 if( PCB_TUNING_PATTERN* pattern = dynamic_cast<PCB_TUNING_PATTERN*>( aItem ) )
2563 return pattern->GetTuningMode() == DIFF_PAIR_SKEW;
2564
2565 return false;
2566 };
2567
2568 auto notIsSkew =
2569 [&]( INSPECTABLE* aItem ) -> bool
2570 {
2571 return !isSkew( aItem );
2572 };
2573
2574 propMgr.AddProperty( new PROPERTY<PCB_TUNING_PATTERN, std::optional<int>>(
2575 _HKI( "Target Length" ),
2578 PROPERTY_DISPLAY::PT_SIZE, ORIGIN_TRANSFORMS::ABS_X_COORD ),
2579 groupTab )
2580 .SetAvailableFunc( notIsSkew );
2581
2582
2584 _HKI( "Target Skew" ), &PCB_TUNING_PATTERN::SetTargetSkew,
2586 PROPERTY_DISPLAY::PT_SIZE, ORIGIN_TRANSFORMS::ABS_X_COORD ),
2587 groupTab )
2588 .SetAvailableFunc( isSkew );
2589
2590
2592 _HKI( "Override Custom Rules" ),
2595 groupTab );
2596
2598 _HKI( "Single-sided" ),
2601 groupTab );
2602
2604 _HKI( "Rounded" ), &PCB_TUNING_PATTERN::SetRounded,
2606 groupTab );
2607 }
2609
2612
2614
2615// Also register under the 7.99 name
2616template <typename T>
2618{
2620 {
2621 GENERATORS_MGR::Instance().Register( wxS( "meanders" ), T::DISPLAY_NAME,
2622 []()
2623 {
2624 return new T;
2625 } );
2626 }
2627};
2628
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
constexpr int ARC_LOW_DEF
Definition: base_units.h:119
static TOOL_ACTION undo
Definition: actions.h:68
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
virtual void Revert() override
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
PNS::MEANDER_SETTINGS m_DiffPairMeanderSettings
PNS::MEANDER_SETTINGS m_SingleTrackMeanderSettings
PNS::MEANDER_SETTINGS m_SkewMeanderSettings
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:240
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:93
PCB_LAYER_ID m_layer
Definition: board_item.h:409
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: board_item.cpp:244
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:47
virtual wxString layerMaskDescribe() const
Return a string (to be shown to the user) describing a layer mask.
Definition: board_item.cpp:131
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:289
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:1971
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1900
const TRACKS & Tracks() const
Definition: board.h:328
std::tuple< int, double, double > GetTrackLength(const PCB_TRACK &aTrack) const
Return data on the length and number of track segments connected to a given track.
Definition: board.cpp:2278
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:874
void SetMaximum()
Definition: box2.h:70
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:294
bool Contains(const Vec &aPoint) const
Definition: box2.h:158
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:541
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
int m_Threshold
Definition: collector.h:234
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
Definition: commit.h:92
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
PCB_SELECTION m_preview
Definition: drawing_tool.h:362
KIGFX::VIEW * m_view
Definition: drawing_tool.h:351
BOARD_CONNECTED_ITEM * m_pickerItem
Definition: drawing_tool.h:363
bool m_inDrawingTool
Definition: drawing_tool.h:356
int PlaceTuningPattern(const TOOL_EVENT &aEvent)
BOARD * m_board
Definition: drawing_tool.h:353
PCB_BASE_EDIT_FRAME * m_frame
Definition: drawing_tool.h:354
PCB_TUNING_PATTERN * m_tuningPattern
Definition: drawing_tool.h:364
wxString GetName() const
Definition: drc_rule.h:150
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:142
bool IsNull() const
Definition: drc_rule.h:137
void ShowInfoBarWarning(const wxString &aWarningMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and a warning icon on the left ...
The base class for create windows for drawing purpose.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual const VECTOR2I GetFocusPosition() const
Similar to GetPosition, but allows items to return their visual center rather than their anchor.
Definition: eda_item.h:250
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
bool IsSelected() const
Definition: eda_item.h:110
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:131
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:130
bool IsNew() const
Definition: eda_item.h:107
static const int POINT_SIZE
Definition: edit_points.h:190
static ENUM_MAP< T > & Instance()
Definition: property.h:663
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:277
A general implementation of a COLLECTORS_GUIDE.
Definition: collectors.h:324
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:207
void Collect(BOARD_ITEM *aItem, const std::vector< KICAD_T > &aScanList, const VECTOR2I &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:482
A factory which returns an instance of a PCB_GENERATOR.
void Register(const wxString &aTypeStr, const wxString &aName, std::function< PCB_GENERATOR *(void)> aCreateFunc)
Associate a type string to display name and create function.
static GENERATORS_MGR & Instance()
const std::vector< GENERATOR_PNS_CHANGES > & GetRouterChanges()
Handle actions specific to filling copper zones.
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:36
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics) const
Draw a string.
Definition: font.cpp:257
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr)
Definition: font.cpp:146
static const METRICS & Default()
Definition: font.cpp:52
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
void ToHSL(double &aOutHue, double &aOutSaturation, double &aOutLightness) const
Converts current color (stored in RGB) to HSL format.
Definition: color4d.cpp:296
Abstract interface for drawing on a 2D-surface.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
virtual void Restore()
Restore the context.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
virtual void Scale(const VECTOR2D &aScale)
Scale the context.
virtual void Save()
Save the context.
A KIGFX::PREVIEW::DRAW_CONTEXT is a wrapper around a GAL and some other settings that makes it easy t...
Definition: draw_context.h:45
void DrawLineDashed(const VECTOR2I &aStart, const VECTOR2I &aEn, int aDashStep, int aDashFill, bool aDeEmphasised)
Draw a dashed line on the current layer.
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
void FreeItems()
Free all the items that were added to the group.
Definition: view_group.cpp:204
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:317
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:357
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1687
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:203
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:484
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1635
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:295
T Min() const
Definition: minoptmax.h:33
void SetMin(T v)
Definition: minoptmax.h:41
void SetMax(T v)
Definition: minoptmax.h:42
T Max() const
Definition: minoptmax.h:34
T Opt() const
Definition: minoptmax.h:35
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:44
const wxString GetName() const
Definition: netclass.h:62
Handle the data for a net.
Definition: netinfo.h:56
const wxString & GetNetname() const
Definition: netinfo.h:114
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:176
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION spacingDecrease
Definition: pcb_actions.h:207
static TOOL_ACTION amplIncrease
Definition: pcb_actions.h:208
static TOOL_ACTION amplDecrease
Definition: pcb_actions.h:209
static TOOL_ACTION lengthTunerSettings
Definition: pcb_actions.h:210
static TOOL_ACTION spacingIncrease
Definition: pcb_actions.h:206
const VECTOR2I & GetMid() const
Definition: pcb_track.h:281
Common, abstract interface for edit frames.
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
virtual void SetProperties(const STRING_ANY_MAP &aProps)
wxString m_generatorType
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
bool AddItem(BOARD_ITEM *aItem) override
Add item to group.
VECTOR2I m_origin
void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_generator.h:83
void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
VECTOR2I GetPosition() const override
Definition: pcb_generator.h:82
virtual std::vector< std::pair< wxString, wxVariant > > GetRowData()
virtual const STRING_ANY_MAP GetProperties() const
std::unordered_set< BOARD_ITEM * > m_items
Definition: pcb_group.h:218
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:69
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: pcb_group.cpp:345
wxString m_name
Definition: pcb_group.h:219
The selection tool: currently supports:
void GuessSelectionCandidates(GENERAL_COLLECTOR &aCollector, const VECTOR2I &aWhere) const
Try to guess best selection candidates in case multiple items are clicked, by doing some brain-dead h...
KIGFX::VIEW_CONTROLS * controls() const
BOARD * board() const
bool m_isFootprintEditor
int GetWidth() const
Definition: pcb_track.h:116
const VECTOR2I & GetStart() const
Definition: pcb_track.h:122
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:119
void SetTargetSkew(int aValue)
const STRING_ANY_MAP GetProperties() const override
bool HitTest(const BOX2I &aRect, bool aContained, int aAccuracy) const override
Test if aRect intersects this item.
void SetEnd(const VECTOR2I &aValue)
void SetMinAmplitude(int aValue)
void SetSpacing(int aValue)
bool initBaseLines(PNS::ROUTER *aRouter, int aLayer, BOARD *aBoard)
wxString GetGeneratorType() const override
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
static const wxString DISPLAY_NAME
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
PNS::ROUTER_MODE GetPNSMode()
PCB_TUNING_PATTERN(BOARD_ITEM *aParent=nullptr, PCB_LAYER_ID aLayer=F_Cu, LENGTH_TUNING_MODE aMode=LENGTH_TUNING_MODE::SINGLE)
void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
void swapData(BOARD_ITEM *aImage) override
bool recoverBaseline(PNS::ROUTER *aRouter)
void EditRevert(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
PNS::MEANDER_SIDE GetInitialSide() const
const VECTOR2I & GetEnd() const
bool UpdateEditPoints(std::shared_ptr< EDIT_POINTS > aEditPoints) override
void SetInitialSide(PNS::MEANDER_SIDE aValue)
wxString GetFriendlyName() const override
LENGTH_TUNING_MODE GetTuningMode() const
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
std::vector< EDA_ITEM * > GetPreviewItems(GENERATOR_TOOL *aTool, PCB_BASE_EDIT_FRAME *aFrame, bool aStatusItemsOnly=false) override
void EditStart(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
bool resetToBaseline(GENERATOR_TOOL *aTool, int aLayer, SHAPE_LINE_CHAIN &aBaseLine, bool aPrimary)
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
void SetOverrideCustomRules(bool aOverride)
void SetRounded(bool aFlag)
LENGTH_TUNING_MODE m_tuningMode
std::vector< std::pair< wxString, wxVariant > > GetRowData() override
static const wxString GENERATOR_TYPE
void SetCornerRadiusPercentage(int aValue)
void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
PNS::MEANDER_PLACER_BASE::TUNING_STATUS m_tuningStatus
bool UpdateFromEditPoints(std::shared_ptr< EDIT_POINTS > aEditPoints, BOARD_COMMIT *aCommit) override
std::optional< SHAPE_LINE_CHAIN > m_baseLineCoupled
void SetProperties(const STRING_ANY_MAP &aProps) override
bool removeToBaseline(PNS::ROUTER *aRouter, int aLayer, SHAPE_LINE_CHAIN &aBaseLine)
wxString GetPluralName() const override
void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override final
Draw the parts of the object belonging to layer aLayer.
void Remove(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
std::optional< SHAPE_LINE_CHAIN > m_baseLine
PNS::MEANDER_SETTINGS m_settings
void SetEndX(int aValue)
void ShowPropertiesDialog(PCB_BASE_EDIT_FRAME *aEditFrame) override
bool Update(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
bool GetOverrideCustomRules() const
void SetMaxAmplitude(int aValue)
void EditPush(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit, const wxString &aCommitMsg=wxEmptyString, int aCommitFlags=0) override
PNS::MEANDER_SETTINGS & GetSettings()
void SetSingleSided(bool aValue)
bool initBaseLine(PNS::ROUTER *aRouter, int aLayer, BOARD *aBoard, VECTOR2I &aStart, VECTOR2I &aEnd, NETINFO_ITEM *aNet, std::optional< SHAPE_LINE_CHAIN > &aBaseLine)
std::optional< int > GetTargetLength() const
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
int GetCornerRadiusPercentage() const
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
SHAPE_LINE_CHAIN getOutline() const
void SetEndY(int aValue)
void SetTargetLength(std::optional< int > aValue)
static PCB_TUNING_PATTERN * CreateNew(GENERATOR_TOOL *aTool, PCB_BASE_EDIT_FRAME *aFrame, BOARD_CONNECTED_ITEM *aStartItem, LENGTH_TUNING_MODE aMode)
bool MakeEditPoints(std::shared_ptr< EDIT_POINTS > points) const override
SHAPE_ARC & Arc()
Definition: pns_arc.h:115
Differential Pair length-matching/meandering tool.
std::vector< ITEM * > & Items()
Definition: pns_itemset.h:87
Base class for PNS router board items.
Definition: pns_item.h:97
virtual NET_HANDLE Net() const
Definition: pns_item.h:194
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:193
void SetLayer(int aLayer)
Definition: pns_item.h:199
@ SEGMENT_T
Definition: pns_item.h:106
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:185
bool OfKind(int aKindMask) const
Definition: pns_item.h:175
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:237
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:136
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:135
void SetWidth(int aWidth)
Return line width.
Definition: pns_line.h:148
virtual int Width() const
Base class for Single trace & Differential pair meandering tools, as both of them share a lot of code...
virtual void UpdateSettings(const MEANDER_SETTINGS &aSettings)
TUNING_STATUS
< Result of the length tuning operation
virtual void SpacingStep(int aSign)
Increase/decrease the current meandering spacing by one step.
virtual TUNING_STATUS TuningStatus() const =0
Return the tuning status (too short, too long, etc.) of the trace(s) being tuned.
virtual const MEANDER_SETTINGS & MeanderSettings() const
Return the current meandering configuration.
virtual long long int TuningResult() const =0
Return the resultant length or skew of the tuned traces.
virtual void AmplitudeStep(int aSign)
Increase/decreases the current meandering amplitude by one step.
Dimensions for the meandering algorithm.
Definition: pns_meander.h:68
int m_minAmplitude
Maximum meandering amplitude.
Definition: pns_meander.h:82
void SetTargetLength(long long int aOpt)
Definition: pns_meander.cpp:54
static const long long int LENGTH_UNCONSTRAINED
Definition: pns_meander.h:71
int m_cornerRadiusPercentage
Place meanders on one side.
Definition: pns_meander.h:108
MEANDER_SIDE m_initialSide
Allowable tuning error.
Definition: pns_meander.h:114
bool m_singleSided
Initial side when placing meanders at segment.
Definition: pns_meander.h:111
MINOPTMAX< long long int > m_targetLength
Target skew value for diff pair de-skewing.
Definition: pns_meander.h:97
void SetTargetSkew(int aOpt)
Definition: pns_meander.cpp:83
MINOPTMAX< int > m_targetSkew
Definition: pns_meander.h:100
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
Definition: pns_meander.h:105
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
Definition: pns_meander.h:85
bool m_overrideCustomRules
Type of corners for the meandered line.
Definition: pns_meander.h:102
int m_spacing
Amplitude/spacing adjustment step.
Definition: pns_meander.h:88
Keep the router "world" - i.e.
Definition: pns_node.h:207
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:143
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:663
std::set< OBSTACLE > OBSTACLES
Definition: pns_node.h:219
int QueryColliding(const ITEM *aItem, OBSTACLES &aObstacles, const COLLISION_SEARCH_OPTIONS &aOpts=COLLISION_SEARCH_OPTIONS()) const
Find items colliding (closer than clearance) with the item aItem.
Definition: pns_node.cpp:252
void Remove(ARC *aArc)
Remove an item from this branch.
Definition: pns_node.cpp:884
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Definition: pns_node.cpp:1014
virtual void RemoveItem(ITEM *aItem)=0
virtual void AddItem(ITEM *aItem)=0
void SetMode(ROUTER_MODE aMode)
void StopRouting()
Definition: pns_router.cpp:905
PLACEMENT_ALGO * Placer()
Definition: pns_router.h:216
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:218
void CommitRouting()
Definition: pns_router.cpp:896
const ITEM_SET QueryHoverItems(const VECTOR2I &aP, int aSlopRadius=0)
Definition: pns_router.cpp:123
void SyncWorld()
Definition: pns_router.cpp:94
RULE_RESOLVER * GetRuleResolver() const
Definition: pns_router.h:180
bool RoutingInProgress() const
Definition: pns_router.cpp:117
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:390
SIZES_SETTINGS & Sizes()
Definition: pns_router.h:211
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish, bool aForceCommit)
Definition: pns_router.cpp:858
NODE * GetWorld() const
Definition: pns_router.h:164
bool Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:450
virtual int Clearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true)=0
const SHAPE_LINE_CHAIN CLine() const
Definition: pns_segment.h:89
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_segment.h:69
void SetShape(SHAPE *shape)
Definition: pns_solid.h:98
ROUTER * Router() const
PNS_KICAD_IFACE * GetInterface() const
void SetStartLayer(int aLayer)
void DisplayItem(const PNS::ITEM *aItem, int aClearance, bool aEdit=false, int aFlags=0) override
void EraseView() override
wxString GetNetName(PNS::NET_HANDLE aNet) const override
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition: property.h:257
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:87
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
RAII class that sets an value at construction and resets it to the original value at destruction.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
int LineDistance(const VECTOR2I &aP, bool aDetermineSide=false) const
Return the closest Euclidean distance between point aP and the line defined by the ends of segment (t...
Definition: seg.cpp:400
VECTOR2I::extended_type ecoord
Definition: seg.h:44
VECTOR2I B
Definition: seg.h:50
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
Definition: seg.cpp:327
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
Definition: seg.h:143
int AddItemToSel(const TOOL_EVENT &aEvent)
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:42
virtual void Clear() override
Remove all the stored items from the group.
Definition: selection.h:93
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:115
VECTOR2I NearestPoint(const VECTOR2I &aP) const
Definition: shape_arc.cpp:399
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Simplify(int aMaxError=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
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.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in 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.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
int SegmentCount() const
Return the number of segments in this line chain.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
bool OffsetLine(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, SHAPE_LINE_CHAIN &aLeft, SHAPE_LINE_CHAIN &aRight, bool aSimplify=false) const
Creates line chains aLeft and aRight offset to this line chain.
Represent a set of closed polygons.
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void OffsetLineChain(const SHAPE_LINE_CHAIN &aLine, int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify)
Perform offsetting of a line chain.
int OutlineCount() const
Return the number of outlines in the set.
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
Definition: shape.h:232
A name/value tuple with unique names and wxAny values.
void set_iu(const std::string &aKey, const T &aVar)
bool get_to(const std::string &aKey, T &aVar) const
std::optional< T > get_opt(const std::string &aKey) const
void set(const std::string &aKey, const T &aVar)
bool get_to_iu(const std::string &aKey, T &aVar) const
GR_TEXT_H_ALIGN_T m_Halign
virtual void PopTool(const TOOL_EVENT &aEvent)
Pops a tool from the stack.
virtual void PushTool(const TOOL_EVENT &aEvent)
NB: the definition of "tool" is different at the user level.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:146
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
Generic, UI-independent tool event.
Definition: tool_event.h:167
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:460
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
VECTOR2D GetMousePosition() const
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:400
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:391
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:57
void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
wxString GetClass() const override
Return the class name.
VECTOR2I GetPosition() const override
void SetMinMax(double aMin, double aMax)
void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override
Draw the parts of the object belonging to layer aLayer.
void SetCurrent(double aCurrent, const wxString &aLabel)
TUNING_STATUS_VIEW_ITEM(PCB_BASE_EDIT_FRAME *aFrame)
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
void SetPosition(const VECTOR2I &aPos) override
wxString MessageTextFromMinOptMax(const MINOPTMAX< int > &aValue) const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
static constexpr extended_type ECOORD_MAX
Definition: vector2d.h:75
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:380
static bool IsZoneFillAction(const TOOL_EVENT *aEvent)
@ CHT_GROUP
Definition: commit.h:45
@ CHT_UNGROUP
Definition: commit.h:46
#define _HKI(x)
static bool empty(const wxTextEntryBase *aCtrl)
@ LENGTH_CONSTRAINT
Definition: drc_rule.h:65
@ SKEW_CONSTRAINT
Definition: drc_rule.h:66
#define _(s)
#define IS_NEW
New item, just created.
#define IN_EDIT
Item currently edited.
EDA_UNITS
Definition: eda_units.h:46
@ IGNORE_GRID
#define HITTEST_THRESHOLD_PIXELS
static FILENAME_RESOLVER * resolver
Definition: export_idf.cpp:53
@ LAYER_UI_START
Definition: layer_ids.h:266
@ LAYER_ANCHOR
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:205
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_Cu
Definition: layer_ids.h:64
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
Definition: eda_units.cpp:408
TEXT_DIMS GetConstantGlyphHeight(KIGFX::GAL *aGal, int aRelativeSize=0)
Set the GAL glyph height to a constant scaled value, so that it always looks the same on screen.
Push and Shove diff pair dimensions (gap) settings dialog.
MEANDER_SIDE
Definition: pns_meander.h:58
@ MEANDER_SIDE_RIGHT
Definition: pns_meander.h:61
@ MEANDER_SIDE_DEFAULT
Definition: pns_meander.h:60
@ MEANDER_SIDE_LEFT
Definition: pns_meander.h:59
@ MEANDER_STYLE_ROUND
Definition: pns_meander.h:52
@ MEANDER_STYLE_CHAMFER
Definition: pns_meander.h:53
ROUTER_MODE
Definition: pns_router.h:62
@ PNS_MODE_TUNE_DIFF_PAIR
Definition: pns_router.h:66
@ PNS_MODE_TUNE_SINGLE
Definition: pns_router.h:65
@ PNS_MODE_TUNE_DIFF_PAIR_SKEW
Definition: pns_router.h:67
Class to handle a set of BOARD_ITEMs.
static PNS::MEANDER_SIDE sideFromString(const std::string &aStr)
static LENGTH_TUNING_MODE tuningFromString(const std::string &aStr)
static std::string tuningToString(const LENGTH_TUNING_MODE aTuning)
static struct PCB_TUNING_PATTERN_DESC _PCB_TUNING_PATTERN_DESC
static LENGTH_TUNING_MODE fromPNSMode(PNS::ROUTER_MODE aRouterMode)
static PNS::MEANDER_PLACER_BASE::TUNING_STATUS statusFromString(const std::string &aStr)
static std::string sideToString(const PNS::MEANDER_SIDE aValue)
static std::string statusToString(const PNS::MEANDER_PLACER_BASE::TUNING_STATUS aStatus)
static GENERATORS_MGR::REGISTER< PCB_TUNING_PATTERN > registerMe
static PNS::LINKED_ITEM * pickSegment(PNS::ROUTER *aRouter, const VECTOR2I &aWhere, int aLayer, VECTOR2I &aPointOut, const SHAPE_LINE_CHAIN &aBaseline=SHAPE_LINE_CHAIN())
static std::optional< PNS::LINE > getPNSLine(const VECTOR2I &aStart, const VECTOR2I &aEnd, PNS::ROUTER *router, int layer, VECTOR2I &aStartOut, VECTOR2I &aEndOut)
LENGTH_TUNING_MODE
@ DIFF_PAIR
@ DIFF_PAIR_SKEW
static VECTOR2I snapToNearestTrack(const VECTOR2I &aP, BOARD *aBoard, NETINFO_ITEM *aNet, PCB_TRACK **aNearestTrack)
static REGISTER_LEGACY_TUNING_PATTERN< PCB_TUNING_PATTERN > registerMeToo
#define TYPE_HASH(x)
Definition: property.h:71
#define NO_SETTER(owner, type)
Definition: property.h:774
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition: property.h:765
#define REGISTER_TYPE(x)
Definition: property_mgr.h:371
constexpr double correction
const double epsilon
#define PNS_HOVER_ITEM
#define PNS_COLLISION
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
An abstract function object, returning a design rule (clearance, diff pair gap, etc) required between...
Definition: pns_node.h:73
MINOPTMAX< int > m_Value
Definition: pns_node.h:75
Hold an object colliding with another object, along with some useful data about the collision.
Definition: pns_node.h:87
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ BUT_LEFT
Definition: tool_event.h:131
@ BUT_RIGHT
Definition: tool_event.h:132
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:228
double DEG2RAD(double deg)
Definition: trigo.h:140
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition: typeinfo.h:91
@ NOT_USED
the 3d code uses this value
Definition: typeinfo.h:79
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:121
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673