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