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
1060private:
1061 double nextDepth()
1062 {
1063 // Use different depths so that the transculent shapes won't overwrite each other.
1064
1065 m_depth++;
1066
1067 if( m_depth >= 0 && m_view->GetGAL() )
1069
1070 return m_depth;
1071 }
1072
1076
1077 double m_depth;
1078};
1079
1080
1082{
1083 return m_debugDecorator;
1084}
1085
1086
1088{
1089 m_ruleResolver = nullptr;
1090 m_board = nullptr;
1091 m_world = nullptr;
1092 m_debugDecorator = nullptr;
1093 m_startLayer = -1;
1094}
1095
1096
1098{
1099 m_tool = nullptr;
1100 m_view = nullptr;
1101 m_previewItems = nullptr;
1102 m_commitFlags = 0;
1103}
1104
1105
1107{
1108 delete m_ruleResolver;
1109 delete m_debugDecorator;
1110}
1111
1112
1114{
1115 if( m_previewItems )
1116 {
1118 delete m_previewItems;
1119 }
1120}
1121
1122
1123std::vector<std::unique_ptr<PNS::SOLID>> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1124{
1125 std::vector<std::unique_ptr<PNS::SOLID>> solids;
1126 PNS_LAYER_RANGE layers( 0, aPad->BoardCopperLayerCount() );
1127 LSEQ lmsk = aPad->GetLayerSet().CuStack();
1128
1129 // ignore non-copper pads except for those with holes
1130 if( lmsk.empty() && aPad->GetDrillSize().x == 0 )
1131 return solids;
1132
1133 switch( aPad->GetAttribute() )
1134 {
1135 case PAD_ATTRIB::PTH:
1136 case PAD_ATTRIB::NPTH:
1137 break;
1138
1139 case PAD_ATTRIB::CONN:
1140 case PAD_ATTRIB::SMD:
1141 {
1142 bool is_copper = false;
1143
1144 if( !lmsk.empty() && aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1145 {
1146 layers = SetLayersFromPCBNew( lmsk.front(), lmsk.front() );
1147 is_copper = true;
1148 }
1149
1150 if( !is_copper )
1151 return solids;
1152
1153 break;
1154 }
1155
1156 default:
1157 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1158 return solids;
1159 }
1160
1161 auto makeSolidFromPadLayer =
1162 [&]( PCB_LAYER_ID aLayer )
1163 {
1164 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1165
1166 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1167 solid->SetRoutable( false );
1168
1169 if( aPad->Padstack().Mode() == PADSTACK::MODE::CUSTOM )
1170 {
1171 solid->SetLayers( GetPNSLayerFromBoardLayer( aLayer ) );
1172 }
1173 else if( aPad->Padstack().Mode() == PADSTACK::MODE::FRONT_INNER_BACK )
1174 {
1175 if( aLayer == F_Cu || aLayer == B_Cu )
1176 solid->SetLayers( GetPNSLayerFromBoardLayer( aLayer ) );
1177 else
1178 solid->SetLayers( PNS_LAYER_RANGE( 1, aPad->BoardCopperLayerCount() - 1 ) );
1179 }
1180 else
1181 {
1182 solid->SetLayers( layers );
1183 }
1184
1185 solid->SetNet( aPad->GetNet() );
1186 solid->SetParent( aPad );
1187 solid->SetPadToDie( aPad->GetPadToDieLength() );
1188 solid->SetOrientation( aPad->GetOrientation() );
1189
1190 if( aPad->IsFreePad() )
1191 solid->SetIsFreePad();
1192
1193 VECTOR2I wx_c = aPad->ShapePos( aLayer );
1194 VECTOR2I offset = aPad->GetOffset( aLayer );
1195
1196 VECTOR2I c( wx_c.x, wx_c.y );
1197
1198 RotatePoint( offset, aPad->GetOrientation() );
1199
1200 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1201 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1202
1203 if( aPad->GetDrillSize().x > 0 )
1204 solid->SetHole( new PNS::HOLE( aPad->GetEffectiveHoleShape()->Clone() ) );
1205
1206 // We generate a single SOLID for a pad, so we have to treat it as ALWAYS_FLASHED and
1207 // then perform layer-specific flashing tests internally.
1208 const std::shared_ptr<SHAPE>& shape =
1209 aPad->GetEffectiveShape( aLayer, FLASHING::ALWAYS_FLASHED );
1210
1211 if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 )
1212 {
1213 std::vector<const SHAPE*> subshapes;
1214 shape->GetIndexableSubshapes( subshapes );
1215
1216 solid->SetShape( subshapes[0]->Clone() );
1217 }
1218 // For anything that's not a single shape we use a polygon. Multiple shapes have a tendency
1219 // to confuse the hull generator. https://gitlab.com/kicad/code/kicad/-/issues/15553
1220 else
1221 {
1222 const std::shared_ptr<SHAPE_POLY_SET>& poly =
1223 aPad->GetEffectivePolygon( aLayer, ERROR_OUTSIDE );
1224
1225 if( poly->OutlineCount() )
1226 solid->SetShape( new SHAPE_SIMPLE( poly->Outline( 0 ) ) );
1227 }
1228
1229 solids.emplace_back( std::move( solid ) );
1230 };
1231
1232 aPad->Padstack().ForEachUniqueLayer( makeSolidFromPadLayer );
1233
1234 return solids;
1235}
1236
1237
1238std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1239{
1240 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1241 aTrack->GetNet() );
1242
1243 segment->SetWidth( aTrack->GetWidth() );
1244 segment->SetLayer( GetPNSLayerFromBoardLayer( aTrack->GetLayer() ) );
1245 segment->SetParent( aTrack );
1246
1247 if( aTrack->IsLocked() )
1248 segment->Mark( PNS::MK_LOCKED );
1249
1250 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aTrack->GetParentGroup() ) )
1251 {
1252 if( !generator->HasFlag( IN_EDIT ) )
1253 segment->Mark( PNS::MK_LOCKED );
1254 }
1255
1256 return segment;
1257}
1258
1259
1260std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1261{
1262 auto arc = std::make_unique<PNS::ARC>( SHAPE_ARC( aArc->GetStart(), aArc->GetMid(),
1263 aArc->GetEnd(), aArc->GetWidth() ),
1264 aArc->GetNet() );
1265
1266 arc->SetLayer( GetPNSLayerFromBoardLayer( aArc->GetLayer() ) );
1267 arc->SetParent( aArc );
1268
1269 if( aArc->IsLocked() )
1270 arc->Mark( PNS::MK_LOCKED );
1271
1272 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aArc->GetParentGroup() ) )
1273 {
1274 if( !generator->HasFlag( IN_EDIT ) )
1275 arc->Mark( PNS::MK_LOCKED );
1276 }
1277
1278 return arc;
1279}
1280
1281
1282std::vector<std::unique_ptr<PNS::VIA>> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1283{
1284 std::vector<std::unique_ptr<PNS::VIA>> vias;
1285 PCB_LAYER_ID top, bottom;
1286 aVia->LayerPair( &top, &bottom );
1287
1289 [&]( PCB_LAYER_ID aLayer )
1290 {
1291 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1292 SetLayersFromPCBNew( aVia->TopLayer(), aVia->BottomLayer() ),
1293 aVia->GetWidth( aLayer ),
1294 aVia->GetDrillValue(),
1295 aVia->GetNet(),
1296 aVia->GetViaType() );
1297
1298 via->SetParent( aVia );
1299
1300 if( aVia->IsLocked() )
1301 via->Mark( PNS::MK_LOCKED );
1302
1303 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aVia->GetParentGroup() ) )
1304 {
1305 if( !generator->HasFlag( IN_EDIT ) )
1306 via->Mark( PNS::MK_LOCKED );
1307 }
1308
1309 via->SetIsFree( aVia->GetIsFree() );
1310 via->SetHole( PNS::HOLE::MakeCircularHole( aVia->GetPosition(),
1311 aVia->GetDrillValue() / 2 ) );
1312 vias.emplace_back( std::move( via ) );
1313 } );
1314
1315 return vias;
1316}
1317
1318
1319bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1320{
1321 static wxString msg;
1322 SHAPE_POLY_SET* poly;
1323
1324 if( !aZone->GetIsRuleArea() || !aZone->HasKeepoutParametersSet() )
1325 return false;
1326
1327 LSET layers = aZone->GetLayerSet();
1328
1329 poly = aZone->Outline();
1330 poly->CacheTriangulation( false );
1331
1332 if( !poly->IsTriangulationUpToDate() )
1333 {
1334 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1335 msg.Printf( _( "%s is malformed." ), aZone->GetItemDescription( &unitsProvider, true ) );
1336
1337 KIDIALOG dlg( nullptr, msg, KIDIALOG::KD_WARNING );
1338 dlg.ShowDetailedText( _( "This zone cannot be handled by the router.\n"
1339 "Please verify it is not a self-intersecting polygon." ) );
1340 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1341 dlg.ShowModal();
1342
1343 return false;
1344 }
1345
1347 {
1348 if( !layers[ layer ] )
1349 continue;
1350
1351 for( int polyId = 0; polyId < poly->TriangulatedPolyCount(); polyId++ )
1352 {
1353 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( polyId );
1354
1355 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1356 {
1357 VECTOR2I a, b, c;
1358 tri->GetTriangle( i, a, b, c );
1359 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1360
1361 triShape->Append( a );
1362 triShape->Append( b );
1363 triShape->Append( c );
1364
1365 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1366
1367 solid->SetLayer( GetPNSLayerFromBoardLayer( layer ) );
1368 solid->SetNet( nullptr );
1369 solid->SetParent( aZone );
1370 solid->SetShape( triShape );
1371 solid->SetIsCompoundShapePrimitive();
1372 solid->SetRoutable( false );
1373
1374 aWorld->Add( std::move( solid ) );
1375 }
1376 }
1377 }
1378
1379 return true;
1380}
1381
1382
1384{
1385 if( !IsKicadCopperLayer( aLayer ) )
1386 return false;
1387
1388 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1389 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1390
1391 solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
1392 solid->SetNet( nullptr );
1393 solid->SetParent( aText );
1394 solid->SetShape( shape ); // takes ownership
1395 solid->SetRoutable( false );
1396
1397 SHAPE_POLY_SET cornerBuffer;
1398
1399 aText->TransformShapeToPolygon( cornerBuffer, aText->GetLayer(), 0,
1401
1402 if( !cornerBuffer.OutlineCount() )
1403 return false;
1404
1405 for( const VECTOR2I& pt : cornerBuffer.Outline( 0 ).CPoints() )
1406 shape->Append( pt );
1407
1408 aWorld->Add( std::move( solid ) );
1409
1410 return true;
1411}
1412
1413
1415{
1416 if( aItem->GetLayer() == Edge_Cuts
1417 || aItem->GetLayer() == Margin
1418 || IsKicadCopperLayer( aItem->GetLayer() ) )
1419 {
1420 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1421
1422 for( SHAPE* shape : shapes )
1423 {
1424 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1425
1426 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1427 {
1428 solid->SetLayers( PNS_LAYER_RANGE( 0, m_board->GetCopperLayerCount() ) );
1429 solid->SetRoutable( false );
1430 }
1431 else
1432 {
1433 solid->SetLayer( GetPNSLayerFromBoardLayer( aItem->GetLayer() ) );
1434 }
1435
1436 if( aItem->GetLayer() == Edge_Cuts )
1437 {
1438 switch( shape->Type() )
1439 {
1440 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1441 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1442 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1443 default: /* remaining shapes don't have width */ break;
1444 }
1445 }
1446
1447 solid->SetAnchorPoints( aItem->GetConnectionPoints() );
1448 solid->SetNet( aItem->GetNet() );
1449 solid->SetParent( aItem );
1450 solid->SetShape( shape ); // takes ownership
1451
1452 if( shapes.size() > 1 )
1453 solid->SetIsCompoundShapePrimitive();
1454
1455 aWorld->Add( std::move( solid ) );
1456 }
1457
1458 return true;
1459 }
1460
1461 return false;
1462}
1463
1464
1466{
1467 m_board = aBoard;
1468 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1469}
1470
1471
1473{
1474 return ::IsCopperLayer( GetBoardLayerFromPNSLayer( aPNSLayer ) );
1475}
1476
1477
1478
1480{
1481 return ::IsCopperLayer( aKicadLayer );
1482}
1483
1484
1486{
1487 if( !m_view )
1488 return false;
1489
1490 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1491 {
1493 return true;
1494 }
1495
1496 return false;
1497}
1498
1499
1500bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1501{
1503 if( aLayer < 0 )
1504 return true;
1505
1506 if( aItem->Parent() )
1507 {
1508 switch( aItem->Parent()->Type() )
1509 {
1510 case PCB_VIA_T:
1511 {
1512 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1513
1514 return via->FlashLayer( GetBoardLayerFromPNSLayer( aLayer ) );
1515 }
1516
1517 case PCB_PAD_T:
1518 {
1519 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1520
1521 return pad->FlashLayer( GetBoardLayerFromPNSLayer( aLayer ) );
1522 }
1523
1524 default:
1525 break;
1526 }
1527 }
1528
1529 return aItem->Layers().Overlaps( aLayer );
1530}
1531
1532
1534 const PNS_LAYER_RANGE& aLayer ) const
1535{
1536 PNS_LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
1537
1538 if( aItem->Parent() )
1539 {
1540 switch( aItem->Parent()->Type() )
1541 {
1542 case PCB_VIA_T:
1543 {
1544 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1545
1546 for( int layer = test.Start(); layer <= test.End(); ++layer )
1547 {
1548 if( via->FlashLayer( GetBoardLayerFromPNSLayer( layer ) ) )
1549 return true;
1550 }
1551
1552 return false;
1553 }
1554
1555 case PCB_PAD_T:
1556 {
1557 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1558
1559 for( int layer = test.Start(); layer <= test.End(); ++layer )
1560 {
1561 if( pad->FlashLayer( GetBoardLayerFromPNSLayer( layer ) ) )
1562 return true;
1563 }
1564
1565 return false;
1566 }
1567
1568 default:
1569 break;
1570 }
1571 }
1572
1573 return test.Start() <= test.End();
1574}
1575
1576
1578{
1579 // by default, all items are visible (new ones created by the router have parent == NULL
1580 // as they have not been committed yet to the BOARD)
1581 if( !m_view || !aItem->Parent() )
1582 return true;
1583
1584 BOARD_ITEM* item = aItem->Parent();
1585 bool isOnVisibleLayer = true;
1586 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1587
1588 if( settings->GetHighContrast() )
1589 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1590
1591 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1592 {
1593 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
1594 {
1595 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1596 return true;
1597 }
1598 }
1599
1600 // Items hidden in the router are not hidden on the board
1601 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1602 return true;
1603
1604 return false;
1605}
1606
1607
1609{
1610 if( !m_board )
1611 {
1612 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1613 return;
1614 }
1615
1616 int worstClearance = m_board->GetMaxClearanceValue();
1617
1618 m_world = aWorld;
1619
1620 for( BOARD_ITEM* gitem : m_board->Drawings() )
1621 {
1622 if ( gitem->Type() == PCB_SHAPE_T || gitem->Type() == PCB_TEXTBOX_T )
1623 {
1624 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1625 }
1626 else if( gitem->Type() == PCB_TEXT_T )
1627 {
1628 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1629 }
1630 }
1631
1632 SHAPE_POLY_SET buffer;
1633 SHAPE_POLY_SET* boardOutline = nullptr;
1634
1635 if( m_board->GetBoardPolygonOutlines( buffer ) )
1636 boardOutline = &buffer;
1637
1638 for( ZONE* zone : m_board->Zones() )
1639 {
1640 syncZone( aWorld, zone, boardOutline );
1641 }
1642
1643 for( FOOTPRINT* footprint : m_board->Footprints() )
1644 {
1645 for( PAD* pad : footprint->Pads() )
1646 {
1647 std::vector<std::unique_ptr<PNS::SOLID>> solids = syncPad( pad );
1648
1649 for( std::unique_ptr<PNS::SOLID>& solid : solids )
1650 aWorld->Add( std::move( solid ) );
1651
1652 std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
1653
1654 if( clearanceOverride.has_value() )
1655 worstClearance = std::max( worstClearance, clearanceOverride.value() );
1656
1657 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1658 {
1659 std::unique_ptr<SHAPE> hole;
1660 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1661 aWorld->AddEdgeExclusion( std::move( hole ) );
1662 }
1663 }
1664
1665 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1666 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1667
1668 for( ZONE* zone : footprint->Zones() )
1669 syncZone( aWorld, zone, boardOutline );
1670
1671 for( PCB_FIELD* field : footprint->Fields() )
1672 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1673
1674 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1675 {
1676 if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_TEXTBOX_T )
1677 {
1678 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1679 }
1680 else if( item->Type() == PCB_TEXT_T )
1681 {
1682 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1683 }
1684 }
1685 }
1686
1687 for( PCB_TRACK* t : m_board->Tracks() )
1688 {
1689 KICAD_T type = t->Type();
1690
1691 if( type == PCB_TRACE_T )
1692 {
1693 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1694 aWorld->Add( std::move( segment ) );
1695 }
1696 else if( type == PCB_ARC_T )
1697 {
1698 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1699 aWorld->Add( std::move( arc ) );
1700 }
1701 else if( type == PCB_VIA_T )
1702 {
1703 std::vector<std::unique_ptr<PNS::VIA>> vias = syncVia( static_cast<PCB_VIA*>( t ) );
1704
1705 for( std::unique_ptr<PNS::VIA>& via : vias )
1706 aWorld->Add( std::move( via ) );
1707 }
1708 }
1709
1710 // NB: if this were ever to become a long-lived object we would need to dirty its
1711 // clearance cache here....
1712 delete m_ruleResolver;
1714
1716 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1717}
1718
1719
1721{
1722 for( BOARD_ITEM* item : m_hiddenItems )
1723 m_view->SetVisible( item, true );
1724
1725 m_hiddenItems.clear();
1726
1727 if( m_previewItems )
1728 {
1731 }
1732
1733 if( m_debugDecorator )
1735}
1736
1737
1739{
1740 m_debugDecorator = aDec;
1741}
1742
1743
1744void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, int aFlags )
1745{
1746 if( aItem->IsVirtual() )
1747 return;
1748
1749 if( ZONE* zone = dynamic_cast<ZONE*>( aItem->Parent() ) )
1750 {
1751 if( zone->GetIsRuleArea() )
1752 aFlags |= PNS_SEMI_SOLID;
1753 }
1754
1755 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, this, m_view, aFlags );
1756
1757 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1759 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1760
1761 if( aClearance >= 0 )
1762 {
1763 pitem->SetClearance( aClearance );
1764
1765 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1766
1767 switch( settings->m_Display.m_TrackClearance )
1768 {
1771 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1772 break;
1773
1775 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1776 break;
1777
1778 case SHOW_WHILE_ROUTING:
1779 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1780 break;
1781
1782 default:
1783 pitem->ShowClearance( false );
1784 break;
1785 }
1786 }
1787
1788 m_previewItems->Add( pitem );
1790}
1791
1792
1793void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1794{
1795 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, this, m_view );
1797
1798 COLOR4D color;
1799
1800 if( aImportance >= 1 )
1801 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1802 else if( aImportance == 0 )
1803 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1804
1805 pitem->SetColor( color );
1806
1807 m_previewItems->Add( pitem );
1809}
1810
1811
1813{
1814 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, this, m_view );
1815
1816 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1817 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1818 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1819 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1820 COLOR4D color = defaultColor;
1821
1822 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1823 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1824 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1825 int netCode = -1;
1826
1827 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
1828 netCode = net->GetNetCode();
1829
1830 const NETCLASS* nc = nullptr;
1831 const NET_SETTINGS* netSettings = connectivity->GetNetSettings();
1832
1833 if( connectivity->HasNetNameForNetCode( netCode ) )
1834 {
1835 const wxString& netName = connectivity->GetNetNameForNetCode( netCode );
1836
1837 if( netSettings && netSettings->HasEffectiveNetClass( netName ) )
1838 nc = netSettings->GetCachedEffectiveNetClass( netName ).get();
1839 }
1840
1841 if( colorByNet && netColors.count( netCode ) )
1842 color = netColors.at( netCode );
1843 else if( colorByNet && nc && nc->HasPcbColor() )
1844 color = nc->GetPcbColor();
1845 else
1846 color = defaultColor;
1847
1848 if( color == COLOR4D::UNSPECIFIED )
1849 color = defaultColor;
1850
1851 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
1852
1853 m_previewItems->Add( pitem );
1855}
1856
1857
1859{
1860 BOARD_ITEM* parent = aItem->Parent();
1861
1862 if( parent )
1863 {
1864 if( m_view->IsVisible( parent ) )
1865 m_hiddenItems.insert( parent );
1866
1867 m_view->SetVisible( parent, false );
1868 m_view->Update( parent, KIGFX::APPEARANCE );
1869
1870 for( ZONE* td : m_board->Zones() )
1871 {
1872 if( td->IsTeardropArea()
1873 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
1874 && td->Outline()->Collide( aItem->Shape() ) )
1875 {
1876 m_view->SetVisible( td, false );
1878 }
1879 }
1880 }
1881}
1882
1883
1885{
1886}
1887
1888
1890{
1891 BOARD_ITEM* parent = aItem->Parent();
1892
1893 if( aItem->OfKind( PNS::ITEM::SOLID_T ) )
1894 {
1895 PAD* pad = static_cast<PAD*>( parent );
1896 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1897
1898 m_fpOffsets[ pad ].p_old = pos;
1899 return;
1900 }
1901
1902 if( parent )
1903 {
1904 m_commit->Remove( parent );
1905 }
1906}
1907
1908
1910{
1911}
1912
1913
1915{
1916 BOARD_ITEM* board_item = aItem->Parent();
1917
1918 switch( aItem->Kind() )
1919 {
1920 case PNS::ITEM::ARC_T:
1921 {
1922 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1923 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
1924 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape() );
1925
1926 m_commit->Modify( arc_board );
1927
1928 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
1929 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
1930 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
1931 arc_board->SetWidth( arc->Width() );
1932 break;
1933 }
1934
1936 {
1937 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1938 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
1939 const SEG& s = seg->Seg();
1940
1941 m_commit->Modify( track );
1942
1943 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1944 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1945 track->SetWidth( seg->Width() );
1946 break;
1947 }
1948
1949 case PNS::ITEM::VIA_T:
1950 {
1951 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
1952 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1953
1954 m_commit->Modify( via_board );
1955
1956 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1957 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter() );
1958 via_board->SetDrill( via->Drill() );
1959 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
1960 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1961 via_board->SetIsFree( via->IsFree() );
1962 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
1963 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
1964 break;
1965 }
1966
1967 case PNS::ITEM::SOLID_T:
1968 {
1969 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1970 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1971
1972 // Don't add to commit; we'll add the parent footprints when processing the m_fpOffsets
1973
1974 m_fpOffsets[pad].p_old = pad->GetPosition();
1975 m_fpOffsets[pad].p_new = pos;
1976 break;
1977 }
1978
1979 default:
1980 m_commit->Modify( aItem->Parent() );
1981 break;
1982 }
1983}
1984
1985
1987{
1988 modifyBoardItem( aItem );
1989}
1990
1991
1993{
1994}
1995
1996
1998{
1999 BOARD_CONNECTED_ITEM* newBoardItem = nullptr;
2000 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem->Net() );
2001
2002 if( !net )
2004
2005 switch( aItem->Kind() )
2006 {
2007 case PNS::ITEM::ARC_T:
2008 {
2009 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
2010 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape() ) );
2011 new_arc->SetWidth( arc->Width() );
2012 new_arc->SetLayer( GetBoardLayerFromPNSLayer( arc->Layers().Start() ) );
2013 new_arc->SetNet( net );
2014 newBoardItem = new_arc;
2015 break;
2016 }
2017
2019 {
2020 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
2021 PCB_TRACK* track = new PCB_TRACK( m_board );
2022 const SEG& s = seg->Seg();
2023 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
2024 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
2025 track->SetWidth( seg->Width() );
2026 track->SetLayer( GetBoardLayerFromPNSLayer( seg->Layers().Start() ) );
2027 track->SetNet( net );
2028 newBoardItem = track;
2029 break;
2030 }
2031
2032 case PNS::ITEM::VIA_T:
2033 {
2034 PCB_VIA* via_board = new PCB_VIA( m_board );
2035 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
2036 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
2037 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter() );
2038 via_board->SetDrill( via->Drill() );
2039 via_board->SetNet( net );
2040 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
2041 via_board->SetIsFree( via->IsFree() );
2042 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
2043 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
2044 newBoardItem = via_board;
2045 break;
2046 }
2047
2048 case PNS::ITEM::SOLID_T:
2049 {
2050 PAD* pad = static_cast<PAD*>( aItem->Parent() );
2051 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2052
2053 m_fpOffsets[pad].p_new = pos;
2054 return nullptr;
2055 }
2056
2057 default:
2058 return nullptr;
2059 }
2060
2061 if( net->GetNetCode() <= 0 )
2062 {
2063 NETINFO_ITEM* newNetInfo = newBoardItem->GetNet();
2064
2065 newNetInfo->SetParent( m_board );
2066 newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->GetDefaultNetclass() );
2067 }
2068
2069 return newBoardItem;
2070}
2071
2072
2074{
2075 BOARD_CONNECTED_ITEM* boardItem = createBoardItem( aItem );
2076
2077 if( boardItem )
2078 {
2079 aItem->SetParent( boardItem );
2080 boardItem->ClearFlags();
2081
2082 m_commit->Add( boardItem );
2083 }
2084}
2085
2086
2088{
2089 std::set<FOOTPRINT*> processedFootprints;
2090
2091 EraseView();
2092
2093 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
2094 {
2095 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
2096 FOOTPRINT* footprint = pad->GetParentFootprint();
2097 VECTOR2I p_orig = footprint->GetPosition();
2098 VECTOR2I p_new = p_orig + offset;
2099
2100 if( processedFootprints.find( footprint ) != processedFootprints.end() )
2101 continue;
2102
2103 processedFootprints.insert( footprint );
2104 m_commit->Modify( footprint );
2105 footprint->SetPosition( p_new );
2106 }
2107
2108 m_fpOffsets.clear();
2109
2110 m_commit->Push( _( "Routing" ), m_commitFlags );
2111 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2112}
2113
2114
2116{
2117 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
2118}
2119
2120
2122{
2123 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
2124
2125 if( m_previewItems )
2126 {
2128 delete m_previewItems;
2129 }
2130
2131 m_view = aView;
2134
2135 if(m_view)
2137
2138 delete m_debugDecorator;
2139
2140 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR( this );
2141 m_debugDecorator = dec;
2142
2143 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2144
2145 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2146 dec->SetView( m_view );
2147}
2148
2149
2151{
2152 if( aNet )
2153 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2154 else
2155 return -1;
2156}
2157
2158
2160{
2161 if( aNet )
2162 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2163 else
2164 return wxEmptyString;
2165}
2166
2167
2169{
2170 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2171}
2172
2173
2175{
2177}
2178
2179
2181{
2182 return m_ruleResolver;
2183}
2184
2185
2187{
2188 m_tool = aTool;
2189 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2190}
2191
2192
2194{
2195 if( aLayer < 0 )
2196 return PCB_LAYER_ID::UNDEFINED_LAYER;
2197
2198 if( aLayer == 0 )
2199 return F_Cu;
2200
2201 if( aLayer == m_board->GetCopperLayerCount() - 1 )
2202 return B_Cu;
2203
2204 return static_cast<PCB_LAYER_ID>( ( aLayer + 1 ) * 2 );
2205}
2206
2207
2209{
2210 if( aLayer < 0 )
2211 return -1;
2212
2213 if( aLayer == F_Cu )
2214 return 0;
2215
2216 if( aLayer == B_Cu )
2217 return m_board->GetCopperLayerCount() - 1;
2218
2219 return ( aLayer / 2 ) - 1;
2220}
2221
2222
2224{
2226}
2227
2228
2230{
2231 return PNS_LAYER_RANGE( GetPNSLayerFromBoardLayer( aStartLayer ),
2232 GetPNSLayerFromBoardLayer( aEndLayer ) );
2233}
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:80
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:238
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:91
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:320
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:289
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:258
virtual bool IsLocked() const
Definition: board_item.cpp:75
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:117
virtual bool IsOnCopperLayer() const
Definition: board_item.h:151
Manage layers needed to make a physical board.
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h: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:2491
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:1987
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1916
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:896
int GetCopperLayerCount() const
Definition: board.cpp:736
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition: board.cpp:1937
const FOOTPRINTS & Footprints() const
Definition: board.h:331
const TRACKS & Tracks() const
Definition: board.h:329
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:890
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:159
SEVERITY GetSeverity() const
Definition: drc_rule.h:172
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:151
bool IsNull() const
Definition: drc_rule.h:146
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:2334
bool IsNetTie() const
Definition: footprint.h:296
VECTOR2I GetPosition() const override
Definition: footprint.h:223
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:204
virtual void SetLayer(int aLayer)
Set layer used to draw the group.
Definition: view_group.h:99
virtual void Add(VIEW_ITEM *aItem)
Add an item to the group.
Definition: view_group.cpp:58
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h: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:763
@ 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:275
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:138
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:486
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:260
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:474
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition: pad.cpp:966
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:540
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:622
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:633
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:1165
VECTOR2I GetPosition() const override
Definition: pcb_track.h:484
const PADSTACK & Padstack() const
Definition: pcb_track.h:403
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:599
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:634
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:485
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:1116
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_track.cpp:1003
int GetWidth() const override
Definition: pcb_track.cpp:337
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:401
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:1159
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:589
VIATYPE GetViaType() const
Definition: pcb_track.h:400
void SetWidth(int aWidth) override
Definition: pcb_track.cpp:329
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:1137
int Width() const override
Definition: pns_arc.h:88
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_arc.h:78
void SetDebugEnabled(bool aEnabled)
static HOLE * MakeCircularHole(const VECTOR2I &pos, int radius)
Definition: pns_hole.cpp:131
ITEM_SET & ExcludeItem(const ITEM *aItem)
ITEM_SET & FilterKinds(int aKindMask, bool aInvert=false)
Definition: pns_itemset.cpp:70
std::vector< ITEM * > & Items()
Definition: pns_itemset.h:87
Base class for PNS router board items.
Definition: pns_item.h:97
BOARD_ITEM * Parent() const
Definition: pns_item.h:186
virtual ITEM * ParentPadVia() const
Definition: pns_item.h:262
const PNS_LAYER_RANGE & Layers() const
Definition: pns_item.h:196
virtual NET_HANDLE Net() const
Definition: pns_item.h:194
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:167
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:193
virtual int Layer() const
Definition: pns_item.h:200
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:225
void SetLayer(int aLayer)
Definition: pns_item.h:199
@ SEGMENT_T
Definition: pns_item.h:106
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:185
bool OfKind(int aKindMask) const
Definition: pns_item.h:175
bool IsVirtual() const
Definition: pns_item.h:264
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:237
virtual BOARD_ITEM * BoardItem() const
Definition: pns_item.h:191
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
Definition: pns_joint.h:43
const ITEM_SET & CLinks() const
Definition: pns_joint.h:278
Keep the router "world" - i.e.
Definition: pns_node.h:207
void SetMaxClearance(int aClearance)
Assign a clearance resolution function object.
Definition: pns_node.h:234
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:663
void SetRuleResolver(RULE_RESOLVER *aFunc)
Definition: pns_node.h:240
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
Definition: pns_node.cpp:707
const ITEM_OWNER * Owner() const
Return the owner of this item, or NULL if there's none.
Definition: pns_item.h:71
virtual wxString GetNetName(PNS::NET_HANDLE aNet) const =0
virtual int GetNetCode(NET_HANDLE aNet) const =0
virtual PCB_LAYER_ID GetBoardLayerFromPNSLayer(int aLayer) const =0
const SEG & Seg() const
Definition: pns_segment.h:84
void SetEnds(const VECTOR2I &a, const VECTOR2I &b)
Definition: pns_segment.h:94
int Width() const override
Definition: pns_segment.h:79
void SetTrackWidth(int aWidth)
void SetBoardMinTrackWidth(int aWidth)
void SetDiffPairViaGapSameAsTraceGap(bool aEnable)
void SetDiffPairWidth(int aWidth)
void SetDiffPairWidthSource(const wxString &aSource)
void SetDiffPairGapSource(const wxString &aSource)
void SetDiffPairGap(int aGap)
void SetHoleToHole(int aHoleToHole)
void SetViaDrill(int aDrill)
void SetDiffPairViaGap(int aGap)
void SetDiffPairHoleToHole(int aHoleToHole)
void SetMinClearance(int aClearance)
void SetClearance(int aClearance)
void SetViaDiameter(int aDiameter)
void SetClearanceSource(const wxString &aSource)
void SetWidthSource(const wxString &aSource)
void SetTrackWidthIsExplicit(bool aIsExplicit)
bool syncGraphicalItem(PNS::NODE *aWorld, PCB_SHAPE *aItem)
bool inheritTrackWidth(PNS::ITEM *aItem, int *aInheritedWidth)
void AddItem(PNS::ITEM *aItem) override
virtual EDA_UNITS GetUnits() const
PNS::DEBUG_DECORATOR * m_debugDecorator
void SetDebugDecorator(PNS::DEBUG_DECORATOR *aDec)
std::vector< std::unique_ptr< PNS::VIA > > syncVia(PCB_VIA *aVia)
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
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:82
bool Overlaps(const PNS_LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
int End() const
Definition: pns_layerset.h:87
PNS_LAYER_RANGE Intersection(const PNS_LAYER_RANGE &aOther) const
Shortcut for comparisons/overlap tests.
Definition: pns_layerset.h:108
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
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:206
@ LAYER_SELECT_OVERLAY
currently selected items overlay
Definition: layer_ids.h:221
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