KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_kicad_iface.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2016 CERN
5 * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <board.h>
25#include <netinfo.h>
26#include <footprint.h>
27#include <pad.h>
28#include <pcb_track.h>
29#include <zone.h>
30#include <pcb_shape.h>
31#include <pcb_generator.h>
32#include <pcb_text.h>
33#include <board_commit.h>
34#include <layer_ids.h>
35#include <kidialog.h>
36#include <tools/pcb_tool_base.h>
37#include <tool/tool_manager.h>
39
41#include <pcb_painter.h>
42
43#include <geometry/shape.h>
45#include <geometry/shape_arc.h>
47
48#include <drc/drc_rule.h>
49#include <drc/drc_engine.h>
50
52
53#include <wx/log.h>
54
55#include <memory>
56
57#include <advanced_config.h>
58#include <pcbnew_settings.h>
59#include <macros.h>
60
61#include "pns_kicad_iface.h"
62#include "pns_arc.h"
63#include "pns_sizes_settings.h"
64#include "pns_item.h"
65#include "pns_line.h"
66#include "pns_solid.h"
67#include "pns_segment.h"
68#include "pns_node.h"
69#include "pns_router.h"
70#include "pns_debug_decorator.h"
71#include "router_preview_item.h"
72
74
75
77{
78 const PNS::ITEM* A;
79 const PNS::ITEM* B;
80 bool Flag;
81
82 bool operator==(const CLEARANCE_CACHE_KEY& other) const
83 {
84 return A == other.A && B == other.B && Flag == other.Flag;
85 }
86};
87
88namespace std
89{
90 template <>
92 {
93 std::size_t operator()( const CLEARANCE_CACHE_KEY& k ) const
94 {
95 size_t retval = 0xBADC0FFEE0DDF00D;
96 hash_combine( retval, hash<const void*>()( k.A ), hash<const void*>()( k.B ), hash<int>()( k.Flag ) );
97 return retval;
98 }
99 };
100}
101
102
104{
105public:
106 PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER_IFACE* aRouterIface );
108
109 int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
110 bool aUseClearanceEpsilon = true ) override;
111
113 int DpNetPolarity( PNS::NET_HANDLE aNet ) override;
114 bool DpNetPair( const PNS::ITEM* aItem, PNS::NET_HANDLE& aNetP,
115 PNS::NET_HANDLE& aNetN ) override;
116
117 int NetCode( PNS::NET_HANDLE aNet ) override;
118 wxString NetName( PNS::NET_HANDLE aNet ) override;
119
120 bool IsInNetTie( const PNS::ITEM* aA ) override;
121 bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
122 const PNS::ITEM* aCollidingItem ) override;
123
124 bool IsDrilledHole( const PNS::ITEM* aItem ) override;
125 bool IsNonPlatedSlot( const PNS::ITEM* aItem ) override;
126
131 bool IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem, bool* aEnforce ) override;
132
133 bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
134 const PNS::ITEM* aItemB, int aLayer,
135 PNS::CONSTRAINT* aConstraint ) override;
136
137 int ClearanceEpsilon() const override { return m_clearanceEpsilon; }
138
139 void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
140 void ClearCaches() override;
141 void ClearTemporaryCaches() override;
142
143private:
144 BOARD_ITEM* getBoardItem( const PNS::ITEM* aItem, int aLayer, int aIdx = 0 );
145
146private:
153
154 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
155 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_tempClearanceCache;
156};
157
158
160 PNS::ROUTER_IFACE* aRouterIface ) :
161 m_routerIface( aRouterIface ),
162 m_board( aBoard ),
163 m_dummyTracks{ { aBoard }, { aBoard } },
164 m_dummyArcs{ { aBoard }, { aBoard } },
165 m_dummyVias{ { aBoard }, { aBoard } }
166{
167 for( PCB_TRACK& track : m_dummyTracks )
168 track.SetFlags( ROUTER_TRANSIENT );
169
170 for( PCB_ARC& arc : m_dummyArcs )
171 arc.SetFlags( ROUTER_TRANSIENT );
172
173 for ( PCB_VIA& via : m_dummyVias )
174 via.SetFlags( ROUTER_TRANSIENT );
175
176 if( aBoard )
177 m_clearanceEpsilon = aBoard->GetDesignSettings().GetDRCEpsilon();
178 else
179 m_clearanceEpsilon = 0;
180}
181
182
184{
185}
186
187
189{
190 BOARD_ITEM* item = aA->BoardItem();
191
192 return item && item->GetParentFootprint() && item->GetParentFootprint()->IsNetTie();
193}
194
195
197 const VECTOR2I& aCollisionPos,
198 const PNS::ITEM* aCollidingItem )
199{
200 wxCHECK( aItem && aCollidingItem, false );
201
202 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
203 BOARD_ITEM* item = aItem->BoardItem();
204 BOARD_ITEM* collidingItem = aCollidingItem->BoardItem();
205
206 FOOTPRINT* collidingFp = collidingItem->GetParentFootprint();
207 FOOTPRINT* itemFp = item ? item->GetParentFootprint() : nullptr;
208
209 if( collidingFp && itemFp && ( collidingFp == itemFp ) && itemFp->IsNetTie() )
210 {
211 // Two items colliding from the same net tie footprint are not checked
212 return true;
213 }
214
215 if( drcEngine )
216 {
217 return drcEngine->IsNetTieExclusion( NetCode( aItem->Net() ), ToLAYER_ID( aItem->Layer() ),
218 aCollisionPos, collidingItem );
219 }
220
221 return false;
222}
223
224
225bool PNS_PCBNEW_RULE_RESOLVER::IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem,
226 bool* aEnforce )
227{
228 auto checkKeepout =
229 []( const ZONE* aKeepout, const BOARD_ITEM* aOther )
230 {
231 if( !aOther )
232 return false;
233
234 if( aKeepout->GetDoNotAllowTracks() && aOther->IsType( { PCB_ARC_T, PCB_TRACE_T } ) )
235 return true;
236
237 if( aKeepout->GetDoNotAllowVias() && aOther->Type() == PCB_VIA_T )
238 return true;
239
240 if( aKeepout->GetDoNotAllowPads() && aOther->Type() == PCB_PAD_T )
241 return true;
242
243 // Incomplete test, but better than nothing:
244 if( aKeepout->GetDoNotAllowFootprints() && aOther->Type() == PCB_PAD_T )
245 {
246 return !aKeepout->GetParentFootprint()
247 || aKeepout->GetParentFootprint() != aOther->GetParentFootprint();
248 }
249
250 return false;
251 };
252
253 if( aObstacle->Parent() && aObstacle->Parent()->Type() == PCB_ZONE_T )
254 {
255 const ZONE* zone = static_cast<ZONE*>( aObstacle->Parent() );
256
257 if( zone->GetIsRuleArea() )
258 {
259 *aEnforce = checkKeepout( zone, getBoardItem( aItem, aObstacle->Layer() ) );
260 return true;
261 }
262 }
263
264 return false;
265}
266
267
268static bool isCopper( const PNS::ITEM* aItem )
269{
270 if ( !aItem )
271 return false;
272
273 const BOARD_ITEM *parent = aItem->Parent();
274
275 return !parent || parent->IsOnCopperLayer();
276}
277
278
279static bool isHole( const PNS::ITEM* aItem )
280{
281 if ( !aItem )
282 return false;
283
284 return aItem->OfKind( PNS::ITEM::HOLE_T );
285}
286
287
288static bool isEdge( const PNS::ITEM* aItem )
289{
290 if ( !aItem )
291 return false;
292
293 const PCB_SHAPE *parent = dynamic_cast<PCB_SHAPE*>( aItem->BoardItem() );
294
295 return parent && ( parent->IsOnLayer( Edge_Cuts ) || parent->IsOnLayer( Margin ) );
296}
297
298
300{
301 if( isHole( aItem ) )
302 {
303 if( BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItem->Parent() ) )
304 return item->HasDrilledHole();
305 }
306
307 return false;
308}
309
310
312{
313 if( !isHole( aItem ) )
314 return false;
315
316 BOARD_ITEM* parent = aItem->Parent();
317
318 if( !parent && aItem->ParentPadVia() )
319 parent = aItem->ParentPadVia()->Parent();
320
321 if( parent )
322 {
323 if( parent->Type() == PCB_PAD_T )
324 {
325 PAD* pad = static_cast<PAD*>( parent );
326
327 return pad->GetAttribute() == PAD_ATTRIB::NPTH
328 && pad->GetDrillSizeX() != pad->GetDrillSizeY();
329 }
330
331 // Via holes are (currently) always round, and always plated
332 }
333
334 return false;
335}
336
337
338BOARD_ITEM* PNS_PCBNEW_RULE_RESOLVER::getBoardItem( const PNS::ITEM* aItem, int aLayer, int aIdx )
339{
340 switch( aItem->Kind() )
341 {
342 case PNS::ITEM::ARC_T:
343 m_dummyArcs[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
344 m_dummyArcs[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
345 m_dummyArcs[aIdx].SetStart( aItem->Anchor( 0 ) );
346 m_dummyArcs[aIdx].SetEnd( aItem->Anchor( 1 ) );
347 return &m_dummyArcs[aIdx];
348
349 case PNS::ITEM::VIA_T:
351 m_dummyVias[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
352 m_dummyVias[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
353 m_dummyVias[aIdx].SetStart( aItem->Anchor( 0 ) );
354 return &m_dummyVias[aIdx];
355
358 m_dummyTracks[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
359 m_dummyTracks[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
360 m_dummyTracks[aIdx].SetStart( aItem->Anchor( 0 ) );
361 m_dummyTracks[aIdx].SetEnd( aItem->Anchor( 1 ) );
362 return &m_dummyTracks[aIdx];
363
364 default:
365 return nullptr;
366 }
367}
368
369
371 const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
372 int aLayer, PNS::CONSTRAINT* aConstraint )
373{
374 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
375
376 if( !drcEngine )
377 return false;
378
379 DRC_CONSTRAINT_T hostType;
380
381 switch ( aType )
382 {
395 default: return false; // should not happen
396 }
397
398 BOARD_ITEM* parentA = aItemA ? aItemA->BoardItem() : nullptr;
399 BOARD_ITEM* parentB = aItemB ? aItemB->BoardItem() : nullptr;
400 DRC_CONSTRAINT hostConstraint;
401
402 // A track being routed may not have a BOARD_ITEM associated yet.
403 if( aItemA && !parentA )
404 parentA = getBoardItem( aItemA, aLayer, 0 );
405
406 if( aItemB && !parentB )
407 parentB = getBoardItem( aItemB, aLayer, 1 );
408
409 if( parentA )
410 hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, ToLAYER_ID( aLayer ) );
411
412 if( hostConstraint.IsNull() )
413 return false;
414
415 if( hostConstraint.GetSeverity() == RPT_SEVERITY_IGNORE )
416 {
417 aConstraint->m_Value.SetMin( -1 );
418 aConstraint->m_RuleName = hostConstraint.GetName();
419 aConstraint->m_Type = aType;
420 return true;
421 }
422
423 switch ( aType )
424 {
437 aConstraint->m_Value = hostConstraint.GetValue();
438 aConstraint->m_RuleName = hostConstraint.GetName();
439 aConstraint->m_Type = aType;
440 return true;
441
442 default:
443 return false;
444 }
445}
446
447
448void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems )
449{
450 int n_pruned = 0;
451 std::set<const PNS::ITEM*> remainingItems( aItems.begin(), aItems.end() );
452
453/* We need to carefully check both A and B item pointers in the cache against dirty/invalidated
454 items in the set, as the clearance relation is commutative ( CL[a,b] == CL[b,a] ). The code
455 below is a bit ugly, but works in O(n*log(m)) and is run once or twice during ROUTER::Move() call
456 - so I hope it still gets better performance than no cache at all */
457 for( auto it = m_clearanceCache.begin(); it != m_clearanceCache.end(); )
458 {
459 bool dirty = remainingItems.find( it->first.A ) != remainingItems.end();
460 dirty |= remainingItems.find( it->first.B) != remainingItems.end();
461
462 if( dirty )
463 {
464 it = m_clearanceCache.erase( it );
465 n_pruned++;
466 } else
467 it++;
468 }
469#if 0
470 printf("ClearCache : n_pruned %d\n", n_pruned );
471#endif
472}
473
474
476{
477 m_clearanceCache.clear();
478 m_tempClearanceCache.clear();
479}
480
481
483{
484 m_tempClearanceCache.clear();
485}
486
487
489 bool aUseClearanceEpsilon )
490{
491 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
492
493 // Search cache (used for actual board items)
494 auto it = m_clearanceCache.find( key );
495
496 if( it != m_clearanceCache.end() )
497 return it->second;
498
499 // Search cache (used for temporary items within an algorithm)
500 it = m_tempClearanceCache.find( key );
501
502 if( it != m_tempClearanceCache.end() )
503 return it->second;
504
505 PNS::CONSTRAINT constraint;
506 int rv = 0;
507 LAYER_RANGE layers;
508
509 if( !aB )
510 layers = aA->Layers();
511 else if( isEdge( aA ) )
512 layers = aB->Layers();
513 else if( isEdge( aB ) )
514 layers = aA->Layers();
515 else
516 layers = aA->Layers().Intersection( aB->Layers() );
517
518 // Normalize layer range (no -1 magic numbers)
520
521 for( int layer = layers.Start(); layer <= layers.End(); ++layer )
522 {
523 if( IsDrilledHole( aA ) && IsDrilledHole( aB ) )
524 {
525 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer, &constraint ) )
526 {
527 if( constraint.m_Value.Min() > rv )
528 rv = constraint.m_Value.Min();
529 }
530 }
531 else if( isHole( aA ) || isHole( aB ) )
532 {
533 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
534 {
535 if( constraint.m_Value.Min() > rv )
536 rv = constraint.m_Value.Min();
537 }
538 }
539
540 // No 'else'; plated holes get both HOLE_CLEARANCE and CLEARANCE
541 if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
542 {
543 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
544 {
545 if( constraint.m_Value.Min() > rv )
546 rv = constraint.m_Value.Min();
547 }
548 }
549
550 // No 'else'; non-plated milled holes get both HOLE_CLEARANCE and EDGE_CLEARANCE
551 if( isEdge( aA ) || IsNonPlatedSlot( aA ) || isEdge( aB ) || IsNonPlatedSlot( aB ) )
552 {
553 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
554 {
555 if( constraint.m_Value.Min() > rv )
556 rv = constraint.m_Value.Min();
557 }
558 }
559
560 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_PHYSICAL_CLEARANCE, aA, aB, layer, &constraint ) )
561 {
562 if( constraint.m_Value.Min() > rv )
563 rv = constraint.m_Value.Min();
564 }
565 }
566
567 if( aUseClearanceEpsilon && rv > 0 )
568 rv = std::max( 0, rv - m_clearanceEpsilon );
569
570 /*
571 * It makes no sense to put items that have no owning NODE in the cache - they can be
572 * allocated on stack and we can't really invalidate them in the cache when they are
573 * destroyed. Probably a better idea would be to use a static unique counter in PNS::ITEM
574 * constructor to generate the cache keys.
575 *
576 * However, algorithms DO greatly benefit from using the cache, so ownerless items need to be
577 * cached. In order to easily clear those only, a temporary cache is created. If this doesn't
578 * seem nice, an alternative is clearing the full cache once it reaches a certain size. Also
579 * not pretty, but VERY effective to keep things interactive.
580 */
581 if( aA && aB )
582 {
583 if ( aA->Owner() && aB->Owner() )
584 m_clearanceCache[ key ] = rv;
585 else
586 m_tempClearanceCache[ key ] = rv;
587 }
588
589 return rv;
590}
591
592
593bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth )
594{
595 VECTOR2I p;
596
597 assert( aItem->Owner() != nullptr );
598
599 auto tryGetTrackWidth =
600 []( PNS::ITEM* aPnsItem ) -> int
601 {
602 switch( aPnsItem->Kind() )
603 {
604 case PNS::ITEM::SEGMENT_T: return static_cast<PNS::SEGMENT*>( aPnsItem )->Width();
605 case PNS::ITEM::ARC_T: return static_cast<PNS::ARC*>( aPnsItem )->Width();
606 default: return -1;
607 }
608 };
609
610 int itemTrackWidth = tryGetTrackWidth( aItem );
611
612 if( itemTrackWidth > 0 )
613 {
614 *aInheritedWidth = itemTrackWidth;
615 return true;
616 }
617
618 switch( aItem->Kind() )
619 {
620 case PNS::ITEM::VIA_T: p = static_cast<PNS::VIA*>( aItem )->Pos(); break;
621 case PNS::ITEM::SOLID_T: p = static_cast<PNS::SOLID*>( aItem )->Pos(); break;
622 default: return false;
623 }
624
625 const PNS::JOINT* jt = static_cast<const PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
626
627 assert( jt != nullptr );
628
629 int mval = INT_MAX;
630
631 PNS::ITEM_SET linkedSegs( jt->CLinks() );
633
634 for( PNS::ITEM* item : linkedSegs.Items() )
635 {
636 int w = tryGetTrackWidth( item );
637
638 if( w > 0 )
639 mval = std::min( w, mval );
640 }
641
642 if( mval == INT_MAX )
643 return false;
644
645 *aInheritedWidth = mval;
646 return true;
647}
648
649
651 PNS::NET_HANDLE aNet )
652{
654 PNS::CONSTRAINT constraint;
655
656 if( aStartItem && m_startLayer < 0 )
657 m_startLayer = aStartItem->Layer();
658
659 aSizes.SetClearance( bds.m_MinClearance );
660 aSizes.SetMinClearance( bds.m_MinClearance );
661 aSizes.SetClearanceSource( _( "board minimum clearance" ) );
662
664 m_startLayer, &constraint ) )
665 {
666 if( constraint.m_Value.Min() > bds.m_MinClearance )
667 {
668 aSizes.SetClearance( constraint.m_Value.Min() );
669 aSizes.SetClearanceSource( constraint.m_RuleName );
670 }
671 }
672
673 int trackWidth = bds.m_TrackMinWidth;
674 bool found = false;
675 aSizes.SetWidthSource( _( "board minimum track width" ) );
676
677 if( bds.m_UseConnectedTrackWidth && !bds.m_TempOverrideTrackWidth && aStartItem != nullptr )
678 {
679 found = inheritTrackWidth( aStartItem, &trackWidth );
680
681 if( found )
682 aSizes.SetWidthSource( _( "existing track" ) );
683 }
684
685 if( !found && bds.UseNetClassTrack() && aStartItem )
686 {
688 m_startLayer, &constraint ) )
689 {
690 trackWidth = std::max( trackWidth, constraint.m_Value.Opt() );
691 found = true;
692
693 if( trackWidth == constraint.m_Value.Opt() )
694 aSizes.SetWidthSource( constraint.m_RuleName );
695 }
696 }
697
698 if( !found )
699 {
700 trackWidth = std::max( trackWidth, bds.GetCurrentTrackWidth() );
701
702 if( bds.UseNetClassTrack() )
703 aSizes.SetWidthSource( _( "netclass 'Default'" ) );
704 else if( trackWidth == bds.GetCurrentTrackWidth() )
705 aSizes.SetWidthSource( _( "user choice" ) );
706 }
707
708 aSizes.SetTrackWidth( trackWidth );
711
712 int viaDiameter = bds.m_ViasMinSize;
713 int viaDrill = bds.m_MinThroughDrill;
714
715 PNS::VIA dummyVia, coupledVia;
716
717 if( aStartItem )
718 {
719 dummyVia.SetNet( aStartItem->Net() );
720 coupledVia.SetNet( m_ruleResolver->DpCoupledNet( aStartItem->Net() ) );
721 }
722
723 if( bds.UseNetClassVia() && aStartItem ) // netclass value
724 {
726 nullptr, m_startLayer, &constraint ) )
727 {
728 viaDiameter = std::max( viaDiameter, constraint.m_Value.Opt() );
729 }
730
732 nullptr, m_startLayer, &constraint ) )
733 {
734 viaDrill = std::max( viaDrill, constraint.m_Value.Opt() );
735 }
736 }
737 else
738 {
739 viaDiameter = bds.GetCurrentViaSize();
740 viaDrill = bds.GetCurrentViaDrill();
741 }
742
743 aSizes.SetViaDiameter( viaDiameter );
744 aSizes.SetViaDrill( viaDrill );
745
746 int diffPairWidth = bds.m_TrackMinWidth;
747 int diffPairGap = bds.m_MinClearance;
748 int diffPairViaGap = bds.m_MinClearance;
749
750 aSizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
751 aSizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
752
753 found = false;
754
755 // First try to pick up diff pair width from starting track, if enabled
756 if( bds.m_UseConnectedTrackWidth && aStartItem )
757 found = inheritTrackWidth( aStartItem, &diffPairWidth );
758
759 // Next, pick up gap from netclass, and width also if we didn't get a starting width above
760 if( bds.UseNetClassDiffPair() && aStartItem )
761 {
763 nullptr, m_startLayer, &constraint ) )
764 {
765 diffPairWidth = std::max( diffPairWidth, constraint.m_Value.Opt() );
766
767 if( diffPairWidth == constraint.m_Value.Opt() )
768 aSizes.SetDiffPairWidthSource( constraint.m_RuleName );
769 }
770
772 nullptr, m_startLayer, &constraint ) )
773 {
774 diffPairGap = std::max( diffPairGap, constraint.m_Value.Opt() );
775 diffPairViaGap = std::max( diffPairViaGap, constraint.m_Value.Opt() );
776
777 if( diffPairGap == constraint.m_Value.Opt() )
778 aSizes.SetDiffPairGapSource( constraint.m_RuleName );
779 }
780 }
781 else
782 {
783 diffPairWidth = bds.GetCurrentDiffPairWidth();
784 diffPairGap = bds.GetCurrentDiffPairGap();
785 diffPairViaGap = bds.GetCurrentDiffPairViaGap();
786
787 aSizes.SetDiffPairWidthSource( _( "user choice" ) );
788 aSizes.SetDiffPairGapSource( _( "user choice" ) );
789 }
790
791 aSizes.SetDiffPairWidth( diffPairWidth );
792 aSizes.SetDiffPairGap( diffPairGap );
793 aSizes.SetDiffPairViaGap( diffPairViaGap );
794 aSizes.SetDiffPairViaGapSameAsTraceGap( false );
795
796 int holeToHoleMin = bds.m_HoleToHoleMin;
797
799 &dummyVia, UNDEFINED_LAYER, &constraint ) )
800 {
801 holeToHoleMin = constraint.m_Value.Min();
802 }
803
804 aSizes.SetHoleToHole( holeToHoleMin );
805
807 &coupledVia, UNDEFINED_LAYER, &constraint ) )
808 {
809 holeToHoleMin = constraint.m_Value.Min();
810 }
811
812 aSizes.SetDiffPairHoleToHole( holeToHoleMin );
813
814 return true;
815}
816
817
818int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const
819{
821 return 0;
822
824
825 return stackup.GetLayerDistance( ToLAYER_ID( aFirstLayer ), ToLAYER_ID( aSecondLayer ) );
826}
827
828
830{
831 return m_board->DpCoupledNet( static_cast<NETINFO_ITEM*>( aNet ) );
832}
833
834
836{
837 return m_routerIface->GetNetCode( aNet );
838}
839
840
842{
843 return m_routerIface->GetNetName( aNet );
844}
845
846
848{
849 wxString refName;
850
851 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
852 refName = net->GetNetname();
853
854 wxString dummy1;
855
856 return m_board->MatchDpSuffix( refName, dummy1 );
857}
858
859
861 PNS::NET_HANDLE& aNetN )
862{
863 if( !aItem || !aItem->Net() )
864 return false;
865
866 wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
867 wxString netNameN, netNameCoupled;
868
869 int r = m_board->MatchDpSuffix( netNameP, netNameCoupled );
870
871 if( r == 0 )
872 {
873 return false;
874 }
875 else if( r == 1 )
876 {
877 netNameN = netNameCoupled;
878 }
879 else
880 {
881 netNameN = netNameP;
882 netNameP = netNameCoupled;
883 }
884
885 PNS::NET_HANDLE netInfoP = m_board->FindNet( netNameP );
886 PNS::NET_HANDLE netInfoN = m_board->FindNet( netNameN );
887
888 if( !netInfoP || !netInfoN )
889 return false;
890
891 aNetP = netInfoP;
892 aNetN = netInfoN;
893
894 return true;
895}
896
897
899{
900public:
903 m_view( nullptr ),
904 m_items( nullptr ),
905 m_depth( 0 )
906 {
907 SetView( aView );
908 }
909
911 {
913 delete m_items;
914 }
915
916 void SetView( KIGFX::VIEW* aView )
917 {
918 Clear();
919 delete m_items;
920 m_items = nullptr;
921 m_view = aView;
922
923 if( m_view == nullptr )
924 return;
925
926 if( m_view->GetGAL() )
928
931 m_view->Add( m_items );
932 }
933
934 void AddPoint( const VECTOR2I& aP, const KIGFX::COLOR4D& aColor, int aSize,
935 const wxString& aName = wxT( "" ),
936 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
937
938 {
940
941 sh.SetWidth( 10000 );
942
943 sh.Append( aP.x - aSize, aP.y - aSize );
944 sh.Append( aP.x + aSize, aP.y + aSize );
945 sh.Append( aP.x, aP.y );
946 sh.Append( aP.x - aSize, aP.y + aSize );
947 sh.Append( aP.x + aSize, aP.y - aSize );
948
949 AddShape( &sh, aColor, sh.Width(), aName, aSrcLoc );
950 }
951
952 void AddItem( const PNS::ITEM* aItem, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
953 const wxString& aName = wxT( "" ),
954 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
955 {
956 if( !m_view || !aItem )
957 return;
958
959 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
960
961 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
962 pitem->SetWidth( aOverrideWidth );
963 pitem->SetDepth( nextDepth() );
964
965 m_items->Add( pitem );
967 }
968
969 void AddShape( const BOX2I& aBox, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
970 const wxString& aName = wxT( "" ),
971 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
972 {
974 l.SetWidth( aOverrideWidth );
975
976 VECTOR2I o = aBox.GetOrigin();
977 VECTOR2I s = aBox.GetSize();
978
979 l.Append( o );
980 l.Append( o.x + s.x, o.y );
981 l.Append( o.x + s.x, o.y + s.y );
982 l.Append( o.x, o.y + s.y );
983 l.Append( o );
984
985 AddShape( &l, aColor, aOverrideWidth, aName, aSrcLoc );
986 }
987
988 void AddShape( const SHAPE* aShape, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
989 const wxString& aName = wxT( "" ),
990 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
991 {
992 if( !m_view || !aShape )
993 return;
994
995 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_view );
996
997 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
998 pitem->SetWidth( aOverrideWidth );
999 pitem->SetDepth( nextDepth() );
1000
1001 m_items->Add( pitem );
1002 m_view->Update( m_items );
1003 }
1004
1005 void Clear() override
1006 {
1007 if( m_view && m_items )
1008 {
1009 m_items->FreeItems();
1010 m_view->Update( m_items );
1011
1012 if( m_view->GetGAL() )
1014 }
1015 }
1016
1017private:
1018 double nextDepth()
1019 {
1020 // Use different depths so that the transculent shapes won't overwrite each other.
1021
1022 m_depth++;
1023
1024 if( m_depth >= 0 && m_view->GetGAL() )
1026
1027 return m_depth;
1028 }
1029
1032
1033 double m_depth;
1034};
1035
1036
1038{
1039 return m_debugDecorator;
1040}
1041
1042
1044{
1045 m_ruleResolver = nullptr;
1046 m_board = nullptr;
1047 m_world = nullptr;
1048 m_debugDecorator = nullptr;
1049 m_startLayer = -1;
1050}
1051
1052
1054{
1055 m_tool = nullptr;
1056 m_view = nullptr;
1057 m_previewItems = nullptr;
1058 m_commitFlags = 0;
1059}
1060
1061
1063{
1064 delete m_ruleResolver;
1065 delete m_debugDecorator;
1066}
1067
1068
1070{
1071 if( m_previewItems )
1072 {
1074 delete m_previewItems;
1075 }
1076}
1077
1078
1079std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1080{
1081 LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 );
1082
1083 // ignore non-copper pads except for those with holes
1084 if( ( aPad->GetLayerSet() & LSET::AllCuMask() ).none() && aPad->GetDrillSize().x == 0 )
1085 return nullptr;
1086
1087 switch( aPad->GetAttribute() )
1088 {
1089 case PAD_ATTRIB::PTH:
1090 case PAD_ATTRIB::NPTH:
1091 break;
1092
1093 case PAD_ATTRIB::CONN:
1094 case PAD_ATTRIB::SMD:
1095 {
1096 LSET lmsk = aPad->GetLayerSet();
1097 bool is_copper = false;
1098
1099 for( int i = 0; i < MAX_CU_LAYERS; i++ )
1100 {
1101 if( lmsk[i] )
1102 {
1103 is_copper = true;
1104
1105 if( aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1106 layers = LAYER_RANGE( i );
1107
1108 break;
1109 }
1110 }
1111
1112 if( !is_copper )
1113 return nullptr;
1114
1115 break;
1116 }
1117
1118 default:
1119 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1120 return nullptr;
1121 }
1122
1123 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1124
1125 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1126 solid->SetRoutable( false );
1127
1128 solid->SetLayers( layers );
1129 solid->SetNet( aPad->GetNet() );
1130 solid->SetParent( aPad );
1131 solid->SetPadToDie( aPad->GetPadToDieLength() );
1132 solid->SetOrientation( aPad->GetOrientation() );
1133
1134 if( aPad->IsFreePad() )
1135 solid->SetIsFreePad();
1136
1137 VECTOR2I wx_c = aPad->ShapePos();
1138 VECTOR2I offset = aPad->GetOffset();
1139
1140 VECTOR2I c( wx_c.x, wx_c.y );
1141
1142 RotatePoint( offset, aPad->GetOrientation() );
1143
1144 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1145 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1146
1147 if( aPad->GetDrillSize().x > 0 )
1148 solid->SetHole( new PNS::HOLE( aPad->GetEffectiveHoleShape()->Clone() ) );
1149
1150 // We generate a single SOLID for a pad, so we have to treat it as ALWAYS_FLASHED and then
1151 // perform layer-specific flashing tests internally.
1152 const std::shared_ptr<SHAPE>& shape = aPad->GetEffectiveShape( UNDEFINED_LAYER,
1153 FLASHING::ALWAYS_FLASHED );
1154
1155 if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 )
1156 {
1157 std::vector<const SHAPE*> subshapes;
1158 shape->GetIndexableSubshapes( subshapes );
1159
1160 solid->SetShape( subshapes[0]->Clone() );
1161 }
1162 // For anything that's not a single shape we use a polygon. Multiple shapes have a tendency
1163 // to confuse the hull generator. https://gitlab.com/kicad/code/kicad/-/issues/15553
1164 else
1165 {
1166 const std::shared_ptr<SHAPE_POLY_SET>& poly = aPad->GetEffectivePolygon( ERROR_OUTSIDE );
1167
1168 if( poly->OutlineCount() )
1169 solid->SetShape( new SHAPE_SIMPLE( poly->Outline( 0 ) ) );
1170 }
1171
1172 return solid;
1173}
1174
1175
1176std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1177{
1178 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1179 aTrack->GetNet() );
1180
1181 segment->SetWidth( aTrack->GetWidth() );
1182 segment->SetLayers( LAYER_RANGE( aTrack->GetLayer() ) );
1183 segment->SetParent( aTrack );
1184
1185 if( aTrack->IsLocked() )
1186 segment->Mark( PNS::MK_LOCKED );
1187
1188 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aTrack->GetParentGroup() ) )
1189 {
1190 if( !generator->HasFlag( IN_EDIT ) )
1191 segment->Mark( PNS::MK_LOCKED );
1192 }
1193
1194 return segment;
1195}
1196
1197
1198std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1199{
1200 auto arc = std::make_unique<PNS::ARC>( SHAPE_ARC( aArc->GetStart(), aArc->GetMid(),
1201 aArc->GetEnd(), aArc->GetWidth() ),
1202 aArc->GetNet() );
1203
1204 arc->SetLayers( LAYER_RANGE( aArc->GetLayer() ) );
1205 arc->SetParent( aArc );
1206
1207 if( aArc->IsLocked() )
1208 arc->Mark( PNS::MK_LOCKED );
1209
1210 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aArc->GetParentGroup() ) )
1211 {
1212 if( !generator->HasFlag( IN_EDIT ) )
1213 arc->Mark( PNS::MK_LOCKED );
1214 }
1215
1216 return arc;
1217}
1218
1219
1220std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1221{
1222 PCB_LAYER_ID top, bottom;
1223 aVia->LayerPair( &top, &bottom );
1224
1225 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1226 LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ),
1227 aVia->GetWidth(),
1228 aVia->GetDrillValue(),
1229 aVia->GetNet(),
1230 aVia->GetViaType() );
1231
1232 via->SetParent( aVia );
1233
1234 if( aVia->IsLocked() )
1235 via->Mark( PNS::MK_LOCKED );
1236
1237 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aVia->GetParentGroup() ) )
1238 {
1239 if( !generator->HasFlag( IN_EDIT ) )
1240 via->Mark( PNS::MK_LOCKED );
1241 }
1242
1243 via->SetIsFree( aVia->GetIsFree() );
1244 via->SetHole( PNS::HOLE::MakeCircularHole( aVia->GetPosition(), aVia->GetDrillValue() / 2 ) );
1245
1246 return via;
1247}
1248
1249
1250bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1251{
1252 static wxString msg;
1253 SHAPE_POLY_SET* poly;
1254
1255 if( !aZone->GetIsRuleArea() )
1256 return false;
1257
1258 LSET layers = aZone->GetLayerSet();
1259
1260 poly = aZone->Outline();
1261 poly->CacheTriangulation( false );
1262
1263 if( !poly->IsTriangulationUpToDate() )
1264 {
1265 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1266 msg.Printf( _( "%s is malformed." ), aZone->GetItemDescription( &unitsProvider, true ) );
1267
1268 KIDIALOG dlg( nullptr, msg, KIDIALOG::KD_WARNING );
1269 dlg.ShowDetailedText( _( "This zone cannot be handled by the router.\n"
1270 "Please verify it is not a self-intersecting polygon." ) );
1271 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1272 dlg.ShowModal();
1273
1274 return false;
1275 }
1276
1277 for( int layer = F_Cu; layer <= B_Cu; layer++ )
1278 {
1279 if( !layers[ layer ] )
1280 continue;
1281
1282 for( int polyId = 0; polyId < poly->TriangulatedPolyCount(); polyId++ )
1283 {
1284 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( polyId );
1285
1286 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1287 {
1288 VECTOR2I a, b, c;
1289 tri->GetTriangle( i, a, b, c );
1290 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1291
1292 triShape->Append( a );
1293 triShape->Append( b );
1294 triShape->Append( c );
1295
1296 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1297
1298 solid->SetLayer( layer );
1299 solid->SetNet( nullptr );
1300 solid->SetParent( aZone );
1301 solid->SetShape( triShape );
1302 solid->SetIsCompoundShapePrimitive();
1303 solid->SetRoutable( false );
1304
1305 aWorld->Add( std::move( solid ) );
1306 }
1307 }
1308 }
1309
1310 return true;
1311}
1312
1313
1315{
1316 if( !IsCopperLayer( aLayer ) )
1317 return false;
1318
1319 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1320 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1321
1322 solid->SetLayer( aLayer );
1323 solid->SetNet( nullptr );
1324 solid->SetParent( aText );
1325 solid->SetShape( shape ); // takes ownership
1326 solid->SetRoutable( false );
1327
1328 SHAPE_POLY_SET cornerBuffer;
1329
1330 aText->TransformShapeToPolygon( cornerBuffer, aText->GetLayer(), 0,
1332
1333 if( !cornerBuffer.OutlineCount() )
1334 return false;
1335
1336 for( const VECTOR2I& pt : cornerBuffer.Outline( 0 ).CPoints() )
1337 shape->Append( pt );
1338
1339 aWorld->Add( std::move( solid ) );
1340
1341 return true;
1342}
1343
1344
1346{
1347 if( aItem->GetLayer() == Edge_Cuts
1348 || aItem->GetLayer() == Margin
1349 || IsCopperLayer( aItem->GetLayer() ) )
1350 {
1351 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1352
1353 for( SHAPE* shape : shapes )
1354 {
1355 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1356
1357 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1358 {
1359 solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
1360 solid->SetRoutable( false );
1361 }
1362 else
1363 {
1364 solid->SetLayer( aItem->GetLayer() );
1365 }
1366
1367 if( aItem->GetLayer() == Edge_Cuts )
1368 {
1369 switch( shape->Type() )
1370 {
1371 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1372 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1373 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1374 default: /* remaining shapes don't have width */ break;
1375 }
1376 }
1377
1378 solid->SetAnchorPoints( aItem->GetConnectionPoints() );
1379 solid->SetNet( aItem->GetNet() );
1380 solid->SetParent( aItem );
1381 solid->SetShape( shape ); // takes ownership
1382
1383 if( shapes.size() > 1 )
1384 solid->SetIsCompoundShapePrimitive();
1385
1386 aWorld->Add( std::move( solid ) );
1387 }
1388
1389 return true;
1390 }
1391
1392 return false;
1393}
1394
1395
1397{
1398 m_board = aBoard;
1399 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1400}
1401
1402
1404{
1405 if( !m_view )
1406 return false;
1407
1408 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1409 {
1410 if( m_view->IsLayerVisible( i ) )
1411 return true;
1412 }
1413
1414 return false;
1415}
1416
1417
1418bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1419{
1421 if( aLayer < 0 )
1422 return true;
1423
1424 if( aItem->Parent() )
1425 {
1426 switch( aItem->Parent()->Type() )
1427 {
1428 case PCB_VIA_T:
1429 {
1430 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1431
1432 return via->FlashLayer( ToLAYER_ID( aLayer ) );
1433 }
1434
1435 case PCB_PAD_T:
1436 {
1437 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1438
1439 return pad->FlashLayer( ToLAYER_ID( aLayer ) );
1440 }
1441
1442 default:
1443 break;
1444 }
1445 }
1446
1447 return aItem->Layers().Overlaps( aLayer );
1448}
1449
1450
1452 const LAYER_RANGE& aLayer ) const
1453{
1454 LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
1455
1456 if( aItem->Parent() )
1457 {
1458 switch( aItem->Parent()->Type() )
1459 {
1460 case PCB_VIA_T:
1461 {
1462 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1463
1464 for( int layer = test.Start(); layer <= test.End(); ++layer )
1465 {
1466 if( via->FlashLayer( ToLAYER_ID( layer ) ) )
1467 return true;
1468 }
1469
1470 return false;
1471 }
1472
1473 case PCB_PAD_T:
1474 {
1475 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1476
1477 for( int layer = test.Start(); layer <= test.End(); ++layer )
1478 {
1479 if( pad->FlashLayer( ToLAYER_ID( layer ) ) )
1480 return true;
1481 }
1482
1483 return false;
1484 }
1485
1486 default:
1487 break;
1488 }
1489 }
1490
1491 return test.Start() <= test.End();
1492}
1493
1494
1496{
1497 // by default, all items are visible (new ones created by the router have parent == NULL
1498 // as they have not been committed yet to the BOARD)
1499 if( !m_view || !aItem->Parent() )
1500 return true;
1501
1502 BOARD_ITEM* item = aItem->Parent();
1503 bool isOnVisibleLayer = true;
1504 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1505
1506 if( settings->GetHighContrast() )
1507 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1508
1509 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1510 {
1511 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
1512 {
1513 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1514 return true;
1515 }
1516 }
1517
1518 // Items hidden in the router are not hidden on the board
1519 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1520 return true;
1521
1522 return false;
1523}
1524
1525
1527{
1528 if( !m_board )
1529 {
1530 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1531 return;
1532 }
1533
1534 int worstClearance = m_board->GetMaxClearanceValue();
1535
1536 m_world = aWorld;
1537
1538 for( BOARD_ITEM* gitem : m_board->Drawings() )
1539 {
1540 if ( gitem->Type() == PCB_SHAPE_T || gitem->Type() == PCB_TEXTBOX_T )
1541 {
1542 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1543 }
1544 else if( gitem->Type() == PCB_TEXT_T )
1545 {
1546 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1547 }
1548 }
1549
1550 SHAPE_POLY_SET buffer;
1551 SHAPE_POLY_SET* boardOutline = nullptr;
1552
1553 if( m_board->GetBoardPolygonOutlines( buffer ) )
1554 boardOutline = &buffer;
1555
1556 for( ZONE* zone : m_board->Zones() )
1557 {
1558 syncZone( aWorld, zone, boardOutline );
1559 }
1560
1561 for( FOOTPRINT* footprint : m_board->Footprints() )
1562 {
1563 for( PAD* pad : footprint->Pads() )
1564 {
1565 if( std::unique_ptr<PNS::SOLID> solid = syncPad( pad ) )
1566 aWorld->Add( std::move( solid ) );
1567
1568 std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
1569
1570 if( clearanceOverride.has_value() )
1571 worstClearance = std::max( worstClearance, clearanceOverride.value() );
1572
1573 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1574 {
1575 std::unique_ptr<SHAPE> hole;
1576 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1577 aWorld->AddEdgeExclusion( std::move( hole ) );
1578 }
1579 }
1580
1581 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1582 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1583
1584 for( ZONE* zone : footprint->Zones() )
1585 syncZone( aWorld, zone, boardOutline );
1586
1587 for( PCB_FIELD* field : footprint->Fields() )
1588 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1589
1590 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1591 {
1592 if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_TEXTBOX_T )
1593 {
1594 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1595 }
1596 else if( item->Type() == PCB_TEXT_T )
1597 {
1598 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1599 }
1600 }
1601 }
1602
1603 for( PCB_TRACK* t : m_board->Tracks() )
1604 {
1605 KICAD_T type = t->Type();
1606
1607 if( type == PCB_TRACE_T )
1608 {
1609 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1610 aWorld->Add( std::move( segment ) );
1611 }
1612 else if( type == PCB_ARC_T )
1613 {
1614 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1615 aWorld->Add( std::move( arc ) );
1616 }
1617 else if( type == PCB_VIA_T )
1618 {
1619 if( std::unique_ptr<PNS::VIA> via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1620 aWorld->Add( std::move( via ) );
1621 }
1622 }
1623
1624 // NB: if this were ever to become a long-lived object we would need to dirty its
1625 // clearance cache here....
1626 delete m_ruleResolver;
1628
1630 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1631}
1632
1633
1635{
1636 for( BOARD_ITEM* item : m_hiddenItems )
1637 m_view->SetVisible( item, true );
1638
1639 m_hiddenItems.clear();
1640
1641 if( m_previewItems )
1642 {
1645 }
1646
1647 if( m_debugDecorator )
1649}
1650
1651
1653{
1654 m_debugDecorator = aDec;
1655}
1656
1657
1658void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, int aFlags )
1659{
1660 if( aItem->IsVirtual() )
1661 return;
1662
1663 if( ZONE* zone = dynamic_cast<ZONE*>( aItem->Parent() ) )
1664 {
1665 if( zone->GetIsRuleArea() )
1666 aFlags |= PNS_SEMI_SOLID;
1667 }
1668
1669 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view, aFlags );
1670
1671 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1673 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1674
1675 if( aClearance >= 0 )
1676 {
1677 pitem->SetClearance( aClearance );
1678
1679 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1680
1681 switch( settings->m_Display.m_TrackClearance )
1682 {
1685 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1686 break;
1687
1689 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1690 break;
1691
1692 case SHOW_WHILE_ROUTING:
1693 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1694 break;
1695
1696 default:
1697 pitem->ShowClearance( false );
1698 break;
1699 }
1700 }
1701
1702 m_previewItems->Add( pitem );
1704}
1705
1706
1707void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1708{
1709 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, m_view );
1711
1712 COLOR4D color;
1713
1714 if( aImportance >= 1 )
1715 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1716 else if( aImportance == 0 )
1717 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1718
1719 pitem->SetColor( color );
1720
1721 m_previewItems->Add( pitem );
1723}
1724
1725
1727{
1728 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, m_view );
1729
1730 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1731 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1732 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1733 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1734 COLOR4D color = defaultColor;
1735
1736 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1737 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1738 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1739 std::map<wxString, KIGFX::COLOR4D>& ncColors = rs->GetNetclassColorMap();
1740 const std::map<int, wxString>& ncMap = connectivity->GetNetclassMap();
1741 int netCode = -1;
1742
1743 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
1744 netCode = net->GetNetCode();
1745
1746 if( colorByNet && netColors.count( netCode ) )
1747 color = netColors.at( netCode );
1748 else if( colorByNet && ncMap.count( netCode ) && ncColors.count( ncMap.at( netCode ) ) )
1749 color = ncColors.at( ncMap.at( netCode ) );
1750 else
1751 color = defaultColor;
1752
1753 if( color == COLOR4D::UNSPECIFIED )
1754 color = defaultColor;
1755
1756 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
1757
1758 m_previewItems->Add( pitem );
1760}
1761
1762
1764{
1765 BOARD_ITEM* parent = aItem->Parent();
1766
1767 if( parent )
1768 {
1769 if( m_view->IsVisible( parent ) )
1770 m_hiddenItems.insert( parent );
1771
1772 m_view->SetVisible( parent, false );
1773 m_view->Update( parent, KIGFX::APPEARANCE );
1774
1775 for( ZONE* td : m_board->Zones() )
1776 {
1777 if( td->IsTeardropArea()
1778 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
1779 && td->Outline()->Collide( aItem->Shape() ) )
1780 {
1781 m_view->SetVisible( td, false );
1783 }
1784 }
1785 }
1786}
1787
1788
1790{
1791}
1792
1793
1795{
1796 BOARD_ITEM* parent = aItem->Parent();
1797
1798 if( aItem->OfKind( PNS::ITEM::SOLID_T ) )
1799 {
1800 PAD* pad = static_cast<PAD*>( parent );
1801 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1802
1803 m_fpOffsets[ pad ].p_old = pos;
1804 return;
1805 }
1806
1807 if( parent )
1808 {
1809 m_commit->Remove( parent );
1810 }
1811}
1812
1813
1815{
1816}
1817
1818
1820{
1821 BOARD_ITEM* board_item = aItem->Parent();
1822
1823 switch( aItem->Kind() )
1824 {
1825 case PNS::ITEM::ARC_T:
1826 {
1827 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1828 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
1829 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape() );
1830
1831 m_commit->Modify( arc_board );
1832
1833 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
1834 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
1835 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
1836 arc_board->SetWidth( arc->Width() );
1837 break;
1838 }
1839
1841 {
1842 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1843 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
1844 const SEG& s = seg->Seg();
1845
1846 m_commit->Modify( track );
1847
1848 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1849 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1850 track->SetWidth( seg->Width() );
1851 break;
1852 }
1853
1854 case PNS::ITEM::VIA_T:
1855 {
1856 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
1857 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1858
1859 m_commit->Modify( via_board );
1860
1861 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1862 via_board->SetWidth( via->Diameter() );
1863 via_board->SetDrill( via->Drill() );
1864 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
1865 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1866 via_board->SetIsFree( via->IsFree() );
1867 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1868 ToLAYER_ID( via->Layers().End() ) );
1869 break;
1870 }
1871
1872 case PNS::ITEM::SOLID_T:
1873 {
1874 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1875 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1876
1877 // Don't add to commit; we'll add the parent footprints when processing the m_fpOffsets
1878
1879 m_fpOffsets[pad].p_old = pad->GetPosition();
1880 m_fpOffsets[pad].p_new = pos;
1881 break;
1882 }
1883
1884 default:
1885 m_commit->Modify( aItem->Parent() );
1886 break;
1887 }
1888}
1889
1890
1892{
1893 modifyBoardItem( aItem );
1894}
1895
1896
1898{
1899}
1900
1901
1903{
1904 BOARD_CONNECTED_ITEM* newBoardItem = nullptr;
1905 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem->Net() );
1906
1907 if( !net )
1909
1910 switch( aItem->Kind() )
1911 {
1912 case PNS::ITEM::ARC_T:
1913 {
1914 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1915 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape() ) );
1916 new_arc->SetWidth( arc->Width() );
1917 new_arc->SetLayer( ToLAYER_ID( arc->Layers().Start() ) );
1918 new_arc->SetNet( net );
1919 newBoardItem = new_arc;
1920 break;
1921 }
1922
1924 {
1925 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1926 PCB_TRACK* track = new PCB_TRACK( m_board );
1927 const SEG& s = seg->Seg();
1928 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1929 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1930 track->SetWidth( seg->Width() );
1931 track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
1932 track->SetNet( net );
1933 newBoardItem = track;
1934 break;
1935 }
1936
1937 case PNS::ITEM::VIA_T:
1938 {
1939 PCB_VIA* via_board = new PCB_VIA( m_board );
1940 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1941 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1942 via_board->SetWidth( via->Diameter() );
1943 via_board->SetDrill( via->Drill() );
1944 via_board->SetNet( net );
1945 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1946 via_board->SetIsFree( via->IsFree() );
1947 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1948 ToLAYER_ID( via->Layers().End() ) );
1949 newBoardItem = via_board;
1950 break;
1951 }
1952
1953 case PNS::ITEM::SOLID_T:
1954 {
1955 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1956 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1957
1958 m_fpOffsets[pad].p_new = pos;
1959 return nullptr;
1960 }
1961
1962 default:
1963 return nullptr;
1964 }
1965
1966 if( net->GetNetCode() <= 0 )
1967 {
1968 NETINFO_ITEM* newNetInfo = newBoardItem->GetNet();
1969
1970 newNetInfo->SetParent( m_board );
1971 newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->m_DefaultNetClass );
1972 }
1973
1974 return newBoardItem;
1975}
1976
1977
1979{
1980 BOARD_CONNECTED_ITEM* boardItem = createBoardItem( aItem );
1981
1982 if( boardItem )
1983 {
1984 aItem->SetParent( boardItem );
1985 boardItem->ClearFlags();
1986
1987 m_commit->Add( boardItem );
1988 }
1989}
1990
1991
1993{
1994 std::set<FOOTPRINT*> processedFootprints;
1995
1996 EraseView();
1997
1998 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
1999 {
2000 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
2001 FOOTPRINT* footprint = pad->GetParentFootprint();
2002 VECTOR2I p_orig = footprint->GetPosition();
2003 VECTOR2I p_new = p_orig + offset;
2004
2005 if( processedFootprints.find( footprint ) != processedFootprints.end() )
2006 continue;
2007
2008 processedFootprints.insert( footprint );
2009 m_commit->Modify( footprint );
2010 footprint->SetPosition( p_new );
2011 }
2012
2013 m_fpOffsets.clear();
2014
2015 m_commit->Push( _( "Routing" ), m_commitFlags );
2016 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2017}
2018
2019
2021{
2022 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
2023}
2024
2025
2027{
2028 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
2029
2030 if( m_previewItems )
2031 {
2033 delete m_previewItems;
2034 }
2035
2036 m_view = aView;
2039
2040 if(m_view)
2042
2043 delete m_debugDecorator;
2044
2045 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR();
2046 m_debugDecorator = dec;
2047
2048 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2049
2050 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2051 dec->SetView( m_view );
2052}
2053
2054
2056{
2057 if( aNet )
2058 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2059 else
2060 return -1;
2061}
2062
2063
2065{
2066 if( aNet )
2067 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2068 else
2069 return wxEmptyString;
2070}
2071
2072
2074{
2075 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2076}
2077
2078
2080{
2082}
2083
2084
2086{
2087 return m_ruleResolver;
2088}
2089
2090
2092{
2093 m_tool = aTool;
2094 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2095}
int color
Definition: DXF_plotter.cpp:58
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
std::shared_ptr< DRC_ENGINE > m_DRCEngine
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
BOARD_STACKUP & GetStackupDescriptor()
bool UseNetClassTrack() const
Return true if netclass values should be used to obtain appropriate track width.
bool UseNetClassDiffPair() const
Return true if netclass values should be used to obtain appropriate diff pair dimensions.
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:240
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:93
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:307
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:276
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:264
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:245
virtual bool IsLocked() const
Definition: board_item.cpp:75
virtual bool IsOnCopperLayer() const
Definition: board_item.h:153
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:289
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2473
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:1971
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1900
const ZONES & Zones() const
Definition: board.h:334
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition: board.cpp:880
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition: board.cpp:1921
const FOOTPRINTS & Footprints() const
Definition: board.h:330
const TRACKS & Tracks() const
Definition: board.h:328
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:874
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:474
const DRAWINGS & Drawings() const
Definition: board.h:332
const Vec & GetOrigin() const
Definition: box2.h:200
const SizeVec & GetSize() const
Definition: box2.h:196
wxString GetName() const
Definition: drc_rule.h:150
SEVERITY GetSeverity() const
Definition: drc_rule.h:163
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:142
bool IsNull() const
Definition: drc_rule.h:137
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:319
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2343
bool IsNetTie() const
Definition: footprint.h:286
VECTOR2I GetPosition() const override
Definition: footprint.h:213
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
@ KD_WARNING
Definition: kidialog.h:46
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
double GetMinDepth() const
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:78
NET_COLOR_MODE GetNetColorMode() const
Definition: pcb_painter.h:126
COLOR4D GetColor(const VIEW_ITEM *aItem, int aLayer) const override
Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer using curr...
std::map< int, KIGFX::COLOR4D > & GetNetColorMap()
Definition: pcb_painter.h:131
std::map< wxString, KIGFX::COLOR4D > & GetNetclassColorMap()
Definition: pcb_painter.h:129
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > & GetHighlightNetCodes() const
Return the netcode of currently highlighted net.
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
bool GetHighContrast() const
Extend VIEW_ITEM by possibility of grouping items into a single object.
Definition: view_group.h:48
void FreeItems()
Free all the items that were added to the group.
Definition: view_group.cpp:204
virtual void SetLayer(int aLayer)
Set layer used to draw the group.
Definition: view_group.h:99
virtual void Add(VIEW_ITEM *aItem)
Add an item to the group.
Definition: view_group.cpp:58
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:141
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
double GetScale() const
Definition: view.h:277
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:317
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1687
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:203
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:418
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:221
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1657
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1614
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
int Start() const
Definition: pns_layerset.h:82
int End() const
Definition: pns_layerset.h:87
LAYER_RANGE Intersection(const LAYER_RANGE &aOther) const
Shortcut for comparisons/overlap tests.
Definition: pns_layerset.h:108
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:35
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:392
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:732
T Min() const
Definition: minoptmax.h:33
void SetMin(T v)
Definition: minoptmax.h:41
T Opt() const
Definition: minoptmax.h:35
Handle the data for a net.
Definition: netinfo.h:56
int GetNetCode() const
Definition: netinfo.h:108
void SetParent(BOARD *aParent)
Definition: netinfo.h:167
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
static NETINFO_ITEM * OrphanedItem()
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:389
Definition: pad.h:54
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:392
const VECTOR2I & GetDrillSize() const
Definition: pad.h:267
PAD_ATTRIB GetAttribute() const
Definition: pad.h:395
const VECTOR2I & GetOffset() const
Definition: pad.h:274
VECTOR2I ShapePos() const
Definition: pad.cpp:896
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition: pad.cpp:453
bool IsFreePad() const
Definition: pad.cpp:279
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:359
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:462
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:499
int GetPadToDieLength() const
Definition: pad.h:408
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:280
const VECTOR2I & GetMid() const
Definition: pcb_track.h:281
std::vector< VECTOR2I > GetConnectionPoints() const
Definition: pcb_shape.cpp:326
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:70
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
Definition: pcb_text.cpp:627
void SetWidth(int aWidth)
Definition: pcb_track.h:115
int GetWidth() const
Definition: pcb_track.h:116
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:118
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:121
const VECTOR2I & GetStart() const
Definition: pcb_track.h:122
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:119
bool GetIsFree() const
Check if the via is a free via (as opposed to one created on a track by the router).
Definition: pcb_track.h:598
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:988
VECTOR2I GetPosition() const override
Definition: pcb_track.h:449
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:564
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:599
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:450
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
Definition: pcb_track.cpp:939
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_track.cpp:885
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:378
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:982
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:544
VIATYPE GetViaType() const
Definition: pcb_track.h:377
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Return the 2 layers used by the via (the via actually uses all layers between these 2 layers)
Definition: pcb_track.cpp:960
int Width() const override
Definition: pns_arc.h:88
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_arc.h:78
void SetDebugEnabled(bool aEnabled)
static HOLE * MakeCircularHole(const VECTOR2I &pos, int radius)
Definition: pns_hole.cpp:131
ITEM_SET & ExcludeItem(const ITEM *aItem)
ITEM_SET & FilterKinds(int aKindMask, bool aInvert=false)
Definition: pns_itemset.cpp:70
std::vector< ITEM * > & Items()
Definition: pns_itemset.h:87
Base class for PNS router board items.
Definition: pns_item.h:97
BOARD_ITEM * Parent() const
Definition: pns_item.h:186
virtual ITEM * ParentPadVia() const
Definition: pns_item.h:262
virtual NET_HANDLE Net() const
Definition: pns_item.h:194
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:167
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:193
virtual int Layer() const
Definition: pns_item.h:200
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:225
@ SEGMENT_T
Definition: pns_item.h:106
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:185
const LAYER_RANGE & Layers() const
Definition: pns_item.h:196
bool OfKind(int aKindMask) const
Definition: pns_item.h:175
bool IsVirtual() const
Definition: pns_item.h:264
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:237
virtual BOARD_ITEM * BoardItem() const
Definition: pns_item.h:191
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
Definition: pns_joint.h:43
const ITEM_SET & CLinks() const
Definition: pns_joint.h:279
Keep the router "world" - i.e.
Definition: pns_node.h:207
void SetMaxClearance(int aClearance)
Assign a clearance resolution function object.
Definition: pns_node.h:234
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:663
void SetRuleResolver(RULE_RESOLVER *aFunc)
Definition: pns_node.h:240
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
Definition: pns_node.cpp:707
const ITEM_OWNER * Owner() const
Return the owner of this item, or NULL if there's none.
Definition: pns_item.h:71
virtual wxString GetNetName(PNS::NET_HANDLE aNet) const =0
virtual int GetNetCode(NET_HANDLE aNet) const =0
const SEG & Seg() const
Definition: pns_segment.h:84
int Width() const override
Definition: pns_segment.h:79
void SetTrackWidth(int aWidth)
void SetBoardMinTrackWidth(int aWidth)
void SetDiffPairViaGapSameAsTraceGap(bool aEnable)
void SetDiffPairWidth(int aWidth)
void SetDiffPairWidthSource(const wxString &aSource)
void SetDiffPairGapSource(const wxString &aSource)
void SetDiffPairGap(int aGap)
void SetHoleToHole(int aHoleToHole)
void SetViaDrill(int aDrill)
void SetDiffPairViaGap(int aGap)
void SetDiffPairHoleToHole(int aHoleToHole)
void SetMinClearance(int aClearance)
void SetClearance(int aClearance)
void SetViaDiameter(int aDiameter)
void SetClearanceSource(const wxString &aSource)
void SetWidthSource(const wxString &aSource)
void SetTrackWidthIsExplicit(bool aIsExplicit)
bool syncGraphicalItem(PNS::NODE *aWorld, PCB_SHAPE *aItem)
bool inheritTrackWidth(PNS::ITEM *aItem, int *aInheritedWidth)
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, PNS::NET_HANDLE aNet) override
void AddItem(PNS::ITEM *aItem) override
virtual EDA_UNITS GetUnits() const
PNS::DEBUG_DECORATOR * m_debugDecorator
void SetDebugDecorator(PNS::DEBUG_DECORATOR *aDec)
bool syncZone(PNS::NODE *aWorld, ZONE *aZone, SHAPE_POLY_SET *aBoardOutline)
void SetBoard(BOARD *aBoard)
std::unique_ptr< PNS::ARC > syncArc(PCB_ARC *aArc)
void RemoveItem(PNS::ITEM *aItem) override
PNS::RULE_RESOLVER * GetRuleResolver() override
bool syncTextItem(PNS::NODE *aWorld, PCB_TEXT *aText, PCB_LAYER_ID aLayer)
bool IsFlashedOnLayer(const PNS::ITEM *aItem, int aLayer) const override
std::unique_ptr< PNS::SOLID > syncPad(PAD *aPad)
void SyncWorld(PNS::NODE *aWorld) override
int StackupHeight(int aFirstLayer, int aSecondLayer) const override
PNS::DEBUG_DECORATOR * GetDebugDecorator() override
std::unique_ptr< PNS::SEGMENT > syncTrack(PCB_TRACK *aTrack)
PNS_PCBNEW_RULE_RESOLVER * m_ruleResolver
PNS::NET_HANDLE GetOrphanedNetHandle() override
std::unique_ptr< PNS::VIA > syncVia(PCB_VIA *aVia)
void UpdateItem(PNS::ITEM *aItem) override
void SetView(KIGFX::VIEW *aView)
void RemoveItem(PNS::ITEM *aItem) override
void AddItem(PNS::ITEM *aItem) override
void UpdateItem(PNS::ITEM *aItem) override
std::map< PAD *, OFFSET > m_fpOffsets
int GetNetCode(PNS::NET_HANDLE aNet) const override
virtual void SetHostTool(PCB_TOOL_BASE *aTool)
void DisplayItem(const PNS::ITEM *aItem, int aClearance, bool aEdit=false, int aFlags=0) override
std::unique_ptr< BOARD_COMMIT > m_commit
void EraseView() override
void HideItem(PNS::ITEM *aItem) override
void UpdateNet(PNS::NET_HANDLE aNet) override
BOARD_CONNECTED_ITEM * createBoardItem(PNS::ITEM *aItem)
KIGFX::VIEW * m_view
void DisplayPathLine(const SHAPE_LINE_CHAIN &aLine, int aImportance) override
bool IsItemVisible(const PNS::ITEM *aItem) const override
std::unordered_set< BOARD_ITEM * > m_hiddenItems
EDA_UNITS GetUnits() const override
bool IsAnyLayerVisible(const LAYER_RANGE &aLayer) const override
PCB_TOOL_BASE * m_tool
void modifyBoardItem(PNS::ITEM *aItem)
void Commit() override
KIGFX::VIEW_GROUP * m_previewItems
void DisplayRatline(const SHAPE_LINE_CHAIN &aRatline, PNS::NET_HANDLE aNet) override
wxString GetNetName(PNS::NET_HANDLE aNet) const override
~PNS_KICAD_IFACE() override
void AddPoint(const VECTOR2I &aP, const KIGFX::COLOR4D &aColor, int aSize, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
PNS_PCBNEW_DEBUG_DECORATOR(KIGFX::VIEW *aView=nullptr)
void AddShape(const BOX2I &aBox, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
void AddItem(const PNS::ITEM *aItem, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
void SetView(KIGFX::VIEW *aView)
void AddShape(const SHAPE *aShape, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
int NetCode(PNS::NET_HANDLE aNet) override
PNS_PCBNEW_RULE_RESOLVER(BOARD *aBoard, PNS::ROUTER_IFACE *aRouterIface)
bool IsDrilledHole(const PNS::ITEM *aItem) override
void ClearTemporaryCaches() override
bool QueryConstraint(PNS::CONSTRAINT_TYPE aType, const PNS::ITEM *aItemA, const PNS::ITEM *aItemB, int aLayer, PNS::CONSTRAINT *aConstraint) override
int ClearanceEpsilon() const override
bool IsKeepout(const PNS::ITEM *aObstacle, const PNS::ITEM *aItem, bool *aEnforce) override
BOARD_ITEM * getBoardItem(const PNS::ITEM *aItem, int aLayer, int aIdx=0)
int Clearance(const PNS::ITEM *aA, const PNS::ITEM *aB, bool aUseClearanceEpsilon=true) override
void ClearCacheForItems(std::vector< const PNS::ITEM * > &aItems) override
bool IsNonPlatedSlot(const PNS::ITEM *aItem) override
std::unordered_map< CLEARANCE_CACHE_KEY, int > m_clearanceCache
int DpNetPolarity(PNS::NET_HANDLE aNet) override
std::unordered_map< CLEARANCE_CACHE_KEY, int > m_tempClearanceCache
bool IsNetTieExclusion(const PNS::ITEM *aItem, const VECTOR2I &aCollisionPos, const PNS::ITEM *aCollidingItem) override
bool IsInNetTie(const PNS::ITEM *aA) override
PNS::NET_HANDLE DpCoupledNet(PNS::NET_HANDLE aNet) override
bool DpNetPair(const PNS::ITEM *aItem, PNS::NET_HANDLE &aNetP, PNS::NET_HANDLE &aNetN) override
PNS::ROUTER_IFACE * m_routerIface
wxString NetName(PNS::NET_HANDLE aNet) override
void SetWidth(int aWidth)
void SetClearance(int aClearance)
static constexpr double PathOverlayDepth
void SetColor(const KIGFX::COLOR4D &aColor)
double GetOriginDepth() const
void SetDepth(double aDepth)
void ShowClearance(bool aEnabled)
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:115
const VECTOR2I & GetP1() const
Definition: shape_arc.h:114
const VECTOR2I & GetP0() const
Definition: shape_arc.h:113
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int Width() const
Get the current width of the segments in the chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void SetWidth(int aWidth)
Set the width of all segments in the chain.
const std::vector< VECTOR2I > & CPoints() const
void GetTriangle(int index, VECTOR2I &a, VECTOR2I &b, VECTOR2I &c) const
Represent a set of closed polygons.
bool IsTriangulationUpToDate() const
virtual void CacheTriangulation(bool aPartition=true, bool aSimplify=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
unsigned int TriangulatedPolyCount() const
Return the number of triangulated polygons.
int OutlineCount() const
Return the number of outlines in the set.
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
void Append(int aX, int aY)
Append a new point at the end of the polygon.
Definition: shape_simple.h:135
An abstract shape on 2D plane.
Definition: shape.h:126
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:146
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:400
VECTOR2_TRAITS< int32_t >::extended_type extended_type
Definition: vector2d.h:72
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: zone.cpp:824
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:711
bool GetDoNotAllowVias() const
Definition: zone.h:713
bool GetDoNotAllowPads() const
Definition: zone.h:715
bool GetDoNotAllowTracks() const
Definition: zone.h:714
SHAPE_POLY_SET * Outline()
Definition: zone.h:337
bool GetDoNotAllowFootprints() const
Definition: zone.h:716
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:130
DRC_CONSTRAINT_T
Definition: drc_rule.h:46
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:64
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:67
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:57
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:51
@ LENGTH_CONSTRAINT
Definition: drc_rule.h:65
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:48
@ MAX_UNCOUPLED_CONSTRAINT
Definition: drc_rule.h:68
@ SKEW_CONSTRAINT
Definition: drc_rule.h:66
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:49
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:52
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:71
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:50
#define _(s)
#define ROUTER_TRANSIENT
transient items that should NOT be cached
#define IN_EDIT
Item currently edited.
EDA_UNITS
Definition: eda_units.h:46
@ ERROR_OUTSIDE
static void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
Definition: hash.h:34
This file is part of the common library.
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START
Definition: layer_ids.h:140
#define MAX_CU_LAYERS
Definition: layer_ids.h:142
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:531
@ LAYER_RATSNEST
Definition: layer_ids.h:208
@ LAYER_SELECT_OVERLAY
currently selected items overlay
Definition: layer_ids.h:223
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Edge_Cuts
Definition: layer_ids.h:113
@ B_Cu
Definition: layer_ids.h:95
@ Margin
Definition: layer_ids.h:114
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:875
This file contains miscellaneous commonly used macros and functions.
@ APPEARANCE
Visibility flag has changed.
Definition: view_item.h:52
Push and Shove diff pair dimensions (gap) settings dialog.
CONSTRAINT_TYPE
Definition: pns_node.h:52
void * NET_HANDLE
Definition: pns_item.h:54
@ MK_LOCKED
Definition: pns_item.h:44
STL namespace.
@ SHOW_WITH_VIA_WHILE_ROUTING_OR_DRAGGING
@ SHOW_WHILE_ROUTING
@ SHOW_WITH_VIA_ALWAYS
@ SHOW_WITH_VIA_WHILE_ROUTING
static bool isEdge(const PNS::ITEM *aItem)
static bool isHole(const PNS::ITEM *aItem)
static bool isCopper(const PNS::ITEM *aItem)
VECTOR2I::extended_type ecoord
@ RPT_SEVERITY_IGNORE
#define PNS_SEMI_SOLID
@ SH_SEGMENT
line segment
Definition: shape.h:48
@ SH_ARC
circular arc
Definition: shape.h:54
@ SH_LINE_CHAIN
line chain (polyline)
Definition: shape.h:49
const PNS::ITEM * A
bool operator==(const CLEARANCE_CACHE_KEY &other) const
const PNS::ITEM * B
An abstract function object, returning a design rule (clearance, diff pair gap, etc) required between...
Definition: pns_node.h:73
wxString m_RuleName
Definition: pns_node.h:77
MINOPTMAX< int > m_Value
Definition: pns_node.h:75
CONSTRAINT_TYPE m_Type
Definition: pns_node.h:74
std::size_t operator()(const CLEARANCE_CACHE_KEY &k) const
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:228
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ 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:673