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 break;
1771
1772 default:
1773 UNIMPLEMENTED_FOR( gitem->GetClass() );
1774 break;
1775 }
1776 }
1777
1778 SHAPE_POLY_SET buffer;
1779 SHAPE_POLY_SET* boardOutline = nullptr;
1780
1781 if( m_board->GetBoardPolygonOutlines( buffer ) )
1782 boardOutline = &buffer;
1783
1784 for( ZONE* zone : m_board->Zones() )
1785 {
1786 syncZone( aWorld, zone, boardOutline );
1787 }
1788
1789 for( FOOTPRINT* footprint : m_board->Footprints() )
1790 {
1791 for( PAD* pad : footprint->Pads() )
1792 {
1793 std::vector<std::unique_ptr<PNS::SOLID>> solids = syncPad( pad );
1794
1795 for( std::unique_ptr<PNS::SOLID>& solid : solids )
1796 aWorld->Add( std::move( solid ) );
1797
1798 std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
1799
1800 if( clearanceOverride.has_value() )
1801 worstClearance = std::max( worstClearance, clearanceOverride.value() );
1802
1803 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1804 {
1805 std::unique_ptr<SHAPE> hole;
1806 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1807 aWorld->AddEdgeExclusion( std::move( hole ) );
1808 }
1809 }
1810
1811 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1812 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1813
1814 for( ZONE* zone : footprint->Zones() )
1815 syncZone( aWorld, zone, boardOutline );
1816
1817 for( PCB_FIELD* field : footprint->GetFields() )
1818 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1819
1820 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1821 {
1822 switch( item->Type() )
1823 {
1824 case PCB_SHAPE_T:
1825 case PCB_TEXTBOX_T:
1826 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1827 break;
1828
1829 case PCB_TEXT_T:
1830 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1831 break;
1832
1833 case PCB_TABLE_T:
1834 syncTextItem( aWorld, static_cast<PCB_TABLE*>( item ), item->GetLayer() );
1835 break;
1836
1837 case PCB_BARCODE_T:
1838 syncBarcode( aWorld, static_cast<PCB_BARCODE*>( item ) );
1839 break;
1840
1841 case PCB_DIM_ALIGNED_T: // ignore only if not on a copper layer
1842 case PCB_DIM_CENTER_T:
1843 case PCB_DIM_RADIAL_T:
1845 case PCB_DIM_LEADER_T:
1847 if( item->IsOnCopperLayer() )
1848 UNIMPLEMENTED_FOR( wxString::Format( wxT( "%s on copper layer" ), item->GetClass() ) );
1849
1850 break;
1851
1852 default:
1853 UNIMPLEMENTED_FOR( item->GetClass() );
1854 break;
1855 }
1856 }
1857 }
1858
1859 for( PCB_TRACK* t : m_board->Tracks() )
1860 {
1861 KICAD_T type = t->Type();
1862
1863 if( type == PCB_TRACE_T )
1864 {
1865 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1866 aWorld->Add( std::move( segment ), true );
1867 }
1868 else if( type == PCB_ARC_T )
1869 {
1870 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1871 aWorld->Add( std::move( arc ), true );
1872 }
1873 else if( type == PCB_VIA_T )
1874 {
1875 if( std::unique_ptr<PNS::VIA> via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1876 aWorld->Add( std::move( via ) );
1877 }
1878 }
1879
1880 // NB: if this were ever to become a long-lived object we would need to dirty its
1881 // clearance cache here....
1882 delete m_ruleResolver;
1884
1886 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1887}
1888
1889
1891{
1892 for( BOARD_ITEM* item : m_hiddenItems )
1893 m_view->SetVisible( item, true );
1894
1895 m_hiddenItems.clear();
1896
1897 if( m_previewItems )
1898 {
1899 m_previewItems->FreeItems();
1900 m_view->Update( m_previewItems );
1901 }
1902
1903 if( m_debugDecorator )
1904 m_debugDecorator->Clear();
1905}
1906
1907
1912
1913
1914void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, int aFlags )
1915{
1916 if( aItem->IsVirtual() )
1917 return;
1918
1919 if( ZONE* zone = dynamic_cast<ZONE*>( aItem->Parent() ) )
1920 {
1921 if( zone->GetIsRuleArea() )
1922 aFlags |= PNS_SEMI_SOLID;
1923 }
1924
1925 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, this, m_view, aFlags );
1926
1927 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1929 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1930
1931 if( aClearance >= 0 )
1932 {
1933 pitem->SetClearance( aClearance );
1934
1935 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1936
1937 switch( settings->m_Display.m_TrackClearance )
1938 {
1941 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1942 break;
1943
1945 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1946 break;
1947
1948 case SHOW_WHILE_ROUTING:
1949 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1950 break;
1951
1952 default:
1953 pitem->ShowClearance( false );
1954 break;
1955 }
1956 }
1957
1958 m_previewItems->Add( pitem );
1959 m_view->Update( m_previewItems );
1960}
1961
1962
1963void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1964{
1965 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, this, m_view );
1967
1968 COLOR4D color;
1969
1970 if( aImportance >= 1 )
1971 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1972 else if( aImportance == 0 )
1973 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1974
1975 pitem->SetColor( color );
1976
1977 m_previewItems->Add( pitem );
1978 m_view->Update( m_previewItems );
1979}
1980
1981
1983{
1984 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, this, m_view );
1985
1986 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1987 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1988 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1989 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1990 COLOR4D color = defaultColor;
1991
1992 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1993 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1994 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1995 int netCode = -1;
1996
1997 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
1998 netCode = net->GetNetCode();
1999
2000 const NETCLASS* nc = nullptr;
2001 const NET_SETTINGS* netSettings = connectivity->GetNetSettings();
2002
2003 if( connectivity->HasNetNameForNetCode( netCode ) )
2004 {
2005 const wxString& netName = connectivity->GetNetNameForNetCode( netCode );
2006
2007 if( netSettings && netSettings->HasEffectiveNetClass( netName ) )
2008 nc = netSettings->GetCachedEffectiveNetClass( netName ).get();
2009 }
2010
2011 if( colorByNet && netColors.count( netCode ) )
2012 color = netColors.at( netCode );
2013 else if( colorByNet && nc && nc->HasPcbColor() )
2014 color = nc->GetPcbColor();
2015 else
2016 color = defaultColor;
2017
2019 color = defaultColor;
2020
2021 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
2022
2023 m_previewItems->Add( pitem );
2024 m_view->Update( m_previewItems );
2025}
2026
2027
2029{
2030 BOARD_ITEM* parent = aItem->Parent();
2031
2032 if( parent )
2033 {
2034 if( m_view->IsVisible( parent ) )
2035 m_hiddenItems.insert( parent );
2036
2037 m_view->SetVisible( parent, false );
2038 m_view->Update( parent, KIGFX::APPEARANCE );
2039
2040 for( ZONE* td : m_board->Zones() )
2041 {
2042 if( td->IsTeardropArea()
2043 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
2044 && td->Outline()->Collide( aItem->Shape( td->GetLayer() ) ) )
2045 {
2046 m_view->SetVisible( td, false );
2047 m_view->Update( td, KIGFX::APPEARANCE );
2048 }
2049 }
2050 }
2051}
2052
2053
2057
2058
2060{
2061 BOARD_ITEM* parent = aItem->Parent();
2062
2063 if( aItem->OfKind( PNS::ITEM::SOLID_T ) && parent->Type() == PCB_PAD_T )
2064 {
2065 PAD* pad = static_cast<PAD*>( parent );
2066 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2067
2068 m_fpOffsets[ pad ].p_old = pos;
2069 return;
2070 }
2071
2072 if( parent )
2073 {
2074 if( EDA_GROUP* group = parent->GetParentGroup() )
2075 m_itemGroups[parent] = group;
2076
2077 m_commit->Remove( parent );
2078 }
2079}
2080
2081
2085
2086
2088{
2089 BOARD_ITEM* board_item = aItem->Parent();
2090
2091 switch( aItem->Kind() )
2092 {
2093 case PNS::ITEM::ARC_T:
2094 {
2095 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
2096 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
2097 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape( -1 ) );
2098
2099 m_commit->Modify( arc_board );
2100
2101 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
2102 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
2103 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
2104 arc_board->SetWidth( arc->Width() );
2105 break;
2106 }
2107
2109 {
2110 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
2111 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
2112 const SEG& s = seg->Seg();
2113
2114 m_commit->Modify( track );
2115
2116 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
2117 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
2118 track->SetWidth( seg->Width() );
2119 break;
2120 }
2121
2122 case PNS::ITEM::VIA_T:
2123 {
2124 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
2125 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
2126
2127 m_commit->Modify( via_board );
2128
2129 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
2130 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter( 0 ) );
2131 via_board->SetDrill( via->Drill() );
2132 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
2133 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
2134 via_board->Padstack().SetUnconnectedLayerMode( via->UnconnectedLayerMode() );
2135 via_board->SetIsFree( via->IsFree() );
2136 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
2137 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
2138 break;
2139 }
2140
2141 case PNS::ITEM::SOLID_T:
2142 {
2143 if( aItem->Parent()->Type() == PCB_PAD_T )
2144 {
2145 PAD* pad = static_cast<PAD*>( aItem->Parent() );
2146 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2147
2148 // Don't add to commit; we'll add the parent footprints when processing the m_fpOffsets
2149
2150 m_fpOffsets[pad].p_old = pad->GetPosition();
2151 m_fpOffsets[pad].p_new = pos;
2152 }
2153 break;
2154 }
2155
2156 default:
2157 m_commit->Modify( aItem->Parent() );
2158 break;
2159 }
2160}
2161
2162
2164{
2165 modifyBoardItem( aItem );
2166}
2167
2168
2170{
2171}
2172
2173
2175{
2176 BOARD_CONNECTED_ITEM* newBoardItem = nullptr;
2177 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem->Net() );
2178
2179 if( !net )
2181
2182 switch( aItem->Kind() )
2183 {
2184 case PNS::ITEM::ARC_T:
2185 {
2186 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
2187 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape( -1 ) ) );
2188 new_arc->SetWidth( arc->Width() );
2189 new_arc->SetLayer( GetBoardLayerFromPNSLayer( arc->Layers().Start() ) );
2190 new_arc->SetNet( net );
2191
2192 if( aItem->GetSourceItem() && aItem->GetSourceItem()->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
2193 {
2194 PCB_TRACK* sourceTrack = static_cast<PCB_TRACK*>( aItem->GetSourceItem() );
2195 new_arc->SetHasSolderMask( sourceTrack->HasSolderMask() );
2196 new_arc->SetLocalSolderMaskMargin( sourceTrack->GetLocalSolderMaskMargin() );
2197 }
2198
2199 newBoardItem = new_arc;
2200 break;
2201 }
2202
2204 {
2205 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
2206 PCB_TRACK* track = new PCB_TRACK( m_board );
2207 const SEG& s = seg->Seg();
2208 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
2209 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
2210 track->SetWidth( seg->Width() );
2211 track->SetLayer( GetBoardLayerFromPNSLayer( seg->Layers().Start() ) );
2212 track->SetNet( net );
2213
2214 if( aItem->GetSourceItem() && aItem->GetSourceItem()->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
2215 {
2216 PCB_TRACK* sourceTrack = static_cast<PCB_TRACK*>( aItem->GetSourceItem() );
2217 track->SetHasSolderMask( sourceTrack->HasSolderMask() );
2218 track->SetLocalSolderMaskMargin( sourceTrack->GetLocalSolderMaskMargin() );
2219 }
2220
2221 newBoardItem = track;
2222 break;
2223 }
2224
2225 case PNS::ITEM::VIA_T:
2226 {
2227 PCB_VIA* via_board = new PCB_VIA( m_board );
2228 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
2229 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
2230 via_board->SetWidth( PADSTACK::ALL_LAYERS, via->Diameter( 0 ) );
2231 via_board->SetDrill( via->Drill() );
2232 via_board->SetNet( net );
2233 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
2234 via_board->Padstack().SetUnconnectedLayerMode( via->UnconnectedLayerMode() );
2235 via_board->SetIsFree( via->IsFree() );
2236 via_board->SetLayerPair( GetBoardLayerFromPNSLayer( via->Layers().Start() ),
2237 GetBoardLayerFromPNSLayer( via->Layers().End() ) );
2238
2239 if( aItem->GetSourceItem() && aItem->GetSourceItem()->Type() == PCB_VIA_T )
2240 {
2241 PCB_VIA* sourceVia = static_cast<PCB_VIA*>( aItem->GetSourceItem() );
2242 via_board->SetFrontTentingMode( sourceVia->GetFrontTentingMode() );
2243 via_board->SetBackTentingMode( sourceVia->GetBackTentingMode() );
2244 }
2245
2246 newBoardItem = via_board;
2247 break;
2248 }
2249
2250 case PNS::ITEM::SOLID_T:
2251 {
2252 PAD* pad = static_cast<PAD*>( aItem->Parent() );
2253 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
2254
2255 m_fpOffsets[pad].p_new = pos;
2256 return nullptr;
2257 }
2258
2259 default:
2260 return nullptr;
2261 }
2262
2263 if( net->GetNetCode() <= 0 )
2264 {
2265 NETINFO_ITEM* newNetInfo = newBoardItem->GetNet();
2266
2267 newNetInfo->SetParent( m_board );
2268 newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->GetDefaultNetclass() );
2269 }
2270
2271 if( newBoardItem )
2272 {
2273 if( BOARD_ITEM* src = aItem->GetSourceItem() )
2274 {
2275 if( m_itemGroups.contains( src ) )
2276 m_replacementMap[src].push_back( newBoardItem );
2277 }
2278 }
2279
2280 return newBoardItem;
2281}
2282
2283
2285{
2286 BOARD_CONNECTED_ITEM* boardItem = createBoardItem( aItem );
2287
2288 if( boardItem )
2289 {
2290 aItem->SetParent( boardItem );
2291 boardItem->ClearFlags();
2292
2293 m_commit->Add( boardItem );
2294 }
2295}
2296
2297
2299{
2300 std::set<FOOTPRINT*> processedFootprints;
2301
2302 EraseView();
2303
2304 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
2305 {
2306 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
2307 FOOTPRINT* footprint = pad->GetParentFootprint();
2308 VECTOR2I p_orig = footprint->GetPosition();
2309 VECTOR2I p_new = p_orig + offset;
2310
2311 if( processedFootprints.find( footprint ) != processedFootprints.end() )
2312 continue;
2313
2314 processedFootprints.insert( footprint );
2315 m_commit->Modify( footprint );
2316 footprint->SetPosition( p_new );
2317 }
2318
2319 m_fpOffsets.clear();
2320
2321 for( const auto& [ src, items ] : m_replacementMap )
2322 {
2323 if( auto it = m_itemGroups.find( src ); it != m_itemGroups.end() )
2324 {
2325 EDA_GROUP* group = it->second;
2326 m_commit->Modify( group->AsEdaItem(), nullptr, RECURSE_MODE::NO_RECURSE );
2327
2328 for( BOARD_ITEM* bi : items )
2329 group->AddItem( bi );
2330 }
2331 }
2332
2333 m_itemGroups.clear();
2334 m_replacementMap.clear();
2335
2336 m_commit->Push( _( "Routing" ), m_commitFlags );
2337 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2338}
2339
2340
2342{
2343 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
2344}
2345
2346
2348{
2349 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
2350
2351 if( m_previewItems )
2352 {
2353 m_previewItems->FreeItems();
2354 delete m_previewItems;
2355 }
2356
2357 m_view = aView;
2360
2361 if(m_view)
2362 m_view->Add( m_previewItems );
2363
2364 delete m_debugDecorator;
2365
2366 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR( this );
2367 m_debugDecorator = dec;
2368
2369 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2370
2371 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2372 dec->SetView( m_view );
2373}
2374
2375
2377{
2378 if( aNet )
2379 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2380 else
2381 return -1;
2382}
2383
2384
2386{
2387 if( aNet )
2388 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2389 else
2390 return wxEmptyString;
2391}
2392
2393
2395{
2396 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2397}
2398
2399
2404
2405
2410
2411
2413{
2414 m_tool = aTool;
2415 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2416}
2417
2418
2420{
2421 if( aLayer < 0 )
2423
2424 if( aLayer == 0 )
2425 return F_Cu;
2426
2427 if( aLayer == m_board->GetCopperLayerCount() - 1 )
2428 return B_Cu;
2429
2430 return static_cast<PCB_LAYER_ID>( ( aLayer + 1 ) * 2 );
2431}
2432
2433
2435{
2436 if( aLayer < 0 )
2437 return -1;
2438
2439 if( aLayer == F_Cu )
2440 return 0;
2441
2442 if( aLayer == B_Cu )
2443 return m_board->GetCopperLayerCount() - 1;
2444
2445 return ( aLayer / 2 ) - 1;
2446}
2447
2448
2453
2454
2460
2461
2463 const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
2464{
2465 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
2466
2467 const PAD* startPad = nullptr;
2468 const PAD* endPad = nullptr;
2469
2470 if( aStartPad )
2471 startPad = static_cast<PAD*>( aStartPad->Parent() );
2472
2473 if( aEndPad )
2474 endPad = static_cast<PAD*>( aEndPad->Parent() );
2475
2476 constexpr PATH_OPTIMISATIONS opts = {
2477 .OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = true
2478 };
2479 const BOARD* board = GetBoard();
2480 return board->GetLengthCalculation()->CalculateLength( lengthItems, opts, startPad, endPad );
2481}
2482
2483
2485 const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
2486{
2487 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
2488
2489 const PAD* startPad = nullptr;
2490 const PAD* endPad = nullptr;
2491
2492 if( aStartPad )
2493 startPad = static_cast<PAD*>( aStartPad->Parent() );
2494
2495 if( aEndPad )
2496 endPad = static_cast<PAD*>( aEndPad->Parent() );
2497
2498 constexpr PATH_OPTIMISATIONS opts = {
2499 .OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = true
2500 };
2501 const BOARD* board = GetBoard();
2502 return board->GetLengthCalculation()->CalculateDelay( lengthItems, opts, startPad, endPad );
2503}
2504
2505
2506int64_t PNS_KICAD_IFACE_BASE::CalculateLengthForDelay( int64_t aDesiredDelay, const int aWidth,
2507 const bool aIsDiffPairCoupled, const int aDiffPairCouplingGap,
2508 const int aPNSLayer, const NETCLASS* aNetClass )
2509{
2511 ctx.NetClass = aNetClass;
2512 ctx.Width = aWidth;
2513 ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
2514 ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
2515 ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
2516
2517 const BOARD* board = GetBoard();
2518 return board->GetLengthCalculation()->CalculateLengthForDelay( aDesiredDelay, ctx );
2519}
2520
2521
2523 bool aIsDiffPairCoupled, int aDiffPairCouplingGap,
2524 int aPNSLayer, const NETCLASS* aNetClass )
2525{
2527 ctx.NetClass = aNetClass;
2528 ctx.Width = aWidth;
2529 ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
2530 ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
2531 ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
2532
2533 const BOARD* board = GetBoard();
2535}
2536
2537
2538std::vector<LENGTH_DELAY_CALCULATION_ITEM>
2540{
2541 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems;
2542
2543 for( int idx = 0; idx < aLine.Size(); idx++ )
2544 {
2545 const PNS::ITEM* lineItem = aLine[idx];
2546
2547 if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( lineItem ) )
2548 {
2550 item.SetLine( l->CLine() );
2551
2552 const PCB_LAYER_ID layer = GetBoardLayerFromPNSLayer( lineItem->Layer() );
2553 item.SetLayers( layer );
2554 item.SetEffectiveNetClass( aNetClass );
2555
2556 lengthItems.emplace_back( std::move( item ) );
2557 }
2558 else if( lineItem->OfKind( PNS::ITEM::VIA_T ) && idx > 0 && idx < aLine.Size() - 1 )
2559 {
2560 const int layerPrev = aLine[idx - 1]->Layer();
2561 const int layerNext = aLine[idx + 1]->Layer();
2562 const PCB_LAYER_ID pcbLayerPrev = GetBoardLayerFromPNSLayer( layerPrev );
2563 const PCB_LAYER_ID pcbLayerNext = GetBoardLayerFromPNSLayer( layerNext );
2564
2565 if( layerPrev != layerNext )
2566 {
2568 item.SetVia( static_cast<PCB_VIA*>( lineItem->GetSourceItem() ) );
2569 item.SetLayers( pcbLayerPrev, pcbLayerNext ); // TODO: BUG IS HERE!!!
2570 item.SetEffectiveNetClass( aNetClass );
2571 lengthItems.emplace_back( std::move( item ) );
2572 }
2573 }
2574 }
2575
2576 return lengthItems;
2577}
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:379
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 TIME_DOMAIN_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 TIME_DOMAIN_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:373
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:118
const VECTOR2I & GetP1() const
Definition shape_arc.h:117
const VECTOR2I & GetP0() const
Definition shape_arc.h:116
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int Width() const
Get the current width of the segments in the chain.
void 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:1154
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.
PCB_LAYER_ID Layer
The layer this track is on.
bool IsDiffPairCoupled
Whether this track or via is a member of a coupled differential pair.
int64_t DiffPairCouplingGap
The gap between coupled tracks.
int64_t Width
The width (in internal units) of the track.
const NETCLASS * NetClass
The net class this track belongs to.
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_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