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 The 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 <layer_range.h>
29#include <pad.h>
30#include <pcb_track.h>
31#include <zone.h>
32#include <pcb_shape.h>
33#include <pcb_generator.h>
34#include <pcb_text.h>
35#include <pcb_table.h>
36#include <pcb_tablecell.h>
37#include <board_commit.h>
38#include <layer_ids.h>
39#include <kidialog.h>
40#include <tools/pcb_tool_base.h>
41#include <tool/tool_manager.h>
43
45#include <pcb_painter.h>
46
47#include <geometry/shape.h>
49#include <geometry/shape_arc.h>
51
52#include <drc/drc_rule.h>
53#include <drc/drc_engine.h>
54
56
57#include <wx/log.h>
58
59#include <memory>
60
61#include <advanced_config.h>
62#include <pcbnew_settings.h>
63#include <macros.h>
64
65#include "pns_kicad_iface.h"
66#include "pns_arc.h"
67#include "pns_sizes_settings.h"
68#include "pns_item.h"
69#include "pns_layerset.h"
70#include "pns_line.h"
71#include "pns_solid.h"
72#include "pns_segment.h"
73#include "pns_node.h"
74#include "pns_router.h"
75#include "pns_debug_decorator.h"
76#include "router_preview_item.h"
77
79
80
82{
83 const PNS::ITEM* A;
84 const PNS::ITEM* B;
85 bool Flag;
86
87 bool operator==(const CLEARANCE_CACHE_KEY& other) const
88 {
89 return A == other.A && B == other.B && Flag == other.Flag;
90 }
91};
92
93namespace std
94{
95 template <>
97 {
98 std::size_t operator()( const CLEARANCE_CACHE_KEY& k ) const
99 {
100 size_t retval = 0xBADC0FFEE0DDF00D;
101 hash_combine( retval, hash<const void*>()( k.A ), hash<const void*>()( k.B ), hash<int>()( k.Flag ) );
102 return retval;
103 }
104 };
105}
106
107
109{
110public:
111 PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER_IFACE* aRouterIface );
113
114 int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
115 bool aUseClearanceEpsilon = true ) override;
116
118 int DpNetPolarity( PNS::NET_HANDLE aNet ) override;
119 bool DpNetPair( const PNS::ITEM* aItem, PNS::NET_HANDLE& aNetP,
120 PNS::NET_HANDLE& aNetN ) override;
121
122 int NetCode( PNS::NET_HANDLE aNet ) override;
123 wxString NetName( PNS::NET_HANDLE aNet ) override;
124
125 bool IsInNetTie( const PNS::ITEM* aA ) override;
126 bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
127 const PNS::ITEM* aCollidingItem ) override;
128
129 bool IsDrilledHole( const PNS::ITEM* aItem ) override;
130 bool IsNonPlatedSlot( const PNS::ITEM* aItem ) override;
131
136 bool IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem, bool* aEnforce ) override;
137
138 bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
139 const PNS::ITEM* aItemB, int aLayer,
140 PNS::CONSTRAINT* aConstraint ) override;
141
142 int ClearanceEpsilon() const override { return m_clearanceEpsilon; }
143
144 void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
145 void ClearCaches() override;
146 void ClearTemporaryCaches() override;
147
148private:
149 BOARD_ITEM* getBoardItem( const PNS::ITEM* aItem, PCB_LAYER_ID aBoardLayer, int aIdx = 0 );
150
151private:
158
159 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
160 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_tempClearanceCache;
161};
162
163
165 PNS::ROUTER_IFACE* aRouterIface ) :
166 m_routerIface( aRouterIface ),
167 m_board( aBoard ),
168 m_dummyTracks{ { aBoard }, { aBoard } },
169 m_dummyArcs{ { aBoard }, { aBoard } },
170 m_dummyVias{ { aBoard }, { aBoard } }
171{
172 for( PCB_TRACK& track : m_dummyTracks )
173 track.SetFlags( ROUTER_TRANSIENT );
174
175 for( PCB_ARC& arc : m_dummyArcs )
176 arc.SetFlags( ROUTER_TRANSIENT );
177
178 for ( PCB_VIA& via : m_dummyVias )
179 via.SetFlags( ROUTER_TRANSIENT );
180
181 if( aBoard )
182 m_clearanceEpsilon = aBoard->GetDesignSettings().GetDRCEpsilon();
183 else
184 m_clearanceEpsilon = 0;
185}
186
187
189{
190}
191
192
194{
195 BOARD_ITEM* item = aA->BoardItem();
196
197 return item && item->GetParentFootprint() && item->GetParentFootprint()->IsNetTie();
198}
199
200
202 const VECTOR2I& aCollisionPos,
203 const PNS::ITEM* aCollidingItem )
204{
205 if( !aItem || !aCollidingItem )
206 return false;
207
208 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
209 BOARD_ITEM* item = aItem->BoardItem();
210 BOARD_ITEM* collidingItem = aCollidingItem->BoardItem();
211
212 FOOTPRINT* collidingFp = collidingItem->GetParentFootprint();
213 FOOTPRINT* itemFp = item ? item->GetParentFootprint() : nullptr;
214
215 if( collidingFp && itemFp && ( collidingFp == itemFp ) && itemFp->IsNetTie() )
216 {
217 // Two items colliding from the same net tie footprint are not checked
218 return true;
219 }
220
221 if( drcEngine )
222 {
223 return drcEngine->IsNetTieExclusion( NetCode( aItem->Net() ),
225 aCollisionPos, collidingItem );
226 }
227
228 return false;
229}
230
231
232bool PNS_PCBNEW_RULE_RESOLVER::IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem,
233 bool* aEnforce )
234{
235 auto checkKeepout =
236 []( const ZONE* aKeepout, const BOARD_ITEM* aOther )
237 {
238 if( !aOther )
239 return false;
240
241 if( aKeepout->GetDoNotAllowTracks() && aOther->IsType( { PCB_ARC_T, PCB_TRACE_T } ) )
242 return true;
243
244 if( aKeepout->GetDoNotAllowVias() && aOther->Type() == PCB_VIA_T )
245 return true;
246
247 if( aKeepout->GetDoNotAllowPads() && aOther->Type() == PCB_PAD_T )
248 return true;
249
250 // Incomplete test, but better than nothing:
251 if( aKeepout->GetDoNotAllowFootprints() && aOther->Type() == PCB_PAD_T )
252 {
253 return !aKeepout->GetParentFootprint()
254 || aKeepout->GetParentFootprint() != aOther->GetParentFootprint();
255 }
256
257 return false;
258 };
259
260 if( aObstacle->Parent() && aObstacle->Parent()->Type() == PCB_ZONE_T )
261 {
262 const ZONE* zone = static_cast<ZONE*>( aObstacle->Parent() );
263
264 if( zone->GetIsRuleArea() && zone->HasKeepoutParametersSet() )
265 {
266 *aEnforce = checkKeepout( zone,
268 aObstacle->Layer() ) ) );
269 return true;
270 }
271 }
272
273 return false;
274}
275
276
277static bool isCopper( const PNS::ITEM* aItem )
278{
279 if ( !aItem )
280 return false;
281
282 const BOARD_ITEM *parent = aItem->Parent();
283
284 return !parent || parent->IsOnCopperLayer();
285}
286
287
288static bool isHole( const PNS::ITEM* aItem )
289{
290 if ( !aItem )
291 return false;
292
293 return aItem->OfKind( PNS::ITEM::HOLE_T );
294}
295
296
297static bool isEdge( const PNS::ITEM* aItem )
298{
299 if ( !aItem )
300 return false;
301
302 const PCB_SHAPE *parent = dynamic_cast<PCB_SHAPE*>( aItem->BoardItem() );
303
304 return parent && ( parent->IsOnLayer( Edge_Cuts ) || parent->IsOnLayer( Margin ) );
305}
306
307
309{
310 if( !isHole( aItem ) )
311 return false;
312
313 BOARD_ITEM* parent = aItem->Parent();
314
315 if( !parent && aItem->ParentPadVia() )
316 parent = aItem->ParentPadVia()->Parent();
317
318 return parent && parent->HasDrilledHole();
319}
320
321
323{
324 if( !isHole( aItem ) )
325 return false;
326
327 BOARD_ITEM* parent = aItem->Parent();
328
329 if( !parent && aItem->ParentPadVia() )
330 parent = aItem->ParentPadVia()->Parent();
331
332 if( parent )
333 {
334 if( parent->Type() == PCB_PAD_T )
335 {
336 PAD* pad = static_cast<PAD*>( parent );
337
338 return pad->GetAttribute() == PAD_ATTRIB::NPTH
339 && pad->GetDrillSizeX() != pad->GetDrillSizeY();
340 }
341
342 // Via holes are (currently) always round, and always plated
343 }
344
345 return false;
346}
347
348
350{
351 switch( aItem->Kind() )
352 {
353 case PNS::ITEM::ARC_T:
354 m_dummyArcs[aIdx].SetLayer( aBoardLayer );
355 m_dummyArcs[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
356 m_dummyArcs[aIdx].SetStart( aItem->Anchor( 0 ) );
357 m_dummyArcs[aIdx].SetEnd( aItem->Anchor( 1 ) );
358 return &m_dummyArcs[aIdx];
359
360 case PNS::ITEM::VIA_T:
362 m_dummyVias[aIdx].SetLayer( aBoardLayer );
363 m_dummyVias[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
364 m_dummyVias[aIdx].SetStart( aItem->Anchor( 0 ) );
365 return &m_dummyVias[aIdx];
366
369 m_dummyTracks[aIdx].SetLayer( aBoardLayer );
370 m_dummyTracks[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
371 m_dummyTracks[aIdx].SetStart( aItem->Anchor( 0 ) );
372 m_dummyTracks[aIdx].SetEnd( aItem->Anchor( 1 ) );
373 return &m_dummyTracks[aIdx];
374
375 default:
376 return nullptr;
377 }
378}
379
380
382 const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
383 int aPNSLayer, PNS::CONSTRAINT* aConstraint )
384{
385 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
386
387 if( !drcEngine )
388 return false;
389
390 DRC_CONSTRAINT_T hostType;
391
392 switch ( aType )
393 {
406 default: return false; // should not happen
407 }
408
409 BOARD_ITEM* parentA = aItemA ? aItemA->BoardItem() : nullptr;
410 BOARD_ITEM* parentB = aItemB ? aItemB->BoardItem() : nullptr;
411 PCB_LAYER_ID board_layer = m_routerIface->GetBoardLayerFromPNSLayer( aPNSLayer );
412 DRC_CONSTRAINT hostConstraint;
413
414 // A track being routed may not have a BOARD_ITEM associated yet.
415 if( aItemA && !parentA )
416 parentA = getBoardItem( aItemA, board_layer, 0 );
417
418 if( aItemB && !parentB )
419 parentB = getBoardItem( aItemB, board_layer, 1 );
420
421 if( parentA )
422 hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, board_layer );
423
424 if( hostConstraint.IsNull() )
425 return false;
426
427 if( hostConstraint.GetSeverity() == RPT_SEVERITY_IGNORE )
428 {
429 aConstraint->m_Value.SetMin( -1 );
430 aConstraint->m_RuleName = hostConstraint.GetName();
431 aConstraint->m_Type = aType;
432 return true;
433 }
434
435 switch ( aType )
436 {
449 aConstraint->m_Value = hostConstraint.GetValue();
450 aConstraint->m_RuleName = hostConstraint.GetName();
451 aConstraint->m_Type = aType;
452 aConstraint->m_IsTimeDomain = hostConstraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN );
453 return true;
454
455 default:
456 return false;
457 }
458}
459
460
461void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems )
462{
463 int n_pruned = 0;
464 std::set<const PNS::ITEM*> remainingItems( aItems.begin(), aItems.end() );
465
466/* We need to carefully check both A and B item pointers in the cache against dirty/invalidated
467 items in the set, as the clearance relation is commutative ( CL[a,b] == CL[b,a] ). The code
468 below is a bit ugly, but works in O(n*log(m)) and is run once or twice during ROUTER::Move() call
469 - so I hope it still gets better performance than no cache at all */
470 for( auto it = m_clearanceCache.begin(); it != m_clearanceCache.end(); )
471 {
472 bool dirty = remainingItems.find( it->first.A ) != remainingItems.end();
473 dirty |= remainingItems.find( it->first.B) != remainingItems.end();
474
475 if( dirty )
476 {
477 it = m_clearanceCache.erase( it );
478 n_pruned++;
479 } else
480 it++;
481 }
482#if 0
483 printf("ClearCache : n_pruned %d\n", n_pruned );
484#endif
485}
486
487
489{
490 m_clearanceCache.clear();
491 m_tempClearanceCache.clear();
492}
493
494
496{
497 m_tempClearanceCache.clear();
498}
499
500
502 bool aUseClearanceEpsilon )
503{
504 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
505
506 // Search cache (used for actual board items)
507 auto it = m_clearanceCache.find( key );
508
509 if( it != m_clearanceCache.end() )
510 return it->second;
511
512 // Search cache (used for temporary items within an algorithm)
513 it = m_tempClearanceCache.find( key );
514
515 if( it != m_tempClearanceCache.end() )
516 return it->second;
517
518 PNS::CONSTRAINT constraint;
519 int rv = 0;
520 PNS_LAYER_RANGE layers;
521
522 if( !aB )
523 layers = aA->Layers();
524 else if( isEdge( aA ) )
525 layers = aB->Layers();
526 else if( isEdge( aB ) )
527 layers = aA->Layers();
528 else
529 layers = aA->Layers().Intersection( aB->Layers() );
530
531 // Normalize layer range (no -1 magic numbers)
533
534 for( int layer = layers.Start(); layer <= layers.End(); ++layer )
535 {
536 if( IsDrilledHole( aA ) && IsDrilledHole( aB ) )
537 {
538 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer, &constraint ) )
539 {
540 if( constraint.m_Value.Min() > rv )
541 rv = constraint.m_Value.Min();
542 }
543 }
544 else if( isHole( aA ) || isHole( aB ) )
545 {
546 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
547 {
548 if( constraint.m_Value.Min() > rv )
549 rv = constraint.m_Value.Min();
550 }
551 }
552
553 // No 'else'; plated holes get both HOLE_CLEARANCE and CLEARANCE
554 if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
555 {
556 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
557 {
558 if( constraint.m_Value.Min() > rv )
559 rv = constraint.m_Value.Min();
560 }
561 }
562
563 // No 'else'; non-plated milled holes get both HOLE_CLEARANCE and EDGE_CLEARANCE
564 if( isEdge( aA ) || IsNonPlatedSlot( aA ) || isEdge( aB ) || IsNonPlatedSlot( aB ) )
565 {
566 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
567 {
568 if( constraint.m_Value.Min() > rv )
569 rv = constraint.m_Value.Min();
570 }
571 }
572
573 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_PHYSICAL_CLEARANCE, aA, aB, layer, &constraint ) )
574 {
575 if( constraint.m_Value.Min() > rv )
576 rv = constraint.m_Value.Min();
577 }
578 }
579
580 if( aUseClearanceEpsilon && rv > 0 )
581 rv = std::max( 0, rv - m_clearanceEpsilon );
582
583 /*
584 * It makes no sense to put items that have no owning NODE in the cache - they can be
585 * allocated on stack and we can't really invalidate them in the cache when they are
586 * destroyed. Probably a better idea would be to use a static unique counter in PNS::ITEM
587 * constructor to generate the cache keys.
588 *
589 * However, algorithms DO greatly benefit from using the cache, so ownerless items need to be
590 * cached. In order to easily clear those only, a temporary cache is created. If this doesn't
591 * seem nice, an alternative is clearing the full cache once it reaches a certain size. Also
592 * not pretty, but VERY effective to keep things interactive.
593 */
594 if( aA && aB )
595 {
596 if ( aA->Owner() && aB->Owner() )
597 m_clearanceCache[ key ] = rv;
598 else
599 m_tempClearanceCache[ key ] = rv;
600 }
601
602 return rv;
603}
604
605
606bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth )
607{
608 VECTOR2I p;
609
610 assert( aItem->Owner() != nullptr );
611
612 auto tryGetTrackWidth =
613 []( PNS::ITEM* aPnsItem ) -> int
614 {
615 switch( aPnsItem->Kind() )
616 {
617 case PNS::ITEM::SEGMENT_T: return static_cast<PNS::SEGMENT*>( aPnsItem )->Width();
618 case PNS::ITEM::ARC_T: return static_cast<PNS::ARC*>( aPnsItem )->Width();
619 default: return -1;
620 }
621 };
622
623 int itemTrackWidth = tryGetTrackWidth( aItem );
624
625 if( itemTrackWidth > 0 )
626 {
627 *aInheritedWidth = itemTrackWidth;
628 return true;
629 }
630
631 switch( aItem->Kind() )
632 {
633 case PNS::ITEM::VIA_T: p = static_cast<PNS::VIA*>( aItem )->Pos(); break;
634 case PNS::ITEM::SOLID_T: p = static_cast<PNS::SOLID*>( aItem )->Pos(); break;
635 default: return false;
636 }
637
638 const PNS::JOINT* jt = static_cast<const PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
639
640 assert( jt != nullptr );
641
642 int mval = INT_MAX;
643
644 PNS::ITEM_SET linkedSegs( jt->CLinks() );
646
647 for( PNS::ITEM* item : linkedSegs.Items() )
648 {
649 int w = tryGetTrackWidth( item );
650
651 if( w > 0 )
652 mval = std::min( w, mval );
653 }
654
655 if( mval == INT_MAX )
656 return false;
657
658 *aInheritedWidth = mval;
659 return true;
660}
661
662
664 PNS::NET_HANDLE aNet, VECTOR2D aStartPosition )
665{
667 PNS::CONSTRAINT constraint;
668
669 if( aStartItem && m_startLayer < 0 )
670 m_startLayer = aStartItem->Layer();
671
672 aSizes.SetClearance( bds.m_MinClearance );
673 aSizes.SetMinClearance( bds.m_MinClearance );
674 aSizes.SetClearanceSource( _( "board minimum clearance" ) );
675
676 int startAnchor = 0;
677 VECTOR2I startPosInt( aStartPosition.x, aStartPosition.y );
678
679 if( aStartItem && aStartItem->Kind() == PNS::ITEM::SEGMENT_T )
680 {
681 // Find the start anchor which is closest to the start mouse location
682 double anchor0Distance = startPosInt.Distance( aStartItem->Anchor( 0 ) );
683 double anchor1Distance = startPosInt.Distance( aStartItem->Anchor( 1 ) );
684
685 if( anchor1Distance < anchor0Distance )
686 startAnchor = 1;
687 }
688
689 if( aStartItem )
690 {
691 PNS::SEGMENT dummyTrack;
692 dummyTrack.SetEnds( aStartItem->Anchor( startAnchor ), aStartItem->Anchor( startAnchor ) );
693 dummyTrack.SetLayer( m_startLayer );
694 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( aStartItem->Net() ) );
695
697 nullptr, m_startLayer, &constraint ) )
698 {
699 if( constraint.m_Value.Min() >= bds.m_MinClearance )
700 {
701 aSizes.SetClearance( constraint.m_Value.Min() );
702 aSizes.SetClearanceSource( constraint.m_RuleName );
703 }
704 }
705 }
706
707 int trackWidth = bds.m_TrackMinWidth;
708 bool found = false;
709 aSizes.SetWidthSource( _( "board minimum track width" ) );
710
711 if( bds.m_UseConnectedTrackWidth && !bds.m_TempOverrideTrackWidth && aStartItem != nullptr )
712 {
713 found = inheritTrackWidth( aStartItem, &trackWidth );
714
715 if( found )
716 aSizes.SetWidthSource( _( "existing track" ) );
717 }
718
719 if( !found && bds.UseNetClassTrack() && aStartItem )
720 {
721 PNS::SEGMENT dummyTrack;
722 dummyTrack.SetEnds( aStartItem->Anchor( startAnchor ), aStartItem->Anchor( startAnchor ) );
723 dummyTrack.SetLayer( m_startLayer );
724 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( aStartItem->Net() ) );
725
727 m_startLayer, &constraint ) )
728 {
729 trackWidth = std::max( trackWidth, constraint.m_Value.Opt() );
730 found = true;
731
732 if( trackWidth == constraint.m_Value.Opt() )
733 aSizes.SetWidthSource( constraint.m_RuleName );
734 }
735 }
736
737 if( !found )
738 {
739 trackWidth = std::max( trackWidth, bds.GetCurrentTrackWidth() );
740
741 if( bds.UseNetClassTrack() )
742 aSizes.SetWidthSource( _( "netclass 'Default'" ) );
743 else if( trackWidth == bds.GetCurrentTrackWidth() )
744 aSizes.SetWidthSource( _( "user choice" ) );
745 }
746
747 aSizes.SetTrackWidth( trackWidth );
750
751 int viaDiameter = bds.m_ViasMinSize;
752 int viaDrill = bds.m_MinThroughDrill;
753
754 PNS::VIA dummyVia, coupledVia;
755
756 if( aStartItem )
757 {
758 dummyVia.SetNet( aStartItem->Net() );
759 coupledVia.SetNet( m_ruleResolver->DpCoupledNet( aStartItem->Net() ) );
760 }
761
762 if( bds.UseNetClassVia() && aStartItem ) // netclass value
763 {
765 nullptr, m_startLayer, &constraint ) )
766 {
767 viaDiameter = std::max( viaDiameter, constraint.m_Value.Opt() );
768 }
769
771 nullptr, m_startLayer, &constraint ) )
772 {
773 viaDrill = std::max( viaDrill, constraint.m_Value.Opt() );
774 }
775 }
776 else
777 {
778 viaDiameter = bds.GetCurrentViaSize();
779 viaDrill = bds.GetCurrentViaDrill();
780 }
781
782 aSizes.SetViaDiameter( viaDiameter );
783 aSizes.SetViaDrill( viaDrill );
784
785 int diffPairWidth = bds.m_TrackMinWidth;
786 int diffPairGap = bds.m_MinClearance;
787 int diffPairViaGap = bds.m_MinClearance;
788
789 aSizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
790 aSizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
791
792 found = false;
793
794 // First try to pick up diff pair width from starting track, if enabled
795 if( bds.m_UseConnectedTrackWidth && aStartItem )
796 found = inheritTrackWidth( aStartItem, &diffPairWidth );
797
798 // Next, pick up gap from netclass, and width also if we didn't get a starting width above
799 if( bds.UseNetClassDiffPair() && aStartItem )
800 {
801 PNS::NET_HANDLE coupledNet = m_ruleResolver->DpCoupledNet( aStartItem->Net() );
802
803 PNS::SEGMENT dummyTrack;
804 dummyTrack.SetEnds( aStartItem->Anchor( 0 ), aStartItem->Anchor( 0 ) );
805 dummyTrack.SetLayer( m_startLayer );
806 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( aStartItem->Net() ) );
807
808 PNS::SEGMENT coupledTrack;
809 dummyTrack.SetEnds( aStartItem->Anchor( 0 ), aStartItem->Anchor( 0 ) );
810 dummyTrack.SetLayer( m_startLayer );
811 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( coupledNet ) );
812
813 if( !found
815 &coupledTrack, m_startLayer, &constraint ) )
816 {
817 diffPairWidth = std::max( diffPairWidth, constraint.m_Value.Opt() );
818
819 if( diffPairWidth == constraint.m_Value.Opt() )
820 aSizes.SetDiffPairWidthSource( constraint.m_RuleName );
821 }
822
824 &coupledTrack, m_startLayer, &constraint ) )
825 {
826 diffPairGap = std::max( diffPairGap, constraint.m_Value.Opt() );
827 diffPairViaGap = std::max( diffPairViaGap, constraint.m_Value.Opt() );
828
829 if( diffPairGap == constraint.m_Value.Opt() )
830 aSizes.SetDiffPairGapSource( constraint.m_RuleName );
831 }
832 }
833 else
834 {
835 diffPairWidth = bds.GetCurrentDiffPairWidth();
836 diffPairGap = bds.GetCurrentDiffPairGap();
837 diffPairViaGap = bds.GetCurrentDiffPairViaGap();
838
839 aSizes.SetDiffPairWidthSource( _( "user choice" ) );
840 aSizes.SetDiffPairGapSource( _( "user choice" ) );
841 }
842
843 aSizes.SetDiffPairWidth( diffPairWidth );
844 aSizes.SetDiffPairGap( diffPairGap );
845 aSizes.SetDiffPairViaGap( diffPairViaGap );
846 aSizes.SetDiffPairViaGapSameAsTraceGap( false );
847
848 int holeToHoleMin = bds.m_HoleToHoleMin;
849
851 &dummyVia, UNDEFINED_LAYER, &constraint ) )
852 {
853 holeToHoleMin = constraint.m_Value.Min();
854 }
855
856 aSizes.SetHoleToHole( holeToHoleMin );
857
859 &coupledVia, UNDEFINED_LAYER, &constraint ) )
860 {
861 holeToHoleMin = constraint.m_Value.Min();
862 }
863
864 aSizes.SetDiffPairHoleToHole( holeToHoleMin );
865
866 return true;
867}
868
869
870int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const
871{
873 return 0;
874
876
877 return stackup.GetLayerDistance( GetBoardLayerFromPNSLayer( aFirstLayer ),
878 GetBoardLayerFromPNSLayer( aSecondLayer ) );
879}
880
881
883{
884 return m_board->DpCoupledNet( static_cast<NETINFO_ITEM*>( aNet ) );
885}
886
887
889{
890 return m_routerIface->GetNetCode( aNet );
891}
892
893
895{
896 return m_routerIface->GetNetName( aNet );
897}
898
899
901{
902 wxString refName;
903
904 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
905 refName = net->GetNetname();
906
907 wxString dummy1;
908
909 return m_board->MatchDpSuffix( refName, dummy1 );
910}
911
912
914 PNS::NET_HANDLE& aNetN )
915{
916 if( !aItem || !aItem->Net() )
917 return false;
918
919 wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
920 wxString netNameN, netNameCoupled;
921
922 int r = m_board->MatchDpSuffix( netNameP, netNameCoupled );
923
924 if( r == 0 )
925 {
926 return false;
927 }
928 else if( r == 1 )
929 {
930 netNameN = netNameCoupled;
931 }
932 else
933 {
934 netNameN = netNameP;
935 netNameP = netNameCoupled;
936 }
937
938 PNS::NET_HANDLE netInfoP = m_board->FindNet( netNameP );
939 PNS::NET_HANDLE netInfoN = m_board->FindNet( netNameN );
940
941 if( !netInfoP || !netInfoN )
942 return false;
943
944 aNetP = netInfoP;
945 aNetN = netInfoN;
946
947 return true;
948}
949
950
952{
953public:
956 m_iface( aIface ),
957 m_view( nullptr ),
958 m_items( nullptr ),
959 m_depth( 0 )
960 {}
961
963 {
965 delete m_items;
966 }
967
968 void SetView( KIGFX::VIEW* aView )
969 {
970 Clear();
971 delete m_items;
972 m_items = nullptr;
973 m_view = aView;
974
975 if( m_view == nullptr )
976 return;
977
978 if( m_view->GetGAL() )
980
983 m_view->Add( m_items );
984 }
985
986 void AddPoint( const VECTOR2I& aP, const KIGFX::COLOR4D& aColor, int aSize,
987 const wxString& aName = wxT( "" ),
988 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
989
990 {
992
993 sh.SetWidth( 10000 );
994
995 sh.Append( aP.x - aSize, aP.y - aSize );
996 sh.Append( aP.x + aSize, aP.y + aSize );
997 sh.Append( aP.x, aP.y );
998 sh.Append( aP.x - aSize, aP.y + aSize );
999 sh.Append( aP.x + aSize, aP.y - aSize );
1000
1001 AddShape( &sh, aColor, sh.Width(), aName, aSrcLoc );
1002 }
1003
1004 void AddItem( const PNS::ITEM* aItem, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1005 const wxString& aName = wxT( "" ),
1006 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1007 {
1008 if( !m_view || !aItem )
1009 return;
1010
1011 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_iface, m_view );
1012
1013 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
1014 pitem->SetWidth( aOverrideWidth );
1015 pitem->SetDepth( nextDepth() );
1016
1017 m_items->Add( pitem );
1018 m_view->Update( m_items );
1019 }
1020
1021 void AddShape( const BOX2I& aBox, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1022 const wxString& aName = wxT( "" ),
1023 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1024 {
1026 l.SetWidth( aOverrideWidth );
1027
1028 VECTOR2I o = aBox.GetOrigin();
1029 VECTOR2I s = aBox.GetSize();
1030
1031 l.Append( o );
1032 l.Append( o.x + s.x, o.y );
1033 l.Append( o.x + s.x, o.y + s.y );
1034 l.Append( o.x, o.y + s.y );
1035 l.Append( o );
1036
1037 AddShape( &l, aColor, aOverrideWidth, aName, aSrcLoc );
1038 }
1039
1040 void AddShape( const SHAPE* aShape, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1041 const wxString& aName = wxT( "" ),
1042 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1043 {
1044 if( !m_view || !aShape )
1045 return;
1046
1047 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_iface, m_view );
1048
1049 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
1050 pitem->SetWidth( aOverrideWidth );
1051 pitem->SetDepth( nextDepth() );
1052
1053 m_items->Add( pitem );
1054 m_view->Update( m_items );
1055 }
1056
1057 void Clear() override
1058 {
1059 if( m_view && m_items )
1060 {
1061 m_items->FreeItems();
1062 m_view->Update( m_items );
1063
1064 if( m_view->GetGAL() )
1066 }
1067 }
1068
1069 virtual void Message( const wxString& msg,
1070 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1071 {
1072 printf("PNS: %s\n", msg.c_str().AsChar() );
1073 }
1074
1075private:
1076 double nextDepth()
1077 {
1078 // Use different depths so that the transculent shapes won't overwrite each other.
1079
1080 m_depth++;
1081
1082 if( m_depth >= 0 && m_view->GetGAL() )
1084
1085 return m_depth;
1086 }
1087
1091
1092 double m_depth;
1093};
1094
1095
1097{
1098 return m_debugDecorator;
1099}
1100
1101
1103{
1104 m_ruleResolver = nullptr;
1105 m_board = nullptr;
1106 m_world = nullptr;
1107 m_debugDecorator = nullptr;
1108 m_startLayer = -1;
1109}
1110
1111
1113{
1114 m_tool = nullptr;
1115 m_view = nullptr;
1116 m_previewItems = nullptr;
1117 m_commitFlags = 0;
1118}
1119
1120
1122{
1123 delete m_ruleResolver;
1124 delete m_debugDecorator;
1125}
1126
1127
1129{
1130 if( m_previewItems )
1131 {
1133 delete m_previewItems;
1134 }
1135}
1136
1137
1138std::vector<std::unique_ptr<PNS::SOLID>> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1139{
1140 std::vector<std::unique_ptr<PNS::SOLID>> solids;
1141 PNS_LAYER_RANGE layers( 0, aPad->BoardCopperLayerCount() - 1 );
1142 LSEQ lmsk = aPad->GetLayerSet().CuStack();
1143
1144 // ignore non-copper pads except for those with holes
1145 if( lmsk.empty() && aPad->GetDrillSize().x == 0 )
1146 return solids;
1147
1148 switch( aPad->GetAttribute() )
1149 {
1150 case PAD_ATTRIB::PTH:
1151 case PAD_ATTRIB::NPTH:
1152 break;
1153
1154 case PAD_ATTRIB::CONN:
1155 case PAD_ATTRIB::SMD:
1156 {
1157 bool is_copper = false;
1158
1159 if( !lmsk.empty() && aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1160 {
1161 layers = SetLayersFromPCBNew( lmsk.front(), lmsk.front() );
1162 is_copper = true;
1163 }
1164
1165 if( !is_copper )
1166 return solids;
1167
1168 break;
1169 }
1170
1171 default:
1172 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1173 return solids;
1174 }
1175
1176 auto makeSolidFromPadLayer =
1177 [&]( PCB_LAYER_ID aLayer )
1178 {
1179 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1180
1181 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1182 solid->SetRoutable( false );
1183
1184 if( aPad->Padstack().Mode() == PADSTACK::MODE::CUSTOM )
1185 {
1186 solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
1187 }
1188 else if( aPad->Padstack().Mode() == PADSTACK::MODE::FRONT_INNER_BACK )
1189 {
1190 if( aLayer == F_Cu || aLayer == B_Cu )
1191 solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
1192 else
1193 solid->SetLayers( PNS_LAYER_RANGE( 1, aPad->BoardCopperLayerCount() - 2 ) );
1194 }
1195 else
1196 {
1197 solid->SetLayers( layers );
1198 }
1199
1200 solid->SetNet( aPad->GetNet() );
1201 solid->SetParent( aPad );
1202 solid->SetPadToDie( aPad->GetPadToDieLength() );
1203 solid->SetPadToDieDelay( aPad->GetPadToDieDelay() );
1204 solid->SetOrientation( aPad->GetOrientation() );
1205
1206 if( aPad->IsFreePad() )
1207 solid->SetIsFreePad();
1208
1209 VECTOR2I wx_c = aPad->ShapePos( aLayer );
1210 VECTOR2I offset = aPad->GetOffset( aLayer );
1211
1212 VECTOR2I c( wx_c.x, wx_c.y );
1213
1214 RotatePoint( offset, aPad->GetOrientation() );
1215
1216 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1217 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1218
1219 if( aPad->GetDrillSize().x > 0 )
1220 {
1221 solid->SetHole( new PNS::HOLE( aPad->GetEffectiveHoleShape()->Clone() ) );
1222 solid->Hole()->SetLayers( PNS_LAYER_RANGE( 0, aPad->BoardCopperLayerCount() - 1 ) );
1223 }
1224
1225 // We generate a single SOLID for a pad, so we have to treat it as ALWAYS_FLASHED and
1226 // then perform layer-specific flashing tests internally.
1227 const std::shared_ptr<SHAPE>& shape =
1228 aPad->GetEffectiveShape( aLayer, FLASHING::ALWAYS_FLASHED );
1229
1230 if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 )
1231 {
1232 std::vector<const SHAPE*> subshapes;
1233 shape->GetIndexableSubshapes( subshapes );
1234
1235 solid->SetShape( subshapes[0]->Clone() );
1236 }
1237 // For anything that's not a single shape we use a polygon. Multiple shapes have a tendency
1238 // to confuse the hull generator. https://gitlab.com/kicad/code/kicad/-/issues/15553
1239 else
1240 {
1241 const std::shared_ptr<SHAPE_POLY_SET>& poly =
1242 aPad->GetEffectivePolygon( aLayer, ERROR_OUTSIDE );
1243
1244 if( poly->OutlineCount() )
1245 solid->SetShape( new SHAPE_SIMPLE( poly->Outline( 0 ) ) );
1246 }
1247
1248 solids.emplace_back( std::move( solid ) );
1249 };
1250
1251 aPad->Padstack().ForEachUniqueLayer( makeSolidFromPadLayer );
1252
1253 return solids;
1254}
1255
1256
1257std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1258{
1259 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1260 aTrack->GetNet() );
1261
1262 segment->SetWidth( aTrack->GetWidth() );
1263 segment->SetLayer( GetPNSLayerFromBoardLayer( aTrack->GetLayer() ) );
1264 segment->SetParent( aTrack );
1265
1266 if( aTrack->IsLocked() )
1267 segment->Mark( PNS::MK_LOCKED );
1268
1269 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aTrack->GetParentGroup() ) )
1270 {
1271 if( !generator->HasFlag( IN_EDIT ) )
1272 segment->Mark( PNS::MK_LOCKED );
1273 }
1274
1275 return segment;
1276}
1277
1278
1279std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1280{
1281 auto arc = std::make_unique<PNS::ARC>( SHAPE_ARC( aArc->GetStart(), aArc->GetMid(),
1282 aArc->GetEnd(), aArc->GetWidth() ),
1283 aArc->GetNet() );
1284
1285 arc->SetLayer( GetPNSLayerFromBoardLayer( aArc->GetLayer() ) );
1286 arc->SetParent( aArc );
1287
1288 if( aArc->IsLocked() )
1289 arc->Mark( PNS::MK_LOCKED );
1290
1291 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aArc->GetParentGroup() ) )
1292 {
1293 if( !generator->HasFlag( IN_EDIT ) )
1294 arc->Mark( PNS::MK_LOCKED );
1295 }
1296
1297 return arc;
1298}
1299
1300
1301std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1302{
1303 PCB_LAYER_ID top, bottom;
1304 aVia->LayerPair( &top, &bottom );
1305
1306 /*
1307 * NOTE about PNS via padstacks:
1308 *
1309 * PNS::VIA has no knowledge about how many layers are in the board, and there is no fixed
1310 * reference to the "back layer" in the PNS. That means that there is no way for a VIA to know
1311 * the difference between its bottom layer and the bottom layer of the overall board (i.e. if
1312 * the via is a blind/buried via). For this reason, PNS::VIA::STACK_MODE::FRONT_INNER_BACK
1313 * cannot be used for blind/buried vias. This mode will always assume that the via's top layer
1314 * is the "front" layer and the via's bottom layer is the "back" layer, but from KiCad's point
1315 * of view, at least at the moment, front/inner/back padstack mode is board-scoped, not
1316 * via-scoped, so a buried via would only use the inner layer size even if its padstack mode is
1317 * set to PADSTACK::MODE::FRONT_INNER_BACK and different sizes are defined for front or back.
1318 * For this kind of via, the PNS VIA stack mode will be set to NORMAL because effectively it has
1319 * the same size on every layer it exists on.
1320 */
1321
1322 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1323 SetLayersFromPCBNew( aVia->TopLayer(), aVia->BottomLayer() ),
1324 0,
1325 aVia->GetDrillValue(),
1326 aVia->GetNet(),
1327 aVia->GetViaType() );
1328 via->SetUnconnectedLayerMode( aVia->Padstack().UnconnectedLayerMode() );
1329
1330 auto syncDiameter =
1331 [&]( PCB_LAYER_ID aLayer )
1332 {
1333 via->SetDiameter( GetPNSLayerFromBoardLayer( aLayer ), aVia->GetWidth( aLayer ) );
1334 };
1335
1336 switch( aVia->Padstack().Mode() )
1337 {
1339 via->SetDiameter( 0, aVia->GetWidth( PADSTACK::ALL_LAYERS ) );
1340 break;
1341
1343 if( aVia->GetViaType() == VIATYPE::BLIND_BURIED )
1344 {
1345 via->SetDiameter( 0, aVia->GetWidth( PADSTACK::INNER_LAYERS ) );
1346 }
1347 else
1348 {
1350 aVia->Padstack().ForEachUniqueLayer( syncDiameter );
1351 }
1352
1353 break;
1354
1356 via->SetStackMode( PNS::VIA::STACK_MODE::CUSTOM );
1357 aVia->Padstack().ForEachUniqueLayer( syncDiameter );
1358 }
1359
1360 via->SetParent( aVia );
1361
1362 if( aVia->IsLocked() )
1363 via->Mark( PNS::MK_LOCKED );
1364
1365 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aVia->GetParentGroup() ) )
1366 {
1367 if( !generator->HasFlag( IN_EDIT ) )
1368 via->Mark( PNS::MK_LOCKED );
1369 }
1370
1371 via->SetIsFree( aVia->GetIsFree() );
1372 via->SetHole( PNS::HOLE::MakeCircularHole( aVia->GetPosition(),
1373 aVia->GetDrillValue() / 2,
1374 SetLayersFromPCBNew( aVia->TopLayer(), aVia->BottomLayer() ) ) );
1375
1376 return via;
1377}
1378
1379
1380bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1381{
1382 static wxString msg;
1383 SHAPE_POLY_SET* poly;
1384
1385 if( !aZone->GetIsRuleArea() || !aZone->HasKeepoutParametersSet() )
1386 return false;
1387
1388 LSET layers = aZone->GetLayerSet();
1389
1390 poly = aZone->Outline();
1391 poly->CacheTriangulation( false );
1392
1393 if( !poly->IsTriangulationUpToDate() )
1394 {
1395 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1396 msg.Printf( _( "%s is malformed." ), aZone->GetItemDescription( &unitsProvider, true ) );
1397
1398 KIDIALOG dlg( nullptr, msg, KIDIALOG::KD_WARNING );
1399 dlg.ShowDetailedText( _( "This zone cannot be handled by the router.\n"
1400 "Please verify it is not a self-intersecting polygon." ) );
1401 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1402 dlg.ShowModal();
1403
1404 return false;
1405 }
1406
1408 {
1409 if( !layers[ layer ] )
1410 continue;
1411
1412 for( int polyId = 0; polyId < poly->TriangulatedPolyCount(); polyId++ )
1413 {
1414 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( polyId );
1415
1416 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1417 {
1418 VECTOR2I a, b, c;
1419 tri->GetTriangle( i, a, b, c );
1420 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1421
1422 triShape->Append( a );
1423 triShape->Append( b );
1424 triShape->Append( c );
1425
1426 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1427
1428 solid->SetLayer( GetPNSLayerFromBoardLayer( layer ) );
1429 solid->SetNet( nullptr );
1430 solid->SetParent( aZone );
1431 solid->SetShape( triShape );
1432 solid->SetIsCompoundShapePrimitive();
1433 solid->SetRoutable( false );
1434
1435 aWorld->Add( std::move( solid ) );
1436 }
1437 }
1438 }
1439
1440 return true;
1441}
1442
1443
1445{
1446 if( !IsKicadCopperLayer( aLayer ) )
1447 return false;
1448
1449 if( aItem->Type() == PCB_FIELD_T && !static_cast<PCB_FIELD*>( aItem )->IsVisible() )
1450 return false;
1451
1452 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1453 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1454
1455 solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
1456 solid->SetNet( nullptr );
1457 solid->SetParent( aItem );
1458 solid->SetShape( shape ); // takes ownership
1459 solid->SetRoutable( false );
1460
1461 SHAPE_POLY_SET cornerBuffer;
1462
1463 aItem->TransformShapeToPolygon( cornerBuffer, aItem->GetLayer(), 0, aItem->GetMaxError(), ERROR_OUTSIDE );
1464
1465 cornerBuffer.Simplify();
1466
1467 if( !cornerBuffer.OutlineCount() )
1468 return false;
1469
1470 for( const VECTOR2I& pt : cornerBuffer.Outline( 0 ).CPoints() )
1471 shape->Append( pt );
1472
1473 aWorld->Add( std::move( solid ) );
1474
1475 return true;
1476}
1477
1478
1480{
1481 if( aItem->GetLayer() == Edge_Cuts
1482 || aItem->GetLayer() == Margin
1483 || IsKicadCopperLayer( aItem->GetLayer() ) )
1484 {
1485 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1486
1487 for( SHAPE* shape : shapes )
1488 {
1489 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1490
1491 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1492 {
1493 solid->SetLayers( PNS_LAYER_RANGE( 0, m_board->GetCopperLayerCount() - 1 ) );
1494 solid->SetRoutable( false );
1495 }
1496 else
1497 {
1498 solid->SetLayer( GetPNSLayerFromBoardLayer( aItem->GetLayer() ) );
1499 solid->SetRoutable( aItem->Type() != PCB_TABLECELL_T );
1500 }
1501
1502 if( aItem->GetLayer() == Edge_Cuts )
1503 {
1504 switch( shape->Type() )
1505 {
1506 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1507 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1508 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1509 default: /* remaining shapes don't have width */ break;
1510 }
1511 }
1512
1513 solid->SetAnchorPoints( aItem->GetConnectionPoints() );
1514 solid->SetNet( aItem->GetNet() );
1515 solid->SetParent( aItem );
1516 solid->SetShape( shape ); // takes ownership
1517
1518 if( shapes.size() > 1 )
1519 solid->SetIsCompoundShapePrimitive();
1520
1521 aWorld->Add( std::move( solid ) );
1522 }
1523
1524 return true;
1525 }
1526
1527 return false;
1528}
1529
1530
1532{
1533 m_board = aBoard;
1534 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1535}
1536
1537
1539{
1540 return ::IsCopperLayer( GetBoardLayerFromPNSLayer( aPNSLayer ) );
1541}
1542
1543
1544
1546{
1547 return ::IsCopperLayer( aKicadLayer );
1548}
1549
1550
1552{
1553 if( !m_view )
1554 return false;
1555
1556 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1557 {
1559 return true;
1560 }
1561
1562 return false;
1563}
1564
1565
1566bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1567{
1569 if( aLayer < 0 )
1570 return true;
1571
1572 if( aItem->Parent() )
1573 {
1574 switch( aItem->Parent()->Type() )
1575 {
1576 case PCB_VIA_T:
1577 {
1578 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1579
1580 return via->FlashLayer( GetBoardLayerFromPNSLayer( aLayer ) );
1581 }
1582
1583 case PCB_PAD_T:
1584 {
1585 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1586
1587 return pad->FlashLayer( GetBoardLayerFromPNSLayer( aLayer ) );
1588 }
1589
1590 default:
1591 break;
1592 }
1593 }
1594
1595 if( aItem->OfKind( PNS::ITEM::VIA_T ) )
1596 return static_cast<const PNS::VIA*>( aItem )->ConnectsLayer( aLayer );
1597
1598 return aItem->Layers().Overlaps( aLayer );
1599}
1600
1601
1603 const PNS_LAYER_RANGE& aLayer ) const
1604{
1605 PNS_LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
1606
1607 if( aItem->Parent() )
1608 {
1609 switch( aItem->Parent()->Type() )
1610 {
1611 case PCB_VIA_T:
1612 {
1613 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1614
1615 for( int layer = test.Start(); layer <= test.End(); ++layer )
1616 {
1617 if( via->FlashLayer( GetBoardLayerFromPNSLayer( layer ) ) )
1618 return true;
1619 }
1620
1621 return false;
1622 }
1623
1624 case PCB_PAD_T:
1625 {
1626 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1627
1628 for( int layer = test.Start(); layer <= test.End(); ++layer )
1629 {
1630 if( pad->FlashLayer( GetBoardLayerFromPNSLayer( layer ) ) )
1631 return true;
1632 }
1633
1634 return false;
1635 }
1636
1637 default:
1638 break;
1639 }
1640 }
1641
1642 if( aItem->OfKind( PNS::ITEM::VIA_T ) )
1643 {
1644 const PNS::VIA* via = static_cast<const PNS::VIA*>( aItem );
1645
1646 for( int layer = test.Start(); layer <= test.End(); ++layer )
1647 {
1648 if( via->ConnectsLayer( layer ) )
1649 return true;
1650 }
1651
1652 return false;
1653 }
1654
1655 return test.Start() <= test.End();
1656}
1657
1658
1660{
1661 // by default, all items are visible (new ones created by the router have parent == NULL
1662 // as they have not been committed yet to the BOARD)
1663 if( !m_view || !aItem->Parent() )
1664 return true;
1665
1666 BOARD_ITEM* item = aItem->Parent();
1667 bool isOnVisibleLayer = true;
1668 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1669
1670 if( settings->GetHighContrast() )
1671 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1672
1673 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1674 {
1675 for( PCB_LAYER_ID layer : item->GetLayerSet() )
1676 {
1677 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1678 return true;
1679 }
1680 }
1681
1682 // Items hidden in the router are not hidden on the board
1683 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1684 return true;
1685
1686 return false;
1687}
1688
1689
1691{
1692 if( !m_board )
1693 {
1694 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1695 return;
1696 }
1697
1698 int worstClearance = m_board->GetMaxClearanceValue();
1699
1700 m_world = aWorld;
1701
1702 for( BOARD_ITEM* gitem : m_board->Drawings() )
1703 {
1704 if ( gitem->Type() == PCB_SHAPE_T || gitem->Type() == PCB_TEXTBOX_T )
1705 {
1706 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1707 }
1708 else if( gitem->Type() == PCB_TEXT_T )
1709 {
1710 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1711 }
1712 else if( gitem->Type() == PCB_TABLE_T )
1713 {
1714 syncTextItem( aWorld, static_cast<PCB_TABLE*>( gitem ), gitem->GetLayer() );
1715 }
1716 }
1717
1718 SHAPE_POLY_SET buffer;
1719 SHAPE_POLY_SET* boardOutline = nullptr;
1720
1721 if( m_board->GetBoardPolygonOutlines( buffer ) )
1722 boardOutline = &buffer;
1723
1724 for( ZONE* zone : m_board->Zones() )
1725 {
1726 syncZone( aWorld, zone, boardOutline );
1727 }
1728
1729 for( FOOTPRINT* footprint : m_board->Footprints() )
1730 {
1731 for( PAD* pad : footprint->Pads() )
1732 {
1733 std::vector<std::unique_ptr<PNS::SOLID>> solids = syncPad( pad );
1734
1735 for( std::unique_ptr<PNS::SOLID>& solid : solids )
1736 aWorld->Add( std::move( solid ) );
1737
1738 std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
1739
1740 if( clearanceOverride.has_value() )
1741 worstClearance = std::max( worstClearance, clearanceOverride.value() );
1742
1743 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1744 {
1745 std::unique_ptr<SHAPE> hole;
1746 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1747 aWorld->AddEdgeExclusion( std::move( hole ) );
1748 }
1749 }
1750
1751 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1752 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1753
1754 for( ZONE* zone : footprint->Zones() )
1755 syncZone( aWorld, zone, boardOutline );
1756
1757 for( PCB_FIELD* field : footprint->GetFields() )
1758 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1759
1760 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1761 {
1762 if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_TEXTBOX_T )
1763 {
1764 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1765 }
1766 else if( item->Type() == PCB_TEXT_T )
1767 {
1768 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1769 }
1770 else if( item->Type() == PCB_TABLE_T )
1771 {
1772 syncTextItem( aWorld, static_cast<PCB_TABLE*>( item ), item->GetLayer() );
1773 }
1774 }
1775 }
1776
1777 for( PCB_TRACK* t : m_board->Tracks() )
1778 {
1779 KICAD_T type = t->Type();
1780
1781 if( type == PCB_TRACE_T )
1782 {
1783 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1784 aWorld->Add( std::move( segment ), true );
1785 }
1786 else if( type == PCB_ARC_T )
1787 {
1788 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1789 aWorld->Add( std::move( arc ), true );
1790 }
1791 else if( type == PCB_VIA_T )
1792 {
1793 if( std::unique_ptr<PNS::VIA> via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1794 aWorld->Add( std::move( via ) );
1795 }
1796 }
1797
1798 // NB: if this were ever to become a long-lived object we would need to dirty its
1799 // clearance cache here....
1800 delete m_ruleResolver;
1802
1804 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1805}
1806
1807
1809{
1810 for( BOARD_ITEM* item : m_hiddenItems )
1811 m_view->SetVisible( item, true );
1812
1813 m_hiddenItems.clear();
1814
1815 if( m_previewItems )
1816 {
1819 }
1820
1821 if( m_debugDecorator )
1823}
1824
1825
1827{
1828 m_debugDecorator = aDec;
1829}
1830
1831
1832void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, int aFlags )
1833{
1834 if( aItem->IsVirtual() )
1835 return;
1836
1837 if( ZONE* zone = dynamic_cast<ZONE*>( aItem->Parent() ) )
1838 {
1839 if( zone->GetIsRuleArea() )
1840 aFlags |= PNS_SEMI_SOLID;
1841 }
1842
1843 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, this, m_view, aFlags );
1844
1845 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1847 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1848
1849 if( aClearance >= 0 )
1850 {
1851 pitem->SetClearance( aClearance );
1852
1853 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1854
1855 switch( settings->m_Display.m_TrackClearance )
1856 {
1859 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1860 break;
1861
1863 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1864 break;
1865
1866 case SHOW_WHILE_ROUTING:
1867 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1868 break;
1869
1870 default:
1871 pitem->ShowClearance( false );
1872 break;
1873 }
1874 }
1875
1876 m_previewItems->Add( pitem );
1878}
1879
1880
1881void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1882{
1883 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, this, m_view );
1885
1886 COLOR4D color;
1887
1888 if( aImportance >= 1 )
1889 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1890 else if( aImportance == 0 )
1891 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1892
1893 pitem->SetColor( color );
1894
1895 m_previewItems->Add( pitem );
1897}
1898
1899
1901{
1902 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, this, m_view );
1903
1904 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1905 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1906 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1907 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1908 COLOR4D color = defaultColor;
1909
1910 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1911 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1912 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1913 int netCode = -1;
1914
1915 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
1916 netCode = net->GetNetCode();
1917
1918 const NETCLASS* nc = nullptr;
1919 const NET_SETTINGS* netSettings = connectivity->GetNetSettings();
1920
1921 if( connectivity->HasNetNameForNetCode( netCode ) )
1922 {
1923 const wxString& netName = connectivity->GetNetNameForNetCode( netCode );
1924
1925 if( netSettings && netSettings->HasEffectiveNetClass( netName ) )
1926 nc = netSettings->GetCachedEffectiveNetClass( netName ).get();
1927 }
1928
1929 if( colorByNet && netColors.count( netCode ) )
1930 color = netColors.at( netCode );
1931 else if( colorByNet && nc && nc->HasPcbColor() )
1932 color = nc->GetPcbColor();
1933 else
1934 color = defaultColor;
1935
1936 if( color == COLOR4D::UNSPECIFIED )
1937 color = defaultColor;
1938
1939 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
1940
1941 m_previewItems->Add( pitem );
1943}
1944
1945
1947{
1948 BOARD_ITEM* parent = aItem->Parent();
1949
1950 if( parent )
1951 {
1952 if( m_view->IsVisible( parent ) )
1953 m_hiddenItems.insert( parent );
1954
1955 m_view->SetVisible( parent, false );
1956 m_view->Update( parent, KIGFX::APPEARANCE );
1957
1958 for( ZONE* td : m_board->Zones() )
1959 {
1960 if( td->IsTeardropArea()
1961 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
1962 && td->Outline()->Collide( aItem->Shape( td->GetLayer() ) ) )
1963 {
1964 m_view->SetVisible( td, false );
1966 }
1967 }
1968 }
1969}
1970
1971
1973{
1974}
1975
1976
1978{
1979 BOARD_ITEM* parent = aItem->Parent();
1980
1981 if( aItem->OfKind( PNS::ITEM::SOLID_T ) && parent->Type() == PCB_PAD_T )
1982 {
1983 PAD* pad = static_cast<PAD*>( parent );
1984 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1985
1986 m_fpOffsets[ pad ].p_old = pos;
1987 return;
1988 }
1989
1990 if( parent )
1991 {
1992 m_commit->Remove( parent );
1993 }
1994}
1995
1996
1998{
1999}
2000
2001
2003{
2004 BOARD_ITEM* board_item = aItem->Parent();
2005
2006 switch( aItem->Kind() )
2007 {
2008 case PNS::ITEM::ARC_T:
2009 {
2010 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
2011 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
2012 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape( -1 ) );
2013
2014 m_commit->Modify( arc_board );
2015
2016 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
2017 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
2018 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
2019 arc_board->SetWidth( arc->Width() );
2020 break;
2021 }
2022
2024 {
2025 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
2026 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
2027 const SEG& s = seg->Seg();
2028
2029 m_commit->Modify( track );
2030
2031 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
2032 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
2033 track->SetWidth( seg->Width() );
2034 break;
2035 }
2036
2037 case PNS::ITEM::VIA_T:
2038 {
2039 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
2040 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
2041
2042 m_commit->Modify( via_board );
2043
2044 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
2045 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter( 0 ) );
2046 via_board->SetDrill( via->Drill() );
2047 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
2048 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
2049 via_board->Padstack().SetUnconnectedLayerMode( via->UnconnectedLayerMode() );
2050 via_board->SetIsFree( via->IsFree() );
2051 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
2052 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
2053 break;
2054 }
2055
2056 case PNS::ITEM::SOLID_T:
2057 {
2058 if( aItem->Parent()->Type() == PCB_PAD_T )
2059 {
2060 PAD* pad = static_cast<PAD*>( aItem->Parent() );
2061 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2062
2063 // Don't add to commit; we'll add the parent footprints when processing the m_fpOffsets
2064
2065 m_fpOffsets[pad].p_old = pad->GetPosition();
2066 m_fpOffsets[pad].p_new = pos;
2067 }
2068 break;
2069 }
2070
2071 default:
2072 m_commit->Modify( aItem->Parent() );
2073 break;
2074 }
2075}
2076
2077
2079{
2080 modifyBoardItem( aItem );
2081}
2082
2083
2085{
2086}
2087
2088
2090{
2091 BOARD_CONNECTED_ITEM* newBoardItem = nullptr;
2092 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem->Net() );
2093
2094 if( !net )
2096
2097 switch( aItem->Kind() )
2098 {
2099 case PNS::ITEM::ARC_T:
2100 {
2101 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
2102 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape( -1 ) ) );
2103 new_arc->SetWidth( arc->Width() );
2104 new_arc->SetLayer( GetBoardLayerFromPNSLayer( arc->Layers().Start() ) );
2105 new_arc->SetNet( net );
2106
2107 if( aItem->GetSourceItem() && aItem->GetSourceItem()->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
2108 {
2109 PCB_TRACK* sourceTrack = static_cast<PCB_TRACK*>( aItem->GetSourceItem() );
2110 new_arc->SetHasSolderMask( sourceTrack->HasSolderMask() );
2111 new_arc->SetLocalSolderMaskMargin( sourceTrack->GetLocalSolderMaskMargin() );
2112 }
2113
2114 newBoardItem = new_arc;
2115 break;
2116 }
2117
2119 {
2120 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
2121 PCB_TRACK* track = new PCB_TRACK( m_board );
2122 const SEG& s = seg->Seg();
2123 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
2124 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
2125 track->SetWidth( seg->Width() );
2126 track->SetLayer( GetBoardLayerFromPNSLayer( seg->Layers().Start() ) );
2127 track->SetNet( net );
2128
2129 if( aItem->GetSourceItem() && aItem->GetSourceItem()->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
2130 {
2131 PCB_TRACK* sourceTrack = static_cast<PCB_TRACK*>( aItem->GetSourceItem() );
2132 track->SetHasSolderMask( sourceTrack->HasSolderMask() );
2133 track->SetLocalSolderMaskMargin( sourceTrack->GetLocalSolderMaskMargin() );
2134 }
2135
2136 newBoardItem = track;
2137 break;
2138 }
2139
2140 case PNS::ITEM::VIA_T:
2141 {
2142 PCB_VIA* via_board = new PCB_VIA( m_board );
2143 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
2144 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
2145 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter( 0 ) );
2146 via_board->SetDrill( via->Drill() );
2147 via_board->SetNet( net );
2148 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
2149 via_board->Padstack().SetUnconnectedLayerMode( via->UnconnectedLayerMode() );
2150 via_board->SetIsFree( via->IsFree() );
2151 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
2152 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
2153
2154 if( aItem->GetSourceItem() && aItem->GetSourceItem()->Type() == PCB_VIA_T )
2155 {
2156 PCB_VIA* sourceVia = static_cast<PCB_VIA*>( aItem->GetSourceItem() );
2157 via_board->SetFrontTentingMode( sourceVia->GetFrontTentingMode() );
2158 via_board->SetBackTentingMode( sourceVia->GetBackTentingMode() );
2159 }
2160
2161 newBoardItem = via_board;
2162 break;
2163 }
2164
2165 case PNS::ITEM::SOLID_T:
2166 {
2167 PAD* pad = static_cast<PAD*>( aItem->Parent() );
2168 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2169
2170 m_fpOffsets[pad].p_new = pos;
2171 return nullptr;
2172 }
2173
2174 default:
2175 return nullptr;
2176 }
2177
2178 if( net->GetNetCode() <= 0 )
2179 {
2180 NETINFO_ITEM* newNetInfo = newBoardItem->GetNet();
2181
2182 newNetInfo->SetParent( m_board );
2183 newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->GetDefaultNetclass() );
2184 }
2185
2186 return newBoardItem;
2187}
2188
2189
2191{
2192 BOARD_CONNECTED_ITEM* boardItem = createBoardItem( aItem );
2193
2194 if( boardItem )
2195 {
2196 aItem->SetParent( boardItem );
2197 boardItem->ClearFlags();
2198
2199 m_commit->Add( boardItem );
2200 }
2201}
2202
2203
2205{
2206 std::set<FOOTPRINT*> processedFootprints;
2207
2208 EraseView();
2209
2210 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
2211 {
2212 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
2213 FOOTPRINT* footprint = pad->GetParentFootprint();
2214 VECTOR2I p_orig = footprint->GetPosition();
2215 VECTOR2I p_new = p_orig + offset;
2216
2217 if( processedFootprints.find( footprint ) != processedFootprints.end() )
2218 continue;
2219
2220 processedFootprints.insert( footprint );
2221 m_commit->Modify( footprint );
2222 footprint->SetPosition( p_new );
2223 }
2224
2225 m_fpOffsets.clear();
2226
2227 m_commit->Push( _( "Routing" ), m_commitFlags );
2228 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2229}
2230
2231
2233{
2234 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
2235}
2236
2237
2239{
2240 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
2241
2242 if( m_previewItems )
2243 {
2245 delete m_previewItems;
2246 }
2247
2248 m_view = aView;
2251
2252 if(m_view)
2254
2255 delete m_debugDecorator;
2256
2257 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR( this );
2258 m_debugDecorator = dec;
2259
2260 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2261
2262 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2263 dec->SetView( m_view );
2264}
2265
2266
2268{
2269 if( aNet )
2270 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2271 else
2272 return -1;
2273}
2274
2275
2277{
2278 if( aNet )
2279 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2280 else
2281 return wxEmptyString;
2282}
2283
2284
2286{
2287 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2288}
2289
2290
2292{
2294}
2295
2296
2298{
2299 return m_ruleResolver;
2300}
2301
2302
2304{
2305 m_tool = aTool;
2306 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2307}
2308
2309
2311{
2312 if( aLayer < 0 )
2313 return PCB_LAYER_ID::UNDEFINED_LAYER;
2314
2315 if( aLayer == 0 )
2316 return F_Cu;
2317
2318 if( aLayer == m_board->GetCopperLayerCount() - 1 )
2319 return B_Cu;
2320
2321 return static_cast<PCB_LAYER_ID>( ( aLayer + 1 ) * 2 );
2322}
2323
2324
2326{
2327 if( aLayer < 0 )
2328 return -1;
2329
2330 if( aLayer == F_Cu )
2331 return 0;
2332
2333 if( aLayer == B_Cu )
2334 return m_board->GetCopperLayerCount() - 1;
2335
2336 return ( aLayer / 2 ) - 1;
2337}
2338
2339
2341{
2343}
2344
2345
2347{
2348 return PNS_LAYER_RANGE( GetPNSLayerFromBoardLayer( aStartLayer ),
2349 GetPNSLayerFromBoardLayer( aEndLayer ) );
2350}
2351
2352
2354 const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
2355{
2356 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
2357
2358 const PAD* startPad = nullptr;
2359 const PAD* endPad = nullptr;
2360
2361 if( aStartPad )
2362 startPad = static_cast<PAD*>( aStartPad->Parent() );
2363
2364 if( aEndPad )
2365 endPad = static_cast<PAD*>( aEndPad->Parent() );
2366
2367 constexpr PATH_OPTIMISATIONS opts = {
2368 .OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = true
2369 };
2370 const BOARD* board = GetBoard();
2371 return board->GetLengthCalculation()->CalculateLength( lengthItems, opts, startPad, endPad );
2372}
2373
2374
2376 const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
2377{
2378 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
2379
2380 const PAD* startPad = nullptr;
2381 const PAD* endPad = nullptr;
2382
2383 if( aStartPad )
2384 startPad = static_cast<PAD*>( aStartPad->Parent() );
2385
2386 if( aEndPad )
2387 endPad = static_cast<PAD*>( aEndPad->Parent() );
2388
2389 constexpr PATH_OPTIMISATIONS opts = {
2390 .OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = true
2391 };
2392 const BOARD* board = GetBoard();
2393 return board->GetLengthCalculation()->CalculateDelay( lengthItems, opts, startPad, endPad );
2394}
2395
2396
2397int64_t PNS_KICAD_IFACE_BASE::CalculateLengthForDelay( int64_t aDesiredDelay, const int aWidth,
2398 const bool aIsDiffPairCoupled, const int aDiffPairCouplingGap,
2399 const int aPNSLayer, const NETCLASS* aNetClass )
2400{
2402 ctx.NetClass = aNetClass;
2403 ctx.Width = aWidth;
2404 ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
2405 ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
2406 ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
2407
2408 const BOARD* board = GetBoard();
2409 return board->GetLengthCalculation()->CalculateLengthForDelay( aDesiredDelay, ctx );
2410}
2411
2412
2414 bool aIsDiffPairCoupled, int aDiffPairCouplingGap,
2415 int aPNSLayer, const NETCLASS* aNetClass )
2416{
2418 ctx.NetClass = aNetClass;
2419 ctx.Width = aWidth;
2420 ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
2421 ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
2422 ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
2423
2424 const BOARD* board = GetBoard();
2426}
2427
2428
2429std::vector<LENGTH_DELAY_CALCULATION_ITEM>
2431{
2432 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems;
2433
2434 for( int idx = 0; idx < aLine.Size(); idx++ )
2435 {
2436 const PNS::ITEM* lineItem = aLine[idx];
2437
2438 if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( lineItem ) )
2439 {
2441 item.SetLine( l->CLine() );
2442
2443 const PCB_LAYER_ID layer = GetBoardLayerFromPNSLayer( lineItem->Layer() );
2444 item.SetLayers( layer );
2445 item.SetEffectiveNetClass( aNetClass );
2446
2447 lengthItems.emplace_back( std::move( item ) );
2448 }
2449 else if( lineItem->OfKind( PNS::ITEM::VIA_T ) && idx > 0 && idx < aLine.Size() - 1 )
2450 {
2451 const int layerPrev = aLine[idx - 1]->Layer();
2452 const int layerNext = aLine[idx + 1]->Layer();
2453 const PCB_LAYER_ID pcbLayerPrev = GetBoardLayerFromPNSLayer( layerPrev );
2454 const PCB_LAYER_ID pcbLayerNext = GetBoardLayerFromPNSLayer( layerNext );
2455
2456 if( layerPrev != layerNext )
2457 {
2459 item.SetVia( static_cast<PCB_VIA*>( lineItem->GetSourceItem() ) );
2460 item.SetLayers( pcbLayerPrev, pcbLayerNext ); // TODO: BUG IS HERE!!!
2461 item.SetEffectiveNetClass( aNetClass );
2462 lengthItems.emplace_back( std::move( item ) );
2463 }
2464 }
2465 }
2466
2467 return lengthItems;
2468}
int color
Definition: DXF_plotter.cpp:63
@ ERROR_OUTSIDE
Definition: approximation.h:33
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
std::shared_ptr< DRC_ENGINE > m_DRCEngine
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
BOARD_STACKUP & GetStackupDescriptor()
bool UseNetClassTrack() const
Return true if netclass values should be used to obtain appropriate track width.
bool UseNetClassDiffPair() const
Return true if netclass values should be used to obtain appropriate diff pair dimensions.
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:232
bool IsLocked() const override
Definition: board_item.cpp:103
virtual void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const
Convert the item shape to a closed polygon.
Definition: board_item.cpp:303
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:314
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:280
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:97
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:252
virtual bool HasDrilledHole() const
Definition: board_item.h:161
virtual int BoardCopperLayerCount() const
Return the total number of copper layers for the board that this item resides on.
Definition: board_item.cpp:158
virtual bool IsOnCopperLayer() const
Definition: board_item.h:151
int GetMaxError() const
Definition: board_item.cpp:138
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:317
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:2604
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:2168
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition: board.h:1340
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:2099
const ZONES & Zones() const
Definition: board.h:362
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition: board.cpp:1036
int GetCopperLayerCount() const
Definition: board.cpp:859
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition: board.cpp:2118
const FOOTPRINTS & Footprints() const
Definition: board.h:358
const TRACKS & Tracks() const
Definition: board.h:356
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:522
const DRAWINGS & Drawings() const
Definition: board.h:360
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
constexpr const SizeVec & GetSize() const
Definition: box2.h:206
wxString GetName() const
Definition: drc_rule.h:168
SEVERITY GetSeverity() const
Definition: drc_rule.h:181
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:160
bool GetOption(OPTIONS option) const
Definition: drc_rule.h:193
bool IsNull() const
Definition: drc_rule.h:155
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:110
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
virtual EDA_GROUP * GetParentGroup() const
Definition: eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:144
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:192
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:379
virtual bool IsVisible() const
Definition: eda_text.h:184
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2513
bool IsNetTie() const
Definition: footprint.h:306
VECTOR2I GetPosition() const override
Definition: footprint.h:227
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:50
@ KD_WARNING
Definition: kidialog.h:53
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
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:80
NET_COLOR_MODE GetNetColorMode() const
Definition: pcb_painter.h:135
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:138
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:43
void FreeItems()
Free all the items that were added to the group.
Definition: view_group.cpp:218
virtual void SetLayer(int aLayer)
Set layer used to draw the group.
Definition: view_group.h:96
virtual void Add(VIEW_ITEM *aItem)
Add an item to the group.
Definition: view_group.cpp:65
virtual double ViewGetLOD(int aLayer, const VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:155
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:66
double GetScale() const
Definition: view.h:276
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:298
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:1685
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:202
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:422
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:220
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1655
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1612
Lightweight class which holds a pad, via, or a routed trace outline.
void SetLine(const SHAPE_LINE_CHAIN &aLine)
Sets the source SHAPE_LINE_CHAIN of this item.
void SetVia(const PCB_VIA *aVia)
Sets the VIA associated with this item.
void SetEffectiveNetClass(const NETCLASS *aNetClass)
Sets the effective net class for the item.
void SetLayers(const PCB_LAYER_ID aStart, const PCB_LAYER_ID aEnd=PCB_LAYER_ID::UNDEFINED_LAYER)
Sets the first and last layers associated with this item.
int64_t CalculateLengthForDelay(int64_t aDesiredDelay, const TIME_DOMAIN_GEOMETRY_CONTEXT &aCtx) const
Calculates the length of track required for the given delay in a specific geometry context.
int64_t CalculatePropagationDelayForShapeLineChain(const SHAPE_LINE_CHAIN &aShape, const TIME_DOMAIN_GEOMETRY_CONTEXT &aCtx) const
Gets the propagation delay for the given shape line chain.
int64_t CalculateDelay(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical propagation delay of the given items.
int64_t CalculateLength(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical length of the given items.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition: lset.cpp:246
T Min() const
Definition: minoptmax.h:33
void SetMin(T v)
Definition: minoptmax.h:41
T Opt() const
Definition: minoptmax.h:35
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:45
COLOR4D GetPcbColor(bool aIsForSave=false) const
Definition: netclass.h:189
bool HasPcbColor() const
Definition: netclass.h:188
Handle the data for a net.
Definition: netinfo.h:56
int GetNetCode() const
Definition: netinfo.h:108
void SetParent(BOARD *aParent)
Definition: netinfo.h:167
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
static NETINFO_ITEM * OrphanedItem()
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:389
NET_SETTINGS stores various net-related settings in a project context.
Definition: net_settings.h:39
bool HasEffectiveNetClass(const wxString &aNetName) const
Determines if an effective netclass for the given net name has been cached.
std::shared_ptr< NETCLASS > GetCachedEffectiveNetClass(const wxString &aNetName) const
Returns an already cached effective netclass for the given net name.
void ForEachUniqueLayer(const std::function< void(PCB_LAYER_ID)> &aMethod) const
Runs the given callable for each active unique copper layer in this padstack, meaning F_Cu for MODE::...
Definition: padstack.cpp:882
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition: padstack.h:315
UNCONNECTED_LAYER_MODE UnconnectedLayerMode() const
Definition: padstack.h:314
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
MODE Mode() const
Definition: padstack.h:295
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:145
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition: padstack.h:148
Definition: pad.h:54
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:437
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:537
const VECTOR2I & GetDrillSize() const
Definition: pad.h:305
PAD_ATTRIB GetAttribute() const
Definition: pad.h:440
int GetPadToDieDelay() const
Definition: pad.h:456
const PADSTACK & Padstack() const
Definition: pad.h:321
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
Definition: pad.h:317
bool IsFreePad() const
Definition: pad.cpp:284
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:408
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition: pad.cpp:525
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition: pad.cpp:1068
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:598
int GetPadToDieLength() const
Definition: pad.h:453
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:344
const VECTOR2I & GetMid() const
Definition: pcb_track.h:345
std::vector< VECTOR2I > GetConnectionPoints() const
Definition: pcb_shape.cpp:260
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
Definition: pcb_shape.cpp:212
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:71
void SetHasSolderMask(bool aVal)
Definition: pcb_track.h:175
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:148
bool HasSolderMask() const
Definition: pcb_track.h:176
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:151
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: pcb_track.h:178
std::optional< int > GetLocalSolderMaskMargin() const
Definition: pcb_track.h:179
const VECTOR2I & GetStart() const
Definition: pcb_track.h:152
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:149
virtual void SetWidth(int aWidth)
Definition: pcb_track.h:145
virtual int GetWidth() const
Definition: pcb_track.h:146
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:704
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:1395
VECTOR2I GetPosition() const override
Definition: pcb_track.h:557
const PADSTACK & Padstack() const
Definition: pcb_track.h:459
void SetFrontTentingMode(TENTING_MODE aMode)
Definition: pcb_track.cpp:912
TENTING_MODE GetFrontTentingMode() const
Definition: pcb_track.cpp:923
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:670
void SetBackTentingMode(TENTING_MODE aMode)
Definition: pcb_track.cpp:935
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:705
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:558
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
Definition: pcb_track.cpp:1337
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_track.cpp:1224
int GetWidth() const override
Definition: pcb_track.cpp:379
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:452
TENTING_MODE GetBackTentingMode() const
Definition: pcb_track.cpp:946
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:1389
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:628
VIATYPE GetViaType() const
Definition: pcb_track.h:451
void SetWidth(int aWidth) override
Definition: pcb_track.cpp:373
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:1367
int Width() const override
Definition: pns_arc.h:88
const SHAPE * Shape(int aLayer) 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, PNS_LAYER_RANGE aLayers)
Definition: pns_hole.cpp:131
int Size() const
Definition: pns_itemset.h:112
ITEM_SET & ExcludeItem(const ITEM *aItem)
ITEM_SET & FilterKinds(int aKindMask, bool aInvert=false)
Definition: pns_itemset.cpp:71
std::vector< ITEM * > & Items()
Definition: pns_itemset.h:87
Base class for PNS router board items.
Definition: pns_item.h:98
BOARD_ITEM * Parent() const
Definition: pns_item.h:199
virtual ITEM * ParentPadVia() const
Definition: pns_item.h:293
virtual const SHAPE * Shape(int aLayer) const
Return the geometrical shape of the item.
Definition: pns_item.h:242
const PNS_LAYER_RANGE & Layers() const
Definition: pns_item.h:212
virtual NET_HANDLE Net() const
Definition: pns_item.h:210
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:173
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:209
BOARD_ITEM * GetSourceItem() const
Definition: pns_item.h:202
virtual int Layer() const
Definition: pns_item.h:216
void SetLayer(int aLayer)
Definition: pns_item.h:215
@ SEGMENT_T
Definition: pns_item.h:107
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:191
bool OfKind(int aKindMask) const
Definition: pns_item.h:181
bool IsVirtual() const
Definition: pns_item.h:295
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:268
virtual BOARD_ITEM * BoardItem() const
Definition: pns_item.h:207
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:308
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:62
Keep the router "world" - i.e.
Definition: pns_node.h:232
void SetMaxClearance(int aClearance)
Assign a clearance resolution function object.
Definition: pns_node.h:259
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:665
void SetRuleResolver(RULE_RESOLVER *aFunc)
Definition: pns_node.h:265
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
Definition: pns_node.cpp:709
const ITEM_OWNER * Owner() const
Return the owner of this item, or NULL if there's none.
Definition: pns_item.h:72
virtual wxString GetNetName(PNS::NET_HANDLE aNet) const =0
virtual int GetNetCode(NET_HANDLE aNet) const =0
virtual PCB_LAYER_ID GetBoardLayerFromPNSLayer(int aLayer) const =0
const SEG & Seg() const
Definition: pns_segment.h:93
void SetEnds(const VECTOR2I &a, const VECTOR2I &b)
Definition: pns_segment.h:103
int Width() const override
Definition: pns_segment.h:88
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 ConnectsLayer(int aLayer) const
Definition: pns_via.cpp:78
bool syncGraphicalItem(PNS::NODE *aWorld, PCB_SHAPE *aItem)
bool inheritTrackWidth(PNS::ITEM *aItem, int *aInheritedWidth)
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)
long long int CalculateRoutedPathLength(const PNS::ITEM_SET &aLine, const PNS::SOLID *aStartPad, const PNS::SOLID *aEndPad, const NETCLASS *aNetClass) override
int64_t CalculateRoutedPathDelay(const PNS::ITEM_SET &aLine, const PNS::SOLID *aStartPad, const PNS::SOLID *aEndPad, const NETCLASS *aNetClass) override
std::unique_ptr< PNS::ARC > syncArc(PCB_ARC *aArc)
void RemoveItem(PNS::ITEM *aItem) override
bool IsPNSCopperLayer(int aPNSLayer) const override
int64_t CalculateLengthForDelay(int64_t aDesiredDelay, int aWidth, bool aIsDiffPairCoupled, int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS *aNetClass) override
PNS::RULE_RESOLVER * GetRuleResolver() override
bool syncTextItem(PNS::NODE *aWorld, BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
std::vector< LENGTH_DELAY_CALCULATION_ITEM > getLengthDelayCalculationItems(const PNS::ITEM_SET &aLine, const NETCLASS *aNetClass) const
bool IsKicadCopperLayer(PCB_LAYER_ID aPcbnewLayer) const
std::vector< std::unique_ptr< PNS::SOLID > > syncPad(PAD *aPad)
void SetStartLayerFromPCBNew(PCB_LAYER_ID aLayer)
bool IsFlashedOnLayer(const PNS::ITEM *aItem, int aLayer) const override
PCB_LAYER_ID GetBoardLayerFromPNSLayer(int aLayer) const override
BOARD * GetBoard() const
void SyncWorld(PNS::NODE *aWorld) override
int StackupHeight(int aFirstLayer, int aSecondLayer) const override
int64_t CalculateDelayForShapeLineChain(const SHAPE_LINE_CHAIN &aShape, int aWidth, bool aIsDiffPairCoupled, int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS *aNetClass) 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)
int GetPNSLayerFromBoardLayer(PCB_LAYER_ID aLayer) const override
PNS_LAYER_RANGE SetLayersFromPCBNew(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer)
void UpdateItem(PNS::ITEM *aItem) override
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, PNS::NET_HANDLE aNet, VECTOR2D aStartPosition) 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 PNS_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
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
int Start() const
Definition: pns_layerset.h:86
bool Overlaps(const PNS_LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
int End() const
Definition: pns_layerset.h:91
PNS_LAYER_RANGE Intersection(const PNS_LAYER_RANGE &aOther) const
Shortcut for comparisons/overlap tests.
Definition: pns_layerset.h:112
PNS_PCBNEW_DEBUG_DECORATOR(PNS::ROUTER_IFACE *aIface)
void AddPoint(const VECTOR2I &aP, const KIGFX::COLOR4D &aColor, int aSize, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
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
virtual void Message(const wxString &msg, 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
BOARD_ITEM * getBoardItem(const PNS::ITEM *aItem, PCB_LAYER_ID aBoardLayer, int aIdx=0)
bool IsKeepout(const PNS::ITEM *aObstacle, const PNS::ITEM *aItem, bool *aEnforce) override
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:118
const VECTOR2I & GetP1() const
Definition: shape_arc.h:117
const VECTOR2I & GetP0() const
Definition: shape_arc.h:116
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.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
unsigned int TriangulatedPolyCount() const
Return the number of triangulated polygons.
int OutlineCount() const
Return the number of outlines in the set.
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
void Append(int aX, int aY)
Append a new point at the end of the polygon.
Definition: shape_simple.h:135
An abstract shape on 2D plane.
Definition: shape.h:126
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:146
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:404
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition: vector2d.h:561
VECTOR2_TRAITS< int32_t >::extended_type extended_type
Definition: vector2d.h:73
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: zone.cpp:1154
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:704
bool GetDoNotAllowVias() const
Definition: zone.h:720
bool GetDoNotAllowPads() const
Definition: zone.h:722
bool GetDoNotAllowTracks() const
Definition: zone.h:721
SHAPE_POLY_SET * Outline()
Definition: zone.h:335
bool GetDoNotAllowFootprints() const
Definition: zone.h:723
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:136
bool HasKeepoutParametersSet() const
Accessor to determine if any keepout parameters are set.
Definition: zone.h:695
DRC_CONSTRAINT_T
Definition: drc_rule.h:47
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:70
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:73
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:59
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:53
@ LENGTH_CONSTRAINT
Definition: drc_rule.h:71
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:49
@ MAX_UNCOUPLED_CONSTRAINT
Definition: drc_rule.h:74
@ SKEW_CONSTRAINT
Definition: drc_rule.h:72
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:51
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:54
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:77
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:52
#define _(s)
#define ROUTER_TRANSIENT
transient items that should NOT be cached
#define IN_EDIT
Item currently edited.
EDA_UNITS
Definition: eda_units.h:48
static constexpr void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
Definition: hash.h:32
This file is part of the common library.
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START
Definition: layer_ids.h:174
@ LAYER_RATSNEST
Definition: layer_ids.h:252
@ LAYER_SELECT_OVERLAY
Selected items overlay.
Definition: layer_ids.h:279
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Edge_Cuts
Definition: layer_ids.h:112
@ B_Cu
Definition: layer_ids.h:65
@ Margin
Definition: layer_ids.h:113
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:171
@ F_Cu
Definition: layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
@ APPEARANCE
Visibility flag has changed.
Definition: view_item.h:53
Push and Shove diff pair dimensions (gap) settings dialog.
CONSTRAINT_TYPE
Definition: pns_node.h:52
void * NET_HANDLE
Definition: pns_item.h:55
@ MK_LOCKED
Definition: pns_item.h:45
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
Struct to control which optimisations the length calculation code runs on the given path objects.
bool OptimiseViaLayers
Optimise via layers for height calculations, ensuring only the distance between routed segments is co...
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
bool m_IsTimeDomain
Definition: pns_node.h:80
MINOPTMAX< int > m_Value
Definition: pns_node.h:75
CONSTRAINT_TYPE m_Type
Definition: pns_node.h:74
A data structure to contain basic geometry data which can affect signal propagation calculations.
PCB_LAYER_ID Layer
The layer this track is on.
bool IsDiffPairCoupled
Whether this track or via is a member of a coupled differential pair.
int64_t DiffPairCouplingGap
The gap between coupled tracks.
int64_t Width
The width (in internal units) of the track.
const NETCLASS * NetClass
The net class this track belongs to.
std::size_t operator()(const CLEARANCE_CACHE_KEY &k) const
arc1_slc SetWidth(0)
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
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_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition: typeinfo.h:95
@ 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_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition: typeinfo.h:94
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695