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