KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_track.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) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2012 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include "pcb_track.h"
28
29#include <pcb_base_frame.h>
30#include <core/mirror.h>
32#include <board.h>
35#include <base_units.h>
36#include <layer_range.h>
38#include <lset.h>
39#include <string_utils.h>
40#include <view/view.h>
44#include <geometry/seg.h>
47#include <geometry/shape_arc.h>
48#include <drc/drc_engine.h>
49#include <pcb_painter.h>
50#include <trigo.h>
51
52#include <google/protobuf/any.pb.h>
53#include <api/api_enums.h>
54#include <api/api_utils.h>
55#include <api/api_pcb_utils.h>
56#include <api/board/board_types.pb.h>
57
60
62 BOARD_CONNECTED_ITEM( aParent, idtype )
63{
64 m_width = pcbIUScale.mmToIU( 0.2 ); // Gives a reasonable default width
65 m_hasSolderMask = false;
66}
67
68
70{
71 return new PCB_TRACK( *this );
72}
73
74
75void PCB_TRACK::CopyFrom( const BOARD_ITEM* aOther )
76{
77 wxCHECK( aOther && aOther->Type() == PCB_TRACE_T, /* void */ );
78 *this = *static_cast<const PCB_TRACK*>( aOther );
79}
80
81
82PCB_ARC::PCB_ARC( BOARD_ITEM* aParent, const SHAPE_ARC* aArc ) :
83 PCB_TRACK( aParent, PCB_ARC_T )
84{
85 m_Start = aArc->GetP0();
86 m_End = aArc->GetP1();
87 m_Mid = aArc->GetArcMid();
88}
89
90
92{
93 return new PCB_ARC( *this );
94}
95
96
97void PCB_ARC::CopyFrom( const BOARD_ITEM* aOther )
98{
99 wxCHECK( aOther && aOther->Type() == PCB_ARC_T, /* void */ );
100 *this = *static_cast<const PCB_ARC*>( aOther );
101}
102
103
105 PCB_TRACK( aParent, PCB_VIA_T ),
106 m_padStack( this )
107{
108 SetViaType( VIATYPE::THROUGH );
109 Padstack().Drill().start = F_Cu;
110 Padstack().Drill().end = B_Cu;
112
114
115 // Padstack layerset is not used for vias right now
117
118 // For now, vias are always circles
119 m_padStack.SetShape( PAD_SHAPE::CIRCLE, PADSTACK::ALL_LAYERS );
120
123
124 m_isFree = false;
125}
126
127
128PCB_VIA::PCB_VIA( const PCB_VIA& aOther ) :
129 PCB_TRACK( aOther.GetParent(), PCB_VIA_T ),
130 m_padStack( this )
131{
132 PCB_VIA::operator=( aOther );
133
134 const_cast<KIID&>( m_Uuid ) = aOther.m_Uuid;
136}
137
138
140{
142
143 m_Start = aOther.m_Start;
144 m_End = aOther.m_End;
145
146 m_viaType = aOther.m_viaType;
147 m_padStack = aOther.m_padStack;
148 m_isFree = aOther.m_isFree;
149
150 return *this;
151}
152
153
154void PCB_VIA::CopyFrom( const BOARD_ITEM* aOther )
155{
156 wxCHECK( aOther && aOther->Type() == PCB_VIA_T, /* void */ );
157 *this = *static_cast<const PCB_VIA*>( aOther );
158}
159
160
162{
163 return new PCB_VIA( *this );
164}
165
166
167wxString PCB_VIA::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
168{
169 wxString formatStr;
170
171 switch( GetViaType() )
172 {
173 case VIATYPE::BLIND_BURIED: formatStr = _( "Blind/Buried Via %s on %s" ); break;
174 case VIATYPE::MICROVIA: formatStr = _( "Micro Via %s on %s" ); break;
175 default: formatStr = _( "Via %s on %s" ); break;
176 }
177
178 return wxString::Format( formatStr, GetNetnameMsg(), layerMaskDescribe() );
179}
180
181
183{
184 return BITMAPS::via;
185}
186
187
188bool PCB_TRACK::operator==( const BOARD_ITEM& aBoardItem ) const
189{
190 if( aBoardItem.Type() != Type() )
191 return false;
192
193 const PCB_TRACK& other = static_cast<const PCB_TRACK&>( aBoardItem );
194
195 return *this == other;
196}
197
198
199bool PCB_TRACK::operator==( const PCB_TRACK& aOther ) const
200{
201 return m_Start == aOther.m_Start
202 && m_End == aOther.m_End
203 && m_layer == aOther.m_layer
204 && m_width == aOther.m_width
207}
208
209
210double PCB_TRACK::Similarity( const BOARD_ITEM& aOther ) const
211{
212 if( aOther.Type() != Type() )
213 return 0.0;
214
215 const PCB_TRACK& other = static_cast<const PCB_TRACK&>( aOther );
216
217 double similarity = 1.0;
218
219 if( m_layer != other.m_layer )
220 similarity *= 0.9;
221
222 if( m_width != other.m_width )
223 similarity *= 0.9;
224
225 if( m_Start != other.m_Start )
226 similarity *= 0.9;
227
228 if( m_End != other.m_End )
229 similarity *= 0.9;
230
231 if( m_hasSolderMask != other.m_hasSolderMask )
232 similarity *= 0.9;
233
235 similarity *= 0.9;
236
237 return similarity;
238}
239
240
241bool PCB_ARC::operator==( const BOARD_ITEM& aBoardItem ) const
242{
243 if( aBoardItem.Type() != Type() )
244 return false;
245
246 const PCB_ARC& other = static_cast<const PCB_ARC&>( aBoardItem );
247
248 return *this == other;
249}
250
251
252bool PCB_ARC::operator==( const PCB_TRACK& aOther ) const
253{
254 if( aOther.Type() != Type() )
255 return false;
256
257 const PCB_ARC& other = static_cast<const PCB_ARC&>( aOther );
258
259 return *this == other;
260}
261
262
263bool PCB_ARC::operator==( const PCB_ARC& aOther ) const
264{
265 return m_Start == aOther.m_Start
266 && m_End == aOther.m_End
267 && m_Mid == aOther.m_Mid
268 && m_layer == aOther.m_layer
269 && GetWidth() == aOther.GetWidth()
272}
273
274
275double PCB_ARC::Similarity( const BOARD_ITEM& aOther ) const
276{
277 if( aOther.Type() != Type() )
278 return 0.0;
279
280 const PCB_ARC& other = static_cast<const PCB_ARC&>( aOther );
281
282 double similarity = 1.0;
283
284 if( m_layer != other.m_layer )
285 similarity *= 0.9;
286
287 if( GetWidth() != other.GetWidth() )
288 similarity *= 0.9;
289
290 if( m_Start != other.m_Start )
291 similarity *= 0.9;
292
293 if( m_End != other.m_End )
294 similarity *= 0.9;
295
296 if( m_Mid != other.m_Mid )
297 similarity *= 0.9;
298
299 if( m_hasSolderMask != other.m_hasSolderMask )
300 similarity *= 0.9;
301
303 similarity *= 0.9;
304
305 return similarity;
306}
307
308
309bool PCB_VIA::operator==( const BOARD_ITEM& aBoardItem ) const
310{
311 if( aBoardItem.Type() != Type() )
312 return false;
313
314 const PCB_VIA& other = static_cast<const PCB_VIA&>( aBoardItem );
315
316 return *this == other;
317}
318
319
320bool PCB_VIA::operator==( const PCB_TRACK& aOther ) const
321{
322 if( aOther.Type() != Type() )
323 return false;
324
325 const PCB_VIA& other = static_cast<const PCB_VIA&>( aOther );
326
327 return *this == other;
328}
329
330
331bool PCB_VIA::operator==( const PCB_VIA& aOther ) const
332{
333 return m_Start == aOther.m_Start
334 && m_End == aOther.m_End
335 && m_layer == aOther.m_layer
336 && m_padStack == aOther.m_padStack
337 && m_viaType == aOther.m_viaType
339}
340
341
342double PCB_VIA::Similarity( const BOARD_ITEM& aOther ) const
343{
344 if( aOther.Type() != Type() )
345 return 0.0;
346
347 const PCB_VIA& other = static_cast<const PCB_VIA&>( aOther );
348
349 double similarity = 1.0;
350
351 if( m_layer != other.m_layer )
352 similarity *= 0.9;
353
354 if( m_Start != other.m_Start )
355 similarity *= 0.9;
356
357 if( m_End != other.m_End )
358 similarity *= 0.9;
359
360 if( m_padStack != other.m_padStack )
361 similarity *= 0.9;
362
363 if( m_viaType != other.m_viaType )
364 similarity *= 0.9;
365
367 similarity *= 0.9;
368
369 return similarity;
370}
371
372
373void PCB_VIA::SetWidth( int aWidth )
374{
375 m_padStack.SetSize( { aWidth, aWidth }, PADSTACK::ALL_LAYERS );
376}
377
378
380{
382}
383
384
385void PCB_VIA::SetWidth( PCB_LAYER_ID aLayer, int aWidth )
386{
387 m_padStack.SetSize( { aWidth, aWidth }, aLayer );
388}
389
390
392{
393 return m_padStack.Size( aLayer ).x;
394}
395
396
397void PCB_TRACK::Serialize( google::protobuf::Any &aContainer ) const
398{
399 kiapi::board::types::Track track;
400
401 track.mutable_id()->set_value( m_Uuid.AsStdString() );
402 track.mutable_start()->set_x_nm( GetStart().x );
403 track.mutable_start()->set_y_nm( GetStart().y );
404 track.mutable_end()->set_x_nm( GetEnd().x );
405 track.mutable_end()->set_y_nm( GetEnd().y );
406 track.mutable_width()->set_value_nm( GetWidth() );
407 track.set_layer( ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( GetLayer() ) );
408 track.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
409 : kiapi::common::types::LockedState::LS_UNLOCKED );
410 PackNet( track.mutable_net() );
411 // TODO m_hasSolderMask and m_solderMaskMargin
412
413 aContainer.PackFrom( track );
414}
415
416
417bool PCB_TRACK::Deserialize( const google::protobuf::Any &aContainer )
418{
419 kiapi::board::types::Track track;
420
421 if( !aContainer.UnpackTo( &track ) )
422 return false;
423
424 const_cast<KIID&>( m_Uuid ) = KIID( track.id().value() );
425 SetStart( VECTOR2I( track.start().x_nm(), track.start().y_nm() ) );
426 SetEnd( VECTOR2I( track.end().x_nm(), track.end().y_nm() ) );
427 SetWidth( track.width().value_nm() );
428 SetLayer( FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( track.layer() ) );
429 UnpackNet( track.net() );
430 SetLocked( track.locked() == kiapi::common::types::LockedState::LS_LOCKED );
431 // TODO m_hasSolderMask and m_solderMaskMargin
432
433 return true;
434}
435
436
437void PCB_ARC::Serialize( google::protobuf::Any &aContainer ) const
438{
439 kiapi::board::types::Arc arc;
440
441 arc.mutable_id()->set_value( m_Uuid.AsStdString() );
442 arc.mutable_start()->set_x_nm( GetStart().x );
443 arc.mutable_start()->set_y_nm( GetStart().y );
444 arc.mutable_mid()->set_x_nm( GetMid().x );
445 arc.mutable_mid()->set_y_nm( GetMid().y );
446 arc.mutable_end()->set_x_nm( GetEnd().x );
447 arc.mutable_end()->set_y_nm( GetEnd().y );
448 arc.mutable_width()->set_value_nm( GetWidth() );
449 arc.set_layer( ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( GetLayer() ) );
450 arc.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
451 : kiapi::common::types::LockedState::LS_UNLOCKED );
452 PackNet( arc.mutable_net() );
453 // TODO m_hasSolderMask and m_solderMaskMargin
454
455 aContainer.PackFrom( arc );
456}
457
458
459bool PCB_ARC::Deserialize( const google::protobuf::Any &aContainer )
460{
461 kiapi::board::types::Arc arc;
462
463 if( !aContainer.UnpackTo( &arc ) )
464 return false;
465
466 const_cast<KIID&>( m_Uuid ) = KIID( arc.id().value() );
467 SetStart( VECTOR2I( arc.start().x_nm(), arc.start().y_nm() ) );
468 SetMid( VECTOR2I( arc.mid().x_nm(), arc.mid().y_nm() ) );
469 SetEnd( VECTOR2I( arc.end().x_nm(), arc.end().y_nm() ) );
470 SetWidth( arc.width().value_nm() );
471 SetLayer( FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( arc.layer() ) );
472 UnpackNet( arc.net() );
473 SetLocked( arc.locked() == kiapi::common::types::LockedState::LS_LOCKED );
474 // TODO m_hasSolderMask and m_solderMaskMargin
475
476 return true;
477}
478
479
480void PCB_VIA::Serialize( google::protobuf::Any &aContainer ) const
481{
482 kiapi::board::types::Via via;
483
484 via.mutable_id()->set_value( m_Uuid.AsStdString() );
485 via.mutable_position()->set_x_nm( GetPosition().x );
486 via.mutable_position()->set_y_nm( GetPosition().y );
487
488 PADSTACK padstack = Padstack();
489
490 google::protobuf::Any padStackWrapper;
491 padstack.Serialize( padStackWrapper );
492 padStackWrapper.UnpackTo( via.mutable_pad_stack() );
493
494 // PADSTACK::m_layerSet is not used by vias
495 via.mutable_pad_stack()->clear_layers();
496 kiapi::board::PackLayerSet( *via.mutable_pad_stack()->mutable_layers(), GetLayerSet() );
497
498 via.set_type( ToProtoEnum<VIATYPE, kiapi::board::types::ViaType>( GetViaType() ) );
499 via.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
500 : kiapi::common::types::LockedState::LS_UNLOCKED );
501 PackNet( via.mutable_net() );
502
503 aContainer.PackFrom( via );
504}
505
506
507bool PCB_VIA::Deserialize( const google::protobuf::Any &aContainer )
508{
509 kiapi::board::types::Via via;
510
511 if( !aContainer.UnpackTo( &via ) )
512 return false;
513
514 const_cast<KIID&>( m_Uuid ) = KIID( via.id().value() );
515 SetStart( VECTOR2I( via.position().x_nm(), via.position().y_nm() ) );
516 SetEnd( GetStart() );
517
518 google::protobuf::Any padStackWrapper;
519 padStackWrapper.PackFrom( via.pad_stack() );
520
521 if( !m_padStack.Deserialize( padStackWrapper ) )
522 return false;
523
524 // PADSTACK::m_layerSet is not used by vias
526
527 SetViaType( FromProtoEnum<VIATYPE>( via.type() ) );
528 UnpackNet( via.net() );
529 SetLocked( via.locked() == kiapi::common::types::LockedState::LS_LOCKED );
530
531 return true;
532}
533
534
536{
537 SEG a( m_Start, m_End );
538 SEG b( aTrack.GetStart(), aTrack.GetEnd() );
539 return a.ApproxCollinear( b );
540}
541
542
544{
545 DRC_CONSTRAINT constraint;
546
547 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
548 {
550
551 constraint = bds.m_DRCEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, this, nullptr, m_layer );
552 }
553
554 if( aSource )
555 *aSource = constraint.GetName();
556
557 return constraint.Value();
558}
559
560
562{
563 DRC_CONSTRAINT constraint;
564
565 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
566 {
568
569 constraint = bds.m_DRCEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, this, nullptr, m_layer );
570 }
571
572 if( aSource )
573 *aSource = constraint.GetName();
574
575 return constraint.Value();
576}
577
578
580{
581 DRC_CONSTRAINT constraint;
582
583 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
584 {
586
587 constraint = bds.m_DRCEngine->EvalRules( HOLE_SIZE_CONSTRAINT, this, nullptr, m_layer );
588 }
589
590 if( aSource )
591 *aSource = constraint.GetName();
592
593 return constraint.Value();
594}
595
596
597int PCB_VIA::GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const
598{
599 if( !FlashLayer( aLayer ) )
600 {
601 if( aSource )
602 *aSource = _( "removed annular ring" );
603
604 return 0;
605 }
606
607 DRC_CONSTRAINT constraint;
608
609 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
610 {
612
613 constraint = bds.m_DRCEngine->EvalRules( ANNULAR_WIDTH_CONSTRAINT, this, nullptr, aLayer );
614 }
615
616 if( constraint.Value().HasMin() )
617 {
618 if( aSource )
619 *aSource = constraint.GetName();
620
621 return constraint.Value().Min();
622 }
623
624 return 0;
625}
626
627
629{
630 if( m_padStack.Drill().size.x > 0 ) // Use the specific value.
631 return m_padStack.Drill().size.x;
632
633 // Use the default value from the Netclass
634 NETCLASS* netclass = GetEffectiveNetClass();
635
636 if( GetViaType() == VIATYPE::MICROVIA )
637 return netclass->GetuViaDrill();
638
639 return netclass->GetViaDrill();
640}
641
642
643EDA_ITEM_FLAGS PCB_TRACK::IsPointOnEnds( const VECTOR2I& point, int min_dist ) const
644{
645 EDA_ITEM_FLAGS result = 0;
646
647 if( min_dist < 0 )
648 min_dist = m_width / 2;
649
650 if( min_dist == 0 )
651 {
652 if( m_Start == point )
653 result |= STARTPOINT;
654
655 if( m_End == point )
656 result |= ENDPOINT;
657 }
658 else
659 {
660 double dist = m_Start.Distance( point );
661
662 if( min_dist >= dist )
663 result |= STARTPOINT;
664
665 dist = m_End.Distance( point );
666
667 if( min_dist >= dist )
668 result |= ENDPOINT;
669 }
670
671 return result;
672}
673
674
676{
677 // end of track is round, this is its radius, rounded up
678 int radius = ( m_width + 1 ) / 2;
679 int ymax, xmax, ymin, xmin;
680
681 if( Type() == PCB_VIA_T )
682 {
683 ymax = m_Start.y;
684 xmax = m_Start.x;
685
686 ymin = m_Start.y;
687 xmin = m_Start.x;
688 }
689 else if( Type() == PCB_ARC_T )
690 {
691 std::shared_ptr<SHAPE> arc = GetEffectiveShape();
692 BOX2I bbox = arc->BBox();
693
694 xmin = bbox.GetLeft();
695 xmax = bbox.GetRight();
696 ymin = bbox.GetTop();
697 ymax = bbox.GetBottom();
698 }
699 else
700 {
701 ymax = std::max( m_Start.y, m_End.y );
702 xmax = std::max( m_Start.x, m_End.x );
703
704 ymin = std::min( m_Start.y, m_End.y );
705 xmin = std::min( m_Start.x, m_End.x );
706 }
707
708 ymax += radius;
709 xmax += radius;
710
711 ymin -= radius;
712 xmin -= radius;
713
714 // return a rectangle which is [pos,dim) in nature. therefore the +1
715 return BOX2ISafe( VECTOR2I( xmin, ymin ),
716 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
717}
718
719
721{
722 int radius = 0;
723
725 [&]( PCB_LAYER_ID aLayer )
726 {
727 radius = std::max( radius, GetWidth( aLayer ) );
728 } );
729
730 // via is round, this is its radius, rounded up
731 radius = ( radius + 1 ) / 2;
732
733 int ymax = m_Start.y + radius;
734 int xmax = m_Start.x + radius;
735
736 int ymin = m_Start.y - radius;
737 int xmin = m_Start.x - radius;
738
739 // return a rectangle which is [pos,dim) in nature. therefore the +1
740 return BOX2ISafe( VECTOR2I( xmin, ymin ),
741 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
742}
743
744
746{
747 int radius = GetWidth( aLayer );
748
749 // via is round, this is its radius, rounded up
750 radius = ( radius + 1 ) / 2;
751
752 int ymax = m_Start.y + radius;
753 int xmax = m_Start.x + radius;
754
755 int ymin = m_Start.y - radius;
756 int xmin = m_Start.x - radius;
757
758 // return a rectangle which is [pos,dim) in nature. therefore the +1
759 return BOX2ISafe( VECTOR2I( xmin, ymin ),
760 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
761}
762
763
765{
766 return m_Start.Distance( m_End );
767}
768
769
771{
772 const BOARD* board = GetBoard();
773
774 if( !board )
775 return 0.0;
776
777 const LENGTH_DELAY_CALCULATION* calc = board->GetLengthCalculation();
778 std::vector<LENGTH_DELAY_CALCULATION_ITEM> items{ calc->GetLengthCalculationItem( this ) };
779 constexpr PATH_OPTIMISATIONS opts = { .OptimiseViaLayers = false,
780 .MergeTracks = false,
781 .OptimiseTracesInPads = false,
782 .InferViaInPad = false
783 };
784
785 return (double) calc->CalculateDelay( items, opts );
786}
787
788
789void PCB_TRACK::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
790{
791 RotatePoint( m_Start, aRotCentre, aAngle );
792 RotatePoint( m_End, aRotCentre, aAngle );
793}
794
795
796void PCB_ARC::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
797{
798 RotatePoint( m_Start, aRotCentre, aAngle );
799 RotatePoint( m_End, aRotCentre, aAngle );
800 RotatePoint( m_Mid, aRotCentre, aAngle );
801}
802
803
804void PCB_TRACK::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
805{
806 MIRROR( m_Start, aCentre, aFlipDirection );
807 MIRROR( m_End, aCentre, aFlipDirection );
808}
809
810
811void PCB_ARC::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
812{
813 MIRROR( m_Start, aCentre, aFlipDirection );
814 MIRROR( m_End, aCentre, aFlipDirection );
815 MIRROR( m_Mid, aCentre, aFlipDirection );
816}
817
818
819void PCB_TRACK::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
820{
821 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
822 {
823 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
824 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
825 }
826 else
827 {
828 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
829 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
830 }
831
833}
834
835
836void PCB_ARC::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
837{
838 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
839 {
840 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
841 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
842 m_Mid.x = aCentre.x - ( m_Mid.x - aCentre.x );
843 }
844 else
845 {
846 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
847 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
848 m_Mid.y = aCentre.y - ( m_Mid.y - aCentre.y );
849 }
850
852}
853
854
855bool PCB_ARC::IsCCW() const
856{
857 VECTOR2L start = m_Start;
858 VECTOR2L start_end = m_End - start;
859 VECTOR2L start_mid = m_Mid - start;
860
861 return start_end.Cross( start_mid ) < 0;
862}
863
864
865void PCB_VIA::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
866{
867 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
868 {
869 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
870 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
871 }
872 else
873 {
874 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
875 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
876 }
877
878 if( GetViaType() != VIATYPE::THROUGH )
879 {
880 PCB_LAYER_ID top_layer;
881 PCB_LAYER_ID bottom_layer;
882 LayerPair( &top_layer, &bottom_layer );
883 top_layer = GetBoard()->FlipLayer( top_layer );
884 bottom_layer = GetBoard()->FlipLayer( bottom_layer );
885 SetLayerPair( top_layer, bottom_layer );
886 }
887}
888
889
890INSPECT_RESULT PCB_TRACK::Visit( INSPECTOR inspector, void* testData,
891 const std::vector<KICAD_T>& aScanTypes )
892{
893 for( KICAD_T scanType : aScanTypes )
894 {
895 if( scanType == Type() )
896 {
897 if( INSPECT_RESULT::QUIT == inspector( this, testData ) )
898 return INSPECT_RESULT::QUIT;
899 }
900 }
901
902 return INSPECT_RESULT::CONTINUE;
903}
904
905
906std::shared_ptr<SHAPE_SEGMENT> PCB_VIA::GetEffectiveHoleShape() const
907{
908 return std::make_shared<SHAPE_SEGMENT>( SEG( m_Start, m_Start ), Padstack().Drill().size.x );
909}
910
911// clang-format off: the suggestion is slightly less readable
913{
914 switch( aMode )
915 {
916 case TENTING_MODE::FROM_RULES: m_padStack.FrontOuterLayers().has_solder_mask.reset(); break;
917 case TENTING_MODE::TENTED: m_padStack.FrontOuterLayers().has_solder_mask = true; break;
918 case TENTING_MODE::NOT_TENTED: m_padStack.FrontOuterLayers().has_solder_mask = false; break;
919 }
920}
921
922
924{
926 {
928 TENTING_MODE::TENTED : TENTING_MODE::NOT_TENTED;
929 }
930
931 return TENTING_MODE::FROM_RULES;
932}
933
934
936{
937 switch( aMode )
938 {
939 case TENTING_MODE::FROM_RULES: m_padStack.BackOuterLayers().has_solder_mask.reset(); break;
940 case TENTING_MODE::TENTED: m_padStack.BackOuterLayers().has_solder_mask = true; break;
941 case TENTING_MODE::NOT_TENTED: m_padStack.BackOuterLayers().has_solder_mask = false; break;
942 }
943}
944
945
947{
948 if( m_padStack.BackOuterLayers().has_solder_mask.has_value() )
949 {
951 TENTING_MODE::TENTED : TENTING_MODE::NOT_TENTED;
952 }
953
954 return TENTING_MODE::FROM_RULES;
955}
956
957
959{
960 switch( aMode )
961 {
962 case COVERING_MODE::FROM_RULES: m_padStack.FrontOuterLayers().has_covering.reset(); break;
963 case COVERING_MODE::COVERED: m_padStack.FrontOuterLayers().has_covering = true; break;
964 case COVERING_MODE::NOT_COVERED: m_padStack.FrontOuterLayers().has_covering = false; break;
965 }
966}
967
968
970{
971 if( m_padStack.FrontOuterLayers().has_covering.has_value() )
972 {
974 COVERING_MODE::COVERED : COVERING_MODE::NOT_COVERED;
975 }
976
977 return COVERING_MODE::FROM_RULES;
978}
979
980
982{
983 switch( aMode )
984 {
985 case COVERING_MODE::FROM_RULES: m_padStack.BackOuterLayers().has_covering.reset(); break;
986 case COVERING_MODE::COVERED: m_padStack.BackOuterLayers().has_covering = true; break;
987 case COVERING_MODE::NOT_COVERED: m_padStack.BackOuterLayers().has_covering = false; break;
988 }
989}
990
991
993{
994 if( m_padStack.BackOuterLayers().has_covering.has_value() )
995 {
997 COVERING_MODE::COVERED : COVERING_MODE::NOT_COVERED;
998 }
999
1000 return COVERING_MODE::FROM_RULES;
1001}
1002
1003
1005{
1006 switch( aMode )
1007 {
1008 case PLUGGING_MODE::FROM_RULES: m_padStack.FrontOuterLayers().has_plugging.reset(); break;
1009 case PLUGGING_MODE::PLUGGED: m_padStack.FrontOuterLayers().has_plugging = true; break;
1010 case PLUGGING_MODE::NOT_PLUGGED: m_padStack.FrontOuterLayers().has_plugging = false; break;
1011 }
1012}
1013
1014
1016{
1017 if( m_padStack.FrontOuterLayers().has_plugging.has_value() )
1018 {
1020 PLUGGING_MODE::PLUGGED : PLUGGING_MODE::NOT_PLUGGED;
1021 }
1022
1023 return PLUGGING_MODE::FROM_RULES;
1024}
1025
1026
1028{
1029 switch( aMode )
1030 {
1031 case PLUGGING_MODE::FROM_RULES: m_padStack.BackOuterLayers().has_plugging.reset(); break;
1032 case PLUGGING_MODE::PLUGGED: m_padStack.BackOuterLayers().has_plugging = true; break;
1033 case PLUGGING_MODE::NOT_PLUGGED: m_padStack.BackOuterLayers().has_plugging = false; break;
1034 }
1035}
1036
1037
1039{
1040 if( m_padStack.BackOuterLayers().has_plugging.has_value() )
1041 {
1043 PLUGGING_MODE::PLUGGED : PLUGGING_MODE::NOT_PLUGGED;
1044 }
1045
1046 return PLUGGING_MODE::FROM_RULES;
1047}
1048
1049
1051{
1052 switch( aMode )
1053 {
1054 case CAPPING_MODE::FROM_RULES: m_padStack.Drill().is_capped.reset(); break;
1055 case CAPPING_MODE::CAPPED: m_padStack.Drill().is_capped = true; break;
1056 case CAPPING_MODE::NOT_CAPPED: m_padStack.Drill().is_capped = false; break;
1057 }
1058}
1059
1060
1062{
1063 if( m_padStack.Drill().is_capped.has_value() )
1064 {
1065 return *m_padStack.Drill().is_capped ?
1066 CAPPING_MODE::CAPPED : CAPPING_MODE::NOT_CAPPED;
1067 }
1068
1069 return CAPPING_MODE::FROM_RULES;
1070}
1071
1072
1074{
1075 switch( aMode )
1076 {
1077 case FILLING_MODE::FROM_RULES: m_padStack.Drill().is_filled.reset(); break;
1078 case FILLING_MODE::FILLED: m_padStack.Drill().is_filled = true; break;
1079 case FILLING_MODE::NOT_FILLED: m_padStack.Drill().is_filled = false; break;
1080 }
1081}
1082
1083
1085{
1086 if( m_padStack.Drill().is_filled.has_value() )
1087 {
1088 return *m_padStack.Drill().is_filled ?
1089 FILLING_MODE::FILLED : FILLING_MODE::NOT_FILLED;
1090 }
1091
1092 return FILLING_MODE::FROM_RULES;
1093}
1094// clang-format on: the suggestion is slightly less readable
1095
1096
1098{
1099 wxCHECK_MSG( IsFrontLayer( aLayer ) || IsBackLayer( aLayer ), true,
1100 "Invalid layer passed to IsTented" );
1101
1102 bool front = IsFrontLayer( aLayer );
1103
1104 if( front && m_padStack.FrontOuterLayers().has_solder_mask.has_value() )
1106
1107 if( !front && m_padStack.BackOuterLayers().has_solder_mask.has_value() )
1109
1110 if( const BOARD* board = GetBoard() )
1111 {
1112 return front ? board->GetDesignSettings().m_TentViasFront
1113 : board->GetDesignSettings().m_TentViasBack;
1114 }
1115
1116 return true;
1117}
1118
1119
1121{
1122 if( const BOARD* board = GetBoard() )
1123 return board->GetDesignSettings().m_SolderMaskExpansion;
1124 else
1125 return 0;
1126}
1127
1128
1130{
1131 int margin = 0;
1132
1133 if( const BOARD* board = GetBoard() )
1134 {
1135 DRC_CONSTRAINT constraint;
1136 std::shared_ptr<DRC_ENGINE> drcEngine = board->GetDesignSettings().m_DRCEngine;
1137
1138 constraint = drcEngine->EvalRules( SOLDER_MASK_EXPANSION_CONSTRAINT, this, nullptr, m_layer );
1139
1140 if( constraint.m_Value.HasOpt() )
1141 margin = constraint.m_Value.Opt();
1142 }
1143 else if( m_solderMaskMargin.has_value() )
1144 {
1145 margin = m_solderMaskMargin.value();
1146 }
1147
1148 // Ensure the resulting mask opening has a non-negative size
1149 if( margin < 0 )
1150 margin = std::max( margin, -m_width / 2 );
1151
1152 return margin;
1153}
1154
1155
1157{
1158 if( aLayer == m_layer )
1159 {
1160 return true;
1161 }
1162
1163 if( m_hasSolderMask && ( ( aLayer == F_Mask && m_layer == F_Cu )
1164 || ( aLayer == B_Mask && m_layer == B_Cu ) ) )
1165 {
1166 return true;
1167 }
1168
1169 return false;
1170}
1171
1172
1174{
1175#if 0
1176 // Nice and simple, but raises its ugly head in performance profiles....
1177 return GetLayerSet().test( aLayer );
1178#endif
1179 if( IsCopperLayer( aLayer ) &&
1180 LAYER_RANGE::Contains( Padstack().Drill().start, Padstack().Drill().end, aLayer ) )
1181 {
1182 return true;
1183 }
1184
1185 // Test for via on mask layers: a via on on a mask layer if not tented and if
1186 // it is on the corresponding external copper layer
1187 if( aLayer == F_Mask )
1188 return Padstack().Drill().start == F_Cu && !IsTented( F_Mask );
1189 else if( aLayer == B_Mask )
1190 return Padstack().Drill().end == B_Cu && !IsTented( B_Mask );
1191
1192 return false;
1193}
1194
1195
1196bool PCB_VIA::HasValidLayerPair( int aCopperLayerCount )
1197{
1198 // return true if top and bottom layers are valid, depending on the copper layer count
1199 // aCopperLayerCount is expected >= 2
1200
1201 int layer_id = aCopperLayerCount*2;
1202
1203 if( Padstack().Drill().start > B_Cu )
1204 {
1205 if( Padstack().Drill().start > layer_id )
1206 return false;
1207 }
1208 if( Padstack().Drill().end > B_Cu )
1209 {
1210 if( Padstack().Drill().end > layer_id )
1211 return false;
1212 }
1213
1214 return true;
1215}
1216
1217
1219{
1220 return Padstack().Drill().start;
1221}
1222
1223
1225{
1226 Padstack().Drill().start = aLayer;
1227}
1228
1229
1230void PCB_TRACK::SetLayerSet( const LSET& aLayerSet )
1231{
1232 aLayerSet.RunOnLayers(
1233 [&]( PCB_LAYER_ID layer )
1234 {
1235 if( IsCopperLayer( layer ) )
1236 SetLayer( layer );
1237 else if( IsSolderMaskLayer( layer ) )
1238 SetHasSolderMask( true );
1239 } );
1240}
1241
1242
1244{
1245 LSET layermask( { m_layer } );
1246
1247 if( m_hasSolderMask )
1248 {
1249 if( layermask.test( F_Cu ) )
1250 layermask.set( F_Mask );
1251 else if( layermask.test( B_Cu ) )
1252 layermask.set( B_Mask );
1253 }
1254
1255 return layermask;
1256}
1257
1258
1260{
1261 LSET layermask;
1262
1263 if( Padstack().Drill().start < PCBNEW_LAYER_ID_START )
1264 return layermask;
1265
1266 if( GetViaType() == VIATYPE::THROUGH )
1267 {
1268 layermask = LSET::AllCuMask( BoardCopperLayerCount() );
1269 }
1270 else
1271 {
1272 LAYER_RANGE range( Padstack().Drill().start, Padstack().Drill().end, BoardCopperLayerCount() );
1273
1274 int cnt = BoardCopperLayerCount();
1275 // PCB_LAYER_IDs are numbered from front to back, this is top to bottom.
1276 for( PCB_LAYER_ID id : range )
1277 {
1278 layermask.set( id );
1279
1280 if( --cnt <= 0 )
1281 break;
1282 }
1283 }
1284
1285 if( !IsTented( F_Mask ) && layermask.test( F_Cu ) )
1286 layermask.set( F_Mask );
1287
1288 if( !IsTented( B_Mask ) && layermask.test( B_Cu ) )
1289 layermask.set( B_Mask );
1290
1291 return layermask;
1292}
1293
1294
1295void PCB_VIA::SetLayerSet( const LSET& aLayerSet )
1296{
1297 // Vias do not use a LSET, just a top and bottom layer pair
1298 // So we need to set these 2 layers according to the allowed layers in aLayerSet
1299
1300 // For via through, only F_Cu and B_Cu are allowed. aLayerSet is ignored
1301 if( GetViaType() == VIATYPE::THROUGH )
1302 {
1303 Padstack().Drill().start = F_Cu;
1304 Padstack().Drill().end = B_Cu;
1305 return;
1306 }
1307
1308 // For blind buried vias, find the top and bottom layers
1309 bool top_found = false;
1310 bool bottom_found = false;
1311
1312 aLayerSet.RunOnLayers(
1313 [&]( PCB_LAYER_ID layer )
1314 {
1315 // tpo layer and bottom Layer are copper layers, so consider only copper layers
1316 if( IsCopperLayer( layer ) )
1317 {
1318 // The top layer is the first layer found in list and
1319 // cannot the B_Cu
1320 if( !top_found && layer != B_Cu )
1321 {
1322 Padstack().Drill().start = layer;
1323 top_found = true;
1324 }
1325
1326 // The bottom layer is the last layer found in list or B_Cu
1327 if( !bottom_found )
1328 Padstack().Drill().end = layer;
1329
1330 if( layer == B_Cu )
1331 bottom_found = true;
1332 }
1333 } );
1334}
1335
1336
1337void PCB_VIA::SetLayerPair( PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer )
1338{
1339 Padstack().Drill().start = aTopLayer;
1340 Padstack().Drill().end = aBottomLayer;
1342}
1343
1344
1346{
1347 // refuse invalid via
1348 if( aLayer == Padstack().Drill().end )
1349 return;
1350
1351 Padstack().Drill().start = aLayer;
1353}
1354
1355
1357{
1358 // refuse invalid via
1359 if( aLayer == Padstack().Drill().start )
1360 return;
1361
1362 Padstack().Drill().end = aLayer;
1364}
1365
1366
1367void PCB_VIA::LayerPair( PCB_LAYER_ID* top_layer, PCB_LAYER_ID* bottom_layer ) const
1368{
1369 PCB_LAYER_ID t_layer = F_Cu;
1370 PCB_LAYER_ID b_layer = B_Cu;
1371
1372 if( GetViaType() != VIATYPE::THROUGH )
1373 {
1374 b_layer = Padstack().Drill().end;
1375 t_layer = Padstack().Drill().start;
1376
1377 if( !IsCopperLayerLowerThan( b_layer, t_layer ) )
1378 std::swap( b_layer, t_layer );
1379 }
1380
1381 if( top_layer )
1382 *top_layer = t_layer;
1383
1384 if( bottom_layer )
1385 *bottom_layer = b_layer;
1386}
1387
1388
1390{
1391 return Padstack().Drill().start;
1392}
1393
1394
1396{
1397 return Padstack().Drill().end;
1398}
1399
1400
1402{
1403 if( GetViaType() == VIATYPE::THROUGH )
1404 {
1405 Padstack().Drill().start = F_Cu;
1406 Padstack().Drill().end = B_Cu;
1407 }
1408
1409 if( !IsCopperLayerLowerThan( Padstack().Drill().end, Padstack().Drill().start) )
1410 std::swap( Padstack().Drill().end, Padstack().Drill().start );
1411}
1412
1413
1414bool PCB_VIA::FlashLayer( const LSET& aLayers ) const
1415{
1416 for( PCB_LAYER_ID layer : aLayers )
1417 {
1418 if( FlashLayer( layer ) )
1419 return true;
1420 }
1421
1422 return false;
1423}
1424
1425
1426bool PCB_VIA::FlashLayer( int aLayer ) const
1427{
1428 // Return the "normal" shape if the caller doesn't specify a particular layer
1429 if( aLayer == UNDEFINED_LAYER )
1430 return true;
1431
1432 const BOARD* board = GetBoard();
1433 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aLayer );
1434
1435 if( !board )
1436 return true;
1437
1438 if( !IsOnLayer( layer ) )
1439 return false;
1440
1441 if( !IsCopperLayer( layer ) )
1442 return true;
1443
1444 switch( Padstack().UnconnectedLayerMode() )
1445 {
1447 return true;
1448
1450 {
1451 if( layer == Padstack().Drill().start || layer == Padstack().Drill().end )
1452 return true;
1453
1454 // Check for removal below
1455 break;
1456 }
1457
1459 // Check for removal below
1460 break;
1461
1463 return layer == Padstack().Drill().start || layer == Padstack().Drill().end;
1464 }
1465
1466 if( GetZoneLayerOverride( layer ) == ZLO_FORCE_FLASHED )
1467 {
1468 return true;
1469 }
1470 else
1471 {
1472 // Must be static to keep from raising its ugly head in performance profiles
1473 static std::initializer_list<KICAD_T> nonZoneTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
1474 PCB_PAD_T };
1475
1476 return board->GetConnectivity()->IsConnectedOnLayer( this, layer, nonZoneTypes );
1477 }
1478}
1479
1480
1482{
1483 std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
1484
1487}
1488
1489
1491{
1492 static const ZONE_LAYER_OVERRIDE defaultOverride = ZLO_NONE;
1493 auto it = m_zoneLayerOverrides.find( aLayer );
1494 return it != m_zoneLayerOverrides.end() ? it->second : defaultOverride;
1495}
1496
1497
1499{
1500 std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
1501 m_zoneLayerOverrides[aLayer] = aOverride;
1502}
1503
1504
1506 PCB_LAYER_ID* aBottommost ) const
1507{
1508 *aTopmost = UNDEFINED_LAYER;
1509 *aBottommost = UNDEFINED_LAYER;
1510
1511 static std::initializer_list<KICAD_T> nonZoneTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
1512 PCB_PAD_T };
1513
1514 for( int layer = TopLayer(); layer <= BottomLayer(); ++layer )
1515 {
1516 bool connected = false;
1517
1518 if( GetZoneLayerOverride( static_cast<PCB_LAYER_ID>( layer ) ) == ZLO_FORCE_FLASHED )
1519 {
1520 connected = true;
1521 }
1522 else if( GetBoard()->GetConnectivity()->IsConnectedOnLayer( this, layer, nonZoneTypes ) )
1523 {
1524 connected = true;
1525 }
1526
1527 if( connected )
1528 {
1529 if( *aTopmost == UNDEFINED_LAYER )
1530 *aTopmost = ToLAYER_ID( layer );
1531
1532 *aBottommost = ToLAYER_ID( layer );
1533 }
1534 }
1535
1536}
1537
1538
1539std::vector<int> PCB_TRACK::ViewGetLayers() const
1540{
1541 // Show the track and its netname on different layers
1542 const PCB_LAYER_ID layer = GetLayer();
1543 std::vector<int> layers{
1544 layer,
1545 GetNetnameLayer( layer ),
1546 LAYER_CLEARANCE_START + layer,
1547 };
1548
1549 layers.reserve( 6 );
1550
1551 if( m_hasSolderMask )
1552 {
1553 if( m_layer == F_Cu )
1554 layers.push_back( F_Mask );
1555 else if( m_layer == B_Cu )
1556 layers.push_back( B_Mask );
1557 }
1558
1559 if( IsLocked() )
1560 layers.push_back( LAYER_LOCKED_ITEM_SHADOW );
1561
1562 return layers;
1563}
1564
1565
1566double PCB_TRACK::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
1567{
1568 PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
1569 PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
1570
1571 if( !aView->IsLayerVisible( LAYER_TRACKS ) )
1572 return LOD_HIDE;
1573
1574 if( IsNetnameLayer( aLayer ) )
1575 {
1577 return LOD_HIDE;
1578
1579 // Hide netnames on dimmed tracks
1580 if( renderSettings->GetHighContrast() )
1581 {
1582 if( m_layer != renderSettings->GetPrimaryHighContrastLayer() )
1583 return LOD_HIDE;
1584 }
1585
1586 VECTOR2I start( GetStart() );
1587 VECTOR2I end( GetEnd() );
1588
1589 // Calc the approximate size of the netname (assume square chars)
1590 SEG::ecoord nameSize = GetDisplayNetname().size() * GetWidth();
1591
1592 if( VECTOR2I( end - start ).SquaredEuclideanNorm() < nameSize * nameSize )
1593 return LOD_HIDE;
1594
1595 BOX2I clipBox = BOX2ISafe( aView->GetViewport() );
1596
1597 ClipLine( &clipBox, start.x, start.y, end.x, end.y );
1598
1599 if( VECTOR2I( end - start ).SquaredEuclideanNorm() == 0 )
1600 return LOD_HIDE;
1601
1602 // Netnames will be shown only if zoom is appropriate
1603 return lodScaleForThreshold( aView, m_width, pcbIUScale.mmToIU( 4.0 ) );
1604 }
1605
1606 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
1607 {
1608 // Hide shadow if the main layer is not shown
1609 if( !aView->IsLayerVisible( m_layer ) )
1610 return LOD_HIDE;
1611
1612 // Hide shadow on dimmed tracks
1613 if( renderSettings->GetHighContrast() )
1614 {
1615 if( m_layer != renderSettings->GetPrimaryHighContrastLayer() )
1616 return LOD_HIDE;
1617 }
1618 }
1619
1620 // Other layers are shown without any conditions
1621 return LOD_SHOW;
1622}
1623
1624
1626{
1627 BOX2I bbox = GetBoundingBox();
1628
1629 if( const BOARD* board = GetBoard() )
1630 bbox.Inflate( 2 * board->GetDesignSettings().GetBiggestClearanceValue() );
1631 else
1632 bbox.Inflate( GetWidth() ); // Add a bit extra for safety
1633
1634 return bbox;
1635}
1636
1637
1638std::vector<int> PCB_VIA::ViewGetLayers() const
1639{
1640 LAYER_RANGE layers( Padstack().Drill().start, Padstack().Drill().end, MAX_CU_LAYERS );
1641 std::vector<int> ret_layers{ LAYER_VIA_HOLES, LAYER_VIA_HOLEWALLS, LAYER_VIA_NETNAMES };
1642 ret_layers.reserve( MAX_CU_LAYERS + 6 );
1643
1644 // TODO(JE) Rendering order issue
1645#if 0
1646 // Blind/buried vias (and microvias) use a different net name layer
1647 PCB_LAYER_ID layerTop, layerBottom;
1648 LayerPair( &layerTop, &layerBottom );
1649
1650 bool isBlindBuried =
1651 m_viaType == VIATYPE::BLIND_BURIED
1652 || ( m_viaType == VIATYPE::MICROVIA && ( layerTop != F_Cu || layerBottom != B_Cu ) );
1653#endif
1654 LSET cuMask = LSET::AllCuMask();
1655
1656 if( const BOARD* board = GetBoard() )
1657 cuMask &= board->GetEnabledLayers();
1658
1659 for( PCB_LAYER_ID layer : layers )
1660 {
1661 if( !cuMask.Contains( layer ) )
1662 continue;
1663
1664 ret_layers.push_back( LAYER_VIA_COPPER_START + layer );
1665 ret_layers.push_back( LAYER_CLEARANCE_START + layer );
1666 }
1667
1668 if( IsLocked() )
1669 ret_layers.push_back( LAYER_LOCKED_ITEM_SHADOW );
1670
1671 // Vias can also be on a solder mask layer. They are on these layers or not,
1672 // depending on the plot and solder mask options
1673 if( IsOnLayer( F_Mask ) )
1674 ret_layers.push_back( F_Mask );
1675
1676 if( IsOnLayer( B_Mask ) )
1677 ret_layers.push_back( B_Mask );
1678
1679 return ret_layers;
1680}
1681
1682
1683double PCB_VIA::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
1684{
1685 PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
1686 PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
1687 const BOARD* board = GetBoard();
1688
1689 // Meta control for hiding all vias
1690 if( !aView->IsLayerVisible( LAYER_VIAS ) )
1691 return LOD_HIDE;
1692
1693 // In high contrast mode don't show vias that don't cross the high-contrast layer
1694 if( renderSettings->GetHighContrast() )
1695 {
1696 PCB_LAYER_ID highContrastLayer = renderSettings->GetPrimaryHighContrastLayer();
1697
1698 if( LSET::FrontTechMask().Contains( highContrastLayer ) )
1699 highContrastLayer = F_Cu;
1700 else if( LSET::BackTechMask().Contains( highContrastLayer ) )
1701 highContrastLayer = B_Cu;
1702
1703 if( IsCopperLayer( highContrastLayer ) && GetViaType() != VIATYPE::THROUGH )
1704 {
1705 if( IsCopperLayerLowerThan( Padstack().Drill().start, highContrastLayer )
1706 || IsCopperLayerLowerThan( highContrastLayer, Padstack().Drill().end ) )
1707 {
1708 return LOD_HIDE;
1709 }
1710 }
1711 }
1712
1713 if( IsHoleLayer( aLayer ) )
1714 {
1715 LSET visible;
1716
1717 if( board )
1718 {
1719 visible = board->GetVisibleLayers();
1720 visible &= board->GetEnabledLayers();
1721 }
1722 else
1723 {
1724 visible = LSET::AllLayersMask();
1725 }
1726
1727 if( m_viaType == VIATYPE::THROUGH )
1728 {
1729 // Show a through via's hole if any physical layer is shown
1730 visible &= LSET::PhysicalLayersMask();
1731
1732 if( !visible.any() )
1733 return LOD_HIDE;
1734 }
1735 else
1736 {
1737 // Show a blind or micro via's hole if it crosses a visible layer
1738 visible &= GetLayerSet();
1739
1740 if( !visible.any() )
1741 return LOD_HIDE;
1742 }
1743
1744 // The hole won't be visible anyway at this scale
1745 return lodScaleForThreshold( aView, GetDrillValue(), pcbIUScale.mmToIU( 0.25 ) );
1746 }
1747 else if( IsNetnameLayer( aLayer ) )
1748 {
1749 if( renderSettings->GetHighContrast() )
1750 {
1751 // Hide netnames unless via is flashed to a high-contrast layer
1752 if( !FlashLayer( renderSettings->GetPrimaryHighContrastLayer() ) )
1753 return LOD_HIDE;
1754 }
1755 else
1756 {
1757 LSET visible;
1758
1759 if( board )
1760 {
1761 visible = board->GetVisibleLayers();
1762 visible &= board->GetEnabledLayers();
1763 }
1764 else
1765 {
1766 visible = LSET::AllLayersMask();
1767 }
1768
1769 // Hide netnames unless pad is flashed to a visible layer
1770 if( !FlashLayer( visible ) )
1771 return LOD_HIDE;
1772 }
1773
1774 int width = GetWidth( ToLAYER_ID( aLayer ) );
1775
1776 // Netnames will be shown only if zoom is appropriate
1777 return lodScaleForThreshold( aView, width, pcbIUScale.mmToIU( 10 ) );
1778 }
1779
1780 if( !IsCopperLayer( aLayer ) )
1781 {
1782 int width = GetWidth( ToLAYER_ID( aLayer ) );
1783
1784 return lodScaleForThreshold( aView, width, pcbIUScale.mmToIU( 0.6 ) );
1785 }
1786
1787 return LOD_SHOW;
1788}
1789
1790
1792{
1793 switch( Type() )
1794 {
1795 case PCB_ARC_T: return _( "Track (arc)" );
1796 case PCB_VIA_T: return _( "Via" );
1797 case PCB_TRACE_T:
1798 default: return _( "Track" );
1799 }
1800}
1801
1802
1803void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1804{
1805 wxString msg;
1806 BOARD* board = GetBoard();
1807
1808 aList.emplace_back( _( "Type" ), GetFriendlyName() );
1809
1810 GetMsgPanelInfoBase_Common( aFrame, aList );
1811
1812 aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
1813
1814 aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( m_width ) );
1815
1816 if( Type() == PCB_ARC_T )
1817 {
1818 double radius = static_cast<PCB_ARC*>( this )->GetRadius();
1819 aList.emplace_back( _( "Radius" ), aFrame->MessageTextFromValue( radius ) );
1820 }
1821
1822 double segmentLength = GetLength();
1823 double segmentDelay = GetDelay();
1824
1825 if( segmentDelay == 0.0 )
1826 {
1827 aList.emplace_back( _( "Segment Length" ), aFrame->MessageTextFromValue( segmentLength ) );
1828 }
1829 else
1830 {
1831 aList.emplace_back( _( "Segment Delay" ),
1832 aFrame->MessageTextFromValue( segmentDelay, true, EDA_DATA_TYPE::TIME ) );
1833 }
1834
1835 // Display full track length (in Pcbnew)
1836 if( board && GetNetCode() > 0 )
1837 {
1838 int count = 0;
1839 double trackLen = 0.0;
1840 double lenPadToDie = 0.0;
1841 double trackDelay = 0.0;
1842 double delayPadToDie = 0.0;
1843
1844 std::tie( count, trackLen, lenPadToDie, trackDelay, delayPadToDie ) = board->GetTrackLength( *this );
1845
1846 if( trackDelay == 0.0 )
1847 {
1848 aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
1849
1850 if( lenPadToDie != 0 )
1851 {
1852 msg = aFrame->MessageTextFromValue( lenPadToDie );
1853 aList.emplace_back( _( "Pad To Die Length" ), msg );
1854
1855 msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
1856 aList.emplace_back( _( "Full Length" ), msg );
1857 }
1858 }
1859 else
1860 {
1861 aList.emplace_back( _( "Routed Delay" ),
1862 aFrame->MessageTextFromValue( trackDelay, true, EDA_DATA_TYPE::TIME ) );
1863
1864 if( delayPadToDie != 0.0 )
1865 {
1866 msg = aFrame->MessageTextFromValue( delayPadToDie, true, EDA_DATA_TYPE::TIME );
1867 aList.emplace_back( _( "Pad To Die Delay" ), msg );
1868
1869 msg = aFrame->MessageTextFromValue( trackDelay + delayPadToDie, true, EDA_DATA_TYPE::TIME );
1870 aList.emplace_back( _( "Full Delay" ), msg );
1871 }
1872 }
1873 }
1874
1875 SHAPE_POLY_SET copper;
1877 aList.emplace_back( _( "Copper Area" ),
1878 aFrame->MessageTextFromValue( copper.Area(), true, EDA_DATA_TYPE::AREA ) );
1879
1880 wxString source;
1881 int clearance = GetOwnClearance( GetLayer(), &source );
1882
1883 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
1884 aFrame->MessageTextFromValue( clearance ) ),
1885 wxString::Format( _( "(from %s)" ), source ) );
1886
1887 MINOPTMAX<int> constraintValue = GetWidthConstraint( &source );
1888 msg = aFrame->MessageTextFromMinOptMax( constraintValue );
1889
1890 if( !msg.IsEmpty() )
1891 {
1892 aList.emplace_back( wxString::Format( _( "Width Constraints: %s" ), msg ),
1893 wxString::Format( _( "(from %s)" ), source ) );
1894 }
1895}
1896
1897
1898void PCB_VIA::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1899{
1900 wxString msg;
1901
1902 switch( GetViaType() )
1903 {
1904 case VIATYPE::MICROVIA: msg = _( "Micro Via" ); break;
1905 case VIATYPE::BLIND_BURIED: msg = _( "Blind/Buried Via" ); break;
1906 case VIATYPE::THROUGH: msg = _( "Through Via" ); break;
1907 default: msg = _( "Via" ); break;
1908 }
1909
1910 aList.emplace_back( _( "Type" ), msg );
1911
1912 GetMsgPanelInfoBase_Common( aFrame, aList );
1913
1914 aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
1915 // TODO(JE) padstacks
1916 aList.emplace_back( _( "Diameter" ),
1918 aList.emplace_back( _( "Hole" ), aFrame->MessageTextFromValue( GetDrillValue() ) );
1919
1920 wxString source;
1921 int clearance = GetOwnClearance( GetLayer(), &source );
1922
1923 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
1924 aFrame->MessageTextFromValue( clearance ) ),
1925 wxString::Format( _( "(from %s)" ), source ) );
1926
1927 int minAnnulus = GetMinAnnulus( GetLayer(), &source );
1928
1929 aList.emplace_back( wxString::Format( _( "Min Annular Width: %s" ),
1930 aFrame->MessageTextFromValue( minAnnulus ) ),
1931 wxString::Format( _( "(from %s)" ), source ) );
1932}
1933
1934
1936 std::vector<MSG_PANEL_ITEM>& aList ) const
1937{
1938 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
1939
1940 aList.emplace_back( _( "Resolved Netclass" ),
1941 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
1942
1943#if 0 // Enable for debugging
1944 if( GetBoard() )
1945 aList.emplace_back( _( "NetCode" ), fmt::format( "{}", GetNetCode() ) );
1946
1947 aList.emplace_back( wxT( "Flags" ), fmt::format( "#08X", m_flags ) );
1948
1949 aList.emplace_back( wxT( "Start pos" ), fmt::format( "{} {}", m_Start.x, m_Start.y ) );
1950 aList.emplace_back( wxT( "End pos" ), fmt::format( "{} {}", m_End.x, m_End.y ) );
1951#endif
1952
1953 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
1954 aList.emplace_back( _( "Status" ), _( "Locked" ) );
1955}
1956
1957
1959{
1960 const BOARD* board = GetBoard();
1961 PCB_LAYER_ID top_layer;
1962 PCB_LAYER_ID bottom_layer;
1963
1964 LayerPair( &top_layer, &bottom_layer );
1965
1966 return board->GetLayerName( top_layer ) + wxT( " - " ) + board->GetLayerName( bottom_layer );
1967}
1968
1969
1970bool PCB_TRACK::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1971{
1972 return TestSegmentHit( aPosition, m_Start, m_End, aAccuracy + ( m_width / 2 ) );
1973}
1974
1975
1976bool PCB_ARC::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1977{
1978 double max_dist = aAccuracy + ( GetWidth() / 2.0 );
1979
1980 // Short-circuit common cases where the arc is connected to a track or via at an endpoint
1981 if( GetStart().Distance( aPosition ) <= max_dist || GetEnd().Distance( aPosition ) <= max_dist )
1982 {
1983 return true;
1984 }
1985
1987 VECTOR2L relpos = aPosition - center;
1988 int64_t dist = relpos.EuclideanNorm();
1989 double radius = GetRadius();
1990
1991 if( std::abs( dist - radius ) > max_dist )
1992 return false;
1993
1994 EDA_ANGLE arc_angle = GetAngle();
1995 EDA_ANGLE arc_angle_start = GetArcAngleStart(); // Always 0.0 ... 360 deg
1996 EDA_ANGLE arc_hittest( relpos );
1997
1998 // Calculate relative angle between the starting point of the arc, and the test point
1999 arc_hittest -= arc_angle_start;
2000
2001 // Normalise arc_hittest between 0 ... 360 deg
2002 arc_hittest.Normalize();
2003
2004 if( arc_angle < ANGLE_0 )
2005 return arc_hittest >= ANGLE_360 + arc_angle;
2006
2007 return arc_hittest <= arc_angle;
2008}
2009
2010
2011bool PCB_VIA::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2012{
2013 bool hit = false;
2014
2016 [&]( PCB_LAYER_ID aLayer )
2017 {
2018 if( hit )
2019 return;
2020
2021 int max_dist = aAccuracy + ( GetWidth( aLayer ) / 2 );
2022
2023 // rel_pos is aPosition relative to m_Start (or the center of the via)
2024 VECTOR2D rel_pos = aPosition - m_Start;
2025 double dist = rel_pos.x * rel_pos.x + rel_pos.y * rel_pos.y;
2026
2027 if( dist <= static_cast<double>( max_dist ) * max_dist )
2028 hit = true;
2029 } );
2030
2031 return hit;
2032}
2033
2034
2035bool PCB_TRACK::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2036{
2037 BOX2I arect = aRect;
2038 arect.Inflate( aAccuracy );
2039
2040 if( aContained )
2041 return arect.Contains( GetStart() ) && arect.Contains( GetEnd() );
2042 else
2043 return arect.Intersects( GetStart(), GetEnd() );
2044}
2045
2046
2047bool PCB_ARC::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2048{
2049 BOX2I arect = aRect;
2050 arect.Inflate( aAccuracy );
2051
2052 BOX2I box( GetStart() );
2053 box.Merge( GetMid() );
2054 box.Merge( GetEnd() );
2055
2056 box.Inflate( GetWidth() / 2 );
2057
2058 if( aContained )
2059 return arect.Contains( box );
2060 else
2061 return arect.Intersects( box );
2062}
2063
2064
2065bool PCB_VIA::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2066{
2067 BOX2I arect = aRect;
2068 arect.Inflate( aAccuracy );
2069
2070 bool hit = false;
2071
2073 [&]( PCB_LAYER_ID aLayer )
2074 {
2075 if( hit )
2076 return;
2077
2078 BOX2I box( GetStart() );
2079 box.Inflate( GetWidth( aLayer ) / 2 );
2080
2081 if( aContained )
2082 hit = arect.Contains( box );
2083 else
2084 hit = arect.IntersectsCircle( GetStart(), GetWidth( aLayer ) / 2 );
2085 } );
2086
2087 return hit;
2088}
2089
2090
2091bool PCB_TRACK::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
2092{
2093 return KIGEOM::ShapeHitTest( aPoly, *GetEffectiveShape(), aContained );
2094}
2095
2096
2097wxString PCB_TRACK::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2098{
2099 return wxString::Format( Type() == PCB_ARC_T ? _("Track (arc) %s on %s, length %s" )
2100 : _("Track %s on %s, length %s" ),
2101 GetNetnameMsg(),
2102 GetLayerName(),
2103 aUnitsProvider->MessageTextFromValue( GetLength() ) );
2104}
2105
2106
2108{
2109 return BITMAPS::add_tracks;
2110}
2111
2113{
2114 assert( aImage->Type() == PCB_TRACE_T );
2115
2116 std::swap( *((PCB_TRACK*) this), *((PCB_TRACK*) aImage) );
2117}
2118
2120{
2121 assert( aImage->Type() == PCB_ARC_T );
2122
2123 std::swap( *this, *static_cast<PCB_ARC*>( aImage ) );
2124}
2125
2127{
2128 assert( aImage->Type() == PCB_VIA_T );
2129
2130 std::swap( *((PCB_VIA*) this), *((PCB_VIA*) aImage) );
2131}
2132
2133
2135{
2137 return center;
2138}
2139
2140
2142{
2143 auto center = CalcArcCenter( m_Start, m_Mid , m_End );
2144 return std::min( center.Distance( m_Start ), (double) INT_MAX / 2.0 );
2145}
2146
2147
2149{
2151 EDA_ANGLE angle1 = EDA_ANGLE( m_Mid - center ) - EDA_ANGLE( m_Start - center );
2152 EDA_ANGLE angle2 = EDA_ANGLE( m_End - center ) - EDA_ANGLE( m_Mid - center );
2153
2154 return angle1.Normalize180() + angle2.Normalize180();
2155}
2156
2157
2159{
2160 VECTOR2D pos( GetPosition() );
2161 EDA_ANGLE angleStart( m_Start - pos );
2162
2163 return angleStart.Normalize();
2164}
2165
2166
2167// Note: used in python tests. Ignore CLion's claim that it's unused....
2169{
2170 VECTOR2D pos( GetPosition() );
2171 EDA_ANGLE angleEnd( m_End - pos );
2172
2173 return angleEnd.Normalize();
2174}
2175
2176bool PCB_ARC::IsDegenerated( int aThreshold ) const
2177{
2178 // We have lots of code that will blow up if the radius overflows an int.
2179 if( GetRadius() >= (double)INT_MAX/2.0 )
2180 return true;
2181
2182 // Too small arcs cannot be really handled: arc center (and arc radius)
2183 // cannot be safely computed if the distance between mid and end points
2184 // is too small (a few internal units)
2185
2186 // len of both segments must be < aThreshold to be a very small degenerated arc
2187 return ( GetMid() - GetStart() ).EuclideanNorm() < aThreshold
2188 && ( GetMid() - GetEnd() ).EuclideanNorm() < aThreshold;
2189}
2190
2191
2193{
2194 if( a->GetNetCode() != b->GetNetCode() )
2195 return a->GetNetCode() < b->GetNetCode();
2196
2197 if( a->GetLayer() != b->GetLayer() )
2198 return a->GetLayer() < b->GetLayer();
2199
2200 if( a->Type() != b->Type() )
2201 return a->Type() < b->Type();
2202
2203 if( a->m_Uuid != b->m_Uuid )
2204 return a->m_Uuid < b->m_Uuid;
2205
2206 return a < b;
2207}
2208
2209
2210std::shared_ptr<SHAPE> PCB_TRACK::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2211{
2212 int width = m_width;
2213
2214 if( IsSolderMaskLayer( aLayer ) )
2215 width += 2 * GetSolderMaskExpansion();
2216
2217 return std::make_shared<SHAPE_SEGMENT>( m_Start, m_End, width );
2218}
2219
2220
2221std::shared_ptr<SHAPE> PCB_VIA::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2222{
2223 if( aFlash == FLASHING::ALWAYS_FLASHED
2224 || ( aFlash == FLASHING::DEFAULT && FlashLayer( aLayer ) ) )
2225 {
2226 int width = 0;
2227
2228 if( aLayer == UNDEFINED_LAYER )
2229 {
2230 Padstack().ForEachUniqueLayer(
2231 [&]( PCB_LAYER_ID layer )
2232 {
2233 width = std::max( width, GetWidth( layer ) );
2234 } );
2235
2236 width /= 2;
2237 }
2238 else
2239 {
2240 PCB_LAYER_ID cuLayer = m_padStack.EffectiveLayerFor( aLayer );
2241 width = GetWidth( cuLayer ) / 2;
2242 }
2243
2244 return std::make_shared<SHAPE_CIRCLE>( m_Start, width );
2245 }
2246 else
2247 {
2248 return std::make_shared<SHAPE_CIRCLE>( m_Start, GetDrillValue() / 2 );
2249 }
2250}
2251
2252
2253std::shared_ptr<SHAPE> PCB_ARC::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2254{
2255 int width = GetWidth();
2256
2257 if( IsSolderMaskLayer( aLayer ) )
2258 width += 2 * GetSolderMaskExpansion();
2259
2260 SHAPE_ARC arc( GetStart(), GetMid(), GetEnd(), width );
2261
2262 if( arc.IsEffectiveLine() )
2263 return std::make_shared<SHAPE_SEGMENT>( GetStart(), GetEnd(), width );
2264
2265 return std::make_shared<SHAPE_ARC>( arc );
2266}
2267
2268
2270 int aClearance, int aError, ERROR_LOC aErrorLoc,
2271 bool ignoreLineWidth ) const
2272{
2273 wxASSERT_MSG( !ignoreLineWidth, wxT( "IgnoreLineWidth has no meaning for tracks." ) );
2274
2275
2276 switch( Type() )
2277 {
2278 case PCB_VIA_T:
2279 {
2280 int radius = ( static_cast<const PCB_VIA*>( this )->GetWidth( aLayer ) / 2 ) + aClearance;
2281 TransformCircleToPolygon( aBuffer, m_Start, radius, aError, aErrorLoc );
2282 break;
2283 }
2284
2285 case PCB_ARC_T:
2286 {
2287 const PCB_ARC* arc = static_cast<const PCB_ARC*>( this );
2288 int width = m_width + ( 2 * aClearance );
2289
2290 if( IsSolderMaskLayer( aLayer ) )
2291 width += 2 * GetSolderMaskExpansion();
2292
2293 TransformArcToPolygon( aBuffer, arc->GetStart(), arc->GetMid(), arc->GetEnd(), width,
2294 aError, aErrorLoc );
2295 break;
2296 }
2297
2298 default:
2299 {
2300 int width = m_width + ( 2 * aClearance );
2301
2302 if( IsSolderMaskLayer( aLayer ) )
2303 width += 2 * GetSolderMaskExpansion();
2304
2305 TransformOvalToPolygon( aBuffer, m_Start, m_End, width, aError, aErrorLoc );
2306
2307 break;
2308 }
2309 }
2310}
2311
2312
2313static struct TRACK_VIA_DESC
2314{
2316 {
2317 // clang-format off: the suggestion is less readable
2319 .Undefined( VIATYPE::NOT_DEFINED )
2320 .Map( VIATYPE::THROUGH, _HKI( "Through" ) )
2321 .Map( VIATYPE::BLIND_BURIED, _HKI( "Blind/buried" ) )
2322 .Map( VIATYPE::MICROVIA, _HKI( "Micro" ) );
2323
2325 .Undefined( TENTING_MODE::FROM_RULES )
2326 .Map( TENTING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2327 .Map( TENTING_MODE::TENTED, _HKI( "Tented" ) )
2328 .Map( TENTING_MODE::NOT_TENTED, _HKI( "Not tented" ) );
2329
2331 .Undefined( COVERING_MODE::FROM_RULES )
2332 .Map( COVERING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2333 .Map( COVERING_MODE::COVERED, _HKI( "Covered" ) )
2334 .Map( COVERING_MODE::NOT_COVERED, _HKI( "Not covered" ) );
2335
2337 .Undefined( PLUGGING_MODE::FROM_RULES )
2338 .Map( PLUGGING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2339 .Map( PLUGGING_MODE::PLUGGED, _HKI( "Plugged" ) )
2340 .Map( PLUGGING_MODE::NOT_PLUGGED, _HKI( "Not plugged" ) );
2341
2343 .Undefined( CAPPING_MODE::FROM_RULES )
2344 .Map( CAPPING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2345 .Map( CAPPING_MODE::CAPPED, _HKI( "Capped" ) )
2346 .Map( CAPPING_MODE::NOT_CAPPED, _HKI( "Not capped" ) );
2347
2349 .Undefined( FILLING_MODE::FROM_RULES )
2350 .Map( FILLING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2351 .Map( FILLING_MODE::FILLED, _HKI( "Filled" ) )
2352 .Map( FILLING_MODE::NOT_FILLED, _HKI( "Not filled" ) );
2353 // clang-format on: the suggestion is less readable
2354
2356
2357 if( layerEnum.Choices().GetCount() == 0 )
2358 {
2359 layerEnum.Undefined( UNDEFINED_LAYER );
2360
2361 for( PCB_LAYER_ID layer : LSET::AllLayersMask() )
2362 layerEnum.Map( layer, LSET::Name( layer ) );
2363 }
2364
2366
2367 // Track
2370
2371 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "Width" ),
2372 &PCB_TRACK::SetWidth, &PCB_TRACK::GetWidth, PROPERTY_DISPLAY::PT_SIZE ) );
2373 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ),
2374 new PROPERTY<PCB_TRACK, int>( _HKI( "Start X" ),
2375 &PCB_TRACK::SetStartX, &PCB_TRACK::GetStartX, PROPERTY_DISPLAY::PT_COORD,
2377 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ),
2378 new PROPERTY<PCB_TRACK, int>( _HKI( "Start Y" ),
2379 &PCB_TRACK::SetStartY, &PCB_TRACK::GetStartY, PROPERTY_DISPLAY::PT_COORD,
2381 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "End X" ),
2382 &PCB_TRACK::SetEndX, &PCB_TRACK::GetEndX, PROPERTY_DISPLAY::PT_COORD,
2384 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "End Y" ),
2385 &PCB_TRACK::SetEndY, &PCB_TRACK::GetEndY, PROPERTY_DISPLAY::PT_COORD,
2387
2388 const wxString groupTechLayers = _HKI( "Technical Layers" );
2389
2390 auto isExternalLayerTrack =
2391 []( INSPECTABLE* aItem )
2392 {
2393 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( aItem ) )
2394 return IsExternalCopperLayer( track->GetLayer() );
2395
2396 return false;
2397 };
2398
2399 propMgr.AddProperty( new PROPERTY<PCB_TRACK, bool>( _HKI( "Soldermask" ),
2401 .SetAvailableFunc( isExternalLayerTrack );
2402 propMgr.AddProperty( new PROPERTY<PCB_TRACK, std::optional<int>>( _HKI( "Soldermask Margin Override" ),
2404 PROPERTY_DISPLAY::PT_SIZE ), groupTechLayers )
2405 .SetAvailableFunc( isExternalLayerTrack );
2406
2407 // Arc
2410
2411 // Via
2414
2415 // TODO test drill, use getdrillvalue?
2416 const wxString groupVia = _HKI( "Via Properties" );
2417
2418 propMgr.Mask( TYPE_HASH( PCB_VIA ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ) );
2419
2420 // clang-format off: the suggestion is less readable
2421 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Diameter" ),
2422 &PCB_VIA::SetFrontWidth, &PCB_VIA::GetFrontWidth, PROPERTY_DISPLAY::PT_SIZE ), groupVia );
2423 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Hole" ),
2424 &PCB_VIA::SetDrill, &PCB_VIA::GetDrillValue, PROPERTY_DISPLAY::PT_SIZE ), groupVia );
2425 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Layer Top" ),
2426 &PCB_VIA::SetTopLayer, &PCB_VIA::GetLayer ), groupVia );
2427 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Layer Bottom" ),
2429 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, VIATYPE>( _HKI( "Via Type" ),
2431 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, TENTING_MODE>( _HKI( "Front tenting" ),
2433 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, TENTING_MODE>( _HKI( "Back tenting" ),
2435 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, COVERING_MODE>( _HKI( "Front covering" ),
2437 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, COVERING_MODE>( _HKI( "Back covering" ),
2439 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PLUGGING_MODE>( _HKI( "Front plugging" ),
2441 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PLUGGING_MODE>( _HKI( "Back plugging" ),
2443 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, CAPPING_MODE>( _HKI( "Capping" ),
2445 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, FILLING_MODE>( _HKI( "Filling" ),
2447 // clang-format on: the suggestion is less readable
2448 }
2450
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
Definition: approximation.h:32
@ ERROR_INSIDE
Definition: approximation.h:34
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
constexpr int ARC_LOW_DEF
Definition: base_units.h:128
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
ZONE_LAYER_OVERRIDE
Conditionally flashed vias and pads that interact with zones of different priority can be very squirr...
Definition: board_item.h:67
@ ZLO_NONE
Definition: board_item.h:68
@ ZLO_FORCE_FLASHED
Definition: board_item.h:69
constexpr BOX2I BOX2ISafe(const BOX2D &aInput)
Definition: box2.h:929
BASE_SET & reset(size_t pos)
Definition: base_set.h:143
BASE_SET & set(size_t pos)
Definition: base_set.h:116
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
wxString GetNetnameMsg() const
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
void PackNet(kiapi::board::types::Net *aProto) const
const wxString & GetDisplayNetname() const
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
void UnpackNet(const kiapi::board::types::Net &aProto)
Assigns a net to this item from an API message.
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
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:232
virtual void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc) const
Convert the item shape to a polyset.
Definition: board_item.h:425
void SetLocked(bool aLocked) override
Definition: board_item.h:323
PCB_LAYER_ID m_layer
Definition: board_item.h:453
bool IsLocked() const override
Definition: board_item.cpp:103
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:280
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:79
virtual int BoardCopperLayerCount() const
Return the total number of copper layers for the board that this item resides on.
Definition: board_item.cpp:158
virtual wxString layerMaskDescribe() const
Return a string (to be shown to the user) describing a layer mask.
Definition: board_item.cpp:207
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:180
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:317
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition: board.h:1340
std::tuple< int, double, double, 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:2470
const LSET & GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:921
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition: board.cpp:852
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:680
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:907
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:522
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
bool IntersectsCircle(const Vec &aCenter, const int aRadius) const
Definition: box2.h:504
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr bool Contains(const Vec &aPoint) const
Definition: box2.h:168
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:311
constexpr coord_type GetBottom() const
Definition: box2.h:222
wxString GetName() const
Definition: drc_rule.h:168
MINOPTMAX< int > & Value()
Definition: drc_rule.h:161
MINOPTMAX< int > m_Value
Definition: drc_rule.h:202
EDA_ANGLE Normalize()
Definition: eda_angle.h:229
EDA_ANGLE Normalize180()
Definition: eda_angle.h:268
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:98
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition: eda_item.cpp:329
const KIID m_Uuid
Definition: eda_item.h:516
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:110
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:527
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:703
static ENUM_MAP< T > & Instance()
Definition: property.h:697
ENUM_MAP & Undefined(T aValue)
Definition: property.h:710
wxPGChoices & Choices()
Definition: property.h:746
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:37
Contains methods for drawing PCB-specific items.
Definition: pcb_painter.h:182
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
Definition: pcb_painter.h:187
PCB specific render settings.
Definition: pcb_painter.h:80
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
bool GetHighContrast() const
static double lodScaleForThreshold(const KIGFX::VIEW *aView, int aWhatIu, int aThresholdIu)
Get the scale at which aWhatIu would be drawn at the same size as aThresholdIu on screen.
Definition: view_item.cpp:39
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition: view_item.h:180
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition: view_item.h:185
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:66
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:530
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:422
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:220
Definition: kiid.h:49
std::string AsStdString() const
Definition: kiid.cpp:252
static bool Contains(int aStart_layer, int aEnd_layer, int aTest_layer)
Definition: layer_range.h:131
Class which calculates lengths (and associated routing statistics) in a BOARD context.
int64_t CalculateDelay(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical propagation delay of the given items.
LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem(const BOARD_CONNECTED_ITEM *aBoardItem) const
Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM.
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
Definition: lset.h:260
static const LSET & BackTechMask()
Return a mask holding all technical layers (no CU layer) on back side.
Definition: lset.cpp:631
static const LSET & AllLayersMask()
Definition: lset.cpp:624
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition: lset.cpp:591
static const LSET & PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:680
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:188
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition: lset.h:63
static const LSET & FrontTechMask()
Return a mask holding all technical layers (no CU layer) on front side.
Definition: lset.cpp:645
T Min() const
Definition: minoptmax.h:33
bool HasMin() const
Definition: minoptmax.h:37
T Opt() const
Definition: minoptmax.h:35
bool HasOpt() const
Definition: minoptmax.h:39
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:45
int GetViaDrill() const
Definition: netclass.h:141
int GetuViaDrill() const
Definition: netclass.h:157
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:381
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
Definition: padstack.h:125
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: padstack.cpp:212
MASK_LAYER_PROPS & FrontOuterLayers()
Definition: padstack.h:320
void ForEachUniqueLayer(const std::function< void(PCB_LAYER_ID)> &aMethod) const
Runs the given callable for each active unique copper layer in this padstack, meaning F_Cu for MODE::...
Definition: padstack.cpp:882
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition: padstack.h:315
const LSET & LayerSet() const
Definition: padstack.h:282
void SetShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
Definition: padstack.cpp:1068
UNCONNECTED_LAYER_MODE UnconnectedLayerMode() const
Definition: padstack.h:314
DRILL_PROPS & Drill()
Definition: padstack.h:308
const VECTOR2I & Size(PCB_LAYER_ID aLayer) const
Definition: padstack.cpp:1083
MASK_LAYER_PROPS & BackOuterLayers()
Definition: padstack.h:323
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: padstack.cpp:414
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
Definition: padstack.cpp:1074
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:145
virtual VECTOR2I GetPosition() const override
Definition: pcb_track.cpp:2134
bool IsDegenerated(int aThreshold=5) const
Definition: pcb_track.cpp:2176
virtual void swapData(BOARD_ITEM *aImage) override
Definition: pcb_track.cpp:2119
bool IsCCW() const
Definition: pcb_track.cpp:855
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: pcb_track.cpp:437
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_track.cpp:91
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pcb_track.cpp:836
EDA_ANGLE GetArcAngleStart() const
Definition: pcb_track.cpp:2158
void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
Definition: pcb_track.cpp:811
virtual bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: pcb_track.cpp:1976
EDA_ANGLE GetArcAngleEnd() const
Definition: pcb_track.cpp:2168
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: pcb_track.cpp:459
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:344
double GetRadius() const
Definition: pcb_track.cpp:2141
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:2148
const VECTOR2I & GetMid() const
Definition: pcb_track.h:345
PCB_ARC(BOARD_ITEM *aParent)
Definition: pcb_track.h:318
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
Definition: pcb_track.cpp:275
VECTOR2I m_Mid
Arc mid point, halfway between start and end.
Definition: pcb_track.h:409
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_track.cpp:796
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pcb_track.cpp:2253
bool operator==(const PCB_ARC &aOther) const
Definition: pcb_track.cpp:263
void CopyFrom(const BOARD_ITEM *aOther) override
Definition: pcb_track.cpp:97
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pcb_track.cpp:1243
virtual void SetLayerSet(const LSET &aLayers) override
Definition: pcb_track.cpp:1230
int GetSolderMaskExpansion() const
Definition: pcb_track.cpp:1129
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_track.cpp:789
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: pcb_track.cpp:397
void SetEndY(int aY)
Definition: pcb_track.h:161
void SetHasSolderMask(bool aVal)
Definition: pcb_track.h:175
virtual double GetLength() const
Get the length of the track using the hypotenuse calculation.
Definition: pcb_track.cpp:764
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: pcb_track.cpp:1566
virtual void swapData(BOARD_ITEM *aImage) override
Definition: pcb_track.cpp:2112
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:148
bool HasSolderMask() const
Definition: pcb_track.h:176
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:151
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pcb_track.cpp:1625
int GetStartY() const
Definition: pcb_track.h:158
int GetEndX() const
Definition: pcb_track.h:163
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: pcb_track.cpp:2097
virtual void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
Definition: pcb_track.cpp:804
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: pcb_track.cpp:417
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition: pcb_track.cpp:890
bool ApproxCollinear(const PCB_TRACK &aTrack)
Definition: pcb_track.cpp:535
VECTOR2I m_End
Line end point.
Definition: pcb_track.h:305
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: pcb_track.h:178
std::optional< int > m_solderMaskMargin
Definition: pcb_track.h:308
void CopyFrom(const BOARD_ITEM *aOther) override
Definition: pcb_track.cpp:75
std::optional< int > GetLocalSolderMaskMargin() const
Definition: pcb_track.h:179
virtual double GetDelay() const
Get the time delay of the track.
Definition: pcb_track.cpp:770
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.
Definition: pcb_track.cpp:1803
virtual EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_track.cpp:69
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_track.cpp:675
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the track shape to a closed polygon.
Definition: pcb_track.cpp:2269
const VECTOR2I & GetStart() const
Definition: pcb_track.h:152
virtual bool operator==(const BOARD_ITEM &aOther) const override
Definition: pcb_track.cpp:188
VECTOR2I m_Start
Line start point.
Definition: pcb_track.h:304
int GetEndY() const
Definition: pcb_track.h:164
wxString GetFriendlyName() const override
Definition: pcb_track.cpp:1791
virtual std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition: pcb_track.cpp:1539
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: pcb_track.cpp:2107
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: pcb_track.cpp:1970
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pcb_track.cpp:819
virtual double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
Definition: pcb_track.cpp:210
bool m_hasSolderMask
Definition: pcb_track.h:307
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pcb_track.cpp:2210
void SetStartX(int aX)
Definition: pcb_track.h:154
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:149
PCB_TRACK(BOARD_ITEM *aParent, KICAD_T idtype=PCB_TRACE_T)
Definition: pcb_track.cpp:61
void SetStartY(int aY)
Definition: pcb_track.h:155
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
Definition: pcb_track.cpp:1156
virtual MINOPTMAX< int > GetWidthConstraint(wxString *aSource=nullptr) const
Definition: pcb_track.cpp:543
void SetEndX(int aX)
Definition: pcb_track.h:160
int GetStartX() const
Definition: pcb_track.h:157
int m_width
Thickness of track (or arc) – no longer the width of a via.
Definition: pcb_track.h:311
EDA_ITEM_FLAGS IsPointOnEnds(const VECTOR2I &point, int min_dist=0) const
Return STARTPOINT if point if near (dist = min_dist) start point, ENDPOINT if point if near (dist = m...
Definition: pcb_track.cpp:643
virtual void SetWidth(int aWidth)
Definition: pcb_track.h:145
virtual int GetWidth() const
Definition: pcb_track.h:146
void GetMsgPanelInfoBase_Common(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) const
Definition: pcb_track.cpp:1935
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:1395
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: pcb_track.cpp:182
PLUGGING_MODE GetFrontPluggingMode() const
Definition: pcb_track.cpp:1015
VECTOR2I GetPosition() const override
Definition: pcb_track.h:557
bool IsTented(PCB_LAYER_ID aLayer) const override
Checks if the given object is tented (its copper shape is covered by solder mask) on a given side of ...
Definition: pcb_track.cpp:1097
void CopyFrom(const BOARD_ITEM *aOther) override
Definition: pcb_track.cpp:154
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pcb_track.cpp:2221
void SetCappingMode(CAPPING_MODE aMode)
Definition: pcb_track.cpp:1050
void SetFrontCoveringMode(COVERING_MODE aMode)
Definition: pcb_track.cpp:958
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: pcb_track.cpp:507
COVERING_MODE GetBackCoveringMode() const
Definition: pcb_track.cpp:992
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
Definition: pcb_track.cpp:1426
void SetDrillDefault()
Set the drill value for vias to the default value UNDEFINED_DRILL_DIAMETER.
Definition: pcb_track.h:692
std::map< PCB_LAYER_ID, ZONE_LAYER_OVERRIDE > m_zoneLayerOverrides
Definition: pcb_track.h:741
void ClearZoneLayerOverrides()
Definition: pcb_track.cpp:1481
CAPPING_MODE GetCappingMode() const
Definition: pcb_track.cpp:1061
const PADSTACK & Padstack() const
Definition: pcb_track.h:459
void SetFrontTentingMode(TENTING_MODE aMode)
Definition: pcb_track.cpp:912
bool m_isFree
"Free" vias don't get their nets auto-updated
Definition: pcb_track.h:738
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: pcb_track.cpp:2011
TENTING_MODE GetFrontTentingMode() const
Definition: pcb_track.cpp:923
void SetBottomLayer(PCB_LAYER_ID aLayer)
Definition: pcb_track.cpp:1356
int GetSolderMaskExpansion() const
Definition: pcb_track.cpp:1120
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:670
PLUGGING_MODE GetBackPluggingMode() const
Definition: pcb_track.cpp:1038
void SetBackPluggingMode(PLUGGING_MODE aMode)
Definition: pcb_track.cpp:1027
MINOPTMAX< int > GetDrillConstraint(wxString *aSource=nullptr) const
Definition: pcb_track.cpp:579
void SetBackTentingMode(TENTING_MODE aMode)
Definition: pcb_track.cpp:935
void SetFrontPluggingMode(PLUGGING_MODE aMode)
Definition: pcb_track.cpp:1004
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pcb_track.cpp:865
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.
Definition: pcb_track.cpp:1898
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_track.cpp:161
bool operator==(const PCB_VIA &aOther) const
Definition: pcb_track.cpp:331
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_track.cpp:1218
std::mutex m_zoneLayerOverridesMutex
Definition: pcb_track.h:740
void SetTopLayer(PCB_LAYER_ID aLayer)
Definition: pcb_track.cpp:1345
FILLING_MODE GetFillingMode() const
Definition: pcb_track.cpp:1084
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Definition: pcb_track.cpp:906
int GetFrontWidth() const
Definition: pcb_track.h:474
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
Definition: pcb_track.cpp:1337
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: pcb_track.cpp:167
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
Definition: pcb_track.cpp:342
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_track.cpp:1224
virtual void SetLayerSet(const LSET &aLayers) override
Note SetLayerSet() initialize the first and last copper layers connected by the via.
Definition: pcb_track.cpp:1295
void GetOutermostConnectedLayers(PCB_LAYER_ID *aTopmost, PCB_LAYER_ID *aBottommost) const
Return the top-most and bottom-most connected layers.
Definition: pcb_track.cpp:1505
void SanitizeLayers()
Check so that the layers are correct depending on the type of via, and so that the top actually is on...
Definition: pcb_track.cpp:1401
int GetWidth() const override
Definition: pcb_track.cpp:379
PCB_VIA & operator=(const PCB_VIA &aOther)
Definition: pcb_track.cpp:139
void swapData(BOARD_ITEM *aImage) override
Definition: pcb_track.cpp:2126
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: pcb_track.cpp:480
void SetFillingMode(FILLING_MODE aMode)
Definition: pcb_track.cpp:1073
PCB_VIA(BOARD_ITEM *aParent)
Definition: pcb_track.cpp:104
wxString layerMaskDescribe() const override
Return a string (to be shown to the user) describing a layer mask.
Definition: pcb_track.cpp:1958
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition: pcb_track.cpp:1638
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:452
int GetMinAnnulus(PCB_LAYER_ID aLayer, wxString *aSource) const
Definition: pcb_track.cpp:597
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
Definition: pcb_track.cpp:1173
TENTING_MODE GetBackTentingMode() const
Definition: pcb_track.cpp:946
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:1389
VIATYPE m_viaType
through, blind/buried or micro
Definition: pcb_track.h:734
PADSTACK m_padStack
Definition: pcb_track.h:736
COVERING_MODE GetFrontCoveringMode() const
Definition: pcb_track.cpp:969
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:628
void SetZoneLayerOverride(PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride)
Definition: pcb_track.cpp:1498
void SetFrontWidth(int aWidth)
Definition: pcb_track.h:473
VIATYPE GetViaType() const
Definition: pcb_track.h:451
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: pcb_track.cpp:1683
MINOPTMAX< int > GetWidthConstraint(wxString *aSource=nullptr) const override
Definition: pcb_track.cpp:561
void SetWidth(int aWidth) override
Definition: pcb_track.cpp:373
void SetBackCoveringMode(COVERING_MODE aMode)
Definition: pcb_track.cpp:981
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pcb_track.cpp:1259
const ZONE_LAYER_OVERRIDE & GetZoneLayerOverride(PCB_LAYER_ID aLayer) const
Definition: pcb_track.cpp:1490
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Return the 2 layers used by the via (the via actually uses all layers between these 2 layers)
Definition: pcb_track.cpp:1367
bool HasValidLayerPair(int aCopperLayerCount)
Definition: pcb_track.cpp:1196
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_track.cpp:720
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:74
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:76
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
PROPERTY_BASE & ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew, const wxString &aGroup=wxEmptyString)
Replace an existing property for a specific type.
Definition: seg.h:42
VECTOR2I::extended_type ecoord
Definition: seg.h:44
bool ApproxCollinear(const SEG &aSeg, int aDistanceThreshold=1) const
Definition: seg.cpp:768
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:118
const VECTOR2I & GetP1() const
Definition: shape_arc.h:117
bool IsEffectiveLine() const
Definition: shape_arc.cpp:245
const VECTOR2I & GetP0() const
Definition: shape_arc.h:116
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
double Area()
Return the area of this poly set.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString MessageTextFromMinOptMax(const MINOPTMAX< int > &aValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector2d.h:546
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition: vector2d.h:561
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void TransformArcToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arc to multiple straight segments.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define _HKI(x)
@ ANNULAR_WIDTH_CONSTRAINT
Definition: drc_rule.h:61
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:70
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:59
@ SOLDER_MASK_EXPANSION_CONSTRAINT
Definition: drc_rule.h:66
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:54
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:417
#define PCB_EDIT_FRAME_NAME
INSPECT_RESULT
Definition: eda_item.h:44
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition: eda_item.h:91
#define ENDPOINT
ends. (Used to support dragging.)
std::uint32_t EDA_ITEM_FLAGS
#define STARTPOINT
When a line is selected, these flags indicate which.
a few functions useful in geometry calculations.
bool ClipLine(const BOX2I *aClipBox, int &x1, int &y1, int &x2, int &y2)
Test if any part of a line falls within the bounds of a rectangle.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: layer_id.cpp:170
bool IsSolderMaskLayer(int aLayer)
Definition: layer_ids.h:735
@ LAYER_VIA_NETNAMES
Definition: layer_ids.h:203
bool IsCopperLayerLowerThan(PCB_LAYER_ID aLayerA, PCB_LAYER_ID aLayerB)
Return true if copper aLayerA is placed lower than aLayerB, false otherwise.
Definition: layer_ids.h:811
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START
Definition: layer_ids.h:174
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
Definition: layer_ids.h:767
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:184
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition: layer_ids.h:790
#define MAX_CU_LAYERS
Definition: layer_ids.h:176
int GetNetnameLayer(int aLayer)
Return a netname layer corresponding to the given layer.
Definition: layer_ids.h:841
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:665
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition: layer_ids.h:306
@ LAYER_VIA_HOLEWALLS
Definition: layer_ids.h:297
@ LAYER_VIA_COPPER_START
Virtual layers for via copper on a given copper layer.
Definition: layer_ids.h:336
@ LAYER_TRACKS
Definition: layer_ids.h:266
@ LAYER_CLEARANCE_START
Virtual layers for pad/via/track clearance outlines for a given copper layer.
Definition: layer_ids.h:340
@ LAYER_VIA_HOLES
Draw via holes (pad holes do not use this layer).
Definition: layer_ids.h:273
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:232
bool IsNetnameLayer(int aLayer)
Test whether a layer is a netname layer.
Definition: layer_ids.h:856
bool IsHoleLayer(int aLayer)
Definition: layer_ids.h:726
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
Definition: layer_ids.h:676
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ F_Mask
Definition: layer_ids.h:97
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:744
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:45
FLIP_DIRECTION
Definition: mirror.h:27
bool ShapeHitTest(const SHAPE_LINE_CHAIN &aHitter, const SHAPE &aHittee, bool aHitteeContained)
Perform a shape-to-shape hit test.
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:400
static struct TRACK_VIA_DESC _TRACK_VIA_DESC
FILLING_MODE
Definition: pcb_track.h:103
VIATYPE
Definition: pcb_track.h:66
TENTING_MODE
Definition: pcb_track.h:75
COVERING_MODE
Definition: pcb_track.h:82
PLUGGING_MODE
Definition: pcb_track.h:89
CAPPING_MODE
Definition: pcb_track.h:96
#define TYPE_HASH(x)
Definition: property.h:72
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition: property.h:799
#define REGISTER_TYPE(x)
Definition: property_mgr.h:351
wxString UnescapeString(const wxString &aSource)
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
PCB_LAYER_ID start
Definition: padstack.h:247
PCB_LAYER_ID end
Definition: padstack.h:248
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
Definition: padstack.h:245
std::optional< bool > is_capped
True if the drill hole should be capped.
Definition: padstack.h:251
std::optional< bool > is_filled
True if the drill hole should be filled completely.
Definition: padstack.h:250
std::optional< bool > has_covering
True if the pad on this side should have covering.
Definition: padstack.h:236
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
Definition: padstack.h:234
std::optional< bool > has_plugging
True if the drill hole should be plugged on this side.
Definition: padstack.h:237
Struct to control which optimisations the length calculation code runs on the given path objects.
bool OptimiseViaLayers
Optimise via layers for height calculations, ensuring only the distance between routed segments is co...
bool operator()(const PCB_TRACK *aFirst, const PCB_TRACK *aSecond) const
Definition: pcb_track.cpp:2192
VECTOR2I center
int radius
VECTOR2I end
int clearance
bool TestSegmentHit(const VECTOR2I &aRefPoint, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
Definition: trigo.cpp:175
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:521
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ 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
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
VECTOR2< int64_t > VECTOR2L
Definition: vector2d.h:696