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 return false;
303
304 if( PAD* pad = dynamic_cast<PAD*>( aItem->Parent() ) )
305 return pad->GetDrillSizeX() && pad->GetDrillSizeX() == pad->GetDrillSizeY();
306
307 // Via holes are (currently) always round
308
309 return true;
310}
311
312
314{
315 if( !isHole( aItem ) )
316 return false;
317
318 BOARD_ITEM* parent = aItem->Parent();
319
320 if( !parent && aItem->ParentPadVia() )
321 parent = aItem->ParentPadVia()->Parent();
322
323 if( parent )
324 {
325 if( parent->Type() == PCB_PAD_T )
326 {
327 PAD* pad = static_cast<PAD*>( parent );
328
329 return pad->GetAttribute() == PAD_ATTRIB::NPTH
330 && pad->GetDrillSizeX() != pad->GetDrillSizeY();
331 }
332
333 // Via holes are (currently) always round, and always plated
334 }
335
336 return false;
337}
338
339
340BOARD_ITEM* PNS_PCBNEW_RULE_RESOLVER::getBoardItem( const PNS::ITEM* aItem, int aLayer, int aIdx )
341{
342 switch( aItem->Kind() )
343 {
344 case PNS::ITEM::ARC_T:
345 m_dummyArcs[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
346 m_dummyArcs[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
347 m_dummyArcs[aIdx].SetStart( aItem->Anchor( 0 ) );
348 m_dummyArcs[aIdx].SetEnd( aItem->Anchor( 1 ) );
349 return &m_dummyArcs[aIdx];
350
351 case PNS::ITEM::VIA_T:
353 m_dummyVias[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
354 m_dummyVias[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
355 m_dummyVias[aIdx].SetStart( aItem->Anchor( 0 ) );
356 return &m_dummyVias[aIdx];
357
360 m_dummyTracks[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
361 m_dummyTracks[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
362 m_dummyTracks[aIdx].SetStart( aItem->Anchor( 0 ) );
363 m_dummyTracks[aIdx].SetEnd( aItem->Anchor( 1 ) );
364 return &m_dummyTracks[aIdx];
365
366 default:
367 return nullptr;
368 }
369}
370
371
373 const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
374 int aLayer, PNS::CONSTRAINT* aConstraint )
375{
376 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
377
378 if( !drcEngine )
379 return false;
380
381 DRC_CONSTRAINT_T hostType;
382
383 switch ( aType )
384 {
397 default: return false; // should not happen
398 }
399
400 BOARD_ITEM* parentA = aItemA ? aItemA->BoardItem() : nullptr;
401 BOARD_ITEM* parentB = aItemB ? aItemB->BoardItem() : nullptr;
402 DRC_CONSTRAINT hostConstraint;
403
404 // A track being routed may not have a BOARD_ITEM associated yet.
405 if( aItemA && !parentA )
406 parentA = getBoardItem( aItemA, aLayer, 0 );
407
408 if( aItemB && !parentB )
409 parentB = getBoardItem( aItemB, aLayer, 1 );
410
411 if( parentA )
412 hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, ToLAYER_ID( aLayer ) );
413
414 if( hostConstraint.IsNull() )
415 return false;
416
417 if( hostConstraint.GetSeverity() == RPT_SEVERITY_IGNORE )
418 {
419 aConstraint->m_Value.SetMin( -1 );
420 aConstraint->m_RuleName = hostConstraint.GetName();
421 aConstraint->m_Type = aType;
422 return true;
423 }
424
425 switch ( aType )
426 {
439 aConstraint->m_Value = hostConstraint.GetValue();
440 aConstraint->m_RuleName = hostConstraint.GetName();
441 aConstraint->m_Type = aType;
442 return true;
443
444 default:
445 return false;
446 }
447}
448
449
450void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems )
451{
452 int n_pruned = 0;
453 std::set<const PNS::ITEM*> remainingItems( aItems.begin(), aItems.end() );
454
455/* We need to carefully check both A and B item pointers in the cache against dirty/invalidated
456 items in the set, as the clearance relation is commutative ( CL[a,b] == CL[b,a] ). The code
457 below is a bit ugly, but works in O(n*log(m)) and is run once or twice during ROUTER::Move() call
458 - so I hope it still gets better performance than no cache at all */
459 for( auto it = m_clearanceCache.begin(); it != m_clearanceCache.end(); )
460 {
461 bool dirty = remainingItems.find( it->first.A ) != remainingItems.end();
462 dirty |= remainingItems.find( it->first.B) != remainingItems.end();
463
464 if( dirty )
465 {
466 it = m_clearanceCache.erase( it );
467 n_pruned++;
468 } else
469 it++;
470 }
471#if 0
472 printf("ClearCache : n_pruned %d\n", n_pruned );
473#endif
474}
475
476
478{
479 m_clearanceCache.clear();
480 m_tempClearanceCache.clear();
481}
482
483
485{
486 m_tempClearanceCache.clear();
487}
488
489
491 bool aUseClearanceEpsilon )
492{
493 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
494
495 // Search cache (used for actual board items)
496 auto it = m_clearanceCache.find( key );
497 if( it != m_clearanceCache.end() )
498 return it->second;
499
500 // Search cache (used for temporary items within an algorithm)
501 it = m_tempClearanceCache.find( key );
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 else if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
540 {
541 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
542 {
543 if( constraint.m_Value.Min() > rv )
544 rv = constraint.m_Value.Min();
545 }
546 }
547
548 // No 'else'; non-plated milled holes get both HOLE_CLEARANCE and EDGE_CLEARANCE
549 if( isEdge( aA ) || IsNonPlatedSlot( aA ) || isEdge( aB ) || IsNonPlatedSlot( aB ) )
550 {
551 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
552 {
553 if( constraint.m_Value.Min() > rv )
554 rv = constraint.m_Value.Min();
555 }
556 }
557
558 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_PHYSICAL_CLEARANCE, aA, aB, layer, &constraint ) )
559 {
560 if( constraint.m_Value.Min() > rv )
561 rv = constraint.m_Value.Min();
562 }
563 }
564
565 if( aUseClearanceEpsilon && rv > 0 )
566 rv = std::max( 0, rv - m_clearanceEpsilon );
567
568
569/* It makes no sense to put items that have no owning NODE in the cache - they can be allocated on stack
570 and we can't really invalidate them in the cache when they are destroyed. Probably a better idea would be
571 to use a static unique counter in PNS::ITEM constructor to generate the cache keys. */
572/* However, algorithms DO greatly benefit from using the cache, so ownerless items need to be cached.
573 In order to easily clear those only, a temporary cache is created. If this doesn't seem nice, an alternative
574 is clearing the full cache once it reaches a certain size. Also not pretty, but VERY effective
575 to keep things interactive. */
576 if( aA && aB )
577 {
578 if ( aA->Owner() && aB->Owner() )
579 m_clearanceCache[ key ] = rv;
580 else
581 m_tempClearanceCache[ key ] = rv;
582 }
583
584 return rv;
585}
586
587
588bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth )
589{
590 VECTOR2I p;
591
592 assert( aItem->Owner() != nullptr );
593
594 auto tryGetTrackWidth =
595 []( PNS::ITEM* aPnsItem ) -> int
596 {
597 switch( aPnsItem->Kind() )
598 {
599 case PNS::ITEM::SEGMENT_T: return static_cast<PNS::SEGMENT*>( aPnsItem )->Width();
600 case PNS::ITEM::ARC_T: return static_cast<PNS::ARC*>( aPnsItem )->Width();
601 default: return -1;
602 }
603 };
604
605 int itemTrackWidth = tryGetTrackWidth( aItem );
606
607 if( itemTrackWidth > 0 )
608 {
609 *aInheritedWidth = itemTrackWidth;
610 return true;
611 }
612
613 switch( aItem->Kind() )
614 {
615 case PNS::ITEM::VIA_T: p = static_cast<PNS::VIA*>( aItem )->Pos(); break;
616 case PNS::ITEM::SOLID_T: p = static_cast<PNS::SOLID*>( aItem )->Pos(); break;
617 default: return false;
618 }
619
620 const PNS::JOINT* jt = static_cast<const PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
621
622 assert( jt != nullptr );
623
624 int mval = INT_MAX;
625
626 PNS::ITEM_SET linkedSegs( jt->CLinks() );
628
629 for( PNS::ITEM* item : linkedSegs.Items() )
630 {
631 int w = tryGetTrackWidth( item );
632
633 if( w > 0 )
634 mval = std::min( w, mval );
635 }
636
637 if( mval == INT_MAX )
638 return false;
639
640 *aInheritedWidth = mval;
641 return true;
642}
643
644
646 PNS::NET_HANDLE aNet )
647{
649 PNS::CONSTRAINT constraint;
650
651 if( aStartItem && m_startLayer < 0 )
652 m_startLayer = aStartItem->Layer();
653
654 aSizes.SetClearance( bds.m_MinClearance );
655 aSizes.SetMinClearance( bds.m_MinClearance );
656 aSizes.SetClearanceSource( _( "board minimum clearance" ) );
657
659 m_startLayer, &constraint ) )
660 {
661 if( constraint.m_Value.Min() > bds.m_MinClearance )
662 {
663 aSizes.SetClearance( constraint.m_Value.Min() );
664 aSizes.SetClearanceSource( constraint.m_RuleName );
665 }
666 }
667
668 int trackWidth = bds.m_TrackMinWidth;
669 bool found = false;
670 aSizes.SetWidthSource( _( "board minimum track width" ) );
671
672 if( bds.m_UseConnectedTrackWidth && !bds.m_TempOverrideTrackWidth && aStartItem != nullptr )
673 {
674 found = inheritTrackWidth( aStartItem, &trackWidth );
675
676 if( found )
677 aSizes.SetWidthSource( _( "existing track" ) );
678 }
679
680 if( !found && bds.UseNetClassTrack() && aStartItem )
681 {
683 m_startLayer, &constraint ) )
684 {
685 trackWidth = std::max( trackWidth, constraint.m_Value.Opt() );
686 found = true;
687
688 if( trackWidth == constraint.m_Value.Opt() )
689 aSizes.SetWidthSource( constraint.m_RuleName );
690 }
691 }
692
693 if( !found )
694 {
695 trackWidth = std::max( trackWidth, bds.GetCurrentTrackWidth() );
696
697 if( bds.UseNetClassTrack() )
698 aSizes.SetWidthSource( _( "netclass 'Default'" ) );
699 else if( trackWidth == bds.GetCurrentTrackWidth() )
700 aSizes.SetWidthSource( _( "user choice" ) );
701 }
702
703 aSizes.SetTrackWidth( trackWidth );
706
707 int viaDiameter = bds.m_ViasMinSize;
708 int viaDrill = bds.m_MinThroughDrill;
709
710 PNS::VIA dummyVia, coupledVia;
711
712 if( aStartItem )
713 {
714 dummyVia.SetNet( aStartItem->Net() );
715 coupledVia.SetNet( m_ruleResolver->DpCoupledNet( aStartItem->Net() ) );
716 }
717
718 if( bds.UseNetClassVia() && aStartItem ) // netclass value
719 {
721 nullptr, m_startLayer, &constraint ) )
722 {
723 viaDiameter = std::max( viaDiameter, constraint.m_Value.Opt() );
724 }
725
727 nullptr, m_startLayer, &constraint ) )
728 {
729 viaDrill = std::max( viaDrill, constraint.m_Value.Opt() );
730 }
731 }
732 else
733 {
734 viaDiameter = bds.GetCurrentViaSize();
735 viaDrill = bds.GetCurrentViaDrill();
736 }
737
738 aSizes.SetViaDiameter( viaDiameter );
739 aSizes.SetViaDrill( viaDrill );
740
741 int diffPairWidth = bds.m_TrackMinWidth;
742 int diffPairGap = bds.m_MinClearance;
743 int diffPairViaGap = bds.m_MinClearance;
744
745 aSizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
746 aSizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
747
748 found = false;
749
750 // First try to pick up diff pair width from starting track, if enabled
751 if( bds.m_UseConnectedTrackWidth && aStartItem )
752 found = inheritTrackWidth( aStartItem, &diffPairWidth );
753
754 // Next, pick up gap from netclass, and width also if we didn't get a starting width above
755 if( bds.UseNetClassDiffPair() && aStartItem )
756 {
758 nullptr, m_startLayer, &constraint ) )
759 {
760 diffPairWidth = std::max( diffPairWidth, constraint.m_Value.Opt() );
761
762 if( diffPairWidth == constraint.m_Value.Opt() )
763 aSizes.SetDiffPairWidthSource( constraint.m_RuleName );
764 }
765
767 nullptr, m_startLayer, &constraint ) )
768 {
769 diffPairGap = std::max( diffPairGap, constraint.m_Value.Opt() );
770 diffPairViaGap = std::max( diffPairViaGap, constraint.m_Value.Opt() );
771
772 if( diffPairGap == constraint.m_Value.Opt() )
773 aSizes.SetDiffPairGapSource( constraint.m_RuleName );
774 }
775 }
776 else
777 {
778 diffPairWidth = bds.GetCurrentDiffPairWidth();
779 diffPairGap = bds.GetCurrentDiffPairGap();
780 diffPairViaGap = bds.GetCurrentDiffPairViaGap();
781
782 aSizes.SetDiffPairWidthSource( _( "user choice" ) );
783 aSizes.SetDiffPairGapSource( _( "user choice" ) );
784 }
785
786 aSizes.SetDiffPairWidth( diffPairWidth );
787 aSizes.SetDiffPairGap( diffPairGap );
788 aSizes.SetDiffPairViaGap( diffPairViaGap );
789 aSizes.SetDiffPairViaGapSameAsTraceGap( false );
790
791 int holeToHoleMin = bds.m_HoleToHoleMin;
792
794 &dummyVia, UNDEFINED_LAYER, &constraint ) )
795 {
796 holeToHoleMin = constraint.m_Value.Min();
797 }
798
799 aSizes.SetHoleToHole( holeToHoleMin );
800
802 &coupledVia, UNDEFINED_LAYER, &constraint ) )
803 {
804 holeToHoleMin = constraint.m_Value.Min();
805 }
806
807 aSizes.SetDiffPairHoleToHole( holeToHoleMin );
808
809 return true;
810}
811
812
813int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const
814{
816 return 0;
817
819
820 return stackup.GetLayerDistance( ToLAYER_ID( aFirstLayer ), ToLAYER_ID( aSecondLayer ) );
821}
822
823
825{
826 return m_board->DpCoupledNet( static_cast<NETINFO_ITEM*>( aNet ) );
827}
828
829
831{
832 return m_routerIface->GetNetCode( aNet );
833}
834
835
837{
838 return m_routerIface->GetNetName( aNet );
839}
840
841
843{
844 wxString refName;
845
846 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
847 refName = net->GetNetname();
848
849 wxString dummy1;
850
851 return m_board->MatchDpSuffix( refName, dummy1 );
852}
853
854
856 PNS::NET_HANDLE& aNetN )
857{
858 if( !aItem || !aItem->Net() )
859 return false;
860
861 wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
862 wxString netNameN, netNameCoupled;
863
864 int r = m_board->MatchDpSuffix( netNameP, netNameCoupled );
865
866 if( r == 0 )
867 {
868 return false;
869 }
870 else if( r == 1 )
871 {
872 netNameN = netNameCoupled;
873 }
874 else
875 {
876 netNameN = netNameP;
877 netNameP = netNameCoupled;
878 }
879
880 PNS::NET_HANDLE netInfoP = m_board->FindNet( netNameP );
881 PNS::NET_HANDLE netInfoN = m_board->FindNet( netNameN );
882
883 if( !netInfoP || !netInfoN )
884 return false;
885
886 aNetP = netInfoP;
887 aNetN = netInfoN;
888
889 return true;
890}
891
892
894{
895public:
898 m_view( nullptr ),
899 m_items( nullptr ),
900 m_depth( 0 )
901 {
902 SetView( aView );
903 }
904
906 {
908 delete m_items;
909 }
910
911 void SetView( KIGFX::VIEW* aView )
912 {
913 Clear();
914 delete m_items;
915 m_items = nullptr;
916 m_view = aView;
917
918 if( m_view == nullptr )
919 return;
920
921 if( m_view->GetGAL() )
923
926 m_view->Add( m_items );
927 }
928
929 void AddPoint( const VECTOR2I& aP, const KIGFX::COLOR4D& aColor, int aSize,
930 const wxString& aName = wxT( "" ),
931 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
932
933 {
935
936 sh.SetWidth( 10000 );
937
938 sh.Append( aP.x - aSize, aP.y - aSize );
939 sh.Append( aP.x + aSize, aP.y + aSize );
940 sh.Append( aP.x, aP.y );
941 sh.Append( aP.x - aSize, aP.y + aSize );
942 sh.Append( aP.x + aSize, aP.y - aSize );
943
944 AddShape( &sh, aColor, sh.Width(), aName, aSrcLoc );
945 }
946
947 void AddItem( const PNS::ITEM* aItem, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
948 const wxString& aName = wxT( "" ),
949 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
950 {
951 if( !m_view || !aItem )
952 return;
953
954 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
955
956 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
957 pitem->SetWidth( aOverrideWidth );
958 pitem->SetDepth( nextDepth() );
959
960 m_items->Add( pitem );
962 }
963
964 void AddShape( const BOX2I& aBox, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
965 const wxString& aName = wxT( "" ),
966 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
967 {
969 l.SetWidth( aOverrideWidth );
970
971 VECTOR2I o = aBox.GetOrigin();
972 VECTOR2I s = aBox.GetSize();
973
974 l.Append( o );
975 l.Append( o.x + s.x, o.y );
976 l.Append( o.x + s.x, o.y + s.y );
977 l.Append( o.x, o.y + s.y );
978 l.Append( o );
979
980 AddShape( &l, aColor, aOverrideWidth, aName, aSrcLoc );
981 }
982
983 void AddShape( const SHAPE* aShape, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
984 const wxString& aName = wxT( "" ),
985 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
986 {
987 if( !m_view || !aShape )
988 return;
989
990 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_view );
991
992 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
993 pitem->SetWidth( aOverrideWidth );
994 pitem->SetDepth( nextDepth() );
995
996 m_items->Add( pitem );
998 }
999
1000 void Clear() override
1001 {
1002 if( m_view && m_items )
1003 {
1004 m_items->FreeItems();
1005 m_view->Update( m_items );
1006
1007 if( m_view->GetGAL() )
1009 }
1010 }
1011
1012private:
1013 double nextDepth()
1014 {
1015 // Use different depths so that the transculent shapes won't overwrite each other.
1016
1017 m_depth++;
1018
1019 if( m_depth >= 0 && m_view->GetGAL() )
1021
1022 return m_depth;
1023 }
1024
1027
1028 double m_depth;
1029};
1030
1031
1033{
1034 return m_debugDecorator;
1035}
1036
1037
1039{
1040 m_ruleResolver = nullptr;
1041 m_board = nullptr;
1042 m_world = nullptr;
1043 m_debugDecorator = nullptr;
1044 m_startLayer = -1;
1045}
1046
1047
1049{
1050 m_tool = nullptr;
1051 m_view = nullptr;
1052 m_previewItems = nullptr;
1053 m_commitFlags = 0;
1054}
1055
1056
1058{
1059 delete m_ruleResolver;
1060 delete m_debugDecorator;
1061}
1062
1063
1065{
1066 if( m_previewItems )
1067 {
1069 delete m_previewItems;
1070 }
1071}
1072
1073
1074std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1075{
1076 LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 );
1077
1078 // ignore non-copper pads except for those with holes
1079 if( ( aPad->GetLayerSet() & LSET::AllCuMask() ).none() && aPad->GetDrillSize().x == 0 )
1080 return nullptr;
1081
1082 switch( aPad->GetAttribute() )
1083 {
1084 case PAD_ATTRIB::PTH:
1085 case PAD_ATTRIB::NPTH:
1086 break;
1087
1088 case PAD_ATTRIB::CONN:
1089 case PAD_ATTRIB::SMD:
1090 {
1091 LSET lmsk = aPad->GetLayerSet();
1092 bool is_copper = false;
1093
1094 for( int i = 0; i < MAX_CU_LAYERS; i++ )
1095 {
1096 if( lmsk[i] )
1097 {
1098 is_copper = true;
1099
1100 if( aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1101 layers = LAYER_RANGE( i );
1102
1103 break;
1104 }
1105 }
1106
1107 if( !is_copper )
1108 return nullptr;
1109
1110 break;
1111 }
1112
1113 default:
1114 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1115 return nullptr;
1116 }
1117
1118 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1119
1120 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1121 solid->SetRoutable( false );
1122
1123 solid->SetLayers( layers );
1124 solid->SetNet( aPad->GetNet() );
1125 solid->SetParent( aPad );
1126 solid->SetPadToDie( aPad->GetPadToDieLength() );
1127 solid->SetOrientation( aPad->GetOrientation() );
1128
1129 if( aPad->IsFreePad() )
1130 solid->SetIsFreePad();
1131
1132 VECTOR2I wx_c = aPad->ShapePos();
1133 VECTOR2I offset = aPad->GetOffset();
1134
1135 VECTOR2I c( wx_c.x, wx_c.y );
1136
1137 RotatePoint( offset, aPad->GetOrientation() );
1138
1139 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1140 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1141
1142 if( aPad->GetDrillSize().x > 0 )
1143 solid->SetHole( new PNS::HOLE( aPad->GetEffectiveHoleShape()->Clone() ) );
1144
1145 // We generate a single SOLID for a pad, so we have to treat it as ALWAYS_FLASHED and then
1146 // perform layer-specific flashing tests internally.
1147 const std::shared_ptr<SHAPE>& shape = aPad->GetEffectiveShape( UNDEFINED_LAYER,
1148 FLASHING::ALWAYS_FLASHED );
1149
1150 if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 )
1151 {
1152 std::vector<const SHAPE*> subshapes;
1153 shape->GetIndexableSubshapes( subshapes );
1154
1155 solid->SetShape( subshapes[0]->Clone() );
1156 }
1157 // For anything that's not a single shape we use a polygon. Multiple shapes have a tendency
1158 // to confuse the hull generator. https://gitlab.com/kicad/code/kicad/-/issues/15553
1159 else
1160 {
1161 const std::shared_ptr<SHAPE_POLY_SET>& poly = aPad->GetEffectivePolygon( ERROR_OUTSIDE );
1162
1163 if( poly->OutlineCount() )
1164 solid->SetShape( new SHAPE_SIMPLE( poly->Outline( 0 ) ) );
1165 }
1166
1167 return solid;
1168}
1169
1170
1171std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1172{
1173 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1174 aTrack->GetNet() );
1175
1176 segment->SetWidth( aTrack->GetWidth() );
1177 segment->SetLayers( LAYER_RANGE( aTrack->GetLayer() ) );
1178 segment->SetParent( aTrack );
1179
1180 if( aTrack->IsLocked() )
1181 segment->Mark( PNS::MK_LOCKED );
1182
1183 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aTrack->GetParentGroup() ) )
1184 {
1185 if( !generator->HasFlag( IN_EDIT ) )
1186 segment->Mark( PNS::MK_LOCKED );
1187 }
1188
1189 return segment;
1190}
1191
1192
1193std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1194{
1195 auto arc = std::make_unique<PNS::ARC>( SHAPE_ARC( aArc->GetStart(), aArc->GetMid(),
1196 aArc->GetEnd(), aArc->GetWidth() ),
1197 aArc->GetNet() );
1198
1199 arc->SetLayers( LAYER_RANGE( aArc->GetLayer() ) );
1200 arc->SetParent( aArc );
1201
1202 if( aArc->IsLocked() )
1203 arc->Mark( PNS::MK_LOCKED );
1204
1205 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aArc->GetParentGroup() ) )
1206 {
1207 if( !generator->HasFlag( IN_EDIT ) )
1208 arc->Mark( PNS::MK_LOCKED );
1209 }
1210
1211 return arc;
1212}
1213
1214
1215std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1216{
1217 PCB_LAYER_ID top, bottom;
1218 aVia->LayerPair( &top, &bottom );
1219
1220 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1221 LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ),
1222 aVia->GetWidth(),
1223 aVia->GetDrillValue(),
1224 aVia->GetNet(),
1225 aVia->GetViaType() );
1226
1227 via->SetParent( aVia );
1228
1229 if( aVia->IsLocked() )
1230 via->Mark( PNS::MK_LOCKED );
1231
1232 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aVia->GetParentGroup() ) )
1233 {
1234 if( !generator->HasFlag( IN_EDIT ) )
1235 via->Mark( PNS::MK_LOCKED );
1236 }
1237
1238 via->SetIsFree( aVia->GetIsFree() );
1239 via->SetHole( PNS::HOLE::MakeCircularHole( aVia->GetPosition(), aVia->GetDrillValue() / 2 ) );
1240
1241 return via;
1242}
1243
1244
1245bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1246{
1247 static wxString msg;
1248 SHAPE_POLY_SET* poly;
1249
1250 if( !aZone->GetIsRuleArea() )
1251 return false;
1252
1253 LSET layers = aZone->GetLayerSet();
1254
1255 poly = aZone->Outline();
1256 poly->CacheTriangulation( false );
1257
1258 if( !poly->IsTriangulationUpToDate() )
1259 {
1260 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1261 msg.Printf( _( "%s is malformed." ), aZone->GetItemDescription( &unitsProvider ) );
1262
1263 KIDIALOG dlg( nullptr, msg, KIDIALOG::KD_WARNING );
1264 dlg.ShowDetailedText( _( "This zone cannot be handled by the router.\n"
1265 "Please verify it is not a self-intersecting polygon." ) );
1266 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1267 dlg.ShowModal();
1268
1269 return false;
1270 }
1271
1272 for( int layer = F_Cu; layer <= B_Cu; layer++ )
1273 {
1274 if( !layers[ layer ] )
1275 continue;
1276
1277 for( int polyId = 0; polyId < poly->TriangulatedPolyCount(); polyId++ )
1278 {
1279 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( polyId );
1280
1281 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1282 {
1283 VECTOR2I a, b, c;
1284 tri->GetTriangle( i, a, b, c );
1285 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1286
1287 triShape->Append( a );
1288 triShape->Append( b );
1289 triShape->Append( c );
1290
1291 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1292
1293 solid->SetLayer( layer );
1294 solid->SetNet( nullptr );
1295 solid->SetParent( aZone );
1296 solid->SetShape( triShape );
1297 solid->SetIsCompoundShapePrimitive();
1298 solid->SetRoutable( false );
1299
1300 aWorld->Add( std::move( solid ) );
1301 }
1302 }
1303 }
1304
1305 return true;
1306}
1307
1308
1310{
1311 if( !IsCopperLayer( aLayer ) )
1312 return false;
1313
1314 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1315 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1316
1317 solid->SetLayer( aLayer );
1318 solid->SetNet( nullptr );
1319 solid->SetParent( aText );
1320 solid->SetShape( shape ); // takes ownership
1321 solid->SetRoutable( false );
1322
1323 SHAPE_POLY_SET cornerBuffer;
1324
1325 aText->TransformShapeToPolygon( cornerBuffer, aText->GetLayer(), 0,
1327
1328 if( !cornerBuffer.OutlineCount() )
1329 return false;
1330
1331 for( const VECTOR2I& pt : cornerBuffer.Outline( 0 ).CPoints() )
1332 shape->Append( pt );
1333
1334 aWorld->Add( std::move( solid ) );
1335
1336 return true;
1337}
1338
1339
1341{
1342 if( aItem->GetLayer() == Edge_Cuts
1343 || aItem->GetLayer() == Margin
1344 || IsCopperLayer( aItem->GetLayer() ) )
1345 {
1346 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1347
1348 for( SHAPE* shape : shapes )
1349 {
1350 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1351
1352 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1353 solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
1354 else
1355 solid->SetLayer( aItem->GetLayer() );
1356
1357 if( aItem->GetLayer() == Edge_Cuts )
1358 {
1359 switch( shape->Type() )
1360 {
1361 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1362 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1363 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1364 default: /* remaining shapes don't have width */ break;
1365 }
1366 }
1367
1368 solid->SetAnchorPoints( aItem->GetConnectionPoints() );
1369 solid->SetNet( aItem->GetNet() );
1370 solid->SetParent( aItem );
1371 solid->SetShape( shape ); // takes ownership
1372
1373 if( shapes.size() > 1 )
1374 solid->SetIsCompoundShapePrimitive();
1375
1376 aWorld->Add( std::move( solid ) );
1377 }
1378
1379 return true;
1380 }
1381
1382 return false;
1383}
1384
1385
1387{
1388 m_board = aBoard;
1389 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1390}
1391
1392
1394{
1395 if( !m_view )
1396 return false;
1397
1398 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1399 {
1400 if( m_view->IsLayerVisible( i ) )
1401 return true;
1402 }
1403
1404 return false;
1405}
1406
1407
1408bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1409{
1411 if( aLayer < 0 )
1412 return true;
1413
1414 if( aItem->Parent() )
1415 {
1416 switch( aItem->Parent()->Type() )
1417 {
1418 case PCB_VIA_T:
1419 {
1420 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1421
1422 return via->FlashLayer( ToLAYER_ID( aLayer ) );
1423 }
1424
1425 case PCB_PAD_T:
1426 {
1427 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1428
1429 return pad->FlashLayer( ToLAYER_ID( aLayer ) );
1430 }
1431
1432 default:
1433 break;
1434 }
1435 }
1436
1437 return aItem->Layers().Overlaps( aLayer );
1438}
1439
1440
1442 const LAYER_RANGE& aLayer ) const
1443{
1444 LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
1445
1446 if( aItem->Parent() )
1447 {
1448 switch( aItem->Parent()->Type() )
1449 {
1450 case PCB_VIA_T:
1451 {
1452 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1453
1454 for( int layer = test.Start(); layer <= test.End(); ++layer )
1455 {
1456 if( via->FlashLayer( ToLAYER_ID( layer ) ) )
1457 return true;
1458 }
1459
1460 return false;
1461 }
1462
1463 case PCB_PAD_T:
1464 {
1465 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1466
1467 for( int layer = test.Start(); layer <= test.End(); ++layer )
1468 {
1469 if( pad->FlashLayer( ToLAYER_ID( layer ) ) )
1470 return true;
1471 }
1472
1473 return false;
1474 }
1475
1476 default:
1477 break;
1478 }
1479 }
1480
1481 return test.Start() <= test.End();
1482}
1483
1484
1486{
1487 // by default, all items are visible (new ones created by the router have parent == NULL
1488 // as they have not been committed yet to the BOARD)
1489 if( !m_view || !aItem->Parent() )
1490 return true;
1491
1492 BOARD_ITEM* item = aItem->Parent();
1493 bool isOnVisibleLayer = true;
1494 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1495
1496 if( settings->GetHighContrast() )
1497 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1498
1499 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1500 {
1501 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
1502 {
1503 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1504 return true;
1505 }
1506 }
1507
1508 // Items hidden in the router are not hidden on the board
1509 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1510 return true;
1511
1512 return false;
1513}
1514
1515
1517{
1518 if( !m_board )
1519 {
1520 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1521 return;
1522 }
1523
1524 int worstClearance = m_board->GetMaxClearanceValue();
1525
1526 m_world = aWorld;
1527
1528 for( BOARD_ITEM* gitem : m_board->Drawings() )
1529 {
1530 if ( gitem->Type() == PCB_SHAPE_T || gitem->Type() == PCB_TEXTBOX_T )
1531 {
1532 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1533 }
1534 else if( gitem->Type() == PCB_TEXT_T )
1535 {
1536 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1537 }
1538 }
1539
1540 SHAPE_POLY_SET buffer;
1541 SHAPE_POLY_SET* boardOutline = nullptr;
1542
1543 if( m_board->GetBoardPolygonOutlines( buffer ) )
1544 boardOutline = &buffer;
1545
1546 for( ZONE* zone : m_board->Zones() )
1547 {
1548 syncZone( aWorld, zone, boardOutline );
1549 }
1550
1551 for( FOOTPRINT* footprint : m_board->Footprints() )
1552 {
1553 for( PAD* pad : footprint->Pads() )
1554 {
1555 if( std::unique_ptr<PNS::SOLID> solid = syncPad( pad ) )
1556 aWorld->Add( std::move( solid ) );
1557
1558 std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
1559
1560 if( clearanceOverride.has_value() )
1561 worstClearance = std::max( worstClearance, clearanceOverride.value() );
1562
1563 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1564 {
1565 std::unique_ptr<SHAPE> hole;
1566 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1567 aWorld->AddEdgeExclusion( std::move( hole ) );
1568 }
1569 }
1570
1571 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1572 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1573
1574 for( ZONE* zone : footprint->Zones() )
1575 syncZone( aWorld, zone, boardOutline );
1576
1577 for( PCB_FIELD* field : footprint->Fields() )
1578 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1579
1580 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1581 {
1582 if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_TEXTBOX_T )
1583 {
1584 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1585 }
1586 else if( item->Type() == PCB_TEXT_T )
1587 {
1588 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1589 }
1590 }
1591 }
1592
1593 for( PCB_TRACK* t : m_board->Tracks() )
1594 {
1595 KICAD_T type = t->Type();
1596
1597 if( type == PCB_TRACE_T )
1598 {
1599 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1600 aWorld->Add( std::move( segment ) );
1601 }
1602 else if( type == PCB_ARC_T )
1603 {
1604 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1605 aWorld->Add( std::move( arc ) );
1606 }
1607 else if( type == PCB_VIA_T )
1608 {
1609 if( std::unique_ptr<PNS::VIA> via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1610 aWorld->Add( std::move( via ) );
1611 }
1612 }
1613
1614 // NB: if this were ever to become a long-lived object we would need to dirty its
1615 // clearance cache here....
1616 delete m_ruleResolver;
1618
1620 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1621}
1622
1623
1625{
1626 for( BOARD_ITEM* item : m_hiddenItems )
1627 m_view->SetVisible( item, true );
1628
1629 m_hiddenItems.clear();
1630
1631 if( m_previewItems )
1632 {
1635 }
1636
1637 if( m_debugDecorator )
1639}
1640
1641
1643{
1644 m_debugDecorator = aDec;
1645}
1646
1647
1648void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, int aFlags )
1649{
1650 if( aItem->IsVirtual() )
1651 return;
1652
1653 if( ZONE* zone = dynamic_cast<ZONE*>( aItem->Parent() ) )
1654 {
1655 if( zone->GetIsRuleArea() )
1656 aFlags |= PNS_SEMI_SOLID;
1657 }
1658
1659 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view, aFlags );
1660
1661 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1663 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1664
1665 if( aClearance >= 0 )
1666 {
1667 pitem->SetClearance( aClearance );
1668
1669 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1670
1671 switch( settings->m_Display.m_TrackClearance )
1672 {
1675 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1676 break;
1677
1679 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1680 break;
1681
1682 case SHOW_WHILE_ROUTING:
1683 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1684 break;
1685
1686 default:
1687 pitem->ShowClearance( false );
1688 break;
1689 }
1690 }
1691
1692 m_previewItems->Add( pitem );
1694}
1695
1696
1697void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1698{
1699 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, m_view );
1701
1702 COLOR4D color;
1703
1704 if( aImportance >= 1 )
1705 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1706 else if( aImportance == 0 )
1707 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1708
1709 pitem->SetColor( color );
1710
1711 m_previewItems->Add( pitem );
1713}
1714
1715
1717{
1718 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, m_view );
1719
1720 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1721 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1722 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1723 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1724 COLOR4D color = defaultColor;
1725
1726 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1727 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1728 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1729 std::map<wxString, KIGFX::COLOR4D>& ncColors = rs->GetNetclassColorMap();
1730 const std::map<int, wxString>& ncMap = connectivity->GetNetclassMap();
1731 int netCode = -1;
1732
1733 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
1734 netCode = net->GetNetCode();
1735
1736 if( colorByNet && netColors.count( netCode ) )
1737 color = netColors.at( netCode );
1738 else if( colorByNet && ncMap.count( netCode ) && ncColors.count( ncMap.at( netCode ) ) )
1739 color = ncColors.at( ncMap.at( netCode ) );
1740 else
1741 color = defaultColor;
1742
1743 if( color == COLOR4D::UNSPECIFIED )
1744 color = defaultColor;
1745
1746 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
1747
1748 m_previewItems->Add( pitem );
1750}
1751
1752
1754{
1755 BOARD_ITEM* parent = aItem->Parent();
1756
1757 if( parent )
1758 {
1759 if( m_view->IsVisible( parent ) )
1760 m_hiddenItems.insert( parent );
1761
1762 m_view->SetVisible( parent, false );
1763 m_view->Update( parent, KIGFX::APPEARANCE );
1764
1765 for( ZONE* td : m_board->Zones() )
1766 {
1767 if( td->IsTeardropArea()
1768 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
1769 && td->Outline()->Collide( aItem->Shape() ) )
1770 {
1771 m_view->SetVisible( td, false );
1773 }
1774 }
1775 }
1776}
1777
1778
1780{
1781}
1782
1783
1785{
1786 BOARD_ITEM* parent = aItem->Parent();
1787
1788 if( aItem->OfKind( PNS::ITEM::SOLID_T ) )
1789 {
1790 PAD* pad = static_cast<PAD*>( parent );
1791 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1792
1793 m_fpOffsets[ pad ].p_old = pos;
1794 return;
1795 }
1796
1797 if( parent )
1798 {
1799 m_commit->Remove( parent );
1800 }
1801}
1802
1803
1805{
1806}
1807
1808
1810{
1811 BOARD_ITEM* board_item = aItem->Parent();
1812
1813 switch( aItem->Kind() )
1814 {
1815 case PNS::ITEM::ARC_T:
1816 {
1817 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1818 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
1819 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape() );
1820
1821 m_commit->Modify( arc_board );
1822
1823 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
1824 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
1825 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
1826 arc_board->SetWidth( arc->Width() );
1827 break;
1828 }
1829
1831 {
1832 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1833 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
1834 const SEG& s = seg->Seg();
1835
1836 m_commit->Modify( track );
1837
1838 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1839 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1840 track->SetWidth( seg->Width() );
1841 break;
1842 }
1843
1844 case PNS::ITEM::VIA_T:
1845 {
1846 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
1847 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1848
1849 m_commit->Modify( via_board );
1850
1851 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1852 via_board->SetWidth( via->Diameter() );
1853 via_board->SetDrill( via->Drill() );
1854 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
1855 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1856 via_board->SetIsFree( via->IsFree() );
1857 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1858 ToLAYER_ID( via->Layers().End() ) );
1859 break;
1860 }
1861
1862 case PNS::ITEM::SOLID_T:
1863 {
1864 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1865 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1866
1867 // Don't add to commit; we'll add the parent footprints when processing the m_fpOffsets
1868
1869 m_fpOffsets[pad].p_old = pad->GetPosition();
1870 m_fpOffsets[pad].p_new = pos;
1871 break;
1872 }
1873
1874 default:
1875 m_commit->Modify( aItem->Parent() );
1876 break;
1877 }
1878}
1879
1880
1882{
1883 modifyBoardItem( aItem );
1884}
1885
1886
1888{
1889}
1890
1891
1893{
1894 BOARD_CONNECTED_ITEM* newBoardItem = nullptr;
1895 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem->Net() );
1896
1897 if( !net )
1899
1900 switch( aItem->Kind() )
1901 {
1902 case PNS::ITEM::ARC_T:
1903 {
1904 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1905 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape() ) );
1906 new_arc->SetWidth( arc->Width() );
1907 new_arc->SetLayer( ToLAYER_ID( arc->Layers().Start() ) );
1908 new_arc->SetNet( net );
1909 newBoardItem = new_arc;
1910 break;
1911 }
1912
1914 {
1915 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1916 PCB_TRACK* track = new PCB_TRACK( m_board );
1917 const SEG& s = seg->Seg();
1918 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1919 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1920 track->SetWidth( seg->Width() );
1921 track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
1922 track->SetNet( net );
1923 newBoardItem = track;
1924 break;
1925 }
1926
1927 case PNS::ITEM::VIA_T:
1928 {
1929 PCB_VIA* via_board = new PCB_VIA( m_board );
1930 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1931 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1932 via_board->SetWidth( via->Diameter() );
1933 via_board->SetDrill( via->Drill() );
1934 via_board->SetNet( net );
1935 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1936 via_board->SetIsFree( via->IsFree() );
1937 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1938 ToLAYER_ID( via->Layers().End() ) );
1939 newBoardItem = via_board;
1940 break;
1941 }
1942
1943 case PNS::ITEM::SOLID_T:
1944 {
1945 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1946 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1947
1948 m_fpOffsets[pad].p_new = pos;
1949 return nullptr;
1950 }
1951
1952 default:
1953 return nullptr;
1954 }
1955
1956 if( net->GetNetCode() <= 0 )
1957 {
1958 NETINFO_ITEM* newNetInfo = newBoardItem->GetNet();
1959
1960 newNetInfo->SetParent( m_board );
1961 newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->m_DefaultNetClass );
1962 }
1963
1964 return newBoardItem;
1965}
1966
1967
1969{
1970 BOARD_CONNECTED_ITEM* boardItem = createBoardItem( aItem );
1971
1972 if( boardItem )
1973 {
1974 aItem->SetParent( boardItem );
1975 boardItem->ClearFlags();
1976
1977 m_commit->Add( boardItem );
1978 }
1979}
1980
1981
1983{
1984 std::set<FOOTPRINT*> processedFootprints;
1985
1986 EraseView();
1987
1988 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
1989 {
1990 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
1991 FOOTPRINT* footprint = pad->GetParentFootprint();
1992 VECTOR2I p_orig = footprint->GetPosition();
1993 VECTOR2I p_new = p_orig + offset;
1994
1995 if( processedFootprints.find( footprint ) != processedFootprints.end() )
1996 continue;
1997
1998 processedFootprints.insert( footprint );
1999 m_commit->Modify( footprint );
2000 footprint->SetPosition( p_new );
2001 }
2002
2003 m_fpOffsets.clear();
2004
2005 m_commit->Push( _( "Routing" ), m_commitFlags );
2006 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2007}
2008
2009
2011{
2012 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
2013}
2014
2015
2017{
2018 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
2019
2020 if( m_previewItems )
2021 {
2023 delete m_previewItems;
2024 }
2025
2026 m_view = aView;
2029
2030 if(m_view)
2032
2033 delete m_debugDecorator;
2034
2035 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR();
2036 m_debugDecorator = dec;
2037
2038 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2039
2040 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2041 dec->SetView( m_view );
2042}
2043
2044
2046{
2047 if( aNet )
2048 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2049 else
2050 return -1;
2051}
2052
2053
2055{
2056 if( aNet )
2057 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2058 else
2059 return wxEmptyString;
2060}
2061
2062
2064{
2065 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2066}
2067
2068
2070{
2072}
2073
2074
2076{
2077 return m_ruleResolver;
2078}
2079
2080
2082{
2083 m_tool = aTool;
2084 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2085}
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:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:226
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:91
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:291
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:260
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:248
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:231
virtual bool IsLocked() const
Definition: board_item.cpp:74
virtual bool IsOnCopperLayer() const
Definition: board_item.h:151
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:282
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:2373
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:1874
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1803
const ZONES & Zones() const
Definition: board.h:327
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition: board.cpp:800
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition: board.cpp:1824
const FOOTPRINTS & Footprints() const
Definition: board.h:323
const TRACKS & Tracks() const
Definition: board.h:321
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:794
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:460
const DRAWINGS & Drawings() const
Definition: board.h:325
const Vec & GetOrigin() const
Definition: box2.h:200
const SizeVec & GetSize() const
Definition: box2.h:196
wxString GetName() const
Definition: drc_rule.h:149
SEVERITY GetSeverity() const
Definition: drc_rule.h:162
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:141
bool IsNull() const
Definition: drc_rule.h:136
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:126
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:128
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:316
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2315
bool IsNetTie() const
Definition: footprint.h:283
VECTOR2I GetPosition() const override
Definition: footprint.h:209
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:117
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:122
std::map< wxString, KIGFX::COLOR4D > & GetNetclassColorMap()
Definition: pcb_painter.h:120
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:271
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:315
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:1631
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:197
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:412
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:215
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1601
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1558
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: layer_ids.h:575
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:418
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:863
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:383
Definition: pad.h:53
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:386
const VECTOR2I & GetDrillSize() const
Definition: pad.h:261
PAD_ATTRIB GetAttribute() const
Definition: pad.h:389
const VECTOR2I & GetOffset() const
Definition: pad.h:268
VECTOR2I ShapePos() const
Definition: pad.cpp:923
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition: pad.cpp:479
bool IsFreePad() const
Definition: pad.cpp:305
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:353
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:488
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:525
int GetPadToDieLength() const
Definition: pad.h:402
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:315
const VECTOR2I & GetMid() const
Definition: pcb_track.h:316
std::vector< VECTOR2I > GetConnectionPoints() const
Definition: pcb_shape.cpp:324
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:107
int GetWidth() const
Definition: pcb_track.h:108
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:110
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:113
const VECTOR2I & GetStart() const
Definition: pcb_track.h:114
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:111
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:622
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:951
VECTOR2I GetPosition() const override
Definition: pcb_track.h:473
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:588
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:623
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:474
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
Definition: pcb_track.cpp:902
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_track.cpp:846
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:412
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:945
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:560
VIATYPE GetViaType() const
Definition: pcb_track.h:411
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:923
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:185
virtual ITEM * ParentPadVia() const
Definition: pns_item.h:261
virtual NET_HANDLE Net() const
Definition: pns_item.h:193
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:166
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:192
virtual int Layer() const
Definition: pns_item.h:199
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:224
@ SEGMENT_T
Definition: pns_item.h:105
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:184
const LAYER_RANGE & Layers() const
Definition: pns_item.h:195
bool OfKind(int aKindMask) const
Definition: pns_item.h:174
bool IsVirtual() const
Definition: pns_item.h:263
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:236
virtual BOARD_ITEM * BoardItem() const
Definition: pns_item.h:190
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:145
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:400
VECTOR2_TRAITS< int >::extended_type extended_type
Definition: vector2d.h:72
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: zone.cpp:821
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:710
bool GetDoNotAllowVias() const
Definition: zone.h:712
bool GetDoNotAllowPads() const
Definition: zone.h:714
bool GetDoNotAllowTracks() const
Definition: zone.h:713
SHAPE_POLY_SET * Outline()
Definition: zone.h:336
bool GetDoNotAllowFootprints() const
Definition: zone.h:715
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:129
DRC_CONSTRAINT_T
Definition: drc_rule.h:45
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:63
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:66
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:56
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:50
@ LENGTH_CONSTRAINT
Definition: drc_rule.h:64
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:47
@ MAX_UNCOUPLED_CONSTRAINT
Definition: drc_rule.h:67
@ SKEW_CONSTRAINT
Definition: drc_rule.h:65
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:48
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:51
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:70
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:49
#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:881
@ 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:1022
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< int > VECTOR2I
Definition: vector2d.h:602