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