KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_track.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2012 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include "pcb_track.h"
28
29#include <pcb_base_frame.h>
30#include <core/mirror.h>
32#include <board.h>
35#include <base_units.h>
36#include <layer_range.h>
38#include <lset.h>
39#include <cstdlib>
40#include <string_utils.h>
41#include <view/view.h>
45#include <geometry/seg.h>
48#include <geometry/shape_arc.h>
49#include <drc/drc_engine.h>
50#include <pcb_painter.h>
51#include <trigo.h>
53#include <properties/property.h>
55
56#include <google/protobuf/any.pb.h>
57#include <api/api_enums.h>
58#include <api/api_utils.h>
59#include <api/api_pcb_utils.h>
60#include <api/board/board_types.pb.h>
61
64
66 BOARD_CONNECTED_ITEM( aParent, idtype )
67{
68 m_width = pcbIUScale.mmToIU( 0.2 ); // Gives a reasonable default width
69 m_hasSolderMask = false;
70}
71
72
74{
75 return new PCB_TRACK( *this );
76}
77
78
79void PCB_TRACK::CopyFrom( const BOARD_ITEM* aOther )
80{
81 wxCHECK( aOther && aOther->Type() == PCB_TRACE_T, /* void */ );
82 *this = *static_cast<const PCB_TRACK*>( aOther );
83}
84
85
86PCB_ARC::PCB_ARC( BOARD_ITEM* aParent, const SHAPE_ARC* aArc ) :
87 PCB_TRACK( aParent, PCB_ARC_T )
88{
89 m_Start = aArc->GetP0();
90 m_End = aArc->GetP1();
91 m_Mid = aArc->GetArcMid();
92}
93
94
96{
97 return new PCB_ARC( *this );
98}
99
100
101void PCB_ARC::CopyFrom( const BOARD_ITEM* aOther )
102{
103 wxCHECK( aOther && aOther->Type() == PCB_ARC_T, /* void */ );
104 *this = *static_cast<const PCB_ARC*>( aOther );
105}
106
107
109 PCB_TRACK( aParent, PCB_VIA_T ),
110 m_padStack( this )
111{
113 Padstack().Drill().start = F_Cu;
114 Padstack().Drill().end = B_Cu;
116
117 m_padStack.SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::KEEP_ALL );
118
119 // Padstack layerset is not used for vias right now
120 m_padStack.LayerSet().reset();
121
122 // For now, vias are always circles
124
127
128 m_isFree = false;
129}
130
131
132PCB_VIA::PCB_VIA( const PCB_VIA& aOther ) :
133 PCB_TRACK( aOther.GetParent(), PCB_VIA_T ),
134 m_padStack( this )
135{
136 PCB_VIA::operator=( aOther );
137
138 const_cast<KIID&>( m_Uuid ) = aOther.m_Uuid;
140}
141
142
144{
146
147 m_Start = aOther.m_Start;
148 m_End = aOther.m_End;
149
150 m_viaType = aOther.m_viaType;
151 m_padStack = aOther.m_padStack;
152 m_isFree = aOther.m_isFree;
153
154 return *this;
155}
156
157
158void PCB_VIA::CopyFrom( const BOARD_ITEM* aOther )
159{
160 wxCHECK( aOther && aOther->Type() == PCB_VIA_T, /* void */ );
161 *this = *static_cast<const PCB_VIA*>( aOther );
162}
163
164
166{
167 return new PCB_VIA( *this );
168}
169
170
171wxString PCB_VIA::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
172{
173 wxString formatStr;
174
175 switch( GetViaType() )
176 {
177 case VIATYPE::BLIND: formatStr = _( "Blind via %s on %s" ); break;
178 case VIATYPE::BURIED: formatStr = _( "Buried via %s on %s" ); break;
179 case VIATYPE::MICROVIA: formatStr = _( "Micro via %s on %s" ); break;
180 default: formatStr = _( "Via %s on %s" ); break;
181 }
182
183 return wxString::Format( formatStr, GetNetnameMsg(), LayerMaskDescribe() );
184}
185
186
188{
189 return BITMAPS::via;
190}
191
192
193bool PCB_TRACK::operator==( const BOARD_ITEM& aBoardItem ) const
194{
195 if( aBoardItem.Type() != Type() )
196 return false;
197
198 const PCB_TRACK& other = static_cast<const PCB_TRACK&>( aBoardItem );
199
200 return *this == other;
201}
202
203
204bool PCB_TRACK::operator==( const PCB_TRACK& aOther ) const
205{
206 return m_Start == aOther.m_Start
207 && m_End == aOther.m_End
208 && m_layer == aOther.m_layer
209 && m_width == aOther.m_width
212}
213
214
215double PCB_TRACK::Similarity( const BOARD_ITEM& aOther ) const
216{
217 if( aOther.Type() != Type() )
218 return 0.0;
219
220 const PCB_TRACK& other = static_cast<const PCB_TRACK&>( aOther );
221
222 double similarity = 1.0;
223
224 if( m_layer != other.m_layer )
225 similarity *= 0.9;
226
227 if( m_width != other.m_width )
228 similarity *= 0.9;
229
230 if( m_Start != other.m_Start )
231 similarity *= 0.9;
232
233 if( m_End != other.m_End )
234 similarity *= 0.9;
235
236 if( m_hasSolderMask != other.m_hasSolderMask )
237 similarity *= 0.9;
238
240 similarity *= 0.9;
241
242 return similarity;
243}
244
245
246bool PCB_ARC::operator==( const BOARD_ITEM& aBoardItem ) const
247{
248 if( aBoardItem.Type() != Type() )
249 return false;
250
251 const PCB_ARC& other = static_cast<const PCB_ARC&>( aBoardItem );
252
253 return *this == other;
254}
255
256
257bool PCB_ARC::operator==( const PCB_TRACK& aOther ) const
258{
259 if( aOther.Type() != Type() )
260 return false;
261
262 const PCB_ARC& other = static_cast<const PCB_ARC&>( aOther );
263
264 return *this == other;
265}
266
267
268bool PCB_ARC::operator==( const PCB_ARC& aOther ) const
269{
270 return m_Start == aOther.m_Start
271 && m_End == aOther.m_End
272 && m_Mid == aOther.m_Mid
273 && m_layer == aOther.m_layer
274 && GetWidth() == aOther.GetWidth()
277}
278
279
280double PCB_ARC::Similarity( const BOARD_ITEM& aOther ) const
281{
282 if( aOther.Type() != Type() )
283 return 0.0;
284
285 const PCB_ARC& other = static_cast<const PCB_ARC&>( aOther );
286
287 double similarity = 1.0;
288
289 if( m_layer != other.m_layer )
290 similarity *= 0.9;
291
292 if( GetWidth() != other.GetWidth() )
293 similarity *= 0.9;
294
295 if( m_Start != other.m_Start )
296 similarity *= 0.9;
297
298 if( m_End != other.m_End )
299 similarity *= 0.9;
300
301 if( m_Mid != other.m_Mid )
302 similarity *= 0.9;
303
304 if( m_hasSolderMask != other.m_hasSolderMask )
305 similarity *= 0.9;
306
308 similarity *= 0.9;
309
310 return similarity;
311}
312
313
314bool PCB_VIA::operator==( const BOARD_ITEM& aBoardItem ) const
315{
316 if( aBoardItem.Type() != Type() )
317 return false;
318
319 const PCB_VIA& other = static_cast<const PCB_VIA&>( aBoardItem );
320
321 return *this == other;
322}
323
324
325bool PCB_VIA::operator==( const PCB_TRACK& aOther ) const
326{
327 if( aOther.Type() != Type() )
328 return false;
329
330 const PCB_VIA& other = static_cast<const PCB_VIA&>( aOther );
331
332 return *this == other;
333}
334
335
336bool PCB_VIA::operator==( const PCB_VIA& aOther ) const
337{
338 return m_Start == aOther.m_Start
339 && m_End == aOther.m_End
340 && m_layer == aOther.m_layer
341 && m_padStack == aOther.m_padStack
342 && m_viaType == aOther.m_viaType
344}
345
346
347double PCB_VIA::Similarity( const BOARD_ITEM& aOther ) const
348{
349 if( aOther.Type() != Type() )
350 return 0.0;
351
352 const PCB_VIA& other = static_cast<const PCB_VIA&>( aOther );
353
354 double similarity = 1.0;
355
356 if( m_layer != other.m_layer )
357 similarity *= 0.9;
358
359 if( m_Start != other.m_Start )
360 similarity *= 0.9;
361
362 if( m_End != other.m_End )
363 similarity *= 0.9;
364
365 if( m_padStack != other.m_padStack )
366 similarity *= 0.9;
367
368 if( m_viaType != other.m_viaType )
369 similarity *= 0.9;
370
372 similarity *= 0.9;
373
374 return similarity;
375}
376
377
378void PCB_VIA::SetWidth( int aWidth )
379{
380 m_padStack.SetSize( { aWidth, aWidth }, PADSTACK::ALL_LAYERS );
381}
382
383
385{
386 // This is present because of the parent class. It should never be actually called on a via.
387 wxCHECK_MSG( false, m_padStack.Size( PADSTACK::ALL_LAYERS ).x, "Warning: PCB_VIA::GetWidth called without a layer argument" );
388}
389
390
391void PCB_VIA::SetWidth( PCB_LAYER_ID aLayer, int aWidth )
392{
393 m_padStack.SetSize( { aWidth, aWidth }, aLayer );
394}
395
396
398{
399 return m_padStack.Size( aLayer ).x;
400}
401
402
403void PCB_TRACK::Serialize( google::protobuf::Any &aContainer ) const
404{
405 kiapi::board::types::Track track;
406
407 track.mutable_id()->set_value( m_Uuid.AsStdString() );
408 track.mutable_start()->set_x_nm( GetStart().x );
409 track.mutable_start()->set_y_nm( GetStart().y );
410 track.mutable_end()->set_x_nm( GetEnd().x );
411 track.mutable_end()->set_y_nm( GetEnd().y );
412 track.mutable_width()->set_value_nm( GetWidth() );
414 track.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
415 : kiapi::common::types::LockedState::LS_UNLOCKED );
416 PackNet( track.mutable_net() );
417 // TODO m_hasSolderMask and m_solderMaskMargin
418
419 aContainer.PackFrom( track );
420}
421
422
423bool PCB_TRACK::Deserialize( const google::protobuf::Any &aContainer )
424{
425 kiapi::board::types::Track track;
426
427 if( !aContainer.UnpackTo( &track ) )
428 return false;
429
430 const_cast<KIID&>( m_Uuid ) = KIID( track.id().value() );
431 SetStart( VECTOR2I( track.start().x_nm(), track.start().y_nm() ) );
432 SetEnd( VECTOR2I( track.end().x_nm(), track.end().y_nm() ) );
433 SetWidth( track.width().value_nm() );
435 UnpackNet( track.net() );
436 SetLocked( track.locked() == kiapi::common::types::LockedState::LS_LOCKED );
437 // TODO m_hasSolderMask and m_solderMaskMargin
438
439 return true;
440}
441
442
443void PCB_ARC::Serialize( google::protobuf::Any &aContainer ) const
444{
445 kiapi::board::types::Arc arc;
446
447 arc.mutable_id()->set_value( m_Uuid.AsStdString() );
448 arc.mutable_start()->set_x_nm( GetStart().x );
449 arc.mutable_start()->set_y_nm( GetStart().y );
450 arc.mutable_mid()->set_x_nm( GetMid().x );
451 arc.mutable_mid()->set_y_nm( GetMid().y );
452 arc.mutable_end()->set_x_nm( GetEnd().x );
453 arc.mutable_end()->set_y_nm( GetEnd().y );
454 arc.mutable_width()->set_value_nm( GetWidth() );
456 arc.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
457 : kiapi::common::types::LockedState::LS_UNLOCKED );
458 PackNet( arc.mutable_net() );
459 // TODO m_hasSolderMask and m_solderMaskMargin
460
461 aContainer.PackFrom( arc );
462}
463
464
465bool PCB_ARC::Deserialize( const google::protobuf::Any &aContainer )
466{
467 kiapi::board::types::Arc arc;
468
469 if( !aContainer.UnpackTo( &arc ) )
470 return false;
471
472 const_cast<KIID&>( m_Uuid ) = KIID( arc.id().value() );
473 SetStart( VECTOR2I( arc.start().x_nm(), arc.start().y_nm() ) );
474 SetMid( VECTOR2I( arc.mid().x_nm(), arc.mid().y_nm() ) );
475 SetEnd( VECTOR2I( arc.end().x_nm(), arc.end().y_nm() ) );
476 SetWidth( arc.width().value_nm() );
478 UnpackNet( arc.net() );
479 SetLocked( arc.locked() == kiapi::common::types::LockedState::LS_LOCKED );
480 // TODO m_hasSolderMask and m_solderMaskMargin
481
482 return true;
483}
484
485
486void PCB_VIA::Serialize( google::protobuf::Any &aContainer ) const
487{
488 kiapi::board::types::Via via;
489
490 via.mutable_id()->set_value( m_Uuid.AsStdString() );
491 via.mutable_position()->set_x_nm( GetPosition().x );
492 via.mutable_position()->set_y_nm( GetPosition().y );
493
494 PADSTACK padstack = Padstack();
495
496 google::protobuf::Any padStackWrapper;
497 padstack.Serialize( padStackWrapper );
498 padStackWrapper.UnpackTo( via.mutable_pad_stack() );
499
500 // PADSTACK::m_layerSet is not used by vias
501 via.mutable_pad_stack()->clear_layers();
502 kiapi::board::PackLayerSet( *via.mutable_pad_stack()->mutable_layers(), GetLayerSet() );
503
505 via.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
506 : kiapi::common::types::LockedState::LS_UNLOCKED );
507 PackNet( via.mutable_net() );
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
531 m_padStack.LayerSet().reset();
532
534 UnpackNet( via.net() );
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 m_padStack.Drill().size = aSize;
637}
638
639
641{
642 m_padStack.Drill().shape = aShape;
643}
644
645
647{
648 m_padStack.Drill().start = aLayer;
649}
650
651
653{
654 m_padStack.Drill().end = aLayer;
655}
656
657
658void PCB_VIA::SetFrontPostMachining( const std::optional<PAD_DRILL_POST_MACHINING_MODE>& aMode )
659{
660 m_padStack.FrontPostMachining().mode = aMode;
661}
662
663
664void PCB_VIA::SetBackPostMachining( const std::optional<PAD_DRILL_POST_MACHINING_MODE>& aMode )
665{
666 m_padStack.BackPostMachining().mode = aMode;
667}
668
669
670void PCB_VIA::SetPrimaryDrillFilled( const std::optional<bool>& aFilled )
671{
672 m_padStack.Drill().is_filled = aFilled;
673}
674
675
677{
678 m_padStack.Drill().is_filled = aFilled;
679}
680
681
682void PCB_VIA::SetPrimaryDrillCapped( const std::optional<bool>& aCapped )
683{
684 m_padStack.Drill().is_capped = aCapped;
685}
686
687
689{
690 m_padStack.Drill().is_capped = aCapped;
691}
692
693
695{
696 if( m_padStack.Drill().size.x > 0 ) // Use the specific value.
697 return m_padStack.Drill().size.x;
698
699 // Use the default value from the Netclass
700 NETCLASS* netclass = GetEffectiveNetClass();
701
703 return netclass->GetuViaDrill();
704
705 return netclass->GetViaDrill();
706}
707
708
710{
711 m_padStack.SecondaryDrill().size = aSize;
712}
713
714
716{
717 m_padStack.SecondaryDrill().size = { 0, 0 };
718}
719
720
721void PCB_VIA::SetSecondaryDrillSize( const std::optional<int>& aDrill )
722{
723 if( aDrill.has_value() && *aDrill > 0 )
724 SetSecondaryDrillSize( { *aDrill, *aDrill } );
725 else
727}
728
729
730std::optional<int> PCB_VIA::GetSecondaryDrillSize() const
731{
732 if( m_padStack.SecondaryDrill().size.x > 0 )
733 return m_padStack.SecondaryDrill().size.x;
734
735 return std::nullopt;
736}
737
738
740{
741 m_padStack.SecondaryDrill().start = aLayer;
742}
743
744
746{
747 m_padStack.SecondaryDrill().end = aLayer;
748}
749
750
752{
753 m_padStack.SecondaryDrill().shape = aShape;
754}
755
756
758{
759 m_padStack.TertiaryDrill().size = aSize;
760}
761
762
764{
765 m_padStack.TertiaryDrill().size = { 0, 0 };
766}
767
768
769void PCB_VIA::SetTertiaryDrillSize( const std::optional<int>& aDrill )
770{
771 if( aDrill.has_value() && *aDrill > 0 )
772 SetTertiaryDrillSize( { *aDrill, *aDrill } );
773 else
775}
776
777
778std::optional<int> PCB_VIA::GetTertiaryDrillSize() const
779{
780 if( m_padStack.TertiaryDrill().size.x > 0 )
781 return m_padStack.TertiaryDrill().size.x;
782
783 return std::nullopt;
784}
785
786
788{
789 m_padStack.TertiaryDrill().start = aLayer;
790}
791
792
794{
795 m_padStack.TertiaryDrill().end = aLayer;
796}
797
798
800{
801 m_padStack.TertiaryDrill().shape = aShape;
802}
803
804
806{
807 if( !IsCopperLayer( aLayer ) )
808 return false;
809
810 const BOARD* board = GetBoard();
811
812 if( !board )
813 return false;
814
815 // Check secondary drill (backdrill from top)
816 const PADSTACK::DRILL_PROPS& secondaryDrill = m_padStack.SecondaryDrill();
817
818 if( secondaryDrill.size.x > 0 && secondaryDrill.start != UNDEFINED_LAYER
819 && secondaryDrill.end != UNDEFINED_LAYER )
820 {
821 // Check if aLayer is between start and end of secondary drill
822 for( PCB_LAYER_ID layer : LAYER_RANGE( secondaryDrill.start, secondaryDrill.end,
823 board->GetCopperLayerCount() ) )
824 {
825 if( layer == aLayer )
826 return true;
827 }
828 }
829
830 // Check tertiary drill (backdrill from bottom)
831 const PADSTACK::DRILL_PROPS& tertiaryDrill = m_padStack.TertiaryDrill();
832
833 if( tertiaryDrill.size.x > 0 && tertiaryDrill.start != UNDEFINED_LAYER
834 && tertiaryDrill.end != UNDEFINED_LAYER )
835 {
836 // Check if aLayer is between start and end of tertiary drill
837 for( PCB_LAYER_ID layer : LAYER_RANGE( tertiaryDrill.start, tertiaryDrill.end,
838 board->GetCopperLayerCount() ) )
839 {
840 if( layer == aLayer )
841 return true;
842 }
843 }
844
845 // Check if the layer is affected by post-machining
846 if( GetPostMachiningKnockout( aLayer ) > 0 )
847 return true;
848
849 return false;
850}
851
852
854{
855 if( !IsCopperLayer( aLayer ) )
856 return 0;
857
858 const BOARD* board = GetBoard();
859
860 if( !board )
861 return 0;
862
863 const BOARD_STACKUP& stackup = board->GetDesignSettings().GetStackupDescriptor();
864
865 // Check front post-machining (counterbore/countersink from top)
866 const PADSTACK::POST_MACHINING_PROPS& frontPM = m_padStack.FrontPostMachining();
867
868 if( frontPM.mode.has_value() && *frontPM.mode != PAD_DRILL_POST_MACHINING_MODE::NOT_POST_MACHINED
869 && *frontPM.mode != PAD_DRILL_POST_MACHINING_MODE::UNKNOWN && frontPM.size > 0 )
870 {
871 int pmDepth = frontPM.depth;
872
873 // For countersink without explicit depth, calculate from diameter and angle
874 if( pmDepth <= 0 && *frontPM.mode == PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK
875 && frontPM.angle > 0 )
876 {
877 double halfAngleRad = ( frontPM.angle / 10.0 ) * M_PI / 180.0 / 2.0;
878 pmDepth = static_cast<int>( ( frontPM.size / 2.0 ) / tan( halfAngleRad ) );
879 }
880
881 if( pmDepth > 0 )
882 {
883 // Calculate distance from F_Cu to aLayer
884 int layerDist = stackup.GetLayerDistance( F_Cu, aLayer );
885
886 if( layerDist < pmDepth )
887 {
888 // For countersink, diameter decreases with depth
889 if( *frontPM.mode == PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK && frontPM.angle > 0 )
890 {
891 double halfAngleRad = ( frontPM.angle / 10.0 ) * M_PI / 180.0 / 2.0;
892 int diameterAtLayer = frontPM.size - static_cast<int>( 2.0 * layerDist * tan( halfAngleRad ) );
893 return std::max( 0, diameterAtLayer );
894 }
895 else
896 {
897 // Counterbore - constant diameter
898 return frontPM.size;
899 }
900 }
901 }
902 }
903
904 // Check back post-machining (counterbore/countersink from bottom)
905 const PADSTACK::POST_MACHINING_PROPS& backPM = m_padStack.BackPostMachining();
906
907 if( backPM.mode.has_value() && *backPM.mode != PAD_DRILL_POST_MACHINING_MODE::NOT_POST_MACHINED
908 && *backPM.mode != PAD_DRILL_POST_MACHINING_MODE::UNKNOWN && backPM.size > 0 )
909 {
910 int pmDepth = backPM.depth;
911
912 // For countersink without explicit depth, calculate from diameter and angle
913 if( pmDepth <= 0 && *backPM.mode == PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK
914 && backPM.angle > 0 )
915 {
916 double halfAngleRad = ( backPM.angle / 10.0 ) * M_PI / 180.0 / 2.0;
917 pmDepth = static_cast<int>( ( backPM.size / 2.0 ) / tan( halfAngleRad ) );
918 }
919
920 if( pmDepth > 0 )
921 {
922 // Calculate distance from B_Cu to aLayer
923 int layerDist = stackup.GetLayerDistance( B_Cu, aLayer );
924
925 if( layerDist < pmDepth )
926 {
927 // For countersink, diameter decreases with depth
928 if( *backPM.mode == PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK && backPM.angle > 0 )
929 {
930 double halfAngleRad = ( backPM.angle / 10.0 ) * M_PI / 180.0 / 2.0;
931 int diameterAtLayer = backPM.size - static_cast<int>( 2.0 * layerDist * tan( halfAngleRad ) );
932 return std::max( 0, diameterAtLayer );
933 }
934 else
935 {
936 // Counterbore - constant diameter
937 return backPM.size;
938 }
939 }
940 }
941 }
942
943 return 0;
944}
945
946
947EDA_ITEM_FLAGS PCB_TRACK::IsPointOnEnds( const VECTOR2I& point, int min_dist ) const
948{
950
951 if( min_dist < 0 )
952 min_dist = m_width / 2;
953
954 if( min_dist == 0 )
955 {
956 if( m_Start == point )
958
959 if( m_End == point )
960 result |= ENDPOINT;
961 }
962 else
963 {
964 double dist = m_Start.Distance( point );
965
966 if( min_dist >= dist )
968
969 dist = m_End.Distance( point );
970
971 if( min_dist >= dist )
972 result |= ENDPOINT;
973 }
974
975 return result;
976}
977
978
980{
981 // end of track is round, this is its radius, rounded up
982 int radius = ( m_width + 1 ) / 2;
983 int ymax, xmax, ymin, xmin;
984
985 if( Type() == PCB_VIA_T )
986 {
987 ymax = m_Start.y;
988 xmax = m_Start.x;
989
990 ymin = m_Start.y;
991 xmin = m_Start.x;
992 }
993 else if( Type() == PCB_ARC_T )
994 {
995 std::shared_ptr<SHAPE> arc = GetEffectiveShape();
996 BOX2I bbox = arc->BBox();
997
998 xmin = bbox.GetLeft();
999 xmax = bbox.GetRight();
1000 ymin = bbox.GetTop();
1001 ymax = bbox.GetBottom();
1002 }
1003 else
1004 {
1005 ymax = std::max( m_Start.y, m_End.y );
1006 xmax = std::max( m_Start.x, m_End.x );
1007
1008 ymin = std::min( m_Start.y, m_End.y );
1009 xmin = std::min( m_Start.x, m_End.x );
1010 }
1011
1012 ymax += radius;
1013 xmax += radius;
1014
1015 ymin -= radius;
1016 xmin -= radius;
1017
1018 // return a rectangle which is [pos,dim) in nature. therefore the +1
1019 return BOX2ISafe( VECTOR2I( xmin, ymin ),
1020 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
1021}
1022
1023
1025{
1026 int radius = 0;
1027
1029 [&]( PCB_LAYER_ID aLayer )
1030 {
1031 radius = std::max( radius, GetWidth( aLayer ) );
1032 } );
1033
1034 // via is round, this is its radius, rounded up
1035 radius = ( radius + 1 ) / 2;
1036
1037 int ymax = m_Start.y + radius;
1038 int xmax = m_Start.x + radius;
1039
1040 int ymin = m_Start.y - radius;
1041 int xmin = m_Start.x - radius;
1042
1043 // return a rectangle which is [pos,dim) in nature. therefore the +1
1044 return BOX2ISafe( VECTOR2I( xmin, ymin ),
1045 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
1046}
1047
1048
1050{
1051 int radius = GetWidth( aLayer );
1052
1053 // via is round, this is its radius, rounded up
1054 radius = ( radius + 1 ) / 2;
1055
1056 int ymax = m_Start.y + radius;
1057 int xmax = m_Start.x + radius;
1058
1059 int ymin = m_Start.y - radius;
1060 int xmin = m_Start.x - radius;
1061
1062 // return a rectangle which is [pos,dim) in nature. therefore the +1
1063 return BOX2ISafe( VECTOR2I( xmin, ymin ),
1064 VECTOR2L( (int64_t) xmax - xmin + 1, (int64_t) ymax - ymin + 1 ) );
1065}
1066
1067
1069{
1070 return m_Start.Distance( m_End );
1071}
1072
1073
1075{
1076 const BOARD* board = GetBoard();
1077
1078 if( !board )
1079 return 0.0;
1080
1081 const LENGTH_DELAY_CALCULATION* calc = board->GetLengthCalculation();
1082 std::vector<LENGTH_DELAY_CALCULATION_ITEM> items{ calc->GetLengthCalculationItem( this ) };
1083 constexpr PATH_OPTIMISATIONS opts = { .OptimiseViaLayers = false,
1084 .MergeTracks = false,
1085 .OptimiseTracesInPads = false,
1086 .InferViaInPad = false
1087 };
1088
1089 return (double) calc->CalculateDelay( items, opts );
1090}
1091
1092
1093void PCB_TRACK::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1094{
1095 RotatePoint( m_Start, aRotCentre, aAngle );
1096 RotatePoint( m_End, aRotCentre, aAngle );
1097}
1098
1099
1100void PCB_ARC::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1101{
1102 RotatePoint( m_Start, aRotCentre, aAngle );
1103 RotatePoint( m_End, aRotCentre, aAngle );
1104 RotatePoint( m_Mid, aRotCentre, aAngle );
1105}
1106
1107
1108void PCB_TRACK::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1109{
1110 MIRROR( m_Start, aCentre, aFlipDirection );
1111 MIRROR( m_End, aCentre, aFlipDirection );
1112}
1113
1114
1115void PCB_ARC::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1116{
1117 MIRROR( m_Start, aCentre, aFlipDirection );
1118 MIRROR( m_End, aCentre, aFlipDirection );
1119 MIRROR( m_Mid, aCentre, aFlipDirection );
1120}
1121
1122
1123void PCB_TRACK::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1124{
1125 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
1126 {
1127 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
1128 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
1129 }
1130 else
1131 {
1132 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
1133 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
1134 }
1135
1137}
1138
1139
1140void PCB_ARC::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1141{
1142 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
1143 {
1144 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
1145 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
1146 m_Mid.x = aCentre.x - ( m_Mid.x - aCentre.x );
1147 }
1148 else
1149 {
1150 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
1151 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
1152 m_Mid.y = aCentre.y - ( m_Mid.y - aCentre.y );
1153 }
1154
1156}
1157
1158
1159bool PCB_ARC::IsCCW() const
1160{
1161 VECTOR2L start = m_Start;
1162 VECTOR2L start_end = m_End - start;
1163 VECTOR2L start_mid = m_Mid - start;
1164
1165 return start_end.Cross( start_mid ) < 0;
1166}
1167
1168
1169void PCB_VIA::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1170{
1171 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
1172 {
1173 m_Start.x = aCentre.x - ( m_Start.x - aCentre.x );
1174 m_End.x = aCentre.x - ( m_End.x - aCentre.x );
1175 }
1176 else
1177 {
1178 m_Start.y = aCentre.y - ( m_Start.y - aCentre.y );
1179 m_End.y = aCentre.y - ( m_End.y - aCentre.y );
1180 }
1181
1182 if( GetViaType() != VIATYPE::THROUGH )
1183 {
1184 PCB_LAYER_ID top_layer;
1185 PCB_LAYER_ID bottom_layer;
1186 LayerPair( &top_layer, &bottom_layer );
1187 top_layer = GetBoard()->FlipLayer( top_layer );
1188 bottom_layer = GetBoard()->FlipLayer( bottom_layer );
1189 SetLayerPair( top_layer, bottom_layer );
1190 }
1191}
1192
1193
1194INSPECT_RESULT PCB_TRACK::Visit( INSPECTOR inspector, void* testData,
1195 const std::vector<KICAD_T>& aScanTypes )
1196{
1197 for( KICAD_T scanType : aScanTypes )
1198 {
1199 if( scanType == Type() )
1200 {
1201 if( INSPECT_RESULT::QUIT == inspector( this, testData ) )
1202 return INSPECT_RESULT::QUIT;
1203 }
1204 }
1205
1207}
1208
1209
1210std::shared_ptr<SHAPE_SEGMENT> PCB_VIA::GetEffectiveHoleShape() const
1211{
1212 return std::make_shared<SHAPE_SEGMENT>( SEG( m_Start, m_Start ), Padstack().Drill().size.x );
1213}
1214
1215// clang-format off: the suggestion is slightly less readable
1217{
1218 switch( aMode )
1219 {
1220 case TENTING_MODE::FROM_BOARD: m_padStack.FrontOuterLayers().has_solder_mask.reset(); break;
1221 case TENTING_MODE::TENTED: m_padStack.FrontOuterLayers().has_solder_mask = true; break;
1222 case TENTING_MODE::NOT_TENTED: m_padStack.FrontOuterLayers().has_solder_mask = false; break;
1223 }
1224}
1225
1226
1228{
1229 if( m_padStack.FrontOuterLayers().has_solder_mask.has_value() )
1230 {
1231 return *m_padStack.FrontOuterLayers().has_solder_mask ? TENTING_MODE::TENTED
1233 }
1234
1236}
1237
1238
1240{
1241 switch( aMode )
1242 {
1243 case TENTING_MODE::FROM_BOARD: m_padStack.BackOuterLayers().has_solder_mask.reset(); break;
1244 case TENTING_MODE::TENTED: m_padStack.BackOuterLayers().has_solder_mask = true; break;
1245 case TENTING_MODE::NOT_TENTED: m_padStack.BackOuterLayers().has_solder_mask = false; break;
1246 }
1247}
1248
1249
1251{
1252 if( m_padStack.BackOuterLayers().has_solder_mask.has_value() )
1253 {
1254 return *m_padStack.BackOuterLayers().has_solder_mask ? TENTING_MODE::TENTED
1256 }
1257
1259}
1260
1261
1263{
1264 switch( aMode )
1265 {
1266 case COVERING_MODE::FROM_BOARD: m_padStack.FrontOuterLayers().has_covering.reset(); break;
1267 case COVERING_MODE::COVERED: m_padStack.FrontOuterLayers().has_covering = true; break;
1268 case COVERING_MODE::NOT_COVERED: m_padStack.FrontOuterLayers().has_covering = false; break;
1269 }
1270}
1271
1272
1274{
1275 if( m_padStack.FrontOuterLayers().has_covering.has_value() )
1276 {
1277 return *m_padStack.FrontOuterLayers().has_covering ? COVERING_MODE::COVERED
1279 }
1280
1282}
1283
1284
1286{
1287 switch( aMode )
1288 {
1289 case COVERING_MODE::FROM_BOARD: m_padStack.BackOuterLayers().has_covering.reset(); break;
1290 case COVERING_MODE::COVERED: m_padStack.BackOuterLayers().has_covering = true; break;
1291 case COVERING_MODE::NOT_COVERED: m_padStack.BackOuterLayers().has_covering = false; break;
1292 }
1293}
1294
1295
1297{
1298 if( m_padStack.BackOuterLayers().has_covering.has_value() )
1299 {
1300 return *m_padStack.BackOuterLayers().has_covering ? COVERING_MODE::COVERED
1302 }
1303
1305}
1306
1307
1309{
1310 switch( aMode )
1311 {
1312 case PLUGGING_MODE::FROM_BOARD: m_padStack.FrontOuterLayers().has_plugging.reset(); break;
1313 case PLUGGING_MODE::PLUGGED: m_padStack.FrontOuterLayers().has_plugging = true; break;
1314 case PLUGGING_MODE::NOT_PLUGGED: m_padStack.FrontOuterLayers().has_plugging = false; break;
1315 }
1316}
1317
1318
1320{
1321 if( m_padStack.FrontOuterLayers().has_plugging.has_value() )
1322 {
1323 return *m_padStack.FrontOuterLayers().has_plugging ? PLUGGING_MODE::PLUGGED
1325 }
1326
1328}
1329
1330
1332{
1333 switch( aMode )
1334 {
1335 case PLUGGING_MODE::FROM_BOARD: m_padStack.BackOuterLayers().has_plugging.reset(); break;
1336 case PLUGGING_MODE::PLUGGED: m_padStack.BackOuterLayers().has_plugging = true; break;
1337 case PLUGGING_MODE::NOT_PLUGGED: m_padStack.BackOuterLayers().has_plugging = false; break;
1338 }
1339}
1340
1341
1343{
1344 if( m_padStack.BackOuterLayers().has_plugging.has_value() )
1345 {
1346 return *m_padStack.BackOuterLayers().has_plugging ? PLUGGING_MODE::PLUGGED
1348 }
1349
1351}
1352
1353
1355{
1356 switch( aMode )
1357 {
1358 case CAPPING_MODE::FROM_BOARD: m_padStack.Drill().is_capped.reset(); break;
1359 case CAPPING_MODE::CAPPED: m_padStack.Drill().is_capped = true; break;
1360 case CAPPING_MODE::NOT_CAPPED: m_padStack.Drill().is_capped = false; break;
1361 }
1362}
1363
1364
1366{
1367 if( m_padStack.Drill().is_capped.has_value() )
1368 {
1369 return *m_padStack.Drill().is_capped ? CAPPING_MODE::CAPPED
1371 }
1372
1374}
1375
1376
1378{
1379 switch( aMode )
1380 {
1381 case FILLING_MODE::FROM_BOARD: m_padStack.Drill().is_filled.reset(); break;
1382 case FILLING_MODE::FILLED: m_padStack.Drill().is_filled = true; break;
1383 case FILLING_MODE::NOT_FILLED: m_padStack.Drill().is_filled = false; break;
1384 }
1385}
1386
1387
1389{
1390 if( m_padStack.Drill().is_filled.has_value() )
1391 {
1392 return *m_padStack.Drill().is_filled ? FILLING_MODE::FILLED
1394 }
1395
1397}
1398
1399
1401{
1402 wxCHECK_MSG( IsFrontLayer( aLayer ) || IsBackLayer( aLayer ), true,
1403 "Invalid layer passed to IsTented" );
1404
1405 bool front = IsFrontLayer( aLayer );
1406
1407 if( front && m_padStack.FrontOuterLayers().has_solder_mask.has_value() )
1408 return *m_padStack.FrontOuterLayers().has_solder_mask;
1409
1410 if( !front && m_padStack.BackOuterLayers().has_solder_mask.has_value() )
1411 return *m_padStack.BackOuterLayers().has_solder_mask;
1412
1413 if( const BOARD* board = GetBoard() )
1414 {
1415 return front ? board->GetDesignSettings().m_TentViasFront
1416 : board->GetDesignSettings().m_TentViasBack;
1417 }
1418
1419 return true;
1420}
1421
1422
1424{
1425 if( const BOARD* board = GetBoard() )
1426 return board->GetDesignSettings().m_SolderMaskExpansion;
1427 else
1428 return 0;
1429}
1430
1431
1433{
1434 int margin = 0;
1435
1436 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine
1437 && GetBoard()->GetDesignSettings().m_DRCEngine->HasRulesForConstraintType(
1439 {
1440 DRC_CONSTRAINT constraint;
1441 std::shared_ptr<DRC_ENGINE> drcEngine = GetBoard()->GetDesignSettings().m_DRCEngine;
1442
1443 constraint = drcEngine->EvalRules( SOLDER_MASK_EXPANSION_CONSTRAINT, this, nullptr, m_layer );
1444
1445 if( constraint.m_Value.HasOpt() )
1446 margin = constraint.m_Value.Opt();
1447 }
1448 else if( m_solderMaskMargin.has_value() )
1449 {
1450 margin = m_solderMaskMargin.value();
1451 }
1452 else if( const BOARD* board = GetBoard() )
1453 {
1454 margin = board->GetDesignSettings().m_SolderMaskExpansion;
1455 }
1456
1457 // Ensure the resulting mask opening has a non-negative size
1458 if( margin < 0 )
1459 margin = std::max( margin, -m_width / 2 );
1460
1461 return margin;
1462}
1463
1464
1466{
1467 if( aLayer == m_layer )
1468 {
1469 return true;
1470 }
1471
1472 if( m_hasSolderMask && ( ( aLayer == F_Mask && m_layer == F_Cu )
1473 || ( aLayer == B_Mask && m_layer == B_Cu ) ) )
1474 {
1475 return true;
1476 }
1477
1478 return false;
1479}
1480
1481
1483{
1484#if 0
1485 // Nice and simple, but raises its ugly head in performance profiles....
1486 return GetLayerSet().test( aLayer );
1487#endif
1488 if( IsCopperLayer( aLayer ) &&
1489 LAYER_RANGE::Contains( Padstack().Drill().start, Padstack().Drill().end, aLayer ) )
1490 {
1491 return true;
1492 }
1493
1494 // Test for via on mask layers: a via on on a mask layer if not tented and if
1495 // it is on the corresponding external copper layer
1496 if( aLayer == F_Mask )
1497 return Padstack().Drill().start == F_Cu && !IsTented( F_Mask );
1498 else if( aLayer == B_Mask )
1499 return Padstack().Drill().end == B_Cu && !IsTented( B_Mask );
1500
1501 return false;
1502}
1503
1504
1505bool PCB_VIA::HasValidLayerPair( int aCopperLayerCount )
1506{
1507 // return true if top and bottom layers are valid, depending on the copper layer count
1508 // aCopperLayerCount is expected >= 2
1509
1510 int layer_id = aCopperLayerCount*2;
1511
1512 if( Padstack().Drill().start > B_Cu )
1513 {
1514 if( Padstack().Drill().start > layer_id )
1515 return false;
1516 }
1517 if( Padstack().Drill().end > B_Cu )
1518 {
1519 if( Padstack().Drill().end > layer_id )
1520 return false;
1521 }
1522
1523 return true;
1524}
1525
1526
1528{
1529 return Padstack().Drill().start;
1530}
1531
1532
1534{
1535 Padstack().Drill().start = aLayer;
1536}
1537
1538
1539void PCB_TRACK::SetLayerSet( const LSET& aLayerSet )
1540{
1541 aLayerSet.RunOnLayers(
1542 [&]( PCB_LAYER_ID layer )
1543 {
1544 if( IsCopperLayer( layer ) )
1545 SetLayer( layer );
1546 else if( IsSolderMaskLayer( layer ) )
1547 SetHasSolderMask( true );
1548 } );
1549}
1550
1551
1553{
1554 LSET layermask( { m_layer } );
1555
1556 if( m_hasSolderMask )
1557 {
1558 if( layermask.test( F_Cu ) )
1559 layermask.set( F_Mask );
1560 else if( layermask.test( B_Cu ) )
1561 layermask.set( B_Mask );
1562 }
1563
1564 return layermask;
1565}
1566
1567
1569{
1570 LSET layermask;
1571
1572 if( Padstack().Drill().start < PCBNEW_LAYER_ID_START )
1573 return layermask;
1574
1575 if( GetViaType() == VIATYPE::THROUGH )
1576 {
1577 layermask = LSET::AllCuMask( BoardCopperLayerCount() );
1578 }
1579 else
1580 {
1581 LAYER_RANGE range( Padstack().Drill().start, Padstack().Drill().end, BoardCopperLayerCount() );
1582
1583 int cnt = BoardCopperLayerCount();
1584 // PCB_LAYER_IDs are numbered from front to back, this is top to bottom.
1585 for( PCB_LAYER_ID id : range )
1586 {
1587 layermask.set( id );
1588
1589 if( --cnt <= 0 )
1590 break;
1591 }
1592 }
1593
1594 if( !IsTented( F_Mask ) && layermask.test( F_Cu ) )
1595 layermask.set( F_Mask );
1596
1597 if( !IsTented( B_Mask ) && layermask.test( B_Cu ) )
1598 layermask.set( B_Mask );
1599
1600 return layermask;
1601}
1602
1603
1604void PCB_VIA::SetLayerSet( const LSET& aLayerSet )
1605{
1606 // Vias do not use a LSET, just a top and bottom layer pair
1607 // So we need to set these 2 layers according to the allowed layers in aLayerSet
1608
1609 // For via through, only F_Cu and B_Cu are allowed. aLayerSet is ignored
1610 if( GetViaType() == VIATYPE::THROUGH )
1611 {
1612 Padstack().Drill().start = F_Cu;
1613 Padstack().Drill().end = B_Cu;
1614 return;
1615 }
1616
1617 // For blind buried vias, find the top and bottom layers
1618 bool top_found = false;
1619 bool bottom_found = false;
1620
1621 aLayerSet.RunOnLayers(
1622 [&]( PCB_LAYER_ID layer )
1623 {
1624 // tpo layer and bottom Layer are copper layers, so consider only copper layers
1625 if( IsCopperLayer( layer ) )
1626 {
1627 // The top layer is the first layer found in list and
1628 // cannot the B_Cu
1629 if( !top_found && layer != B_Cu )
1630 {
1631 Padstack().Drill().start = layer;
1632 top_found = true;
1633 }
1634
1635 // The bottom layer is the last layer found in list or B_Cu
1636 if( !bottom_found )
1637 Padstack().Drill().end = layer;
1638
1639 if( layer == B_Cu )
1640 bottom_found = true;
1641 }
1642 } );
1643}
1644
1645
1646void PCB_VIA::SetLayerPair( PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer )
1647{
1648 Padstack().Drill().start = aTopLayer;
1649 Padstack().Drill().end = aBottomLayer;
1651
1652 if( !( GetFlags() & ROUTER_TRANSIENT ) )
1653 {
1654 if( BOARD* board = GetBoard() )
1655 board->InvalidateClearanceCache( m_Uuid );
1656 }
1657}
1658
1659
1661{
1662 // refuse invalid via
1663 if( aLayer == Padstack().Drill().end )
1664 return;
1665
1666 Padstack().Drill().start = aLayer;
1668
1669 if( !( GetFlags() & ROUTER_TRANSIENT ) )
1670 {
1671 if( BOARD* board = GetBoard() )
1672 board->InvalidateClearanceCache( m_Uuid );
1673 }
1674}
1675
1676
1678{
1679 // refuse invalid via
1680 if( aLayer == Padstack().Drill().start )
1681 return;
1682
1683 Padstack().Drill().end = aLayer;
1685
1686 if( !( GetFlags() & ROUTER_TRANSIENT ) )
1687 {
1688 if( BOARD* board = GetBoard() )
1689 board->InvalidateClearanceCache( m_Uuid );
1690 }
1691}
1692
1693
1694void PCB_VIA::LayerPair( PCB_LAYER_ID* top_layer, PCB_LAYER_ID* bottom_layer ) const
1695{
1696 PCB_LAYER_ID t_layer = F_Cu;
1697 PCB_LAYER_ID b_layer = B_Cu;
1698
1699 if( GetViaType() != VIATYPE::THROUGH )
1700 {
1701 b_layer = Padstack().Drill().end;
1702 t_layer = Padstack().Drill().start;
1703
1704 if( !IsCopperLayerLowerThan( b_layer, t_layer ) )
1705 std::swap( b_layer, t_layer );
1706 }
1707
1708 if( top_layer )
1709 *top_layer = t_layer;
1710
1711 if( bottom_layer )
1712 *bottom_layer = b_layer;
1713}
1714
1715
1717{
1718 return Padstack().Drill().start;
1719}
1720
1721
1723{
1724 return Padstack().Drill().end;
1725}
1726
1727
1729{
1730 if( GetViaType() == VIATYPE::THROUGH )
1731 {
1732 Padstack().Drill().start = F_Cu;
1733 Padstack().Drill().end = B_Cu;
1734 }
1735
1736 if( !IsCopperLayerLowerThan( Padstack().Drill().end, Padstack().Drill().start) )
1737 std::swap( Padstack().Drill().end, Padstack().Drill().start );
1738
1740
1741 if( secondary.start != UNDEFINED_LAYER && !IsCopperLayer( secondary.start ) )
1742 secondary.start = UNDEFINED_LAYER;
1743
1744 if( secondary.end != UNDEFINED_LAYER && !IsCopperLayer( secondary.end ) )
1745 secondary.end = UNDEFINED_LAYER;
1746
1747 int copperCount = BoardCopperLayerCount();
1748
1749 if( copperCount > 0 )
1750 {
1751 LSET cuMask = LSET::AllCuMask( copperCount );
1752
1753 if( secondary.start != UNDEFINED_LAYER && !cuMask.Contains( secondary.start ) )
1754 secondary.start = UNDEFINED_LAYER;
1755
1756 if( secondary.end != UNDEFINED_LAYER && !cuMask.Contains( secondary.end ) )
1757 secondary.end = UNDEFINED_LAYER;
1758 }
1759
1760 if( secondary.start != UNDEFINED_LAYER && secondary.end != UNDEFINED_LAYER
1761 && secondary.start == secondary.end )
1762 {
1763 secondary.end = UNDEFINED_LAYER;
1764 }
1765}
1766
1767
1768std::optional<PCB_VIA::VIA_PARAMETER_ERROR>
1769PCB_VIA::ValidateViaParameters( std::optional<int> aDiameter,
1770 std::optional<int> aPrimaryDrill,
1771 std::optional<PCB_LAYER_ID> aPrimaryStartLayer,
1772 std::optional<PCB_LAYER_ID> aPrimaryEndLayer,
1773 std::optional<int> aSecondaryDrill,
1774 std::optional<PCB_LAYER_ID> aSecondaryStartLayer,
1775 std::optional<PCB_LAYER_ID> aSecondaryEndLayer,
1776 std::optional<int> aTertiaryDrill,
1777 std::optional<PCB_LAYER_ID> aTertiaryStartLayer,
1778 std::optional<PCB_LAYER_ID> aTertiaryEndLayer,
1779 int aCopperLayerCount )
1780{
1781 VIA_PARAMETER_ERROR error;
1782
1783 if( aDiameter.has_value() && aDiameter.value() < GEOMETRY_MIN_SIZE )
1784 {
1785 error.m_Message = _( "Via diameter is too small." );
1787 return error;
1788 }
1789
1790 if( aPrimaryDrill.has_value() && aPrimaryDrill.value() < GEOMETRY_MIN_SIZE )
1791 {
1792 error.m_Message = _( "Via drill is too small." );
1794 return error;
1795 }
1796
1797 if( aDiameter.has_value() && !aPrimaryDrill.has_value() )
1798 {
1799 error.m_Message = _( "No via hole size defined." );
1801 return error;
1802 }
1803
1804 if( aPrimaryDrill.has_value() && !aDiameter.has_value() )
1805 {
1806 error.m_Message = _( "No via diameter defined." );
1808 return error;
1809 }
1810
1811 if( aDiameter.has_value() && aPrimaryDrill.has_value()
1812 && aDiameter.value() <= aPrimaryDrill.value() )
1813 {
1814 error.m_Message = _( "Via hole size must be smaller than via diameter" );
1816 return error;
1817 }
1818
1819 std::optional<LSET> copperMask;
1820
1821 auto validateLayer = [&]( std::optional<PCB_LAYER_ID> aLayer,
1822 VIA_PARAMETER_ERROR::FIELD aField ) -> bool
1823 {
1824 if( !aLayer.has_value() )
1825 return true;
1826
1827 PCB_LAYER_ID layer = aLayer.value();
1828
1829 if( layer == UNDEFINED_LAYER )
1830 return true;
1831
1832 if( !IsCopperLayer( layer ) )
1833 {
1834 error.m_Message = _( "Via layer must be a copper layer." );
1835 error.m_Field = aField;
1836 return false;
1837 }
1838
1839 if( aCopperLayerCount > 0 )
1840 {
1841 if( !copperMask.has_value() )
1842 copperMask = LSET::AllCuMask( aCopperLayerCount );
1843
1844 if( !copperMask->Contains( layer ) )
1845 {
1846 error.m_Message = _( "Via layer is outside the board stack." );
1847 error.m_Field = aField;
1848 return false;
1849 }
1850 }
1851
1852 return true;
1853 };
1854
1855 if( !validateLayer( aPrimaryStartLayer, VIA_PARAMETER_ERROR::FIELD::START_LAYER ) )
1856 return error;
1857
1858 if( !validateLayer( aPrimaryEndLayer, VIA_PARAMETER_ERROR::FIELD::END_LAYER ) )
1859 return error;
1860
1861 if( aPrimaryStartLayer.has_value() && aPrimaryEndLayer.has_value()
1862 && aPrimaryStartLayer.value() == aPrimaryEndLayer.value() )
1863 {
1864 error.m_Message = _( "Via start layer and end layer cannot be the same" );
1866 return error;
1867 }
1868
1869 if( aSecondaryDrill.has_value() )
1870 {
1871 if( aSecondaryDrill.value() < aPrimaryDrill.value_or( GEOMETRY_MIN_SIZE ) )
1872 {
1873 error.m_Message = _( "Backdrill diameter is too small." );
1875 return error;
1876 }
1877
1878 if( !validateLayer( aSecondaryStartLayer, VIA_PARAMETER_ERROR::FIELD::SECONDARY_START_LAYER ) )
1879 return error;
1880
1881 if( !validateLayer( aSecondaryEndLayer, VIA_PARAMETER_ERROR::FIELD::SECONDARY_END_LAYER ) )
1882 return error;
1883 }
1884
1885 if( aTertiaryDrill.has_value() )
1886 {
1887 if( aTertiaryDrill.value() < aPrimaryDrill.value_or( GEOMETRY_MIN_SIZE ) )
1888 {
1889 error.m_Message = _( "Tertiary backdrill diameter is too small." );
1891 return error;
1892 }
1893
1894 if( !validateLayer( aTertiaryStartLayer, VIA_PARAMETER_ERROR::FIELD::TERTIARY_START_LAYER ) )
1895 return error;
1896
1897 if( !validateLayer( aTertiaryEndLayer, VIA_PARAMETER_ERROR::FIELD::TERTIARY_END_LAYER ) )
1898 return error;
1899 }
1900
1901 return std::nullopt;
1902}
1903
1904
1906{
1907 return m_viaType == VIATYPE::MICROVIA;
1908}
1909
1910
1912{
1913 // We don't actually have an GUI or file tokens to differentiate these, so we have to look at
1914 // the layers.
1916 {
1917 bool startOuter = Padstack().Drill().start == F_Cu || Padstack().Drill().start == B_Cu;
1918 bool endOuter = Padstack().Drill().end == F_Cu || Padstack().Drill().end == B_Cu;
1919
1920 return startOuter ^ endOuter;
1921 }
1922
1923 return false;
1924}
1925
1926
1928{
1929 // We don't actually have an GUI or file tokens to differentiate these, so we have to look at
1930 // the layers.
1932 {
1933 return Padstack().Drill().start != F_Cu && Padstack().Drill().start != B_Cu
1934 && Padstack().Drill().end != F_Cu && Padstack().Drill().end != B_Cu;
1935 }
1936
1937 return false;
1938}
1939
1940
1941bool PCB_VIA::FlashLayer( const LSET& aLayers ) const
1942{
1943 for( PCB_LAYER_ID layer : aLayers )
1944 {
1945 if( FlashLayer( layer ) )
1946 return true;
1947 }
1948
1949 return false;
1950}
1951
1952
1953bool PCB_VIA::FlashLayer( int aLayer ) const
1954{
1955 // Return the "normal" shape if the caller doesn't specify a particular layer
1956 if( aLayer == UNDEFINED_LAYER )
1957 return true;
1958
1959 const BOARD* board = GetBoard();
1960 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aLayer );
1961
1962 if( !board )
1963 return true;
1964
1965 if( !IsOnLayer( layer ) )
1966 return false;
1967
1968 if( !IsCopperLayer( layer ) )
1969 return true;
1970
1971 switch( Padstack().UnconnectedLayerMode() )
1972 {
1974 return true;
1975
1977 if( layer == Padstack().Drill().start || layer == Padstack().Drill().end )
1978 return true;
1979
1980 // Check for removal below
1981 break;
1982
1984 // Check for removal below
1985 break;
1986
1988 return layer == Padstack().Drill().start || layer == Padstack().Drill().end;
1989 }
1990
1991 if( GetZoneLayerOverride( layer ) == ZLO_FORCE_FLASHED )
1992 {
1993 return true;
1994 }
1995 else
1996 {
1997 // Must be static to keep from raising its ugly head in performance profiles
1998 static std::initializer_list<KICAD_T> nonZoneTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
1999 PCB_PAD_T };
2000
2001 return board->GetConnectivity()->IsConnectedOnLayer( this, layer, nonZoneTypes );
2002 }
2003}
2004
2005
2007{
2008 std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
2009
2012}
2013
2014
2016{
2017 static const ZONE_LAYER_OVERRIDE defaultOverride = ZLO_NONE;
2018 auto it = m_zoneLayerOverrides.find( aLayer );
2019 return it != m_zoneLayerOverrides.end() ? it->second : defaultOverride;
2020}
2021
2022
2024{
2025 std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
2026 m_zoneLayerOverrides[aLayer] = aOverride;
2027}
2028
2029
2031 PCB_LAYER_ID* aBottommost ) const
2032{
2033 *aTopmost = UNDEFINED_LAYER;
2034 *aBottommost = UNDEFINED_LAYER;
2035
2036 static std::initializer_list<KICAD_T> nonZoneTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
2037 PCB_PAD_T };
2038
2039 for( int layer = TopLayer(); layer <= BottomLayer(); ++layer )
2040 {
2041 bool connected = false;
2042
2043 if( GetZoneLayerOverride( static_cast<PCB_LAYER_ID>( layer ) ) == ZLO_FORCE_FLASHED )
2044 {
2045 connected = true;
2046 }
2047 else if( GetBoard()->GetConnectivity()->IsConnectedOnLayer( this, layer, nonZoneTypes ) )
2048 {
2049 connected = true;
2050 }
2051
2052 if( connected )
2053 {
2054 if( *aTopmost == UNDEFINED_LAYER )
2055 *aTopmost = ToLAYER_ID( layer );
2056
2057 *aBottommost = ToLAYER_ID( layer );
2058 }
2059 }
2060
2061}
2062
2063
2064std::vector<int> PCB_TRACK::ViewGetLayers() const
2065{
2066 // Show the track and its netname on different layers
2067 const PCB_LAYER_ID layer = GetLayer();
2068 std::vector<int> layers{
2069 layer,
2070 GetNetnameLayer( layer ),
2071 LAYER_CLEARANCE_START + layer,
2072 };
2073
2074 layers.reserve( 6 );
2075
2076 if( m_hasSolderMask )
2077 {
2078 if( m_layer == F_Cu )
2079 layers.push_back( F_Mask );
2080 else if( m_layer == B_Cu )
2081 layers.push_back( B_Mask );
2082 }
2083
2084 if( IsLocked() )
2085 layers.push_back( LAYER_LOCKED_ITEM_SHADOW );
2086
2087 return layers;
2088}
2089
2090
2091double PCB_TRACK::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
2092{
2093 PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
2094 PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
2095
2096 if( !aView->IsLayerVisible( LAYER_TRACKS ) )
2097 return LOD_HIDE;
2098
2099 if( IsNetnameLayer( aLayer ) )
2100 {
2102 return LOD_HIDE;
2103
2104 // Hide netnames on dimmed tracks
2105 if( renderSettings->GetHighContrast() )
2106 {
2107 if( m_layer != renderSettings->GetPrimaryHighContrastLayer() )
2108 return LOD_HIDE;
2109 }
2110
2111 VECTOR2I start( GetStart() );
2112 VECTOR2I end( GetEnd() );
2113
2114 // Calc the approximate size of the netname (assume square chars)
2115 SEG::ecoord nameSize = GetDisplayNetname().size() * GetWidth();
2116
2117 if( VECTOR2I( end - start ).SquaredEuclideanNorm() < nameSize * nameSize )
2118 return LOD_HIDE;
2119
2120 BOX2I clipBox = BOX2ISafe( aView->GetViewport() );
2121
2122 ClipLine( &clipBox, start.x, start.y, end.x, end.y );
2123
2124 if( VECTOR2I( end - start ).SquaredEuclideanNorm() == 0 )
2125 return LOD_HIDE;
2126
2127 // Netnames will be shown only if zoom is appropriate
2128 return lodScaleForThreshold( aView, m_width, pcbIUScale.mmToIU( 4.0 ) );
2129 }
2130
2131 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
2132 {
2133 // Hide shadow if the main layer is not shown
2134 if( !aView->IsLayerVisible( m_layer ) )
2135 return LOD_HIDE;
2136
2137 // Hide shadow on dimmed tracks
2138 if( renderSettings->GetHighContrast() )
2139 {
2140 if( m_layer != renderSettings->GetPrimaryHighContrastLayer() )
2141 return LOD_HIDE;
2142 }
2143 }
2144
2145 // Other layers are shown without any conditions
2146 return LOD_SHOW;
2147}
2148
2149
2151{
2152 BOX2I bbox = GetBoundingBox();
2153
2154 if( const BOARD* board = GetBoard() )
2155 bbox.Inflate( 2 * board->GetDesignSettings().GetBiggestClearanceValue() );
2156 else
2157 bbox.Inflate( GetWidth() ); // Add a bit extra for safety
2158
2159 return bbox;
2160}
2161
2162
2163std::vector<int> PCB_VIA::ViewGetLayers() const
2164{
2165 LAYER_RANGE layers( Padstack().Drill().start, Padstack().Drill().end, MAX_CU_LAYERS );
2166 std::vector<int> ret_layers{ LAYER_VIA_HOLES, LAYER_VIA_HOLEWALLS, LAYER_VIA_NETNAMES };
2167 ret_layers.reserve( MAX_CU_LAYERS + 6 );
2168
2169 // TODO(JE) Rendering order issue
2170#if 0
2171 // Blind/buried vias (and microvias) use a different net name layer
2172 PCB_LAYER_ID layerTop, layerBottom;
2173 LayerPair( &layerTop, &layerBottom );
2174
2175 bool isBlindBuried =
2178 || ( m_viaType == VIATYPE::MICROVIA && ( layerTop != F_Cu || layerBottom != B_Cu ) );
2179#endif
2180 LSET cuMask = LSET::AllCuMask();
2181
2182 if( const BOARD* board = GetBoard() )
2183 cuMask &= board->GetEnabledLayers();
2184
2185 for( PCB_LAYER_ID layer : layers )
2186 {
2187 if( !cuMask.Contains( layer ) )
2188 continue;
2189
2190 ret_layers.push_back( LAYER_VIA_COPPER_START + layer );
2191 ret_layers.push_back( LAYER_CLEARANCE_START + layer );
2192 }
2193
2194 if( IsLocked() )
2195 ret_layers.push_back( LAYER_LOCKED_ITEM_SHADOW );
2196
2197 // Vias can also be on a solder mask layer. They are on these layers or not,
2198 // depending on the plot and solder mask options
2199 if( IsOnLayer( F_Mask ) )
2200 ret_layers.push_back( F_Mask );
2201
2202 if( IsOnLayer( B_Mask ) )
2203 ret_layers.push_back( B_Mask );
2204
2205 return ret_layers;
2206}
2207
2208
2209double PCB_VIA::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
2210{
2211 PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
2212 PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
2213 const BOARD* board = GetBoard();
2214
2215 // Meta control for hiding all vias
2216 if( !aView->IsLayerVisible( LAYER_VIAS ) )
2217 return LOD_HIDE;
2218
2219 // In high contrast mode don't show vias that don't cross the high-contrast layer
2220 if( renderSettings->GetHighContrast() )
2221 {
2222 PCB_LAYER_ID highContrastLayer = renderSettings->GetPrimaryHighContrastLayer();
2223
2224 if( LSET::FrontTechMask().Contains( highContrastLayer ) )
2225 highContrastLayer = F_Cu;
2226 else if( LSET::BackTechMask().Contains( highContrastLayer ) )
2227 highContrastLayer = B_Cu;
2228
2229 if( IsCopperLayer( highContrastLayer ) && GetViaType() != VIATYPE::THROUGH )
2230 {
2231 if( IsCopperLayerLowerThan( Padstack().Drill().start, highContrastLayer )
2232 || IsCopperLayerLowerThan( highContrastLayer, Padstack().Drill().end ) )
2233 {
2234 return LOD_HIDE;
2235 }
2236 }
2237 }
2238
2239 if( IsHoleLayer( aLayer ) )
2240 {
2241 LSET visible;
2242
2243 if( board )
2244 {
2245 visible = board->GetVisibleLayers();
2246 visible &= board->GetEnabledLayers();
2247 }
2248 else
2249 {
2250 visible = LSET::AllLayersMask();
2251 }
2252
2254 {
2255 // Show a through via's hole if any physical layer is shown
2256 visible &= LSET::PhysicalLayersMask();
2257
2258 if( !visible.any() )
2259 return LOD_HIDE;
2260 }
2261 else
2262 {
2263 // Show a blind or micro via's hole if it crosses a visible layer
2264 visible &= GetLayerSet();
2265
2266 if( !visible.any() )
2267 return LOD_HIDE;
2268 }
2269
2270 // The hole won't be visible anyway at this scale
2271 return lodScaleForThreshold( aView, GetDrillValue(), pcbIUScale.mmToIU( 0.25 ) );
2272 }
2273 else if( IsNetnameLayer( aLayer ) )
2274 {
2275 if( renderSettings->GetHighContrast() )
2276 {
2277 // Hide netnames unless via is flashed to a high-contrast layer
2278 if( !FlashLayer( renderSettings->GetPrimaryHighContrastLayer() ) )
2279 return LOD_HIDE;
2280 }
2281 else
2282 {
2283 LSET visible;
2284
2285 if( board )
2286 {
2287 visible = board->GetVisibleLayers();
2288 visible &= board->GetEnabledLayers();
2289 }
2290 else
2291 {
2292 visible = LSET::AllLayersMask();
2293 }
2294
2295 // Hide netnames unless pad is flashed to a visible layer
2296 if( !FlashLayer( visible ) )
2297 return LOD_HIDE;
2298 }
2299
2300 int width = GetWidth( ToLAYER_ID( aLayer ) );
2301
2302 // Netnames will be shown only if zoom is appropriate
2303 return lodScaleForThreshold( aView, width, pcbIUScale.mmToIU( 10 ) );
2304 }
2305
2306 if( !IsCopperLayer( aLayer ) )
2307 {
2308 int width = GetWidth( ToLAYER_ID( aLayer ) );
2309
2310 return lodScaleForThreshold( aView, width, pcbIUScale.mmToIU( 0.6 ) );
2311 }
2312
2313 return LOD_SHOW;
2314}
2315
2316
2318{
2319 switch( Type() )
2320 {
2321 case PCB_ARC_T: return _( "Track (arc)" );
2322 case PCB_VIA_T: return _( "Via" );
2323 case PCB_TRACE_T:
2324 default: return _( "Track" );
2325 }
2326}
2327
2328
2329void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
2330{
2331 wxString msg;
2332 BOARD* board = GetBoard();
2333
2334 aList.emplace_back( _( "Type" ), GetFriendlyName() );
2335
2336 GetMsgPanelInfoBase_Common( aFrame, aList );
2337
2338 aList.emplace_back( _( "Layer" ), LayerMaskDescribe() );
2339
2340 aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( m_width ) );
2341
2342 if( Type() == PCB_ARC_T )
2343 {
2344 double radius = static_cast<PCB_ARC*>( this )->GetRadius();
2345 aList.emplace_back( _( "Radius" ), aFrame->MessageTextFromValue( radius ) );
2346
2347 aList.emplace_back( _( "Angle" ), wxString::Format( "%.2fdeg",
2348 static_cast<PCB_ARC*>(this)->GetAngle().AsDegrees() ) );
2349 }
2350
2351 double segmentLength = GetLength();
2352 double segmentDelay = GetDelay();
2353
2354 if( segmentDelay == 0.0 )
2355 {
2356 aList.emplace_back( _( "Segment Length" ), aFrame->MessageTextFromValue( segmentLength ) );
2357 }
2358 else
2359 {
2360 aList.emplace_back( _( "Segment Delay" ),
2361 aFrame->MessageTextFromValue( segmentDelay, true, EDA_DATA_TYPE::TIME ) );
2362 }
2363
2364 // Display full track length (in Pcbnew)
2365 if( board && GetNetCode() > 0 )
2366 {
2367 int count = 0;
2368 double trackLen = 0.0;
2369 double lenPadToDie = 0.0;
2370 double trackDelay = 0.0;
2371 double delayPadToDie = 0.0;
2372
2373 std::tie( count, trackLen, lenPadToDie, trackDelay, delayPadToDie ) = board->GetTrackLength( *this );
2374
2375 if( trackDelay == 0.0 )
2376 {
2377 aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
2378
2379 if( lenPadToDie != 0 )
2380 {
2381 msg = aFrame->MessageTextFromValue( lenPadToDie );
2382 aList.emplace_back( _( "Pad To Die Length" ), msg );
2383
2384 msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
2385 aList.emplace_back( _( "Full Length" ), msg );
2386 }
2387 }
2388 else
2389 {
2390 aList.emplace_back( _( "Routed Delay" ),
2391 aFrame->MessageTextFromValue( trackDelay, true, EDA_DATA_TYPE::TIME ) );
2392
2393 if( delayPadToDie != 0.0 )
2394 {
2395 msg = aFrame->MessageTextFromValue( delayPadToDie, true, EDA_DATA_TYPE::TIME );
2396 aList.emplace_back( _( "Pad To Die Delay" ), msg );
2397
2398 msg = aFrame->MessageTextFromValue( trackDelay + delayPadToDie, true, EDA_DATA_TYPE::TIME );
2399 aList.emplace_back( _( "Full Delay" ), msg );
2400 }
2401 }
2402 }
2403
2404 SHAPE_POLY_SET copper;
2406 aList.emplace_back( _( "Copper Area" ),
2407 aFrame->MessageTextFromValue( copper.Area(), true, EDA_DATA_TYPE::AREA ) );
2408
2409 wxString source;
2410 int clearance = GetOwnClearance( GetLayer(), &source );
2411
2412 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2413 aFrame->MessageTextFromValue( clearance ) ),
2414 wxString::Format( _( "(from %s)" ), source ) );
2415
2416 MINOPTMAX<int> constraintValue = GetWidthConstraint( &source );
2417 msg = aFrame->MessageTextFromMinOptMax( constraintValue );
2418
2419 if( !msg.IsEmpty() )
2420 {
2421 aList.emplace_back( wxString::Format( _( "Width Constraints: %s" ), msg ),
2422 wxString::Format( _( "(from %s)" ), source ) );
2423 }
2424}
2425
2426
2427void PCB_VIA::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
2428{
2429 wxString msg;
2430
2431 switch( GetViaType() )
2432 {
2433 case VIATYPE::MICROVIA: msg = _( "Micro Via" ); break;
2434 case VIATYPE::BLIND: msg = _( "Blind Via" ); break;
2435 case VIATYPE::BURIED: msg = _( "Buried Via" ); break;
2436 case VIATYPE::THROUGH: msg = _( "Through Via" ); break;
2437 default: msg = _( "Via" ); break;
2438 }
2439
2440 aList.emplace_back( _( "Type" ), msg );
2441
2442 GetMsgPanelInfoBase_Common( aFrame, aList );
2443
2444 aList.emplace_back( _( "Layer" ), LayerMaskDescribe() );
2445 // TODO(JE) padstacks
2446 aList.emplace_back( _( "Diameter" ), aFrame->MessageTextFromValue( GetWidth( PADSTACK::ALL_LAYERS ) ) );
2447 aList.emplace_back( _( "Hole" ), aFrame->MessageTextFromValue( GetDrillValue() ) );
2448
2449 wxString source;
2450 int clearance = GetOwnClearance( GetLayer(), &source );
2451
2452 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ), aFrame->MessageTextFromValue( clearance ) ),
2453 wxString::Format( _( "(from %s)" ), source ) );
2454
2455 int minAnnulus = GetMinAnnulus( GetLayer(), &source );
2456
2457 aList.emplace_back( wxString::Format( _( "Min Annular Width: %s" ), aFrame->MessageTextFromValue( minAnnulus ) ),
2458 wxString::Format( _( "(from %s)" ), source ) );
2459}
2460
2461
2462void PCB_TRACK::GetMsgPanelInfoBase_Common( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) const
2463{
2464 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
2465
2466 aList.emplace_back( _( "Resolved Netclass" ),
2467 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
2468
2469#if 0 // Enable for debugging
2470 if( GetBoard() )
2471 aList.emplace_back( _( "NetCode" ), fmt::format( "{}", GetNetCode() ) );
2472
2473 aList.emplace_back( wxT( "Flags" ), fmt::format( "#08X", m_flags ) );
2474
2475 aList.emplace_back( wxT( "Start pos" ), fmt::format( "{} {}", m_Start.x, m_Start.y ) );
2476 aList.emplace_back( wxT( "End pos" ), fmt::format( "{} {}", m_End.x, m_End.y ) );
2477#endif
2478
2479 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
2480 aList.emplace_back( _( "Status" ), _( "Locked" ) );
2481}
2482
2483
2485{
2486 const BOARD* board = GetBoard();
2487 PCB_LAYER_ID top_layer;
2488 PCB_LAYER_ID bottom_layer;
2489
2490 LayerPair( &top_layer, &bottom_layer );
2491
2492 return board->GetLayerName( top_layer ) + wxT( " - " ) + board->GetLayerName( bottom_layer );
2493}
2494
2495
2496bool PCB_TRACK::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2497{
2498 return TestSegmentHit( aPosition, m_Start, m_End, aAccuracy + ( m_width / 2 ) );
2499}
2500
2501
2502bool PCB_ARC::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2503{
2504 double max_dist = aAccuracy + ( GetWidth() / 2.0 );
2505
2506 // Short-circuit common cases where the arc is connected to a track or via at an endpoint
2507 if( GetStart().Distance( aPosition ) <= max_dist || GetEnd().Distance( aPosition ) <= max_dist )
2508 {
2509 return true;
2510 }
2511
2513 VECTOR2L relpos = aPosition - center;
2514 int64_t dist = relpos.EuclideanNorm();
2515 double radius = GetRadius();
2516
2517 if( std::abs( dist - radius ) > max_dist )
2518 return false;
2519
2520 EDA_ANGLE arc_angle = GetAngle();
2521 EDA_ANGLE arc_angle_start = GetArcAngleStart(); // Always 0.0 ... 360 deg
2522 EDA_ANGLE arc_hittest( relpos );
2523
2524 // Calculate relative angle between the starting point of the arc, and the test point
2525 arc_hittest -= arc_angle_start;
2526
2527 // Normalise arc_hittest between 0 ... 360 deg
2528 arc_hittest.Normalize();
2529
2530 if( arc_angle < ANGLE_0 )
2531 return arc_hittest >= ANGLE_360 + arc_angle;
2532
2533 return arc_hittest <= arc_angle;
2534}
2535
2536
2537bool PCB_VIA::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2538{
2539 bool hit = false;
2540
2542 [&]( PCB_LAYER_ID aLayer )
2543 {
2544 if( hit )
2545 return;
2546
2547 int max_dist = aAccuracy + ( GetWidth( aLayer ) / 2 );
2548
2549 // rel_pos is aPosition relative to m_Start (or the center of the via)
2550 VECTOR2D rel_pos = aPosition - m_Start;
2551 double dist = rel_pos.x * rel_pos.x + rel_pos.y * rel_pos.y;
2552
2553 if( dist <= static_cast<double>( max_dist ) * max_dist )
2554 hit = true;
2555 } );
2556
2557 return hit;
2558}
2559
2560
2561bool PCB_TRACK::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2562{
2563 BOX2I arect = aRect;
2564 arect.Inflate( aAccuracy );
2565
2566 if( aContained )
2567 return arect.Contains( GetStart() ) && arect.Contains( GetEnd() );
2568 else
2569 return arect.Intersects( GetStart(), GetEnd() );
2570}
2571
2572
2573bool PCB_ARC::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2574{
2575 BOX2I arect = aRect;
2576 arect.Inflate( aAccuracy );
2577
2578 BOX2I box( GetStart() );
2579 box.Merge( GetMid() );
2580 box.Merge( GetEnd() );
2581
2582 box.Inflate( GetWidth() / 2 );
2583
2584 if( aContained )
2585 return arect.Contains( box );
2586 else
2587 return arect.Intersects( box );
2588}
2589
2590
2591bool PCB_VIA::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2592{
2593 BOX2I arect = aRect;
2594 arect.Inflate( aAccuracy );
2595
2596 bool hit = false;
2597
2599 [&]( PCB_LAYER_ID aLayer )
2600 {
2601 if( hit )
2602 return;
2603
2604 BOX2I box( GetStart() );
2605 box.Inflate( GetWidth( aLayer ) / 2 );
2606
2607 if( aContained )
2608 hit = arect.Contains( box );
2609 else
2610 hit = arect.IntersectsCircle( GetStart(), GetWidth( aLayer ) / 2 );
2611 } );
2612
2613 return hit;
2614}
2615
2616
2617bool PCB_TRACK::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
2618{
2619 return KIGEOM::ShapeHitTest( aPoly, *GetEffectiveShape(), aContained );
2620}
2621
2622
2623wxString PCB_TRACK::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2624{
2625 return wxString::Format( Type() == PCB_ARC_T ? _("Track (arc) %s on %s, length %s" )
2626 : _("Track %s on %s, length %s" ),
2627 GetNetnameMsg(),
2628 GetLayerName(),
2629 aUnitsProvider->MessageTextFromValue( GetLength() ) );
2630}
2631
2632
2634{
2635 return BITMAPS::add_tracks;
2636}
2637
2639{
2640 assert( aImage->Type() == PCB_TRACE_T );
2641
2642 std::swap( *((PCB_TRACK*) this), *((PCB_TRACK*) aImage) );
2643}
2644
2646{
2647 assert( aImage->Type() == PCB_ARC_T );
2648
2649 std::swap( *this, *static_cast<PCB_ARC*>( aImage ) );
2650}
2651
2653{
2654 assert( aImage->Type() == PCB_VIA_T );
2655
2656 std::swap( *((PCB_VIA*) this), *((PCB_VIA*) aImage) );
2657}
2658
2659
2665
2666
2668{
2669 auto center = CalcArcCenter( m_Start, m_Mid , m_End );
2670 return std::min( center.Distance( m_Start ), (double) INT_MAX / 2.0 );
2671}
2672
2673
2675{
2677 EDA_ANGLE angle1 = EDA_ANGLE( m_Mid - center ) - EDA_ANGLE( m_Start - center );
2678 EDA_ANGLE angle2 = EDA_ANGLE( m_End - center ) - EDA_ANGLE( m_Mid - center );
2679
2680 return angle1.Normalize180() + angle2.Normalize180();
2681}
2682
2683
2685{
2686 VECTOR2D pos( GetPosition() );
2687 EDA_ANGLE angleStart( m_Start - pos );
2688
2689 return angleStart.Normalize();
2690}
2691
2692
2693// Note: used in python tests. Ignore CLion's claim that it's unused....
2695{
2696 VECTOR2D pos( GetPosition() );
2697 EDA_ANGLE angleEnd( m_End - pos );
2698
2699 return angleEnd.Normalize();
2700}
2701
2702bool PCB_ARC::IsDegenerated( int aThreshold ) const
2703{
2704 // We have lots of code that will blow up if the radius overflows an int.
2705 if( GetRadius() >= (double)INT_MAX/2.0 )
2706 return true;
2707
2708 // Too small arcs cannot be really handled: arc center (and arc radius)
2709 // cannot be safely computed if the distance between mid and end points
2710 // is too small (a few internal units)
2711
2712 // len of both segments must be < aThreshold to be a very small degenerated arc
2713 return ( GetMid() - GetStart() ).EuclideanNorm() < aThreshold
2714 && ( GetMid() - GetEnd() ).EuclideanNorm() < aThreshold;
2715}
2716
2717
2719{
2720 if( a->GetNetCode() != b->GetNetCode() )
2721 return a->GetNetCode() < b->GetNetCode();
2722
2723 if( a->GetLayer() != b->GetLayer() )
2724 return a->GetLayer() < b->GetLayer();
2725
2726 if( a->Type() != b->Type() )
2727 return a->Type() < b->Type();
2728
2729 if( a->m_Uuid != b->m_Uuid )
2730 return a->m_Uuid < b->m_Uuid;
2731
2732 return a < b;
2733}
2734
2735
2736std::shared_ptr<SHAPE> PCB_TRACK::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2737{
2738 int width = m_width;
2739
2740 if( IsSolderMaskLayer( aLayer ) )
2741 width += 2 * GetSolderMaskExpansion();
2742
2743 return std::make_shared<SHAPE_SEGMENT>( m_Start, m_End, width );
2744}
2745
2746
2747std::shared_ptr<SHAPE> PCB_VIA::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2748{
2749 // Check if this layer has copper removed by backdrill or post-machining
2750 if( aLayer != UNDEFINED_LAYER && IsBackdrilledOrPostMachined( aLayer ) )
2751 {
2752 // Return the larger of the backdrill or post-machining hole
2753 int holeSize = 0;
2754
2755 const PADSTACK::POST_MACHINING_PROPS& frontPM = Padstack().FrontPostMachining();
2756 const PADSTACK::POST_MACHINING_PROPS& backPM = Padstack().BackPostMachining();
2757
2760 {
2761 holeSize = std::max( holeSize, frontPM.size );
2762 }
2763
2766 {
2767 holeSize = std::max( holeSize, backPM.size );
2768 }
2769
2770 const PADSTACK::DRILL_PROPS& secDrill = Padstack().SecondaryDrill();
2771
2772 if( secDrill.start != UNDEFINED_LAYER && secDrill.end != UNDEFINED_LAYER )
2773 holeSize = std::max( holeSize, secDrill.size.x );
2774
2775 if( holeSize > 0 )
2776 return std::make_shared<SHAPE_CIRCLE>( m_Start, holeSize / 2 );
2777 else
2778 return std::make_shared<SHAPE_CIRCLE>( m_Start, GetDrillValue() / 2 );
2779 }
2780
2781 if( aFlash == FLASHING::ALWAYS_FLASHED
2782 || ( aFlash == FLASHING::DEFAULT && FlashLayer( aLayer ) ) )
2783 {
2784 int width = 0;
2785
2786 if( aLayer == UNDEFINED_LAYER )
2787 {
2788 Padstack().ForEachUniqueLayer(
2789 [&]( PCB_LAYER_ID layer )
2790 {
2791 width = std::max( width, GetWidth( layer ) );
2792 } );
2793
2794 width /= 2;
2795 }
2796 else
2797 {
2798 PCB_LAYER_ID cuLayer = m_padStack.EffectiveLayerFor( aLayer );
2799 width = GetWidth( cuLayer ) / 2;
2800 }
2801
2802 return std::make_shared<SHAPE_CIRCLE>( m_Start, width );
2803 }
2804 else
2805 {
2806 return std::make_shared<SHAPE_CIRCLE>( m_Start, GetDrillValue() / 2 );
2807 }
2808}
2809
2810
2811std::shared_ptr<SHAPE> PCB_ARC::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2812{
2813 int width = GetWidth();
2814
2815 if( IsSolderMaskLayer( aLayer ) )
2816 width += 2 * GetSolderMaskExpansion();
2817
2818 SHAPE_ARC arc( GetStart(), GetMid(), GetEnd(), width );
2819
2820 if( arc.IsEffectiveLine() )
2821 return std::make_shared<SHAPE_SEGMENT>( GetStart(), GetEnd(), width );
2822
2823 return std::make_shared<SHAPE_ARC>( arc );
2824}
2825
2826
2828 int aClearance, int aError, ERROR_LOC aErrorLoc,
2829 bool ignoreLineWidth ) const
2830{
2831 wxASSERT_MSG( !ignoreLineWidth, wxT( "IgnoreLineWidth has no meaning for tracks." ) );
2832
2833
2834 switch( Type() )
2835 {
2836 case PCB_VIA_T:
2837 {
2838 int radius = ( static_cast<const PCB_VIA*>( this )->GetWidth( aLayer ) / 2 ) + aClearance;
2839 TransformCircleToPolygon( aBuffer, m_Start, radius, aError, aErrorLoc );
2840 break;
2841 }
2842
2843 case PCB_ARC_T:
2844 {
2845 const PCB_ARC* arc = static_cast<const PCB_ARC*>( this );
2846 int width = m_width + ( 2 * aClearance );
2847
2848 if( IsSolderMaskLayer( aLayer ) )
2849 width += 2 * GetSolderMaskExpansion();
2850
2851 TransformArcToPolygon( aBuffer, arc->GetStart(), arc->GetMid(), arc->GetEnd(), width,
2852 aError, aErrorLoc );
2853 break;
2854 }
2855
2856 default:
2857 {
2858 int width = m_width + ( 2 * aClearance );
2859
2860 if( IsSolderMaskLayer( aLayer ) )
2861 width += 2 * GetSolderMaskExpansion();
2862
2863 TransformOvalToPolygon( aBuffer, m_Start, m_End, width, aError, aErrorLoc );
2864
2865 break;
2866 }
2867 }
2868}
2869
2870
2871static struct TRACK_VIA_DESC
2872{
2874 {
2875 // clang-format off: the suggestion is less readable
2877 .Undefined( VIATYPE::NOT_DEFINED )
2878 .Map( VIATYPE::THROUGH, _HKI( "Through" ) )
2879 .Map( VIATYPE::BLIND, _HKI( "Blind" ) )
2880 .Map( VIATYPE::BURIED, _HKI( "Buried" ) )
2881 .Map( VIATYPE::MICROVIA, _HKI( "Micro" ) );
2882
2884 .Undefined( TENTING_MODE::FROM_BOARD )
2885 .Map( TENTING_MODE::FROM_BOARD, _HKI( "From board stackup" ) )
2886 .Map( TENTING_MODE::TENTED, _HKI( "Tented" ) )
2887 .Map( TENTING_MODE::NOT_TENTED, _HKI( "Not tented" ) );
2888
2890 .Undefined( COVERING_MODE::FROM_BOARD )
2891 .Map( COVERING_MODE::FROM_BOARD, _HKI( "From board stackup" ) )
2892 .Map( COVERING_MODE::COVERED, _HKI( "Covered" ) )
2893 .Map( COVERING_MODE::NOT_COVERED, _HKI( "Not covered" ) );
2894
2896 .Undefined( PLUGGING_MODE::FROM_BOARD )
2897 .Map( PLUGGING_MODE::FROM_BOARD, _HKI( "From board stackup" ) )
2898 .Map( PLUGGING_MODE::PLUGGED, _HKI( "Plugged" ) )
2899 .Map( PLUGGING_MODE::NOT_PLUGGED, _HKI( "Not plugged" ) );
2900
2902 .Undefined( CAPPING_MODE::FROM_BOARD )
2903 .Map( CAPPING_MODE::FROM_BOARD, _HKI( "From board stackup" ) )
2904 .Map( CAPPING_MODE::CAPPED, _HKI( "Capped" ) )
2905 .Map( CAPPING_MODE::NOT_CAPPED, _HKI( "Not capped" ) );
2906
2908 .Undefined( FILLING_MODE::FROM_BOARD )
2909 .Map( FILLING_MODE::FROM_BOARD, _HKI( "From board stackup" ) )
2910 .Map( FILLING_MODE::FILLED, _HKI( "Filled" ) )
2911 .Map( FILLING_MODE::NOT_FILLED, _HKI( "Not filled" ) );
2912
2913 // clang-format on: the suggestion is less readable
2914
2916
2917 if( layerEnum.Choices().GetCount() == 0 )
2918 {
2919 layerEnum.Undefined( UNDEFINED_LAYER );
2920
2921 for( PCB_LAYER_ID layer : LSET::AllLayersMask() )
2922 layerEnum.Map( layer, LSET::Name( layer ) );
2923 }
2924
2925 auto viaDiameterPropertyValidator =
2926 []( const wxAny&& aValue, EDA_ITEM* aItem ) -> VALIDATOR_RESULT
2927 {
2928 if( !aItem || aItem->Type() != PCB_VIA_T )
2929 return std::nullopt;
2930
2931 if( !aValue.CheckType<int>() )
2932 return std::nullopt;
2933
2934 PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
2935
2936 std::optional<int> diameter = aValue.As<int>();
2937 std::optional<int> drill = via->GetDrillValue();
2938
2939 std::optional<PCB_LAYER_ID> startLayer;
2940
2941 if( via->Padstack().Drill().start != UNDEFINED_LAYER )
2942 startLayer = via->Padstack().Drill().start;
2943
2944 std::optional<PCB_LAYER_ID> endLayer;
2945
2946 if( via->Padstack().Drill().end != UNDEFINED_LAYER )
2947 endLayer = via->Padstack().Drill().end;
2948
2949 int copperLayerCount = via->BoardCopperLayerCount();
2950
2951 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
2952 PCB_VIA::ValidateViaParameters( diameter, drill, startLayer, endLayer,
2953 std::nullopt, std::nullopt, std::nullopt, // secondary drill
2954 std::nullopt, std::nullopt, std::nullopt, // tertiary drill
2955 copperLayerCount ) )
2956 {
2957 return std::make_unique<VALIDATION_ERROR_MSG>( error->m_Message );
2958 }
2959
2960 return std::nullopt;
2961 };
2962
2963 auto viaDrillPropertyValidator =
2964 []( const wxAny&& aValue, EDA_ITEM* aItem ) -> VALIDATOR_RESULT
2965 {
2966 if( !aItem || aItem->Type() != PCB_VIA_T )
2967 return std::nullopt;
2968
2969 if( !aValue.CheckType<int>() )
2970 return std::nullopt;
2971
2972 PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
2973
2974 std::optional<int> diameter = via->GetFrontWidth();
2975 std::optional<int> drill = aValue.As<int>();
2976
2977 std::optional<PCB_LAYER_ID> startLayer;
2978
2979 if( via->Padstack().Drill().start != UNDEFINED_LAYER )
2980 startLayer = via->Padstack().Drill().start;
2981
2982 std::optional<PCB_LAYER_ID> endLayer;
2983
2984 if( via->Padstack().Drill().end != UNDEFINED_LAYER )
2985 endLayer = via->Padstack().Drill().end;
2986
2987 std::optional<int> secondaryDrill = via->GetSecondaryDrillSize();
2988
2989 std::optional<PCB_LAYER_ID> secondaryStart;
2990
2991 if( via->GetSecondaryDrillStartLayer() != UNDEFINED_LAYER )
2992 secondaryStart = via->GetSecondaryDrillStartLayer();
2993
2994 std::optional<PCB_LAYER_ID> secondaryEnd;
2995
2996 if( via->GetSecondaryDrillEndLayer() != UNDEFINED_LAYER )
2997 secondaryEnd = via->GetSecondaryDrillEndLayer();
2998
2999 std::optional<int> tertiaryDrill = via->GetTertiaryDrillSize();
3000
3001 std::optional<PCB_LAYER_ID> tertiaryStart;
3002
3003 if( via->GetTertiaryDrillStartLayer() != UNDEFINED_LAYER )
3004 tertiaryStart = via->GetTertiaryDrillStartLayer();
3005
3006 std::optional<PCB_LAYER_ID> tertiaryEnd;
3007
3008 if( via->GetTertiaryDrillEndLayer() != UNDEFINED_LAYER )
3009 tertiaryEnd = via->GetTertiaryDrillEndLayer();
3010
3011 int copperLayerCount = via->BoardCopperLayerCount();
3012
3013 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
3014 PCB_VIA::ValidateViaParameters( diameter, drill, startLayer, endLayer,
3015 secondaryDrill, secondaryStart, secondaryEnd,
3016 tertiaryDrill, tertiaryStart, tertiaryEnd,
3017 copperLayerCount ) )
3018 {
3019 return std::make_unique<VALIDATION_ERROR_MSG>( error->m_Message );
3020 }
3021
3022 return std::nullopt;
3023 };
3024
3025 auto viaStartLayerPropertyValidator =
3026 []( const wxAny&& aValue, EDA_ITEM* aItem ) -> VALIDATOR_RESULT
3027 {
3028 if( !aItem || aItem->Type() != PCB_VIA_T )
3029 return std::nullopt;
3030
3031 PCB_LAYER_ID layer;
3032
3033 if( aValue.CheckType<PCB_LAYER_ID>() )
3034 layer = aValue.As<PCB_LAYER_ID>();
3035 else if( aValue.CheckType<int>() )
3036 layer = static_cast<PCB_LAYER_ID>( aValue.As<int>() );
3037 else
3038 return std::nullopt;
3039
3040 PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
3041
3042 std::optional<int> diameter = via->GetFrontWidth();
3043 std::optional<int> drill = via->GetDrillValue();
3044
3045 std::optional<PCB_LAYER_ID> endLayer;
3046
3047 if( via->BottomLayer() != UNDEFINED_LAYER )
3048 endLayer = via->BottomLayer();
3049
3050 std::optional<int> secondaryDrill = via->GetSecondaryDrillSize();
3051
3052 std::optional<PCB_LAYER_ID> secondaryStart;
3053
3054 if( via->GetSecondaryDrillStartLayer() != UNDEFINED_LAYER )
3055 secondaryStart = via->GetSecondaryDrillStartLayer();
3056
3057 std::optional<PCB_LAYER_ID> secondaryEnd;
3058
3059 if( via->GetSecondaryDrillEndLayer() != UNDEFINED_LAYER )
3060 secondaryEnd = via->GetSecondaryDrillEndLayer();
3061
3062 int copperLayerCount = via->BoardCopperLayerCount();
3063
3064 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
3065 PCB_VIA::ValidateViaParameters( diameter, drill, layer, endLayer,
3066 secondaryDrill, secondaryStart, secondaryEnd,
3067 std::nullopt, std::nullopt, std::nullopt, // tertiary drill
3068 copperLayerCount ) )
3069 {
3070 return std::make_unique<VALIDATION_ERROR_MSG>( error->m_Message );
3071 }
3072
3073 return std::nullopt;
3074 };
3075
3076 auto viaEndLayerPropertyValidator =
3077 []( const wxAny&& aValue, EDA_ITEM* aItem ) -> VALIDATOR_RESULT
3078 {
3079 if( !aItem || aItem->Type() != PCB_VIA_T )
3080 return std::nullopt;
3081
3082 PCB_LAYER_ID layer;
3083
3084 if( aValue.CheckType<PCB_LAYER_ID>() )
3085 layer = aValue.As<PCB_LAYER_ID>();
3086 else if( aValue.CheckType<int>() )
3087 layer = static_cast<PCB_LAYER_ID>( aValue.As<int>() );
3088 else
3089 return std::nullopt;
3090
3091 PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
3092
3093 std::optional<int> diameter = via->GetFrontWidth();
3094 std::optional<int> drill = via->GetDrillValue();
3095
3096 std::optional<PCB_LAYER_ID> startLayer;
3097
3098 if( via->TopLayer() != UNDEFINED_LAYER )
3099 startLayer = via->TopLayer();
3100
3101 std::optional<int> secondaryDrill = via->GetSecondaryDrillSize();
3102
3103 std::optional<PCB_LAYER_ID> secondaryStart;
3104
3105 if( via->GetSecondaryDrillStartLayer() != UNDEFINED_LAYER )
3106 secondaryStart = via->GetSecondaryDrillStartLayer();
3107
3108 std::optional<PCB_LAYER_ID> secondaryEnd;
3109
3110 if( via->GetSecondaryDrillEndLayer() != UNDEFINED_LAYER )
3111 secondaryEnd = via->GetSecondaryDrillEndLayer();
3112
3113 int copperLayerCount = via->BoardCopperLayerCount();
3114
3115 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
3116 PCB_VIA::ValidateViaParameters( diameter, drill, startLayer, layer,
3117 secondaryDrill, secondaryStart, secondaryEnd,
3118 std::nullopt, std::nullopt, std::nullopt, // tertiary drill
3119 copperLayerCount ) )
3120 {
3121 return std::make_unique<VALIDATION_ERROR_MSG>( error->m_Message );
3122 }
3123
3124 return std::nullopt;
3125 };
3126
3128
3129 // Track
3132
3133 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "Width" ),
3135 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ),
3136 new PROPERTY<PCB_TRACK, int>( _HKI( "Start X" ),
3139 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ),
3140 new PROPERTY<PCB_TRACK, int>( _HKI( "Start Y" ),
3143 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "End X" ),
3146 propMgr.AddProperty( new PROPERTY<PCB_TRACK, int>( _HKI( "End Y" ),
3149
3150 const wxString groupTechLayers = _HKI( "Technical Layers" );
3151
3152 auto isExternalLayerTrack =
3153 []( INSPECTABLE* aItem )
3154 {
3155 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( aItem ) )
3156 return IsExternalCopperLayer( track->GetLayer() );
3157
3158 return false;
3159 };
3160
3161 propMgr.AddProperty( new PROPERTY<PCB_TRACK, bool>( _HKI( "Soldermask" ),
3163 .SetAvailableFunc( isExternalLayerTrack );
3164 propMgr.AddProperty( new PROPERTY<PCB_TRACK, std::optional<int>>( _HKI( "Soldermask Margin Override" ),
3166 PROPERTY_DISPLAY::PT_SIZE ), groupTechLayers )
3167 .SetAvailableFunc( isExternalLayerTrack );
3168
3169 // Arc
3172
3173 // Via
3176
3177 // TODO test drill, use getdrillvalue?
3178 const wxString groupVia = _HKI( "Via Properties" );
3179 const wxString groupBackdrill = _HKI( "Backdrill" );
3180 const wxString groupPostMachining = _HKI( "Post-machining" );
3181
3182 propMgr.Mask( TYPE_HASH( PCB_VIA ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ) );
3183
3184 // clang-format off: the suggestion is less readable
3185 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Diameter" ),
3187 .SetValidator( viaDiameterPropertyValidator );
3188 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Hole" ),
3190 .SetValidator( viaDrillPropertyValidator );
3191 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Layer Top" ),
3193 .SetValidator( viaStartLayerPropertyValidator );
3194 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Layer Bottom" ),
3196 .SetValidator( viaEndLayerPropertyValidator );
3197 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, VIATYPE>( _HKI( "Via Type" ),
3199 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, TENTING_MODE>( _HKI( "Front tenting" ),
3201 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, TENTING_MODE>( _HKI( "Back tenting" ),
3203 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, COVERING_MODE>( _HKI( "Front covering" ),
3205 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, COVERING_MODE>( _HKI( "Back covering" ),
3207 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PLUGGING_MODE>( _HKI( "Front plugging" ),
3209 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PLUGGING_MODE>( _HKI( "Back plugging" ),
3211 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, CAPPING_MODE>( _HKI( "Capping" ),
3213 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, FILLING_MODE>( _HKI( "Filling" ),
3215
3216 auto canHaveBackdrill =
3217 []( INSPECTABLE* aItem )
3218 {
3219 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3220 {
3221 if( via->GetViaType() == VIATYPE::THROUGH )
3222 return true;
3223
3224 if( via->Padstack().GetBackdrillMode() != BACKDRILL_MODE::NO_BACKDRILL )
3225 return true;
3226 }
3227
3228 return false;
3229 };
3230
3231 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, BACKDRILL_MODE>( _HKI( "Backdrill Mode" ),
3233 .SetAvailableFunc( canHaveBackdrill );
3234
3235 propMgr.AddProperty( new PROPERTY<PCB_VIA, std::optional<int>>( _HKI( "Bottom Backdrill Size" ),
3237 groupBackdrill )
3239 []( INSPECTABLE* aItem ) -> bool
3240 {
3241 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3242 {
3243 auto mode = via->GetBackdrillMode();
3245 }
3246 return false;
3247 } );
3248
3249 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Bottom Backdrill Must-Cut" ),
3252 []( INSPECTABLE* aItem ) -> bool
3253 {
3254 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3255 {
3256 auto mode = via->GetBackdrillMode();
3258 }
3259 return false;
3260 } );
3261
3262 propMgr.AddProperty( new PROPERTY<PCB_VIA, std::optional<int>>( _HKI( "Top Backdrill Size" ),
3264 groupBackdrill )
3266 []( INSPECTABLE* aItem ) -> bool
3267 {
3268 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3269 {
3270 auto mode = via->GetBackdrillMode();
3272 }
3273 return false;
3274 } );
3275
3276 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PCB_LAYER_ID>( _HKI( "Top Backdrill Must-Cut" ),
3279 []( INSPECTABLE* aItem ) -> bool
3280 {
3281 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3282 {
3283 auto mode = via->GetBackdrillMode();
3285 }
3286 return false;
3287 } );
3288
3289 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PAD_DRILL_POST_MACHINING_MODE>( _HKI( "Front Post-machining" ),
3291
3292 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Front Post-machining Size" ),
3294 groupPostMachining )
3296 []( INSPECTABLE* aItem )
3297 {
3298 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3299 {
3300 auto mode = via->GetFrontPostMachining();
3303 }
3304 return false;
3305 } );
3306
3307 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Front Post-machining Depth" ),
3309 groupPostMachining )
3311 []( INSPECTABLE* aItem )
3312 {
3313 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3314 {
3315 auto mode = via->GetFrontPostMachining();
3317 }
3318 return false;
3319 } );
3320
3321 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Front Post-machining Angle" ),
3323 groupPostMachining )
3325 []( INSPECTABLE* aItem )
3326 {
3327 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3328 {
3329 auto mode = via->GetFrontPostMachining();
3331 }
3332 return false;
3333 } );
3334
3335 propMgr.AddProperty( new PROPERTY_ENUM<PCB_VIA, PAD_DRILL_POST_MACHINING_MODE>( _HKI( "Back Post-machining" ),
3337
3338 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Back Post-machining Size" ),
3340 groupPostMachining )
3342 []( INSPECTABLE* aItem )
3343 {
3344 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3345 {
3346 auto mode = via->GetBackPostMachining();
3349 }
3350 return false;
3351 } );
3352
3353 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Back Post-machining Depth" ),
3355 groupPostMachining )
3357 []( INSPECTABLE* aItem )
3358 {
3359 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3360 {
3361 auto mode = via->GetBackPostMachining();
3363 }
3364 return false;
3365 } );
3366
3367 propMgr.AddProperty( new PROPERTY<PCB_VIA, int>( _HKI( "Back Post-machining Angle" ),
3369 groupPostMachining )
3371 []( INSPECTABLE* aItem )
3372 {
3373 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
3374 {
3375 auto mode = via->GetBackPostMachining();
3377 }
3378 return false;
3379 } );
3380 // clang-format on: the suggestion is less readable
3381 }
3383
3390
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
Definition api_enums.cpp:97
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:36
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
constexpr int ARC_LOW_DEF
Definition base_units.h:128
BITMAPS
A list of all bitmap identifiers.
ZONE_LAYER_OVERRIDE
Conditionally flashed vias and pads that interact with zones of different priority can be very squirr...
Definition board_item.h:72
@ ZLO_NONE
Definition board_item.h:73
@ ZLO_FORCE_FLASHED
Definition board_item.h:74
constexpr BOX2I BOX2ISafe(const BOX2D &aInput)
Definition box2.h:929
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
BOARD_CONNECTED_ITEM(BOARD_ITEM *aParent, KICAD_T idtype)
void PackNet(kiapi::board::types::Net *aProto) const
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
const wxString & GetDisplayNetname() const
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
void UnpackNet(const kiapi::board::types::Net &aProto)
Assigns a net to this item from an API message.
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:86
void SetLocked(bool aLocked) override
Definition board_item.h:328
PCB_LAYER_ID m_layer
Definition board_item.h:459
bool IsLocked() const override
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
virtual void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const
Convert the item shape to a polyset.
Definition board_item.h:430
virtual wxString LayerMaskDescribe() const
Return a string (to be shown to the user) describing a layer mask.
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:215
virtual int BoardCopperLayerCount() const
Return the total number of copper layers for the board that this item resides on.
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Manage layers needed to make a physical board.
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1402
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:2915
const LSET & GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:982
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:913
int GetCopperLayerCount() const
Definition board.cpp:920
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:729
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1083
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:968
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition board.h:563
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
bool IsConnectedOnLayer(const BOARD_CONNECTED_ITEM *aItem, int aLayer, const std::initializer_list< KICAD_T > &aTypes={}) const
wxString GetName() const
Definition drc_rule.h:195
MINOPTMAX< int > & Value()
Definition drc_rule.h:188
MINOPTMAX< int > m_Value
Definition drc_rule.h:229
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
EDA_ANGLE Normalize()
Definition eda_angle.h:229
EDA_ANGLE Normalize180()
Definition eda_angle.h:268
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:99
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition eda_item.cpp:338
const KIID m_Uuid
Definition eda_item.h:527
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:538
EDA_ITEM_FLAGS GetFlags() const
Definition eda_item.h:151
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:41
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:727
static ENUM_MAP< T > & Instance()
Definition property.h:721
ENUM_MAP & Undefined(T aValue)
Definition property.h:734
wxPGChoices & Choices()
Definition property.h:770
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:38
Contains methods for drawing PCB-specific items.
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition pcb_painter.h:82
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
static double lodScaleForThreshold(const KIGFX::VIEW *aView, int aWhatIu, int aThresholdIu)
Get the scale at which aWhatIu would be drawn at the same size as aThresholdIu on screen.
Definition view_item.cpp:39
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:180
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:185
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:67
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition view.cpp:536
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition view.h:423
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition view.h:221
Definition kiid.h:49
static bool Contains(int aStart_layer, int aEnd_layer, int aTest_layer)
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
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:608
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
Definition lset.h:263
static const LSET & BackTechMask()
Return a mask holding all technical layers (no CU layer) on back side.
Definition lset.cpp:648
static const LSET & AllLayersMask()
Definition lset.cpp:641
static const LSET & PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition lset.cpp:697
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:662
T Min() const
Definition minoptmax.h:33
bool HasMin() const
Definition minoptmax.h:37
T Opt() const
Definition minoptmax.h:35
bool HasOpt() const
Definition minoptmax.h:39
A collection of nets and the parameters used to route or test these nets.
Definition netclass.h:45
int GetViaDrill() const
Definition netclass.h:141
int GetuViaDrill() const
Definition netclass.h:157
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition netinfo.h:247
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
Definition padstack.h:157
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::...
DRILL_PROPS & Drill()
Definition padstack.h:348
DRILL_PROPS & SecondaryDrill()
Definition padstack.h:351
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition padstack.cpp:634
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
virtual VECTOR2I GetPosition() const override
bool IsDegenerated(int aThreshold=5) const
virtual void swapData(BOARD_ITEM *aImage) override
bool IsCCW() const
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition pcb_track.cpp:95
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
EDA_ANGLE GetArcAngleStart() const
void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
virtual bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
EDA_ANGLE GetArcAngleEnd() const
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void SetMid(const VECTOR2I &aMid)
Definition pcb_track.h:289
double GetRadius() const
EDA_ANGLE GetAngle() const
const VECTOR2I & GetMid() const
Definition pcb_track.h:290
PCB_ARC(BOARD_ITEM *aParent)
Definition pcb_track.h:263
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
VECTOR2I m_Mid
Arc mid point, halfway between start and end.
Definition pcb_track.h:354
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
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.
bool operator==(const PCB_ARC &aOther) const
void CopyFrom(const BOARD_ITEM *aOther) override
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
virtual void SetLayerSet(const LSET &aLayers) override
int GetSolderMaskExpansion() const
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void SetEndY(int aY)
Definition pcb_track.h:106
void SetHasSolderMask(bool aVal)
Definition pcb_track.h:120
virtual double GetLength() const
Get the length of the track using the hypotenuse calculation.
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
virtual void swapData(BOARD_ITEM *aImage) override
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:93
bool HasSolderMask() const
Definition pcb_track.h:121
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:96
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
int GetStartY() const
Definition pcb_track.h:103
int GetEndX() const
Definition pcb_track.h:108
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
virtual void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
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...
bool ApproxCollinear(const PCB_TRACK &aTrack)
VECTOR2I m_End
Line end point.
Definition pcb_track.h:250
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition pcb_track.h:123
std::optional< int > m_solderMaskMargin
Definition pcb_track.h:253
void CopyFrom(const BOARD_ITEM *aOther) override
Definition pcb_track.cpp:79
std::optional< int > GetLocalSolderMaskMargin() const
Definition pcb_track.h:124
virtual double GetDelay() const
Get the time delay of the track.
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.
virtual EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition pcb_track.cpp:73
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
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.
const VECTOR2I & GetStart() const
Definition pcb_track.h:97
virtual bool operator==(const BOARD_ITEM &aOther) const override
VECTOR2I m_Start
Line start point.
Definition pcb_track.h:249
int GetEndY() const
Definition pcb_track.h:109
wxString GetFriendlyName() const override
virtual std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
virtual double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
bool m_hasSolderMask
Definition pcb_track.h:252
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.
void SetStartX(int aX)
Definition pcb_track.h:99
const VECTOR2I & GetEnd() const
Definition pcb_track.h:94
PCB_TRACK(BOARD_ITEM *aParent, KICAD_T idtype=PCB_TRACE_T)
Definition pcb_track.cpp:65
void SetStartY(int aY)
Definition pcb_track.h:100
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
virtual MINOPTMAX< int > GetWidthConstraint(wxString *aSource=nullptr) const
void SetEndX(int aX)
Definition pcb_track.h:105
int GetStartX() const
Definition pcb_track.h:102
int m_width
Thickness of track (or arc) – no longer the width of a via.
Definition pcb_track.h:256
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...
virtual void SetWidth(int aWidth)
Definition pcb_track.h:90
virtual int GetWidth() const
Definition pcb_track.h:91
void GetMsgPanelInfoBase_Common(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) const
int GetFrontPostMachiningSize() const
Definition pcb_track.h:693
PCB_LAYER_ID BottomLayer() const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
PLUGGING_MODE GetFrontPluggingMode() const
VECTOR2I GetPosition() const override
Definition pcb_track.h:557
bool IsTented(PCB_LAYER_ID aLayer) const override
Checks if the given object is tented (its copper shape is covered by solder mask) on a given side of ...
void CopyFrom(const BOARD_ITEM *aOther) override
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.
PCB_LAYER_ID GetTopBackdrillLayer() const
Definition pcb_track.h:422
void SetFrontPostMachiningDepth(int aDepth)
Definition pcb_track.h:694
void SetCappingMode(CAPPING_MODE aMode)
void SetFrontCoveringMode(COVERING_MODE aMode)
wxString LayerMaskDescribe() const override
Return a string (to be shown to the user) describing a layer mask.
int GetBackPostMachiningDepth() const
Definition pcb_track.h:715
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void SetBackPostMachiningAngle(int aAngle)
Definition pcb_track.h:716
int GetBackPostMachiningAngle() const
Definition pcb_track.h:717
COVERING_MODE GetBackCoveringMode() const
std::optional< int > GetTertiaryDrillSize() const
void SetTopBackdrillSize(std::optional< int > aSize)
Definition pcb_track.h:420
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
void SetBackPostMachiningMode(PAD_DRILL_POST_MACHINING_MODE aMode)
Definition pcb_track.h:702
std::optional< int > GetTopBackdrillSize() const
Definition pcb_track.h:419
void SetBackdrillMode(BACKDRILL_MODE aMode)
Definition pcb_track.h:411
void SetDrillDefault()
Set the drill value for vias to the default value UNDEFINED_DRILL_DIAMETER.
Definition pcb_track.h:770
std::map< PCB_LAYER_ID, ZONE_LAYER_OVERRIDE > m_zoneLayerOverrides
Definition pcb_track.h:847
void SetBottomBackdrillSize(std::optional< int > aSize)
Definition pcb_track.h:414
void ClearZoneLayerOverrides()
CAPPING_MODE GetCappingMode() const
const PADSTACK & Padstack() const
Definition pcb_track.h:406
void SetFrontTentingMode(TENTING_MODE aMode)
bool m_isFree
"Free" vias don't get their nets auto-updated
Definition pcb_track.h:844
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
int GetFrontPostMachiningDepth() const
Definition pcb_track.h:695
bool IsBlindVia() const
TENTING_MODE GetFrontTentingMode() const
int GetPostMachiningKnockout(PCB_LAYER_ID aLayer) const
Get the knockout diameter for a layer affected by post-machining.
void SetBottomLayer(PCB_LAYER_ID aLayer)
void SetPrimaryDrillSize(const VECTOR2I &aSize)
Set the drill value for vias.
bool IsBackdrilledOrPostMachined(PCB_LAYER_ID aLayer) const
Check if a layer is affected by backdrilling or post-machining operations.
std::optional< int > GetSecondaryDrillSize() const
void SetPrimaryDrillCappedFlag(bool aCapped)
int GetSolderMaskExpansion() const
void SetSecondaryDrillStartLayer(PCB_LAYER_ID aLayer)
void SetTertiaryDrillEndLayer(PCB_LAYER_ID aLayer)
void ClearSecondaryDrillSize()
void SetBackPostMachiningDepth(int aDepth)
Definition pcb_track.h:714
void SetDrill(int aDrill)
Definition pcb_track.h:748
PLUGGING_MODE GetBackPluggingMode() const
void SetBackPluggingMode(PLUGGING_MODE aMode)
MINOPTMAX< int > GetDrillConstraint(wxString *aSource=nullptr) const
void SetBackTentingMode(TENTING_MODE aMode)
void SetFrontPluggingMode(PLUGGING_MODE aMode)
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
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.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
void SetFrontPostMachining(const std::optional< PAD_DRILL_POST_MACHINING_MODE > &aMode)
bool operator==(const PCB_VIA &aOther) const
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
void SetSecondaryDrillEndLayer(PCB_LAYER_ID aLayer)
int GetFrontPostMachiningAngle() const
Definition pcb_track.h:697
std::mutex m_zoneLayerOverridesMutex
Definition pcb_track.h:846
void SetFrontPostMachiningAngle(int aAngle)
Definition pcb_track.h:696
void SetTopLayer(PCB_LAYER_ID aLayer)
FILLING_MODE GetFillingMode() const
bool IsBuriedVia() const
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
int GetFrontWidth() const
Definition pcb_track.h:474
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
PAD_DRILL_POST_MACHINING_MODE GetFrontPostMachiningMode() const
Definition pcb_track.h:687
void SetFrontPostMachiningSize(int aSize)
Definition pcb_track.h:692
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetTertiaryDrillStartLayer(PCB_LAYER_ID aLayer)
PCB_LAYER_ID GetBottomBackdrillLayer() const
Definition pcb_track.h:416
void SetPrimaryDrillShape(PAD_DRILL_SHAPE aShape)
static std::optional< VIA_PARAMETER_ERROR > ValidateViaParameters(std::optional< int > aDiameter, std::optional< int > aPrimaryDrill, std::optional< PCB_LAYER_ID > aPrimaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aPrimaryEndLayer=std::nullopt, std::optional< int > aSecondaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryEndLayer=std::nullopt, std::optional< int > aTertiaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryEndLayer=std::nullopt, int aCopperLayerCount=0)
bool IsMicroVia() const
void SetTertiaryDrillShape(PAD_DRILL_SHAPE aShape)
virtual void SetLayerSet(const LSET &aLayers) override
Note SetLayerSet() initialize the first and last copper layers connected by the via.
void GetOutermostConnectedLayers(PCB_LAYER_ID *aTopmost, PCB_LAYER_ID *aBottommost) const
Return the top-most and bottom-most connected layers.
void SetSecondaryDrillShape(PAD_DRILL_SHAPE aShape)
void SanitizeLayers()
Check so that the layers are correct depending on the type of via, and so that the top actually is on...
int GetWidth() const override
void SetBackPostMachining(const std::optional< PAD_DRILL_POST_MACHINING_MODE > &aMode)
PCB_VIA & operator=(const PCB_VIA &aOther)
void swapData(BOARD_ITEM *aImage) override
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void SetFillingMode(FILLING_MODE aMode)
PCB_VIA(BOARD_ITEM *aParent)
void SetPrimaryDrillFilledFlag(bool aFilled)
std::optional< int > GetBottomBackdrillSize() const
Definition pcb_track.h:413
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
void SetViaType(VIATYPE aViaType)
Definition pcb_track.h:399
int GetMinAnnulus(PCB_LAYER_ID aLayer, wxString *aSource) const
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
TENTING_MODE GetBackTentingMode() const
PCB_LAYER_ID TopLayer() const
void ClearTertiaryDrillSize()
VIATYPE m_viaType
through, blind/buried or micro
Definition pcb_track.h:840
void SetBottomBackdrillLayer(PCB_LAYER_ID aLayer)
Definition pcb_track.h:417
int GetBackPostMachiningSize() const
Definition pcb_track.h:713
void SetTertiaryDrillSize(const VECTOR2I &aSize)
PADSTACK m_padStack
Definition pcb_track.h:842
void SetSecondaryDrillSize(const VECTOR2I &aSize)
COVERING_MODE GetFrontCoveringMode() const
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
void SetZoneLayerOverride(PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride)
PAD_DRILL_POST_MACHINING_MODE GetBackPostMachiningMode() const
Definition pcb_track.h:707
void SetFrontWidth(int aWidth)
Definition pcb_track.h:473
VIATYPE GetViaType() const
Definition pcb_track.h:398
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
void SetPrimaryDrillCapped(const std::optional< bool > &aCapped)
MINOPTMAX< int > GetWidthConstraint(wxString *aSource=nullptr) const override
BACKDRILL_MODE GetBackdrillMode() const
Definition pcb_track.h:410
void SetWidth(int aWidth) override
void SetBackCoveringMode(COVERING_MODE aMode)
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetPrimaryDrillFilled(const std::optional< bool > &aFilled)
void SetTopBackdrillLayer(PCB_LAYER_ID aLayer)
Definition pcb_track.h:423
const ZONE_LAYER_OVERRIDE & GetZoneLayerOverride(PCB_LAYER_ID aLayer) const
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)
bool HasValidLayerPair(int aCopperLayerCount)
void SetFrontPostMachiningMode(PAD_DRILL_POST_MACHINING_MODE aMode)
Definition pcb_track.h:682
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void SetBackPostMachiningSize(int aSize)
Definition pcb_track.h:712
void SetPrimaryDrillEndLayer(PCB_LAYER_ID aLayer)
void SetPrimaryDrillStartLayer(PCB_LAYER_ID aLayer)
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:262
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition property.h:349
Provide class metadata.Helper macro to map type hashes to names.
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()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
PROPERTY_BASE & ReplaceProperty(PROPERTY_BASE *aProperty, const wxString &aGroup)
Replace an existing property.
Definition seg.h:42
VECTOR2I::extended_type ecoord
Definition seg.h:44
bool ApproxCollinear(const SEG &aSeg, int aDistanceThreshold=1) const
Definition seg.cpp:795
const VECTOR2I & GetArcMid() const
Definition shape_arc.h:120
const VECTOR2I & GetP1() const
Definition shape_arc.h:119
bool IsEffectiveLine() const
const VECTOR2I & GetP0() const
Definition shape_arc.h:118
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
double Area()
Return the area of this poly set.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString MessageTextFromMinOptMax(const MINOPTMAX< int > &aValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition vector2d.h:546
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.
@ ANNULAR_WIDTH_CONSTRAINT
Definition drc_rule.h:61
@ VIA_DIAMETER_CONSTRAINT
Definition drc_rule.h:70
@ TRACK_WIDTH_CONSTRAINT
Definition drc_rule.h:59
@ SOLDER_MASK_EXPANSION_CONSTRAINT
Definition drc_rule.h:66
@ HOLE_SIZE_CONSTRAINT
Definition drc_rule.h:54
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:417
#define PCB_EDIT_FRAME_NAME
INSPECT_RESULT
Definition eda_item.h:45
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:92
#define ROUTER_TRANSIENT
transient items that should NOT be cached
#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:172
bool IsSolderMaskLayer(int aLayer)
Definition layer_ids.h:748
@ 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:824
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:780
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:184
@ DEFAULT
Flashing follows connectivity.
Definition layer_ids.h:185
@ ALWAYS_FLASHED
Always flashed for connectivity.
Definition layer_ids.h:186
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition layer_ids.h:803
#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:854
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:677
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:307
@ LAYER_VIA_HOLEWALLS
Definition layer_ids.h:298
@ LAYER_VIA_COPPER_START
Virtual layers for via copper on a given copper layer.
Definition layer_ids.h:341
@ LAYER_TRACKS
Definition layer_ids.h:267
@ LAYER_CLEARANCE_START
Virtual layers for pad/via/track clearance outlines for a given copper layer.
Definition layer_ids.h:345
@ LAYER_VIA_HOLES
Draw via holes (pad holes do not use this layer).
Definition layer_ids.h:274
@ 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:869
bool IsHoleLayer(int aLayer)
Definition layer_ids.h:739
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
Definition layer_ids.h:688
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:754
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
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:28
bool ShapeHitTest(const SHAPE_LINE_CHAIN &aHitter, const SHAPE &aHittee, bool aHitteeContained)
Perform a shape-to-shape hit test.
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
PAD_DRILL_SHAPE
The set of pad drill shapes, used with PAD::{Set,Get}DrillShape()
Definition padstack.h:69
#define _HKI(x)
Definition page_info.cpp:44
static struct TRACK_VIA_DESC _TRACK_VIA_DESC
#define GEOMETRY_MIN_SIZE
Definition pcb_track.h:57
FILLING_MODE
VIATYPE
TENTING_MODE
COVERING_MODE
PLUGGING_MODE
CAPPING_MODE
#define TYPE_HASH(x)
Definition property.h:74
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition property.h:823
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
@ PT_DECIDEGREE
Angle expressed in decidegrees.
Definition property.h:67
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
std::optional< std::unique_ptr< VALIDATION_ERROR > > VALIDATOR_RESULT
Null optional means validation succeeded.
wxString UnescapeString(const wxString &aSource)
! The properties of a padstack drill. Drill position is always the pad position (origin).
Definition padstack.h:266
PCB_LAYER_ID start
Definition padstack.h:269
PCB_LAYER_ID end
Definition padstack.h:270
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
Definition padstack.h:267
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
Definition padstack.h:281
Struct to control which optimisations the length calculation code runs on the given path objects.
bool operator()(const PCB_TRACK *aFirst, const PCB_TRACK *aSecond) const
VECTOR2I center
int radius
VECTOR2I end
int clearance
wxString result
Test unit parsing edge cases and error handling.
#define M_PI
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< double > VECTOR2D
Definition vector2d.h:694
VECTOR2< int64_t > VECTOR2L
Definition vector2d.h:696