KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_kicad_iface.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2016 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <board.h>
25#include <netinfo.h>
26#include <footprint.h>
27#include <layer_range.h>
29#include <pad.h>
30#include <pcb_track.h>
31#include <zone.h>
32#include <pcb_shape.h>
33#include <pcb_generator.h>
34#include <pcb_text.h>
35#include <pcb_barcode.h>
36#include <pcb_table.h>
37#include <pcb_tablecell.h>
38#include <board_commit.h>
39#include <eda_group.h>
40#include <layer_ids.h>
41#include <optional>
42#include <kidialog.h>
43#include <tools/pcb_tool_base.h>
45#include <tool/tool_manager.h>
47
49#include <pcb_painter.h>
50
51#include <geometry/shape.h>
53#include <geometry/shape_arc.h>
55
56#include <drc/drc_rule.h>
57#include <drc/drc_engine.h>
58
60
61#include <wx/log.h>
62
63#include <memory>
64
65#include <advanced_config.h>
66#include <pcbnew_settings.h>
67#include <macros.h>
68
69#include "pns_kicad_iface.h"
70#include "pns_arc.h"
71#include "pns_sizes_settings.h"
72#include "pns_item.h"
73#include "pns_layerset.h"
74#include "pns_line.h"
75#include "pns_solid.h"
76#include "pns_segment.h"
77#include "pns_node.h"
78#include "pns_router.h"
79#include "pns_debug_decorator.h"
80#include "router_preview_item.h"
81
83
84// Keep this odd so that it can never match a "real" pointer
85#define ENTERED_GROUP_MAGIC_NUMBER ( (BOARD*)777 )
86
88{
89 const PNS::ITEM* A;
90 const PNS::ITEM* B;
91 bool Flag;
92
93 bool operator==(const CLEARANCE_CACHE_KEY& other) const
94 {
95 return A == other.A && B == other.B && Flag == other.Flag;
96 }
97};
98
99namespace std
100{
101 template <>
103 {
104 std::size_t operator()( const CLEARANCE_CACHE_KEY& k ) const
105 {
106 size_t retval = 0xBADC0FFEE0DDF00D;
107 hash_combine( retval, hash<const void*>()( k.A ), hash<const void*>()( k.B ), hash<int>()( k.Flag ) );
108 return retval;
109 }
110 };
111}
112
113
115{
116public:
117 PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER_IFACE* aRouterIface );
119
120 int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
121 bool aUseClearanceEpsilon = true ) override;
122
124 int DpNetPolarity( PNS::NET_HANDLE aNet ) override;
125 bool DpNetPair( const PNS::ITEM* aItem, PNS::NET_HANDLE& aNetP,
126 PNS::NET_HANDLE& aNetN ) override;
127
128 int NetCode( PNS::NET_HANDLE aNet ) override;
129 wxString NetName( PNS::NET_HANDLE aNet ) override;
130
131 bool IsInNetTie( const PNS::ITEM* aA ) override;
132 bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
133 const PNS::ITEM* aCollidingItem ) override;
134
135 bool IsDrilledHole( const PNS::ITEM* aItem ) override;
136 bool IsNonPlatedSlot( const PNS::ITEM* aItem ) override;
137
142 bool IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem, bool* aEnforce ) override;
143
144 bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
145 const PNS::ITEM* aItemB, int aLayer,
146 PNS::CONSTRAINT* aConstraint ) override;
147
148 int ClearanceEpsilon() const override { return m_clearanceEpsilon; }
149
150 void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
151 void ClearCaches() override;
152 void ClearTemporaryCaches() override;
153
154private:
155 BOARD_ITEM* getBoardItem( const PNS::ITEM* aItem, PCB_LAYER_ID aBoardLayer, int aIdx = 0 );
156
157private:
164
165 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
166 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_tempClearanceCache;
167};
168
169
171 PNS::ROUTER_IFACE* aRouterIface ) :
172 m_routerIface( aRouterIface ),
173 m_board( aBoard ),
174 m_dummyTracks{ { aBoard }, { aBoard } },
175 m_dummyArcs{ { aBoard }, { aBoard } },
176 m_dummyVias{ { aBoard }, { aBoard } }
177{
178 for( PCB_TRACK& track : m_dummyTracks )
179 track.SetFlags( ROUTER_TRANSIENT );
180
181 for( PCB_ARC& arc : m_dummyArcs )
182 arc.SetFlags( ROUTER_TRANSIENT );
183
184 for ( PCB_VIA& via : m_dummyVias )
185 via.SetFlags( ROUTER_TRANSIENT );
186
187 if( aBoard )
188 m_clearanceEpsilon = aBoard->GetDesignSettings().GetDRCEpsilon();
189 else
190 m_clearanceEpsilon = 0;
191}
192
193
197
198
200{
201 BOARD_ITEM* item = aA->BoardItem();
202
203 return item && item->GetParentFootprint() && item->GetParentFootprint()->IsNetTie();
204}
205
206
208 const VECTOR2I& aCollisionPos,
209 const PNS::ITEM* aCollidingItem )
210{
211 if( !aItem || !aCollidingItem )
212 return false;
213
214 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
215 BOARD_ITEM* item = aItem->BoardItem();
216 BOARD_ITEM* collidingItem = aCollidingItem->BoardItem();
217
218 FOOTPRINT* collidingFp = collidingItem->GetParentFootprint();
219 FOOTPRINT* itemFp = item ? item->GetParentFootprint() : nullptr;
220
221 if( collidingFp && itemFp && ( collidingFp == itemFp ) && itemFp->IsNetTie() )
222 {
223 // Two items colliding from the same net tie footprint are not checked
224 return true;
225 }
226
227 if( drcEngine )
228 {
229 return drcEngine->IsNetTieExclusion( NetCode( aItem->Net() ),
230 m_routerIface->GetBoardLayerFromPNSLayer( aItem->Layer() ),
231 aCollisionPos, collidingItem );
232 }
233
234 return false;
235}
236
237
238bool PNS_PCBNEW_RULE_RESOLVER::IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem,
239 bool* aEnforce )
240{
241 auto checkKeepout =
242 []( const ZONE* aKeepout, const BOARD_ITEM* aOther )
243 {
244 if( !aOther )
245 return false;
246
247 if( aKeepout->GetDoNotAllowTracks() && aOther->IsType( { PCB_ARC_T, PCB_TRACE_T } ) )
248 return true;
249
250 if( aKeepout->GetDoNotAllowVias() && aOther->Type() == PCB_VIA_T )
251 return true;
252
253 if( aKeepout->GetDoNotAllowPads() && aOther->Type() == PCB_PAD_T )
254 return true;
255
256 // Incomplete test, but better than nothing:
257 if( aKeepout->GetDoNotAllowFootprints() && aOther->Type() == PCB_PAD_T )
258 {
259 return !aKeepout->GetParentFootprint()
260 || aKeepout->GetParentFootprint() != aOther->GetParentFootprint();
261 }
262
263 return false;
264 };
265
266 if( aObstacle->Parent() && aObstacle->Parent()->Type() == PCB_ZONE_T )
267 {
268 const ZONE* zone = static_cast<ZONE*>( aObstacle->Parent() );
269
270 if( zone->GetIsRuleArea() && zone->HasKeepoutParametersSet() )
271 {
272 *aEnforce = checkKeepout( zone,
273 getBoardItem( aItem, m_routerIface->GetBoardLayerFromPNSLayer(
274 aObstacle->Layer() ) ) );
275 return true;
276 }
277 }
278
279 return false;
280}
281
282
283static bool isCopper( const PNS::ITEM* aItem )
284{
285 if ( !aItem )
286 return false;
287
288 const BOARD_ITEM *parent = aItem->Parent();
289
290 return !parent || parent->IsOnCopperLayer();
291}
292
293
294static bool isHole( const PNS::ITEM* aItem )
295{
296 if ( !aItem )
297 return false;
298
299 return aItem->OfKind( PNS::ITEM::HOLE_T );
300}
301
302
303static bool isEdge( const PNS::ITEM* aItem )
304{
305 if ( !aItem )
306 return false;
307
308 const PCB_SHAPE *parent = dynamic_cast<PCB_SHAPE*>( aItem->BoardItem() );
309
310 return parent && ( parent->IsOnLayer( Edge_Cuts ) || parent->IsOnLayer( Margin ) );
311}
312
313
315{
316 if( !isHole( aItem ) )
317 return false;
318
319 BOARD_ITEM* parent = aItem->Parent();
320
321 if( !parent && aItem->ParentPadVia() )
322 parent = aItem->ParentPadVia()->Parent();
323
324 return parent && parent->HasDrilledHole();
325}
326
327
329{
330 if( !isHole( aItem ) )
331 return false;
332
333 BOARD_ITEM* parent = aItem->Parent();
334
335 if( !parent && aItem->ParentPadVia() )
336 parent = aItem->ParentPadVia()->Parent();
337
338 if( parent )
339 {
340 if( parent->Type() == PCB_PAD_T )
341 {
342 PAD* pad = static_cast<PAD*>( parent );
343
344 return pad->GetAttribute() == PAD_ATTRIB::NPTH
345 && pad->GetDrillSizeX() != pad->GetDrillSizeY();
346 }
347
348 // Via holes are (currently) always round, and always plated
349 }
350
351 return false;
352}
353
354
356{
357 switch( aItem->Kind() )
358 {
359 case PNS::ITEM::ARC_T:
360 m_dummyArcs[aIdx].SetLayer( aBoardLayer );
361 m_dummyArcs[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
362 m_dummyArcs[aIdx].SetStart( aItem->Anchor( 0 ) );
363 m_dummyArcs[aIdx].SetEnd( aItem->Anchor( 1 ) );
364 return &m_dummyArcs[aIdx];
365
366 case PNS::ITEM::VIA_T:
368 m_dummyVias[aIdx].SetLayer( aBoardLayer );
369 m_dummyVias[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
370 m_dummyVias[aIdx].SetStart( aItem->Anchor( 0 ) );
371 return &m_dummyVias[aIdx];
372
375 m_dummyTracks[aIdx].SetLayer( aBoardLayer );
376 m_dummyTracks[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
377 m_dummyTracks[aIdx].SetStart( aItem->Anchor( 0 ) );
378 m_dummyTracks[aIdx].SetEnd( aItem->Anchor( 1 ) );
379 return &m_dummyTracks[aIdx];
380
381 default:
382 return nullptr;
383 }
384}
385
386
388 const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
389 int aPNSLayer, PNS::CONSTRAINT* aConstraint )
390{
391 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
392
393 if( !drcEngine )
394 return false;
395
396 DRC_CONSTRAINT_T hostType;
397
398 switch ( aType )
399 {
412 default: return false; // should not happen
413 }
414
415 BOARD_ITEM* parentA = aItemA ? aItemA->BoardItem() : nullptr;
416 BOARD_ITEM* parentB = aItemB ? aItemB->BoardItem() : nullptr;
417 PCB_LAYER_ID board_layer = m_routerIface->GetBoardLayerFromPNSLayer( aPNSLayer );
418 DRC_CONSTRAINT hostConstraint;
419
420 // A track being routed may not have a BOARD_ITEM associated yet.
421 if( aItemA && !parentA )
422 parentA = getBoardItem( aItemA, board_layer, 0 );
423
424 if( aItemB && !parentB )
425 parentB = getBoardItem( aItemB, board_layer, 1 );
426
427 if( parentA )
428 hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, board_layer );
429
430 if( hostConstraint.IsNull() )
431 return false;
432
433 if( hostConstraint.GetSeverity() == RPT_SEVERITY_IGNORE
434 && ( !hostConstraint.GetParentRule()->IsImplicit()
436 {
437 aConstraint->m_Value.SetMin( -1 );
438 aConstraint->m_RuleName = hostConstraint.GetName();
439 aConstraint->m_Type = aType;
440 return true;
441 }
442
443 switch ( aType )
444 {
457 aConstraint->m_Value = hostConstraint.GetValue();
458 aConstraint->m_RuleName = hostConstraint.GetName();
459 aConstraint->m_Type = aType;
460 aConstraint->m_IsTimeDomain = hostConstraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN );
461 return true;
462
463 default:
464 return false;
465 }
466}
467
468
469void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems )
470{
471 int n_pruned = 0;
472 std::set<const PNS::ITEM*> remainingItems( aItems.begin(), aItems.end() );
473
474/* We need to carefully check both A and B item pointers in the cache against dirty/invalidated
475 items in the set, as the clearance relation is commutative ( CL[a,b] == CL[b,a] ). The code
476 below is a bit ugly, but works in O(n*log(m)) and is run once or twice during ROUTER::Move() call
477 - so I hope it still gets better performance than no cache at all */
478 for( auto it = m_clearanceCache.begin(); it != m_clearanceCache.end(); )
479 {
480 bool dirty = remainingItems.find( it->first.A ) != remainingItems.end();
481 dirty |= remainingItems.find( it->first.B) != remainingItems.end();
482
483 if( dirty )
484 {
485 it = m_clearanceCache.erase( it );
486 n_pruned++;
487 } else
488 it++;
489 }
490#if 0
491 printf("ClearCache : n_pruned %d\n", n_pruned );
492#endif
493}
494
495
501
502
507
508
510 bool aUseClearanceEpsilon )
511{
512 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
513
514 // Search cache (used for actual board items)
515 auto it = m_clearanceCache.find( key );
516
517 if( it != m_clearanceCache.end() )
518 return it->second;
519
520 // Search cache (used for temporary items within an algorithm)
521 it = m_tempClearanceCache.find( key );
522
523 if( it != m_tempClearanceCache.end() )
524 return it->second;
525
526 PNS::CONSTRAINT constraint;
527 int rv = 0;
528 PNS_LAYER_RANGE layers;
529
530 if( !aB )
531 layers = aA->Layers();
532 else if( isEdge( aA ) )
533 layers = aB->Layers();
534 else if( isEdge( aB ) )
535 layers = aA->Layers();
536 else
537 layers = aA->Layers().Intersection( aB->Layers() );
538
539 // Normalize layer range (no -1 magic numbers)
541
542 for( int layer = layers.Start(); layer <= layers.End(); ++layer )
543 {
544 if( IsDrilledHole( aA ) && IsDrilledHole( aB ) )
545 {
546 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer, &constraint ) )
547 {
548 if( constraint.m_Value.Min() > rv )
549 rv = constraint.m_Value.Min();
550 }
551 }
552 else if( isHole( aA ) || isHole( aB ) )
553 {
554 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
555 {
556 if( constraint.m_Value.Min() > rv )
557 rv = constraint.m_Value.Min();
558 }
559 }
560
561 // No 'else'; plated holes get both HOLE_CLEARANCE and CLEARANCE
562 if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
563 {
564 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
565 {
566 if( constraint.m_Value.Min() > rv )
567 rv = constraint.m_Value.Min();
568 }
569 }
570
571 // No 'else'; non-plated milled holes get both HOLE_CLEARANCE and EDGE_CLEARANCE
572 if( isEdge( aA ) || IsNonPlatedSlot( aA ) || isEdge( aB ) || IsNonPlatedSlot( aB ) )
573 {
574 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
575 {
576 if( constraint.m_Value.Min() > rv )
577 rv = constraint.m_Value.Min();
578 }
579 }
580
581 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_PHYSICAL_CLEARANCE, aA, aB, layer, &constraint ) )
582 {
583 if( constraint.m_Value.Min() > rv )
584 rv = constraint.m_Value.Min();
585 }
586 }
587
588 if( aUseClearanceEpsilon && rv > 0 )
589 rv = std::max( 0, rv - m_clearanceEpsilon );
590
591 /*
592 * It makes no sense to put items that have no owning NODE in the cache - they can be
593 * allocated on stack and we can't really invalidate them in the cache when they are
594 * destroyed. Probably a better idea would be to use a static unique counter in PNS::ITEM
595 * constructor to generate the cache keys.
596 *
597 * However, algorithms DO greatly benefit from using the cache, so ownerless items need to be
598 * cached. In order to easily clear those only, a temporary cache is created. If this doesn't
599 * seem nice, an alternative is clearing the full cache once it reaches a certain size. Also
600 * not pretty, but VERY effective to keep things interactive.
601 */
602 if( aA && aB )
603 {
604 if ( aA->Owner() && aB->Owner() )
605 m_clearanceCache[ key ] = rv;
606 else
607 m_tempClearanceCache[ key ] = rv;
608 }
609
610 return rv;
611}
612
613
614bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth )
615{
616 VECTOR2I p;
617
618 assert( aItem->Owner() != nullptr );
619
620 auto tryGetTrackWidth =
621 []( PNS::ITEM* aPnsItem ) -> int
622 {
623 switch( aPnsItem->Kind() )
624 {
625 case PNS::ITEM::SEGMENT_T: return static_cast<PNS::SEGMENT*>( aPnsItem )->Width();
626 case PNS::ITEM::ARC_T: return static_cast<PNS::ARC*>( aPnsItem )->Width();
627 default: return -1;
628 }
629 };
630
631 int itemTrackWidth = tryGetTrackWidth( aItem );
632
633 if( itemTrackWidth > 0 )
634 {
635 *aInheritedWidth = itemTrackWidth;
636 return true;
637 }
638
639 switch( aItem->Kind() )
640 {
641 case PNS::ITEM::VIA_T: p = static_cast<PNS::VIA*>( aItem )->Pos(); break;
642 case PNS::ITEM::SOLID_T: p = static_cast<PNS::SOLID*>( aItem )->Pos(); break;
643 default: return false;
644 }
645
646 const PNS::JOINT* jt = static_cast<const PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
647
648 assert( jt != nullptr );
649
650 int mval = INT_MAX;
651
652 PNS::ITEM_SET linkedSegs( jt->CLinks() );
654
655 for( PNS::ITEM* item : linkedSegs.Items() )
656 {
657 int w = tryGetTrackWidth( item );
658
659 if( w > 0 )
660 mval = std::min( w, mval );
661 }
662
663 if( mval == INT_MAX )
664 return false;
665
666 *aInheritedWidth = mval;
667 return true;
668}
669
670
672 PNS::NET_HANDLE aNet, VECTOR2D aStartPosition )
673{
674 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
675 PNS::CONSTRAINT constraint;
676
677 if( aStartItem && m_startLayer < 0 )
678 m_startLayer = aStartItem->Layer();
679
680 aSizes.SetClearance( bds.m_MinClearance );
681 aSizes.SetMinClearance( bds.m_MinClearance );
682 aSizes.SetClearanceSource( _( "board minimum clearance" ) );
683
684 int startAnchor = 0;
685 VECTOR2I startPosInt( aStartPosition.x, aStartPosition.y );
686
687 if( aStartItem && aStartItem->Kind() == PNS::ITEM::SEGMENT_T )
688 {
689 // Find the start anchor which is closest to the start mouse location
690 double anchor0Distance = startPosInt.Distance( aStartItem->Anchor( 0 ) );
691 double anchor1Distance = startPosInt.Distance( aStartItem->Anchor( 1 ) );
692
693 if( anchor1Distance < anchor0Distance )
694 startAnchor = 1;
695 }
696
697 if( aStartItem )
698 {
699 PNS::SEGMENT dummyTrack;
700 dummyTrack.SetEnds( aStartItem->Anchor( startAnchor ), aStartItem->Anchor( startAnchor ) );
701 dummyTrack.SetLayer( m_startLayer );
702 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( aStartItem->Net() ) );
703
704 if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, &dummyTrack,
705 nullptr, m_startLayer, &constraint ) )
706 {
707 if( constraint.m_Value.Min() >= bds.m_MinClearance )
708 {
709 aSizes.SetClearance( constraint.m_Value.Min() );
710 aSizes.SetClearanceSource( constraint.m_RuleName );
711 }
712 }
713 }
714
715 int trackWidth = bds.m_TrackMinWidth;
716 bool found = false;
717 aSizes.SetWidthSource( _( "board minimum track width" ) );
718
719 if( bds.m_UseConnectedTrackWidth && !bds.m_TempOverrideTrackWidth && aStartItem != nullptr )
720 {
721 found = inheritTrackWidth( aStartItem, &trackWidth );
722
723 if( found )
724 aSizes.SetWidthSource( _( "existing track" ) );
725 }
726
727 if( !found && bds.UseNetClassTrack() && aStartItem )
728 {
729 PNS::SEGMENT dummyTrack;
730 dummyTrack.SetEnds( aStartItem->Anchor( startAnchor ), aStartItem->Anchor( startAnchor ) );
731 dummyTrack.SetLayer( m_startLayer );
732 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( aStartItem->Net() ) );
733
734 if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, &dummyTrack, nullptr,
735 m_startLayer, &constraint ) )
736 {
737 trackWidth = std::max( trackWidth, constraint.m_Value.Opt() );
738 found = true;
739
740 if( trackWidth == constraint.m_Value.Opt() )
741 aSizes.SetWidthSource( constraint.m_RuleName );
742 }
743 }
744
745 if( !found )
746 {
747 trackWidth = std::max( trackWidth, bds.GetCurrentTrackWidth() );
748
749 if( bds.UseNetClassTrack() )
750 aSizes.SetWidthSource( _( "netclass 'Default'" ) );
751 else if( trackWidth == bds.GetCurrentTrackWidth() )
752 aSizes.SetWidthSource( _( "user choice" ) );
753 }
754
755 aSizes.SetTrackWidth( trackWidth );
758
759 int viaDiameter = bds.m_ViasMinSize;
760 int viaDrill = bds.m_MinThroughDrill;
761
762 PNS::VIA dummyVia, coupledVia;
763
764 if( aStartItem )
765 {
766 dummyVia.SetNet( aStartItem->Net() );
767 coupledVia.SetNet( m_ruleResolver->DpCoupledNet( aStartItem->Net() ) );
768 }
769
770 if( bds.UseNetClassVia() && aStartItem ) // netclass value
771 {
772 if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_DIAMETER, &dummyVia,
773 nullptr, m_startLayer, &constraint ) )
774 {
775 viaDiameter = std::max( viaDiameter, constraint.m_Value.Opt() );
776 }
777
778 if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_HOLE, &dummyVia,
779 nullptr, m_startLayer, &constraint ) )
780 {
781 viaDrill = std::max( viaDrill, constraint.m_Value.Opt() );
782 }
783 }
784 else
785 {
786 viaDiameter = bds.GetCurrentViaSize();
787 viaDrill = bds.GetCurrentViaDrill();
788 }
789
790 aSizes.SetViaDiameter( viaDiameter );
791 aSizes.SetViaDrill( viaDrill );
792
793 int diffPairWidth = bds.m_TrackMinWidth;
794 int diffPairGap = bds.m_MinClearance;
795 int diffPairViaGap = bds.m_MinClearance;
796
797 aSizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
798 aSizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
799
800 found = false;
801
802 // First try to pick up diff pair width from starting track, if enabled
803 if( bds.m_UseConnectedTrackWidth && aStartItem )
804 found = inheritTrackWidth( aStartItem, &diffPairWidth );
805
806 // Next, pick up gap from netclass, and width also if we didn't get a starting width above
807 if( bds.UseNetClassDiffPair() && aStartItem )
808 {
809 PNS::NET_HANDLE coupledNet = m_ruleResolver->DpCoupledNet( aStartItem->Net() );
810
811 PNS::SEGMENT dummyTrack;
812 dummyTrack.SetEnds( aStartItem->Anchor( 0 ), aStartItem->Anchor( 0 ) );
813 dummyTrack.SetLayer( m_startLayer );
814 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( aStartItem->Net() ) );
815
816 PNS::SEGMENT coupledTrack;
817 dummyTrack.SetEnds( aStartItem->Anchor( 0 ), aStartItem->Anchor( 0 ) );
818 dummyTrack.SetLayer( m_startLayer );
819 dummyTrack.SetNet( static_cast<NETINFO_ITEM*>( coupledNet ) );
820
821 if( !found
822 && m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, &dummyTrack,
823 &coupledTrack, m_startLayer, &constraint ) )
824 {
825 diffPairWidth = std::max( diffPairWidth, constraint.m_Value.Opt() );
826
827 if( diffPairWidth == constraint.m_Value.Opt() )
828 aSizes.SetDiffPairWidthSource( constraint.m_RuleName );
829 }
830
831 if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP, &dummyTrack,
832 &coupledTrack, m_startLayer, &constraint ) )
833 {
834 diffPairGap = std::max( diffPairGap, constraint.m_Value.Opt() );
835 diffPairViaGap = std::max( diffPairViaGap, constraint.m_Value.Opt() );
836
837 if( diffPairGap == constraint.m_Value.Opt() )
838 aSizes.SetDiffPairGapSource( constraint.m_RuleName );
839 }
840 }
841 else
842 {
843 diffPairWidth = bds.GetCurrentDiffPairWidth();
844 diffPairGap = bds.GetCurrentDiffPairGap();
845 diffPairViaGap = bds.GetCurrentDiffPairViaGap();
846
847 aSizes.SetDiffPairWidthSource( _( "user choice" ) );
848 aSizes.SetDiffPairGapSource( _( "user choice" ) );
849 }
850
851 aSizes.SetDiffPairWidth( diffPairWidth );
852 aSizes.SetDiffPairGap( diffPairGap );
853 aSizes.SetDiffPairViaGap( diffPairViaGap );
854 aSizes.SetDiffPairViaGapSameAsTraceGap( false );
855
856 int holeToHoleMin = bds.m_HoleToHoleMin;
857
858 if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, &dummyVia,
859 &dummyVia, UNDEFINED_LAYER, &constraint ) )
860 {
861 holeToHoleMin = constraint.m_Value.Min();
862 }
863
864 aSizes.SetHoleToHole( holeToHoleMin );
865
866 if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, &dummyVia,
867 &coupledVia, UNDEFINED_LAYER, &constraint ) )
868 {
869 holeToHoleMin = constraint.m_Value.Min();
870 }
871
872 aSizes.SetDiffPairHoleToHole( std::max( holeToHoleMin, aSizes.GetHoleToHole() ) );
873
874 return true;
875}
876
877
878int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const
879{
880 if( !m_board || !m_board->GetDesignSettings().m_UseHeightForLengthCalcs )
881 return 0;
882
883 BOARD_STACKUP& stackup = m_board->GetDesignSettings().GetStackupDescriptor();
884
885 return stackup.GetLayerDistance( GetBoardLayerFromPNSLayer( aFirstLayer ),
886 GetBoardLayerFromPNSLayer( aSecondLayer ) );
887}
888
889
891{
892 return m_board->DpCoupledNet( static_cast<NETINFO_ITEM*>( aNet ) );
893}
894
895
897{
898 return m_routerIface->GetNetCode( aNet );
899}
900
901
903{
904 return m_routerIface->GetNetName( aNet );
905}
906
907
909{
910 wxString refName;
911
912 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
913 refName = net->GetNetname();
914
915 wxString dummy1;
916
917 return m_board->MatchDpSuffix( refName, dummy1 );
918}
919
920
922 PNS::NET_HANDLE& aNetN )
923{
924 if( !aItem || !aItem->Net() )
925 return false;
926
927 wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
928 wxString netNameN, netNameCoupled;
929
930 int r = m_board->MatchDpSuffix( netNameP, netNameCoupled );
931
932 if( r == 0 )
933 {
934 return false;
935 }
936 else if( r == 1 )
937 {
938 netNameN = netNameCoupled;
939 }
940 else
941 {
942 netNameN = netNameP;
943 netNameP = netNameCoupled;
944 }
945
946 PNS::NET_HANDLE netInfoP = m_board->FindNet( netNameP );
947 PNS::NET_HANDLE netInfoN = m_board->FindNet( netNameN );
948
949 if( !netInfoP || !netInfoN )
950 return false;
951
952 aNetP = netInfoP;
953 aNetN = netInfoN;
954
955 return true;
956}
957
958
960{
961public:
964 m_iface( aIface ),
965 m_view( nullptr ),
966 m_items( nullptr ),
967 m_depth( 0 )
968 {}
969
975
976 void SetView( KIGFX::VIEW* aView )
977 {
978 Clear();
979 delete m_items;
980 m_items = nullptr;
981 m_view = aView;
982
983 if( m_view == nullptr )
984 return;
985
986 if( m_view->GetGAL() )
987 m_depth = m_view->GetGAL()->GetMinDepth();
988
990 m_items->SetLayer( LAYER_SELECT_OVERLAY ) ;
991 m_view->Add( m_items );
992 }
993
994 void AddPoint( const VECTOR2I& aP, const KIGFX::COLOR4D& aColor, int aSize,
995 const wxString& aName = wxT( "" ),
996 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
997
998 {
1000
1001 sh.SetWidth( 10000 );
1002
1003 sh.Append( aP.x - aSize, aP.y - aSize );
1004 sh.Append( aP.x + aSize, aP.y + aSize );
1005 sh.Append( aP.x, aP.y );
1006 sh.Append( aP.x - aSize, aP.y + aSize );
1007 sh.Append( aP.x + aSize, aP.y - aSize );
1008
1009 AddShape( &sh, aColor, sh.Width(), aName, aSrcLoc );
1010 }
1011
1012 void AddItem( const PNS::ITEM* aItem, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1013 const wxString& aName = wxT( "" ),
1014 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1015 {
1016 if( !m_view || !aItem )
1017 return;
1018
1019 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_iface, m_view );
1020
1021 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
1022 pitem->SetWidth( aOverrideWidth );
1023 pitem->SetDepth( nextDepth() );
1024
1025 m_items->Add( pitem );
1026 m_view->Update( m_items );
1027 }
1028
1029 void AddShape( const BOX2I& aBox, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1030 const wxString& aName = wxT( "" ),
1031 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1032 {
1034 l.SetWidth( aOverrideWidth );
1035
1036 VECTOR2I o = aBox.GetOrigin();
1037 VECTOR2I s = aBox.GetSize();
1038
1039 l.Append( o );
1040 l.Append( o.x + s.x, o.y );
1041 l.Append( o.x + s.x, o.y + s.y );
1042 l.Append( o.x, o.y + s.y );
1043 l.Append( o );
1044
1045 AddShape( &l, aColor, aOverrideWidth, aName, aSrcLoc );
1046 }
1047
1048 void AddShape( const SHAPE* aShape, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
1049 const wxString& aName = wxT( "" ),
1050 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1051 {
1052 if( !m_view || !aShape )
1053 return;
1054
1055 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_iface, m_view );
1056
1057 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
1058 pitem->SetWidth( aOverrideWidth );
1059 pitem->SetDepth( nextDepth() );
1060
1061 m_items->Add( pitem );
1062 m_view->Update( m_items );
1063 }
1064
1065 void Clear() override
1066 {
1067 if( m_view && m_items )
1068 {
1069 m_items->FreeItems();
1070 m_view->Update( m_items );
1071
1072 if( m_view->GetGAL() )
1073 m_depth = m_view->GetGAL()->GetMinDepth();
1074 }
1075 }
1076
1077 virtual void Message( const wxString& msg,
1078 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
1079 {
1080 printf("PNS: %s\n", msg.c_str().AsChar() );
1081 }
1082
1083private:
1084 double nextDepth()
1085 {
1086 // Use different depths so that the transculent shapes won't overwrite each other.
1087
1088 m_depth++;
1089
1090 if( m_depth >= 0 && m_view->GetGAL() )
1091 m_depth = m_view->GetGAL()->GetMinDepth();
1092
1093 return m_depth;
1094 }
1095
1099
1100 double m_depth;
1101};
1102
1103
1108
1109
1111{
1112 m_ruleResolver = nullptr;
1113 m_board = nullptr;
1114 m_world = nullptr;
1115 m_debugDecorator = nullptr;
1116 m_startLayer = -1;
1117}
1118
1119
1121{
1122 m_tool = nullptr;
1123 m_view = nullptr;
1124 m_previewItems = nullptr;
1125 m_commitFlags = 0;
1126}
1127
1128
1134
1135
1137{
1138 if( m_previewItems )
1139 {
1140 m_previewItems->FreeItems();
1141 delete m_previewItems;
1142 }
1143}
1144
1145
1146std::vector<std::unique_ptr<PNS::SOLID>> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1147{
1148 std::vector<std::unique_ptr<PNS::SOLID>> solids;
1149 PNS_LAYER_RANGE layers( 0, aPad->BoardCopperLayerCount() - 1 );
1150 LSEQ lmsk = aPad->GetLayerSet().CuStack();
1151
1152 // ignore non-copper pads except for those with holes
1153 if( lmsk.empty() && aPad->GetDrillSize().x == 0 )
1154 return solids;
1155
1156 switch( aPad->GetAttribute() )
1157 {
1158 case PAD_ATTRIB::PTH:
1159 case PAD_ATTRIB::NPTH:
1160 break;
1161
1162 case PAD_ATTRIB::CONN:
1163 case PAD_ATTRIB::SMD:
1164 {
1165 bool is_copper = false;
1166
1167 if( !lmsk.empty() && aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1168 {
1169 layers = SetLayersFromPCBNew( lmsk.front(), lmsk.front() );
1170 is_copper = true;
1171 }
1172
1173 if( !is_copper )
1174 return solids;
1175
1176 break;
1177 }
1178
1179 default:
1180 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1181 return solids;
1182 }
1183
1184 auto makeSolidFromPadLayer =
1185 [&]( PCB_LAYER_ID aLayer )
1186 {
1187 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1188
1189 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1190 solid->SetRoutable( false );
1191
1192 if( aPad->Padstack().Mode() == PADSTACK::MODE::CUSTOM )
1193 {
1194 solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
1195 }
1196 else if( aPad->Padstack().Mode() == PADSTACK::MODE::FRONT_INNER_BACK )
1197 {
1198 if( aLayer == F_Cu || aLayer == B_Cu )
1199 solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
1200 else
1201 solid->SetLayers( PNS_LAYER_RANGE( 1, aPad->BoardCopperLayerCount() - 2 ) );
1202 }
1203 else
1204 {
1205 solid->SetLayers( layers );
1206 }
1207
1208 solid->SetNet( aPad->GetNet() );
1209 solid->SetParent( aPad );
1210 solid->SetPadToDie( aPad->GetPadToDieLength() );
1211 solid->SetPadToDieDelay( aPad->GetPadToDieDelay() );
1212 solid->SetOrientation( aPad->GetOrientation() );
1213
1214 if( aPad->IsFreePad() )
1215 solid->SetIsFreePad();
1216
1217 VECTOR2I wx_c = aPad->ShapePos( aLayer );
1218 VECTOR2I offset = aPad->GetOffset( aLayer );
1219
1220 VECTOR2I c( wx_c.x, wx_c.y );
1221
1222 RotatePoint( offset, aPad->GetOrientation() );
1223
1224 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1225 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1226
1227 if( aPad->GetDrillSize().x > 0 )
1228 {
1229 solid->SetHole( new PNS::HOLE( aPad->GetEffectiveHoleShape()->Clone() ) );
1230 solid->Hole()->SetLayers( PNS_LAYER_RANGE( 0, aPad->BoardCopperLayerCount() - 1 ) );
1231 }
1232
1233 // We generate a single SOLID for a pad, so we have to treat it as ALWAYS_FLASHED and
1234 // then perform layer-specific flashing tests internally.
1235 const std::shared_ptr<SHAPE>& shape =
1237
1238 if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 )
1239 {
1240 std::vector<const SHAPE*> subshapes;
1241 shape->GetIndexableSubshapes( subshapes );
1242
1243 solid->SetShape( subshapes[0]->Clone() );
1244 }
1245 // For anything that's not a single shape we use a polygon. Multiple shapes have a tendency
1246 // to confuse the hull generator. https://gitlab.com/kicad/code/kicad/-/issues/15553
1247 else
1248 {
1249 const std::shared_ptr<SHAPE_POLY_SET>& poly =
1250 aPad->GetEffectivePolygon( aLayer, ERROR_OUTSIDE );
1251
1252 if( poly->OutlineCount() )
1253 solid->SetShape( new SHAPE_SIMPLE( poly->Outline( 0 ) ) );
1254 }
1255
1256 solids.emplace_back( std::move( solid ) );
1257 };
1258
1259 aPad->Padstack().ForEachUniqueLayer( makeSolidFromPadLayer );
1260
1261 return solids;
1262}
1263
1264
1265std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1266{
1267 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1268 aTrack->GetNet() );
1269
1270 segment->SetWidth( aTrack->GetWidth() );
1271 segment->SetLayer( GetPNSLayerFromBoardLayer( aTrack->GetLayer() ) );
1272 segment->SetParent( aTrack );
1273
1274 if( aTrack->IsLocked() )
1275 segment->Mark( PNS::MK_LOCKED );
1276
1277 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aTrack->GetParentGroup() ) )
1278 {
1279 if( !generator->HasFlag( IN_EDIT ) )
1280 segment->Mark( PNS::MK_LOCKED );
1281 }
1282
1283 return segment;
1284}
1285
1286
1287std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1288{
1289 auto arc = std::make_unique<PNS::ARC>( SHAPE_ARC( aArc->GetStart(), aArc->GetMid(),
1290 aArc->GetEnd(), aArc->GetWidth() ),
1291 aArc->GetNet() );
1292
1293 arc->SetLayer( GetPNSLayerFromBoardLayer( aArc->GetLayer() ) );
1294 arc->SetParent( aArc );
1295
1296 if( aArc->IsLocked() )
1297 arc->Mark( PNS::MK_LOCKED );
1298
1299 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aArc->GetParentGroup() ) )
1300 {
1301 if( !generator->HasFlag( IN_EDIT ) )
1302 arc->Mark( PNS::MK_LOCKED );
1303 }
1304
1305 return arc;
1306}
1307
1308
1309std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1310{
1311 PCB_LAYER_ID top, bottom;
1312 aVia->LayerPair( &top, &bottom );
1313
1314 /*
1315 * NOTE about PNS via padstacks:
1316 *
1317 * PNS::VIA has no knowledge about how many layers are in the board, and there is no fixed
1318 * reference to the "back layer" in the PNS. That means that there is no way for a VIA to know
1319 * the difference between its bottom layer and the bottom layer of the overall board (i.e. if
1320 * the via is a blind/buried via). For this reason, PNS::VIA::STACK_MODE::FRONT_INNER_BACK
1321 * cannot be used for blind/buried vias. This mode will always assume that the via's top layer
1322 * is the "front" layer and the via's bottom layer is the "back" layer, but from KiCad's point
1323 * of view, at least at the moment, front/inner/back padstack mode is board-scoped, not
1324 * via-scoped, so a buried via would only use the inner layer size even if its padstack mode is
1325 * set to PADSTACK::MODE::FRONT_INNER_BACK and different sizes are defined for front or back.
1326 * For this kind of via, the PNS VIA stack mode will be set to NORMAL because effectively it has
1327 * the same size on every layer it exists on.
1328 */
1329
1330 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1331 SetLayersFromPCBNew( aVia->TopLayer(), aVia->BottomLayer() ),
1332 0,
1333 aVia->GetDrillValue(),
1334 aVia->GetNet(),
1335 aVia->GetViaType() );
1336 via->SetUnconnectedLayerMode( aVia->Padstack().UnconnectedLayerMode() );
1337
1338 auto syncDiameter =
1339 [&]( PCB_LAYER_ID aLayer )
1340 {
1341 via->SetDiameter( GetPNSLayerFromBoardLayer( aLayer ), aVia->GetWidth( aLayer ) );
1342 };
1343
1344 switch( aVia->Padstack().Mode() )
1345 {
1347 via->SetDiameter( 0, aVia->GetWidth( PADSTACK::ALL_LAYERS ) );
1348 break;
1349
1351 if( aVia->GetViaType() == VIATYPE::BLIND || aVia->GetViaType() == VIATYPE::BURIED )
1352 {
1353 via->SetDiameter( 0, aVia->GetWidth( PADSTACK::INNER_LAYERS ) );
1354 }
1355 else
1356 {
1358 aVia->Padstack().ForEachUniqueLayer( syncDiameter );
1359 }
1360
1361 break;
1362
1364 via->SetStackMode( PNS::VIA::STACK_MODE::CUSTOM );
1365 aVia->Padstack().ForEachUniqueLayer( syncDiameter );
1366 }
1367
1368 via->SetParent( aVia );
1369
1370 if( aVia->IsLocked() )
1371 via->Mark( PNS::MK_LOCKED );
1372
1373 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aVia->GetParentGroup() ) )
1374 {
1375 if( !generator->HasFlag( IN_EDIT ) )
1376 via->Mark( PNS::MK_LOCKED );
1377 }
1378
1379 via->SetIsFree( aVia->GetIsFree() );
1380 via->SetHole( PNS::HOLE::MakeCircularHole( aVia->GetPosition(),
1381 aVia->GetDrillValue() / 2,
1382 SetLayersFromPCBNew( aVia->TopLayer(), aVia->BottomLayer() ) ) );
1383
1384 PCB_LAYER_ID primaryStart = aVia->GetPrimaryDrillStartLayer();
1385 PCB_LAYER_ID primaryEnd = aVia->GetPrimaryDrillEndLayer();
1386
1387 if( primaryStart != UNDEFINED_LAYER && primaryEnd != UNDEFINED_LAYER )
1388 via->SetHoleLayers( SetLayersFromPCBNew( primaryStart, primaryEnd ) );
1389 else
1390 via->SetHoleLayers( SetLayersFromPCBNew( aVia->TopLayer(), aVia->BottomLayer() ) );
1391
1392 via->SetHolePostMachining( aVia->GetFrontPostMachining() );
1393 via->SetSecondaryDrill( aVia->GetSecondaryDrillSize() );
1394
1395 std::optional<PNS_LAYER_RANGE> secondaryLayers;
1396
1399 {
1400 secondaryLayers = SetLayersFromPCBNew( aVia->GetSecondaryDrillStartLayer(),
1401 aVia->GetSecondaryDrillEndLayer() );
1402 }
1403
1404 via->SetSecondaryHoleLayers( secondaryLayers );
1405 via->SetSecondaryHolePostMachining( std::nullopt );
1406
1407 return via;
1408}
1409
1410
1411bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1412{
1413 static wxString msg;
1414 SHAPE_POLY_SET* poly;
1415
1416 if( !aZone->GetIsRuleArea() || !aZone->HasKeepoutParametersSet() )
1417 return false;
1418
1419 LSET layers = aZone->GetLayerSet();
1420
1421 poly = aZone->Outline();
1422 poly->CacheTriangulation( false );
1423
1424 if( !poly->IsTriangulationUpToDate() )
1425 {
1426 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1427 msg.Printf( _( "%s is malformed." ), aZone->GetItemDescription( &unitsProvider, true ) );
1428
1429 KIDIALOG dlg( nullptr, msg, KIDIALOG::KD_WARNING );
1430 dlg.ShowDetailedText( _( "This zone cannot be handled by the router.\n"
1431 "Please verify it is not a self-intersecting polygon." ) );
1432 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1433 dlg.ShowModal();
1434
1435 return false;
1436 }
1437
1438 for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, m_board->GetCopperLayerCount() ) )
1439 {
1440 if( !layers[ layer ] )
1441 continue;
1442
1443 for( int polyId = 0; polyId < poly->TriangulatedPolyCount(); polyId++ )
1444 {
1445 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( polyId );
1446
1447 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1448 {
1449 VECTOR2I a, b, c;
1450 tri->GetTriangle( i, a, b, c );
1451 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1452
1453 triShape->Append( a );
1454 triShape->Append( b );
1455 triShape->Append( c );
1456
1457 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1458
1459 solid->SetLayer( GetPNSLayerFromBoardLayer( layer ) );
1460 solid->SetNet( nullptr );
1461 solid->SetParent( aZone );
1462 solid->SetShape( triShape );
1463 solid->SetIsCompoundShapePrimitive();
1464 solid->SetRoutable( false );
1465
1466 aWorld->Add( std::move( solid ) );
1467 }
1468 }
1469 }
1470
1471 return true;
1472}
1473
1474
1476{
1477 if( !IsKicadCopperLayer( aLayer ) )
1478 return false;
1479
1480 if( aItem->Type() == PCB_FIELD_T && !static_cast<PCB_FIELD*>( aItem )->IsVisible() )
1481 return false;
1482
1483 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1484 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1485
1486 solid->SetLayer( GetPNSLayerFromBoardLayer( aLayer ) );
1487 solid->SetNet( nullptr );
1488 solid->SetParent( aItem );
1489 solid->SetShape( shape ); // takes ownership
1490 solid->SetRoutable( false );
1491
1492 SHAPE_POLY_SET cornerBuffer;
1493
1494 aItem->TransformShapeToPolygon( cornerBuffer, aItem->GetLayer(), 0, aItem->GetMaxError(), ERROR_OUTSIDE );
1495
1496 cornerBuffer.Simplify();
1497
1498 if( !cornerBuffer.OutlineCount() )
1499 return false;
1500
1501 for( const VECTOR2I& pt : cornerBuffer.Outline( 0 ).CPoints() )
1502 shape->Append( pt );
1503
1504 aWorld->Add( std::move( solid ) );
1505
1506 return true;
1507}
1508
1509
1511{
1512 if( aItem->GetLayer() == Edge_Cuts
1513 || aItem->GetLayer() == Margin
1514 || IsKicadCopperLayer( aItem->GetLayer() ) )
1515 {
1516 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1517
1518 for( SHAPE* shape : shapes )
1519 {
1520 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1521
1522 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1523 {
1524 solid->SetLayers( PNS_LAYER_RANGE( 0, m_board->GetCopperLayerCount() - 1 ) );
1525 solid->SetRoutable( false );
1526 }
1527 else
1528 {
1529 solid->SetLayer( GetPNSLayerFromBoardLayer( aItem->GetLayer() ) );
1530 solid->SetRoutable( aItem->Type() != PCB_TABLECELL_T );
1531 }
1532
1533 if( aItem->GetLayer() == Edge_Cuts )
1534 {
1535 switch( shape->Type() )
1536 {
1537 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1538 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1539 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1540 default: /* remaining shapes don't have width */ break;
1541 }
1542 }
1543
1544 solid->SetAnchorPoints( aItem->GetConnectionPoints() );
1545 solid->SetNet( aItem->GetNet() );
1546 solid->SetParent( aItem );
1547 solid->SetShape( shape ); // takes ownership
1548
1549 if( shapes.size() > 1 )
1550 solid->SetIsCompoundShapePrimitive();
1551
1552 aWorld->Add( std::move( solid ) );
1553 }
1554
1555 return true;
1556 }
1557
1558 return false;
1559}
1560
1561
1563{
1564 if( IsKicadCopperLayer( aBarcode->GetLayer() ) )
1565 {
1566 SHAPE_POLY_SET cornerBuffer;
1567
1568 aBarcode->GetBoundingHull( cornerBuffer, aBarcode->GetLayer(), 0, aBarcode->GetMaxError(), ERROR_OUTSIDE );
1569
1570 if( !cornerBuffer.OutlineCount() )
1571 return false;
1572
1573 for( int ii = 0; ii < cornerBuffer.OutlineCount(); ++ii )
1574 {
1575 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1576 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1577
1578 solid->SetLayer( GetPNSLayerFromBoardLayer( aBarcode->GetLayer() ) );
1579 solid->SetNet( nullptr );
1580 solid->SetParent( aBarcode );
1581 solid->SetShape( shape ); // takes ownership
1582 solid->SetRoutable( false );
1583
1584 for( const VECTOR2I& pt : cornerBuffer.Outline( ii ).CPoints() )
1585 shape->Append( pt );
1586
1587 aWorld->Add( std::move( solid ) );
1588 }
1589
1590 return true;
1591 }
1592
1593 return false;
1594}
1595
1596
1598{
1599 m_board = aBoard;
1600 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1601}
1602
1603
1605{
1606 return ::IsCopperLayer( GetBoardLayerFromPNSLayer( aPNSLayer ) );
1607}
1608
1609
1610
1612{
1613 return ::IsCopperLayer( aKicadLayer );
1614}
1615
1616
1618{
1619 if( !m_view )
1620 return false;
1621
1622 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1623 {
1624 if( m_view->IsLayerVisible( GetBoardLayerFromPNSLayer( i ) ) )
1625 return true;
1626 }
1627
1628 return false;
1629}
1630
1631
1632bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1633{
1635 if( aLayer < 0 )
1636 return true;
1637
1638 if( aItem->Parent() )
1639 {
1640 switch( aItem->Parent()->Type() )
1641 {
1642 case PCB_VIA_T:
1643 {
1644 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1645
1646 return via->FlashLayer( GetBoardLayerFromPNSLayer( aLayer ) );
1647 }
1648
1649 case PCB_PAD_T:
1650 {
1651 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1652
1653 return pad->FlashLayer( GetBoardLayerFromPNSLayer( aLayer ) );
1654 }
1655
1656 default:
1657 break;
1658 }
1659 }
1660
1661 if( aItem->OfKind( PNS::ITEM::VIA_T ) )
1662 return static_cast<const PNS::VIA*>( aItem )->ConnectsLayer( aLayer );
1663
1664 return aItem->Layers().Overlaps( aLayer );
1665}
1666
1667
1669 const PNS_LAYER_RANGE& aLayer ) const
1670{
1671 PNS_LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
1672
1673 if( aItem->Parent() )
1674 {
1675 switch( aItem->Parent()->Type() )
1676 {
1677 case PCB_VIA_T:
1678 {
1679 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1680
1681 for( int layer = test.Start(); layer <= test.End(); ++layer )
1682 {
1683 if( via->FlashLayer( GetBoardLayerFromPNSLayer( layer ) ) )
1684 return true;
1685 }
1686
1687 return false;
1688 }
1689
1690 case PCB_PAD_T:
1691 {
1692 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1693
1694 for( int layer = test.Start(); layer <= test.End(); ++layer )
1695 {
1696 if( pad->FlashLayer( GetBoardLayerFromPNSLayer( layer ) ) )
1697 return true;
1698 }
1699
1700 return false;
1701 }
1702
1703 default:
1704 break;
1705 }
1706 }
1707
1708 if( aItem->OfKind( PNS::ITEM::VIA_T ) )
1709 {
1710 const PNS::VIA* via = static_cast<const PNS::VIA*>( aItem );
1711
1712 for( int layer = test.Start(); layer <= test.End(); ++layer )
1713 {
1714 if( via->ConnectsLayer( layer ) )
1715 return true;
1716 }
1717
1718 return false;
1719 }
1720
1721 return test.Start() <= test.End();
1722}
1723
1724
1726{
1727 // by default, all items are visible (new ones created by the router have parent == NULL
1728 // as they have not been committed yet to the BOARD)
1729 if( !m_view || !aItem->Parent() )
1730 return true;
1731
1732 BOARD_ITEM* item = aItem->Parent();
1733 bool isOnVisibleLayer = true;
1734 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1735
1736 if( settings->GetHighContrast() )
1737 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1738
1739 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1740 {
1741 for( PCB_LAYER_ID layer : item->GetLayerSet() )
1742 {
1743 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1744 return true;
1745 }
1746 }
1747
1748 // Items hidden in the router are not hidden on the board
1749 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1750 return true;
1751
1752 return false;
1753}
1754
1755
1757{
1758 if( !m_board )
1759 {
1760 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1761 return;
1762 }
1763
1764 int worstClearance = m_board->GetMaxClearanceValue();
1765
1766 m_world = aWorld;
1767
1768 for( BOARD_ITEM* gitem : m_board->Drawings() )
1769 {
1770 switch( gitem->Type() )
1771 {
1772 case PCB_SHAPE_T:
1773 case PCB_TEXTBOX_T:
1774 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1775 break;
1776
1777 case PCB_TEXT_T:
1778 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1779 break;
1780
1781 case PCB_TABLE_T:
1782 syncTextItem( aWorld, static_cast<PCB_TABLE*>( gitem ), gitem->GetLayer() );
1783 break;
1784
1785 case PCB_BARCODE_T:
1786 syncBarcode( aWorld, static_cast<PCB_BARCODE*>( gitem ) );
1787 break;
1788
1789 case PCB_DIM_ALIGNED_T: // ignore only if not on a copper layer
1790 case PCB_DIM_CENTER_T:
1791 case PCB_DIM_RADIAL_T:
1793 case PCB_DIM_LEADER_T:
1794 if( gitem->IsOnCopperLayer() )
1795 UNIMPLEMENTED_FOR( wxString::Format( wxT( "%s on copper layer" ), gitem->GetClass() ) );
1796 break;
1797
1798 case PCB_REFERENCE_IMAGE_T: // ignore
1799 case PCB_TARGET_T:
1800 break;
1801
1802 default:
1803 UNIMPLEMENTED_FOR( gitem->GetClass() );
1804 break;
1805 }
1806 }
1807
1808 SHAPE_POLY_SET buffer;
1809 SHAPE_POLY_SET* boardOutline = nullptr;
1810
1811 if( m_board->GetBoardPolygonOutlines( buffer, true ) )
1812 boardOutline = &buffer;
1813
1814 for( ZONE* zone : m_board->Zones() )
1815 {
1816 syncZone( aWorld, zone, boardOutline );
1817 }
1818
1819 for( FOOTPRINT* footprint : m_board->Footprints() )
1820 {
1821 for( PAD* pad : footprint->Pads() )
1822 {
1823 std::vector<std::unique_ptr<PNS::SOLID>> solids = syncPad( pad );
1824
1825 for( std::unique_ptr<PNS::SOLID>& solid : solids )
1826 aWorld->Add( std::move( solid ) );
1827
1828 std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
1829
1830 if( clearanceOverride.has_value() )
1831 worstClearance = std::max( worstClearance, clearanceOverride.value() );
1832
1833 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1834 {
1835 std::unique_ptr<SHAPE> hole;
1836 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1837 aWorld->AddEdgeExclusion( std::move( hole ) );
1838 }
1839 }
1840
1841 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1842 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1843
1844 for( ZONE* zone : footprint->Zones() )
1845 syncZone( aWorld, zone, boardOutline );
1846
1847 for( PCB_FIELD* field : footprint->GetFields() )
1848 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1849
1850 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1851 {
1852 switch( item->Type() )
1853 {
1854 case PCB_SHAPE_T:
1855 case PCB_TEXTBOX_T:
1856 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1857 break;
1858
1859 case PCB_TEXT_T:
1860 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1861 break;
1862
1863 case PCB_TABLE_T:
1864 syncTextItem( aWorld, static_cast<PCB_TABLE*>( item ), item->GetLayer() );
1865 break;
1866
1867 case PCB_BARCODE_T:
1868 syncBarcode( aWorld, static_cast<PCB_BARCODE*>( item ) );
1869 break;
1870
1871 case PCB_DIM_ALIGNED_T: // ignore only if not on a copper layer
1872 case PCB_DIM_CENTER_T:
1873 case PCB_DIM_RADIAL_T:
1875 case PCB_DIM_LEADER_T:
1877 if( item->IsOnCopperLayer() )
1878 UNIMPLEMENTED_FOR( wxString::Format( wxT( "%s on copper layer" ), item->GetClass() ) );
1879
1880 break;
1881
1882 default:
1883 UNIMPLEMENTED_FOR( item->GetClass() );
1884 break;
1885 }
1886 }
1887 }
1888
1889 for( PCB_TRACK* t : m_board->Tracks() )
1890 {
1891 KICAD_T type = t->Type();
1892
1893 if( type == PCB_TRACE_T )
1894 {
1895 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1896 aWorld->Add( std::move( segment ), true );
1897 }
1898 else if( type == PCB_ARC_T )
1899 {
1900 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1901 aWorld->Add( std::move( arc ), true );
1902 }
1903 else if( type == PCB_VIA_T )
1904 {
1905 if( std::unique_ptr<PNS::VIA> via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1906 aWorld->Add( std::move( via ) );
1907 }
1908 }
1909
1910 // NB: if this were ever to become a long-lived object we would need to dirty its
1911 // clearance cache here....
1912 delete m_ruleResolver;
1914
1916 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1917}
1918
1919
1921{
1922 for( BOARD_ITEM* item : m_hiddenItems )
1923 m_view->SetVisible( item, true );
1924
1925 m_hiddenItems.clear();
1926
1927 if( m_previewItems )
1928 {
1929 m_previewItems->FreeItems();
1930 m_view->Update( m_previewItems );
1931 }
1932
1933 if( m_debugDecorator )
1934 m_debugDecorator->Clear();
1935}
1936
1937
1942
1943
1944void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, int aFlags )
1945{
1946 if( aItem->IsVirtual() )
1947 return;
1948
1949 if( ZONE* zone = dynamic_cast<ZONE*>( aItem->Parent() ) )
1950 {
1951 if( zone->GetIsRuleArea() )
1952 aFlags |= PNS_SEMI_SOLID;
1953 }
1954
1955 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, this, m_view, aFlags );
1956
1957 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1959 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1960
1961 if( aClearance >= 0 )
1962 {
1963 pitem->SetClearance( aClearance );
1964
1965 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1966
1967 switch( settings->m_Display.m_TrackClearance )
1968 {
1971 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1972 break;
1973
1975 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1976 break;
1977
1978 case SHOW_WHILE_ROUTING:
1979 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1980 break;
1981
1982 default:
1983 pitem->ShowClearance( false );
1984 break;
1985 }
1986 }
1987
1988 m_previewItems->Add( pitem );
1989 m_view->Update( m_previewItems );
1990}
1991
1992
1993void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1994{
1995 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, this, m_view );
1997
1998 COLOR4D color;
1999
2000 if( aImportance >= 1 )
2001 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
2002 else if( aImportance == 0 )
2003 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
2004
2005 pitem->SetColor( color );
2006
2007 m_previewItems->Add( pitem );
2008 m_view->Update( m_previewItems );
2009}
2010
2011
2013{
2014 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, this, m_view );
2015
2016 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
2017 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
2018 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
2019 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
2020 COLOR4D color = defaultColor;
2021
2022 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
2023 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
2024 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
2025 int netCode = -1;
2026
2027 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
2028 netCode = net->GetNetCode();
2029
2030 const NETCLASS* nc = nullptr;
2031 const NET_SETTINGS* netSettings = connectivity->GetNetSettings();
2032
2033 if( connectivity->HasNetNameForNetCode( netCode ) )
2034 {
2035 const wxString& netName = connectivity->GetNetNameForNetCode( netCode );
2036
2037 if( netSettings && netSettings->HasEffectiveNetClass( netName ) )
2038 nc = netSettings->GetCachedEffectiveNetClass( netName ).get();
2039 }
2040
2041 if( colorByNet && netColors.count( netCode ) )
2042 color = netColors.at( netCode );
2043 else if( colorByNet && nc && nc->HasPcbColor() )
2044 color = nc->GetPcbColor();
2045 else
2046 color = defaultColor;
2047
2048 if( color == COLOR4D::UNSPECIFIED )
2049 color = defaultColor;
2050
2051 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
2052
2053 m_previewItems->Add( pitem );
2054 m_view->Update( m_previewItems );
2055}
2056
2057
2059{
2060 BOARD_ITEM* parent = aItem->Parent();
2061
2062 if( parent )
2063 {
2064 if( m_view->IsVisible( parent ) )
2065 m_hiddenItems.insert( parent );
2066
2067 m_view->SetVisible( parent, false );
2068 m_view->Update( parent, KIGFX::APPEARANCE );
2069
2070 for( ZONE* td : m_board->Zones() )
2071 {
2072 if( td->IsTeardropArea()
2073 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
2074 && td->Outline()->Collide( aItem->Shape( td->GetLayer() ) ) )
2075 {
2076 m_view->SetVisible( td, false );
2077 m_view->Update( td, KIGFX::APPEARANCE );
2078 }
2079 }
2080 }
2081}
2082
2083
2087
2088
2090{
2091 BOARD_ITEM* parent = aItem->Parent();
2092
2093 if( aItem->OfKind( PNS::ITEM::SOLID_T ) && parent->Type() == PCB_PAD_T )
2094 {
2095 PAD* pad = static_cast<PAD*>( parent );
2096 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2097
2098 m_fpOffsets[ pad ].p_old = pos;
2099 return;
2100 }
2101
2102 if( parent )
2103 {
2104 if( EDA_GROUP* group = parent->GetParentGroup() )
2105 m_itemGroups[parent] = group;
2106
2107 m_commit->Remove( parent );
2108 }
2109}
2110
2111
2115
2116
2118{
2119 BOARD_ITEM* board_item = aItem->Parent();
2120
2121 switch( aItem->Kind() )
2122 {
2123 case PNS::ITEM::ARC_T:
2124 {
2125 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
2126 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
2127 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape( -1 ) );
2128
2129 m_commit->Modify( arc_board );
2130
2131 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
2132 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
2133 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
2134 arc_board->SetWidth( arc->Width() );
2135 break;
2136 }
2137
2139 {
2140 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
2141 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
2142 const SEG& s = seg->Seg();
2143
2144 m_commit->Modify( track );
2145
2146 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
2147 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
2148 track->SetWidth( seg->Width() );
2149 break;
2150 }
2151
2152 case PNS::ITEM::VIA_T:
2153 {
2154 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
2155 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
2156
2157 m_commit->Modify( via_board );
2158
2159 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
2160 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter( 0 ) );
2161 via_board->SetDrill( via->Drill() );
2162 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
2163 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
2164 via_board->Padstack().SetUnconnectedLayerMode( via->UnconnectedLayerMode() );
2165 via_board->SetIsFree( via->IsFree() );
2166 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
2167 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
2168
2169 PNS_LAYER_RANGE holeLayers = via->HoleLayers();
2170
2171 if( holeLayers.Start() >= 0 && holeLayers.End() >= 0 )
2172 {
2173 via_board->SetPrimaryDrillStartLayer( GetBoardLayerFromPNSLayer( holeLayers.Start() ) );
2174 via_board->SetPrimaryDrillEndLayer( GetBoardLayerFromPNSLayer( holeLayers.End() ) );
2175 }
2176
2177 via_board->SetFrontPostMachining( via->HolePostMachining() );
2178 via_board->SetSecondaryDrillSize( via->SecondaryDrill() );
2179
2180 if( std::optional<PNS_LAYER_RANGE> secondaryLayers = via->SecondaryHoleLayers() )
2181 {
2182 via_board->SetSecondaryDrillStartLayer(
2183 GetBoardLayerFromPNSLayer( secondaryLayers->Start() ) );
2184 via_board->SetSecondaryDrillEndLayer(
2185 GetBoardLayerFromPNSLayer( secondaryLayers->End() ) );
2186 }
2187 else
2188 {
2191 }
2192
2193 break;
2194 }
2195
2196 case PNS::ITEM::SOLID_T:
2197 {
2198 if( aItem->Parent()->Type() == PCB_PAD_T )
2199 {
2200 PAD* pad = static_cast<PAD*>( aItem->Parent() );
2201 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2202
2203 // Don't add to commit; we'll add the parent footprints when processing the m_fpOffsets
2204
2205 m_fpOffsets[pad].p_old = pad->GetPosition();
2206 m_fpOffsets[pad].p_new = pos;
2207 }
2208 break;
2209 }
2210
2211 default:
2212 m_commit->Modify( aItem->Parent() );
2213 break;
2214 }
2215}
2216
2217
2219{
2220 modifyBoardItem( aItem );
2221}
2222
2223
2225{
2226}
2227
2228
2230{
2231 BOARD_CONNECTED_ITEM* newBoardItem = nullptr;
2232 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem->Net() );
2233
2234 if( !net )
2236
2237 switch( aItem->Kind() )
2238 {
2239 case PNS::ITEM::ARC_T:
2240 {
2241 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
2242 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape( -1 ) ) );
2243 new_arc->SetWidth( arc->Width() );
2244 new_arc->SetLayer( GetBoardLayerFromPNSLayer( arc->Layers().Start() ) );
2245 new_arc->SetNet( net );
2246
2247 if( aItem->GetSourceItem() && aItem->GetSourceItem()->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
2248 {
2249 PCB_TRACK* sourceTrack = static_cast<PCB_TRACK*>( aItem->GetSourceItem() );
2250 new_arc->SetHasSolderMask( sourceTrack->HasSolderMask() );
2251 new_arc->SetLocalSolderMaskMargin( sourceTrack->GetLocalSolderMaskMargin() );
2252 }
2253
2254 newBoardItem = new_arc;
2255 break;
2256 }
2257
2259 {
2260 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
2261 PCB_TRACK* track = new PCB_TRACK( m_board );
2262 const SEG& s = seg->Seg();
2263 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
2264 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
2265 track->SetWidth( seg->Width() );
2266 track->SetLayer( GetBoardLayerFromPNSLayer( seg->Layers().Start() ) );
2267 track->SetNet( net );
2268
2269 if( aItem->GetSourceItem() && aItem->GetSourceItem()->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
2270 {
2271 PCB_TRACK* sourceTrack = static_cast<PCB_TRACK*>( aItem->GetSourceItem() );
2272 track->SetHasSolderMask( sourceTrack->HasSolderMask() );
2273 track->SetLocalSolderMaskMargin( sourceTrack->GetLocalSolderMaskMargin() );
2274 }
2275
2276 newBoardItem = track;
2277 break;
2278 }
2279
2280 case PNS::ITEM::VIA_T:
2281 {
2282 PCB_VIA* via_board = new PCB_VIA( m_board );
2283 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
2284 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
2285 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter( 0 ) );
2286 via_board->SetDrill( via->Drill() );
2287 via_board->SetNet( net );
2288 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
2289 via_board->Padstack().SetUnconnectedLayerMode( via->UnconnectedLayerMode() );
2290 via_board->SetIsFree( via->IsFree() );
2291 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
2292 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
2293
2294 PNS_LAYER_RANGE holeLayers = via->HoleLayers();
2295
2296 if( holeLayers.Start() >= 0 && holeLayers.End() >= 0 )
2297 {
2298 via_board->SetPrimaryDrillStartLayer( GetBoardLayerFromPNSLayer( holeLayers.Start() ) );
2299 via_board->SetPrimaryDrillEndLayer( GetBoardLayerFromPNSLayer( holeLayers.End() ) );
2300 }
2301
2302 via_board->SetFrontPostMachining( via->HolePostMachining() );
2303 via_board->SetSecondaryDrillSize( via->SecondaryDrill() );
2304
2305 if( std::optional<PNS_LAYER_RANGE> secondaryLayers = via->SecondaryHoleLayers() )
2306 {
2307 via_board->SetSecondaryDrillStartLayer(
2308 GetBoardLayerFromPNSLayer( secondaryLayers->Start() ) );
2309 via_board->SetSecondaryDrillEndLayer(
2310 GetBoardLayerFromPNSLayer( secondaryLayers->End() ) );
2311 }
2312 else
2313 {
2316 }
2317
2318 if( aItem->GetSourceItem() && aItem->GetSourceItem()->Type() == PCB_VIA_T )
2319 {
2320 PCB_VIA* sourceVia = static_cast<PCB_VIA*>( aItem->GetSourceItem() );
2321 via_board->SetFrontTentingMode( sourceVia->GetFrontTentingMode() );
2322 via_board->SetBackTentingMode( sourceVia->GetBackTentingMode() );
2323 }
2324
2325 newBoardItem = via_board;
2326 break;
2327 }
2328
2329 case PNS::ITEM::SOLID_T:
2330 {
2331 PAD* pad = static_cast<PAD*>( aItem->Parent() );
2332 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2333
2334 m_fpOffsets[pad].p_new = pos;
2335 return nullptr;
2336 }
2337
2338 default:
2339 return nullptr;
2340 }
2341
2342 if( net->GetNetCode() <= 0 )
2343 {
2344 NETINFO_ITEM* newNetInfo = newBoardItem->GetNet();
2345
2346 newNetInfo->SetParent( m_board );
2347 newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->GetDefaultNetclass() );
2348 }
2349
2350 if( newBoardItem )
2351 {
2352 if( BOARD_ITEM* src = aItem->GetSourceItem() )
2353 {
2354 if( m_itemGroups.contains( src ) )
2355 m_replacementMap[src].push_back( newBoardItem );
2356 }
2357 else
2358 {
2359 // This is a new item, which goes in the entered group (if any)
2360 m_replacementMap[ENTERED_GROUP_MAGIC_NUMBER].push_back( newBoardItem );
2361 }
2362 }
2363
2364 return newBoardItem;
2365}
2366
2367
2369{
2370 BOARD_CONNECTED_ITEM* boardItem = createBoardItem( aItem );
2371
2372 if( boardItem )
2373 {
2374 aItem->SetParent( boardItem );
2375 boardItem->ClearFlags();
2376
2377 m_commit->Add( boardItem );
2378 }
2379}
2380
2381
2383{
2384 PCB_SELECTION_TOOL* selTool = m_tool->GetManager()->GetTool<PCB_SELECTION_TOOL>();
2385 std::set<FOOTPRINT*> processedFootprints;
2386
2387 EraseView();
2388
2389 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
2390 {
2391 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
2392 FOOTPRINT* footprint = pad->GetParentFootprint();
2393 VECTOR2I p_orig = footprint->GetPosition();
2394 VECTOR2I p_new = p_orig + offset;
2395
2396 if( processedFootprints.find( footprint ) != processedFootprints.end() )
2397 continue;
2398
2399 processedFootprints.insert( footprint );
2400 m_commit->Modify( footprint );
2401 footprint->SetPosition( p_new );
2402 }
2403
2404 m_fpOffsets.clear();
2405
2406 for( const auto& [ src, items ] : m_replacementMap )
2407 {
2408 EDA_GROUP* group = nullptr;
2409
2410 if( src == ENTERED_GROUP_MAGIC_NUMBER )
2411 group = selTool ? selTool->GetEnteredGroup() : nullptr;
2412 else if( auto it = m_itemGroups.find( src ); it != m_itemGroups.end() )
2413 group = it->second;
2414
2415 if( group )
2416 {
2417 m_commit->Modify( group->AsEdaItem(), nullptr, RECURSE_MODE::NO_RECURSE );
2418
2419 for( BOARD_ITEM* bi : items )
2420 group->AddItem( bi );
2421 }
2422 }
2423
2424 m_itemGroups.clear();
2425 m_replacementMap.clear();
2426
2427 m_commit->Push( _( "Routing" ), m_commitFlags | SKIP_ENTERED_GROUP );
2428 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2429}
2430
2431
2433{
2434 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
2435}
2436
2437
2439{
2440 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
2441
2442 if( m_previewItems )
2443 {
2444 m_previewItems->FreeItems();
2445 delete m_previewItems;
2446 }
2447
2448 m_view = aView;
2451
2452 if(m_view)
2453 m_view->Add( m_previewItems );
2454
2455 delete m_debugDecorator;
2456
2457 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR( this );
2458 m_debugDecorator = dec;
2459
2460 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2461
2462 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2463 dec->SetView( m_view );
2464}
2465
2466
2468{
2469 if( aNet )
2470 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2471 else
2472 return -1;
2473}
2474
2475
2477{
2478 if( aNet )
2479 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2480 else
2481 return wxEmptyString;
2482}
2483
2484
2486{
2487 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2488}
2489
2490
2495
2496
2501
2502
2504{
2505 m_tool = aTool;
2506 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2507}
2508
2509
2511{
2512 if( aLayer < 0 )
2514
2515 if( aLayer == 0 )
2516 return F_Cu;
2517
2518 if( aLayer == m_board->GetCopperLayerCount() - 1 )
2519 return B_Cu;
2520
2521 return static_cast<PCB_LAYER_ID>( ( aLayer + 1 ) * 2 );
2522}
2523
2524
2526{
2527 if( aLayer < 0 )
2528 return -1;
2529
2530 if( aLayer == F_Cu )
2531 return 0;
2532
2533 if( aLayer == B_Cu )
2534 return m_board->GetCopperLayerCount() - 1;
2535
2536 return ( aLayer / 2 ) - 1;
2537}
2538
2539
2544
2545
2551
2552
2554 const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
2555{
2556 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
2557
2558 const PAD* startPad = nullptr;
2559 const PAD* endPad = nullptr;
2560
2561 if( aStartPad )
2562 startPad = static_cast<PAD*>( aStartPad->Parent() );
2563
2564 if( aEndPad )
2565 endPad = static_cast<PAD*>( aEndPad->Parent() );
2566
2567 constexpr PATH_OPTIMISATIONS opts = {
2568 .OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = true
2569 };
2570 const BOARD* board = GetBoard();
2571 return board->GetLengthCalculation()->CalculateLength( lengthItems, opts, startPad, endPad );
2572}
2573
2574
2576 const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
2577{
2578 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
2579
2580 const PAD* startPad = nullptr;
2581 const PAD* endPad = nullptr;
2582
2583 if( aStartPad )
2584 startPad = static_cast<PAD*>( aStartPad->Parent() );
2585
2586 if( aEndPad )
2587 endPad = static_cast<PAD*>( aEndPad->Parent() );
2588
2589 constexpr PATH_OPTIMISATIONS opts = {
2590 .OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = true
2591 };
2592 const BOARD* board = GetBoard();
2593 return board->GetLengthCalculation()->CalculateDelay( lengthItems, opts, startPad, endPad );
2594}
2595
2596
2597int64_t PNS_KICAD_IFACE_BASE::CalculateLengthForDelay( int64_t aDesiredDelay, const int aWidth,
2598 const bool aIsDiffPairCoupled, const int aDiffPairCouplingGap,
2599 const int aPNSLayer, const NETCLASS* aNetClass )
2600{
2602 ctx.NetClass = aNetClass;
2603 ctx.Width = aWidth;
2604 ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
2605 ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
2606 ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
2607
2608 const BOARD* board = GetBoard();
2609 return board->GetLengthCalculation()->CalculateLengthForDelay( aDesiredDelay, ctx );
2610}
2611
2612
2614 bool aIsDiffPairCoupled, int aDiffPairCouplingGap,
2615 int aPNSLayer, const NETCLASS* aNetClass )
2616{
2618 ctx.NetClass = aNetClass;
2619 ctx.Width = aWidth;
2620 ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
2621 ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
2622 ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
2623
2624 const BOARD* board = GetBoard();
2626}
2627
2628
2629std::vector<LENGTH_DELAY_CALCULATION_ITEM>
2631{
2632 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems;
2633
2634 for( int idx = 0; idx < aLine.Size(); idx++ )
2635 {
2636 const PNS::ITEM* lineItem = aLine[idx];
2637
2638 if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( lineItem ) )
2639 {
2641 item.SetLine( l->CLine() );
2642
2643 const PCB_LAYER_ID layer = GetBoardLayerFromPNSLayer( lineItem->Layer() );
2644 item.SetLayers( layer );
2645 item.SetEffectiveNetClass( aNetClass );
2646
2647 lengthItems.emplace_back( std::move( item ) );
2648 }
2649 else if( lineItem->OfKind( PNS::ITEM::VIA_T ) && idx > 0 && idx < aLine.Size() - 1 )
2650 {
2651 const int layerPrev = aLine[idx - 1]->Layer();
2652 const int layerNext = aLine[idx + 1]->Layer();
2653 const PCB_LAYER_ID pcbLayerPrev = GetBoardLayerFromPNSLayer( layerPrev );
2654 const PCB_LAYER_ID pcbLayerNext = GetBoardLayerFromPNSLayer( layerNext );
2655
2656 if( layerPrev != layerNext )
2657 {
2659 item.SetVia( static_cast<PCB_VIA*>( lineItem->GetSourceItem() ) );
2660 item.SetLayers( pcbLayerPrev, pcbLayerNext ); // TODO: BUG IS HERE!!!
2661 item.SetEffectiveNetClass( aNetClass );
2662 lengthItems.emplace_back( std::move( item ) );
2663 }
2664 }
2665 }
2666
2667 return lengthItems;
2668}
@ ERROR_OUTSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
#define SKIP_ENTERED_GROUP
@ OFF
Net (and netclass) colors are not shown.
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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.
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
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.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:236
bool IsLocked() const override
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.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition board_item.h:318
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:284
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:256
virtual bool HasDrilledHole() const
Definition board_item.h:165
virtual int BoardCopperLayerCount() const
Return the total number of copper layers for the board that this item resides on.
virtual bool IsOnCopperLayer() const
Definition board_item.h:155
int GetMaxError() const
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:322
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1361
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr const SizeVec & GetSize() const
Definition box2.h:206
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:399
wxString GetName() const
Definition drc_rule.h:194
SEVERITY GetSeverity() const
Definition drc_rule.h:207
const MINOPTMAX< int > & GetValue() const
Definition drc_rule.h:186
bool GetOption(OPTIONS option) const
Definition drc_rule.h:219
DRC_RULE * GetParentRule() const
Definition drc_rule.h:190
bool IsNull() const
Definition drc_rule.h:181
bool IsImplicit() const
Definition drc_rule.h:134
DRC_IMPLICIT_SOURCE GetImplicitSource() const
Definition drc_rule.h:138
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:110
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:144
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:192
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition eda_shape.h:378
virtual bool IsVisible() const
Definition eda_text.h:187
void SetPosition(const VECTOR2I &aPos) override
bool IsNetTie() const
Definition footprint.h:340
VECTOR2I GetPosition() const override
Definition footprint.h:245
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
@ KD_WARNING
Definition kidialog.h:47
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:55
int ShowModal() override
Definition kidialog.cpp:93
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition color4d.h:312
double a
Alpha component.
Definition color4d.h:396
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition color4d.h:269
PCB specific render settings.
Definition pcb_painter.h:82
NET_COLOR_MODE GetNetColorMode() const
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()
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.
Extend VIEW_ITEM by possibility of grouping items into a single object.
Definition view_group.h:43
virtual double ViewGetLOD(int aLayer, const VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition view_item.h:155
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
Lightweight class which holds a pad, via, or a routed trace outline.
void SetLine(const SHAPE_LINE_CHAIN &aLine)
Sets the source SHAPE_LINE_CHAIN of this item.
void SetVia(const PCB_VIA *aVia)
Sets the VIA associated with this item.
void SetEffectiveNetClass(const NETCLASS *aNetClass)
Sets the effective net class for the item.
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.
int64_t CalculateLengthForDelay(int64_t aDesiredDelay, const TUNING_PROFILE_GEOMETRY_CONTEXT &aCtx) const
Calculates the length of track required for the given delay in a specific geometry context.
int64_t CalculatePropagationDelayForShapeLineChain(const SHAPE_LINE_CHAIN &aShape, const TUNING_PROFILE_GEOMETRY_CONTEXT &aCtx) const
Gets the propagation delay for the given shape line chain.
int64_t CalculateDelay(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical propagation delay of the given items.
int64_t CalculateLength(std::vector< LENGTH_DELAY_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:246
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:189
bool HasPcbColor() const
Definition netclass.h:188
Handle the data for a net.
Definition netinfo.h:54
const wxString & GetNetname() const
Definition netinfo.h:112
int GetNetCode() const
Definition netinfo.h:106
void SetParent(BOARD *aParent)
Definition netinfo.h:151
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:255
NET_SETTINGS stores various net-related settings in a project context.
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::...
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition padstack.h:351
UNCONNECTED_LAYER_MODE UnconnectedLayerMode() const
Definition padstack.h:350
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:171
@ CUSTOM
Shapes can be defined on arbitrary layers.
Definition padstack.h:173
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
Definition padstack.h:172
MODE Mode() const
Definition padstack.h:322
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition padstack.h:180
Definition pad.h:55
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition pad.h:555
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:931
const VECTOR2I & GetDrillSize() const
Definition pad.h:312
PAD_ATTRIB GetAttribute() const
Definition pad.h:558
int GetPadToDieDelay() const
Definition pad.h:574
const PADSTACK & Padstack() const
Definition pad.h:328
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
Definition pad.h:324
bool IsFreePad() const
Definition pad.cpp:332
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.h:415
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition pad.cpp:919
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1503
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition pad.cpp:1033
int GetPadToDieLength() const
Definition pad.h:571
void SetMid(const VECTOR2I &aMid)
Definition pcb_track.h:346
const VECTOR2I & GetMid() const
Definition pcb_track.h:347
void GetBoundingHull(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
The selection tool: currently supports:
PCB_GROUP * GetEnteredGroup()
std::vector< VECTOR2I > GetConnectionPoints() const
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
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:177
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:150
bool HasSolderMask() const
Definition pcb_track.h:178
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:153
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition pcb_track.h:180
std::optional< int > GetLocalSolderMaskMargin() const
Definition pcb_track.h:181
const VECTOR2I & GetStart() const
Definition pcb_track.h:154
const VECTOR2I & GetEnd() const
Definition pcb_track.h:151
virtual void SetWidth(int aWidth)
Definition pcb_track.h:147
virtual int GetWidth() const
Definition pcb_track.h:148
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:867
PCB_LAYER_ID BottomLayer() const
VECTOR2I GetPosition() const override
Definition pcb_track.h:614
const PADSTACK & Padstack() const
Definition pcb_track.h:463
void SetFrontTentingMode(TENTING_MODE aMode)
TENTING_MODE GetFrontTentingMode() const
std::optional< int > GetSecondaryDrillSize() const
void SetSecondaryDrillStartLayer(PCB_LAYER_ID aLayer)
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetFrontPostMachining() const
Definition pcb_track.h:737
void SetDrill(int aDrill)
Definition pcb_track.h:805
PCB_LAYER_ID GetSecondaryDrillEndLayer() const
Definition pcb_track.h:841
void SetBackTentingMode(TENTING_MODE aMode)
void SetIsFree(bool aFree=true)
Definition pcb_track.h:868
PCB_LAYER_ID GetPrimaryDrillStartLayer() const
Definition pcb_track.h:731
void SetFrontPostMachining(const std::optional< PAD_DRILL_POST_MACHINING_MODE > &aMode)
void SetSecondaryDrillEndLayer(PCB_LAYER_ID aLayer)
PCB_LAYER_ID GetPrimaryDrillEndLayer() const
Definition pcb_track.h:734
void SetPosition(const VECTOR2I &aPoint) override
Definition pcb_track.h:615
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/.
int GetWidth() const override
void SetViaType(VIATYPE aViaType)
Definition pcb_track.h:456
TENTING_MODE GetBackTentingMode() const
PCB_LAYER_ID TopLayer() const
void SetSecondaryDrillSize(const VECTOR2I &aSize)
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
VIATYPE GetViaType() const
Definition pcb_track.h:455
PCB_LAYER_ID GetSecondaryDrillStartLayer() const
Definition pcb_track.h:838
void SetWidth(int aWidth) override
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)
void SetPrimaryDrillEndLayer(PCB_LAYER_ID aLayer)
void SetPrimaryDrillStartLayer(PCB_LAYER_ID aLayer)
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
static HOLE * MakeCircularHole(const VECTOR2I &pos, int radius, PNS_LAYER_RANGE aLayers)
Definition pns_hole.cpp:131
int Size() const
ITEM_SET & ExcludeItem(const ITEM *aItem)
ITEM_SET & FilterKinds(int aKindMask, bool aInvert=false)
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
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:232
void SetMaxClearance(int aClearance)
Assign a clearance resolution function object.
Definition pns_node.h:259
const JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, NET_HANDLE aNet) const
Search for a joint at a given position, layer and belonging to given net.
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:265
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
const SEG & Seg() const
Definition pns_segment.h:93
void SetEnds(const VECTOR2I &a, const VECTOR2I &b)
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)
long long int CalculateRoutedPathLength(const PNS::ITEM_SET &aLine, const PNS::SOLID *aStartPad, const PNS::SOLID *aEndPad, const NETCLASS *aNetClass) override
int64_t CalculateRoutedPathDelay(const PNS::ITEM_SET &aLine, const PNS::SOLID *aStartPad, const PNS::SOLID *aEndPad, const NETCLASS *aNetClass) override
std::unique_ptr< PNS::ARC > syncArc(PCB_ARC *aArc)
void RemoveItem(PNS::ITEM *aItem) override
bool IsPNSCopperLayer(int aPNSLayer) const override
int64_t CalculateLengthForDelay(int64_t aDesiredDelay, int aWidth, bool aIsDiffPairCoupled, int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS *aNetClass) override
PNS::RULE_RESOLVER * GetRuleResolver() override
bool syncTextItem(PNS::NODE *aWorld, BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
std::vector< LENGTH_DELAY_CALCULATION_ITEM > getLengthDelayCalculationItems(const PNS::ITEM_SET &aLine, const NETCLASS *aNetClass) const
bool IsKicadCopperLayer(PCB_LAYER_ID aPcbnewLayer) const
std::vector< std::unique_ptr< PNS::SOLID > > syncPad(PAD *aPad)
void SetStartLayerFromPCBNew(PCB_LAYER_ID aLayer)
bool syncBarcode(PNS::NODE *aWorld, PCB_BARCODE *aBarcode)
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
int64_t CalculateDelayForShapeLineChain(const SHAPE_LINE_CHAIN &aShape, int aWidth, bool aIsDiffPairCoupled, int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS *aNetClass) 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
std::unordered_map< BOARD_ITEM *, EDA_GROUP * > m_itemGroups
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
std::unordered_map< BOARD_ITEM *, std::vector< BOARD_ITEM * > > m_replacementMap
wxString GetNetName(PNS::NET_HANDLE aNet) const override
~PNS_KICAD_IFACE() override
Represent a contiguous set of PCB layers.
int Start() const
bool Overlaps(const PNS_LAYER_RANGE &aOther) const
int End() const
PNS_LAYER_RANGE Intersection(const PNS_LAYER_RANGE &aOther) const
Shortcut for comparisons/overlap tests.
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:120
const VECTOR2I & GetP1() const
Definition shape_arc.h:119
const VECTOR2I & GetP0() const
Definition shape_arc.h:118
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 SetWidth(int aWidth) override
Set the width of all segments in the chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const 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.
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
void Append(int aX, int aY)
Append a new point at the end of the polygon.
An abstract shape on 2D plane.
Definition shape.h:126
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:1155
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition zone.h:701
bool GetDoNotAllowVias() const
Definition zone.h:712
bool GetDoNotAllowPads() const
Definition zone.h:714
bool GetDoNotAllowTracks() const
Definition zone.h:713
SHAPE_POLY_SET * Outline()
Definition zone.h:331
bool GetDoNotAllowFootprints() const
Definition zone.h:715
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition zone.h:136
bool HasKeepoutParametersSet() const
Accessor to determine if any keepout parameters are set.
Definition zone.h:692
DRC_CONSTRAINT_T
Definition drc_rule.h:47
@ VIA_DIAMETER_CONSTRAINT
Definition drc_rule.h:70
@ DIFF_PAIR_GAP_CONSTRAINT
Definition drc_rule.h:73
@ TRACK_WIDTH_CONSTRAINT
Definition drc_rule.h:59
@ EDGE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:53
@ LENGTH_CONSTRAINT
Definition drc_rule.h:71
@ CLEARANCE_CONSTRAINT
Definition drc_rule.h:49
@ MAX_UNCOUPLED_CONSTRAINT
Definition drc_rule.h:74
@ SKEW_CONSTRAINT
Definition drc_rule.h:72
@ HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:51
@ HOLE_SIZE_CONSTRAINT
Definition drc_rule.h:54
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition drc_rule.h:77
@ HOLE_TO_HOLE_CONSTRAINT
Definition drc_rule.h:52
#define _(s)
@ NO_RECURSE
Definition eda_item.h:52
#define ROUTER_TRANSIENT
transient items that should NOT be cached
#define IN_EDIT
Item currently edited.
EDA_UNITS
Definition eda_units.h:48
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
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START
Definition layer_ids.h:174
@ ALWAYS_FLASHED
Always flashed for connectivity.
Definition layer_ids.h:186
@ LAYER_RATSNEST
Definition layer_ids.h:253
@ LAYER_SELECT_OVERLAY
Selected items overlay.
Definition layer_ids.h:280
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.
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:96
@ 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.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:103
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:99
@ PTH
Plated through hole pad.
Definition padstack.h:98
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:100
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:121
BARCODE class definition.
@ 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)
#define ENTERED_GROUP_MAGIC_NUMBER
@ 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
VECTOR2I::extended_type ecoord
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.
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
bool m_IsTimeDomain
Definition pns_node.h:80
MINOPTMAX< int > m_Value
Definition pns_node.h:75
CONSTRAINT_TYPE m_Type
Definition pns_node.h:74
A data structure to contain basic geometry data which can affect signal propagation calculations.
int64_t DiffPairCouplingGap
The gap between coupled tracks.
const NETCLASS * NetClass
The net class this track belongs to.
int64_t Width
The width (in internal units) of the track.
bool IsDiffPairCoupled
Whether this track or via is a member of a coupled differential pair.
PCB_LAYER_ID Layer
The layer this track is on.
std::size_t operator()(const CLEARANCE_CACHE_KEY &k) const
KIBIS top(path, &reporter)
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_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:106
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:103
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:97
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:104
@ 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:108
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:92
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition typeinfo.h:89
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:90
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:107
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:95
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:102
@ 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
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:105
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:61
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694