KiCad PCB EDA Suite
Loading...
Searching...
No Matches
multichannel_tool.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24
25#include <board_commit.h>
26#include <tools/pcb_actions.h>
27
30
31#include "multichannel_tool.h"
32
33#include <pcbexpr_evaluator.h>
34
35#include <zone.h>
38#include <pcb_group.h>
41#include <optional>
42#include <algorithm>
44#include <pcb_track.h>
45#include <tool/tool_manager.h>
47#include <random>
48#include <core/profile.h>
49#include <wx/log.h>
50#include <pgm_base.h>
51
52
53#define MULTICHANNEL_EXTRA_DEBUG
54
55static const wxString traceMultichannelTool = wxT( "MULTICHANNEL_TOOL" );
56
57
59{
60}
61
62
64{
65
66}
67
68
70{
73}
74
75
77 std::set<FOOTPRINT*>& aComponents )
78{
80 PCBEXPR_UCODE ucode;
81 PCBEXPR_CONTEXT ctx, preflightCtx;
82
83 auto reportError = [&]( const wxString& aMessage, int aOffset )
84 {
85 wxLogTrace( traceMultichannelTool, wxT( "ERROR: %s"), aMessage );
86 };
87
88 ctx.SetErrorCallback( reportError );
89 preflightCtx.SetErrorCallback( reportError );
90 compiler.SetErrorCallback( reportError );
91 //compiler.SetDebugReporter( m_reporter );
92
93 wxLogTrace( traceMultichannelTool, wxT( "rule area '%s'"), aRuleArea->GetZoneName() );
94
95 wxString ruleText;
96
97 switch( aRuleArea->GetRuleAreaPlacementSourceType() )
98 {
99 case RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME:
100 {
101 ruleText =
102 wxT( "A.memberOfSheet('" ) + aRuleArea->GetRuleAreaPlacementSource() + wxT( "')" );
103 break;
104 }
105 case RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS:
106 ruleText = wxT( "A.hasComponentClass('" ) + aRuleArea->GetRuleAreaPlacementSource()
107 + wxT( "')" );
108 break;
109 }
110
111 auto ok = compiler.Compile( ruleText, &ucode, &preflightCtx );
112
113 if( !ok )
114 {
115 return false;
116 }
117
118 for( FOOTPRINT* fp : board()->Footprints() )
119 {
120 ctx.SetItems( fp, fp );
121 auto val = ucode.Run( &ctx );
122 if( val->AsDouble() != 0.0 )
123 {
124 wxLogTrace( traceMultichannelTool, wxT( " - %s [sheet %s]" ), fp->GetReference(),
125 fp->GetSheetname() );
126
127 aComponents.insert( fp );
128 }
129 }
130
131 return true;
132}
133
134
135bool MULTICHANNEL_TOOL::findOtherItemsInRuleArea( ZONE* aRuleArea, std::set<BOARD_ITEM*>& aItems )
136{
137 std::vector<BOARD_ITEM*> result;
138
140 PCBEXPR_UCODE ucode;
141 PCBEXPR_CONTEXT ctx, preflightCtx;
142
143 auto reportError = [&]( const wxString& aMessage, int aOffset )
144 {
145 wxLogTrace( traceMultichannelTool, wxT( "ERROR: %s"), aMessage );
146 };
147
148 ctx.SetErrorCallback( reportError );
149 preflightCtx.SetErrorCallback( reportError );
150 compiler.SetErrorCallback( reportError );
151
152 bool restoreBlankName = false;
153
154 if( aRuleArea->GetZoneName().IsEmpty() )
155 {
156 restoreBlankName = true;
157 aRuleArea->SetZoneName( aRuleArea->m_Uuid.AsString() );
158 }
159
160 wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ), aRuleArea->GetZoneName() );
161
162 if( !compiler.Compile( ruleText, &ucode, &preflightCtx ) )
163 {
164 if( restoreBlankName )
165 aRuleArea->SetZoneName( wxEmptyString );
166
167 return false;
168 }
169
170 auto testAndAdd =
171 [&]( BOARD_ITEM* aItem )
172 {
173 ctx.SetItems( aItem, aItem );
174 auto val = ucode.Run( &ctx );
175
176 if( val->AsDouble() != 0.0 )
177 aItems.insert( aItem );
178 };
179
180 for( ZONE* zone : board()->Zones() )
181 {
182 if( zone == aRuleArea )
183 continue;
184
185 testAndAdd( zone );
186 }
187
188 for( BOARD_ITEM* drawing : board()->Drawings() )
189 testAndAdd( drawing );
190
191 for( PCB_GROUP* group : board()->Groups() )
192 {
193 // A group is cloned in its entirety if *all* children are contained
194 bool addGroup = true;
195
196 group->RunOnDescendants(
197 [&]( BOARD_ITEM* aItem )
198 {
199 if( aItem->IsType( { PCB_ZONE_T, PCB_SHAPE_T, PCB_DIMENSION_T } ) )
200 {
201 ctx.SetItems( aItem, aItem );
202 auto val = ucode.Run( &ctx );
203
204 if( val->AsDouble() == 0.0 )
205 addGroup = false;
206 }
207 } );
208
209 if( addGroup )
210 aItems.insert( group );
211 }
212
213 if( restoreBlankName )
214 aRuleArea->SetZoneName( wxEmptyString );
215
216 return true;
217}
218
219
220std::set<FOOTPRINT*> MULTICHANNEL_TOOL::queryComponentsInSheet( wxString aSheetName ) const
221{
222 std::set<FOOTPRINT*> rv;
223 if( aSheetName.EndsWith( wxT( "/" ) ) )
224 aSheetName.RemoveLast();
225
226 for( auto& fp : board()->Footprints() )
227 {
228 auto sn = fp->GetSheetname();
229 if( sn.EndsWith( wxT( "/" ) ) )
230 sn.RemoveLast();
231
232 if( sn == aSheetName )
233 {
234 rv.insert( fp );
235 }
236 }
237
238 return rv;
239}
240
241
242std::set<FOOTPRINT*>
243MULTICHANNEL_TOOL::queryComponentsInComponentClass( const wxString& aComponentClassName ) const
244{
245 std::set<FOOTPRINT*> rv;
246
247 for( auto& fp : board()->Footprints() )
248 {
249 if( fp->GetComponentClass()->ContainsClassName( aComponentClassName ) )
250 rv.insert( fp );
251 }
252
253 return rv;
254}
255
256
257const SHAPE_LINE_CHAIN MULTICHANNEL_TOOL::buildRAOutline( std::set<FOOTPRINT*>& aFootprints,
258 int aMargin )
259{
260 std::vector<VECTOR2I> bbCorners;
261 bbCorners.reserve( aFootprints.size() * 4 );
262
263 for( auto fp : aFootprints )
264 {
265 const BOX2I bb = fp->GetBoundingBox( false ).GetInflated( aMargin );
266 KIGEOM::CollectBoxCorners( bb, bbCorners );
267 }
268
269 std::vector<VECTOR2I> hullVertices;
270 BuildConvexHull( hullVertices, bbCorners );
271
272 SHAPE_LINE_CHAIN hull( hullVertices );
273
274 // Make the newly computed convex hull use only 90 degree segments
275 return KIGEOM::RectifyPolygon( hull );
276}
277
278
280{
281 using PathAndName = std::pair<wxString, wxString>;
282 std::set<PathAndName> uniqueSheets;
283 std::set<wxString> uniqueComponentClasses;
284
285 m_areas.m_areas.clear();
286
287 for( const FOOTPRINT* fp : board()->Footprints() )
288 {
289 uniqueSheets.insert( PathAndName( fp->GetSheetname(), fp->GetSheetfile() ) );
290
291 const COMPONENT_CLASS* compClass = fp->GetComponentClass();
292
293 for( const COMPONENT_CLASS* singleClass : compClass->GetConstituentClasses() )
294 uniqueComponentClasses.insert( singleClass->GetName() );
295 }
296
297 for( const PathAndName& sheet : uniqueSheets )
298 {
299 RULE_AREA ent;
300
301 ent.m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME;
302 ent.m_generateEnabled = false;
303 ent.m_sheetPath = sheet.first;
304 ent.m_sheetName = sheet.second;
306 m_areas.m_areas.push_back( ent );
307
308 wxLogTrace( traceMultichannelTool, wxT("found sheet '%s' @ '%s' s %d\n"),
309 ent.m_sheetName, ent.m_sheetPath, (int)m_areas.m_areas.size() );
310 }
311
312 for( const wxString& compClass : uniqueComponentClasses )
313 {
314 RULE_AREA ent;
315
316 ent.m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS;
317 ent.m_generateEnabled = false;
318 ent.m_componentClass = compClass;
320 m_areas.m_areas.push_back( ent );
321
322 wxLogTrace( traceMultichannelTool, wxT( "found component class '%s' s %d\n" ),
323 ent.m_componentClass, static_cast<int>( m_areas.m_areas.size() ) );
324 }
325}
326
327
329{
330 m_areas.m_areas.clear();
331
332 for( ZONE* zone : board()->Zones() )
333 {
334 if( !zone->GetIsRuleArea() )
335 continue;
336 if( !zone->GetRuleAreaPlacementEnabled() )
337 continue;
338
339 RULE_AREA area;
340
341 area.m_existsAlready = true;
342 area.m_area = zone;
343
345
346 area.m_ruleName = zone->GetZoneName();
347 area.m_center = zone->Outline()->COutline( 0 ).Centre();
348 m_areas.m_areas.push_back( area );
349
350 wxLogTrace( traceMultichannelTool, wxT("RA '%s', %d footprints\n"), area.m_ruleName, (int) area.m_raFootprints.size() );
351 }
352
353 wxLogTrace( traceMultichannelTool, wxT("Total RAs found: %d\n"), (int) m_areas.m_areas.size() );
354}
355
356
358{
359 for( RULE_AREA& ra : m_areas.m_areas )
360 {
361 if( ra.m_ruleName == aName )
362 return &ra;
363 }
364
365 return nullptr;
366}
367
368
370{
372}
373
374
376{
377 std::vector<ZONE*> refRAs;
378
379 auto isSelectedItemAnRA = []( EDA_ITEM* aItem ) -> ZONE*
380 {
381 if( !aItem || aItem->Type() != PCB_ZONE_T )
382 return nullptr;
383
384 ZONE* zone = static_cast<ZONE*>( aItem );
385
386 if( !zone->GetIsRuleArea() )
387 return nullptr;
388
389 if( !zone->GetRuleAreaPlacementEnabled() )
390 return nullptr;
391
392 return zone;
393 };
394
395 for( EDA_ITEM* item : selection() )
396 {
397 if( auto zone = isSelectedItemAnRA( item ) )
398 {
399 refRAs.push_back(zone);
400 }
401 else if ( item->Type() == PCB_GROUP_T )
402 {
403 PCB_GROUP *group = static_cast<PCB_GROUP*>( item );
404
405 for( BOARD_ITEM* grpItem : group->GetItems() )
406 {
407 if( auto grpZone = isSelectedItemAnRA( grpItem ) )
408 {
409 refRAs.push_back( grpZone );
410 }
411 }
412 }
413 }
414
415 if( refRAs.size() != 1 )
416 {
419 this,
420 _( "Select a reference Rule Area to copy from..." ),
421 [&]( EDA_ITEM* aItem )
422 {
423 return isSelectedItemAnRA( aItem ) != nullptr;
424 }
425 } );
426
427 return 0;
428 }
429
431
432 int status = CheckRACompatibility( refRAs.front() );
433
434 if( status < 0 )
435 return status;
436
437 if( m_areas.m_areas.size() <= 1 )
438 {
439 frame()->ShowInfoBarError( _( "No Rule Areas to repeat layout to have been found." ),
440 true );
441 return 0;
442 }
443
445 int ret = dialog.ShowModal();
446
447 if( ret != wxID_OK )
448 return 0;
449
450 return RepeatLayout( aEvent, refRAs.front() );
451}
452
453
455{
456 m_areas.m_refRA = nullptr;
457
458 for( RULE_AREA& ra : m_areas.m_areas )
459 {
460 if( ra.m_area == aRefZone )
461 {
462 m_areas.m_refRA = &ra;
463 break;
464 }
465 }
466
467 if( !m_areas.m_refRA )
468 return -1;
469
470 m_areas.m_compatMap.clear();
471
472 for( RULE_AREA& ra : m_areas.m_areas )
473 {
474 if( ra.m_area == m_areas.m_refRA->m_area )
475 continue;
476
478
480 }
481
482 return 0;
483}
484
485
486int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone )
487{
488 int totalCopied = 0;
489
490 BOARD_COMMIT commit( GetManager(), true );
491
492 for( auto& targetArea : m_areas.m_compatMap )
493 {
494 if( !targetArea.second.m_doCopy )
495 {
496 wxLogTrace( traceMultichannelTool, wxT("skipping copy to RA '%s' (disabled in dialog)\n"),
497 targetArea.first->m_ruleName );
498 continue;
499 }
500
501 if( !targetArea.second.m_isOk )
502 continue;
503
504 std::unordered_set<BOARD_ITEM*> affectedItems;
505 std::unordered_set<BOARD_ITEM*> groupableItems;
506
507 if( !copyRuleAreaContents( targetArea.second.m_matchingComponents, &commit, m_areas.m_refRA,
508 targetArea.first, m_areas.m_options, affectedItems,
509 groupableItems ) )
510 {
511 auto errMsg = wxString::Format(
512 _( "Copy Rule Area contents failed between rule areas '%s' and '%s'." ),
514 targetArea.first->m_area->GetZoneName() );
515
516 commit.Revert();
517
518 if( Pgm().IsGUI() )
519 {
520 frame()->ShowInfoBarError( errMsg, true );
521 }
522
523 return -1;
524 }
525
527 {
528 pruneExistingGroups( commit, affectedItems );
529
530 PCB_GROUP* grp = new PCB_GROUP( board() );
531
532 commit.Add( grp );
533
534 for( BOARD_ITEM* item : groupableItems )
535 {
536 commit.Stage( item, CHT_GROUP );
537 }
538 }
539
540 totalCopied++;
541 }
542
543 commit.Push( _( "Repeat layout" ) );
544
545 if( Pgm().IsGUI() )
546 {
547 frame()->ShowInfoBarMsg( wxString::Format( _( "Copied to %d Rule Areas." ), totalCopied ),
548 true );
549 }
550 return 0;
551}
552
553
554wxString MULTICHANNEL_TOOL::stripComponentIndex( const wxString& aRef ) const
555{
556 wxString rv;
557
558 // fixme: i'm pretty sure this can be written in a simpler way, but I really suck at figuring
559 // out which wx's built in functions would do it for me. And I hate regexps :-)
560 for( auto k : aRef )
561 {
562 if( !k.IsAscii() )
563 break;
564 char c;
565 k.GetAsChar( &c );
566
567 if( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || ( c == '_' ) )
568 rv.Append( k );
569 else
570 break;
571 }
572
573 return rv;
574}
575
576
577int MULTICHANNEL_TOOL::findRoutedConnections( std::set<BOARD_ITEM*>& aOutput,
578 std::shared_ptr<CONNECTIVITY_DATA> aConnectivity,
579 const SHAPE_POLY_SET& aRAPoly, RULE_AREA* aRA,
580 FOOTPRINT* aFp,
581 const REPEAT_LAYOUT_OPTIONS& aOpts ) const
582{
583 std::set<BOARD_ITEM*> conns;
584
585 for( PAD* pad : aFp->Pads() )
586 {
587 const std::vector<BOARD_CONNECTED_ITEM*> connItems = aConnectivity->GetConnectedItems(
589
590 for( BOARD_CONNECTED_ITEM* item : connItems )
591 conns.insert( item );
592 }
593
594 int count = 0;
595
596 for( BOARD_ITEM* item : conns )
597 {
598 // fixme: respect layer sets assigned to each RA
599
600 if( item->Type() == PCB_PAD_T )
601 continue;
602
603 std::shared_ptr<SHAPE> effShape = item->GetEffectiveShape( item->GetLayer() );
604
605 if( effShape->Collide( &aRAPoly, 0 ) )
606 {
607 aOutput.insert( item );
608 count++;
609 }
610 }
611
612 // The user also will consider tracks and vias that are inside the source area but
613 // not connected to any of the source pads to count as "routing" (e.g. stitching vias)
614
616 PCBEXPR_UCODE ucode;
617 PCBEXPR_CONTEXT ctx, preflightCtx;
618
619 auto reportError = [&]( const wxString& aMessage, int aOffset )
620 {
621 wxLogTrace( traceMultichannelTool, wxT( "ERROR: %s"), aMessage );
622 };
623
624 ctx.SetErrorCallback( reportError );
625 preflightCtx.SetErrorCallback( reportError );
626 compiler.SetErrorCallback( reportError );
627
628 bool restoreBlankName = false;
629
630 if( aRA->m_area->GetZoneName().IsEmpty() )
631 {
632 restoreBlankName = true;
633 aRA->m_area->SetZoneName( aRA->m_area->m_Uuid.AsString() );
634 }
635
636 wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ),
637 aRA->m_area->GetZoneName() );
638
639 auto testAndAdd =
640 [&]( BOARD_ITEM* aItem )
641 {
642 if( aOutput.contains( aItem ) )
643 return;
644
645 ctx.SetItems( aItem, aItem );
646 auto val = ucode.Run( &ctx );
647
648 if( val->AsDouble() != 0.0 )
649 {
650 aOutput.insert( aItem );
651 count++;
652 }
653 };
654
655 if( compiler.Compile( ruleText, &ucode, &preflightCtx ) )
656 {
657 for( PCB_TRACK* track : board()->Tracks() )
658 testAndAdd( track );
659 }
660
661 if( restoreBlankName )
662 aRA->m_area->SetZoneName( wxEmptyString );
663
664 return count;
665}
666
667
669 BOARD_COMMIT* aCommit,
670 RULE_AREA* aRefArea, RULE_AREA* aTargetArea,
672 std::unordered_set<BOARD_ITEM*>& aAffectedItems,
673 std::unordered_set<BOARD_ITEM*>& aGroupableItems )
674{
675 // copy RA shapes first
676 SHAPE_LINE_CHAIN refOutline = aRefArea->m_area->Outline()->COutline( 0 );
677 SHAPE_LINE_CHAIN targetOutline = aTargetArea->m_area->Outline()->COutline( 0 );
678
679 VECTOR2I disp = aTargetArea->m_center - aRefArea->m_center;
680
681 SHAPE_POLY_SET refPoly;
682 refPoly.AddOutline( refOutline );
683 refPoly.CacheTriangulation( false );
684
685 SHAPE_POLY_SET targetPoly;
686
687 SHAPE_LINE_CHAIN newTargetOutline( refOutline );
688 newTargetOutline.Move( disp );
689 targetPoly.AddOutline( newTargetOutline );
690 targetPoly.CacheTriangulation( false );
691
692 auto connectivity = board()->GetConnectivity();
693
694 aCommit->Modify( aTargetArea->m_area );
695
696 aAffectedItems.insert( aTargetArea->m_area );
697 aGroupableItems.insert( aTargetArea->m_area );
698
699 if( aOpts.m_copyRouting )
700 {
701 std::set<BOARD_ITEM*> refRouting;
702 std::set<BOARD_ITEM*> targetRouting;
703
704 wxLogTrace( traceMultichannelTool, wxT("copying routing: %d fps\n"), (int) aMatches.size() );
705
706 for( auto& fpPair : aMatches )
707 {
708 findRoutedConnections( targetRouting, connectivity, targetPoly, aTargetArea,
709 fpPair.second, aOpts );
710 findRoutedConnections( refRouting, connectivity, refPoly, aRefArea, fpPair.first,
711 aOpts );
712
713 wxLogTrace( traceMultichannelTool, wxT("target-routes %d\n"), (int) targetRouting.size() );
714 }
715
716 for( BOARD_ITEM* item : targetRouting )
717 {
718 if( item->IsLocked() && !aOpts.m_includeLockedItems )
719 continue;
720
721 // item already removed
722 if( aCommit->GetStatus( item ) != 0 )
723 continue;
724
725 if( aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
726 {
727 aAffectedItems.insert( item );
728 aCommit->Remove( item );
729 }
730 }
731
732 for( BOARD_ITEM* item : refRouting )
733 {
734 if( !aRefArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
735 continue;
736
737 if( !aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
738 continue;
739
740 BOARD_ITEM* copied = static_cast<BOARD_ITEM*>( item->Clone() );
741
742 copied->Move( disp );
743 copied->SetParentGroup( nullptr );
744 aGroupableItems.insert( copied );
745 aCommit->Add( copied );
746 }
747 }
748
749 if( aOpts.m_copyOtherItems )
750 {
751 std::set<BOARD_ITEM*> sourceItems;
752 std::set<BOARD_ITEM*> targetItems;
753
754 findOtherItemsInRuleArea( aRefArea->m_area, sourceItems );
755 findOtherItemsInRuleArea( aTargetArea->m_area, targetItems );
756
757 for( BOARD_ITEM* item : targetItems )
758 {
759 if( item->Type() == PCB_TEXT_T && item->GetParent()
760 && item->GetParent()->Type() == PCB_FOOTPRINT_T )
761 continue;
762
763 if( item->IsLocked() && !aOpts.m_includeLockedItems )
764 continue;
765
766 // item already removed
767 if( aCommit->GetStatus( item ) != 0 )
768 continue;
769
770 if( item->Type() != PCB_ZONE_T )
771 {
772 if( aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
773 {
774 aAffectedItems.insert( item );
775 aCommit->Remove( item );
776 }
777 }
778 else
779 {
780 ZONE* zone = static_cast<ZONE*>( item );
781
782 // Check all zone layers are included in the rule area
783 bool layerMismatch = false;
784 LSET zoneLayers = zone->GetLayerSet();
785
786 for( const PCB_LAYER_ID& layer : zoneLayers )
787 {
788 if( !aTargetArea->m_area->GetLayerSet().Contains( layer ) )
789 layerMismatch = true;
790 }
791
792 if( !layerMismatch )
793 {
794 aAffectedItems.insert( zone );
795 aCommit->Remove( zone );
796 }
797 }
798 }
799
800 for( BOARD_ITEM* item : sourceItems )
801 {
802 if( item->Type() == PCB_TEXT_T && item->GetParent()
803 && item->GetParent()->Type() == PCB_FOOTPRINT_T )
804 continue;
805
806 BOARD_ITEM* copied = nullptr;
807
808 if( item->Type() != PCB_ZONE_T )
809 {
810 if( !aRefArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
811 continue;
812 if( !aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
813 continue;
814
815 if( item->Type() == PCB_GROUP_T )
816 {
817 copied = static_cast<PCB_GROUP*>( item )->DeepClone();
818 }
819 else
820 {
821 copied = static_cast<BOARD_ITEM*>( item->Clone() );
822 }
823 }
824 else
825 {
826 ZONE* zone = static_cast<ZONE*>( item );
827
828 // Check all zone layers are included in the rule area
829 bool layerMismatch = false;
830 LSET zoneLayers = zone->GetLayerSet();
831
832 for( const PCB_LAYER_ID& layer : zoneLayers )
833 {
834 if( !aRefArea->m_area->GetLayerSet().Contains( layer )
835 || !aTargetArea->m_area->GetLayerSet().Contains( layer ) )
836 {
837 layerMismatch = true;
838 }
839 }
840
841 if( layerMismatch )
842 continue;
843
844 ZONE* targetZone = static_cast<ZONE*>( item->Clone() );
845 fixupZoneNets( zone, targetZone, aMatches );
846
847 copied = targetZone;
848 }
849
850 if( copied )
851 {
852 copied->ClearFlags();
853 copied->SetParentGroup( nullptr );
854 copied->Move( disp );
855 aGroupableItems.insert( copied );
856 aCommit->Add( copied );
857 }
858 }
859 }
860
861 aTargetArea->m_area->RemoveAllContours();
862 aTargetArea->m_area->AddPolygon( newTargetOutline );
863 aTargetArea->m_area->UnHatchBorder();
864 aTargetArea->m_area->HatchBorder();
865
866 if( aOpts.m_copyPlacement )
867 {
868 for( auto& fpPair : aMatches )
869 {
870 FOOTPRINT* refFP = fpPair.first;
871 FOOTPRINT* targetFP = fpPair.second;
872
873 if( !aRefArea->m_area->GetLayerSet().Contains( refFP->GetLayer() ) )
874 {
875 wxLogTrace( traceMultichannelTool, wxT( "discard ref:%s (ref layer)\n" ),
876 refFP->GetReference() );
877 continue;
878 }
879 if( !aTargetArea->m_area->GetLayerSet().Contains( refFP->GetLayer() ) )
880 {
881 wxLogTrace( traceMultichannelTool, wxT( "discard ref:%s (target layer)\n" ),
882 refFP->GetReference() );
883 continue;
884 }
885
886 // Ignore footprints outside of the rule area
887 if( !refFP->GetEffectiveShape( refFP->GetLayer() )->Collide( &refPoly, 0 ) )
888 continue;
889
890 if( targetFP->IsLocked() && !aOpts.m_includeLockedItems )
891 continue;
892
893 aCommit->Modify( targetFP );
894
895 targetFP->SetLayerAndFlip( refFP->GetLayer() );
896 targetFP->SetOrientation( refFP->GetOrientation() );
897 VECTOR2I targetPos = refFP->GetPosition() + disp;
898 targetFP->SetPosition( targetPos );
899
900 for( PCB_FIELD* refField : refFP->GetFields() )
901 {
902 if( !refField->IsVisible() )
903 continue;
904
905 PCB_FIELD* targetField = targetFP->GetFieldById( refField->GetId() );
906 wxCHECK2( targetField, continue );
907
908 targetField->SetAttributes( refField->GetAttributes() );
909 targetField->SetPosition( refField->GetPosition() + disp );
910 targetField->SetIsKnockout( refField->IsKnockout() );
911 }
912
913 aAffectedItems.insert( targetFP );
914 aGroupableItems.insert( targetFP );
915 }
916 }
917
918 return true;
919}
920
921
926void MULTICHANNEL_TOOL::fixupZoneNets( ZONE* aRefZone, ZONE* aTargetZone,
927 TMATCH::COMPONENT_MATCHES& aComponentMatches )
928{
929 auto connectivity = board()->GetConnectivity();
930 const std::vector<BOARD_CONNECTED_ITEM*> refZoneConnectedPads =
931 connectivity->GetNetItems( aRefZone->GetNetCode(), { PCB_PAD_T } );
932
933 for( const BOARD_CONNECTED_ITEM* refConItem : refZoneConnectedPads )
934 {
935 if( refConItem->Type() != PCB_PAD_T )
936 continue;
937
938 const PAD* refPad = static_cast<const PAD*>( refConItem );
939 FOOTPRINT* sourceFootprint = refPad->GetParentFootprint();
940
941 if( aComponentMatches.contains( sourceFootprint ) )
942 {
943 const FOOTPRINT* targetFootprint = aComponentMatches[sourceFootprint];
944 std::vector<const PAD*> targetFpPads = targetFootprint->GetPads( refPad->GetNumber() );
945
946 if( !targetFpPads.empty() )
947 {
948 int targetNetCode = targetFpPads[0]->GetNet()->GetNetCode();
949 aTargetZone->SetNetCode( targetNetCode );
950
951 break;
952 }
953 }
954 }
955}
956
957
959 RULE_AREA_COMPAT_DATA& aMatches )
960{
961 using namespace TMATCH;
962
963 std::unique_ptr<CONNECTION_GRAPH> cgRef ( CONNECTION_GRAPH::BuildFromFootprintSet( aRefArea->m_raFootprints ) );
964 std::unique_ptr<CONNECTION_GRAPH> cgTarget ( CONNECTION_GRAPH::BuildFromFootprintSet( aTargetArea->m_raFootprints ) );
965
966 auto status = cgRef->FindIsomorphism( cgTarget.get(), aMatches.m_matchingComponents );
967
968 switch( status )
969 {
970 case CONNECTION_GRAPH::ST_OK:
971 aMatches.m_isOk = true;
972 aMatches.m_errorMsg = _("OK");
973 break;
974 case CONNECTION_GRAPH::ST_EMPTY:
975 aMatches.m_isOk = false;
976 aMatches.m_errorMsg = _("One or both of the areas has no components assigned.");
977 break;
978 case CONNECTION_GRAPH::ST_COMPONENT_COUNT_MISMATCH:
979 aMatches.m_isOk = false;
980 aMatches.m_errorMsg = _("Component count mismatch");
981 break;
982 case CONNECTION_GRAPH::ST_ITERATION_COUNT_EXCEEDED:
983 aMatches.m_isOk = false;
984 aMatches.m_errorMsg = _("Iteration count exceeded (timeout)");
985 break;
986 case CONNECTION_GRAPH::ST_TOPOLOGY_MISMATCH:
987 aMatches.m_isOk = false;
988 aMatches.m_errorMsg = _("Topology mismatch");
989 break;
990 default:
991 break;
992 }
993
994 return ( status == TMATCH::CONNECTION_GRAPH::ST_OK );
995}
996
997
999 const std::unordered_set<BOARD_ITEM*>& aItemsToRemove )
1000{
1001 for( PCB_GROUP* grp : board()->Groups() )
1002 {
1003 std::unordered_set<BOARD_ITEM*>& grpItems = grp->GetItems();
1004 size_t n_erased = 0;
1005
1006 for( BOARD_ITEM* refItem : grpItems )
1007 {
1008 //printf("check ref %p [%s]\n", refItem, refItem->GetTypeDesc().c_str().AsChar() );
1009 for( BOARD_ITEM* testItem : aItemsToRemove )
1010 {
1011 if( refItem->m_Uuid == testItem->m_Uuid )
1012 {
1013 aCommit.Stage( refItem, CHT_UNGROUP );
1014 n_erased++;
1015 }
1016 }
1017 }
1018
1019 if( n_erased == grpItems.size() )
1020 {
1021 aCommit.Stage( grp, CHT_REMOVE );
1022 }
1023
1024 //printf("Grp %p items %d pruned %d air %d\n", grp,grpItems.size(), (int) n_erased, (int) aItemsToRemove.size() );
1025 }
1026
1027 return false;
1028}
1029
1030
1032{
1033 if( Pgm().IsGUI() )
1034 {
1036
1037 if( m_areas.m_areas.size() <= 1 )
1038 {
1039 frame()->ShowInfoBarError( _( "Cannot auto-generate any placement areas because the "
1040 "schematic has only one or no hierarchical sheet(s) or "
1041 "component classes." ),
1042 true );
1043 return 0;
1044 }
1045
1047 int ret = dialog.ShowModal();
1048
1049 if( ret != wxID_OK )
1050 return 0;
1051 }
1052
1053 for( ZONE* zone : board()->Zones() )
1054 {
1055 if( !zone->GetIsRuleArea() )
1056 continue;
1057 if( !zone->GetRuleAreaPlacementEnabled() )
1058 continue;
1059
1060 std::set<FOOTPRINT*> components;
1061 identifyComponentsInRuleArea( zone, components );
1062
1063 if( components.empty() )
1064 continue;
1065
1066 for( RULE_AREA& ra : m_areas.m_areas )
1067 {
1068 if( components == ra.m_components )
1069 {
1070 if( zone->GetRuleAreaPlacementSourceType()
1071 == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1072 {
1073 wxLogTrace(
1075 wxT( "Placement rule area for sheet '%s' already exists as '%s'\n" ),
1076 ra.m_sheetPath, zone->GetZoneName() );
1077 }
1078 else
1079 {
1080 wxLogTrace( traceMultichannelTool,
1081 wxT( "Placement rule area for component class '%s' already exists "
1082 "as '%s'\n" ),
1083 ra.m_componentClass, zone->GetZoneName() );
1084 }
1085
1086 ra.m_oldArea = zone;
1087 ra.m_existsAlready = true;
1088 }
1089 }
1090 }
1091
1092 wxLogTrace( traceMultichannelTool,
1093 wxT( "%d placement areas found\n" ), (int) m_areas.m_areas.size() );
1094
1095 BOARD_COMMIT commit( GetManager(), true );
1096
1097 for( RULE_AREA& ra : m_areas.m_areas )
1098 {
1099 if( !ra.m_generateEnabled )
1100 continue;
1101
1103 continue;
1104
1105 SHAPE_LINE_CHAIN raOutline = buildRAOutline( ra.m_components, 100000 );
1106
1107 std::unique_ptr<ZONE> newZone( new ZONE( board() ) );
1108
1109 if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1110 {
1111 newZone->SetZoneName(
1112 wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_sheetPath ) );
1113 }
1114 else
1115 {
1116 newZone->SetZoneName(
1117 wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_componentClass ) );
1118 }
1119
1120 wxLogTrace( traceMultichannelTool, wxT( "Generated rule area '%s' (%d components)\n" ),
1121 newZone->GetZoneName(), (int) ra.m_components.size() );
1122
1123 newZone->SetIsRuleArea( true );
1124 newZone->SetLayerSet( LSET::AllCuMask() );
1125 newZone->SetRuleAreaPlacementEnabled( true );
1126 newZone->SetDoNotAllowCopperPour( false );
1127 newZone->SetDoNotAllowVias( false );
1128 newZone->SetDoNotAllowTracks( false );
1129 newZone->SetDoNotAllowPads( false );
1130 newZone->SetDoNotAllowFootprints( false );
1131
1132 if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1133 {
1134 newZone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
1135 newZone->SetRuleAreaPlacementSource( ra.m_sheetPath );
1136 }
1137 else
1138 {
1139 newZone->SetRuleAreaPlacementSourceType(
1140 RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
1141 newZone->SetRuleAreaPlacementSource( ra.m_componentClass );
1142 }
1143
1144 newZone->AddPolygon( raOutline );
1145 newZone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );
1146
1147 if( ra.m_existsAlready )
1148 {
1149 commit.Remove( ra.m_oldArea );
1150 }
1151
1152 ra.m_area = newZone.get();
1153 commit.Add( newZone.release() );
1154
1155 }
1156
1157 commit.Push( _( "Auto-generate placement rule areas" ) );
1158
1159 // fixme: handle corner cases where the items belonging to a Rule Area already
1160 // belong to other groups.
1161
1163 {
1164 // fixme: sth gets weird when creating new zones & grouping them within a single COMMIT
1165 BOARD_COMMIT grpCommit( GetManager(), true );
1166
1167 for( RULE_AREA& ra : m_areas.m_areas )
1168 {
1169 if( !ra.m_generateEnabled )
1170 continue;
1171
1173 continue;
1174
1175 std::unordered_set<BOARD_ITEM*> toPrune;
1176
1177 std::copy( ra.m_components.begin(), ra.m_components.end(),
1178 std::inserter( toPrune, toPrune.begin() ) );
1179
1180 if( ra.m_existsAlready )
1181 toPrune.insert( ra.m_area );
1182
1183 pruneExistingGroups( grpCommit, toPrune );
1184
1185 PCB_GROUP* grp = new PCB_GROUP( board() );
1186
1187 grpCommit.Add( grp );
1188 grpCommit.Stage( ra.m_area, CHT_GROUP );
1189
1190 for( FOOTPRINT* fp : ra.m_components )
1191 {
1192 grpCommit.Stage( fp, CHT_GROUP );
1193 }
1194 }
1195 grpCommit.Push( _( "Group components with their placement rule areas" ) );
1196 }
1197
1198 return true;
1199}
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
Add a change of the item aItem of type aChangeType to the change list.
virtual void Revert() override
Revert the commit by restoring the modified items state.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual void SetIsKnockout(bool aKnockout)
Definition: board_item.h:327
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:298
const ZONES & Zones() const
Definition: board.h:340
const TRACKS & Tracks() const
Definition: board.h:334
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:483
constexpr BOX2< Vec > GetInflated(coord_type aDx, coord_type aDy) const
Get a new rectangle that is this one, inflated by aDx and aDy.
Definition: box2.h:638
Represent a set of changes (additions, deletions or modifications) of a data model (e....
Definition: commit.h:74
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:92
virtual COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr)
Add a change of the item aItem of type aChangeType to the change list.
Definition: commit.cpp:48
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition: commit.h:80
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Returns status of an item.
Definition: commit.cpp:130
const std::vector< COMPONENT_CLASS * > & GetConstituentClasses() const
Fetches a vector of the constituent classes for this (effective) class.
int ShowModal() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
const KIID m_Uuid
Definition: eda_item.h:490
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:176
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:424
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2434
EDA_ANGLE GetOrientation() const
Definition: footprint.h:225
void SetOrientation(const EDA_ANGLE &aNewAngle)
Definition: footprint.cpp:2522
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: footprint.cpp:2925
std::deque< PAD * > & Pads()
Definition: footprint.h:204
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:234
PCB_FIELD * GetFieldById(int aFieldId)
Return a field in this symbol.
Definition: footprint.cpp:573
bool IsLocked() const override
Definition: footprint.h:409
void SetLayerAndFlip(PCB_LAYER_ID aLayer)
Used as Layer property setter – performs a flip if necessary to set the footprint layer.
Definition: footprint.cpp:2363
std::vector< const PAD * > GetPads(const wxString &aPadNumber, const PAD *aIgnore=nullptr) const
Definition: footprint.cpp:1925
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:647
const wxString & GetReference() const
Definition: footprint.h:620
VECTOR2I GetPosition() const override
Definition: footprint.h:222
wxString AsString() const
Definition: kiid.cpp:246
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
bool Compile(const wxString &aString, UCODE *aCode, CONTEXT *aPreflightContext)
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
VALUE * Run(CONTEXT *ctx)
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:562
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition: lset.h:63
int CheckRACompatibility(ZONE *aRefZone)
std::set< FOOTPRINT * > queryComponentsInSheet(wxString aSheetName) const
int findRoutedConnections(std::set< BOARD_ITEM * > &aOutput, std::shared_ptr< CONNECTIVITY_DATA > aConnectivity, const SHAPE_POLY_SET &aRAPoly, RULE_AREA *aRA, FOOTPRINT *aFp, const REPEAT_LAYOUT_OPTIONS &aOpts) const
int repeatLayout(const TOOL_EVENT &aEvent)
void UpdatePickedItem(const EDA_ITEM *aItem) override
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
const SHAPE_LINE_CHAIN buildRAOutline(std::set< FOOTPRINT * > &aFootprints, int aMargin)
wxString stripComponentIndex(const wxString &aRef) const
bool resolveConnectionTopology(RULE_AREA *aRefArea, RULE_AREA *aTargetArea, RULE_AREA_COMPAT_DATA &aMatches)
RULE_AREAS_DATA m_areas
bool pruneExistingGroups(COMMIT &aCommit, const std::unordered_set< BOARD_ITEM * > &aItemsToCheck)
int RepeatLayout(const TOOL_EVENT &aEvent, ZONE *aRefZone)
int AutogenerateRuleAreas(const TOOL_EVENT &aEvent)
bool identifyComponentsInRuleArea(ZONE *aRuleArea, std::set< FOOTPRINT * > &aComponents)
void fixupZoneNets(ZONE *aRefZone, ZONE *aTargetZone, TMATCH::COMPONENT_MATCHES &aComponentMatches)
Attempts to modify the assigned net of a copied zone.
std::set< FOOTPRINT * > queryComponentsInComponentClass(const wxString &aComponentClassName) const
RULE_AREA * findRAByName(const wxString &aName)
bool copyRuleAreaContents(TMATCH::COMPONENT_MATCHES &aMatches, BOARD_COMMIT *aCommit, RULE_AREA *aRefArea, RULE_AREA *aTargetArea, REPEAT_LAYOUT_OPTIONS aOpts, std::unordered_set< BOARD_ITEM * > &aAffectedItems, std::unordered_set< BOARD_ITEM * > &aGroupableItems)
bool findOtherItemsInRuleArea(ZONE *aRuleArea, std::set< BOARD_ITEM * > &aItems)
Definition: pad.h:54
const wxString & GetNumber() const
Definition: pad.h:134
void SetItems(BOARD_ITEM *a, BOARD_ITEM *b=nullptr)
static TOOL_ACTION repeatLayout
Definition: pcb_actions.h:592
static TOOL_ACTION generatePlacementRuleAreas
Definition: pcb_actions.h:593
static TOOL_ACTION selectItemInteractively
Selection of reference points/items.
Definition: pcb_actions.h:331
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:52
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:87
T * frame() const
BOARD * board() const
const PCB_SELECTION & selection() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Move(const VECTOR2I &aVector) override
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
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.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:146
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:220
Generic, UI-independent tool event.
Definition: tool_event.h:168
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:724
wxString GetRuleAreaPlacementSource() const
Definition: zone.h:730
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition: zone.cpp:1017
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:1143
bool GetRuleAreaPlacementEnabled() const
Definition: zone.h:725
SHAPE_POLY_SET * Outline()
Definition: zone.h:340
const wxString & GetZoneName() const
Definition: zone.h:135
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:133
RULE_AREA_PLACEMENT_SOURCE_TYPE GetRuleAreaPlacementSourceType() const
Definition: zone.h:726
void SetZoneName(const wxString &aName)
Definition: zone.h:136
void UnHatchBorder()
Clear the zone's hatch.
Definition: zone.cpp:1129
void RemoveAllContours(void)
Definition: zone.h:554
@ CHT_GROUP
Definition: commit.h:45
@ CHT_REMOVE
Definition: commit.h:43
@ CHT_UNGROUP
Definition: commit.h:46
void BuildConvexHull(std::vector< VECTOR2I > &aResult, const std::vector< VECTOR2I > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
Definition: convex_hull.cpp:87
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
static const wxString traceMultichannelTool
SHAPE_LINE_CHAIN RectifyPolygon(const SHAPE_LINE_CHAIN &aPoly)
void CollectBoxCorners(const BOX2I &aBox, std::vector< VECTOR2I > &aCorners)
Add the 4 corners of a BOX2I to a vector.
Definition: shape_utils.cpp:84
std::map< FOOTPRINT *, FOOTPRINT * > COMPONENT_MATCHES
Definition: topo_match.h:149
Class to handle a set of BOARD_ITEMs.
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
see class PGM_BASE
Utility functions for working with shapes.
std::unordered_map< RULE_AREA *, RULE_AREA_COMPAT_DATA > m_compatMap
REPEAT_LAYOUT_OPTIONS m_options
std::vector< RULE_AREA > m_areas
TMATCH::COMPONENT_MATCHES m_matchingComponents
VECTOR2I m_center
RULE_AREA_PLACEMENT_SOURCE_TYPE m_sourceType
wxString m_sheetName
wxString m_componentClass
bool m_existsAlready
std::set< FOOTPRINT * > m_raFootprints
ZONE * m_oldArea
std::set< FOOTPRINT * > m_components
wxString m_ruleName
wxString m_sheetPath
bool m_generateEnabled
bool copied
@ 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_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110
@ 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_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ 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