KiCad PCB EDA Suite
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 <fp_text.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
40#include <pcb_painter.h>
41
42#include <geometry/shape.h>
44#include <geometry/shape_arc.h>
46
47#include <drc/drc_rule.h>
48#include <drc/drc_engine.h>
49
51
52#include <wx/log.h>
53
54#include <memory>
55
56#include <advanced_config.h>
57#include <pcbnew_settings.h>
58#include <macros.h>
59
60#include "pns_kicad_iface.h"
61
62#include "pns_arc.h"
64#include "pns_sizes_settings.h"
65#include "pns_item.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 virtual int HoleClearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
110 bool aUseClearanceEpsilon = true ) override;
111 virtual int HoleToHoleClearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
112 bool aUseClearanceEpsilon = true ) override;
113
114 virtual int DpCoupledNet( int aNet ) override;
115 virtual int DpNetPolarity( int aNet ) override;
116 virtual bool DpNetPair( const PNS::ITEM* aItem, int& aNetP, int& aNetN ) override;
117 virtual bool IsDiffPair( const PNS::ITEM* aA, const PNS::ITEM* aB ) override;
118
119 virtual bool IsInNetTie( const PNS::ITEM* aA ) override;
120 virtual bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
121 const PNS::ITEM* aCollidingItem ) override;
122
123 virtual bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
124 const PNS::ITEM* aItemB, int aLayer,
125 PNS::CONSTRAINT* aConstraint ) override;
126 virtual wxString NetName( int aNet ) override;
127
128 int ClearanceEpsilon() const { return m_clearanceEpsilon; }
129
130 void ClearCacheForItem( const PNS::ITEM* aItem ) override;
131 void ClearCaches() override;
132
133private:
134 int holeRadius( const PNS::ITEM* aItem ) const;
135
145 int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet );
146
147private:
154
155 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
156 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_holeClearanceCache;
157 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_holeToHoleClearanceCache;
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 if( aBoard )
170 m_clearanceEpsilon = aBoard->GetDesignSettings().GetDRCEpsilon();
171 else
172 m_clearanceEpsilon = 0;
173}
174
175
177{
178}
179
180
182{
183 if( aItem->Kind() == PNS::ITEM::SOLID_T )
184 {
185 const PAD* pad = dynamic_cast<const PAD*>( aItem->Parent() );
186
187 if( pad && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
188 return pad->GetDrillSize().x / 2;
189 }
190 else if( aItem->Kind() == PNS::ITEM::VIA_T )
191 {
192 const PCB_VIA* via = dynamic_cast<const PCB_VIA*>( aItem->Parent() );
193
194 if( via )
195 return via->GetDrillValue() / 2;
196 }
197
198 return 0;
199}
200
201
203{
204 int net_p, net_n;
205
206 if( !DpNetPair( aA, net_p, net_n ) )
207 return false;
208
209 if( aA->Net() == net_p && aB->Net() == net_n )
210 return true;
211
212 if( aB->Net() == net_p && aA->Net() == net_n )
213 return true;
214
215 return false;
216}
217
218
220{
221 BOARD_ITEM* item = aA->Parent();
222 BOARD_ITEM* parentFootprint = item ? item->GetParentFootprint() : nullptr;
223
224 if( parentFootprint )
225 return static_cast<FOOTPRINT*>( parentFootprint )->IsNetTie();
226
227 return false;
228}
229
230
232 const VECTOR2I& aCollisionPos,
233 const PNS::ITEM* aCollidingItem )
234{
235 wxCHECK( aItem && aCollidingItem, false );
236
237 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
238 BOARD_ITEM* collidingItem = aCollidingItem->Parent();
239
240 FOOTPRINT* collidingFp = static_cast<FOOTPRINT*>( collidingItem->GetParentFootprint() );
241 FOOTPRINT* itemFp = aItem->Parent()
242 ? static_cast<FOOTPRINT*>( aItem->Parent()->GetParentFootprint() )
243 : nullptr;
244
245 if( collidingFp && itemFp && ( collidingFp == itemFp ) && itemFp->IsNetTie() )
246 {
247 // Two items colliding from the same net tie footprint are not checked
248 return true;
249 }
250
251 if( drcEngine && collidingItem )
252 {
253 return drcEngine->IsNetTieExclusion( aItem->Net(), ToLAYER_ID( aItem->Layer() ),
254 aCollisionPos, collidingItem );
255 }
256
257 return false;
258}
259
260
261bool isCopper( const PNS::ITEM* aItem )
262{
263 BOARD_ITEM* parent = aItem->Parent();
264
265 if( parent && parent->Type() == PCB_PAD_T )
266 {
267 PAD* pad = static_cast<PAD*>( parent );
268
269 if( !pad->IsOnCopperLayer() )
270 return false;
271
272 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
273 return true;
274
275 // round NPTH with a hole size >= pad size are not on a copper layer
276 // All other NPTH are seen on copper layers
277 // This is a basic criteria, but probably enough for a NPTH
278 if( pad->GetShape() == PAD_SHAPE::CIRCLE )
279 {
280 if( pad->GetSize().x <= pad->GetDrillSize().x )
281 return false;
282 }
283
284 return true;
285 }
286
287 return true;
288}
289
290
291bool isEdge( const PNS::ITEM* aItem )
292{
293 const BOARD_ITEM *parent = aItem->Parent();
294
295 return parent && ( parent->IsOnLayer( Edge_Cuts ) || parent->IsOnLayer( Margin ) );
296}
297
298
300 const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
301 int aLayer, PNS::CONSTRAINT* aConstraint )
302{
303 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
304
305 if( !drcEngine )
306 return false;
307
308 DRC_CONSTRAINT_T hostType;
309
310 switch ( aType )
311 {
321 default: return false; // should not happen
322 }
323
324 BOARD_ITEM* parentA = aItemA ? aItemA->Parent() : nullptr;
325 BOARD_ITEM* parentB = aItemB ? aItemB->Parent() : nullptr;
326 DRC_CONSTRAINT hostConstraint;
327
328 // A track being routed may not have a BOARD_ITEM associated yet.
329 if( aItemA && !parentA )
330 {
331 switch( aItemA->Kind() )
332 {
333 case PNS::ITEM::ARC_T: parentA = &m_dummyArcs[0]; break;
334 case PNS::ITEM::VIA_T: parentA = &m_dummyVias[0]; break;
335 case PNS::ITEM::SEGMENT_T: parentA = &m_dummyTracks[0]; break;
336 case PNS::ITEM::LINE_T: parentA = &m_dummyTracks[0]; break;
337 default: break;
338 }
339
340 if( parentA )
341 {
342 parentA->SetLayer( ToLAYER_ID( aLayer ) );
343 static_cast<BOARD_CONNECTED_ITEM*>( parentA )->SetNetCode( aItemA->Net(), true );
344 }
345 }
346
347 if( aItemB && !parentB )
348 {
349 switch( aItemB->Kind() )
350 {
351 case PNS::ITEM::ARC_T: parentB = &m_dummyArcs[1]; break;
352 case PNS::ITEM::VIA_T: parentB = &m_dummyVias[1]; break;
353 case PNS::ITEM::SEGMENT_T: parentB = &m_dummyTracks[1]; break;
354 case PNS::ITEM::LINE_T: parentB = &m_dummyTracks[1]; break;
355 default: break;
356 }
357
358 if( parentB )
359 {
360 parentB->SetLayer( ToLAYER_ID( aLayer ) );
361 static_cast<BOARD_CONNECTED_ITEM*>( parentB )->SetNetCode( aItemB->Net(), true );
362 }
363 }
364
365 if( parentA )
366 hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, ToLAYER_ID( aLayer ) );
367
368 if( hostConstraint.IsNull() )
369 return false;
370
371 if( hostConstraint.GetSeverity() == RPT_SEVERITY_IGNORE )
372 {
373 aConstraint->m_Value.SetMin( -1 );
374 aConstraint->m_RuleName = hostConstraint.GetName();
375 aConstraint->m_Type = aType;
376 return true;
377 }
378
379 switch ( aType )
380 {
389 aConstraint->m_Value = hostConstraint.GetValue();
390 aConstraint->m_RuleName = hostConstraint.GetName();
391 aConstraint->m_Type = aType;
392 return true;
393
394 default:
395 return false;
396 }
397}
398
399
401{
402 CLEARANCE_CACHE_KEY key = { aItem, nullptr, false };
403 m_clearanceCache.erase( key );
404
405 key.Flag = true;
406 m_clearanceCache.erase( key );
407}
408
409
411{
412 m_clearanceCache.clear();
413 m_holeClearanceCache.clear();
415}
416
417
419 bool aUseClearanceEpsilon )
420{
421 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
422 auto it = m_clearanceCache.find( key );
423
424 if( it != m_clearanceCache.end() )
425 return it->second;
426
427 PNS::CONSTRAINT constraint;
428 int rv = 0;
429 LAYER_RANGE layers;
430
431 if( !aB )
432 layers = aA->Layers();
433 else if( isEdge( aA ) )
434 layers = aB->Layers();
435 else if( isEdge( aB ) )
436 layers = aA->Layers();
437 else
438 layers = aA->Layers().Intersection( aB->Layers() );
439
440 // Normalize layer range (no -1 magic numbers)
442
443 for( int layer = layers.Start(); layer <= layers.End(); ++layer )
444 {
445 if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
446 {
447 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
448 {
449 if( constraint.m_Value.Min() > rv )
450 rv = constraint.m_Value.Min();
451 }
452 }
453
454 if( isEdge( aA ) || ( aB && isEdge( aB ) ) )
455 {
456 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
457 {
458 if( constraint.m_Value.Min() > rv )
459 rv = constraint.m_Value.Min();
460 }
461 }
462 }
463
464 if( aUseClearanceEpsilon && rv > 0 )
465 rv = std::max( 0, rv - m_clearanceEpsilon );
466
467 m_clearanceCache[ key ] = rv;
468 return rv;
469}
470
471
473 bool aUseClearanceEpsilon )
474{
475 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
476 auto it = m_holeClearanceCache.find( key );
477
478 if( it != m_holeClearanceCache.end() )
479 return it->second;
480
481 PNS::CONSTRAINT constraint;
482 int rv = 0;
483 int layer;
484
485 if( !aA->Layers().IsMultilayer() || !aB || aB->Layers().IsMultilayer() )
486 layer = aA->Layer();
487 else
488 layer = aB->Layer();
489
490 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
491 rv = constraint.m_Value.Min();
492
493#define HAS_PLATED_HOLE( a ) ( a )->IsRoutable()
494
495 if( IsCopperLayer( layer )
496 && ( HAS_PLATED_HOLE( aA ) || HAS_PLATED_HOLE( aB ) )
497 && QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint )
498 && constraint.m_Value.Min() > rv )
499 {
500 rv = constraint.m_Value.Min();
501 }
502
503 if( aUseClearanceEpsilon && rv > 0 )
504 rv = std::max( 0, rv - m_clearanceEpsilon );
505
506 m_holeClearanceCache[ key ] = rv;
507 return rv;
508}
509
510
512 bool aUseClearanceEpsilon )
513{
514 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
515 auto it = m_holeToHoleClearanceCache.find( key );
516
517 if( it != m_holeToHoleClearanceCache.end() )
518 return it->second;
519
520 PNS::CONSTRAINT constraint;
521 int rv = 0;
522 int layer;
523
524 if( !aA->Layers().IsMultilayer() || !aB || aB->Layers().IsMultilayer() )
525 layer = aA->Layer();
526 else
527 layer = aB->Layer();
528
529 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer, &constraint ) )
530 rv = constraint.m_Value.Min();
531
532 if( aUseClearanceEpsilon && rv > 0 )
533 rv = std::max( 0, rv - m_clearanceEpsilon );
534
535 m_holeToHoleClearanceCache[ key ] = rv;
536 return rv;
537}
538
539
540bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth )
541{
542 VECTOR2I p;
543
544 assert( aItem->Owner() != nullptr );
545
546 auto tryGetTrackWidth =
547 []( PNS::ITEM* aPnsItem ) -> int
548 {
549 switch( aPnsItem->Kind() )
550 {
551 case PNS::ITEM::SEGMENT_T: return static_cast<PNS::SEGMENT*>( aPnsItem )->Width();
552 case PNS::ITEM::ARC_T: return static_cast<PNS::ARC*>( aPnsItem )->Width();
553 default: return -1;
554 }
555 };
556
557 int itemTrackWidth = tryGetTrackWidth( aItem );
558
559 if( itemTrackWidth > 0 )
560 {
561 *aInheritedWidth = itemTrackWidth;
562 return true;
563 }
564
565 switch( aItem->Kind() )
566 {
567 case PNS::ITEM::VIA_T:
568 p = static_cast<PNS::VIA*>( aItem )->Pos();
569 break;
570
572 p = static_cast<PNS::SOLID*>( aItem )->Pos();
573 break;
574
575 default:
576 return false;
577 }
578
579 PNS::JOINT* jt = static_cast<PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
580
581 assert( jt != nullptr );
582
583 int mval = INT_MAX;
584
585 PNS::ITEM_SET linkedSegs = jt->Links();
587
588 for( PNS::ITEM* item : linkedSegs.Items() )
589 {
590 int w = tryGetTrackWidth( item );
591 assert( w > 0 );
592 mval = std::min( w, mval );
593 }
594
595 if( mval == INT_MAX )
596 return false;
597
598 *aInheritedWidth = mval;
599 return true;
600}
601
602
604 int aNet )
605{
607 PNS::CONSTRAINT constraint;
608
609 if( aStartItem && m_startLayer < 0 )
610 m_startLayer = aStartItem->Layer();
611
612 aSizes.SetClearance( bds.m_MinClearance );
613 aSizes.SetMinClearance( bds.m_MinClearance );
614 aSizes.SetClearanceSource( _( "board minimum clearance" ) );
615
617 m_startLayer, &constraint ) )
618 {
619 if( constraint.m_Value.Min() > bds.m_MinClearance )
620 {
621 aSizes.SetClearance( constraint.m_Value.Min() );
622 aSizes.SetClearanceSource( constraint.m_RuleName );
623 }
624 }
625
626 int trackWidth = bds.m_TrackMinWidth;
627 bool found = false;
628 aSizes.SetWidthSource( _( "board minimum track width" ) );
629
630 if( bds.m_UseConnectedTrackWidth && !bds.m_TempOverrideTrackWidth && aStartItem != nullptr )
631 {
632 found = inheritTrackWidth( aStartItem, &trackWidth );
633
634 if( found )
635 aSizes.SetWidthSource( _( "existing track" ) );
636 }
637
638 if( !found && bds.UseNetClassTrack() && aStartItem )
639 {
641 m_startLayer, &constraint ) )
642 {
643 trackWidth = std::max( trackWidth, constraint.m_Value.Opt() );
644 found = true;
645
646 if( trackWidth == constraint.m_Value.Opt() )
647 aSizes.SetWidthSource( constraint.m_RuleName );
648 }
649 }
650
651 if( !found )
652 {
653 trackWidth = std::max( trackWidth, bds.GetCurrentTrackWidth() );
654
655 if( bds.UseNetClassTrack() )
656 aSizes.SetWidthSource( _( "netclass 'Default'" ) );
657 else if( trackWidth == bds.GetCurrentTrackWidth() )
658 aSizes.SetWidthSource( _( "user choice" ) );
659 }
660
661 aSizes.SetTrackWidth( trackWidth );
663
664 int viaDiameter = bds.m_ViasMinSize;
665 int viaDrill = bds.m_MinThroughDrill;
666
667 if( bds.UseNetClassVia() && aStartItem ) // netclass value
668 {
670 nullptr, m_startLayer, &constraint ) )
671 {
672 viaDiameter = std::max( viaDiameter, constraint.m_Value.Opt() );
673 }
674
676 nullptr, m_startLayer, &constraint ) )
677 {
678 viaDrill = std::max( viaDrill, constraint.m_Value.Opt() );
679 }
680 }
681 else
682 {
683 viaDiameter = bds.GetCurrentViaSize();
684 viaDrill = bds.GetCurrentViaDrill();
685 }
686
687 aSizes.SetViaDiameter( viaDiameter );
688 aSizes.SetViaDrill( viaDrill );
689
690 int diffPairWidth = bds.m_TrackMinWidth;
691 int diffPairGap = bds.m_MinClearance;
692 int diffPairViaGap = bds.m_MinClearance;
693
694 aSizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
695 aSizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
696
697 found = false;
698
699 // First try to pick up diff pair width from starting track, if enabled
700 if( bds.m_UseConnectedTrackWidth && aStartItem )
701 found = inheritTrackWidth( aStartItem, &diffPairWidth );
702
703 // Next, pick up gap from netclass, and width also if we didn't get a starting width above
704 if( bds.UseNetClassDiffPair() && aStartItem )
705 {
707 nullptr, m_startLayer, &constraint ) )
708 {
709 diffPairWidth = std::max( diffPairWidth, constraint.m_Value.Opt() );
710
711 if( diffPairWidth == constraint.m_Value.Opt() )
712 aSizes.SetDiffPairWidthSource( constraint.m_RuleName );
713 }
714
716 nullptr, m_startLayer, &constraint ) )
717 {
718 diffPairGap = std::max( diffPairGap, constraint.m_Value.Opt() );
719 diffPairViaGap = std::max( diffPairViaGap, constraint.m_Value.Opt() );
720
721 if( diffPairGap == constraint.m_Value.Opt() )
722 aSizes.SetDiffPairGapSource( constraint.m_RuleName );
723 }
724 }
725 else
726 {
727 diffPairWidth = bds.GetCurrentDiffPairWidth();
728 diffPairGap = bds.GetCurrentDiffPairGap();
729 diffPairViaGap = bds.GetCurrentDiffPairViaGap();
730
731 aSizes.SetDiffPairWidthSource( _( "user choice" ) );
732 aSizes.SetDiffPairGapSource( _( "user choice" ) );
733 }
734
735 aSizes.SetDiffPairWidth( diffPairWidth );
736 aSizes.SetDiffPairGap( diffPairGap );
737 aSizes.SetDiffPairViaGap( diffPairViaGap );
738 aSizes.SetDiffPairViaGapSameAsTraceGap( false );
739
740 int holeToHoleMin = bds.m_HoleToHoleMin;
741 PNS::VIA dummyVia, coupledVia;
742
743 if( aStartItem )
744 {
745 dummyVia.SetNet( aStartItem->Net() );
746 coupledVia.SetNet( m_ruleResolver->DpCoupledNet( aStartItem->Net() ) );
747 }
748
750 &dummyVia, UNDEFINED_LAYER, &constraint ) )
751 {
752 holeToHoleMin = constraint.m_Value.Min();
753 }
754
755 aSizes.SetHoleToHole( holeToHoleMin );
756
758 &coupledVia, UNDEFINED_LAYER, &constraint ) )
759 {
760 holeToHoleMin = constraint.m_Value.Min();
761 }
762
763 aSizes.SetDiffPairHoleToHole( holeToHoleMin );
764
765 return true;
766}
767
768
769int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const
770{
772 return 0;
773
775
776 return stackup.GetLayerDistance( ToLAYER_ID( aFirstLayer ), ToLAYER_ID( aSecondLayer ) );
777}
778
779
780int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
781{
782 int rv = 0;
783 int count = 0;
784
785 for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
786 {
787 int ch = *it;
788
789 if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
790 {
791 continue;
792 }
793 else if( ch == '+' )
794 {
795 aComplementNet = wxT( "-" );
796 rv = 1;
797 }
798 else if( ch == '-' )
799 {
800 aComplementNet = wxT( "+" );
801 rv = -1;
802 }
803 else if( ch == 'N' )
804 {
805 aComplementNet = wxT( "P" );
806 rv = -1;
807 }
808 else if ( ch == 'P' )
809 {
810 aComplementNet = wxT( "N" );
811 rv = 1;
812 }
813 else
814 {
815 break;
816 }
817 }
818
819 if( rv != 0 && count >= 1 )
820 {
821 aComplementNet = aNetName.Left( aNetName.length() - count ) + aComplementNet
822 + aNetName.Right( count - 1 );
823 }
824
825 return rv;
826}
827
828
830{
831 wxString refName = m_board->FindNet( aNet )->GetNetname();
832 wxString coupledNetName;
833
834 if( matchDpSuffix( refName, coupledNetName ) )
835 {
836 NETINFO_ITEM* net = m_board->FindNet( coupledNetName );
837
838 if( !net )
839 return -1;
840
841 return net->GetNetCode();
842 }
843
844 return -1;
845}
846
847
849{
850 return m_board->FindNet( aNet )->GetNetname();
851}
852
853
855{
856 wxString refName = m_board->FindNet( aNet )->GetNetname();
857 wxString dummy1;
858
859 return matchDpSuffix( refName, dummy1 );
860}
861
862
863bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( const PNS::ITEM* aItem, int& aNetP, int& aNetN )
864{
865 if( !aItem || !aItem->Parent() || !aItem->Parent()->IsConnected() )
866 return false;
867
868 BOARD_CONNECTED_ITEM* cItem = static_cast<BOARD_CONNECTED_ITEM*>( aItem->Parent() );
869 NETINFO_ITEM* netInfo = cItem->GetNet();
870
871 if( !netInfo )
872 return false;
873
874 wxString netNameP = netInfo->GetNetname();
875 wxString netNameN, netNameCoupled;
876
877 int r = matchDpSuffix( netNameP, netNameCoupled );
878
879 if( r == 0 )
880 {
881 return false;
882 }
883 else if( r == 1 )
884 {
885 netNameN = netNameCoupled;
886 }
887 else
888 {
889 netNameN = netNameP;
890 netNameP = netNameCoupled;
891 }
892
893 NETINFO_ITEM* netInfoP = m_board->FindNet( netNameP );
894 NETINFO_ITEM* netInfoN = m_board->FindNet( netNameN );
895
896 if( !netInfoP || !netInfoN )
897 return false;
898
899 aNetP = netInfoP->GetNetCode();
900 aNetN = netInfoN->GetNetCode();
901
902 return true;
903}
904
905
907{
908public:
911 m_view( nullptr ),
912 m_items( nullptr ),
913 m_depth( 0 )
914 {
915 SetView( aView );
916 }
917
918
920 {
922 delete m_items;
923 }
924
925
926 void SetView( KIGFX::VIEW* aView )
927 {
928 Clear();
929 delete m_items;
930 m_items = nullptr;
931 m_view = aView;
932
933 if( m_view == nullptr )
934 return;
935
936 if( m_view->GetGAL() )
938
941 m_view->Add( m_items );
942 }
943
944
945 void AddPoint( const VECTOR2I& aP, const KIGFX::COLOR4D& aColor, int aSize,
946 const wxString& aName = wxT( "" ),
947 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
948
949 {
951
952 sh.SetWidth( 10000 );
953
954 sh.Append( aP.x - aSize, aP.y - aSize );
955 sh.Append( aP.x + aSize, aP.y + aSize );
956 sh.Append( aP.x, aP.y );
957 sh.Append( aP.x - aSize, aP.y + aSize );
958 sh.Append( aP.x + aSize, aP.y - aSize );
959
960 AddShape( &sh, aColor, sh.Width(), aName, aSrcLoc );
961 }
962
963
964 void AddItem( const PNS::ITEM* aItem, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
965 const wxString& aName = wxT( "" ),
966 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
967 {
968 if( !m_view || !aItem )
969 return;
970
971 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
972
973 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
974 pitem->SetWidth( aOverrideWidth );
975 pitem->SetDepth( nextDepth() );
976
977 m_items->Add( pitem );
979 }
980
981
982 void AddShape( const BOX2I& aBox, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
983 const wxString& aName = wxT( "" ),
984 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
985 {
987 l.SetWidth( aOverrideWidth );
988
989 VECTOR2I o = aBox.GetOrigin();
990 VECTOR2I s = aBox.GetSize();
991
992 l.Append( o );
993 l.Append( o.x + s.x, o.y );
994 l.Append( o.x + s.x, o.y + s.y );
995 l.Append( o.x, o.y + s.y );
996 l.Append( o );
997
998 AddShape( &l, aColor, aOverrideWidth, aName, aSrcLoc );
999 }
1000
1001
1002 void AddShape( const SHAPE* aShape, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1003 const wxString& aName = wxT( "" ),
1004 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1005 {
1006 if( !m_view || !aShape )
1007 return;
1008
1009 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_view );
1010
1011 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
1012 pitem->SetWidth( aOverrideWidth );
1013 pitem->SetDepth( nextDepth() );
1014
1015 m_items->Add( pitem );
1016 m_view->Update( m_items );
1017 }
1018
1019
1020 void Clear() override
1021 {
1022 if( m_view && m_items )
1023 {
1024 m_items->FreeItems();
1025 m_view->Update( m_items );
1026
1027 if( m_view->GetGAL() )
1029 }
1030 }
1031
1032private:
1033 double nextDepth()
1034 {
1035 // Use different depths so that the transculent shapes won't overwrite each other.
1036
1037 m_depth++;
1038
1039 if( m_depth >= 0 && m_view->GetGAL() )
1041
1042 return m_depth;
1043 }
1044
1047
1048 double m_depth;
1049};
1050
1051
1053{
1054 return m_debugDecorator;
1055}
1056
1057
1059{
1060 m_ruleResolver = nullptr;
1061 m_board = nullptr;
1062 m_world = nullptr;
1063 m_debugDecorator = nullptr;
1064 m_startLayer = -1;
1065}
1066
1067
1069{
1070 m_tool = nullptr;
1071 m_view = nullptr;
1072 m_previewItems = nullptr;
1073 m_commitFlags = 0;
1074}
1075
1076
1078{
1079}
1080
1081
1083{
1084 delete m_ruleResolver;
1085 delete m_debugDecorator;
1086
1087 if( m_previewItems )
1088 {
1090 delete m_previewItems;
1091 }
1092}
1093
1094
1095std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1096{
1097 LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 );
1098
1099 // ignore non-copper pads except for those with holes
1100 if( ( aPad->GetLayerSet() & LSET::AllCuMask() ).none() && aPad->GetDrillSize().x == 0 )
1101 return nullptr;
1102
1103 switch( aPad->GetAttribute() )
1104 {
1105 case PAD_ATTRIB::PTH:
1106 case PAD_ATTRIB::NPTH:
1107 break;
1108
1109 case PAD_ATTRIB::CONN:
1110 case PAD_ATTRIB::SMD:
1111 {
1112 LSET lmsk = aPad->GetLayerSet();
1113 bool is_copper = false;
1114
1115 for( int i = 0; i < MAX_CU_LAYERS; i++ )
1116 {
1117 if( lmsk[i] )
1118 {
1119 is_copper = true;
1120
1121 if( aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1122 layers = LAYER_RANGE( i );
1123
1124 break;
1125 }
1126 }
1127
1128 if( !is_copper )
1129 return nullptr;
1130
1131 break;
1132 }
1133
1134 default:
1135 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1136 return nullptr;
1137 }
1138
1139 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1140
1141 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1142 solid->SetRoutable( false );
1143
1144 solid->SetLayers( layers );
1145 solid->SetNet( aPad->GetNetCode() );
1146 solid->SetParent( aPad );
1147 solid->SetPadToDie( aPad->GetPadToDieLength() );
1148 solid->SetOrientation( aPad->GetOrientation() );
1149
1150 if( aPad->IsFreePad() )
1151 solid->SetIsFreePad();
1152
1153 VECTOR2I wx_c = aPad->ShapePos();
1154 VECTOR2I offset = aPad->GetOffset();
1155
1156 VECTOR2I c( wx_c.x, wx_c.y );
1157
1158 RotatePoint( offset, aPad->GetOrientation() );
1159
1160 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1161 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1162
1163 if( aPad->GetDrillSize().x > 0 )
1164 solid->SetHole( aPad->GetEffectiveHoleShape()->Clone() );
1165
1166 // We generate a single SOLID for a pad, so we have to treat it as ALWAYS_FLASHED and then
1167 // perform layer-specific flashing tests internally.
1168 std::shared_ptr<SHAPE> shape = aPad->GetEffectiveShape( UNDEFINED_LAYER,
1170
1171 if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 )
1172 {
1173 std::vector<const SHAPE*> subshapes;
1174 shape->GetIndexableSubshapes( subshapes );
1175
1176 solid->SetShape( subshapes[0]->Clone() );
1177 }
1178 else
1179 {
1180 solid->SetShape( shape->Clone() );
1181 }
1182
1183 return solid;
1184}
1185
1186
1187std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1188{
1189 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1190 aTrack->GetNetCode() );
1191
1192 segment->SetWidth( aTrack->GetWidth() );
1193 segment->SetLayers( LAYER_RANGE( aTrack->GetLayer() ) );
1194 segment->SetParent( aTrack );
1195
1196 if( aTrack->IsLocked() )
1197 segment->Mark( PNS::MK_LOCKED );
1198
1199 return segment;
1200}
1201
1202
1203std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1204{
1205 auto arc = std::make_unique<PNS::ARC>(
1206 SHAPE_ARC( aArc->GetStart(), aArc->GetMid(), aArc->GetEnd(), aArc->GetWidth() ),
1207 aArc->GetNetCode() );
1208
1209 arc->SetLayers( LAYER_RANGE( aArc->GetLayer() ) );
1210 arc->SetParent( aArc );
1211
1212 if( aArc->IsLocked() )
1213 arc->Mark( PNS::MK_LOCKED );
1214
1215 return arc;
1216}
1217
1218
1219std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1220{
1221 PCB_LAYER_ID top, bottom;
1222 aVia->LayerPair( &top, &bottom );
1223
1224 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1225 LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ),
1226 aVia->GetWidth(),
1227 aVia->GetDrillValue(),
1228 aVia->GetNetCode(),
1229 aVia->GetViaType() );
1230
1231 via->SetParent( aVia );
1232
1233 if( aVia->IsLocked() )
1234 via->Mark( PNS::MK_LOCKED );
1235
1236 via->SetIsFree( aVia->GetIsFree() );
1237
1239 via->SetHole( SHAPE_CIRCLE( aVia->GetPosition(),
1240 aVia->GetDrillValue() / 2 ) );
1241
1242 return via;
1243}
1244
1245
1246bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1247{
1248 SHAPE_POLY_SET* poly;
1249
1250 if( !aZone->GetIsRuleArea() && aZone->GetZoneName().IsEmpty() )
1251 return false;
1252
1253 // TODO handle aZone->GetDoNotAllowVias()
1254 // TODO handle rules which disallow tracks & vias
1255 if( !aZone->GetIsRuleArea() || !aZone->GetDoNotAllowTracks() )
1256 return false;
1257
1258 LSET layers = aZone->GetLayerSet();
1259
1260 poly = aZone->Outline();
1261 poly->CacheTriangulation( false );
1262
1263 if( !poly->IsTriangulationUpToDate() )
1264 {
1265 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1266 KIDIALOG dlg( nullptr, wxString::Format( _( "%s is malformed." ),
1267 aZone->GetItemDescription( &unitsProvider ) ),
1269 dlg.ShowDetailedText( wxString::Format( _( "This zone cannot be handled by the router.\n"
1270 "Please verify it is not a self-intersecting "
1271 "polygon." ) ) );
1272 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1273 dlg.ShowModal();
1274
1275 return false;
1276 }
1277
1278 for( int layer = F_Cu; layer <= B_Cu; layer++ )
1279 {
1280 if( !layers[ layer ] )
1281 continue;
1282
1283 for( int outline = 0; outline < poly->OutlineCount(); outline++ )
1284 {
1285 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( outline );
1286
1287 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1288 {
1289 VECTOR2I a, b, c;
1290 tri->GetTriangle( i, a, b, c );
1291 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1292
1293 triShape->Append( a );
1294 triShape->Append( b );
1295 triShape->Append( c );
1296
1297 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1298
1299 solid->SetLayer( layer );
1300 solid->SetNet( -1 );
1301 solid->SetParent( aZone );
1302 solid->SetShape( triShape );
1303 solid->SetIsCompoundShapePrimitive();
1304 solid->SetRoutable( false );
1305
1306 aWorld->Add( std::move( solid ) );
1307 }
1308 }
1309 }
1310
1311 return true;
1312}
1313
1314
1316{
1317 if( !IsCopperLayer( aLayer ) )
1318 return false;
1319
1320 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1321
1322 solid->SetLayer( aLayer );
1323 solid->SetNet( -1 );
1324 solid->SetParent( dynamic_cast<BOARD_ITEM*>( aText ) );
1325
1326 PCB_TEXT* pcb_text = dynamic_cast<PCB_TEXT*>( aText );
1327
1328 if( pcb_text && pcb_text->IsKnockout() )
1329 {
1330 TEXT_ATTRIBUTES attrs = pcb_text->GetAttributes();
1331 SHAPE_POLY_SET buffer;
1332 int margin = attrs.m_StrokeWidth * 1.5
1333 + GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth );
1334 pcb_text->TransformBoundingBoxToPolygon( &buffer, margin );
1335 // buffer should contain a single rectangular polygon
1336 SHAPE_SIMPLE* rectShape = new SHAPE_SIMPLE;
1337
1338 for( int ii = 0; ii < buffer.Outline(0).PointCount(); ii++ )
1339 {
1340 VECTOR2I point = buffer.Outline(0).CPoint(ii);
1341 rectShape->Append( point );
1342 }
1343
1344 solid->SetShape( rectShape );
1345 }
1346 else
1347 solid->SetShape( aText->GetEffectiveTextShape()->Clone() );
1348
1349 solid->SetRoutable( false );
1350
1351 aWorld->Add( std::move( solid ) );
1352
1353 return true;
1354
1355 /* A coarser (but faster) method:
1356 SHAPE_POLY_SET outline;
1357 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE();
1358
1359 aText->TransformBoundingBoxToPolygon( &outline, 0 );
1360
1361 for( auto iter = outline.CIterate( 0 ); iter; iter++ )
1362 shape->Append( *iter );
1363
1364 solid->SetShape( shape );
1365
1366 solid->SetLayer( aLayer );
1367 solid->SetNet( -1 );
1368 solid->SetParent( nullptr );
1369 solid->SetRoutable( false );
1370 aWorld->Add( std::move( solid ) );
1371 return true;
1372 */
1373}
1374
1375
1377{
1378 if( aItem->GetLayer() == Edge_Cuts
1379 || aItem->GetLayer() == Margin
1380 || IsCopperLayer( aItem->GetLayer() ) )
1381 {
1382 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1383
1384 for( SHAPE* shape : shapes )
1385 {
1386 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1387
1388 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1389 solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
1390 else
1391 solid->SetLayer( aItem->GetLayer() );
1392
1393 if( aItem->GetLayer() == Edge_Cuts )
1394 {
1395 switch( shape->Type() )
1396 {
1397 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1398 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1399 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1400 default: /* remaining shapes don't have width */ break;
1401 }
1402 }
1403
1404 solid->SetNet( -1 );
1405 solid->SetParent( aItem );
1406 solid->SetShape( shape ); // takes ownership
1407
1408 if( shapes.size() > 1 )
1409 solid->SetIsCompoundShapePrimitive();
1410
1411 solid->SetRoutable( false );
1412
1413 aWorld->Add( std::move( solid ) );
1414 }
1415
1416 return true;
1417 }
1418
1419 return false;
1420}
1421
1422
1424{
1425 m_board = aBoard;
1426 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1427}
1428
1429
1431{
1432 if( !m_view )
1433 return false;
1434
1435 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1436 {
1437 if( m_view->IsLayerVisible( i ) )
1438 return true;
1439 }
1440
1441 return false;
1442}
1443
1444
1445bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1446{
1448 if( aLayer < 0 )
1449 return true;
1450
1451 if( aItem->Parent() )
1452 {
1453 switch( aItem->Parent()->Type() )
1454 {
1455 case PCB_VIA_T:
1456 {
1457 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1458
1459 return via->FlashLayer( ToLAYER_ID( aLayer ) );
1460 }
1461
1462 case PCB_PAD_T:
1463 {
1464 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1465
1466 return pad->FlashLayer( ToLAYER_ID( aLayer ) );
1467 }
1468
1469 default:
1470 break;
1471 }
1472 }
1473
1474 return aItem->Layers().Overlaps( aLayer );
1475}
1476
1477
1479{
1480 // by default, all items are visible (new ones created by the router have parent == NULL
1481 // as they have not been committed yet to the BOARD)
1482 if( !m_view || !aItem->Parent() )
1483 return true;
1484
1485 BOARD_ITEM* item = aItem->Parent();
1486 bool isOnVisibleLayer = true;
1487 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1488
1489 if( settings->GetHighContrast() )
1490 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1491
1492 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1493 {
1494 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
1495 {
1496 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1497 return true;
1498 }
1499 }
1500
1501 // Items hidden in the router are not hidden on the board
1502 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1503 return true;
1504
1505 return false;
1506}
1507
1508
1510{
1511 if( !m_board )
1512 {
1513 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1514 return;
1515 }
1516
1517 int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
1518
1519 m_world = aWorld;
1520
1521 for( BOARD_ITEM* gitem : m_board->Drawings() )
1522 {
1523 if ( gitem->Type() == PCB_SHAPE_T || gitem->Type() == PCB_TEXTBOX_T )
1524 {
1525 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1526 }
1527 else if( gitem->Type() == PCB_TEXT_T )
1528 {
1529 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1530 }
1531 }
1532
1533 SHAPE_POLY_SET buffer;
1534 SHAPE_POLY_SET* boardOutline = nullptr;
1535
1536 if( m_board->GetBoardPolygonOutlines( buffer ) )
1537 boardOutline = &buffer;
1538
1539 for( ZONE* zone : m_board->Zones() )
1540 {
1541 syncZone( aWorld, zone, boardOutline );
1542 }
1543
1544 for( FOOTPRINT* footprint : m_board->Footprints() )
1545 {
1546 for( PAD* pad : footprint->Pads() )
1547 {
1548 if( std::unique_ptr<PNS::SOLID> solid = syncPad( pad ) )
1549 aWorld->Add( std::move( solid ) );
1550
1551 worstClearance = std::max( worstClearance, pad->GetLocalClearance() );
1552
1553 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1554 {
1555 std::unique_ptr<SHAPE> hole;
1556 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1557 aWorld->AddEdgeExclusion( std::move( hole ) );
1558 }
1559 }
1560
1561 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1562 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1563
1564 for( FP_ZONE* zone : footprint->Zones() )
1565 syncZone( aWorld, zone, boardOutline );
1566
1567 for( BOARD_ITEM* mgitem : footprint->GraphicalItems() )
1568 {
1569 if( mgitem->Type() == PCB_FP_SHAPE_T || mgitem->Type() == PCB_FP_TEXTBOX_T )
1570 {
1571 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( mgitem ) );
1572 }
1573 else if( mgitem->Type() == PCB_FP_TEXT_T )
1574 {
1575 syncTextItem( aWorld, static_cast<FP_TEXT*>( mgitem ), mgitem->GetLayer() );
1576 }
1577 }
1578 }
1579
1580 for( PCB_TRACK* t : m_board->Tracks() )
1581 {
1582 KICAD_T type = t->Type();
1583
1584 if( type == PCB_TRACE_T )
1585 {
1586 if( auto segment = syncTrack( t ) )
1587 aWorld->Add( std::move( segment ) );
1588 }
1589 else if( type == PCB_ARC_T )
1590 {
1591 if( auto arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1592 aWorld->Add( std::move( arc ) );
1593 }
1594 else if( type == PCB_VIA_T )
1595 {
1596 if( auto via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1597 aWorld->Add( std::move( via ) );
1598 }
1599 }
1600
1601 // NB: if this were ever to become a long-lived object we would need to dirty its
1602 // clearance cache here....
1603 delete m_ruleResolver;
1605
1607 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1608}
1609
1610
1612{
1613 for( auto item : m_hiddenItems )
1614 m_view->SetVisible( item, true );
1615
1616 m_hiddenItems.clear();
1617
1618 if( m_previewItems )
1619 {
1622 }
1623
1624 if( m_debugDecorator )
1626}
1627
1628
1630{
1631 m_debugDecorator = aDec;
1632}
1633
1634
1635void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, bool aIsHeadTrace )
1636{
1637 if( aItem->IsVirtual() )
1638 return;
1639
1640 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
1641
1642 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1644 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1645
1646 if( aClearance >= 0 )
1647 {
1648 pitem->SetClearance( aClearance );
1649
1650 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1651
1652 switch( settings->m_Display.m_TrackClearance )
1653 {
1656 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1657 break;
1658
1660 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1661 break;
1662
1663 case SHOW_WHILE_ROUTING:
1664 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1665 break;
1666
1667 default:
1668 pitem->ShowClearance( false );
1669 break;
1670 }
1671 }
1672
1673 if( aIsHeadTrace )
1674 {
1675 pitem->SetIsHeadTrace( true );
1676 pitem->Update( aItem );
1677 }
1678
1679 m_previewItems->Add( pitem );
1681}
1682
1683
1684void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1685{
1686 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, m_view );
1688
1689 COLOR4D color;
1690
1691 if( aImportance >= 1 )
1692 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1693 else if( aImportance == 0 )
1694 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1695
1696 pitem->SetColor( color );
1697
1698 m_previewItems->Add( pitem );
1700}
1701
1702
1703void PNS_KICAD_IFACE::DisplayRatline( const SHAPE_LINE_CHAIN& aRatline, int aNetCode )
1704{
1705 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, m_view );
1706
1707 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1708 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1709 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1710 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1711 COLOR4D color = defaultColor;
1712
1713 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1714 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1715 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1716 std::map<wxString, KIGFX::COLOR4D>& ncColors = rs->GetNetclassColorMap();
1717 const std::map<int, wxString>& ncMap = connectivity->GetNetclassMap();
1718
1719 if( colorByNet && netColors.count( aNetCode ) )
1720 color = netColors.at( aNetCode );
1721 else if( colorByNet && ncMap.count( aNetCode ) && ncColors.count( ncMap.at( aNetCode ) ) )
1722 color = ncColors.at( ncMap.at( aNetCode ) );
1723 else
1724 color = defaultColor;
1725
1726 if( color == COLOR4D::UNSPECIFIED )
1727 color = defaultColor;
1728
1729 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
1730
1731 m_previewItems->Add( pitem );
1733}
1734
1735
1737{
1738 BOARD_ITEM* parent = aItem->Parent();
1739
1740 if( parent )
1741 {
1742 if( m_view->IsVisible( parent ) )
1743 m_hiddenItems.insert( parent );
1744
1745 m_view->SetVisible( parent, false );
1746 m_view->Update( parent, KIGFX::APPEARANCE );
1747 }
1748}
1749
1750
1752{
1753}
1754
1755
1757{
1758 BOARD_ITEM* parent = aItem->Parent();
1759
1760 if( aItem->OfKind( PNS::ITEM::SOLID_T ) )
1761 {
1762 PAD* pad = static_cast<PAD*>( parent );
1763 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1764
1765 m_fpOffsets[ pad ].p_old = pos;
1766 return;
1767 }
1768
1769 if( parent )
1770 {
1771 m_commit->Remove( parent );
1772 }
1773}
1774
1775
1777{
1778}
1779
1780
1782{
1783 BOARD_ITEM* board_item = aItem->Parent();
1784
1785 m_commit->Modify( board_item );
1786
1787 switch( aItem->Kind() )
1788 {
1789 case PNS::ITEM::ARC_T:
1790 {
1791 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1792 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
1793 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape() );
1794 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
1795 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
1796 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
1797 arc_board->SetWidth( arc->Width() );
1798 break;
1799 }
1800
1802 {
1803 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1804 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
1805 const SEG& s = seg->Seg();
1806 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1807 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1808 track->SetWidth( seg->Width() );
1809 break;
1810 }
1811
1812 case PNS::ITEM::VIA_T:
1813 {
1814 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
1815 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1816 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1817 via_board->SetWidth( via->Diameter() );
1818 via_board->SetDrill( via->Drill() );
1819 via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 );
1820 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1821 via_board->SetIsFree( via->IsFree() );
1822 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1823 ToLAYER_ID( via->Layers().End() ) );
1824 break;
1825 }
1826
1827 case PNS::ITEM::SOLID_T:
1828 {
1829 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1830 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1831
1832 m_fpOffsets[ pad ].p_old = pad->GetPosition();
1833 m_fpOffsets[ pad ].p_new = pos;
1834 break;
1835 }
1836
1837 default:
1838 break;
1839 }
1840}
1841
1842
1844{
1845
1846}
1847
1848
1850{
1851 BOARD_CONNECTED_ITEM* newBI = nullptr;
1852
1853 switch( aItem->Kind() )
1854 {
1855 case PNS::ITEM::ARC_T:
1856 {
1857 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1858 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape() ) );
1859 new_arc->SetWidth( arc->Width() );
1860 new_arc->SetLayer( ToLAYER_ID( arc->Layers().Start() ) );
1861 new_arc->SetNetCode( std::max<int>( 0, arc->Net() ) );
1862 newBI = new_arc;
1863 break;
1864 }
1865
1867 {
1868 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1869 PCB_TRACK* track = new PCB_TRACK( m_board );
1870 const SEG& s = seg->Seg();
1871 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1872 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1873 track->SetWidth( seg->Width() );
1874 track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
1875 track->SetNetCode( seg->Net() > 0 ? seg->Net() : 0 );
1876 newBI = track;
1877 break;
1878 }
1879
1880 case PNS::ITEM::VIA_T:
1881 {
1882 PCB_VIA* via_board = new PCB_VIA( m_board );
1883 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1884 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1885 via_board->SetWidth( via->Diameter() );
1886 via_board->SetDrill( via->Drill() );
1887 via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 );
1888 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1889 via_board->SetIsFree( via->IsFree() );
1890 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1891 ToLAYER_ID( via->Layers().End() ) );
1892 newBI = via_board;
1893 break;
1894 }
1895
1896 case PNS::ITEM::SOLID_T:
1897 {
1898 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1899 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1900
1901 m_fpOffsets[ pad ].p_new = pos;
1902 return;
1903 }
1904
1905 default:
1906 break;
1907 }
1908
1909 if( newBI )
1910 {
1911 //newBI->SetLocalRatsnestVisible( m_dispOptions->m_ShowGlobalRatsnest );
1912 aItem->SetParent( newBI );
1913 newBI->ClearFlags();
1914
1915 m_commit->Add( newBI );
1916 }
1917}
1918
1919
1921{
1922 std::set<FOOTPRINT*> processedFootprints;
1923
1924 EraseView();
1925
1926 for( const std::pair<const PAD*, OFFSET>& fpOffset : m_fpOffsets )
1927 {
1928 VECTOR2I offset = fpOffset.second.p_new - fpOffset.second.p_old;
1929 FOOTPRINT* footprint = fpOffset.first->GetParent();
1930 VECTOR2I p_orig = footprint->GetPosition();
1931 VECTOR2I p_new = p_orig + offset;
1932
1933 if( processedFootprints.find( footprint ) != processedFootprints.end() )
1934 continue;
1935
1936 processedFootprints.insert( footprint );
1937 m_commit->Modify( footprint );
1938 footprint->SetPosition( p_new );
1939 }
1940
1941 m_fpOffsets.clear();
1942
1943 m_commit->Push( _( "Interactive Router" ), m_commitFlags );
1944 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
1945}
1946
1947
1949{
1950 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
1951}
1952
1953
1955{
1956 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
1957
1958 if( m_previewItems )
1959 {
1961 delete m_previewItems;
1962 }
1963
1964 m_view = aView;
1967
1968 if(m_view)
1970
1971 delete m_debugDecorator;
1972
1973 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR();
1974 m_debugDecorator = dec;
1975
1976 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
1977
1978 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
1979 dec->SetView( m_view );
1980}
1981
1982
1983void PNS_KICAD_IFACE::UpdateNet( int aNetCode )
1984{
1985 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %d" ), aNetCode );
1986}
1987
1988
1990{
1991 return m_ruleResolver;
1992}
1993
1994
1996{
1997 m_tool = aTool;
1998 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
1999}
int color
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
@ OFF
Net (and netclass) colors are not shown.
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,...
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given 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:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:127
virtual bool IsKnockout() const
Definition: board_item.h:262
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:226
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:197
virtual bool IsLocked() const
Definition: board_item.cpp:71
BOARD_ITEM_CONTAINER * GetParentFootprint() const
Definition: board_item.cpp:239
virtual bool IsOnLayer(PCB_LAYER_ID aLayer, bool aIncludeCourtyards=false) const
Test to see if this object is on the given layer.
Definition: board_item.h:257
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:175
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:269
ZONES & Zones()
Definition: board.h:317
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1478
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:1972
FOOTPRINTS & Footprints()
Definition: board.h:311
TRACKS & Tracks()
Definition: board.h:308
DRAWINGS & Drawings()
Definition: board.h:314
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:430
const Vec & GetOrigin() const
Definition: box2.h:183
const Vec & GetSize() const
Definition: box2.h:179
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
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:141
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:289
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
void TransformBoundingBoxToPolygon(SHAPE_POLY_SET *aBuffer, int aClearance) const
Convert the text bounding box to a rectangular polygon depending on the text orientation,...
Definition: eda_text.cpp:947
const TEXT_ATTRIBUTES & GetAttributes() const
Definition: eda_text.h:172
std::shared_ptr< SHAPE_COMPOUND > GetEffectiveTextShape(bool aTriangulate=true, bool aUseTextRotation=true) const
build a list of segments (SHAPE_SEGMENT) to describe a text shape.
Definition: eda_text.cpp:855
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:1688
bool IsNetTie() const
Definition: footprint.h:257
VECTOR2I GetPosition() const override
Definition: footprint.h:188
A specialization of ZONE for use in footprints.
Definition: zone.h:916
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:46
@ KD_WARNING
Definition: confirm.h:49
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:76
int ShowModal() override
Definition: confirm.cpp:120
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:102
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:309
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:72
NET_COLOR_MODE GetNetColorMode() const
Definition: pcb_painter.h:111
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:116
std::map< wxString, KIGFX::COLOR4D > & GetNetclassColorMap()
Definition: pcb_painter.h:114
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:191
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:57
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:132
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:316
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:1591
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:1569
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1529
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
int Start() const
Definition: pns_layerset.h:82
bool IsMultilayer() const
Definition: pns_layerset.h:77
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:532
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
const wxString & GetNetname() const
Definition: netinfo.h:125
int GetNetCode() const
Definition: netinfo.h:119
Definition: pad.h:60
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:398
const VECTOR2I & GetDrillSize() const
Definition: pad.h:268
PAD_ATTRIB GetAttribute() const
Definition: pad.h:401
const VECTOR2I & GetOffset() const
Definition: pad.h:275
VECTOR2I ShapePos() const
Definition: pad.cpp:770
bool IsFreePad() const
Definition: pad.cpp:189
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:371
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:370
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:407
int GetPadToDieLength() const
Definition: pad.h:414
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:312
const VECTOR2I & GetMid() const
Definition: pcb_track.h:313
void SetWidth(int aWidth)
Definition: pcb_track.h:107
int GetWidth() const
Definition: pcb_track.h:108
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:110
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:113
const VECTOR2I & GetStart() const
Definition: pcb_track.h:114
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:111
bool GetIsFree() const
Checks if the via is a free via (as opposed to one created on a track by the router).
Definition: pcb_track.h:544
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:599
VECTOR2I GetPosition() const override
Definition: pcb_track.h:442
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: pcb_track.h:516
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:545
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:443
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_layer contains the top layer, the other layer is in m_bottomLayer.
Definition: pcb_track.cpp:550
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:395
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:593
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:221
VIATYPE GetViaType() const
Definition: pcb_track.h:394
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
Definition: pcb_track.cpp:571
int Width() const override
Definition: pns_arc.h:87
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_arc.h:77
void SetDebugEnabled(bool aEnabled)
ITEM_SET & ExcludeItem(const ITEM *aItem)
ITEM_SET & FilterKinds(int aKindMask, bool aInvert=false)
Definition: pns_itemset.cpp:68
ENTRIES & Items()
Definition: pns_itemset.h:135
Base class for PNS router board items.
Definition: pns_item.h:56
BOARD_ITEM * Parent() const
Definition: pns_item.h:151
void SetNet(int aNet)
Definition: pns_item.h:153
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:132
NODE * Owner() const
Return the owner of this item, or NULL if there's none.
Definition: pns_item.h:173
virtual int Layer() const
Definition: pns_item.h:160
@ SOLID_T
Definition: pns_item.h:63
@ LINE_T
Definition: pns_item.h:64
@ SEGMENT_T
Definition: pns_item.h:66
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:150
const LAYER_RANGE & Layers() const
Definition: pns_item.h:156
bool OfKind(int aKindMask) const
Return true if the item's type matches the mask aKindMask.
Definition: pns_item.h:140
bool IsVirtual() const
Definition: pns_item.h:240
int Net() const
Definition: pns_item.h:154
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
ITEM_SET & Links()
Definition: pns_joint.h:251
Keep the router "world" - i.e.
Definition: pns_node.h:156
void SetMaxClearance(int aClearance)
Assign a clearance resolution function object.
Definition: pns_node.h:186
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:667
void SetRuleResolver(RULE_RESOLVER *aFunc)
Definition: pns_node.h:192
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
Definition: pns_node.cpp:740
const SEG & Seg() const
Definition: pns_segment.h:84
int Width() const override
Definition: pns_segment.h:79
void SetTrackWidth(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
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, int aNet) override
PNS::DEBUG_DECORATOR * m_debugDecorator
void SetDebugDecorator(PNS::DEBUG_DECORATOR *aDec)
bool syncZone(PNS::NODE *aWorld, ZONE *aZone, SHAPE_POLY_SET *aBoardOutline)
void SetBoard(BOARD *aBoard)
std::unique_ptr< PNS::ARC > syncArc(PCB_ARC *aArc)
void RemoveItem(PNS::ITEM *aItem) override
bool syncTextItem(PNS::NODE *aWorld, EDA_TEXT *aText, PCB_LAYER_ID aLayer)
PNS::RULE_RESOLVER * GetRuleResolver() override
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
std::unique_ptr< PNS::VIA > syncVia(PCB_VIA *aVia)
void UpdateItem(PNS::ITEM *aItem) override
void SetView(KIGFX::VIEW *aView)
void DisplayRatline(const SHAPE_LINE_CHAIN &aRatline, int aNetCode) override
void RemoveItem(PNS::ITEM *aItem) override
void AddItem(PNS::ITEM *aItem) override
void UpdateItem(PNS::ITEM *aItem) override
std::map< PAD *, OFFSET > m_fpOffsets
void SetHostTool(PCB_TOOL_BASE *aTool)
std::unique_ptr< BOARD_COMMIT > m_commit
void UpdateNet(int aNetCode) override
void EraseView() override
void HideItem(PNS::ITEM *aItem) 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 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 HoleToHoleClearance(const PNS::ITEM *aA, const PNS::ITEM *aB, bool aUseClearanceEpsilon=true) override
std::unordered_map< CLEARANCE_CACHE_KEY, int > m_holeToHoleClearanceCache
PNS_PCBNEW_RULE_RESOLVER(BOARD *aBoard, PNS::ROUTER_IFACE *aRouterIface)
virtual bool QueryConstraint(PNS::CONSTRAINT_TYPE aType, const PNS::ITEM *aItemA, const PNS::ITEM *aItemB, int aLayer, PNS::CONSTRAINT *aConstraint) override
virtual wxString NetName(int aNet) override
std::unordered_map< CLEARANCE_CACHE_KEY, int > m_holeClearanceCache
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 ClearCacheForItem(const PNS::ITEM *aItem) override
virtual int DpCoupledNet(int aNet) override
virtual bool DpNetPair(const PNS::ITEM *aItem, int &aNetP, int &aNetN) override
int holeRadius(const PNS::ITEM *aItem) const
std::unordered_map< CLEARANCE_CACHE_KEY, int > m_clearanceCache
virtual bool IsNetTieExclusion(const PNS::ITEM *aItem, const VECTOR2I &aCollisionPos, const PNS::ITEM *aCollidingItem) override
virtual bool IsInNetTie(const PNS::ITEM *aA) override
virtual int DpNetPolarity(int aNet) override
virtual bool IsDiffPair(const PNS::ITEM *aA, const PNS::ITEM *aB) override
PNS::ROUTER_IFACE * m_routerIface
virtual int HoleClearance(const PNS::ITEM *aA, const PNS::ITEM *aB, bool aUseClearanceEpsilon=true) 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.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
void SetWidth(int aWidth)
Set the width of all segments in the chain.
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)
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
int OutlineCount() const
Return the number of vertices in a given outline/hole.
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:124
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:144
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:294
VECTOR2_TRAITS< int >::extended_type extended_type
Definition: vector2d.h:72
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: zone.cpp:786
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:703
bool GetDoNotAllowTracks() const
Definition: zone.h:706
SHAPE_POLY_SET * Outline()
Definition: zone.h:318
wxString GetZoneName() const
Definition: zone.h:124
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:122
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)
EDA_UNITS
Definition: eda_units.h:43
int GetKnockoutTextMargin(const VECTOR2I &aSize, int aThickness)
Returns the margin for knocking out text.
Definition: gr_text.h:104
@ ALWAYS_FLASHED
#define MAX_CU_LAYERS
Definition: layer_ids.h:140
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:827
@ LAYER_RATSNEST
Definition: layer_ids.h:204
@ LAYER_SELECT_OVERLAY
currently selected items overlay
Definition: layer_ids.h:219
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ PCBNEW_LAYER_ID_START
Definition: layer_ids.h:63
@ Edge_Cuts
Definition: layer_ids.h:113
@ B_Cu
Definition: layer_ids.h:95
@ Margin
Definition: layer_ids.h:114
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
This file contains miscellaneous commonly used macros and functions.
@ APPEARANCE
Visibility flag has changed.
Definition: view_item.h:47
void SetWidth(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aWidth, const wxString &aActualConversion)
Push and Shove diff pair dimensions (gap) settings dialog.
CONSTRAINT_TYPE
An abstract function object, returning a design rule (clearance, diff pair gap, etc) required between...
Definition: pns_node.h:55
@ MK_LOCKED
Definition: pns_item.h:43
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:279
Definition: bitmap.cpp:65
@ NPTH
like PAD_PTH, but not plated
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default)
@ PAD_DRILL_SHAPE_CIRCLE
Definition: pad_shapes.h:70
@ CASTELLATED
a pad with a castellated through hole
@ SHOW_WITH_VIA_WHILE_ROUTING_OR_DRAGGING
@ SHOW_WHILE_ROUTING
@ SHOW_WITH_VIA_ALWAYS
@ SHOW_WITH_VIA_WHILE_ROUTING
#define HAS_PLATED_HOLE(a)
bool isEdge(const PNS::ITEM *aItem)
bool isCopper(const PNS::ITEM *aItem)
VECTOR2I::extended_type ecoord
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
@ RPT_SEVERITY_IGNORE
@ SH_SEGMENT
line segment
Definition: shape.h:46
@ SH_ARC
circular arc
Definition: shape.h:52
@ SH_LINE_CHAIN
line chain (polyline)
Definition: shape.h:47
const PNS::ITEM * A
bool operator==(const CLEARANCE_CACHE_KEY &other) const
const PNS::ITEM * B
wxString m_RuleName
Definition: pns_node.h:72
MINOPTMAX< int > m_Value
Definition: pns_node.h:70
CONSTRAINT_TYPE m_Type
Definition: pns_node.h:69
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_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:93
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:103
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590