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 (C) 2016-2024 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 <pad.h>
28#include <pcb_track.h>
29#include <zone.h>
30#include <pcb_shape.h>
31#include <pcb_generator.h>
32#include <pcb_text.h>
33#include <board_commit.h>
34#include <layer_ids.h>
35#include <kidialog.h>
36#include <tools/pcb_tool_base.h>
37#include <tool/tool_manager.h>
39
41#include <pcb_painter.h>
42
43#include <geometry/shape.h>
45#include <geometry/shape_arc.h>
47
48#include <drc/drc_rule.h>
49#include <drc/drc_engine.h>
50
52
53#include <wx/log.h>
54
55#include <memory>
56
57#include <advanced_config.h>
58#include <pcbnew_settings.h>
59#include <macros.h>
60
61#include "pns_kicad_iface.h"
62#include "pns_arc.h"
63#include "pns_sizes_settings.h"
64#include "pns_item.h"
65#include "pns_line.h"
66#include "pns_solid.h"
67#include "pns_segment.h"
68#include "pns_node.h"
69#include "pns_router.h"
70#include "pns_debug_decorator.h"
71#include "router_preview_item.h"
72
74
75
77{
78 const PNS::ITEM* A;
79 const PNS::ITEM* B;
80 bool Flag;
81
82 bool operator==(const CLEARANCE_CACHE_KEY& other) const
83 {
84 return A == other.A && B == other.B && Flag == other.Flag;
85 }
86};
87
88namespace std
89{
90 template <>
92 {
93 std::size_t operator()( const CLEARANCE_CACHE_KEY& k ) const
94 {
95 size_t retval = 0xBADC0FFEE0DDF00D;
96 hash_combine( retval, hash<const void*>()( k.A ), hash<const void*>()( k.B ), hash<int>()( k.Flag ) );
97 return retval;
98 }
99 };
100}
101
102
104{
105public:
106 PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER_IFACE* aRouterIface );
108
109 int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
110 bool aUseClearanceEpsilon = true ) override;
111
113 int DpNetPolarity( PNS::NET_HANDLE aNet ) override;
114 bool DpNetPair( const PNS::ITEM* aItem, PNS::NET_HANDLE& aNetP,
115 PNS::NET_HANDLE& aNetN ) override;
116
117 int NetCode( PNS::NET_HANDLE aNet ) override;
118 wxString NetName( PNS::NET_HANDLE aNet ) override;
119
120 bool IsInNetTie( const PNS::ITEM* aA ) override;
121 bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
122 const PNS::ITEM* aCollidingItem ) override;
123
124 bool IsDrilledHole( const PNS::ITEM* aItem ) override;
125 bool IsNonPlatedSlot( const PNS::ITEM* aItem ) override;
126
131 bool IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem, bool* aEnforce ) override;
132
133 bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
134 const PNS::ITEM* aItemB, int aLayer,
135 PNS::CONSTRAINT* aConstraint ) override;
136
137 int ClearanceEpsilon() const override { return m_clearanceEpsilon; }
138
139 void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
140 void ClearCaches() override;
141 void ClearTemporaryCaches() override;
142
143private:
144 BOARD_ITEM* getBoardItem( const PNS::ITEM* aItem, int aLayer, int aIdx = 0 );
145
146private:
153
154 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
155 std::unordered_map<CLEARANCE_CACHE_KEY, int> m_tempClearanceCache;
156};
157
158
160 PNS::ROUTER_IFACE* aRouterIface ) :
161 m_routerIface( aRouterIface ),
162 m_board( aBoard ),
163 m_dummyTracks{ { aBoard }, { aBoard } },
164 m_dummyArcs{ { aBoard }, { aBoard } },
165 m_dummyVias{ { aBoard }, { aBoard } }
166{
167 for( PCB_TRACK& track : m_dummyTracks )
168 track.SetFlags( ROUTER_TRANSIENT );
169
170 for( PCB_ARC& arc : m_dummyArcs )
171 arc.SetFlags( ROUTER_TRANSIENT );
172
173 for ( PCB_VIA& via : m_dummyVias )
174 via.SetFlags( ROUTER_TRANSIENT );
175
176 if( aBoard )
177 m_clearanceEpsilon = aBoard->GetDesignSettings().GetDRCEpsilon();
178 else
179 m_clearanceEpsilon = 0;
180}
181
182
184{
185}
186
187
189{
190 BOARD_ITEM* item = aA->BoardItem();
191
192 return item && item->GetParentFootprint() && item->GetParentFootprint()->IsNetTie();
193}
194
195
197 const VECTOR2I& aCollisionPos,
198 const PNS::ITEM* aCollidingItem )
199{
200 if( !aItem || !aCollidingItem )
201 return false;
202
203 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
204 BOARD_ITEM* item = aItem->BoardItem();
205 BOARD_ITEM* collidingItem = aCollidingItem->BoardItem();
206
207 FOOTPRINT* collidingFp = collidingItem->GetParentFootprint();
208 FOOTPRINT* itemFp = item ? item->GetParentFootprint() : nullptr;
209
210 if( collidingFp && itemFp && ( collidingFp == itemFp ) && itemFp->IsNetTie() )
211 {
212 // Two items colliding from the same net tie footprint are not checked
213 return true;
214 }
215
216 if( drcEngine )
217 {
218 return drcEngine->IsNetTieExclusion( NetCode( aItem->Net() ), ToLAYER_ID( aItem->Layer() ),
219 aCollisionPos, collidingItem );
220 }
221
222 return false;
223}
224
225
226bool PNS_PCBNEW_RULE_RESOLVER::IsKeepout( const PNS::ITEM* aObstacle, const PNS::ITEM* aItem,
227 bool* aEnforce )
228{
229 auto checkKeepout =
230 []( const ZONE* aKeepout, const BOARD_ITEM* aOther )
231 {
232 if( !aOther )
233 return false;
234
235 if( aKeepout->GetDoNotAllowTracks() && aOther->IsType( { PCB_ARC_T, PCB_TRACE_T } ) )
236 return true;
237
238 if( aKeepout->GetDoNotAllowVias() && aOther->Type() == PCB_VIA_T )
239 return true;
240
241 if( aKeepout->GetDoNotAllowPads() && aOther->Type() == PCB_PAD_T )
242 return true;
243
244 // Incomplete test, but better than nothing:
245 if( aKeepout->GetDoNotAllowFootprints() && aOther->Type() == PCB_PAD_T )
246 {
247 return !aKeepout->GetParentFootprint()
248 || aKeepout->GetParentFootprint() != aOther->GetParentFootprint();
249 }
250
251 return false;
252 };
253
254 if( aObstacle->Parent() && aObstacle->Parent()->Type() == PCB_ZONE_T )
255 {
256 const ZONE* zone = static_cast<ZONE*>( aObstacle->Parent() );
257
258 if( zone->GetIsRuleArea() )
259 {
260 *aEnforce = checkKeepout( zone, getBoardItem( aItem, aObstacle->Layer() ) );
261 return true;
262 }
263 }
264
265 return false;
266}
267
268
269static bool isCopper( const PNS::ITEM* aItem )
270{
271 if ( !aItem )
272 return false;
273
274 const BOARD_ITEM *parent = aItem->Parent();
275
276 return !parent || parent->IsOnCopperLayer();
277}
278
279
280static bool isHole( const PNS::ITEM* aItem )
281{
282 if ( !aItem )
283 return false;
284
285 return aItem->OfKind( PNS::ITEM::HOLE_T );
286}
287
288
289static bool isEdge( const PNS::ITEM* aItem )
290{
291 if ( !aItem )
292 return false;
293
294 const PCB_SHAPE *parent = dynamic_cast<PCB_SHAPE*>( aItem->BoardItem() );
295
296 return parent && ( parent->IsOnLayer( Edge_Cuts ) || parent->IsOnLayer( Margin ) );
297}
298
299
301{
302 if( isHole( aItem ) )
303 {
304 if( BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItem->Parent() ) )
305 return item->HasDrilledHole();
306 }
307
308 return false;
309}
310
311
313{
314 if( !isHole( aItem ) )
315 return false;
316
317 BOARD_ITEM* parent = aItem->Parent();
318
319 if( !parent && aItem->ParentPadVia() )
320 parent = aItem->ParentPadVia()->Parent();
321
322 if( parent )
323 {
324 if( parent->Type() == PCB_PAD_T )
325 {
326 PAD* pad = static_cast<PAD*>( parent );
327
328 return pad->GetAttribute() == PAD_ATTRIB::NPTH
329 && pad->GetDrillSizeX() != pad->GetDrillSizeY();
330 }
331
332 // Via holes are (currently) always round, and always plated
333 }
334
335 return false;
336}
337
338
339BOARD_ITEM* PNS_PCBNEW_RULE_RESOLVER::getBoardItem( const PNS::ITEM* aItem, int aLayer, int aIdx )
340{
341 switch( aItem->Kind() )
342 {
343 case PNS::ITEM::ARC_T:
344 m_dummyArcs[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
345 m_dummyArcs[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
346 m_dummyArcs[aIdx].SetStart( aItem->Anchor( 0 ) );
347 m_dummyArcs[aIdx].SetEnd( aItem->Anchor( 1 ) );
348 return &m_dummyArcs[aIdx];
349
350 case PNS::ITEM::VIA_T:
352 m_dummyVias[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
353 m_dummyVias[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
354 m_dummyVias[aIdx].SetStart( aItem->Anchor( 0 ) );
355 return &m_dummyVias[aIdx];
356
359 m_dummyTracks[aIdx].SetLayer( ToLAYER_ID( aLayer ) );
360 m_dummyTracks[aIdx].SetNet( static_cast<NETINFO_ITEM*>( aItem->Net() ) );
361 m_dummyTracks[aIdx].SetStart( aItem->Anchor( 0 ) );
362 m_dummyTracks[aIdx].SetEnd( aItem->Anchor( 1 ) );
363 return &m_dummyTracks[aIdx];
364
365 default:
366 return nullptr;
367 }
368}
369
370
372 const PNS::ITEM* aItemA, const PNS::ITEM* aItemB,
373 int aLayer, PNS::CONSTRAINT* aConstraint )
374{
375 std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
376
377 if( !drcEngine )
378 return false;
379
380 DRC_CONSTRAINT_T hostType;
381
382 switch ( aType )
383 {
396 default: return false; // should not happen
397 }
398
399 BOARD_ITEM* parentA = aItemA ? aItemA->BoardItem() : nullptr;
400 BOARD_ITEM* parentB = aItemB ? aItemB->BoardItem() : nullptr;
401 DRC_CONSTRAINT hostConstraint;
402
403 // A track being routed may not have a BOARD_ITEM associated yet.
404 if( aItemA && !parentA )
405 parentA = getBoardItem( aItemA, aLayer, 0 );
406
407 if( aItemB && !parentB )
408 parentB = getBoardItem( aItemB, aLayer, 1 );
409
410 if( parentA )
411 hostConstraint = drcEngine->EvalRules( hostType, parentA, parentB, ToLAYER_ID( aLayer ) );
412
413 if( hostConstraint.IsNull() )
414 return false;
415
416 if( hostConstraint.GetSeverity() == RPT_SEVERITY_IGNORE )
417 {
418 aConstraint->m_Value.SetMin( -1 );
419 aConstraint->m_RuleName = hostConstraint.GetName();
420 aConstraint->m_Type = aType;
421 return true;
422 }
423
424 switch ( aType )
425 {
438 aConstraint->m_Value = hostConstraint.GetValue();
439 aConstraint->m_RuleName = hostConstraint.GetName();
440 aConstraint->m_Type = aType;
441 return true;
442
443 default:
444 return false;
445 }
446}
447
448
449void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems )
450{
451 int n_pruned = 0;
452 std::set<const PNS::ITEM*> remainingItems( aItems.begin(), aItems.end() );
453
454/* We need to carefully check both A and B item pointers in the cache against dirty/invalidated
455 items in the set, as the clearance relation is commutative ( CL[a,b] == CL[b,a] ). The code
456 below is a bit ugly, but works in O(n*log(m)) and is run once or twice during ROUTER::Move() call
457 - so I hope it still gets better performance than no cache at all */
458 for( auto it = m_clearanceCache.begin(); it != m_clearanceCache.end(); )
459 {
460 bool dirty = remainingItems.find( it->first.A ) != remainingItems.end();
461 dirty |= remainingItems.find( it->first.B) != remainingItems.end();
462
463 if( dirty )
464 {
465 it = m_clearanceCache.erase( it );
466 n_pruned++;
467 } else
468 it++;
469 }
470#if 0
471 printf("ClearCache : n_pruned %d\n", n_pruned );
472#endif
473}
474
475
477{
478 m_clearanceCache.clear();
479 m_tempClearanceCache.clear();
480}
481
482
484{
485 m_tempClearanceCache.clear();
486}
487
488
490 bool aUseClearanceEpsilon )
491{
492 CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
493
494 // Search cache (used for actual board items)
495 auto it = m_clearanceCache.find( key );
496
497 if( it != m_clearanceCache.end() )
498 return it->second;
499
500 // Search cache (used for temporary items within an algorithm)
501 it = m_tempClearanceCache.find( key );
502
503 if( it != m_tempClearanceCache.end() )
504 return it->second;
505
506 PNS::CONSTRAINT constraint;
507 int rv = 0;
508 LAYER_RANGE layers;
509
510 if( !aB )
511 layers = aA->Layers();
512 else if( isEdge( aA ) )
513 layers = aB->Layers();
514 else if( isEdge( aB ) )
515 layers = aA->Layers();
516 else
517 layers = aA->Layers().Intersection( aB->Layers() );
518
519 // Normalize layer range (no -1 magic numbers)
521
522 for( int layer = layers.Start(); layer <= layers.End(); ++layer )
523 {
524 if( IsDrilledHole( aA ) && IsDrilledHole( aB ) )
525 {
526 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer, &constraint ) )
527 {
528 if( constraint.m_Value.Min() > rv )
529 rv = constraint.m_Value.Min();
530 }
531 }
532 else if( isHole( aA ) || isHole( aB ) )
533 {
534 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
535 {
536 if( constraint.m_Value.Min() > rv )
537 rv = constraint.m_Value.Min();
538 }
539 }
540
541 // No 'else'; plated holes get both HOLE_CLEARANCE and CLEARANCE
542 if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
543 {
544 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
545 {
546 if( constraint.m_Value.Min() > rv )
547 rv = constraint.m_Value.Min();
548 }
549 }
550
551 // No 'else'; non-plated milled holes get both HOLE_CLEARANCE and EDGE_CLEARANCE
552 if( isEdge( aA ) || IsNonPlatedSlot( aA ) || isEdge( aB ) || IsNonPlatedSlot( aB ) )
553 {
554 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
555 {
556 if( constraint.m_Value.Min() > rv )
557 rv = constraint.m_Value.Min();
558 }
559 }
560
561 if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_PHYSICAL_CLEARANCE, aA, aB, layer, &constraint ) )
562 {
563 if( constraint.m_Value.Min() > rv )
564 rv = constraint.m_Value.Min();
565 }
566 }
567
568 if( aUseClearanceEpsilon && rv > 0 )
569 rv = std::max( 0, rv - m_clearanceEpsilon );
570
571 /*
572 * It makes no sense to put items that have no owning NODE in the cache - they can be
573 * allocated on stack and we can't really invalidate them in the cache when they are
574 * destroyed. Probably a better idea would be to use a static unique counter in PNS::ITEM
575 * constructor to generate the cache keys.
576 *
577 * However, algorithms DO greatly benefit from using the cache, so ownerless items need to be
578 * cached. In order to easily clear those only, a temporary cache is created. If this doesn't
579 * seem nice, an alternative is clearing the full cache once it reaches a certain size. Also
580 * not pretty, but VERY effective to keep things interactive.
581 */
582 if( aA && aB )
583 {
584 if ( aA->Owner() && aB->Owner() )
585 m_clearanceCache[ key ] = rv;
586 else
587 m_tempClearanceCache[ key ] = rv;
588 }
589
590 return rv;
591}
592
593
594bool PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth )
595{
596 VECTOR2I p;
597
598 assert( aItem->Owner() != nullptr );
599
600 auto tryGetTrackWidth =
601 []( PNS::ITEM* aPnsItem ) -> int
602 {
603 switch( aPnsItem->Kind() )
604 {
605 case PNS::ITEM::SEGMENT_T: return static_cast<PNS::SEGMENT*>( aPnsItem )->Width();
606 case PNS::ITEM::ARC_T: return static_cast<PNS::ARC*>( aPnsItem )->Width();
607 default: return -1;
608 }
609 };
610
611 int itemTrackWidth = tryGetTrackWidth( aItem );
612
613 if( itemTrackWidth > 0 )
614 {
615 *aInheritedWidth = itemTrackWidth;
616 return true;
617 }
618
619 switch( aItem->Kind() )
620 {
621 case PNS::ITEM::VIA_T: p = static_cast<PNS::VIA*>( aItem )->Pos(); break;
622 case PNS::ITEM::SOLID_T: p = static_cast<PNS::SOLID*>( aItem )->Pos(); break;
623 default: return false;
624 }
625
626 const PNS::JOINT* jt = static_cast<const PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
627
628 assert( jt != nullptr );
629
630 int mval = INT_MAX;
631
632 PNS::ITEM_SET linkedSegs( jt->CLinks() );
634
635 for( PNS::ITEM* item : linkedSegs.Items() )
636 {
637 int w = tryGetTrackWidth( item );
638
639 if( w > 0 )
640 mval = std::min( w, mval );
641 }
642
643 if( mval == INT_MAX )
644 return false;
645
646 *aInheritedWidth = mval;
647 return true;
648}
649
650
652 PNS::NET_HANDLE aNet )
653{
655 PNS::CONSTRAINT constraint;
656
657 if( aStartItem && m_startLayer < 0 )
658 m_startLayer = aStartItem->Layer();
659
660 aSizes.SetClearance( bds.m_MinClearance );
661 aSizes.SetMinClearance( bds.m_MinClearance );
662 aSizes.SetClearanceSource( _( "board minimum clearance" ) );
663
665 m_startLayer, &constraint ) )
666 {
667 if( constraint.m_Value.Min() > bds.m_MinClearance )
668 {
669 aSizes.SetClearance( constraint.m_Value.Min() );
670 aSizes.SetClearanceSource( constraint.m_RuleName );
671 }
672 }
673
674 int trackWidth = bds.m_TrackMinWidth;
675 bool found = false;
676 aSizes.SetWidthSource( _( "board minimum track width" ) );
677
678 if( bds.m_UseConnectedTrackWidth && !bds.m_TempOverrideTrackWidth && aStartItem != nullptr )
679 {
680 found = inheritTrackWidth( aStartItem, &trackWidth );
681
682 if( found )
683 aSizes.SetWidthSource( _( "existing track" ) );
684 }
685
686 if( !found && bds.UseNetClassTrack() && aStartItem )
687 {
689 m_startLayer, &constraint ) )
690 {
691 trackWidth = std::max( trackWidth, constraint.m_Value.Opt() );
692 found = true;
693
694 if( trackWidth == constraint.m_Value.Opt() )
695 aSizes.SetWidthSource( constraint.m_RuleName );
696 }
697 }
698
699 if( !found )
700 {
701 trackWidth = std::max( trackWidth, bds.GetCurrentTrackWidth() );
702
703 if( bds.UseNetClassTrack() )
704 aSizes.SetWidthSource( _( "netclass 'Default'" ) );
705 else if( trackWidth == bds.GetCurrentTrackWidth() )
706 aSizes.SetWidthSource( _( "user choice" ) );
707 }
708
709 aSizes.SetTrackWidth( trackWidth );
712
713 int viaDiameter = bds.m_ViasMinSize;
714 int viaDrill = bds.m_MinThroughDrill;
715
716 PNS::VIA dummyVia, coupledVia;
717
718 if( aStartItem )
719 {
720 dummyVia.SetNet( aStartItem->Net() );
721 coupledVia.SetNet( m_ruleResolver->DpCoupledNet( aStartItem->Net() ) );
722 }
723
724 if( bds.UseNetClassVia() && aStartItem ) // netclass value
725 {
727 nullptr, m_startLayer, &constraint ) )
728 {
729 viaDiameter = std::max( viaDiameter, constraint.m_Value.Opt() );
730 }
731
733 nullptr, m_startLayer, &constraint ) )
734 {
735 viaDrill = std::max( viaDrill, constraint.m_Value.Opt() );
736 }
737 }
738 else
739 {
740 viaDiameter = bds.GetCurrentViaSize();
741 viaDrill = bds.GetCurrentViaDrill();
742 }
743
744 aSizes.SetViaDiameter( viaDiameter );
745 aSizes.SetViaDrill( viaDrill );
746
747 int diffPairWidth = bds.m_TrackMinWidth;
748 int diffPairGap = bds.m_MinClearance;
749 int diffPairViaGap = bds.m_MinClearance;
750
751 aSizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
752 aSizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
753
754 found = false;
755
756 // First try to pick up diff pair width from starting track, if enabled
757 if( bds.m_UseConnectedTrackWidth && aStartItem )
758 found = inheritTrackWidth( aStartItem, &diffPairWidth );
759
760 // Next, pick up gap from netclass, and width also if we didn't get a starting width above
761 if( bds.UseNetClassDiffPair() && aStartItem )
762 {
764 nullptr, m_startLayer, &constraint ) )
765 {
766 diffPairWidth = std::max( diffPairWidth, constraint.m_Value.Opt() );
767
768 if( diffPairWidth == constraint.m_Value.Opt() )
769 aSizes.SetDiffPairWidthSource( constraint.m_RuleName );
770 }
771
773 nullptr, m_startLayer, &constraint ) )
774 {
775 diffPairGap = std::max( diffPairGap, constraint.m_Value.Opt() );
776 diffPairViaGap = std::max( diffPairViaGap, constraint.m_Value.Opt() );
777
778 if( diffPairGap == constraint.m_Value.Opt() )
779 aSizes.SetDiffPairGapSource( constraint.m_RuleName );
780 }
781 }
782 else
783 {
784 diffPairWidth = bds.GetCurrentDiffPairWidth();
785 diffPairGap = bds.GetCurrentDiffPairGap();
786 diffPairViaGap = bds.GetCurrentDiffPairViaGap();
787
788 aSizes.SetDiffPairWidthSource( _( "user choice" ) );
789 aSizes.SetDiffPairGapSource( _( "user choice" ) );
790 }
791
792 aSizes.SetDiffPairWidth( diffPairWidth );
793 aSizes.SetDiffPairGap( diffPairGap );
794 aSizes.SetDiffPairViaGap( diffPairViaGap );
795 aSizes.SetDiffPairViaGapSameAsTraceGap( false );
796
797 int holeToHoleMin = bds.m_HoleToHoleMin;
798
800 &dummyVia, UNDEFINED_LAYER, &constraint ) )
801 {
802 holeToHoleMin = constraint.m_Value.Min();
803 }
804
805 aSizes.SetHoleToHole( holeToHoleMin );
806
808 &coupledVia, UNDEFINED_LAYER, &constraint ) )
809 {
810 holeToHoleMin = constraint.m_Value.Min();
811 }
812
813 aSizes.SetDiffPairHoleToHole( holeToHoleMin );
814
815 return true;
816}
817
818
819int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const
820{
822 return 0;
823
825
826 return stackup.GetLayerDistance( ToLAYER_ID( aFirstLayer ), ToLAYER_ID( aSecondLayer ) );
827}
828
829
831{
832 return m_board->DpCoupledNet( static_cast<NETINFO_ITEM*>( aNet ) );
833}
834
835
837{
838 return m_routerIface->GetNetCode( aNet );
839}
840
841
843{
844 return m_routerIface->GetNetName( aNet );
845}
846
847
849{
850 wxString refName;
851
852 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
853 refName = net->GetNetname();
854
855 wxString dummy1;
856
857 return m_board->MatchDpSuffix( refName, dummy1 );
858}
859
860
862 PNS::NET_HANDLE& aNetN )
863{
864 if( !aItem || !aItem->Net() )
865 return false;
866
867 wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
868 wxString netNameN, netNameCoupled;
869
870 int r = m_board->MatchDpSuffix( netNameP, netNameCoupled );
871
872 if( r == 0 )
873 {
874 return false;
875 }
876 else if( r == 1 )
877 {
878 netNameN = netNameCoupled;
879 }
880 else
881 {
882 netNameN = netNameP;
883 netNameP = netNameCoupled;
884 }
885
886 PNS::NET_HANDLE netInfoP = m_board->FindNet( netNameP );
887 PNS::NET_HANDLE netInfoN = m_board->FindNet( netNameN );
888
889 if( !netInfoP || !netInfoN )
890 return false;
891
892 aNetP = netInfoP;
893 aNetN = netInfoN;
894
895 return true;
896}
897
898
900{
901public:
904 m_view( nullptr ),
905 m_items( nullptr ),
906 m_depth( 0 )
907 {
908 SetView( aView );
909 }
910
912 {
914 delete m_items;
915 }
916
917 void SetView( KIGFX::VIEW* aView )
918 {
919 Clear();
920 delete m_items;
921 m_items = nullptr;
922 m_view = aView;
923
924 if( m_view == nullptr )
925 return;
926
927 if( m_view->GetGAL() )
929
932 m_view->Add( m_items );
933 }
934
935 void AddPoint( const VECTOR2I& aP, const KIGFX::COLOR4D& aColor, int aSize,
936 const wxString& aName = wxT( "" ),
937 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
938
939 {
941
942 sh.SetWidth( 10000 );
943
944 sh.Append( aP.x - aSize, aP.y - aSize );
945 sh.Append( aP.x + aSize, aP.y + aSize );
946 sh.Append( aP.x, aP.y );
947 sh.Append( aP.x - aSize, aP.y + aSize );
948 sh.Append( aP.x + aSize, aP.y - aSize );
949
950 AddShape( &sh, aColor, sh.Width(), aName, aSrcLoc );
951 }
952
953 void AddItem( const PNS::ITEM* aItem, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
954 const wxString& aName = wxT( "" ),
955 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
956 {
957 if( !m_view || !aItem )
958 return;
959
960 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
961
962 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
963 pitem->SetWidth( aOverrideWidth );
964 pitem->SetDepth( nextDepth() );
965
966 m_items->Add( pitem );
968 }
969
970 void AddShape( const BOX2I& aBox, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
971 const wxString& aName = wxT( "" ),
972 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
973 {
975 l.SetWidth( aOverrideWidth );
976
977 VECTOR2I o = aBox.GetOrigin();
978 VECTOR2I s = aBox.GetSize();
979
980 l.Append( o );
981 l.Append( o.x + s.x, o.y );
982 l.Append( o.x + s.x, o.y + s.y );
983 l.Append( o.x, o.y + s.y );
984 l.Append( o );
985
986 AddShape( &l, aColor, aOverrideWidth, aName, aSrcLoc );
987 }
988
989 void AddShape( const SHAPE* aShape, const KIGFX::COLOR4D& aColor, int aOverrideWidth = 0,
990 const wxString& aName = wxT( "" ),
991 const SRC_LOCATION_INFO& aSrcLoc = SRC_LOCATION_INFO() ) override
992 {
993 if( !m_view || !aShape )
994 return;
995
996 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( *aShape, m_view );
997
998 pitem->SetColor( aColor.WithAlpha( 0.5 ) );
999 pitem->SetWidth( aOverrideWidth );
1000 pitem->SetDepth( nextDepth() );
1001
1002 m_items->Add( pitem );
1003 m_view->Update( m_items );
1004 }
1005
1006 void Clear() override
1007 {
1008 if( m_view && m_items )
1009 {
1010 m_items->FreeItems();
1011 m_view->Update( m_items );
1012
1013 if( m_view->GetGAL() )
1015 }
1016 }
1017
1018private:
1019 double nextDepth()
1020 {
1021 // Use different depths so that the transculent shapes won't overwrite each other.
1022
1023 m_depth++;
1024
1025 if( m_depth >= 0 && m_view->GetGAL() )
1027
1028 return m_depth;
1029 }
1030
1033
1034 double m_depth;
1035};
1036
1037
1039{
1040 return m_debugDecorator;
1041}
1042
1043
1045{
1046 m_ruleResolver = nullptr;
1047 m_board = nullptr;
1048 m_world = nullptr;
1049 m_debugDecorator = nullptr;
1050 m_startLayer = -1;
1051}
1052
1053
1055{
1056 m_tool = nullptr;
1057 m_view = nullptr;
1058 m_previewItems = nullptr;
1059 m_commitFlags = 0;
1060}
1061
1062
1064{
1065 delete m_ruleResolver;
1066 delete m_debugDecorator;
1067}
1068
1069
1071{
1072 if( m_previewItems )
1073 {
1075 delete m_previewItems;
1076 }
1077}
1078
1079
1080std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
1081{
1082 LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 );
1083
1084 // ignore non-copper pads except for those with holes
1085 if( ( aPad->GetLayerSet() & LSET::AllCuMask() ).none() && aPad->GetDrillSize().x == 0 )
1086 return nullptr;
1087
1088 switch( aPad->GetAttribute() )
1089 {
1090 case PAD_ATTRIB::PTH:
1091 case PAD_ATTRIB::NPTH:
1092 break;
1093
1094 case PAD_ATTRIB::CONN:
1095 case PAD_ATTRIB::SMD:
1096 {
1097 LSET lmsk = aPad->GetLayerSet();
1098 bool is_copper = false;
1099
1100 for( int i = 0; i < MAX_CU_LAYERS; i++ )
1101 {
1102 if( lmsk[i] )
1103 {
1104 is_copper = true;
1105
1106 if( aPad->GetAttribute() != PAD_ATTRIB::NPTH )
1107 layers = LAYER_RANGE( i );
1108
1109 break;
1110 }
1111 }
1112
1113 if( !is_copper )
1114 return nullptr;
1115
1116 break;
1117 }
1118
1119 default:
1120 wxLogTrace( wxT( "PNS" ), wxT( "unsupported pad type 0x%x" ), aPad->GetAttribute() );
1121 return nullptr;
1122 }
1123
1124 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1125
1126 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1127 solid->SetRoutable( false );
1128
1129 solid->SetLayers( layers );
1130 solid->SetNet( aPad->GetNet() );
1131 solid->SetParent( aPad );
1132 solid->SetPadToDie( aPad->GetPadToDieLength() );
1133 solid->SetOrientation( aPad->GetOrientation() );
1134
1135 if( aPad->IsFreePad() )
1136 solid->SetIsFreePad();
1137
1138 VECTOR2I wx_c = aPad->ShapePos();
1139 VECTOR2I offset = aPad->GetOffset();
1140
1141 VECTOR2I c( wx_c.x, wx_c.y );
1142
1143 RotatePoint( offset, aPad->GetOrientation() );
1144
1145 solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
1146 solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
1147
1148 if( aPad->GetDrillSize().x > 0 )
1149 solid->SetHole( new PNS::HOLE( aPad->GetEffectiveHoleShape()->Clone() ) );
1150
1151 // We generate a single SOLID for a pad, so we have to treat it as ALWAYS_FLASHED and then
1152 // perform layer-specific flashing tests internally.
1153 const std::shared_ptr<SHAPE>& shape = aPad->GetEffectiveShape( UNDEFINED_LAYER,
1154 FLASHING::ALWAYS_FLASHED );
1155
1156 if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 )
1157 {
1158 std::vector<const SHAPE*> subshapes;
1159 shape->GetIndexableSubshapes( subshapes );
1160
1161 solid->SetShape( subshapes[0]->Clone() );
1162 }
1163 // For anything that's not a single shape we use a polygon. Multiple shapes have a tendency
1164 // to confuse the hull generator. https://gitlab.com/kicad/code/kicad/-/issues/15553
1165 else
1166 {
1167 const std::shared_ptr<SHAPE_POLY_SET>& poly = aPad->GetEffectivePolygon( ERROR_OUTSIDE );
1168
1169 if( poly->OutlineCount() )
1170 solid->SetShape( new SHAPE_SIMPLE( poly->Outline( 0 ) ) );
1171 }
1172
1173 return solid;
1174}
1175
1176
1177std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( PCB_TRACK* aTrack )
1178{
1179 auto segment = std::make_unique<PNS::SEGMENT>( SEG( aTrack->GetStart(), aTrack->GetEnd() ),
1180 aTrack->GetNet() );
1181
1182 segment->SetWidth( aTrack->GetWidth() );
1183 segment->SetLayers( LAYER_RANGE( aTrack->GetLayer() ) );
1184 segment->SetParent( aTrack );
1185
1186 if( aTrack->IsLocked() )
1187 segment->Mark( PNS::MK_LOCKED );
1188
1189 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aTrack->GetParentGroup() ) )
1190 {
1191 if( !generator->HasFlag( IN_EDIT ) )
1192 segment->Mark( PNS::MK_LOCKED );
1193 }
1194
1195 return segment;
1196}
1197
1198
1199std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( PCB_ARC* aArc )
1200{
1201 auto arc = std::make_unique<PNS::ARC>( SHAPE_ARC( aArc->GetStart(), aArc->GetMid(),
1202 aArc->GetEnd(), aArc->GetWidth() ),
1203 aArc->GetNet() );
1204
1205 arc->SetLayers( LAYER_RANGE( aArc->GetLayer() ) );
1206 arc->SetParent( aArc );
1207
1208 if( aArc->IsLocked() )
1209 arc->Mark( PNS::MK_LOCKED );
1210
1211 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aArc->GetParentGroup() ) )
1212 {
1213 if( !generator->HasFlag( IN_EDIT ) )
1214 arc->Mark( PNS::MK_LOCKED );
1215 }
1216
1217 return arc;
1218}
1219
1220
1221std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( PCB_VIA* aVia )
1222{
1223 PCB_LAYER_ID top, bottom;
1224 aVia->LayerPair( &top, &bottom );
1225
1226 auto via = std::make_unique<PNS::VIA>( aVia->GetPosition(),
1227 LAYER_RANGE( aVia->TopLayer(), aVia->BottomLayer() ),
1228 aVia->GetWidth(),
1229 aVia->GetDrillValue(),
1230 aVia->GetNet(),
1231 aVia->GetViaType() );
1232
1233 via->SetParent( aVia );
1234
1235 if( aVia->IsLocked() )
1236 via->Mark( PNS::MK_LOCKED );
1237
1238 if( PCB_GENERATOR* generator = dynamic_cast<PCB_GENERATOR*>( aVia->GetParentGroup() ) )
1239 {
1240 if( !generator->HasFlag( IN_EDIT ) )
1241 via->Mark( PNS::MK_LOCKED );
1242 }
1243
1244 via->SetIsFree( aVia->GetIsFree() );
1245 via->SetHole( PNS::HOLE::MakeCircularHole( aVia->GetPosition(), aVia->GetDrillValue() / 2 ) );
1246
1247 return via;
1248}
1249
1250
1251bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline )
1252{
1253 static wxString msg;
1254 SHAPE_POLY_SET* poly;
1255
1256 if( !aZone->GetIsRuleArea() )
1257 return false;
1258
1259 LSET layers = aZone->GetLayerSet();
1260
1261 poly = aZone->Outline();
1262 poly->CacheTriangulation( false );
1263
1264 if( !poly->IsTriangulationUpToDate() )
1265 {
1266 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUnits() );
1267 msg.Printf( _( "%s is malformed." ), aZone->GetItemDescription( &unitsProvider, true ) );
1268
1269 KIDIALOG dlg( nullptr, msg, KIDIALOG::KD_WARNING );
1270 dlg.ShowDetailedText( _( "This zone cannot be handled by the router.\n"
1271 "Please verify it is not a self-intersecting polygon." ) );
1272 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1273 dlg.ShowModal();
1274
1275 return false;
1276 }
1277
1278 for( int layer = F_Cu; layer <= B_Cu; layer++ )
1279 {
1280 if( !layers[ layer ] )
1281 continue;
1282
1283 for( int polyId = 0; polyId < poly->TriangulatedPolyCount(); polyId++ )
1284 {
1285 const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = poly->TriangulatedPolygon( polyId );
1286
1287 for( size_t i = 0; i < tri->GetTriangleCount(); i++)
1288 {
1289 VECTOR2I a, b, c;
1290 tri->GetTriangle( i, a, b, c );
1291 SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
1292
1293 triShape->Append( a );
1294 triShape->Append( b );
1295 triShape->Append( c );
1296
1297 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1298
1299 solid->SetLayer( layer );
1300 solid->SetNet( nullptr );
1301 solid->SetParent( aZone );
1302 solid->SetShape( triShape );
1303 solid->SetIsCompoundShapePrimitive();
1304 solid->SetRoutable( false );
1305
1306 aWorld->Add( std::move( solid ) );
1307 }
1308 }
1309 }
1310
1311 return true;
1312}
1313
1314
1316{
1317 if( !IsCopperLayer( aLayer ) )
1318 return false;
1319
1320 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1321 SHAPE_SIMPLE* shape = new SHAPE_SIMPLE;
1322
1323 solid->SetLayer( aLayer );
1324 solid->SetNet( nullptr );
1325 solid->SetParent( aText );
1326 solid->SetShape( shape ); // takes ownership
1327 solid->SetRoutable( false );
1328
1329 SHAPE_POLY_SET cornerBuffer;
1330
1331 aText->TransformShapeToPolygon( cornerBuffer, aText->GetLayer(), 0,
1333
1334 if( !cornerBuffer.OutlineCount() )
1335 return false;
1336
1337 for( const VECTOR2I& pt : cornerBuffer.Outline( 0 ).CPoints() )
1338 shape->Append( pt );
1339
1340 aWorld->Add( std::move( solid ) );
1341
1342 return true;
1343}
1344
1345
1347{
1348 if( aItem->GetLayer() == Edge_Cuts
1349 || aItem->GetLayer() == Margin
1350 || IsCopperLayer( aItem->GetLayer() ) )
1351 {
1352 std::vector<SHAPE*> shapes = aItem->MakeEffectiveShapes();
1353
1354 for( SHAPE* shape : shapes )
1355 {
1356 std::unique_ptr<PNS::SOLID> solid = std::make_unique<PNS::SOLID>();
1357
1358 if( aItem->GetLayer() == Edge_Cuts || aItem->GetLayer() == Margin )
1359 {
1360 solid->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
1361 solid->SetRoutable( false );
1362 }
1363 else
1364 {
1365 solid->SetLayer( aItem->GetLayer() );
1366 }
1367
1368 if( aItem->GetLayer() == Edge_Cuts )
1369 {
1370 switch( shape->Type() )
1371 {
1372 case SH_SEGMENT: static_cast<SHAPE_SEGMENT*>( shape )->SetWidth( 0 ); break;
1373 case SH_ARC: static_cast<SHAPE_ARC*>( shape )->SetWidth( 0 ); break;
1374 case SH_LINE_CHAIN: static_cast<SHAPE_LINE_CHAIN*>( shape )->SetWidth( 0 ); break;
1375 default: /* remaining shapes don't have width */ break;
1376 }
1377 }
1378
1379 solid->SetAnchorPoints( aItem->GetConnectionPoints() );
1380 solid->SetNet( aItem->GetNet() );
1381 solid->SetParent( aItem );
1382 solid->SetShape( shape ); // takes ownership
1383
1384 if( shapes.size() > 1 )
1385 solid->SetIsCompoundShapePrimitive();
1386
1387 aWorld->Add( std::move( solid ) );
1388 }
1389
1390 return true;
1391 }
1392
1393 return false;
1394}
1395
1396
1398{
1399 m_board = aBoard;
1400 wxLogTrace( wxT( "PNS" ), wxT( "m_board = %p" ), m_board );
1401}
1402
1403
1405{
1406 if( !m_view )
1407 return false;
1408
1409 for( int i = aLayer.Start(); i <= aLayer.End(); i++ )
1410 {
1411 if( m_view->IsLayerVisible( i ) )
1412 return true;
1413 }
1414
1415 return false;
1416}
1417
1418
1419bool PNS_KICAD_IFACE_BASE::IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const
1420{
1422 if( aLayer < 0 )
1423 return true;
1424
1425 if( aItem->Parent() )
1426 {
1427 switch( aItem->Parent()->Type() )
1428 {
1429 case PCB_VIA_T:
1430 {
1431 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1432
1433 return via->FlashLayer( ToLAYER_ID( aLayer ) );
1434 }
1435
1436 case PCB_PAD_T:
1437 {
1438 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1439
1440 return pad->FlashLayer( ToLAYER_ID( aLayer ) );
1441 }
1442
1443 default:
1444 break;
1445 }
1446 }
1447
1448 return aItem->Layers().Overlaps( aLayer );
1449}
1450
1451
1453 const LAYER_RANGE& aLayer ) const
1454{
1455 LAYER_RANGE test = aItem->Layers().Intersection( aLayer );
1456
1457 if( aItem->Parent() )
1458 {
1459 switch( aItem->Parent()->Type() )
1460 {
1461 case PCB_VIA_T:
1462 {
1463 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem->Parent() );
1464
1465 for( int layer = test.Start(); layer <= test.End(); ++layer )
1466 {
1467 if( via->FlashLayer( ToLAYER_ID( layer ) ) )
1468 return true;
1469 }
1470
1471 return false;
1472 }
1473
1474 case PCB_PAD_T:
1475 {
1476 const PAD* pad = static_cast<const PAD*>( aItem->Parent() );
1477
1478 for( int layer = test.Start(); layer <= test.End(); ++layer )
1479 {
1480 if( pad->FlashLayer( ToLAYER_ID( layer ) ) )
1481 return true;
1482 }
1483
1484 return false;
1485 }
1486
1487 default:
1488 break;
1489 }
1490 }
1491
1492 return test.Start() <= test.End();
1493}
1494
1495
1497{
1498 // by default, all items are visible (new ones created by the router have parent == NULL
1499 // as they have not been committed yet to the BOARD)
1500 if( !m_view || !aItem->Parent() )
1501 return true;
1502
1503 BOARD_ITEM* item = aItem->Parent();
1504 bool isOnVisibleLayer = true;
1505 RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
1506
1507 if( settings->GetHighContrast() )
1508 isOnVisibleLayer = item->IsOnLayer( settings->GetPrimaryHighContrastLayer() );
1509
1510 if( m_view->IsVisible( item ) && isOnVisibleLayer )
1511 {
1512 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
1513 {
1514 if( item->ViewGetLOD( layer, m_view ) < m_view->GetScale() )
1515 return true;
1516 }
1517 }
1518
1519 // Items hidden in the router are not hidden on the board
1520 if( m_hiddenItems.find( item ) != m_hiddenItems.end() )
1521 return true;
1522
1523 return false;
1524}
1525
1526
1528{
1529 if( !m_board )
1530 {
1531 wxLogTrace( wxT( "PNS" ), wxT( "No board attached, aborting sync." ) );
1532 return;
1533 }
1534
1535 int worstClearance = m_board->GetMaxClearanceValue();
1536
1537 m_world = aWorld;
1538
1539 for( BOARD_ITEM* gitem : m_board->Drawings() )
1540 {
1541 if ( gitem->Type() == PCB_SHAPE_T || gitem->Type() == PCB_TEXTBOX_T )
1542 {
1543 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( gitem ) );
1544 }
1545 else if( gitem->Type() == PCB_TEXT_T )
1546 {
1547 syncTextItem( aWorld, static_cast<PCB_TEXT*>( gitem ), gitem->GetLayer() );
1548 }
1549 }
1550
1551 SHAPE_POLY_SET buffer;
1552 SHAPE_POLY_SET* boardOutline = nullptr;
1553
1554 if( m_board->GetBoardPolygonOutlines( buffer ) )
1555 boardOutline = &buffer;
1556
1557 for( ZONE* zone : m_board->Zones() )
1558 {
1559 syncZone( aWorld, zone, boardOutline );
1560 }
1561
1562 for( FOOTPRINT* footprint : m_board->Footprints() )
1563 {
1564 for( PAD* pad : footprint->Pads() )
1565 {
1566 if( std::unique_ptr<PNS::SOLID> solid = syncPad( pad ) )
1567 aWorld->Add( std::move( solid ) );
1568
1569 std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
1570
1571 if( clearanceOverride.has_value() )
1572 worstClearance = std::max( worstClearance, clearanceOverride.value() );
1573
1574 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
1575 {
1576 std::unique_ptr<SHAPE> hole;
1577 hole.reset( pad->GetEffectiveHoleShape()->Clone() );
1578 aWorld->AddEdgeExclusion( std::move( hole ) );
1579 }
1580 }
1581
1582 syncTextItem( aWorld, &footprint->Reference(), footprint->Reference().GetLayer() );
1583 syncTextItem( aWorld, &footprint->Value(), footprint->Value().GetLayer() );
1584
1585 for( ZONE* zone : footprint->Zones() )
1586 syncZone( aWorld, zone, boardOutline );
1587
1588 for( PCB_FIELD* field : footprint->Fields() )
1589 syncTextItem( aWorld, static_cast<PCB_TEXT*>( field ), field->GetLayer() );
1590
1591 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1592 {
1593 if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_TEXTBOX_T )
1594 {
1595 syncGraphicalItem( aWorld, static_cast<PCB_SHAPE*>( item ) );
1596 }
1597 else if( item->Type() == PCB_TEXT_T )
1598 {
1599 syncTextItem( aWorld, static_cast<PCB_TEXT*>( item ), item->GetLayer() );
1600 }
1601 }
1602 }
1603
1604 for( PCB_TRACK* t : m_board->Tracks() )
1605 {
1606 KICAD_T type = t->Type();
1607
1608 if( type == PCB_TRACE_T )
1609 {
1610 if( std::unique_ptr<PNS::SEGMENT> segment = syncTrack( t ) )
1611 aWorld->Add( std::move( segment ) );
1612 }
1613 else if( type == PCB_ARC_T )
1614 {
1615 if( std::unique_ptr<PNS::ARC> arc = syncArc( static_cast<PCB_ARC*>( t ) ) )
1616 aWorld->Add( std::move( arc ) );
1617 }
1618 else if( type == PCB_VIA_T )
1619 {
1620 if( std::unique_ptr<PNS::VIA> via = syncVia( static_cast<PCB_VIA*>( t ) ) )
1621 aWorld->Add( std::move( via ) );
1622 }
1623 }
1624
1625 // NB: if this were ever to become a long-lived object we would need to dirty its
1626 // clearance cache here....
1627 delete m_ruleResolver;
1629
1631 aWorld->SetMaxClearance( worstClearance + m_ruleResolver->ClearanceEpsilon() );
1632}
1633
1634
1636{
1637 for( BOARD_ITEM* item : m_hiddenItems )
1638 m_view->SetVisible( item, true );
1639
1640 m_hiddenItems.clear();
1641
1642 if( m_previewItems )
1643 {
1646 }
1647
1648 if( m_debugDecorator )
1650}
1651
1652
1654{
1655 m_debugDecorator = aDec;
1656}
1657
1658
1659void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit, int aFlags )
1660{
1661 if( aItem->IsVirtual() )
1662 return;
1663
1664 if( ZONE* zone = dynamic_cast<ZONE*>( aItem->Parent() ) )
1665 {
1666 if( zone->GetIsRuleArea() )
1667 aFlags |= PNS_SEMI_SOLID;
1668 }
1669
1670 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view, aFlags );
1671
1672 // Note: SEGMENT_T is used for placed tracks; LINE_T is used for the routing head
1674 static int tracksOrVias = tracks | PNS::ITEM::VIA_T;
1675
1676 if( aClearance >= 0 )
1677 {
1678 pitem->SetClearance( aClearance );
1679
1680 auto* settings = static_cast<PCBNEW_SETTINGS*>( m_tool->GetManager()->GetSettings() );
1681
1682 switch( settings->m_Display.m_TrackClearance )
1683 {
1686 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) );
1687 break;
1688
1690 pitem->ShowClearance( aItem->OfKind( tracksOrVias ) && !aEdit );
1691 break;
1692
1693 case SHOW_WHILE_ROUTING:
1694 pitem->ShowClearance( aItem->OfKind( tracks ) && !aEdit );
1695 break;
1696
1697 default:
1698 pitem->ShowClearance( false );
1699 break;
1700 }
1701 }
1702
1703 m_previewItems->Add( pitem );
1705}
1706
1707
1708void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
1709{
1710 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, m_view );
1712
1713 COLOR4D color;
1714
1715 if( aImportance >= 1 )
1716 color = COLOR4D( 1.0, 1.0, 0.0, 0.6 );
1717 else if( aImportance == 0 )
1718 color = COLOR4D( 0.7, 0.7, 0.7, 0.6 );
1719
1720 pitem->SetColor( color );
1721
1722 m_previewItems->Add( pitem );
1724}
1725
1726
1728{
1729 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aRatline, m_view );
1730
1731 KIGFX::RENDER_SETTINGS* renderSettings = m_view->GetPainter()->GetSettings();
1732 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
1733 bool colorByNet = rs->GetNetColorMode() != NET_COLOR_MODE::OFF;
1734 COLOR4D defaultColor = rs->GetColor( nullptr, LAYER_RATSNEST );
1735 COLOR4D color = defaultColor;
1736
1737 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
1738 std::set<int> highlightedNets = rs->GetHighlightNetCodes();
1739 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
1740 std::map<wxString, KIGFX::COLOR4D>& ncColors = rs->GetNetclassColorMap();
1741 const std::map<int, wxString>& ncMap = connectivity->GetNetclassMap();
1742 int netCode = -1;
1743
1744 if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
1745 netCode = net->GetNetCode();
1746
1747 if( colorByNet && netColors.count( netCode ) )
1748 color = netColors.at( netCode );
1749 else if( colorByNet && ncMap.count( netCode ) && ncColors.count( ncMap.at( netCode ) ) )
1750 color = ncColors.at( ncMap.at( netCode ) );
1751 else
1752 color = defaultColor;
1753
1754 if( color == COLOR4D::UNSPECIFIED )
1755 color = defaultColor;
1756
1757 pitem->SetColor( color.Brightened( 0.5 ).WithAlpha( std::min( 1.0, color.a + 0.4 ) ) );
1758
1759 m_previewItems->Add( pitem );
1761}
1762
1763
1765{
1766 BOARD_ITEM* parent = aItem->Parent();
1767
1768 if( parent )
1769 {
1770 if( m_view->IsVisible( parent ) )
1771 m_hiddenItems.insert( parent );
1772
1773 m_view->SetVisible( parent, false );
1774 m_view->Update( parent, KIGFX::APPEARANCE );
1775
1776 for( ZONE* td : m_board->Zones() )
1777 {
1778 if( td->IsTeardropArea()
1779 && td->GetBoundingBox().Intersects( aItem->Parent()->GetBoundingBox() )
1780 && td->Outline()->Collide( aItem->Shape() ) )
1781 {
1782 m_view->SetVisible( td, false );
1784 }
1785 }
1786 }
1787}
1788
1789
1791{
1792}
1793
1794
1796{
1797 BOARD_ITEM* parent = aItem->Parent();
1798
1799 if( aItem->OfKind( PNS::ITEM::SOLID_T ) )
1800 {
1801 PAD* pad = static_cast<PAD*>( parent );
1802 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1803
1804 m_fpOffsets[ pad ].p_old = pos;
1805 return;
1806 }
1807
1808 if( parent )
1809 {
1810 m_commit->Remove( parent );
1811 }
1812}
1813
1814
1816{
1817}
1818
1819
1821{
1822 BOARD_ITEM* board_item = aItem->Parent();
1823
1824 switch( aItem->Kind() )
1825 {
1826 case PNS::ITEM::ARC_T:
1827 {
1828 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1829 PCB_ARC* arc_board = static_cast<PCB_ARC*>( board_item );
1830 const SHAPE_ARC* arc_shape = static_cast<const SHAPE_ARC*>( arc->Shape() );
1831
1832 m_commit->Modify( arc_board );
1833
1834 arc_board->SetStart( VECTOR2I( arc_shape->GetP0() ) );
1835 arc_board->SetEnd( VECTOR2I( arc_shape->GetP1() ) );
1836 arc_board->SetMid( VECTOR2I( arc_shape->GetArcMid() ) );
1837 arc_board->SetWidth( arc->Width() );
1838 break;
1839 }
1840
1842 {
1843 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1844 PCB_TRACK* track = static_cast<PCB_TRACK*>( board_item );
1845 const SEG& s = seg->Seg();
1846
1847 m_commit->Modify( track );
1848
1849 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1850 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1851 track->SetWidth( seg->Width() );
1852 break;
1853 }
1854
1855 case PNS::ITEM::VIA_T:
1856 {
1857 PCB_VIA* via_board = static_cast<PCB_VIA*>( board_item );
1858 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1859
1860 m_commit->Modify( via_board );
1861
1862 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1863 via_board->SetWidth( via->Diameter() );
1864 via_board->SetDrill( via->Drill() );
1865 via_board->SetNet( static_cast<NETINFO_ITEM*>( via->Net() ) );
1866 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1867 via_board->SetIsFree( via->IsFree() );
1868 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1869 ToLAYER_ID( via->Layers().End() ) );
1870 break;
1871 }
1872
1873 case PNS::ITEM::SOLID_T:
1874 {
1875 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1876 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1877
1878 // Don't add to commit; we'll add the parent footprints when processing the m_fpOffsets
1879
1880 m_fpOffsets[pad].p_old = pad->GetPosition();
1881 m_fpOffsets[pad].p_new = pos;
1882 break;
1883 }
1884
1885 default:
1886 m_commit->Modify( aItem->Parent() );
1887 break;
1888 }
1889}
1890
1891
1893{
1894 modifyBoardItem( aItem );
1895}
1896
1897
1899{
1900}
1901
1902
1904{
1905 BOARD_CONNECTED_ITEM* newBoardItem = nullptr;
1906 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem->Net() );
1907
1908 if( !net )
1910
1911 switch( aItem->Kind() )
1912 {
1913 case PNS::ITEM::ARC_T:
1914 {
1915 PNS::ARC* arc = static_cast<PNS::ARC*>( aItem );
1916 PCB_ARC* new_arc = new PCB_ARC( m_board, static_cast<const SHAPE_ARC*>( arc->Shape() ) );
1917 new_arc->SetWidth( arc->Width() );
1918 new_arc->SetLayer( ToLAYER_ID( arc->Layers().Start() ) );
1919 new_arc->SetNet( net );
1920 newBoardItem = new_arc;
1921 break;
1922 }
1923
1925 {
1926 PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
1927 PCB_TRACK* track = new PCB_TRACK( m_board );
1928 const SEG& s = seg->Seg();
1929 track->SetStart( VECTOR2I( s.A.x, s.A.y ) );
1930 track->SetEnd( VECTOR2I( s.B.x, s.B.y ) );
1931 track->SetWidth( seg->Width() );
1932 track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
1933 track->SetNet( net );
1934 newBoardItem = track;
1935 break;
1936 }
1937
1938 case PNS::ITEM::VIA_T:
1939 {
1940 PCB_VIA* via_board = new PCB_VIA( m_board );
1941 PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
1942 via_board->SetPosition( VECTOR2I( via->Pos().x, via->Pos().y ) );
1943 via_board->SetWidth( via->Diameter() );
1944 via_board->SetDrill( via->Drill() );
1945 via_board->SetNet( net );
1946 via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
1947 via_board->SetIsFree( via->IsFree() );
1948 via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
1949 ToLAYER_ID( via->Layers().End() ) );
1950 newBoardItem = via_board;
1951 break;
1952 }
1953
1954 case PNS::ITEM::SOLID_T:
1955 {
1956 PAD* pad = static_cast<PAD*>( aItem->Parent() );
1957 VECTOR2I pos = static_cast<PNS::SOLID*>( aItem )->Pos();
1958
1959 m_fpOffsets[pad].p_new = pos;
1960 return nullptr;
1961 }
1962
1963 default:
1964 return nullptr;
1965 }
1966
1967 if( net->GetNetCode() <= 0 )
1968 {
1969 NETINFO_ITEM* newNetInfo = newBoardItem->GetNet();
1970
1971 newNetInfo->SetParent( m_board );
1972 newNetInfo->SetNetClass( m_board->GetDesignSettings().m_NetSettings->m_DefaultNetClass );
1973 }
1974
1975 return newBoardItem;
1976}
1977
1978
1980{
1981 BOARD_CONNECTED_ITEM* boardItem = createBoardItem( aItem );
1982
1983 if( boardItem )
1984 {
1985 aItem->SetParent( boardItem );
1986 boardItem->ClearFlags();
1987
1988 m_commit->Add( boardItem );
1989 }
1990}
1991
1992
1994{
1995 std::set<FOOTPRINT*> processedFootprints;
1996
1997 EraseView();
1998
1999 for( const auto& [ pad, fpOffset ] : m_fpOffsets )
2000 {
2001 VECTOR2I offset = fpOffset.p_new - fpOffset.p_old;
2002 FOOTPRINT* footprint = pad->GetParentFootprint();
2003 VECTOR2I p_orig = footprint->GetPosition();
2004 VECTOR2I p_new = p_orig + offset;
2005
2006 if( processedFootprints.find( footprint ) != processedFootprints.end() )
2007 continue;
2008
2009 processedFootprints.insert( footprint );
2010 m_commit->Modify( footprint );
2011 footprint->SetPosition( p_new );
2012 }
2013
2014 m_fpOffsets.clear();
2015
2016 m_commit->Push( _( "Routing" ), m_commitFlags );
2017 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2018}
2019
2020
2022{
2023 return static_cast<EDA_UNITS>( m_tool->GetManager()->GetSettings()->m_System.units );
2024}
2025
2026
2028{
2029 wxLogTrace( wxT( "PNS" ), wxT( "SetView %p" ), aView );
2030
2031 if( m_previewItems )
2032 {
2034 delete m_previewItems;
2035 }
2036
2037 m_view = aView;
2040
2041 if(m_view)
2043
2044 delete m_debugDecorator;
2045
2046 auto dec = new PNS_PCBNEW_DEBUG_DECORATOR();
2047 m_debugDecorator = dec;
2048
2049 dec->SetDebugEnabled( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics );
2050
2051 if( ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
2052 dec->SetView( m_view );
2053}
2054
2055
2057{
2058 if( aNet )
2059 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
2060 else
2061 return -1;
2062}
2063
2064
2066{
2067 if( aNet )
2068 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
2069 else
2070 return wxEmptyString;
2071}
2072
2073
2075{
2076 wxLogTrace( wxT( "PNS" ), wxT( "Update-net %s" ), GetNetName( aNet ) );
2077}
2078
2079
2081{
2083}
2084
2085
2087{
2088 return m_ruleResolver;
2089}
2090
2091
2093{
2094 m_tool = aTool;
2095 m_commit = std::make_unique<BOARD_COMMIT>( m_tool );
2096}
int color
Definition: DXF_plotter.cpp:58
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
std::shared_ptr< DRC_ENGINE > m_DRCEngine
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
BOARD_STACKUP & GetStackupDescriptor()
bool UseNetClassTrack() const
Return true if netclass values should be used to obtain appropriate track width.
bool UseNetClassDiffPair() const
Return true if netclass values should be used to obtain appropriate diff pair dimensions.
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:240
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:93
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:307
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:276
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:266
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:245
virtual bool IsLocked() const
Definition: board_item.cpp:75
virtual bool IsOnCopperLayer() const
Definition: board_item.h:153
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:289
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2474
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:1972
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1901
const ZONES & Zones() const
Definition: board.h:334
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition: board.cpp:881
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition: board.cpp:1922
const FOOTPRINTS & Footprints() const
Definition: board.h:330
const TRACKS & Tracks() const
Definition: board.h:328
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:875
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:474
const DRAWINGS & Drawings() const
Definition: board.h:332
const Vec & GetOrigin() const
Definition: box2.h:200
const SizeVec & GetSize() const
Definition: box2.h:196
wxString GetName() const
Definition: drc_rule.h:150
SEVERITY GetSeverity() const
Definition: drc_rule.h:163
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:142
bool IsNull() const
Definition: drc_rule.h:137
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:319
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2348
bool IsNetTie() const
Definition: footprint.h:296
VECTOR2I GetPosition() const override
Definition: footprint.h:223
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
@ KD_WARNING
Definition: kidialog.h:46
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
double GetMinDepth() const
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:78
NET_COLOR_MODE GetNetColorMode() const
Definition: pcb_painter.h:126
COLOR4D GetColor(const VIEW_ITEM *aItem, int aLayer) const override
Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer using curr...
std::map< int, KIGFX::COLOR4D > & GetNetColorMap()
Definition: pcb_painter.h:131
std::map< wxString, KIGFX::COLOR4D > & GetNetclassColorMap()
Definition: pcb_painter.h:129
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > & GetHighlightNetCodes() const
Return the netcode of currently highlighted net.
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
bool GetHighContrast() const
Extend VIEW_ITEM by possibility of grouping items into a single object.
Definition: view_group.h:48
void FreeItems()
Free all the items that were added to the group.
Definition: view_group.cpp:204
virtual void SetLayer(int aLayer)
Set layer used to draw the group.
Definition: view_group.h:99
virtual void Add(VIEW_ITEM *aItem)
Add an item to the group.
Definition: view_group.cpp:58
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:141
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
double GetScale() const
Definition: view.h:277
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:317
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1687
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:203
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:418
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:221
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1657
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1614
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
int Start() const
Definition: pns_layerset.h:82
int End() const
Definition: pns_layerset.h:87
LAYER_RANGE Intersection(const LAYER_RANGE &aOther) const
Shortcut for comparisons/overlap tests.
Definition: pns_layerset.h:108
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:35
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:392
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:732
T Min() const
Definition: minoptmax.h:33
void SetMin(T v)
Definition: minoptmax.h:41
T Opt() const
Definition: minoptmax.h:35
Handle the data for a net.
Definition: netinfo.h:56
int GetNetCode() const
Definition: netinfo.h:108
void SetParent(BOARD *aParent)
Definition: netinfo.h:167
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
static NETINFO_ITEM * OrphanedItem()
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:389
Definition: pad.h:54
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:392
const VECTOR2I & GetDrillSize() const
Definition: pad.h:267
PAD_ATTRIB GetAttribute() const
Definition: pad.h:395
const VECTOR2I & GetOffset() const
Definition: pad.h:274
VECTOR2I ShapePos() const
Definition: pad.cpp:851
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition: pad.cpp:408
bool IsFreePad() const
Definition: pad.cpp:234
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:359
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:417
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:454
int GetPadToDieLength() const
Definition: pad.h:408
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:280
const VECTOR2I & GetMid() const
Definition: pcb_track.h:281
std::vector< VECTOR2I > GetConnectionPoints() const
Definition: pcb_shape.cpp:326
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:70
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
Definition: pcb_text.cpp:627
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:118
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:121
const VECTOR2I & GetStart() const
Definition: pcb_track.h:122
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:119
virtual void SetWidth(int aWidth)
Definition: pcb_track.h:115
virtual int GetWidth() const
Definition: pcb_track.h:116
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:601
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:991
VECTOR2I GetPosition() const override
Definition: pcb_track.h:452
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:567
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:602
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:453
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
Definition: pcb_track.cpp:942
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_track.cpp:888
int GetWidth() const override
Definition: pcb_track.cpp:313
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:378
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:985
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:547
VIATYPE GetViaType() const
Definition: pcb_track.h:377
void SetWidth(int aWidth) override
Definition: pcb_track.cpp:307
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Return the 2 layers used by the via (the via actually uses all layers between these 2 layers)
Definition: pcb_track.cpp:963
int Width() const override
Definition: pns_arc.h:88
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_arc.h:78
void SetDebugEnabled(bool aEnabled)
static HOLE * MakeCircularHole(const VECTOR2I &pos, int radius)
Definition: pns_hole.cpp:131
ITEM_SET & ExcludeItem(const ITEM *aItem)
ITEM_SET & FilterKinds(int aKindMask, bool aInvert=false)
Definition: pns_itemset.cpp:70
std::vector< ITEM * > & Items()
Definition: pns_itemset.h:87
Base class for PNS router board items.
Definition: pns_item.h:97
BOARD_ITEM * Parent() const
Definition: pns_item.h:186
virtual ITEM * ParentPadVia() const
Definition: pns_item.h:262
virtual NET_HANDLE Net() const
Definition: pns_item.h:194
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:167
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:193
virtual int Layer() const
Definition: pns_item.h:200
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:225
@ SEGMENT_T
Definition: pns_item.h:106
void SetParent(BOARD_ITEM *aParent)
Definition: pns_item.h:185
const LAYER_RANGE & Layers() const
Definition: pns_item.h:196
bool OfKind(int aKindMask) const
Definition: pns_item.h:175
bool IsVirtual() const
Definition: pns_item.h:264
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:237
virtual BOARD_ITEM * BoardItem() const
Definition: pns_item.h:191
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:278
Keep the router "world" - i.e.
Definition: pns_node.h:207
void SetMaxClearance(int aClearance)
Assign a clearance resolution function object.
Definition: pns_node.h:234
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:663
void SetRuleResolver(RULE_RESOLVER *aFunc)
Definition: pns_node.h:240
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
Definition: pns_node.cpp:707
const ITEM_OWNER * Owner() const
Return the owner of this item, or NULL if there's none.
Definition: pns_item.h:71
virtual wxString GetNetName(PNS::NET_HANDLE aNet) const =0
virtual int GetNetCode(NET_HANDLE aNet) const =0
const SEG & Seg() const
Definition: pns_segment.h:84
int Width() const override
Definition: pns_segment.h:79
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)
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, PNS::NET_HANDLE aNet) override
void AddItem(PNS::ITEM *aItem) override
virtual EDA_UNITS GetUnits() const
PNS::DEBUG_DECORATOR * m_debugDecorator
void SetDebugDecorator(PNS::DEBUG_DECORATOR *aDec)
bool syncZone(PNS::NODE *aWorld, ZONE *aZone, SHAPE_POLY_SET *aBoardOutline)
void SetBoard(BOARD *aBoard)
std::unique_ptr< PNS::ARC > syncArc(PCB_ARC *aArc)
void RemoveItem(PNS::ITEM *aItem) override
PNS::RULE_RESOLVER * GetRuleResolver() override
bool syncTextItem(PNS::NODE *aWorld, PCB_TEXT *aText, PCB_LAYER_ID aLayer)
bool IsFlashedOnLayer(const PNS::ITEM *aItem, int aLayer) const override
std::unique_ptr< PNS::SOLID > syncPad(PAD *aPad)
void SyncWorld(PNS::NODE *aWorld) override
int StackupHeight(int aFirstLayer, int aSecondLayer) const override
PNS::DEBUG_DECORATOR * GetDebugDecorator() override
std::unique_ptr< PNS::SEGMENT > syncTrack(PCB_TRACK *aTrack)
PNS_PCBNEW_RULE_RESOLVER * m_ruleResolver
PNS::NET_HANDLE GetOrphanedNetHandle() override
std::unique_ptr< PNS::VIA > syncVia(PCB_VIA *aVia)
void UpdateItem(PNS::ITEM *aItem) override
void SetView(KIGFX::VIEW *aView)
void RemoveItem(PNS::ITEM *aItem) override
void AddItem(PNS::ITEM *aItem) override
void UpdateItem(PNS::ITEM *aItem) override
std::map< PAD *, OFFSET > m_fpOffsets
int GetNetCode(PNS::NET_HANDLE aNet) const override
virtual void SetHostTool(PCB_TOOL_BASE *aTool)
void DisplayItem(const PNS::ITEM *aItem, int aClearance, bool aEdit=false, int aFlags=0) override
std::unique_ptr< BOARD_COMMIT > m_commit
void EraseView() override
void HideItem(PNS::ITEM *aItem) override
void UpdateNet(PNS::NET_HANDLE aNet) override
BOARD_CONNECTED_ITEM * createBoardItem(PNS::ITEM *aItem)
KIGFX::VIEW * m_view
void DisplayPathLine(const SHAPE_LINE_CHAIN &aLine, int aImportance) override
bool IsItemVisible(const PNS::ITEM *aItem) const override
std::unordered_set< BOARD_ITEM * > m_hiddenItems
EDA_UNITS GetUnits() const override
bool IsAnyLayerVisible(const LAYER_RANGE &aLayer) const override
PCB_TOOL_BASE * m_tool
void modifyBoardItem(PNS::ITEM *aItem)
void Commit() override
KIGFX::VIEW_GROUP * m_previewItems
void DisplayRatline(const SHAPE_LINE_CHAIN &aRatline, PNS::NET_HANDLE aNet) override
wxString GetNetName(PNS::NET_HANDLE aNet) const override
~PNS_KICAD_IFACE() override
void AddPoint(const VECTOR2I &aP, const KIGFX::COLOR4D &aColor, int aSize, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
PNS_PCBNEW_DEBUG_DECORATOR(KIGFX::VIEW *aView=nullptr)
void AddShape(const BOX2I &aBox, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
void AddItem(const PNS::ITEM *aItem, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
void SetView(KIGFX::VIEW *aView)
void AddShape(const SHAPE *aShape, const KIGFX::COLOR4D &aColor, int aOverrideWidth=0, const wxString &aName=wxT(""), const SRC_LOCATION_INFO &aSrcLoc=SRC_LOCATION_INFO()) override
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
bool IsKeepout(const PNS::ITEM *aObstacle, const PNS::ITEM *aItem, bool *aEnforce) override
BOARD_ITEM * getBoardItem(const PNS::ITEM *aItem, int aLayer, int aIdx=0)
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:115
const VECTOR2I & GetP1() const
Definition: shape_arc.h:114
const VECTOR2I & GetP0() const
Definition: shape_arc.h:113
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int Width() const
Get the current width of the segments in the chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void SetWidth(int aWidth)
Set the width of all segments in the chain.
const std::vector< VECTOR2I > & CPoints() const
void GetTriangle(int index, VECTOR2I &a, VECTOR2I &b, VECTOR2I &c) const
Represent a set of closed polygons.
bool IsTriangulationUpToDate() const
virtual void CacheTriangulation(bool aPartition=true, bool aSimplify=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
unsigned int TriangulatedPolyCount() const
Return the number of triangulated polygons.
int OutlineCount() const
Return the number of outlines in the set.
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
void Append(int aX, int aY)
Append a new point at the end of the polygon.
Definition: shape_simple.h:135
An abstract shape on 2D plane.
Definition: shape.h:126
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:146
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:400
VECTOR2_TRAITS< int32_t >::extended_type extended_type
Definition: vector2d.h:73
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: zone.cpp:824
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:711
bool GetDoNotAllowVias() const
Definition: zone.h:713
bool GetDoNotAllowPads() const
Definition: zone.h:715
bool GetDoNotAllowTracks() const
Definition: zone.h:714
SHAPE_POLY_SET * Outline()
Definition: zone.h:337
bool GetDoNotAllowFootprints() const
Definition: zone.h:716
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:130
DRC_CONSTRAINT_T
Definition: drc_rule.h:46
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:64
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:67
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:57
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:51
@ LENGTH_CONSTRAINT
Definition: drc_rule.h:65
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:48
@ MAX_UNCOUPLED_CONSTRAINT
Definition: drc_rule.h:68
@ SKEW_CONSTRAINT
Definition: drc_rule.h:66
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:49
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:52
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:71
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:50
#define _(s)
#define ROUTER_TRANSIENT
transient items that should NOT be cached
#define IN_EDIT
Item currently edited.
EDA_UNITS
Definition: eda_units.h:46
@ ERROR_OUTSIDE
static void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
Definition: hash.h:34
This file is part of the common library.
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START
Definition: layer_ids.h:140
#define MAX_CU_LAYERS
Definition: layer_ids.h:142
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:531
@ LAYER_RATSNEST
Definition: layer_ids.h:208
@ LAYER_SELECT_OVERLAY
currently selected items overlay
Definition: layer_ids.h:223
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Edge_Cuts
Definition: layer_ids.h:113
@ B_Cu
Definition: layer_ids.h:95
@ Margin
Definition: layer_ids.h:114
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:875
This file contains miscellaneous commonly used macros and functions.
@ APPEARANCE
Visibility flag has changed.
Definition: view_item.h:52
Push and Shove diff pair dimensions (gap) settings dialog.
CONSTRAINT_TYPE
Definition: pns_node.h:52
void * NET_HANDLE
Definition: pns_item.h:54
@ MK_LOCKED
Definition: pns_item.h:44
STL namespace.
@ SHOW_WITH_VIA_WHILE_ROUTING_OR_DRAGGING
@ SHOW_WHILE_ROUTING
@ SHOW_WITH_VIA_ALWAYS
@ SHOW_WITH_VIA_WHILE_ROUTING
static bool isEdge(const PNS::ITEM *aItem)
static bool isHole(const PNS::ITEM *aItem)
static bool isCopper(const PNS::ITEM *aItem)
VECTOR2I::extended_type ecoord
@ RPT_SEVERITY_IGNORE
#define PNS_SEMI_SOLID
@ SH_SEGMENT
line segment
Definition: shape.h:48
@ SH_ARC
circular arc
Definition: shape.h:54
@ SH_LINE_CHAIN
line chain (polyline)
Definition: shape.h:49
const PNS::ITEM * A
bool operator==(const CLEARANCE_CACHE_KEY &other) const
const PNS::ITEM * B
An abstract function object, returning a design rule (clearance, diff pair gap, etc) required between...
Definition: pns_node.h:73
wxString m_RuleName
Definition: pns_node.h:77
MINOPTMAX< int > m_Value
Definition: pns_node.h:75
CONSTRAINT_TYPE m_Type
Definition: pns_node.h:74
std::size_t operator()(const CLEARANCE_CACHE_KEY &k) const
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_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_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:676