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-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <board.h>
25#include <netinfo.h>
26#include <footprint.h>
27#include <pad.h>
28#include <pcb_track.h>
29#include <zone.h>
30#include <pcb_shape.h>
31#include <pcb_text.h>
32#include <board_commit.h>
33#include <layer_ids.h>
35#include <confirm.h>
36#include <tools/pcb_tool_base.h>
37#include <tool/tool_manager.h>
39
41#include <pcb_painter.h>
42
43#include <geometry/shape.h>
45#include <geometry/shape_arc.h>
47
48#include <drc/drc_rule.h>
49#include <drc/drc_engine.h>
50
52
53#include <wx/log.h>
54
55#include <memory>
56
57#include <advanced_config.h>
58#include <pcbnew_settings.h>
59#include <macros.h>
60
61#include "pns_kicad_iface.h"
62#include "pns_arc.h"
63#include "pns_sizes_settings.h"
64#include "pns_item.h"
65#include "pns_line.h"
66#include "pns_solid.h"
67#include "pns_segment.h"
68#include "pns_node.h"
69#include "pns_router.h"
70#include "pns_debug_decorator.h"
71#include "router_preview_item.h"
72
74
75
77{
78 const PNS::ITEM* A;
79 const PNS::ITEM* B;
80 bool Flag;
81
82 bool operator==(const CLEARANCE_CACHE_KEY& other) const
83 {
84 return A == other.A && B == other.B && Flag == other.Flag;
85 }
86};
87
88namespace std
89{
90 template <>
92 {
93 std::size_t operator()( const CLEARANCE_CACHE_KEY& k ) const
94 {
95 return hash<const void*>()( k.A ) ^ hash<const void*>()( k.B ) ^ hash<int>()( k.Flag );
96 }
97 };
98}
99
100
102{
103public:
104 PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER_IFACE* aRouterIface );
106
107 virtual int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
108 bool aUseClearanceEpsilon = true ) override;
109
110 virtual PNS::NET_HANDLE DpCoupledNet( PNS::NET_HANDLE aNet ) override;
111 virtual int DpNetPolarity( PNS::NET_HANDLE aNet ) override;
112 virtual bool DpNetPair( const PNS::ITEM* aItem, PNS::NET_HANDLE& aNetP,
113 PNS::NET_HANDLE& aNetN ) override;
114
115 virtual int NetCode( PNS::NET_HANDLE aNet ) override;
116 virtual wxString NetName( PNS::NET_HANDLE aNet ) override;
117
118 virtual bool IsInNetTie( const PNS::ITEM* aA ) override;
119 virtual bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
120 const PNS::ITEM* aCollidingItem ) override;
121
122 virtual bool IsKeepout( const PNS::ITEM* aA, const PNS::ITEM* aB ) override;
123
124 virtual bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
125 const PNS::ITEM* aItemB, int aLayer,
126 PNS::CONSTRAINT* aConstraint ) override;
127
128 int ClearanceEpsilon() const override { return m_clearanceEpsilon; }
129
130 void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
131 void ClearCaches() override;
132
133private:
143 int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet );
144
145private:
152
153 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
154};
155
156
158 PNS::ROUTER_IFACE* aRouterIface ) :
159 m_routerIface( aRouterIface ),
160 m_board( aBoard ),
161 m_dummyTracks{ { aBoard }, { aBoard } },
162 m_dummyArcs{ { aBoard }, { aBoard } },
163 m_dummyVias{ { aBoard }, { aBoard } }
164{
165 for( PCB_TRACK& track : m_dummyTracks )
166 track.SetFlags( ROUTER_TRANSIENT );
167
168 for( PCB_ARC& arc : m_dummyArcs )
169 arc.SetFlags( ROUTER_TRANSIENT );
170
171 for ( PCB_VIA& via : m_dummyVias )
172 via.SetFlags( ROUTER_TRANSIENT );
173
174 if( aBoard )
175 m_clearanceEpsilon = aBoard->GetDesignSettings().GetDRCEpsilon();
176 else
177 m_clearanceEpsilon = 0;
178}
179
180
182{
183}
184
185
187{
188 BOARD_ITEM* item = aA->BoardItem();
189
190 return item && item->GetParentFootprint() && item->GetParentFootprint()->IsNetTie();
191}
192
193
195 const VECTOR2I& aCollisionPos,
196 const PNS::ITEM* aCollidingItem )
197{
198 wxCHECK( aItem && aCollidingItem, false );
199
200 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
201 BOARD_ITEM* item = aItem->BoardItem();
202 BOARD_ITEM* collidingItem = aCollidingItem->BoardItem();
203
204 FOOTPRINT* collidingFp = collidingItem->GetParentFootprint();
205 FOOTPRINT* itemFp = item ? item->GetParentFootprint() : nullptr;
206
207 if( collidingFp && itemFp && ( collidingFp == itemFp ) && itemFp->IsNetTie() )
208 {
209 // Two items colliding from the same net tie footprint are not checked
210 return true;
211 }
212
213 if( drcEngine )
214 {
215 return drcEngine->IsNetTieExclusion( NetCode( aItem->Net() ), ToLAYER_ID( aItem->Layer() ),
216 aCollisionPos, collidingItem );
217 }
218
219 return false;
220}
221
222
224{
225 auto checkKeepout =
226 []( const ZONE* aKeepout, const BOARD_ITEM* aOther )
227 {
228 if( aKeepout->GetDoNotAllowTracks() && aOther->IsType( { PCB_ARC_T, PCB_TRACE_T } ) )
229 return true;
230
231 if( aKeepout->GetDoNotAllowVias() && aOther->Type() == PCB_VIA_T )
232 return true;
233
234 if( aKeepout->GetDoNotAllowPads() && aOther->Type() == PCB_PAD_T )
235 return true;
236
237 // Incomplete test, but better than nothing:
238 if( aKeepout->GetDoNotAllowFootprints() && aOther->Type() == PCB_PAD_T )
239 {
240 return !aKeepout->GetParentFootprint()
241 || aKeepout->GetParentFootprint() != aOther->GetParentFootprint();
242 }
243
244 return false;
245 };
246
247 if( aA->Parent() && aA->Parent()->Type() == PCB_ZONE_T )
248 {
249 const ZONE* zoneA = static_cast<ZONE*>( aA->Parent() );
250
251 if( zoneA->GetIsRuleArea() && aB->Parent() )
252 return checkKeepout( zoneA, aB->Parent() );
253 }
254
255 if( aB->Parent() && aB->Parent()->Type() == PCB_ZONE_T )
256 {
257 const ZONE* zoneB = static_cast<ZONE*>( aB->Parent() );
258
259 if( zoneB->GetIsRuleArea() && aA->Parent() )
260 return checkKeepout( zoneB, aA->Parent() );
261 }
262
263 return false;
264}
265
266
267static bool isCopper( const PNS::ITEM* aItem )
268{
269 if ( !aItem )
270 return false;
271
272 const BOARD_ITEM *parent = aItem->Parent();
273
274 return !parent || parent->IsOnCopperLayer();
275}
276
277
278static bool isHole( const PNS::ITEM* aItem )
279{
280 if ( !aItem )
281 return false;
282
283 return aItem->OfKind( PNS::ITEM::HOLE_T );
284}
285
286
287static bool isDrilledHole( const PNS::ITEM* aItem )
288{
289 if( !isHole( aItem ) )
290 return false;
291
292 if( PAD* pad = dynamic_cast<PAD*>( aItem->Parent() ) )
293 return pad->GetDrillSizeX() && pad->GetDrillSizeX() == pad->GetDrillSizeY();
294
295 // Via holes are (currently) always round
296
297 return true;
298}
299
300
301static bool isNonPlatedSlot( const PNS::ITEM* aItem )
302{
303 if( !isHole( aItem ) )
304 return false;
305
306 if( PAD* pad = dynamic_cast<PAD*>( aItem->Parent() ) )
307 return pad->GetAttribute() == PAD_ATTRIB::NPTH && pad->GetDrillSizeX() != pad->GetDrillSizeY();
308
309 // Via holes are (currently) always round
310
311 return false;
312}
313
314
315static bool isEdge( const PNS::ITEM* aItem )
316{
317 if ( !aItem )
318 return false;
319
320 const PCB_SHAPE *parent = dynamic_cast<PCB_SHAPE*>( aItem->BoardItem() );
321
322 return parent && ( parent->IsOnLayer( Edge_Cuts ) || parent->IsOnLayer( Margin ) );
323}
324
325
327 const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
328 int aLayer, PNS::CONSTRAINT* aConstraint )
329{
330 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
331
332 if( !drcEngine )
333 return false;
334
335 DRC_CONSTRAINT_T hostType;
336
337 switch ( aType )
338 {
348 default: return false; // should not happen
349 }
350
351 BOARD_ITEM* parentA = aItemA ? aItemA->BoardItem() : nullptr;
352 BOARD_ITEM* parentB = aItemB ? aItemB->BoardItem() : nullptr;
353 DRC_CONSTRAINT hostConstraint;
354
355 // A track being routed may not have a BOARD_ITEM associated yet.
356 if( aItemA && !parentA )
357 {
358 switch( aItemA->Kind() )
359 {
360 case PNS::ITEM::ARC_T:
361 m_dummyArcs[0].SetLayer( ToLAYER_ID( aLayer ) );
362 m_dummyArcs[0].SetNet( static_cast<NETINFO_ITEM*>( aItemA->Net() ) );
363 m_dummyArcs[0].SetStart( aItemA->Anchor( 0 ) );
364 m_dummyArcs[0].SetEnd( aItemA->Anchor( 1 ) );
365 parentA = &m_dummyArcs[0];
366 break;
367
368 case PNS::ITEM::VIA_T:
370 m_dummyVias[0].SetLayer( ToLAYER_ID( aLayer ) );
371 m_dummyVias[0].SetNet( static_cast<NETINFO_ITEM*>( aItemA->Net() ) );
372 m_dummyVias[0].SetStart( aItemA->Anchor( 0 ) );
373 parentA = &m_dummyVias[0];
374 break;
375
378 m_dummyTracks[0].SetLayer( ToLAYER_ID( aLayer ) );
379 m_dummyTracks[0].SetNet( static_cast<NETINFO_ITEM*>( aItemA->Net() ) );
380 m_dummyTracks[0].SetStart( aItemA->Anchor( 0 ) );
381 m_dummyTracks[0].SetEnd( aItemA->Anchor( 1 ) );
382 parentA = &m_dummyTracks[0];
383 break;
384
385 default:
386 break;
387 }
388 }
389
390 if( aItemB && !parentB )
391 {
392 switch( aItemB->Kind() )
393 {
394 case PNS::ITEM::ARC_T:
395 m_dummyArcs[1].SetLayer( ToLAYER_ID( aLayer ) );
396 m_dummyArcs[1].SetNet( static_cast<NETINFO_ITEM*>( aItemB->Net() ) );
397 m_dummyArcs[1].SetStart( aItemB->Anchor( 0 ) );
398 m_dummyArcs[1].SetEnd( aItemB->Anchor( 1 ) );
399 parentB = &m_dummyArcs[1];
400 break;
401
402 case PNS::ITEM::VIA_T:
404 m_dummyVias[1].SetLayer( ToLAYER_ID( aLayer ) );
405 m_dummyVias[1].SetNet( static_cast<NETINFO_ITEM*>( aItemB->Net() ) );
406 m_dummyVias[1].SetStart( aItemB->Anchor( 0 ) );
407 parentB = &m_dummyVias[1];
408 break;
409
412 m_dummyTracks[1].SetLayer( ToLAYER_ID( aLayer ) );
413 m_dummyTracks[1].SetNet( static_cast<NETINFO_ITEM*>( aItemB->Net() ) );
414 m_dummyTracks[1].SetStart( aItemB->Anchor( 0 ) );
415 m_dummyTracks[1].SetEnd( aItemB->Anchor( 1 ) );
416 parentB = &m_dummyTracks[1];
417 break;
418
419 default:
420 break;
421 }
422 }
423
424 if( parentA )
425 hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, ToLAYER_ID( aLayer ) );
426
427 if( hostConstraint.IsNull() )
428 return false;
429
430 if( hostConstraint.GetSeverity() == RPT_SEVERITY_IGNORE )
431 {
432 aConstraint->m_Value.SetMin( -1 );
433 aConstraint->m_RuleName = hostConstraint.GetName();
434 aConstraint->m_Type = aType;
435 return true;
436 }
437
438 switch ( aType )
439 {
448 aConstraint->m_Value = hostConstraint.GetValue();
449 aConstraint->m_RuleName = hostConstraint.GetName();
450 aConstraint->m_Type = aType;
451 return true;
452
453 default:
454 return false;
455 }
456}
457
458
459void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems )
460{
461 int n_pruned = 0;
462 std::set<const PNS::ITEM*> remainingItems( aItems.begin(), aItems.end() );
463
464/* We need to carefully check both A and B item pointers in the cache against dirty/invalidated
465 items in the set, as the clearance relation is commutative ( CL[a,b] == CL[b,a] ). The code
466 below is a bit ugly, but works in O(n*log(m)) and is run once or twice during ROUTER::Move() call
467 - so I hope it still gets better performance than no cache at all */
468 for( auto it = m_clearanceCache.begin(); it != m_clearanceCache.end(); )
469 {
470 bool dirty = remainingItems.find( it->first.A ) != remainingItems.end();
471 dirty |= remainingItems.find( it->first.B) != remainingItems.end();
472
473 if( dirty )
474 {
475 it = m_clearanceCache.erase( it );
476 n_pruned++;
477 } else
478 it++;
479 }
480#if 0
481 printf("ClearCache : n_pruned %d\n", n_pruned );
482#endif
483}
484
485
487{
488 m_clearanceCache.clear();
489}
490
491
493 bool aUseClearanceEpsilon )
494{
495 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
496 auto it = m_clearanceCache.find( key );
497
498 if( it != m_clearanceCache.end() )
499 return it->second;
500
501 PNS::CONSTRAINT constraint;
502 int rv = 0;
503 LAYER_RANGE layers;
504
505 if( !aB )
506 layers = aA->Layers();
507 else if( isEdge( aA ) )
508 layers = aB->Layers();
509 else if( isEdge( aB ) )
510 layers = aA->Layers();
511 else
512 layers = aA->Layers().Intersection( aB->Layers() );
513
514 // Normalize layer range (no -1 magic numbers)
516
517 for( int layer = layers.Start(); layer <= layers.End(); ++layer )
518 {
519 if( isDrilledHole( aA ) && isDrilledHole( aB) )
520 {
521 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer, &constraint ) )
522 {
523 if( constraint.m_Value.Min() > rv )
524 rv = constraint.m_Value.Min();
525 }
526 }
527 else if( isHole( aA ) || isHole( aB ) )
528 {
529 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
530 {
531 if( constraint.m_Value.Min() > rv )
532 rv = constraint.m_Value.Min();
533 }
534 }
535 else if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
536 {
537 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_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'; non-plated milled holes get both HOLE_CLEARANCE and EDGE_CLEARANCE
545 if( isEdge( aA ) || isNonPlatedSlot( aA ) || isEdge( aB ) || isNonPlatedSlot( aB ) )
546 {
547 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
548 {
549 if( constraint.m_Value.Min() > rv )
550 rv = constraint.m_Value.Min();
551 }
552 }
553 }
554
555 if( aUseClearanceEpsilon && rv > 0 )
556 rv = std::max( 0, rv - m_clearanceEpsilon );
557
558
559/* It makes no sense to put items that have no owning NODE in the cache - they can be allocated on stack
560 and we can't really invalidate them in the cache when they are destroyed. Probably a better idea would be
561 to use a static unique counter in PNS::ITEM constructor to generate the cache keys. */
562 if( aA && aB && aA->Owner() && aB->Owner() )
563 {
564 m_clearanceCache[ key ] = rv;
565 }
566
567 return rv;
568}
569
570
571bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth )
572{
573 VECTOR2I p;
574
575 assert( aItem->Owner() != nullptr );
576
577 auto tryGetTrackWidth =
578 []( PNS::ITEM* aPnsItem ) -> int
579 {
580 switch( aPnsItem->Kind() )
581 {
582 case PNS::ITEM::SEGMENT_T: return static_cast<PNS::SEGMENT*>( aPnsItem )->Width();
583 case PNS::ITEM::ARC_T: return static_cast<PNS::ARC*>( aPnsItem )->Width();
584 default: return -1;
585 }
586 };
587
588 int itemTrackWidth = tryGetTrackWidth( aItem );
589
590 if( itemTrackWidth > 0 )
591 {
592 *aInheritedWidth = itemTrackWidth;
593 return true;
594 }
595
596 switch( aItem->Kind() )
597 {
598 case PNS::ITEM::VIA_T: p = static_cast<PNS::VIA*>( aItem )->Pos(); break;
599 case PNS::ITEM::SOLID_T: p = static_cast<PNS::SOLID*>( aItem )->Pos(); break;
600 default: return false;
601 }
602
603 const PNS::JOINT* jt = static_cast<const PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
604
605 assert( jt != nullptr );
606
607 int mval = INT_MAX;
608
609 PNS::ITEM_SET linkedSegs( jt->CLinks() );
611
612 for( PNS::ITEM* item : linkedSegs.Items() )
613 {
614 int w = tryGetTrackWidth( item );
615
616 if( w > 0 )
617 mval = std::min( w, mval );
618 }
619
620 if( mval == INT_MAX )
621 return false;
622
623 *aInheritedWidth = mval;
624 return true;
625}
626
627
629 PNS::NET_HANDLE aNet )
630{
632 PNS::CONSTRAINT constraint;
633
634 if( aStartItem && m_startLayer < 0 )
635 m_startLayer = aStartItem->Layer();
636
637 aSizes.SetClearance( bds.m_MinClearance );
638 aSizes.SetMinClearance( bds.m_MinClearance );
639 aSizes.SetClearanceSource( _( "board minimum clearance" ) );
640
642 m_startLayer, &constraint ) )
643 {
644 if( constraint.m_Value.Min() > bds.m_MinClearance )
645 {
646 aSizes.SetClearance( constraint.m_Value.Min() );
647 aSizes.SetClearanceSource( constraint.m_RuleName );
648 }
649 }
650
651 int trackWidth = bds.m_TrackMinWidth;
652 bool found = false;
653 aSizes.SetWidthSource( _( "board minimum track width" ) );
654
655 if( bds.m_UseConnectedTrackWidth && !bds.m_TempOverrideTrackWidth && aStartItem != nullptr )
656 {
657 found = inheritTrackWidth( aStartItem, &trackWidth );
658
659 if( found )
660 aSizes.SetWidthSource( _( "existing track" ) );
661 }
662
663 if( !found && bds.UseNetClassTrack() && aStartItem )
664 {
666 m_startLayer, &constraint ) )
667 {
668 trackWidth = std::max( trackWidth, constraint.m_Value.Opt() );
669 found = true;
670
671 if( trackWidth == constraint.m_Value.Opt() )
672 aSizes.SetWidthSource( constraint.m_RuleName );
673 }
674 }
675
676 if( !found )
677 {
678 trackWidth = std::max( trackWidth, bds.GetCurrentTrackWidth() );
679
680 if( bds.UseNetClassTrack() )
681 aSizes.SetWidthSource( _( "netclass 'Default'" ) );
682 else if( trackWidth == bds.GetCurrentTrackWidth() )
683 aSizes.SetWidthSource( _( "user choice" ) );
684 }
685
686 aSizes.SetTrackWidth( trackWidth );
689
690 int viaDiameter = bds.m_ViasMinSize;
691 int viaDrill = bds.m_MinThroughDrill;
692
693 PNS::VIA dummyVia, coupledVia;
694
695 if( aStartItem )
696 {
697 dummyVia.SetNet( aStartItem->Net() );
698 coupledVia.SetNet( m_ruleResolver->DpCoupledNet( aStartItem->Net() ) );
699 }
700
701 if( bds.UseNetClassVia() && aStartItem ) // netclass value
702 {
704 nullptr, m_startLayer, &constraint ) )
705 {
706 viaDiameter = std::max( viaDiameter, constraint.m_Value.Opt() );
707 }
708
710 nullptr, m_startLayer, &constraint ) )
711 {
712 viaDrill = std::max( viaDrill, constraint.m_Value.Opt() );
713 }
714 }
715 else
716 {
717 viaDiameter = bds.GetCurrentViaSize();
718 viaDrill = bds.GetCurrentViaDrill();
719 }
720
721 aSizes.SetViaDiameter( viaDiameter );
722 aSizes.SetViaDrill( viaDrill );
723
724 int diffPairWidth = bds.m_TrackMinWidth;
725 int diffPairGap = bds.m_MinClearance;
726 int diffPairViaGap = bds.m_MinClearance;
727
728 aSizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
729 aSizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
730
731 found = false;
732
733 // First try to pick up diff pair width from starting track, if enabled
734 if( bds.m_UseConnectedTrackWidth && aStartItem )
735 found = inheritTrackWidth( aStartItem, &diffPairWidth );
736
737 // Next, pick up gap from netclass, and width also if we didn't get a starting width above
738 if( bds.UseNetClassDiffPair() && aStartItem )
739 {
741 nullptr, m_startLayer, &constraint ) )
742 {
743 diffPairWidth = std::max( diffPairWidth, constraint.m_Value.Opt() );
744
745 if( diffPairWidth == constraint.m_Value.Opt() )
746 aSizes.SetDiffPairWidthSource( constraint.m_RuleName );
747 }
748
750 nullptr, m_startLayer, &constraint ) )
751 {
752 diffPairGap = std::max( diffPairGap, constraint.m_Value.Opt() );
753 diffPairViaGap = std::max( diffPairViaGap, constraint.m_Value.Opt() );
754
755 if( diffPairGap == constraint.m_Value.Opt() )
756 aSizes.SetDiffPairGapSource( constraint.m_RuleName );
757 }
758 }
759 else
760 {
761 diffPairWidth = bds.GetCurrentDiffPairWidth();
762 diffPairGap = bds.GetCurrentDiffPairGap();
763 diffPairViaGap = bds.GetCurrentDiffPairViaGap();
764
765 aSizes.SetDiffPairWidthSource( _( "user choice" ) );
766 aSizes.SetDiffPairGapSource( _( "user choice" ) );
767 }
768
769 aSizes.SetDiffPairWidth( diffPairWidth );
770 aSizes.SetDiffPairGap( diffPairGap );
771 aSizes.SetDiffPairViaGap( diffPairViaGap );
772 aSizes.SetDiffPairViaGapSameAsTraceGap( false );
773
774 int holeToHoleMin = bds.m_HoleToHoleMin;
775
777 &dummyVia, UNDEFINED_LAYER, &constraint ) )
778 {
779 holeToHoleMin = constraint.m_Value.Min();
780 }
781
782 aSizes.SetHoleToHole( holeToHoleMin );
783
785 &coupledVia, UNDEFINED_LAYER, &constraint ) )
786 {
787 holeToHoleMin = constraint.m_Value.Min();
788 }
789
790 aSizes.SetDiffPairHoleToHole( holeToHoleMin );
791
792 return true;
793}
794
795
796int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const
797{
799 return 0;
800
802
803 return stackup.GetLayerDistance( ToLAYER_ID( aFirstLayer ), ToLAYER_ID( aSecondLayer ) );
804}
805
806
807int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
808{
809 int rv = 0;
810 int count = 0;
811
812 for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
813 {
814 int ch = *it;
815
816 if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
817 {
818 continue;
819 }
820 else if( ch == '+' )
821 {
822 aComplementNet = wxT( "-" );
823 rv = 1;
824 }
825 else if( ch == '-' )
826 {
827 aComplementNet = wxT( "+" );
828 rv = -1;
829 }
830 else if( ch == 'N' )
831 {
832 aComplementNet = wxT( "P" );
833 rv = -1;
834 }
835 else if ( ch == 'P' )
836 {
837 aComplementNet = wxT( "N" );
838 rv = 1;
839 }
840 else
841 {
842 break;
843 }
844 }
845
846 if( rv != 0 && count >= 1 )
847 {
848 aComplementNet = aNetName.Left( aNetName.length() - count )
849 + aComplementNet
850 + aNetName.Right( count - 1 );
851 }
852
853 return rv;
854}
855
856
858{
859 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
860 {
861 wxString refName = net->GetNetname();
862 wxString coupledNetName;
863
864 if( matchDpSuffix( refName, coupledNetName ) )
865 return m_board->FindNet( coupledNetName );
866 }
867
868 return nullptr;
869}
870
871
873{
874 return m_routerIface->GetNetCode( aNet );
875}
876
877
879{
880 return m_routerIface->GetNetName( aNet );
881}
882
883
885{
886 wxString refName;
887
888 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
889 refName = net->GetNetname();
890
891 wxString dummy1;
892
893 return matchDpSuffix( refName, dummy1 );
894}
895
896
898 PNS::NET_HANDLE& aNetN )
899{
900 if( !aItem || !aItem->Net() )
901 return false;
902
903 wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
904 wxString netNameN, netNameCoupled;
905
906 int r = matchDpSuffix( netNameP, netNameCoupled );
907
908 if( r == 0 )
909 {
910 return false;
911 }
912 else if( r == 1 )
913 {
914 netNameN = netNameCoupled;
915 }
916 else
917 {
918 netNameN = netNameP;
919 netNameP = netNameCoupled;
920 }
921
922 PNS::NET_HANDLE netInfoP = m_board->FindNet( netNameP );
923 PNS::NET_HANDLE netInfoN = m_board->FindNet( netNameN );
924
925 if( !netInfoP || !netInfoN )
926 return false;
927
928 aNetP = netInfoP;
929 aNetN = netInfoN;
930
931 return true;
932}
933
934
936{
937public:
940 m_view( nullptr ),
941 m_items( nullptr ),
942 m_depth( 0 )
943 {
944 SetView( aView );
945 }
946
948 {
950 delete m_items;
951 }
952
953 void SetView( KIGFX::VIEW* aView )
954 {
955 Clear();
956 delete m_items;
957 m_items = nullptr;
958 m_view = aView;
959
960 if( m_view == nullptr )
961 return;
962
963 if( m_view->GetGAL() )
965
968 m_view->Add( m_items );
969 }
970
971 void AddPoint( const VECTOR2I& aP, const KIGFX::COLOR4D& aColor, int aSize,
972 const wxString& aName = wxT( "" ),
973 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
974
975 {
977
978 sh.SetWidth( 10000 );
979
980 sh.Append( aP.x - aSize, aP.y - aSize );
981 sh.Append( aP.x + aSize, aP.y + aSize );
982 sh.Append( aP.x, aP.y );
983 sh.Append( aP.x - aSize, aP.y + aSize );
984 sh.Append( aP.x + aSize, aP.y - aSize );
985
986 AddShape( &sh, aColor, sh.Width(), aName, aSrcLoc );
987 }
988
989 void AddItem( const PNS::ITEM* aItem, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
990 const wxString& aName = wxT( "" ),
991 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
992 {
993 if( !m_view || !aItem )
994 return;
995
996 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
997
998 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
999 pitem->SetWidth( aOverrideWidth );
1000 pitem->SetDepth( nextDepth() );
1001
1002 m_items->Add( pitem );
1003 m_view->Update( m_items );
1004 }
1005
1006 void AddShape( const BOX2I& aBox, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1007 const wxString& aName = wxT( "" ),
1008 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1009 {
1011 l.SetWidth( aOverrideWidth );
1012
1013 VECTOR2I o = aBox.GetOrigin();
1014 VECTOR2I s = aBox.GetSize();
1015
1016 l.Append( o );
1017 l.Append( o.x + s.x, o.y );
1018 l.Append( o.x + s.x, o.y + s.y );
1019 l.Append( o.x, o.y + s.y );
1020 l.Append( o );
1021
1022 AddShape( &l, aColor, aOverrideWidth, aName, aSrcLoc );
1023 }
1024
1025 void AddShape( const SHAPE* aShape, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1026 const wxString& aName = wxT( "" ),
1027 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1028 {
1029 if( !m_view || !aShape )
1030 return;
1031
1032 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_view );
1033
1034 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
1035 pitem->SetWidth( aOverrideWidth );
1036 pitem->SetDepth( nextDepth() );
1037
1038 m_items->Add( pitem );
1039 m_view->Update( m_items );
1040 }
1041
1042 void Clear() override
1043 {
1044 if( m_view && m_items )
1045 {
1046 m_items->FreeItems();
1047 m_view->Update( m_items );
1048
1049 if( m_view->GetGAL() )
1051 }
1052 }
1053
1054private:
1055 double nextDepth()
1056 {
1057 // Use different depths so that the transculent shapes won't overwrite each other.
1058
1059 m_depth++;
1060
1061 if( m_depth >= 0 && m_view->GetGAL() )
1063
1064 return m_depth;
1065 }
1066
1069
1070 double m_depth;
1071};
1072
1073
1075{
1076 return m_debugDecorator;
1077}
1078
1079
1081{
1082 m_ruleResolver = nullptr;
1083 m_board = nullptr;
1084 m_world = nullptr;
1085 m_debugDecorator = nullptr;
1086 m_startLayer = -1;
1087}
1088
1089
1091{
1092 m_tool = nullptr;
1093 m_view = nullptr;
1094 m_previewItems = nullptr;
1095 m_commitFlags = 0;
1096}
1097
1098
1100{
1101}
1102
1103
1105{
1106 delete m_ruleResolver;
1107 delete m_debugDecorator;
1108
1109 if( m_previewItems )
1110 {
1112 delete m_previewItems;
1113 }
1114}
1115
1116
1117std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1118{
1119 LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 );
1120
1121 // ignore non-copper pads except for those with holes
1122 if( ( aPad->GetLayerSet() & LSET::AllCuMask() ).none() && aPad->GetDrillSize().x == 0 )
1123 return nullptr;
1124
1125 switch( aPad->GetAttribute() )
1126 {
1127 case PAD_ATTRIB::PTH:
1128 case PAD_ATTRIB::NPTH:
1129 break;
1130
1131 case PAD_ATTRIB::CONN:
1132 case PAD_ATTRIB::SMD:
1133 {
1134 LSET lmsk = aPad->GetLayerSet();
1135 bool is_copper = false;
1136
1137 for( int i = 0; i < MAX_CU_LAYERS; i++ )
1138 {
1139 if( lmsk[i] )
1140 {
1141 is_copper = true;
1142
1143 if( aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1144 layers = LAYER_RANGE( i );
1145
1146 break;
1147 }
1148 }
1149
1150 if( !is_copper )
1151 return nullptr;
1152
1153 break;
1154 }
1155
1156 default:
1157 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1158 return nullptr;
1159 }
1160
1161 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1162
1163 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1164 solid->SetRoutable( false );
1165
1166 solid->SetLayers( layers );
1167 solid->SetNet( aPad->GetNet() );
1168 solid->SetParent( aPad );
1169 solid->SetPadToDie( aPad->GetPadToDieLength() );
1170 solid->SetOrientation( aPad->GetOrientation() );
1171
1172 if( aPad->IsFreePad() )
1173 solid->SetIsFreePad();
1174
1175 VECTOR2I wx_c = aPad->ShapePos();
1176 VECTOR2I offset = aPad->GetOffset();
1177
1178 VECTOR2I c( wx_c.x, wx_c.y );
1179
1180 RotatePoint( offset, aPad->GetOrientation() );
1181
1182 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1183 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1184
1185 if( aPad->GetDrillSize().x > 0 )
1186 solid->SetHole( new PNS::HOLE( aPad->GetEffectiveHoleShape()->Clone() ) );
1187
1188 std::shared_ptr<SHAPE_POLY_SET> shape = aPad->GetEffectivePolygon();
1189
1190 if( shape->OutlineCount() )
1191 solid->SetShape( new SHAPE_SIMPLE( shape->Outline( 0 ) ) );
1192
1193 return solid;
1194}
1195
1196
1197std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1198{
1199 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1200 aTrack->GetNet() );
1201
1202 segment->SetWidth( aTrack->GetWidth() );
1203 segment->SetLayers( LAYER_RANGE( aTrack->GetLayer() ) );
1204 segment->SetParent( aTrack );
1205
1206 if( aTrack->IsLocked() )
1207 segment->Mark( PNS::MK_LOCKED );
1208
1209 return segment;
1210}
1211
1212
1213std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1214{
1215 auto arc = std::make_unique<PNS::ARC>( SHAPE_ARC( aArc->GetStart(), aArc->GetMid(),
1216 aArc->GetEnd(), aArc->GetWidth() ),
1217 aArc->GetNet() );
1218
1219 arc->SetLayers( LAYER_RANGE( aArc->GetLayer() ) );
1220 arc->SetParent( aArc );
1221
1222 if( aArc->IsLocked() )
1223 arc->Mark( PNS::MK_LOCKED );
1224
1225 return arc;
1226}
1227
1228
1229std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1230{
1231 PCB_LAYER_ID top, bottom;
1232 aVia->LayerPair( &top, &bottom );
1233
1234 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1235 LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ),
1236 aVia->GetWidth(),
1237 aVia->GetDrillValue(),
1238 aVia->GetNet(),
1239 aVia->GetViaType() );
1240
1241 via->SetParent( aVia );
1242
1243 if( aVia->IsLocked() )
1244 via->Mark( PNS::MK_LOCKED );
1245
1246 via->SetIsFree( aVia->GetIsFree() );
1247 via->SetHole( PNS::HOLE::MakeCircularHole( aVia->GetPosition(), aVia->GetDrillValue() / 2 ) );
1248
1249 return via;
1250}
1251
1252
1253bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1254{
1255 SHAPE_POLY_SET* poly;
1256
1257 // TODO handle aZone->GetDoNotAllowVias()
1258 // TODO handle rules which disallow tracks & vias
1259 if( !aZone->GetIsRuleArea() || !aZone->GetDoNotAllowTracks() )
1260 return false;
1261
1262 LSET layers = aZone->GetLayerSet();
1263
1264 poly = aZone->Outline();
1265 poly->CacheTriangulation( false );
1266
1267 if( !poly->IsTriangulationUpToDate() )
1268 {
1269 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1270 KIDIALOG dlg( nullptr, wxString::Format( _( "%s is malformed." ),
1271 aZone->GetItemDescription( &unitsProvider ) ),
1273 dlg.ShowDetailedText( wxString::Format( _( "This zone cannot be handled by the router.\n"
1274 "Please verify it is not a self-intersecting "
1275 "polygon." ) ) );
1276 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1277 dlg.ShowModal();
1278
1279 return false;
1280 }
1281
1282 for( int layer = F_Cu; layer <= B_Cu; layer++ )
1283 {
1284 if( !layers[ layer ] )
1285 continue;
1286
1287 for( int outline = 0; outline < poly->OutlineCount(); outline++ )
1288 {
1289 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( outline );
1290
1291 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1292 {
1293 VECTOR2I a, b, c;
1294 tri->GetTriangle( i, a, b, c );
1295 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1296
1297 triShape->Append( a );
1298 triShape->Append( b );
1299 triShape->Append( c );
1300
1301 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1302
1303 solid->SetLayer( layer );
1304 solid->SetNet( nullptr );
1305 solid->SetParent( aZone );
1306 solid->SetShape( triShape );
1307 solid->SetIsCompoundShapePrimitive();
1308 solid->SetRoutable( false );
1309
1310 aWorld->Add( std::move( solid ) );
1311 }
1312 }
1313 }
1314
1315 return true;
1316}
1317
1318
1320{
1321 if( !IsCopperLayer( aLayer ) )
1322 return false;
1323
1324 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1325 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1326
1327 solid->SetLayer( aLayer );
1328 solid->SetNet( nullptr );
1329 solid->SetParent( aText );
1330 solid->SetShape( shape ); // takes ownership
1331 solid->SetRoutable( false );
1332
1333 SHAPE_POLY_SET cornerBuffer;
1334
1335 aText->TransformShapeToPolygon( cornerBuffer, aText->GetLayer(), 0,
1337
1338 if( !cornerBuffer.OutlineCount() )
1339 return false;
1340
1341 for( const VECTOR2I& pt : cornerBuffer.Outline( 0 ).CPoints() )
1342 shape->Append( pt );
1343
1344 aWorld->Add( std::move( solid ) );
1345
1346 return true;
1347}
1348
1349
1351{
1352 if( aItem->GetLayer() == Edge_Cuts
1353 || aItem->GetLayer() == Margin
1354 || IsCopperLayer( aItem->GetLayer() ) )
1355 {
1356 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1357
1358 for( SHAPE* shape : shapes )
1359 {
1360 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1361
1362 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1363 solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
1364 else
1365 solid->SetLayer( aItem->GetLayer() );
1366
1367 if( aItem->GetLayer() == Edge_Cuts )
1368 {
1369 switch( shape->Type() )
1370 {
1371 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1372 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1373 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1374 default: /* remaining shapes don't have width */ break;
1375 }
1376 }
1377
1378 solid->SetAnchorPoints( aItem->GetConnectionPoints() );
1379 solid->SetNet( aItem->GetNet() );
1380 solid->SetParent( aItem );
1381 solid->SetShape( shape ); // takes ownership
1382
1383 if( shapes.size() > 1 )
1384 solid->SetIsCompoundShapePrimitive();
1385
1386 aWorld->Add( std::move( solid ) );
1387 }
1388
1389 return true;
1390 }
1391
1392 return false;
1393}
1394
1395
1397{
1398 m_board = aBoard;
1399 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1400}
1401
1402
1404{
1405 if( !m_view )
1406 return false;
1407
1408 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1409 {
1410 if( m_view->IsLayerVisible( i ) )
1411 return true;
1412 }
1413
1414 return false;
1415}
1416
1417
1418bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1419{
1421 if( aLayer < 0 )
1422 return true;
1423
1424 if( aItem->Parent() )
1425 {
1426 switch( aItem->Parent()->Type() )
1427 {
1428 case PCB_VIA_T:
1429 {
1430 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1431
1432 return via->FlashLayer( ToLAYER_ID( aLayer ) );
1433 }
1434
1435 case PCB_PAD_T:
1436 {
1437 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1438
1439 return pad->FlashLayer( ToLAYER_ID( aLayer ) );
1440 }
1441
1442 default:
1443 break;
1444 }
1445 }
1446
1447 return aItem->Layers().Overlaps( aLayer );
1448}
1449
1450
1452 const LAYER_RANGE& aLayer ) const
1453{
1454 LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
1455
1456 if( aItem->Parent() )
1457 {
1458 switch( aItem->Parent()->Type() )
1459 {
1460 case PCB_VIA_T:
1461 {
1462 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1463
1464 for( int layer = test.Start(); layer <= test.End(); ++layer )
1465 {
1466 if( via->FlashLayer( ToLAYER_ID( layer ) ) )
1467 return true;
1468 }
1469
1470 return false;
1471 }
1472
1473 case PCB_PAD_T:
1474 {
1475 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1476
1477 for( int layer = test.Start(); layer <= test.End(); ++layer )
1478 {
1479 if( pad->FlashLayer( ToLAYER_ID( layer ) ) )
1480 return true;
1481 }
1482
1483 return false;
1484 }
1485
1486 default:
1487 break;
1488 }
1489 }
1490
1491 return test.Start() <= test.End();
1492}
1493
1494
1496{
1497 // by default, all items are visible (new ones created by the router have parent == NULL
1498 // as they have not been committed yet to the BOARD)
1499 if( !m_view || !aItem->Parent() )
1500 return true;
1501
1502 BOARD_ITEM* item = aItem->Parent();
1503 bool isOnVisibleLayer = true;
1504 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1505
1506 if( settings->GetHighContrast() )
1507 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1508
1509 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1510 {
1511 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
1512 {
1513 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1514 return true;
1515 }
1516 }
1517
1518 // Items hidden in the router are not hidden on the board
1519 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1520 return true;
1521
1522 return false;
1523}
1524
1525
1527{
1528 if( !m_board )
1529 {
1530 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1531 return;
1532 }
1533
1534 int worstClearance = m_board->GetMaxClearanceValue();
1535
1536 m_world = aWorld;
1537
1538 for( BOARD_ITEM* gitem : m_board->Drawings() )
1539 {
1540 if ( gitem->Type() == PCB_SHAPE_T || gitem->Type() == PCB_TEXTBOX_T )
1541 {
1542 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1543 }
1544 else if( gitem->Type() == PCB_TEXT_T )
1545 {
1546 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1547 }
1548 }
1549
1550 SHAPE_POLY_SET buffer;
1551 SHAPE_POLY_SET* boardOutline = nullptr;
1552
1553 if( m_board->GetBoardPolygonOutlines( buffer ) )
1554 boardOutline = &buffer;
1555
1556 for( ZONE* zone : m_board->Zones() )
1557 {
1558 syncZone( aWorld, zone, boardOutline );
1559 }
1560
1561 for( FOOTPRINT* footprint : m_board->Footprints() )
1562 {
1563 for( PAD* pad : footprint->Pads() )
1564 {
1565 if( std::unique_ptr<PNS::SOLID> solid = syncPad( pad ) )
1566 aWorld->Add( std::move( solid ) );
1567
1568 worstClearance = std::max( worstClearance, pad->GetLocalClearance() );
1569
1570 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1571 {
1572 std::unique_ptr<SHAPE> hole;
1573 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1574 aWorld->AddEdgeExclusion( std::move( hole ) );
1575 }
1576 }
1577
1578 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1579 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1580
1581 for( ZONE* zone : footprint->Zones() )
1582 syncZone( aWorld, zone, boardOutline );
1583
1584 for( PCB_FIELD* field : footprint->Fields() )
1585 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1586
1587 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1588 {
1589 if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_TEXTBOX_T )
1590 {
1591 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1592 }
1593 else if( item->Type() == PCB_TEXT_T )
1594 {
1595 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1596 }
1597 }
1598 }
1599
1600 for( PCB_TRACK* t : m_board->Tracks() )
1601 {
1602 KICAD_T type = t->Type();
1603
1604 if( type == PCB_TRACE_T )
1605 {
1606 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1607 aWorld->Add( std::move( segment ) );
1608 }
1609 else if( type == PCB_ARC_T )
1610 {
1611 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1612 aWorld->Add( std::move( arc ) );
1613 }
1614 else if( type == PCB_VIA_T )
1615 {
1616 if( std::unique_ptr<PNS::VIA> via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1617 aWorld->Add( std::move( via ) );
1618 }
1619 }
1620
1621 // NB: if this were ever to become a long-lived object we would need to dirty its
1622 // clearance cache here....
1623 delete m_ruleResolver;
1625
1627 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1628}
1629
1630
1632{
1633 for( BOARD_ITEM* item : m_hiddenItems )
1634 m_view->SetVisible( item, true );
1635
1636 m_hiddenItems.clear();
1637
1638 if( m_previewItems )
1639 {
1642 }
1643
1644 if( m_debugDecorator )
1646}
1647
1648
1650{
1651 m_debugDecorator = aDec;
1652}
1653
1654
1655void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, bool aIsHeadTrace )
1656{
1657 if( aItem->IsVirtual() )
1658 return;
1659
1660 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
1661
1662 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1664 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1665
1666 if( aClearance >= 0 )
1667 {
1668 pitem->SetClearance( aClearance );
1669
1670 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1671
1672 switch( settings->m_Display.m_TrackClearance )
1673 {
1676 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1677 break;
1678
1680 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1681 break;
1682
1683 case SHOW_WHILE_ROUTING:
1684 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1685 break;
1686
1687 default:
1688 pitem->ShowClearance( false );
1689 break;
1690 }
1691 }
1692
1693 if( aIsHeadTrace )
1694 {
1695 pitem->SetIsHeadTrace( true );
1696 pitem->Update( aItem );
1697 }
1698
1699 m_previewItems->Add( pitem );
1701}
1702
1703
1704void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1705{
1706 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, m_view );
1708
1709 COLOR4D color;
1710
1711 if( aImportance >= 1 )
1712 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1713 else if( aImportance == 0 )
1714 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1715
1716 pitem->SetColor( color );
1717
1718 m_previewItems->Add( pitem );
1720}
1721
1722
1724{
1725 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, m_view );
1726
1727 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1728 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1729 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1730 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1731 COLOR4D color = defaultColor;
1732
1733 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1734 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1735 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1736 std::map<wxString, KIGFX::COLOR4D>& ncColors = rs->GetNetclassColorMap();
1737 const std::map<int, wxString>& ncMap = connectivity->GetNetclassMap();
1738 int netCode = -1;
1739
1740 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
1741 netCode = net->GetNetCode();
1742
1743 if( colorByNet && netColors.count( netCode ) )
1744 color = netColors.at( netCode );
1745 else if( colorByNet && ncMap.count( netCode ) && ncColors.count( ncMap.at( netCode ) ) )
1746 color = ncColors.at( ncMap.at( netCode ) );
1747 else
1748 color = defaultColor;
1749
1750 if( color == COLOR4D::UNSPECIFIED )
1751 color = defaultColor;
1752
1753 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
1754
1755 m_previewItems->Add( pitem );
1757}
1758
1759
1761{
1762 BOARD_ITEM* parent = aItem->Parent();
1763
1764 if( parent )
1765 {
1766 if( m_view->IsVisible( parent ) )
1767 m_hiddenItems.insert( parent );
1768
1769 m_view->SetVisible( parent, false );
1770 m_view->Update( parent, KIGFX::APPEARANCE );
1771
1772 for( ZONE* td : m_board->Zones() )
1773 {
1774 if( td->IsTeardropArea()
1775 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
1776 && td->Outline()->Collide( aItem->Shape() ) )
1777 {
1778 m_view->SetVisible( td, false );
1780 }
1781 }
1782 }
1783}
1784
1785
1787{
1788}
1789
1790
1792{
1793 BOARD_ITEM* parent = aItem->Parent();
1794
1795 if( aItem->OfKind( PNS::ITEM::SOLID_T ) )
1796 {
1797 PAD* pad = static_cast<PAD*>( parent );
1798 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1799
1800 m_fpOffsets[ pad ].p_old = pos;
1801 return;
1802 }
1803
1804 if( parent )
1805 {
1806 m_commit->Remove( parent );
1807 }
1808}
1809
1810
1812{
1813}
1814
1815
1817{
1818 BOARD_ITEM* board_item = aItem->Parent();
1819
1820 m_commit->Modify( board_item );
1821
1822 switch( aItem->Kind() )
1823 {
1824 case PNS::ITEM::ARC_T:
1825 {
1826 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1827 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
1828 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape() );
1829 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
1830 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
1831 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
1832 arc_board->SetWidth( arc->Width() );
1833 break;
1834 }
1835
1837 {
1838 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1839 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
1840 const SEG& s = seg->Seg();
1841 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1842 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1843 track->SetWidth( seg->Width() );
1844 break;
1845 }
1846
1847 case PNS::ITEM::VIA_T:
1848 {
1849 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
1850 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1851 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1852 via_board->SetWidth( via->Diameter() );
1853 via_board->SetDrill( via->Drill() );
1854 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
1855 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1856 via_board->SetIsFree( via->IsFree() );
1857 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1858 ToLAYER_ID( via->Layers().End() ) );
1859 break;
1860 }
1861
1862 case PNS::ITEM::SOLID_T:
1863 {
1864 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1865 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1866
1867 m_fpOffsets[ pad ].p_old = pad->GetPosition();
1868 m_fpOffsets[ pad ].p_new = pos;
1869 break;
1870 }
1871
1872 default:
1873 break;
1874 }
1875}
1876
1877
1879{
1880}
1881
1882
1884{
1885 BOARD_CONNECTED_ITEM* newBI = nullptr;
1886
1887 switch( aItem->Kind() )
1888 {
1889 case PNS::ITEM::ARC_T:
1890 {
1891 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1892 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape() ) );
1893 new_arc->SetWidth( arc->Width() );
1894 new_arc->SetLayer( ToLAYER_ID( arc->Layers().Start() ) );
1895 new_arc->SetNet( static_cast<NETINFO_ITEM*>( arc->Net() ) );
1896 newBI = new_arc;
1897 break;
1898 }
1899
1901 {
1902 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1903 PCB_TRACK* track = new PCB_TRACK( m_board );
1904 const SEG& s = seg->Seg();
1905 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1906 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1907 track->SetWidth( seg->Width() );
1908 track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
1909 track->SetNet( static_cast<NETINFO_ITEM*>( seg->Net() ) );
1910 newBI = track;
1911 break;
1912 }
1913
1914 case PNS::ITEM::VIA_T:
1915 {
1916 PCB_VIA* via_board = new PCB_VIA( m_board );
1917 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1918 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1919 via_board->SetWidth( via->Diameter() );
1920 via_board->SetDrill( via->Drill() );
1921 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
1922 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1923 via_board->SetIsFree( via->IsFree() );
1924 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1925 ToLAYER_ID( via->Layers().End() ) );
1926 newBI = via_board;
1927 break;
1928 }
1929
1930 case PNS::ITEM::SOLID_T:
1931 {
1932 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1933 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1934
1935 m_fpOffsets[ pad ].p_new = pos;
1936 return;
1937 }
1938
1939 default:
1940 break;
1941 }
1942
1943 if( newBI )
1944 {
1945 //newBI->SetLocalRatsnestVisible( m_dispOptions->m_ShowGlobalRatsnest );
1946 aItem->SetParent( newBI );
1947 newBI->ClearFlags();
1948
1949 m_commit->Add( newBI );
1950 }
1951}
1952
1953
1955{
1956 std::set<FOOTPRINT*> processedFootprints;
1957
1958 EraseView();
1959
1960 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
1961 {
1962 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
1963 FOOTPRINT* footprint = pad->GetParentFootprint();
1964 VECTOR2I p_orig = footprint->GetPosition();
1965 VECTOR2I p_new = p_orig + offset;
1966
1967 if( processedFootprints.find( footprint ) != processedFootprints.end() )
1968 continue;
1969
1970 processedFootprints.insert( footprint );
1971 m_commit->Modify( footprint );
1972 footprint->SetPosition( p_new );
1973 }
1974
1975 m_fpOffsets.clear();
1976
1977 m_commit->Push( _( "Interactive Router" ), m_commitFlags );
1978 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
1979}
1980
1981
1983{
1984 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
1985}
1986
1987
1989{
1990 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
1991
1992 if( m_previewItems )
1993 {
1995 delete m_previewItems;
1996 }
1997
1998 m_view = aView;
2001
2002 if(m_view)
2004
2005 delete m_debugDecorator;
2006
2007 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR();
2008 m_debugDecorator = dec;
2009
2010 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2011
2012 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2013 dec->SetView( m_view );
2014}
2015
2016
2018{
2019 if( aNet )
2020 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2021 else
2022 return -1;
2023}
2024
2025
2027{
2028 if( aNet )
2029 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2030 else
2031 return wxEmptyString;
2032}
2033
2034
2036{
2037 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2038}
2039
2040
2042{
2044}
2045
2046
2048{
2049 return m_ruleResolver;
2050}
2051
2052
2054{
2055 m_tool = aTool;
2056 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2057}
int color
Definition: DXF_plotter.cpp:58
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
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< DRC_ENGINE > m_DRCEngine
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
BOARD_STACKUP & GetStackupDescriptor()
bool UseNetClassTrack() const
Return true if netclass values should be used to obtain appropriate track width.
bool UseNetClassDiffPair() const
Return true if netclass values should be used to obtain appropriate diff pair dimensions.
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:204
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:269
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:238
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:247
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:209
virtual bool IsLocked() const
Definition: board_item.cpp:73
virtual bool IsOnCopperLayer() const
Definition: board_item.h:142
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:271
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2056
ZONES & Zones()
Definition: board.h:319
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1562
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition: board.cpp:748
FOOTPRINTS & Footprints()
Definition: board.h:313
TRACKS & Tracks()
Definition: board.h:310
DRAWINGS & Drawings()
Definition: board.h:316
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:731
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:433
const Vec & GetOrigin() const
Definition: box2.h:184
const Vec & GetSize() const
Definition: box2.h:180
wxString GetName() const
Definition: drc_rule.h:149
SEVERITY GetSeverity() const
Definition: drc_rule.h:162
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:141
bool IsNull() const
Definition: drc_rule.h:136
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:123
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:125
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:298
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:1944
bool IsNetTie() const
Definition: footprint.h:281
VECTOR2I GetPosition() const override
Definition: footprint.h:206
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:47
@ KD_WARNING
Definition: confirm.h:50
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:56
int ShowModal() override
Definition: confirm.cpp:100
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
double GetMinDepth() const
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:76
NET_COLOR_MODE GetNetColorMode() const
Definition: pcb_painter.h:115
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:120
std::map< wxString, KIGFX::COLOR4D > & GetNetclassColorMap()
Definition: pcb_painter.h:118
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:47
void FreeItems()
Free all the items that were added to the group.
Definition: view_group.cpp:198
virtual void SetLayer(int aLayer)
Set layer used to draw the group.
Definition: view_group.h:98
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:134
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
double GetScale() const
Definition: view.h:269
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:314
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:1608
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:195
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:410
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1586
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1546
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
int Start() const
Definition: pns_layerset.h:82
int End() const
Definition: pns_layerset.h:87
LAYER_RANGE Intersection(const LAYER_RANGE &aOther) const
Shortcut for comparisons/overlap tests.
Definition: pns_layerset.h:108
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:552
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
T Min() const
Definition: minoptmax.h:33
void SetMin(T v)
Definition: minoptmax.h:41
T Opt() const
Definition: minoptmax.h:35
Handle the data for a net.
Definition: netinfo.h:67
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:395
Definition: pad.h:58
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:369
const VECTOR2I & GetDrillSize() const
Definition: pad.h:253
PAD_ATTRIB GetAttribute() const
Definition: pad.h:372
const VECTOR2I & GetOffset() const
Definition: pad.h:260
VECTOR2I ShapePos() const
Definition: pad.cpp:756
bool IsFreePad() const
Definition: pad.cpp:187
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:341
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon() const
Definition: pad.cpp:359
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:405
int GetPadToDieLength() const
Definition: pad.h:385
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:314
const VECTOR2I & GetMid() const
Definition: pcb_track.h:315
std::vector< VECTOR2I > GetConnectionPoints() const
Definition: pcb_shape.cpp:106
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:67
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:518
void SetWidth(int aWidth)
Definition: pcb_track.h:106
int GetWidth() const
Definition: pcb_track.h:107
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:109
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:112
const VECTOR2I & GetStart() const
Definition: pcb_track.h:113
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:110
bool GetIsFree() const
Check if the via is a free via (as opposed to one created on a track by the router).
Definition: pcb_track.h:559
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:597
VECTOR2I GetPosition() const override
Definition: pcb_track.h:454
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:531
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:560
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:455
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:548
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:403
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:591
int GetDrillValue() const
Calculate the drill value for vias (m-Drill if > 0, or default drill value for the board.
Definition: pcb_track.cpp:220
VIATYPE GetViaType() const
Definition: pcb_track.h:402
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:569
int Width() const override
Definition: pns_arc.h:88
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_arc.h:78
void SetDebugEnabled(bool aEnabled)
static HOLE * MakeCircularHole(const VECTOR2I &pos, int radius)
Definition: pns_hole.cpp:131
ITEM_SET & ExcludeItem(const ITEM *aItem)
ITEM_SET & FilterKinds(int aKindMask, bool aInvert=false)
Definition: pns_itemset.cpp:70
std::vector< ITEM * > & Items()
Definition: pns_itemset.h:87
Base class for PNS router board items.
Definition: pns_item.h:97
BOARD_ITEM * Parent() const
Definition: pns_item.h:185
virtual NET_HANDLE Net() const
Definition: pns_item.h:193
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:166
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:192
virtual int Layer() const
Definition: pns_item.h:199
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:224
@ SEGMENT_T
Definition: pns_item.h:105
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:184
const LAYER_RANGE & Layers() const
Definition: pns_item.h:195
bool OfKind(int aKindMask) const
Definition: pns_item.h:174
bool IsVirtual() const
Definition: pns_item.h:263
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:236
virtual BOARD_ITEM * BoardItem() const
Definition: pns_item.h:190
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
Definition: pns_joint.h:43
const ITEM_SET & CLinks() const
Definition: pns_joint.h:244
Keep the router "world" - i.e.
Definition: pns_node.h:198
void SetMaxClearance(int aClearance)
Assign a clearance resolution function object.
Definition: pns_node.h:225
void SetRuleResolver(RULE_RESOLVER *aFunc)
Definition: pns_node.h:231
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
Definition: pns_node.cpp:684
bool Add(std::unique_ptr< SEGMENT > &&aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:640
const ITEM_OWNER * Owner() const
Return the owner of this item, or NULL if there's none.
Definition: pns_item.h:71
virtual wxString GetNetName(PNS::NET_HANDLE aNet) const =0
virtual int GetNetCode(NET_HANDLE aNet) const =0
const SEG & Seg() const
Definition: pns_segment.h:84
int Width() const override
Definition: pns_segment.h:79
void SetTrackWidth(int aWidth)
void SetBoardMinTrackWidth(int aWidth)
void SetDiffPairViaGapSameAsTraceGap(bool aEnable)
void SetDiffPairWidth(int aWidth)
void SetDiffPairWidthSource(const wxString &aSource)
void SetDiffPairGapSource(const wxString &aSource)
void SetDiffPairGap(int aGap)
void SetHoleToHole(int aHoleToHole)
void SetViaDrill(int aDrill)
void SetDiffPairViaGap(int aGap)
void SetDiffPairHoleToHole(int aHoleToHole)
void SetMinClearance(int aClearance)
void SetClearance(int aClearance)
void SetViaDiameter(int aDiameter)
void SetClearanceSource(const wxString &aSource)
void SetWidthSource(const wxString &aSource)
void SetTrackWidthIsExplicit(bool aIsExplicit)
bool syncGraphicalItem(PNS::NODE *aWorld, PCB_SHAPE *aItem)
bool inheritTrackWidth(PNS::ITEM *aItem, int *aInheritedWidth)
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, PNS::NET_HANDLE aNet) override
void AddItem(PNS::ITEM *aItem) override
virtual EDA_UNITS GetUnits() const
PNS::DEBUG_DECORATOR * m_debugDecorator
void SetDebugDecorator(PNS::DEBUG_DECORATOR *aDec)
bool syncZone(PNS::NODE *aWorld, ZONE *aZone, SHAPE_POLY_SET *aBoardOutline)
void SetBoard(BOARD *aBoard)
std::unique_ptr< PNS::ARC > syncArc(PCB_ARC *aArc)
void RemoveItem(PNS::ITEM *aItem) override
PNS::RULE_RESOLVER * GetRuleResolver() override
bool syncTextItem(PNS::NODE *aWorld, PCB_TEXT *aText, PCB_LAYER_ID aLayer)
bool IsFlashedOnLayer(const PNS::ITEM *aItem, int aLayer) const override
std::unique_ptr< PNS::SOLID > syncPad(PAD *aPad)
void SyncWorld(PNS::NODE *aWorld) override
int StackupHeight(int aFirstLayer, int aSecondLayer) const override
PNS::DEBUG_DECORATOR * GetDebugDecorator() override
std::unique_ptr< PNS::SEGMENT > syncTrack(PCB_TRACK *aTrack)
PNS_PCBNEW_RULE_RESOLVER * m_ruleResolver
PNS::NET_HANDLE GetOrphanedNetHandle() override
std::unique_ptr< PNS::VIA > syncVia(PCB_VIA *aVia)
void UpdateItem(PNS::ITEM *aItem) override
void SetView(KIGFX::VIEW *aView)
void RemoveItem(PNS::ITEM *aItem) override
void AddItem(PNS::ITEM *aItem) override
void UpdateItem(PNS::ITEM *aItem) override
std::map< PAD *, OFFSET > m_fpOffsets
int GetNetCode(PNS::NET_HANDLE aNet) const override
void SetHostTool(PCB_TOOL_BASE *aTool)
std::unique_ptr< BOARD_COMMIT > m_commit
void EraseView() override
void HideItem(PNS::ITEM *aItem) override
void UpdateNet(PNS::NET_HANDLE aNet) override
KIGFX::VIEW * m_view
void DisplayPathLine(const SHAPE_LINE_CHAIN &aLine, int aImportance) override
bool IsItemVisible(const PNS::ITEM *aItem) const override
void DisplayItem(const PNS::ITEM *aItem, int aClearance, bool aEdit=false, bool aIsHeadTrace=false) override
std::unordered_set< BOARD_ITEM * > m_hiddenItems
EDA_UNITS GetUnits() const override
bool IsAnyLayerVisible(const LAYER_RANGE &aLayer) const override
PCB_TOOL_BASE * m_tool
void 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
void AddPoint(const VECTOR2I &aP, const KIGFX::COLOR4D &aColor, int aSize, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
PNS_PCBNEW_DEBUG_DECORATOR(KIGFX::VIEW *aView=nullptr)
void AddShape(const BOX2I &aBox, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
void AddItem(const PNS::ITEM *aItem, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
void SetView(KIGFX::VIEW *aView)
void AddShape(const SHAPE *aShape, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
virtual int NetCode(PNS::NET_HANDLE aNet) override
PNS_PCBNEW_RULE_RESOLVER(BOARD *aBoard, PNS::ROUTER_IFACE *aRouterIface)
virtual bool IsKeepout(const PNS::ITEM *aA, const PNS::ITEM *aB) override
virtual bool QueryConstraint(PNS::CONSTRAINT_TYPE aType, const PNS::ITEM *aItemA, const PNS::ITEM *aItemB, int aLayer, PNS::CONSTRAINT *aConstraint) override
int ClearanceEpsilon() const override
virtual int Clearance(const PNS::ITEM *aA, const PNS::ITEM *aB, bool aUseClearanceEpsilon=true) override
int matchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Checks for netnamed differential pairs.
void ClearCacheForItems(std::vector< const PNS::ITEM * > &aItems) override
std::unordered_map< CLEARANCE_CACHE_KEY, int > m_clearanceCache
virtual int DpNetPolarity(PNS::NET_HANDLE aNet) override
virtual bool IsNetTieExclusion(const PNS::ITEM *aItem, const VECTOR2I &aCollisionPos, const PNS::ITEM *aCollidingItem) override
virtual bool IsInNetTie(const PNS::ITEM *aA) override
virtual PNS::NET_HANDLE DpCoupledNet(PNS::NET_HANDLE aNet) override
virtual bool DpNetPair(const PNS::ITEM *aItem, PNS::NET_HANDLE &aNetP, PNS::NET_HANDLE &aNetN) override
PNS::ROUTER_IFACE * m_routerIface
virtual wxString NetName(PNS::NET_HANDLE aNet) override
void SetWidth(double aWidth)
void SetClearance(int aClearance)
void SetColor(const KIGFX::COLOR4D &aColor)
void SetIsHeadTrace(bool aIsHead)
void Update(const PNS::ITEM *aItem)
static const int PathOverlayDepth
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:114
const VECTOR2I & GetP1() const
Definition: shape_arc.h:113
const VECTOR2I & GetP0() const
Definition: shape_arc.h:112
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
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
int OutlineCount() const
Return the number of outlines in the set.
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
void Append(int aX, int aY)
Append a new point at the end of the polygon.
Definition: shape_simple.h:135
An abstract shape on 2D plane.
Definition: shape.h:126
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:145
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:387
VECTOR2_TRAITS< int >::extended_type extended_type
Definition: vector2d.h:72
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: zone.cpp:825
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:710
bool GetDoNotAllowVias() const
Definition: zone.h:712
bool GetDoNotAllowPads() const
Definition: zone.h:714
bool GetDoNotAllowTracks() const
Definition: zone.h:713
SHAPE_POLY_SET * Outline()
Definition: zone.h:325
bool GetDoNotAllowFootprints() const
Definition: zone.h:715
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:129
This file is part of the common library.
DRC_CONSTRAINT_T
Definition: drc_rule.h:45
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:63
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:66
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:56
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:50
@ LENGTH_CONSTRAINT
Definition: drc_rule.h:64
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:47
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:48
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:51
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:49
#define _(s)
#define ROUTER_TRANSIENT
transient items that should NOT be cached
EDA_UNITS
Definition: eda_units.h:44
@ ERROR_OUTSIDE
#define MAX_CU_LAYERS
Definition: layer_ids.h:141
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:847
@ 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
@ PCBNEW_LAYER_ID_START
Definition: layer_ids.h:64
@ Edge_Cuts
Definition: layer_ids.h:114
@ B_Cu
Definition: layer_ids.h:96
@ Margin
Definition: layer_ids.h:115
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:138
@ F_Cu
Definition: layer_ids.h:65
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
This file contains miscellaneous commonly used macros and functions.
@ APPEARANCE
Visibility flag has changed.
Definition: view_item.h:47
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.
@ NPTH
like PAD_PTH, but not plated
@ 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 isNonPlatedSlot(const PNS::ITEM *aItem)
static bool isCopper(const PNS::ITEM *aItem)
static bool isDrilledHole(const PNS::ITEM *aItem)
VECTOR2I::extended_type ecoord
@ RPT_SEVERITY_IGNORE
@ 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:70
wxString m_RuleName
Definition: pns_node.h:74
MINOPTMAX< int > m_Value
Definition: pns_node.h:72
CONSTRAINT_TYPE m_Type
Definition: pns_node.h:71
std::size_t operator()(const CLEARANCE_CACHE_KEY &k) const
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
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:94
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:92
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:104
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
@ 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:95
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:93
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588