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>
37#include <lset.h>
38#include <string_utils.h>
39#include <view/view.h>
43#include <geometry/seg.h>
46#include <geometry/shape_arc.h>
47#include <drc/drc_engine.h>
48#include <pcb_painter.h>
49#include <trigo.h>
50
51#include <google/protobuf/any.pb.h>
52#include <api/api_enums.h>
53#include <api/api_utils.h>
54#include <api/api_pcb_utils.h>
55#include <api/board/board_types.pb.h>
56
59
61 BOARD_CONNECTED_ITEM( aParent, idtype )
62{
63 m_width = pcbIUScale.mmToIU( 0.2 ); // Gives a reasonable default width
64 m_hasSolderMask = false;
65}
66
67
69{
70 return new PCB_TRACK( *this );
71}
72
73
74void PCB_TRACK::CopyFrom( const BOARD_ITEM* aOther )
75{
76 wxCHECK( aOther && aOther->Type() == PCB_TRACE_T, /* void */ );
77 *this = *static_cast<const PCB_TRACK*>( aOther );
78}
79
80
81PCB_ARC::PCB_ARC( BOARD_ITEM* aParent, const SHAPE_ARC* aArc ) :
82 PCB_TRACK( aParent, PCB_ARC_T )
83{
84 m_Start = aArc->GetP0();
85 m_End = aArc->GetP1();
86 m_Mid = aArc->GetArcMid();
87}
88
89
91{
92 return new PCB_ARC( *this );
93}
94
95
96void PCB_ARC::CopyFrom( const BOARD_ITEM* aOther )
97{
98 wxCHECK( aOther && aOther->Type() == PCB_ARC_T, /* void */ );
99 *this = *static_cast<const PCB_ARC*>( aOther );
100}
101
102
104 PCB_TRACK( aParent, PCB_VIA_T ),
105 m_padStack( this )
106{
107 SetViaType( VIATYPE::THROUGH );
108 Padstack().Drill().start = F_Cu;
109 Padstack().Drill().end = B_Cu;
111
113
114 // Padstack layerset is not used for vias right now
116
117 // For now, vias are always circles
118 m_padStack.SetShape( PAD_SHAPE::CIRCLE, PADSTACK::ALL_LAYERS );
119
122
123 m_isFree = false;
124}
125
126
127PCB_VIA::PCB_VIA( const PCB_VIA& aOther ) :
128 PCB_TRACK( aOther.GetParent(), PCB_VIA_T ),
129 m_padStack( this )
130{
131 PCB_VIA::operator=( aOther );
132
133 const_cast<KIID&>( m_Uuid ) = aOther.m_Uuid;
135}
136
137
139{
141
142 m_Start = aOther.m_Start;
143 m_End = aOther.m_End;
144
145 m_viaType = aOther.m_viaType;
146 m_padStack = aOther.m_padStack;
147 m_isFree = aOther.m_isFree;
148
149 return *this;
150}
151
152
153void PCB_VIA::CopyFrom( const BOARD_ITEM* aOther )
154{
155 wxCHECK( aOther && aOther->Type() == PCB_VIA_T, /* void */ );
156 *this = *static_cast<const PCB_VIA*>( aOther );
157}
158
159
161{
162 return new PCB_VIA( *this );
163}
164
165
166wxString PCB_VIA::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
167{
168 wxString formatStr;
169
170 switch( GetViaType() )
171 {
172 case VIATYPE::BLIND_BURIED: formatStr = _( "Blind/Buried Via %s on %s" ); break;
173 case VIATYPE::MICROVIA: formatStr = _( "Micro Via %s on %s" ); break;
174 default: formatStr = _( "Via %s on %s" ); break;
175 }
176
177 return wxString::Format( formatStr, GetNetnameMsg(), layerMaskDescribe() );
178}
179
180
182{
183 return BITMAPS::via;
184}
185
186
187bool PCB_TRACK::operator==( const BOARD_ITEM& aBoardItem ) const
188{
189 if( aBoardItem.Type() != Type() )
190 return false;
191
192 const PCB_TRACK& other = static_cast<const PCB_TRACK&>( aBoardItem );
193
194 return *this == other;
195}
196
197
198bool PCB_TRACK::operator==( const PCB_TRACK& aOther ) const
199{
200 return m_Start == aOther.m_Start
201 && m_End == aOther.m_End
202 && m_layer == aOther.m_layer
203 && m_width == aOther.m_width
206}
207
208
209double PCB_TRACK::Similarity( const BOARD_ITEM& aOther ) const
210{
211 if( aOther.Type() != Type() )
212 return 0.0;
213
214 const PCB_TRACK& other = static_cast<const PCB_TRACK&>( aOther );
215
216 double similarity = 1.0;
217
218 if( m_layer != other.m_layer )
219 similarity *= 0.9;
220
221 if( m_width != other.m_width )
222 similarity *= 0.9;
223
224 if( m_Start != other.m_Start )
225 similarity *= 0.9;
226
227 if( m_End != other.m_End )
228 similarity *= 0.9;
229
230 if( m_hasSolderMask != other.m_hasSolderMask )
231 similarity *= 0.9;
232
234 similarity *= 0.9;
235
236 return similarity;
237}
238
239
240bool PCB_ARC::operator==( const BOARD_ITEM& aBoardItem ) const
241{
242 if( aBoardItem.Type() != Type() )
243 return false;
244
245 const PCB_ARC& other = static_cast<const PCB_ARC&>( aBoardItem );
246
247 return *this == other;
248}
249
250
251bool PCB_ARC::operator==( const PCB_TRACK& aOther ) const
252{
253 if( aOther.Type() != Type() )
254 return false;
255
256 const PCB_ARC& other = static_cast<const PCB_ARC&>( aOther );
257
258 return *this == other;
259}
260
261
262bool PCB_ARC::operator==( const PCB_ARC& aOther ) const
263{
264 return m_Start == aOther.m_Start
265 && m_End == aOther.m_End
266 && m_Mid == aOther.m_Mid
267 && m_layer == aOther.m_layer
268 && GetWidth() == aOther.GetWidth()
271}
272
273
274double PCB_ARC::Similarity( const BOARD_ITEM& aOther ) const
275{
276 if( aOther.Type() != Type() )
277 return 0.0;
278
279 const PCB_ARC& other = static_cast<const PCB_ARC&>( aOther );
280
281 double similarity = 1.0;
282
283 if( m_layer != other.m_layer )
284 similarity *= 0.9;
285
286 if( GetWidth() != other.GetWidth() )
287 similarity *= 0.9;
288
289 if( m_Start != other.m_Start )
290 similarity *= 0.9;
291
292 if( m_End != other.m_End )
293 similarity *= 0.9;
294
295 if( m_Mid != other.m_Mid )
296 similarity *= 0.9;
297
298 if( m_hasSolderMask != other.m_hasSolderMask )
299 similarity *= 0.9;
300
302 similarity *= 0.9;
303
304 return similarity;
305}
306
307
308bool PCB_VIA::operator==( const BOARD_ITEM& aBoardItem ) const
309{
310 if( aBoardItem.Type() != Type() )
311 return false;
312
313 const PCB_VIA& other = static_cast<const PCB_VIA&>( aBoardItem );
314
315 return *this == other;
316}
317
318
319bool PCB_VIA::operator==( const PCB_TRACK& aOther ) const
320{
321 if( aOther.Type() != Type() )
322 return false;
323
324 const PCB_VIA& other = static_cast<const PCB_VIA&>( aOther );
325
326 return *this == other;
327}
328
329
330bool PCB_VIA::operator==( const PCB_VIA& aOther ) const
331{
332 return m_Start == aOther.m_Start
333 && m_End == aOther.m_End
334 && m_layer == aOther.m_layer
335 && m_padStack == aOther.m_padStack
336 && m_viaType == aOther.m_viaType
338}
339
340
341double PCB_VIA::Similarity( const BOARD_ITEM& aOther ) const
342{
343 if( aOther.Type() != Type() )
344 return 0.0;
345
346 const PCB_VIA& other = static_cast<const PCB_VIA&>( aOther );
347
348 double similarity = 1.0;
349
350 if( m_layer != other.m_layer )
351 similarity *= 0.9;
352
353 if( m_Start != other.m_Start )
354 similarity *= 0.9;
355
356 if( m_End != other.m_End )
357 similarity *= 0.9;
358
359 if( m_padStack != other.m_padStack )
360 similarity *= 0.9;
361
362 if( m_viaType != other.m_viaType )
363 similarity *= 0.9;
364
366 similarity *= 0.9;
367
368 return similarity;
369}
370
371
372void PCB_VIA::SetWidth( int aWidth )
373{
374 // This is present because of the parent class. It should never be actually called on a via.
375 wxASSERT_MSG( false, "Warning: PCB_VIA::SetWidth called without a layer argument" );
376 m_padStack.SetSize( { aWidth, aWidth }, PADSTACK::ALL_LAYERS );
377}
378
379
381{
382 // This is present because of the parent class. It should never be actually called on a via.
383 wxASSERT_MSG( false, "Warning: PCB_VIA::GetWidth called without a layer argument" );
385}
386
387
388void PCB_VIA::SetWidth( PCB_LAYER_ID aLayer, int aWidth )
389{
390 m_padStack.SetSize( { aWidth, aWidth }, aLayer );
391}
392
393
395{
396 return m_padStack.Size( aLayer ).x;
397}
398
399
400void PCB_TRACK::Serialize( google::protobuf::Any &aContainer ) const
401{
402 kiapi::board::types::Track track;
403
404 track.mutable_id()->set_value( m_Uuid.AsStdString() );
405 track.mutable_start()->set_x_nm( GetStart().x );
406 track.mutable_start()->set_y_nm( GetStart().y );
407 track.mutable_end()->set_x_nm( GetEnd().x );
408 track.mutable_end()->set_y_nm( GetEnd().y );
409 track.mutable_width()->set_value_nm( GetWidth() );
410 track.set_layer( ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( GetLayer() ) );
411 track.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
412 : kiapi::common::types::LockedState::LS_UNLOCKED );
413 track.mutable_net()->mutable_code()->set_value( GetNetCode() );
414 track.mutable_net()->set_name( GetNetname() );
415 // TODO m_hasSolderMask and m_solderMaskMargin
416
417 aContainer.PackFrom( track );
418}
419
420
421bool PCB_TRACK::Deserialize( const google::protobuf::Any &aContainer )
422{
423 kiapi::board::types::Track track;
424
425 if( !aContainer.UnpackTo( &track ) )
426 return false;
427
428 const_cast<KIID&>( m_Uuid ) = KIID( track.id().value() );
429 SetStart( VECTOR2I( track.start().x_nm(), track.start().y_nm() ) );
430 SetEnd( VECTOR2I( track.end().x_nm(), track.end().y_nm() ) );
431 SetWidth( track.width().value_nm() );
432 SetLayer( FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( track.layer() ) );
433 SetNetCode( track.net().code().value() );
434 SetLocked( track.locked() == kiapi::common::types::LockedState::LS_LOCKED );
435 // TODO m_hasSolderMask and m_solderMaskMargin
436
437 return true;
438}
439
440
441void PCB_ARC::Serialize( google::protobuf::Any &aContainer ) const
442{
443 kiapi::board::types::Arc arc;
444
445 arc.mutable_id()->set_value( m_Uuid.AsStdString() );
446 arc.mutable_start()->set_x_nm( GetStart().x );
447 arc.mutable_start()->set_y_nm( GetStart().y );
448 arc.mutable_mid()->set_x_nm( GetMid().x );
449 arc.mutable_mid()->set_y_nm( GetMid().y );
450 arc.mutable_end()->set_x_nm( GetEnd().x );
451 arc.mutable_end()->set_y_nm( GetEnd().y );
452 arc.mutable_width()->set_value_nm( GetWidth() );
453 arc.set_layer( ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( GetLayer() ) );
454 arc.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
455 : kiapi::common::types::LockedState::LS_UNLOCKED );
456 arc.mutable_net()->mutable_code()->set_value( GetNetCode() );
457 arc.mutable_net()->set_name( GetNetname() );
458 // TODO m_hasSolderMask and m_solderMaskMargin
459
460 aContainer.PackFrom( arc );
461}
462
463
464bool PCB_ARC::Deserialize( const google::protobuf::Any &aContainer )
465{
466 kiapi::board::types::Arc arc;
467
468 if( !aContainer.UnpackTo( &arc ) )
469 return false;
470
471 const_cast<KIID&>( m_Uuid ) = KIID( arc.id().value() );
472 SetStart( VECTOR2I( arc.start().x_nm(), arc.start().y_nm() ) );
473 SetMid( VECTOR2I( arc.mid().x_nm(), arc.mid().y_nm() ) );
474 SetEnd( VECTOR2I( arc.end().x_nm(), arc.end().y_nm() ) );
475 SetWidth( arc.width().value_nm() );
476 SetLayer( FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( arc.layer() ) );
477 SetNetCode( arc.net().code().value() );
478 SetLocked( arc.locked() == kiapi::common::types::LockedState::LS_LOCKED );
479 // TODO m_hasSolderMask and m_solderMaskMargin
480
481 return true;
482}
483
484
485void PCB_VIA::Serialize( google::protobuf::Any &aContainer ) const
486{
487 kiapi::board::types::Via via;
488
489 via.mutable_id()->set_value( m_Uuid.AsStdString() );
490 via.mutable_position()->set_x_nm( GetPosition().x );
491 via.mutable_position()->set_y_nm( GetPosition().y );
492
493 PADSTACK padstack = Padstack();
494
495 google::protobuf::Any padStackWrapper;
496 padstack.Serialize( padStackWrapper );
497 padStackWrapper.UnpackTo( via.mutable_pad_stack() );
498
499 // PADSTACK::m_layerSet is not used by vias
500 via.mutable_pad_stack()->clear_layers();
501 kiapi::board::PackLayerSet( *via.mutable_pad_stack()->mutable_layers(), GetLayerSet() );
502
503 via.set_type( ToProtoEnum<VIATYPE, kiapi::board::types::ViaType>( GetViaType() ) );
504 via.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
505 : kiapi::common::types::LockedState::LS_UNLOCKED );
506 via.mutable_net()->mutable_code()->set_value( GetNetCode() );
507 via.mutable_net()->set_name( GetNetname() );
508
509 aContainer.PackFrom( via );
510}
511
512
513bool PCB_VIA::Deserialize( const google::protobuf::Any &aContainer )
514{
515 kiapi::board::types::Via via;
516
517 if( !aContainer.UnpackTo( &via ) )
518 return false;
519
520 const_cast<KIID&>( m_Uuid ) = KIID( via.id().value() );
521 SetStart( VECTOR2I( via.position().x_nm(), via.position().y_nm() ) );
522 SetEnd( GetStart() );
523
524 google::protobuf::Any padStackWrapper;
525 padStackWrapper.PackFrom( via.pad_stack() );
526
527 if( !m_padStack.Deserialize( padStackWrapper ) )
528 return false;
529
530 // PADSTACK::m_layerSet is not used by vias
532
533 SetViaType( FromProtoEnum<VIATYPE>( via.type() ) );
534 SetNetCode( via.net().code().value() );
535 SetLocked( via.locked() == kiapi::common::types::LockedState::LS_LOCKED );
536
537 return true;
538}
539
540
542{
543 SEG a( m_Start, m_End );
544 SEG b( aTrack.GetStart(), aTrack.GetEnd() );
545 return a.ApproxCollinear( b );
546}
547
548
550{
551 DRC_CONSTRAINT constraint;
552
553 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
554 {
556
557 constraint = bds.m_DRCEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, this, nullptr, m_layer );
558 }
559
560 if( aSource )
561 *aSource = constraint.GetName();
562
563 return constraint.Value();
564}
565
566
568{
569 DRC_CONSTRAINT constraint;
570
571 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
572 {
574
575 constraint = bds.m_DRCEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, this, nullptr, m_layer );
576 }
577
578 if( aSource )
579 *aSource = constraint.GetName();
580
581 return constraint.Value();
582}
583
584
586{
587 DRC_CONSTRAINT constraint;
588
589 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
590 {
592
593 constraint = bds.m_DRCEngine->EvalRules( HOLE_SIZE_CONSTRAINT, this, nullptr, m_layer );
594 }
595
596 if( aSource )
597 *aSource = constraint.GetName();
598
599 return constraint.Value();
600}
601
602
603int PCB_VIA::GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const
604{
605 if( !FlashLayer( aLayer ) )
606 {
607 if( aSource )
608 *aSource = _( "removed annular ring" );
609
610 return 0;
611 }
612
613 DRC_CONSTRAINT constraint;
614
615 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
616 {
618
619 constraint = bds.m_DRCEngine->EvalRules( ANNULAR_WIDTH_CONSTRAINT, this, nullptr, aLayer );
620 }
621
622 if( constraint.Value().HasMin() )
623 {
624 if( aSource )
625 *aSource = constraint.GetName();
626
627 return constraint.Value().Min();
628 }
629
630 return 0;
631}
632
633
635{
636 if( m_padStack.Drill().size.x > 0 ) // Use the specific value.
637 return m_padStack.Drill().size.x;
638
639 // Use the default value from the Netclass
640 NETCLASS* netclass = GetEffectiveNetClass();
641
642 if( GetViaType() == VIATYPE::MICROVIA )
643 return netclass->GetuViaDrill();
644
645 return netclass->GetViaDrill();
646}
647
648
649EDA_ITEM_FLAGS PCB_TRACK::IsPointOnEnds( const VECTOR2I& point, int min_dist ) const
650{
651 EDA_ITEM_FLAGS result = 0;
652
653 if( min_dist < 0 )
654 min_dist = m_width / 2;
655
656 if( min_dist == 0 )
657 {
658 if( m_Start == point )
659 result |= STARTPOINT;
660
661 if( m_End == point )
662 result |= ENDPOINT;
663 }
664 else
665 {
666 double dist = m_Start.Distance( point );
667
668 if( min_dist >= dist )
669 result |= STARTPOINT;
670
671 dist = m_End.Distance( point );
672
673 if( min_dist >= dist )
674 result |= ENDPOINT;
675 }
676
677 return result;
678}
679
680
682{
683 // end of track is round, this is its radius, rounded up
684 int radius = ( m_width + 1 ) / 2;
685 int ymax, xmax, ymin, xmin;
686
687 if( Type() == PCB_VIA_T )
688 {
689 ymax = m_Start.y;
690 xmax = m_Start.x;
691
692 ymin = m_Start.y;
693 xmin = m_Start.x;
694 }
695 else if( Type() == PCB_ARC_T )
696 {
697 std::shared_ptr<SHAPE> arc = GetEffectiveShape();
698 BOX2I bbox = arc->BBox();
699
700 xmin = bbox.GetLeft();
701 xmax = bbox.GetRight();
702 ymin = bbox.GetTop();
703 ymax = bbox.GetBottom();
704 }
705 else
706 {
707 ymax = std::max( m_Start.y, m_End.y );
708 xmax = std::max( m_Start.x, m_End.x );
709
710 ymin = std::min( m_Start.y, m_End.y );
711 xmin = std::min( m_Start.x, m_End.x );
712 }
713
714 ymax += radius;
715 xmax += radius;
716
717 ymin -= radius;
718 xmin -= radius;
719
720 // return a rectangle which is [pos,dim) in nature. therefore the +1
721 return BOX2ISafe( VECTOR2I( xmin, ymin ),
722 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
723}
724
725
727{
728 int radius = 0;
729
731 [&]( PCB_LAYER_ID aLayer )
732 {
733 radius = std::max( radius, GetWidth( aLayer ) );
734 } );
735
736 // via is round, this is its radius, rounded up
737 radius = ( radius + 1 ) / 2;
738
739 int ymax = m_Start.y + radius;
740 int xmax = m_Start.x + radius;
741
742 int ymin = m_Start.y - radius;
743 int xmin = m_Start.x - radius;
744
745 // return a rectangle which is [pos,dim) in nature. therefore the +1
746 return BOX2ISafe( VECTOR2I( xmin, ymin ),
747 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
748}
749
750
752{
753 int radius = GetWidth( aLayer );
754
755 // via is round, this is its radius, rounded up
756 radius = ( radius + 1 ) / 2;
757
758 int ymax = m_Start.y + radius;
759 int xmax = m_Start.x + radius;
760
761 int ymin = m_Start.y - radius;
762 int xmin = m_Start.x - radius;
763
764 // return a rectangle which is [pos,dim) in nature. therefore the +1
765 return BOX2ISafe( VECTOR2I( xmin, ymin ),
766 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
767}
768
769
771{
772 return m_Start.Distance( m_End );
773}
774
775
777{
778 const BOARD* board = GetBoard();
779
780 if( !board )
781 return 0.0;
782
783 const LENGTH_DELAY_CALCULATION* calc = board->GetLengthCalculation();
784 const LENGTH_DELAY_CALCULATION_ITEM calcItem = calc->GetLengthCalculationItem( this );
785 std::vector<LENGTH_DELAY_CALCULATION_ITEM> items{ calcItem };
786 constexpr PATH_OPTIMISATIONS opts = {
787 .OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = false
788 };
789
790 return calc->CalculateDelay( items, opts );
791}
792
793
794void PCB_TRACK::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
795{
796 RotatePoint( m_Start, aRotCentre, aAngle );
797 RotatePoint( m_End, aRotCentre, aAngle );
798}
799
800
801void PCB_ARC::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
802{
803 RotatePoint( m_Start, aRotCentre, aAngle );
804 RotatePoint( m_End, aRotCentre, aAngle );
805 RotatePoint( m_Mid, aRotCentre, aAngle );
806}
807
808
809void PCB_TRACK::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
810{
811 MIRROR( m_Start, aCentre, aFlipDirection );
812 MIRROR( m_End, aCentre, aFlipDirection );
813}
814
815
816void PCB_ARC::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
817{
818 MIRROR( m_Start, aCentre, aFlipDirection );
819 MIRROR( m_End, aCentre, aFlipDirection );
820 MIRROR( m_Mid, aCentre, aFlipDirection );
821}
822
823
824void PCB_TRACK::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
825{
826 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
827 {
828 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
829 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
830 }
831 else
832 {
833 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
834 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
835 }
836
838}
839
840
841void PCB_ARC::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
842{
843 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
844 {
845 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
846 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
847 m_Mid.x = aCentre.x - ( m_Mid.x - aCentre.x );
848 }
849 else
850 {
851 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
852 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
853 m_Mid.y = aCentre.y - ( m_Mid.y - aCentre.y );
854 }
855
857}
858
859
860bool PCB_ARC::IsCCW() const
861{
862 VECTOR2L start = m_Start;
863 VECTOR2L start_end = m_End - start;
864 VECTOR2L start_mid = m_Mid - start;
865
866 return start_end.Cross( start_mid ) < 0;
867}
868
869
870void PCB_VIA::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
871{
872 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
873 {
874 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
875 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
876 }
877 else
878 {
879 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
880 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
881 }
882
883 if( GetViaType() != VIATYPE::THROUGH )
884 {
885 PCB_LAYER_ID top_layer;
886 PCB_LAYER_ID bottom_layer;
887 LayerPair( &top_layer, &bottom_layer );
888 top_layer = GetBoard()->FlipLayer( top_layer );
889 bottom_layer = GetBoard()->FlipLayer( bottom_layer );
890 SetLayerPair( top_layer, bottom_layer );
891 }
892}
893
894
895INSPECT_RESULT PCB_TRACK::Visit( INSPECTOR inspector, void* testData,
896 const std::vector<KICAD_T>& aScanTypes )
897{
898 for( KICAD_T scanType : aScanTypes )
899 {
900 if( scanType == Type() )
901 {
902 if( INSPECT_RESULT::QUIT == inspector( this, testData ) )
903 return INSPECT_RESULT::QUIT;
904 }
905 }
906
907 return INSPECT_RESULT::CONTINUE;
908}
909
910
911std::shared_ptr<SHAPE_SEGMENT> PCB_VIA::GetEffectiveHoleShape() const
912{
913 return std::make_shared<SHAPE_SEGMENT>( SEG( m_Start, m_Start ), Padstack().Drill().size.x );
914}
915
916// clang-format off: the suggestion is slightly less readable
918{
919 switch( aMode )
920 {
921 case TENTING_MODE::FROM_RULES: m_padStack.FrontOuterLayers().has_solder_mask.reset(); break;
922 case TENTING_MODE::TENTED: m_padStack.FrontOuterLayers().has_solder_mask = true; break;
923 case TENTING_MODE::NOT_TENTED: m_padStack.FrontOuterLayers().has_solder_mask = false; break;
924 }
925}
926
927
929{
931 {
933 TENTING_MODE::TENTED : TENTING_MODE::NOT_TENTED;
934 }
935
936 return TENTING_MODE::FROM_RULES;
937}
938
939
941{
942 switch( aMode )
943 {
944 case TENTING_MODE::FROM_RULES: m_padStack.BackOuterLayers().has_solder_mask.reset(); break;
945 case TENTING_MODE::TENTED: m_padStack.BackOuterLayers().has_solder_mask = true; break;
946 case TENTING_MODE::NOT_TENTED: m_padStack.BackOuterLayers().has_solder_mask = false; break;
947 }
948}
949
950
952{
953 if( m_padStack.BackOuterLayers().has_solder_mask.has_value() )
954 {
956 TENTING_MODE::TENTED : TENTING_MODE::NOT_TENTED;
957 }
958
959 return TENTING_MODE::FROM_RULES;
960}
961
962
964{
965 switch( aMode )
966 {
967 case COVERING_MODE::FROM_RULES: m_padStack.FrontOuterLayers().has_covering.reset(); break;
968 case COVERING_MODE::COVERED: m_padStack.FrontOuterLayers().has_covering = true; break;
969 case COVERING_MODE::NOT_COVERED: m_padStack.FrontOuterLayers().has_covering = false; break;
970 }
971}
972
973
975{
976 if( m_padStack.FrontOuterLayers().has_covering.has_value() )
977 {
979 COVERING_MODE::COVERED : COVERING_MODE::NOT_COVERED;
980 }
981
982 return COVERING_MODE::FROM_RULES;
983}
984
985
987{
988 switch( aMode )
989 {
990 case COVERING_MODE::FROM_RULES: m_padStack.BackOuterLayers().has_covering.reset(); break;
991 case COVERING_MODE::COVERED: m_padStack.BackOuterLayers().has_covering = true; break;
992 case COVERING_MODE::NOT_COVERED: m_padStack.BackOuterLayers().has_covering = false; break;
993 }
994}
995
996
998{
999 if( m_padStack.BackOuterLayers().has_covering.has_value() )
1000 {
1002 COVERING_MODE::COVERED : COVERING_MODE::NOT_COVERED;
1003 }
1004
1005 return COVERING_MODE::FROM_RULES;
1006}
1007
1008
1010{
1011 switch( aMode )
1012 {
1013 case PLUGGING_MODE::FROM_RULES: m_padStack.FrontOuterLayers().has_plugging.reset(); break;
1014 case PLUGGING_MODE::PLUGGED: m_padStack.FrontOuterLayers().has_plugging = true; break;
1015 case PLUGGING_MODE::NOT_PLUGGED: m_padStack.FrontOuterLayers().has_plugging = false; break;
1016 }
1017}
1018
1019
1021{
1022 if( m_padStack.FrontOuterLayers().has_plugging.has_value() )
1023 {
1025 PLUGGING_MODE::PLUGGED : PLUGGING_MODE::NOT_PLUGGED;
1026 }
1027
1028 return PLUGGING_MODE::FROM_RULES;
1029}
1030
1031
1033{
1034 switch( aMode )
1035 {
1036 case PLUGGING_MODE::FROM_RULES: m_padStack.BackOuterLayers().has_plugging.reset(); break;
1037 case PLUGGING_MODE::PLUGGED: m_padStack.BackOuterLayers().has_plugging = true; break;
1038 case PLUGGING_MODE::NOT_PLUGGED: m_padStack.BackOuterLayers().has_plugging = false; break;
1039 }
1040}
1041
1042
1044{
1045 if( m_padStack.BackOuterLayers().has_plugging.has_value() )
1046 {
1048 PLUGGING_MODE::PLUGGED : PLUGGING_MODE::NOT_PLUGGED;
1049 }
1050
1051 return PLUGGING_MODE::FROM_RULES;
1052}
1053
1054
1056{
1057 switch( aMode )
1058 {
1059 case CAPPING_MODE::FROM_RULES: m_padStack.Drill().is_capped.reset(); break;
1060 case CAPPING_MODE::CAPPED: m_padStack.Drill().is_capped = true; break;
1061 case CAPPING_MODE::NOT_CAPPED: m_padStack.Drill().is_capped = false; break;
1062 }
1063}
1064
1065
1067{
1068 if( m_padStack.Drill().is_capped.has_value() )
1069 {
1070 return *m_padStack.Drill().is_capped ?
1071 CAPPING_MODE::CAPPED : CAPPING_MODE::NOT_CAPPED;
1072 }
1073
1074 return CAPPING_MODE::FROM_RULES;
1075}
1076
1077
1079{
1080 switch( aMode )
1081 {
1082 case FILLING_MODE::FROM_RULES: m_padStack.Drill().is_filled.reset(); break;
1083 case FILLING_MODE::FILLED: m_padStack.Drill().is_filled = true; break;
1084 case FILLING_MODE::NOT_FILLED: m_padStack.Drill().is_filled = false; break;
1085 }
1086}
1087
1088
1090{
1091 if( m_padStack.Drill().is_filled.has_value() )
1092 {
1093 return *m_padStack.Drill().is_filled ?
1094 FILLING_MODE::FILLED : FILLING_MODE::NOT_FILLED;
1095 }
1096
1097 return FILLING_MODE::FROM_RULES;
1098}
1099// clang-format on: the suggestion is slightly less readable
1100
1101
1103{
1104 wxCHECK_MSG( IsFrontLayer( aLayer ) || IsBackLayer( aLayer ), true,
1105 "Invalid layer passed to IsTented" );
1106
1107 bool front = IsFrontLayer( aLayer );
1108
1109 if( front && m_padStack.FrontOuterLayers().has_solder_mask.has_value() )
1111
1112 if( !front && m_padStack.BackOuterLayers().has_solder_mask.has_value() )
1114
1115 if( const BOARD* board = GetBoard() )
1116 {
1117 return front ? board->GetDesignSettings().m_TentViasFront
1118 : board->GetDesignSettings().m_TentViasBack;
1119 }
1120
1121 return true;
1122}
1123
1124
1126{
1127 if( const BOARD* board = GetBoard() )
1128 return board->GetDesignSettings().m_SolderMaskExpansion;
1129 else
1130 return 0;
1131}
1132
1133
1135{
1136 int margin = m_solderMaskMargin.value_or( 0 );
1137
1138 // If no local margin is set, get the board's solder mask expansion value
1139 if( !m_solderMaskMargin.has_value() )
1140 {
1141 const BOARD* board = GetBoard();
1142
1143 if( board )
1144 margin = board->GetDesignSettings().m_SolderMaskExpansion;
1145 }
1146
1147 // Ensure the resulting mask opening has a non-negative size
1148 if( margin < 0 )
1149 margin = std::max( margin, -m_width / 2 );
1150
1151 return margin;
1152}
1153
1154
1156{
1157 if( aLayer == m_layer )
1158 {
1159 return true;
1160 }
1161
1162 if( m_hasSolderMask
1163 && ( ( 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
1340 Padstack().Drill().start = aTopLayer;
1341 Padstack().Drill().end = aBottomLayer;
1343}
1344
1345
1347{
1348 Padstack().Drill().start = aLayer;
1349}
1350
1351
1353{
1354 Padstack().Drill().end = aLayer;
1355}
1356
1357
1358void PCB_VIA::LayerPair( PCB_LAYER_ID* top_layer, PCB_LAYER_ID* bottom_layer ) const
1359{
1360 PCB_LAYER_ID t_layer = F_Cu;
1361 PCB_LAYER_ID b_layer = B_Cu;
1362
1363 if( GetViaType() != VIATYPE::THROUGH )
1364 {
1365 b_layer = Padstack().Drill().end;
1366 t_layer = Padstack().Drill().start;
1367
1368 if( !IsCopperLayerLowerThan( b_layer, t_layer ) )
1369 std::swap( b_layer, t_layer );
1370 }
1371
1372 if( top_layer )
1373 *top_layer = t_layer;
1374
1375 if( bottom_layer )
1376 *bottom_layer = b_layer;
1377}
1378
1379
1381{
1382 return Padstack().Drill().start;
1383}
1384
1385
1387{
1388 return Padstack().Drill().end;
1389}
1390
1391
1393{
1394 if( GetViaType() == VIATYPE::THROUGH )
1395 {
1396 Padstack().Drill().start = F_Cu;
1397 Padstack().Drill().end = B_Cu;
1398 }
1399
1400 if( !IsCopperLayerLowerThan( Padstack().Drill().end, Padstack().Drill().start) )
1401 std::swap( Padstack().Drill().end, Padstack().Drill().start );
1402}
1403
1404
1405bool PCB_VIA::FlashLayer( const LSET& aLayers ) const
1406{
1407 for( PCB_LAYER_ID layer : aLayers )
1408 {
1409 if( FlashLayer( layer ) )
1410 return true;
1411 }
1412
1413 return false;
1414}
1415
1416
1417bool PCB_VIA::FlashLayer( int aLayer ) const
1418{
1419 // Return the "normal" shape if the caller doesn't specify a particular layer
1420 if( aLayer == UNDEFINED_LAYER )
1421 return true;
1422
1423 const BOARD* board = GetBoard();
1424 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aLayer );
1425
1426 if( !board )
1427 return true;
1428
1429 if( !IsOnLayer( layer ) )
1430 return false;
1431
1432 if( !IsCopperLayer( layer ) )
1433 return true;
1434
1435 switch( Padstack().UnconnectedLayerMode() )
1436 {
1438 return true;
1439
1441 {
1442 if( layer == Padstack().Drill().start || layer == Padstack().Drill().end )
1443 return true;
1444
1445 // Check for removal below
1446 break;
1447 }
1448
1450 // Check for removal below
1451 break;
1452 }
1453
1454 if( GetZoneLayerOverride( layer ) == ZLO_FORCE_FLASHED )
1455 {
1456 return true;
1457 }
1458 else
1459 {
1460 // Must be static to keep from raising its ugly head in performance profiles
1461 static std::initializer_list<KICAD_T> nonZoneTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
1462 PCB_PAD_T };
1463
1464 return board->GetConnectivity()->IsConnectedOnLayer( this, layer, nonZoneTypes );
1465 }
1466}
1467
1468
1470{
1471 std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
1472
1475}
1476
1477
1479{
1480 static const ZONE_LAYER_OVERRIDE defaultOverride = ZLO_NONE;
1481 auto it = m_zoneLayerOverrides.find( aLayer );
1482 return it != m_zoneLayerOverrides.end() ? it->second : defaultOverride;
1483}
1484
1485
1487{
1488 std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
1489 m_zoneLayerOverrides[aLayer] = aOverride;
1490}
1491
1492
1494 PCB_LAYER_ID* aBottommost ) const
1495{
1496 *aTopmost = UNDEFINED_LAYER;
1497 *aBottommost = UNDEFINED_LAYER;
1498
1499 static std::initializer_list<KICAD_T> nonZoneTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
1500 PCB_PAD_T };
1501
1502 for( int layer = TopLayer(); layer <= BottomLayer(); ++layer )
1503 {
1504 bool connected = false;
1505
1506 if( GetZoneLayerOverride( static_cast<PCB_LAYER_ID>( layer ) ) == ZLO_FORCE_FLASHED )
1507 {
1508 connected = true;
1509 }
1510 else if( GetBoard()->GetConnectivity()->IsConnectedOnLayer( this, layer, nonZoneTypes ) )
1511 {
1512 connected = true;
1513 }
1514
1515 if( connected )
1516 {
1517 if( *aTopmost == UNDEFINED_LAYER )
1518 *aTopmost = ToLAYER_ID( layer );
1519
1520 *aBottommost = ToLAYER_ID( layer );
1521 }
1522 }
1523
1524}
1525
1526
1527std::vector<int> PCB_TRACK::ViewGetLayers() const
1528{
1529 // Show the track and its netname on different layers
1530 const PCB_LAYER_ID layer = GetLayer();
1531 std::vector<int> layers{
1532 layer,
1533 GetNetnameLayer( layer ),
1534 LAYER_CLEARANCE_START + layer,
1535 };
1536
1537 layers.reserve( 6 );
1538
1539 if( m_hasSolderMask )
1540 {
1541 if( m_layer == F_Cu )
1542 layers.push_back( F_Mask );
1543 else if( m_layer == B_Cu )
1544 layers.push_back( B_Mask );
1545 }
1546
1547 if( IsLocked() )
1548 layers.push_back( LAYER_LOCKED_ITEM_SHADOW );
1549
1550 return layers;
1551}
1552
1553
1554double PCB_TRACK::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
1555{
1556 PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
1557 PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
1558
1559 if( !aView->IsLayerVisible( LAYER_TRACKS ) )
1560 return LOD_HIDE;
1561
1562 if( IsNetnameLayer( aLayer ) )
1563 {
1565 return LOD_HIDE;
1566
1567 // Hide netnames on dimmed tracks
1568 if( renderSettings->GetHighContrast() )
1569 {
1570 if( m_layer != renderSettings->GetPrimaryHighContrastLayer() )
1571 return LOD_HIDE;
1572 }
1573
1574 VECTOR2I start( GetStart() );
1575 VECTOR2I end( GetEnd() );
1576
1577 // Calc the approximate size of the netname (assume square chars)
1578 SEG::ecoord nameSize = GetDisplayNetname().size() * GetWidth();
1579
1580 if( VECTOR2I( end - start ).SquaredEuclideanNorm() < nameSize * nameSize )
1581 return LOD_HIDE;
1582
1583 BOX2I clipBox = BOX2ISafe( aView->GetViewport() );
1584
1585 ClipLine( &clipBox, start.x, start.y, end.x, end.y );
1586
1587 if( VECTOR2I( end - start ).SquaredEuclideanNorm() == 0 )
1588 return LOD_HIDE;
1589
1590 // Netnames will be shown only if zoom is appropriate
1591 return lodScaleForThreshold( aView, m_width, pcbIUScale.mmToIU( 4.0 ) );
1592 }
1593
1594 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
1595 {
1596 // Hide shadow if the main layer is not shown
1597 if( !aView->IsLayerVisible( m_layer ) )
1598 return LOD_HIDE;
1599
1600 // Hide shadow on dimmed tracks
1601 if( renderSettings->GetHighContrast() )
1602 {
1603 if( m_layer != renderSettings->GetPrimaryHighContrastLayer() )
1604 return LOD_HIDE;
1605 }
1606 }
1607
1608 // Other layers are shown without any conditions
1609 return LOD_SHOW;
1610}
1611
1612
1614{
1615 BOX2I bbox = GetBoundingBox();
1616
1617 if( const BOARD* board = GetBoard() )
1618 bbox.Inflate( 2 * board->GetDesignSettings().GetBiggestClearanceValue() );
1619 else
1620 bbox.Inflate( GetWidth() ); // Add a bit extra for safety
1621
1622 return bbox;
1623}
1624
1625
1626std::vector<int> PCB_VIA::ViewGetLayers() const
1627{
1628 LAYER_RANGE layers( Padstack().Drill().start, Padstack().Drill().end, MAX_CU_LAYERS );
1629 std::vector<int> ret_layers{ LAYER_VIA_HOLES, LAYER_VIA_HOLEWALLS, LAYER_VIA_NETNAMES };
1630 ret_layers.reserve( MAX_CU_LAYERS + 6 );
1631
1632 // TODO(JE) Rendering order issue
1633#if 0
1634 // Blind/buried vias (and microvias) use a different net name layer
1635 PCB_LAYER_ID layerTop, layerBottom;
1636 LayerPair( &layerTop, &layerBottom );
1637
1638 bool isBlindBuried =
1639 m_viaType == VIATYPE::BLIND_BURIED
1640 || ( m_viaType == VIATYPE::MICROVIA && ( layerTop != F_Cu || layerBottom != B_Cu ) );
1641#endif
1642 LSET cuMask = LSET::AllCuMask();
1643
1644 if( const BOARD* board = GetBoard() )
1645 cuMask = board->GetEnabledLayers();
1646
1647 for( PCB_LAYER_ID layer : layers )
1648 {
1649 if( !cuMask.Contains( layer ) )
1650 continue;
1651
1652 ret_layers.push_back( LAYER_VIA_COPPER_START + layer );
1653 ret_layers.push_back( LAYER_CLEARANCE_START + layer );
1654 }
1655
1656 if( IsLocked() )
1657 ret_layers.push_back( LAYER_LOCKED_ITEM_SHADOW );
1658
1659 // Vias can also be on a solder mask layer. They are on these layers or not,
1660 // depending on the plot and solder mask options
1661 if( IsOnLayer( F_Mask ) )
1662 ret_layers.push_back( F_Mask );
1663
1664 if( IsOnLayer( B_Mask ) )
1665 ret_layers.push_back( B_Mask );
1666
1667 return ret_layers;
1668}
1669
1670
1671double PCB_VIA::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
1672{
1673 PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
1674 PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
1675 LSET visible = LSET::AllLayersMask();
1676
1677 // Meta control for hiding all vias
1678 if( !aView->IsLayerVisible( LAYER_VIAS ) )
1679 return LOD_HIDE;
1680
1681 // Handle board visibility
1682 if( const BOARD* board = GetBoard() )
1683 visible = board->GetVisibleLayers() & board->GetEnabledLayers();
1684
1685 int width = GetWidth( ToLAYER_ID( aLayer ) );
1686
1687 // In high contrast mode don't show vias that don't cross the high-contrast layer
1688 if( renderSettings->GetHighContrast() )
1689 {
1690 PCB_LAYER_ID highContrastLayer = renderSettings->GetPrimaryHighContrastLayer();
1691
1692 if( LSET::FrontTechMask().Contains( highContrastLayer ) )
1693 highContrastLayer = F_Cu;
1694 else if( LSET::BackTechMask().Contains( highContrastLayer ) )
1695 highContrastLayer = B_Cu;
1696
1697 if( IsCopperLayer( highContrastLayer ) && GetViaType() != VIATYPE::THROUGH )
1698 {
1699 if( IsCopperLayerLowerThan( Padstack().Drill().start, highContrastLayer )
1700 || IsCopperLayerLowerThan( highContrastLayer, Padstack().Drill().end ) )
1701 {
1702 return LOD_HIDE;
1703 }
1704 }
1705 }
1706
1707 if( IsHoleLayer( aLayer ) )
1708 {
1709 if( m_viaType == VIATYPE::THROUGH )
1710 {
1711 // Show a through via's hole if any physical layer is shown
1712 if( !( visible & LSET::PhysicalLayersMask() ).any() )
1713 return LOD_HIDE;
1714 }
1715 else
1716 {
1717 // Show a blind or micro via's hole if it crosses a visible layer
1718 if( !( visible & GetLayerSet() ).any() )
1719 return LOD_HIDE;
1720 }
1721
1722 // The hole won't be visible anyway at this scale
1723 return lodScaleForThreshold( aView, GetDrillValue(), pcbIUScale.mmToIU( 0.25 ) );
1724 }
1725 else if( IsNetnameLayer( aLayer ) )
1726 {
1727 if( renderSettings->GetHighContrast() )
1728 {
1729 // Hide netnames unless via is flashed to a high-contrast layer
1730 if( !FlashLayer( renderSettings->GetPrimaryHighContrastLayer() ) )
1731 return LOD_HIDE;
1732 }
1733 else
1734 {
1735 // Hide netnames unless pad is flashed to a visible layer
1736 if( !FlashLayer( visible ) )
1737 return LOD_HIDE;
1738 }
1739
1740 // Netnames will be shown only if zoom is appropriate
1741 return lodScaleForThreshold( aView, width, pcbIUScale.mmToIU( 10 ) );
1742 }
1743
1744 if( !IsCopperLayer( aLayer ) )
1745 return lodScaleForThreshold( aView, width, pcbIUScale.mmToIU( 0.6 ) );
1746
1747 return LOD_SHOW;
1748}
1749
1750
1752{
1753 switch( Type() )
1754 {
1755 case PCB_ARC_T: return _( "Track (arc)" );
1756 case PCB_VIA_T: return _( "Via" );
1757 case PCB_TRACE_T:
1758 default: return _( "Track" );
1759 }
1760}
1761
1762
1763void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1764{
1765 wxString msg;
1766 BOARD* board = GetBoard();
1767
1768 aList.emplace_back( _( "Type" ), GetFriendlyName() );
1769
1770 GetMsgPanelInfoBase_Common( aFrame, aList );
1771
1772 aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
1773
1774 aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( m_width ) );
1775
1776 if( Type() == PCB_ARC_T )
1777 {
1778 double radius = static_cast<PCB_ARC*>( this )->GetRadius();
1779 aList.emplace_back( _( "Radius" ), aFrame->MessageTextFromValue( radius ) );
1780 }
1781
1782 double segmentLength = GetLength();
1783 double segmentDelay = GetDelay();
1784
1785 if( segmentDelay == 0.0 )
1786 {
1787 aList.emplace_back( _( "Segment Length" ), aFrame->MessageTextFromValue( segmentLength ) );
1788 }
1789 else
1790 {
1791 aList.emplace_back( _( "Segment Delay" ),
1792 aFrame->MessageTextFromValue( segmentDelay, true, EDA_DATA_TYPE::TIME ) );
1793 }
1794
1795 // Display full track length (in Pcbnew)
1796 if( board && GetNetCode() > 0 )
1797 {
1798 int count = 0;
1799 double trackLen = 0.0;
1800 double lenPadToDie = 0.0;
1801 double trackDelay = 0.0;
1802 double delayPadToDie = 0.0;
1803
1804 std::tie( count, trackLen, lenPadToDie, trackDelay, delayPadToDie ) = board->GetTrackLength( *this );
1805
1806 if( trackDelay == 0.0 )
1807 {
1808 aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
1809
1810 if( lenPadToDie != 0 )
1811 {
1812 msg = aFrame->MessageTextFromValue( lenPadToDie );
1813 aList.emplace_back( _( "Pad To Die Length" ), msg );
1814
1815 msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
1816 aList.emplace_back( _( "Full Length" ), msg );
1817 }
1818 }
1819 else
1820 {
1821 aList.emplace_back( _( "Routed Delay" ),
1822 aFrame->MessageTextFromValue( trackDelay, true, EDA_DATA_TYPE::TIME ) );
1823
1824 if( delayPadToDie != 0.0 )
1825 {
1826 msg = aFrame->MessageTextFromValue( delayPadToDie, true, EDA_DATA_TYPE::TIME );
1827 aList.emplace_back( _( "Pad To Die Delay" ), msg );
1828
1829 msg = aFrame->MessageTextFromValue( trackDelay + delayPadToDie, true, EDA_DATA_TYPE::TIME );
1830 aList.emplace_back( _( "Full Delay" ), msg );
1831 }
1832 }
1833 }
1834
1835 SHAPE_POLY_SET copper;
1837 aList.emplace_back( _( "Copper Area" ),
1838 aFrame->MessageTextFromValue( copper.Area(), true, EDA_DATA_TYPE::AREA ) );
1839
1840 wxString source;
1841 int clearance = GetOwnClearance( GetLayer(), &source );
1842
1843 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
1844 aFrame->MessageTextFromValue( clearance ) ),
1845 wxString::Format( _( "(from %s)" ), source ) );
1846
1847 MINOPTMAX<int> constraintValue = GetWidthConstraint( &source );
1848 msg = aFrame->MessageTextFromMinOptMax( constraintValue );
1849
1850 if( !msg.IsEmpty() )
1851 {
1852 aList.emplace_back( wxString::Format( _( "Width Constraints: %s" ), msg ),
1853 wxString::Format( _( "(from %s)" ), source ) );
1854 }
1855}
1856
1857
1858void PCB_VIA::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1859{
1860 wxString msg;
1861
1862 switch( GetViaType() )
1863 {
1864 case VIATYPE::MICROVIA: msg = _( "Micro Via" ); break;
1865 case VIATYPE::BLIND_BURIED: msg = _( "Blind/Buried Via" ); break;
1866 case VIATYPE::THROUGH: msg = _( "Through Via" ); break;
1867 default: msg = _( "Via" ); break;
1868 }
1869
1870 aList.emplace_back( _( "Type" ), msg );
1871
1872 GetMsgPanelInfoBase_Common( aFrame, aList );
1873
1874 aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
1875 // TODO(JE) padstacks
1876 aList.emplace_back( _( "Diameter" ),
1878 aList.emplace_back( _( "Hole" ), aFrame->MessageTextFromValue( GetDrillValue() ) );
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 int minAnnulus = GetMinAnnulus( GetLayer(), &source );
1888
1889 aList.emplace_back( wxString::Format( _( "Min Annular Width: %s" ),
1890 aFrame->MessageTextFromValue( minAnnulus ) ),
1891 wxString::Format( _( "(from %s)" ), source ) );
1892}
1893
1894
1896 std::vector<MSG_PANEL_ITEM>& aList ) const
1897{
1898 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
1899
1900 aList.emplace_back( _( "Resolved Netclass" ),
1901 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
1902
1903#if 0 // Enable for debugging
1904 if( GetBoard() )
1905 aList.emplace_back( _( "NetCode" ), fmt::format( "{}", GetNetCode() ) );
1906
1907 aList.emplace_back( wxT( "Flags" ), fmt::format( "#08X", m_flags ) );
1908
1909 aList.emplace_back( wxT( "Start pos" ), fmt::format( "{} {}", m_Start.x, m_Start.y ) );
1910 aList.emplace_back( wxT( "End pos" ), fmt::format( "{} {}", m_End.x, m_End.y ) );
1911#endif
1912
1913 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
1914 aList.emplace_back( _( "Status" ), _( "Locked" ) );
1915}
1916
1917
1919{
1920 const BOARD* board = GetBoard();
1921 PCB_LAYER_ID top_layer;
1922 PCB_LAYER_ID bottom_layer;
1923
1924 LayerPair( &top_layer, &bottom_layer );
1925
1926 return board->GetLayerName( top_layer ) + wxT( " - " ) + board->GetLayerName( bottom_layer );
1927}
1928
1929
1930bool PCB_TRACK::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1931{
1932 return TestSegmentHit( aPosition, m_Start, m_End, aAccuracy + ( m_width / 2 ) );
1933}
1934
1935
1936bool PCB_ARC::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1937{
1938 double max_dist = aAccuracy + ( GetWidth() / 2.0 );
1939
1940 // Short-circuit common cases where the arc is connected to a track or via at an endpoint
1941 if( GetStart().Distance( aPosition ) <= max_dist || GetEnd().Distance( aPosition ) <= max_dist )
1942 {
1943 return true;
1944 }
1945
1947 VECTOR2L relpos = aPosition - center;
1948 int64_t dist = relpos.EuclideanNorm();
1949 double radius = GetRadius();
1950
1951 if( std::abs( dist - radius ) > max_dist )
1952 return false;
1953
1954 EDA_ANGLE arc_angle = GetAngle();
1955 EDA_ANGLE arc_angle_start = GetArcAngleStart(); // Always 0.0 ... 360 deg
1956 EDA_ANGLE arc_hittest( relpos );
1957
1958 // Calculate relative angle between the starting point of the arc, and the test point
1959 arc_hittest -= arc_angle_start;
1960
1961 // Normalise arc_hittest between 0 ... 360 deg
1962 arc_hittest.Normalize();
1963
1964 if( arc_angle < ANGLE_0 )
1965 return arc_hittest >= ANGLE_360 + arc_angle;
1966
1967 return arc_hittest <= arc_angle;
1968}
1969
1970
1971bool PCB_VIA::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1972{
1973 bool hit = false;
1974
1976 [&]( PCB_LAYER_ID aLayer )
1977 {
1978 if( hit )
1979 return;
1980
1981 int max_dist = aAccuracy + ( GetWidth( aLayer ) / 2 );
1982
1983 // rel_pos is aPosition relative to m_Start (or the center of the via)
1984 VECTOR2D rel_pos = aPosition - m_Start;
1985 double dist = rel_pos.x * rel_pos.x + rel_pos.y * rel_pos.y;
1986
1987 if( dist <= static_cast<double>( max_dist ) * max_dist )
1988 hit = true;
1989 } );
1990
1991 return hit;
1992}
1993
1994
1995bool PCB_TRACK::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1996{
1997 BOX2I arect = aRect;
1998 arect.Inflate( aAccuracy );
1999
2000 if( aContained )
2001 return arect.Contains( GetStart() ) && arect.Contains( GetEnd() );
2002 else
2003 return arect.Intersects( GetStart(), GetEnd() );
2004}
2005
2006
2007bool PCB_ARC::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2008{
2009 BOX2I arect = aRect;
2010 arect.Inflate( aAccuracy );
2011
2012 BOX2I box( GetStart() );
2013 box.Merge( GetMid() );
2014 box.Merge( GetEnd() );
2015
2016 box.Inflate( GetWidth() / 2 );
2017
2018 if( aContained )
2019 return arect.Contains( box );
2020 else
2021 return arect.Intersects( box );
2022}
2023
2024
2025bool PCB_VIA::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2026{
2027 BOX2I arect = aRect;
2028 arect.Inflate( aAccuracy );
2029
2030 bool hit = false;
2031
2033 [&]( PCB_LAYER_ID aLayer )
2034 {
2035 if( hit )
2036 return;
2037
2038 BOX2I box( GetStart() );
2039 box.Inflate( GetWidth( aLayer ) / 2 );
2040
2041 if( aContained )
2042 hit = arect.Contains( box );
2043 else
2044 hit = arect.IntersectsCircle( GetStart(), GetWidth( aLayer ) / 2 );
2045 } );
2046
2047 return hit;
2048}
2049
2050
2051wxString PCB_TRACK::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2052{
2053 return wxString::Format( Type() == PCB_ARC_T ? _("Track (arc) %s on %s, length %s" )
2054 : _("Track %s on %s, length %s" ),
2055 GetNetnameMsg(),
2056 GetLayerName(),
2057 aUnitsProvider->MessageTextFromValue( GetLength() ) );
2058}
2059
2060
2062{
2063 return BITMAPS::add_tracks;
2064}
2065
2067{
2068 assert( aImage->Type() == PCB_TRACE_T );
2069
2070 std::swap( *((PCB_TRACK*) this), *((PCB_TRACK*) aImage) );
2071}
2072
2074{
2075 assert( aImage->Type() == PCB_ARC_T );
2076
2077 std::swap( *this, *static_cast<PCB_ARC*>( aImage ) );
2078}
2079
2081{
2082 assert( aImage->Type() == PCB_VIA_T );
2083
2084 std::swap( *((PCB_VIA*) this), *((PCB_VIA*) aImage) );
2085}
2086
2087
2089{
2091 return center;
2092}
2093
2094
2096{
2097 auto center = CalcArcCenter( m_Start, m_Mid , m_End );
2098 return center.Distance( m_Start );
2099}
2100
2101
2103{
2105 EDA_ANGLE angle1 = EDA_ANGLE( m_Mid - center ) - EDA_ANGLE( m_Start - center );
2106 EDA_ANGLE angle2 = EDA_ANGLE( m_End - center ) - EDA_ANGLE( m_Mid - center );
2107
2108 return angle1.Normalize180() + angle2.Normalize180();
2109}
2110
2111
2113{
2114 VECTOR2D pos( GetPosition() );
2115 EDA_ANGLE angleStart( m_Start - pos );
2116
2117 return angleStart.Normalize();
2118}
2119
2120
2121// Note: used in python tests. Ignore CLion's claim that it's unused....
2123{
2124 VECTOR2D pos( GetPosition() );
2125 EDA_ANGLE angleEnd( m_End - pos );
2126
2127 return angleEnd.Normalize();
2128}
2129
2130bool PCB_ARC::IsDegenerated( int aThreshold ) const
2131{
2132 // Too small arcs cannot be really handled: arc center (and arc radius)
2133 // cannot be safely computed if the distance between mid and end points
2134 // is too small (a few internal units)
2135
2136 // len of both segments must be < aThreshold to be a very small degenerated arc
2137 return ( GetMid() - GetStart() ).EuclideanNorm() < aThreshold
2138 && ( GetMid() - GetEnd() ).EuclideanNorm() < aThreshold;
2139}
2140
2141
2143{
2144 if( a->GetNetCode() != b->GetNetCode() )
2145 return a->GetNetCode() < b->GetNetCode();
2146
2147 if( a->GetLayer() != b->GetLayer() )
2148 return a->GetLayer() < b->GetLayer();
2149
2150 if( a->Type() != b->Type() )
2151 return a->Type() < b->Type();
2152
2153 if( a->m_Uuid != b->m_Uuid )
2154 return a->m_Uuid < b->m_Uuid;
2155
2156 return a < b;
2157}
2158
2159
2160std::shared_ptr<SHAPE> PCB_TRACK::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2161{
2162 int width = m_width;
2163
2164 if( IsSolderMaskLayer( aLayer ) )
2165 width += 2 * GetSolderMaskExpansion();
2166
2167 return std::make_shared<SHAPE_SEGMENT>( m_Start, m_End, width );
2168}
2169
2170
2171std::shared_ptr<SHAPE> PCB_VIA::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2172{
2173 if( aFlash == FLASHING::ALWAYS_FLASHED
2174 || ( aFlash == FLASHING::DEFAULT && FlashLayer( aLayer ) ) )
2175 {
2176 int width = 0;
2177
2178 if( aLayer == UNDEFINED_LAYER )
2179 {
2180 Padstack().ForEachUniqueLayer(
2181 [&]( PCB_LAYER_ID layer )
2182 {
2183 width = std::max( width, GetWidth( layer ) );
2184 } );
2185
2186 width /= 2;
2187 }
2188 else
2189 {
2190 PCB_LAYER_ID cuLayer = m_padStack.EffectiveLayerFor( aLayer );
2191 width = GetWidth( cuLayer ) / 2;
2192 }
2193
2194 return std::make_shared<SHAPE_CIRCLE>( m_Start, width );
2195 }
2196 else
2197 {
2198 return std::make_shared<SHAPE_CIRCLE>( m_Start, GetDrillValue() / 2 );
2199 }
2200}
2201
2202
2203std::shared_ptr<SHAPE> PCB_ARC::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2204{
2205 int width = GetWidth();
2206
2207 if( IsSolderMaskLayer( aLayer ) )
2208 width += 2 * GetSolderMaskExpansion();
2209
2210 SHAPE_ARC arc( GetStart(), GetMid(), GetEnd(), width );
2211
2212 if( arc.IsEffectiveLine() )
2213 return std::make_shared<SHAPE_SEGMENT>( GetStart(), GetEnd(), width );
2214
2215 return std::make_shared<SHAPE_ARC>( arc );
2216}
2217
2218
2220 int aClearance, int aError, ERROR_LOC aErrorLoc,
2221 bool ignoreLineWidth ) const
2222{
2223 wxASSERT_MSG( !ignoreLineWidth, wxT( "IgnoreLineWidth has no meaning for tracks." ) );
2224
2225
2226 switch( Type() )
2227 {
2228 case PCB_VIA_T:
2229 {
2230 int radius = ( static_cast<const PCB_VIA*>( this )->GetWidth( aLayer ) / 2 ) + aClearance;
2231 TransformCircleToPolygon( aBuffer, m_Start, radius, aError, aErrorLoc );
2232 break;
2233 }
2234
2235 case PCB_ARC_T:
2236 {
2237 const PCB_ARC* arc = static_cast<const PCB_ARC*>( this );
2238 int width = m_width + ( 2 * aClearance );
2239
2240 if( IsSolderMaskLayer( aLayer ) )
2241 width += 2 * GetSolderMaskExpansion();
2242
2243 TransformArcToPolygon( aBuffer, arc->GetStart(), arc->GetMid(), arc->GetEnd(), width,
2244 aError, aErrorLoc );
2245 break;
2246 }
2247
2248 default:
2249 {
2250 int width = m_width + ( 2 * aClearance );
2251
2252 if( IsSolderMaskLayer( aLayer ) )
2253 width += 2 * GetSolderMaskExpansion();
2254
2255 TransformOvalToPolygon( aBuffer, m_Start, m_End, width, aError, aErrorLoc );
2256
2257 break;
2258 }
2259 }
2260}
2261
2262
2263static struct TRACK_VIA_DESC
2264{
2266 {
2267 // clang-format off: the suggestion is less readable
2269 .Undefined( VIATYPE::NOT_DEFINED )
2270 .Map( VIATYPE::THROUGH, _HKI( "Through" ) )
2271 .Map( VIATYPE::BLIND_BURIED, _HKI( "Blind/buried" ) )
2272 .Map( VIATYPE::MICROVIA, _HKI( "Micro" ) );
2273
2275 .Undefined( TENTING_MODE::FROM_RULES )
2276 .Map( TENTING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2277 .Map( TENTING_MODE::TENTED, _HKI( "Tented" ) )
2278 .Map( TENTING_MODE::NOT_TENTED, _HKI( "Not tented" ) );
2279
2281 .Undefined( COVERING_MODE::FROM_RULES )
2282 .Map( COVERING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2283 .Map( COVERING_MODE::COVERED, _HKI( "Covered" ) )
2284 .Map( COVERING_MODE::NOT_COVERED, _HKI( "Not covered" ) );
2285
2287 .Undefined( PLUGGING_MODE::FROM_RULES )
2288 .Map( PLUGGING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2289 .Map( PLUGGING_MODE::PLUGGED, _HKI( "Plugged" ) )
2290 .Map( PLUGGING_MODE::NOT_PLUGGED, _HKI( "Not plugged" ) );
2291
2293 .Undefined( CAPPING_MODE::FROM_RULES )
2294 .Map( CAPPING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2295 .Map( CAPPING_MODE::CAPPED, _HKI( "Capped" ) )
2296 .Map( CAPPING_MODE::NOT_CAPPED, _HKI( "Not capped" ) );
2297
2299 .Undefined( FILLING_MODE::FROM_RULES )
2300 .Map( FILLING_MODE::FROM_RULES, _HKI( "From design rules" ) )
2301 .Map( FILLING_MODE::FILLED, _HKI( "Filled" ) )
2302 .Map( FILLING_MODE::NOT_FILLED, _HKI( "Not filled" ) );
2303 // clang-format on: the suggestion is less readable
2304
2306
2307 if( layerEnum.Choices().GetCount() == 0 )
2308 {
2309 layerEnum.Undefined( UNDEFINED_LAYER );
2310
2311 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
2312 layerEnum.Map( layer, LSET::Name( layer ) );
2313 }
2314
2316
2317 // Track
2320
2321 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "Width" ),
2322 &PCB_TRACK::SetWidth, &PCB_TRACK::GetWidth, PROPERTY_DISPLAY::PT_SIZE ) );
2323 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ),
2324 new PROPERTY<PCB_TRACK, int>( _HKI( "Start X" ),
2325 &PCB_TRACK::SetStartX, &PCB_TRACK::GetStartX, PROPERTY_DISPLAY::PT_COORD,
2327 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ),
2328 new PROPERTY<PCB_TRACK, int>( _HKI( "Start Y" ),
2329 &PCB_TRACK::SetStartY, &PCB_TRACK::GetStartY, PROPERTY_DISPLAY::PT_COORD,
2331 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "End X" ),
2332 &PCB_TRACK::SetEndX, &PCB_TRACK::GetEndX, PROPERTY_DISPLAY::PT_COORD,
2334 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "End Y" ),
2335 &PCB_TRACK::SetEndY, &PCB_TRACK::GetEndY, PROPERTY_DISPLAY::PT_COORD,
2337
2338 const wxString groupTechLayers = _HKI( "Technical Layers" );
2339
2340 auto isExternalLayerTrack =
2341 []( INSPECTABLE* aItem )
2342 {
2343 if( auto track = dynamic_cast<PCB_TRACK*>( aItem ) )
2344 return track->GetLayer() == F_Cu || track->GetLayer() == B_Cu;
2345
2346 return false;
2347 };
2348
2349 propMgr.AddProperty( new PROPERTY<PCB_TRACK, bool>( _HKI( "Soldermask" ),
2351 .SetAvailableFunc( isExternalLayerTrack );
2352 propMgr.AddProperty( new PROPERTY<PCB_TRACK, std::optional<int>>( _HKI( "Soldermask Margin Override" ),
2354 PROPERTY_DISPLAY::PT_SIZE ), groupTechLayers )
2355 .SetAvailableFunc( isExternalLayerTrack );
2356
2357 // Arc
2360
2361 // Via
2364
2365 // TODO test drill, use getdrillvalue?
2366 const wxString groupVia = _HKI( "Via Properties" );
2367
2368 propMgr.Mask( TYPE_HASH( PCB_VIA ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ) );
2369
2370 // clang-format off: the suggestion is less readable
2371 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Diameter" ),
2372 &PCB_VIA::SetFrontWidth, &PCB_VIA::GetFrontWidth, PROPERTY_DISPLAY::PT_SIZE ), groupVia );
2373 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Hole" ),
2374 &PCB_VIA::SetDrill, &PCB_VIA::GetDrillValue, PROPERTY_DISPLAY::PT_SIZE ), groupVia );
2375 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Layer Top" ),
2376 &PCB_VIA::SetLayer, &PCB_VIA::GetLayer ), groupVia );
2377 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Layer Bottom" ),
2379 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, VIATYPE>( _HKI( "Via Type" ),
2381 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, TENTING_MODE>( _HKI( "Front tenting" ),
2383 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, TENTING_MODE>( _HKI( "Back tenting" ),
2385 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, COVERING_MODE>( _HKI( "Front covering" ),
2387 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, COVERING_MODE>( _HKI( "Back covering" ),
2389 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PLUGGING_MODE>( _HKI( "Front plugging" ),
2391 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PLUGGING_MODE>( _HKI( "Back plugging" ),
2393 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, CAPPING_MODE>( _HKI( "Capping" ),
2395 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, FILLING_MODE>( _HKI( "Filling" ),
2397 // clang-format on: the suggestion is less readable
2398 }
2400
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:110
constexpr int ARC_LOW_DEF
Definition: base_units.h:121
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:66
@ ZLO_NONE
Definition: board_item.h:67
@ ZLO_FORCE_FLASHED
Definition: board_item.h:68
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.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
const wxString & GetDisplayNetname() const
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
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:78
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:229
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:420
void SetLocked(bool aLocked) override
Definition: board_item.h:320
PCB_LAYER_ID m_layer
Definition: board_item.h:445
bool IsLocked() const override
Definition: board_item.cpp:76
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:48
virtual int BoardCopperLayerCount() const
Return the total number of copper layers for the board that this item resides on.
Definition: board_item.cpp:118
virtual wxString layerMaskDescribe() const
Return a string (to be shown to the user) describing a layer mask.
Definition: board_item.cpp:167
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:140
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition: board.h:1291
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:2386
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition: board.cpp:774
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:614
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:495
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:165
MINOPTMAX< int > & Value()
Definition: drc_rule.h:158
EDA_ANGLE Normalize()
Definition: eda_angle.h:224
EDA_ANGLE Normalize180()
Definition: eda_angle.h:263
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:96
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition: eda_item.cpp:303
const KIID m_Uuid
Definition: eda_item.h:501
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:108
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:512
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:687
static ENUM_MAP< T > & Instance()
Definition: property.h:681
ENUM_MAP & Undefined(T aValue)
Definition: property.h:694
wxPGChoices & Choices()
Definition: property.h:730
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:181
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:186
PCB specific render settings.
Definition: pcb_painter.h:79
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:174
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition: view_item.h:179
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:520
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:418
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:216
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
Lightweight class which holds a pad, via, or a routed trace outline.
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:255
static const LSET & BackTechMask()
Return a mask holding all technical layers (no CU layer) on back side.
Definition: lset.cpp:634
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:583
static const LSET & AllLayersMask()
Definition: lset.cpp:627
static const LSET & PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:683
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:648
T Min() const
Definition: minoptmax.h:33
bool HasMin() const
Definition: minoptmax.h:37
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:45
int GetViaDrill() const
Definition: netclass.h:138
int GetuViaDrill() const
Definition: netclass.h:154
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:124
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: padstack.cpp:211
MASK_LAYER_PROPS & FrontOuterLayers()
Definition: padstack.h:318
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:881
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition: padstack.h:313
const LSET & LayerSet() const
Definition: padstack.h:280
void SetShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
Definition: padstack.cpp:1059
UNCONNECTED_LAYER_MODE UnconnectedLayerMode() const
Definition: padstack.h:312
DRILL_PROPS & Drill()
Definition: padstack.h:306
const VECTOR2I & Size(PCB_LAYER_ID aLayer) const
Definition: padstack.cpp:1074
MASK_LAYER_PROPS & BackOuterLayers()
Definition: padstack.h:321
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: padstack.cpp:413
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
Definition: padstack.cpp:1065
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:144
virtual VECTOR2I GetPosition() const override
Definition: pcb_track.cpp:2088
bool IsDegenerated(int aThreshold=5) const
Definition: pcb_track.cpp:2130
virtual void swapData(BOARD_ITEM *aImage) override
Definition: pcb_track.cpp:2073
bool IsCCW() const
Definition: pcb_track.cpp:860
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: pcb_track.cpp:441
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_track.cpp:90
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pcb_track.cpp:841
EDA_ANGLE GetArcAngleStart() const
Definition: pcb_track.cpp:2112
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:816
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:1936
EDA_ANGLE GetArcAngleEnd() const
Definition: pcb_track.cpp:2122
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: pcb_track.cpp:464
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:343
double GetRadius() const
Definition: pcb_track.cpp:2095
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:2102
const VECTOR2I & GetMid() const
Definition: pcb_track.h:344
PCB_ARC(BOARD_ITEM *aParent)
Definition: pcb_track.h:317
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:274
VECTOR2I m_Mid
Arc mid point, halfway between start and end.
Definition: pcb_track.h:408
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_track.cpp:801
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:2203
bool operator==(const PCB_ARC &aOther) const
Definition: pcb_track.cpp:262
void CopyFrom(const BOARD_ITEM *aOther) override
Definition: pcb_track.cpp:96
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:1134
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_track.cpp:794
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: pcb_track.cpp:400
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:770
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: pcb_track.cpp:1554
virtual void swapData(BOARD_ITEM *aImage) override
Definition: pcb_track.cpp:2066
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:1613
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:2051
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:809
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: pcb_track.cpp:421
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:895
bool ApproxCollinear(const PCB_TRACK &aTrack)
Definition: pcb_track.cpp:541
VECTOR2I m_End
Line end point.
Definition: pcb_track.h:304
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: pcb_track.h:178
std::optional< int > m_solderMaskMargin
Definition: pcb_track.h:307
void CopyFrom(const BOARD_ITEM *aOther) override
Definition: pcb_track.cpp:74
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:776
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:1763
virtual EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_track.cpp:68
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_track.cpp:681
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:2219
const VECTOR2I & GetStart() const
Definition: pcb_track.h:152
virtual bool operator==(const BOARD_ITEM &aOther) const override
Definition: pcb_track.cpp:187
VECTOR2I m_Start
Line start point.
Definition: pcb_track.h:303
int GetEndY() const
Definition: pcb_track.h:164
wxString GetFriendlyName() const override
Definition: pcb_track.cpp:1751
virtual std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition: pcb_track.cpp:1527
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: pcb_track.cpp:2061
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:1930
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pcb_track.cpp:824
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:209
bool m_hasSolderMask
Definition: pcb_track.h:306
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:2160
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:60
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:1155
virtual MINOPTMAX< int > GetWidthConstraint(wxString *aSource=nullptr) const
Definition: pcb_track.cpp:549
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:310
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:649
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:1895
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:1386
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: pcb_track.cpp:181
PLUGGING_MODE GetFrontPluggingMode() const
Definition: pcb_track.cpp:1020
VECTOR2I GetPosition() const override
Definition: pcb_track.h:551
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:1102
void CopyFrom(const BOARD_ITEM *aOther) override
Definition: pcb_track.cpp:153
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:2171
void SetCappingMode(CAPPING_MODE aMode)
Definition: pcb_track.cpp:1055
void SetFrontCoveringMode(COVERING_MODE aMode)
Definition: pcb_track.cpp:963
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition: pcb_track.cpp:513
COVERING_MODE GetBackCoveringMode() const
Definition: pcb_track.cpp:997
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
Definition: pcb_track.cpp:1417
void SetDrillDefault()
Set the drill value for vias to the default value UNDEFINED_DRILL_DIAMETER.
Definition: pcb_track.h:688
std::map< PCB_LAYER_ID, ZONE_LAYER_OVERRIDE > m_zoneLayerOverrides
Definition: pcb_track.h:737
void ClearZoneLayerOverrides()
Definition: pcb_track.cpp:1469
CAPPING_MODE GetCappingMode() const
Definition: pcb_track.cpp:1066
const PADSTACK & Padstack() const
Definition: pcb_track.h:453
void SetFrontTentingMode(TENTING_MODE aMode)
Definition: pcb_track.cpp:917
bool m_isFree
"Free" vias don't get their nets auto-updated
Definition: pcb_track.h:734
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:1971
TENTING_MODE GetFrontTentingMode() const
Definition: pcb_track.cpp:928
void SetBottomLayer(PCB_LAYER_ID aLayer)
Definition: pcb_track.cpp:1352
int GetSolderMaskExpansion() const
Definition: pcb_track.cpp:1125
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:666
PLUGGING_MODE GetBackPluggingMode() const
Definition: pcb_track.cpp:1043
void SetBackPluggingMode(PLUGGING_MODE aMode)
Definition: pcb_track.cpp:1032
MINOPTMAX< int > GetDrillConstraint(wxString *aSource=nullptr) const
Definition: pcb_track.cpp:585
void SetBackTentingMode(TENTING_MODE aMode)
Definition: pcb_track.cpp:940
void SetFrontPluggingMode(PLUGGING_MODE aMode)
Definition: pcb_track.cpp:1009
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pcb_track.cpp:870
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:1858
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_track.cpp:160
bool operator==(const PCB_VIA &aOther) const
Definition: pcb_track.cpp:330
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:736
void SetTopLayer(PCB_LAYER_ID aLayer)
Definition: pcb_track.cpp:1346
FILLING_MODE GetFillingMode() const
Definition: pcb_track.cpp:1089
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Definition: pcb_track.cpp:911
int GetFrontWidth() const
Definition: pcb_track.h:468
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:166
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:341
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:1493
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:1392
int GetWidth() const override
Definition: pcb_track.cpp:380
PCB_VIA & operator=(const PCB_VIA &aOther)
Definition: pcb_track.cpp:138
void swapData(BOARD_ITEM *aImage) override
Definition: pcb_track.cpp:2080
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition: pcb_track.cpp:485
void SetFillingMode(FILLING_MODE aMode)
Definition: pcb_track.cpp:1078
PCB_VIA(BOARD_ITEM *aParent)
Definition: pcb_track.cpp:103
wxString layerMaskDescribe() const override
Return a string (to be shown to the user) describing a layer mask.
Definition: pcb_track.cpp:1918
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition: pcb_track.cpp:1626
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:451
int GetMinAnnulus(PCB_LAYER_ID aLayer, wxString *aSource) const
Definition: pcb_track.cpp:603
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:951
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:1380
VIATYPE m_viaType
through, blind/buried or micro
Definition: pcb_track.h:730
PADSTACK m_padStack
Definition: pcb_track.h:732
COVERING_MODE GetFrontCoveringMode() const
Definition: pcb_track.cpp:974
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:634
void SetZoneLayerOverride(PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride)
Definition: pcb_track.cpp:1486
void SetFrontWidth(int aWidth)
Definition: pcb_track.h:467
VIATYPE GetViaType() const
Definition: pcb_track.h:450
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: pcb_track.cpp:1671
MINOPTMAX< int > GetWidthConstraint(wxString *aSource=nullptr) const override
Definition: pcb_track.cpp:567
void SetWidth(int aWidth) override
Definition: pcb_track.cpp:372
void SetBackCoveringMode(COVERING_MODE aMode)
Definition: pcb_track.cpp:986
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:1478
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:1358
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:726
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
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:87
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:533
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 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:67
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:59
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:54
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:404
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:410
#define PCB_EDIT_FRAME_NAME
INSPECT_RESULT
Definition: eda_item.h:43
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition: eda_item.h:89
#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:169
bool IsSolderMaskLayer(int aLayer)
Definition: layer_ids.h:733
@ 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:809
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:765
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:788
#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:839
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:663
@ 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:335
@ 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:339
@ 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:854
bool IsHoleLayer(int aLayer)
Definition: layer_ids.h:724
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:747
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
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:393
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:783
#define REGISTER_TYPE(x)
Definition: property_mgr.h:371
wxString UnescapeString(const wxString &aSource)
constexpr int mmToIU(double mm) const
Definition: base_units.h:90
PCB_LAYER_ID start
Definition: padstack.h:245
PCB_LAYER_ID end
Definition: padstack.h:246
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
Definition: padstack.h:243
std::optional< bool > is_capped
True if the drill hole should be capped.
Definition: padstack.h:249
std::optional< bool > is_filled
True if the drill hole should be filled completely.
Definition: padstack.h:248
std::optional< bool > has_covering
True if the pad on this side should have covering.
Definition: padstack.h:234
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
Definition: padstack.h:232
std::optional< bool > has_plugging
True if the drill hole should be plugged on this side.
Definition: padstack.h:235
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:2142
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