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